<commit_before>/* -----------------------------------------------------------------------------
 * $Id: StgCRun.c,v 1.39 2003/06/09 13:17:41 matthewc Exp $
 *
 * (c) The GHC Team, 1998-2000
 *
 * STG-to-C glue.
 *
 * To run an STG function from C land, call
 *
 *		rv = StgRun(f,BaseReg);
 *
 * where "f" is the STG function to call, and BaseReg is the address of the
 * RegTable for this run (we might have separate RegTables if we're running
 * multiple threads on an SMP machine).
 *
 * In the end, "f" must JMP to StgReturn (defined below),
 * passing the return-value "rv" in R1,
 * to return to the caller of StgRun returning "rv" in
 * the whatever way C returns a value.
 *
 * NOTE: StgRun/StgReturn do *NOT* load or store Hp or any
 * other registers (other than saving the C callee-saves
 * registers).  Instead, the called function "f" must do that
 * in STG land.
 *
 * GCC will have assumed that pushing/popping of C-stack frames is
 * going on when it generated its code, and used stack space
 * accordingly.  However, we actually {\em post-process away} all
 * such stack-framery (see \tr{ghc/driver/ghc-asm.lprl}). Things will
 * be OK however, if we initially make sure there are
 * @RESERVED_C_STACK_BYTES@ on the C-stack to begin with, for local
 * variables.
 *
 * -------------------------------------------------------------------------- */

#include "PosixSource.h"


/*
 * We define the following (unused) global register variables, because for
 * some reason gcc generates sub-optimal code for StgRun() on the Alpha
 * (unnecessarily saving extra registers on the stack) if we don't.
 *
 * Why do it at the top of this file, rather than near StgRun() below?  Because
 * gcc doesn't let us define global register variables after any function
 * definition has been read.  Any point after #include "Stg.h" would be too
 * late.
 *
 * We define alpha_EXTRA_CAREFUL here to save $s6, $f8 and $f9 -- registers
 * that we don't use but which are callee-save registers.  The __divq() routine
 * in libc.a clobbers $s6.
 */
#include "config.h"
#ifdef alpha_TARGET_ARCH
#define alpha_EXTRA_CAREFUL
register long   fake_ra __asm__("$26");
register long   fake_gp __asm__("$29");
#ifdef alpha_EXTRA_CAREFUL
register long   fake_s6 __asm__("$15");
register double fake_f8 __asm__("$f8");
register double fake_f9 __asm__("$f9");
#endif
#endif

/* include Stg.h first because we want real machine regs in here: we
 * have to get the value of R1 back from Stg land to C land intact.
 */
#include "Stg.h"
#include "Rts.h"
#include "StgRun.h"

#ifdef DEBUG
#include "RtsFlags.h"
#include "RtsUtils.h"
#include "Printer.h"
#endif

#ifdef USE_MINIINTERPRETER

/* -----------------------------------------------------------------------------
   any architecture (using miniinterpreter)
   -------------------------------------------------------------------------- */

extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg STG_UNUSED)
{
   while (f) {
      IF_DEBUG(interpreter,
	       fprintf(stderr,"Jumping to ");
	       printPtr((P_)f); fflush(stdout);
	       fprintf(stderr,"\n");
	      );
      f = (StgFunPtr) (f)();
   }
   return (StgThreadReturnCode)R1.i;
}

EXTFUN(StgReturn)
{
   return 0;
}

#else /* !USE_MINIINTERPRETER */

#ifdef LEADING_UNDERSCORE
#define STG_RETURN "_StgReturn"
#else
#define STG_RETURN "StgReturn"
#endif

/* -----------------------------------------------------------------------------
   x86 architecture
   -------------------------------------------------------------------------- */

#ifdef i386_TARGET_ARCH

StgThreadReturnCode
StgRun(StgFunPtr f, StgRegTable *basereg) {

    unsigned char space[ RESERVED_C_STACK_BYTES + 4*sizeof(void *) ];
    StgThreadReturnCode r;

    __asm__ volatile (
	/*
	 * save callee-saves registers on behalf of the STG code.
	 */
	"movl %%esp, %%eax\n\t"
	"addl %4, %%eax\n\t"
        "movl %%ebx,0(%%eax)\n\t"
        "movl %%esi,4(%%eax)\n\t"
        "movl %%edi,8(%%eax)\n\t"
        "movl %%ebp,12(%%eax)\n\t"
	/*
	 * Set BaseReg
	 */
	"movl %3,%%ebx\n\t"
	/*
	 * grab the function argument from the stack, and jump to it.
	 */
        "movl %2,%%eax\n\t"
        "jmp *%%eax\n\t"

	".global " STG_RETURN "\n"
       	STG_RETURN ":\n\t"

	"movl %%esi, %%eax\n\t"   /* Return value in R1  */

	/*
	 * restore callee-saves registers.  (Don't stomp on %%eax!)
	 */
	"movl %%esp, %%edx\n\t"
	"addl %4, %%edx\n\t"
        "movl 0(%%edx),%%ebx\n\t"	/* restore the registers saved above */
        "movl 4(%%edx),%%esi\n\t"
        "movl 8(%%edx),%%edi\n\t"
        "movl 12(%%edx),%%ebp\n\t"

      : "=&a" (r), "=m" (space)
      : "m" (f), "m" (basereg), "i" (RESERVED_C_STACK_BYTES)
      : "edx" /* stomps on %edx */
    );

    return r;
}

#endif

/* -----------------------------------------------------------------------------
   Sparc architecture

   --
   OLD COMMENT from GHC-3.02:
<commit_msg>[project @ 2003-08-29 16:13:48 by simonmar] Oops, forgot one file in the x86_64 commit.<commit_after>/* -----------------------------------------------------------------------------
 * $Id: StgCRun.c,v 1.40 2003/08/29 16:13:48 simonmar Exp $
 *
 * (c) The GHC Team, 1998-2003
 *
 * STG-to-C glue.
 *
 * To run an STG function from C land, call
 *
 *		rv = StgRun(f,BaseReg);
 *
 * where "f" is the STG function to call, and BaseReg is the address of the
 * RegTable for this run (we might have separate RegTables if we're running
 * multiple threads on an SMP machine).
 *
 * In the end, "f" must JMP to StgReturn (defined below),
 * passing the return-value "rv" in R1,
 * to return to the caller of StgRun returning "rv" in
 * the whatever way C returns a value.
 *
 * NOTE: StgRun/StgReturn do *NOT* load or store Hp or any
 * other registers (other than saving the C callee-saves
 * registers).  Instead, the called function "f" must do that
 * in STG land.
 *
 * GCC will have assumed that pushing/popping of C-stack frames is
 * going on when it generated its code, and used stack space
 * accordingly.  However, we actually {\em post-process away} all
 * such stack-framery (see \tr{ghc/driver/ghc-asm.lprl}). Things will
 * be OK however, if we initially make sure there are
 * @RESERVED_C_STACK_BYTES@ on the C-stack to begin with, for local
 * variables.
 *
 * -------------------------------------------------------------------------- */

#include "PosixSource.h"


/*
 * We define the following (unused) global register variables, because for
 * some reason gcc generates sub-optimal code for StgRun() on the Alpha
 * (unnecessarily saving extra registers on the stack) if we don't.
 *
 * Why do it at the top of this file, rather than near StgRun() below?  Because
 * gcc doesn't let us define global register variables after any function
 * definition has been read.  Any point after #include "Stg.h" would be too
 * late.
 *
 * We define alpha_EXTRA_CAREFUL here to save $s6, $f8 and $f9 -- registers
 * that we don't use but which are callee-save registers.  The __divq() routine
 * in libc.a clobbers $s6.
 */
#include "config.h"
#ifdef alpha_TARGET_ARCH
#define alpha_EXTRA_CAREFUL
register long   fake_ra __asm__("$26");
register long   fake_gp __asm__("$29");
#ifdef alpha_EXTRA_CAREFUL
register long   fake_s6 __asm__("$15");
register double fake_f8 __asm__("$f8");
register double fake_f9 __asm__("$f9");
#endif
#endif

/* include Stg.h first because we want real machine regs in here: we
 * have to get the value of R1 back from Stg land to C land intact.
 */
#include "Stg.h"
#include "Rts.h"
#include "StgRun.h"

#ifdef DEBUG
#include "RtsFlags.h"
#include "RtsUtils.h"
#include "Printer.h"
#endif

#ifdef USE_MINIINTERPRETER

/* -----------------------------------------------------------------------------
   any architecture (using miniinterpreter)
   -------------------------------------------------------------------------- */

extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg STG_UNUSED)
{
   while (f) {
      IF_DEBUG(interpreter,
	       fprintf(stderr,"Jumping to ");
	       printPtr((P_)f); fflush(stdout);
	       fprintf(stderr,"\n");
	      );
      f = (StgFunPtr) (f)();
   }
   return (StgThreadReturnCode)R1.i;
}

EXTFUN(StgReturn)
{
   return 0;
}

#else /* !USE_MINIINTERPRETER */

#ifdef LEADING_UNDERSCORE
#define STG_RETURN "_StgReturn"
#else
#define STG_RETURN "StgReturn"
#endif

/* -----------------------------------------------------------------------------
   x86 architecture
   -------------------------------------------------------------------------- */

#ifdef i386_TARGET_ARCH

StgThreadReturnCode
StgRun(StgFunPtr f, StgRegTable *basereg) {

    unsigned char space[ RESERVED_C_STACK_BYTES + 4*sizeof(void *) ];
    StgThreadReturnCode r;

    __asm__ volatile (
	/*
	 * save callee-saves registers on behalf of the STG code.
	 */
	"movl %%esp, %%eax\n\t"
	"addl %4, %%eax\n\t"
        "movl %%ebx,0(%%eax)\n\t"
        "movl %%esi,4(%%eax)\n\t"
        "movl %%edi,8(%%eax)\n\t"
        "movl %%ebp,12(%%eax)\n\t"
	/*
	 * Set BaseReg
	 */
	"movl %3,%%ebx\n\t"
	/*
	 * grab the function argument from the stack, and jump to it.
	 */
        "movl %2,%%eax\n\t"
        "jmp *%%eax\n\t"

	".global " STG_RETURN "\n"
       	STG_RETURN ":\n\t"

	"movl %%esi, %%eax\n\t"   /* Return value in R1  */

	/*
	 * restore callee-saves registers.  (Don't stomp on %%eax!)
	 */
	"movl %%esp, %%edx\n\t"
	"addl %4, %%edx\n\t"
        "movl 0(%%edx),%%ebx\n\t"	/* restore the registers saved above */
        "movl 4(%%edx),%%esi\n\t"
        "movl 8(%%edx),%%edi\n\t"
        "movl 12(%%edx),%%ebp\n\t"

      : "=&a" (r), "=m" (space)
      : "m" (f), "m" (basereg), "i" (RESERVED_C_STACK_BYTES)
      : "edx" /* stomps on %edx */
    );

    return r;
}

#endif

/* ----------------------------------------------------------------------------
   x86-64 is almost the same as plain x86.

   I've done it using entirely inline assembler, because I couldn't
   get gcc to generate the correct subtraction from %rsp by using
   the local array variable trick.  It didn't seem to reserve
   enough space.  Oh well, it's not much harder this way.

   ------------------------------------------------------------------------- */

#ifdef x86_64_TARGET_ARCH

extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg);

static void StgRunIsImplementedInAssembler(void)
{
    __asm__ volatile (
	/*
	 * save callee-saves registers on behalf of the STG code.
	 */
	".globl StgRun\n"
	"StgRun:\n\t"
	"subq %0, %%rsp\n\t"
	"movq %%rsp, %%rax\n\t"
	"addq %0-48, %%rax\n\t"
        "movq %%rbx,0(%%rax)\n\t"
        "movq %%rbp,8(%%rax)\n\t"
        "movq %%r12,16(%%rax)\n\t"
        "movq %%r13,24(%%rax)\n\t"
        "movq %%r14,32(%%rax)\n\t"
        "movq %%r15,40(%%rax)\n\t"
	/*
	 * Set BaseReg
	 */
	"movq %%rsi,%%rbx\n\t"
	/*
	 * grab the function argument from the stack, and jump to it.
	 */
        "movq %%rdi,%%rax\n\t"
        "jmp *%%rax\n\t"

	".global " STG_RETURN "\n"
       	STG_RETURN ":\n\t"

	"movq %%r13, %%rax\n\t"   /* Return value in R1  */

	/*
	 * restore callee-saves registers.  (Don't stomp on %%rax!)
	 */
	"movq %%rsp, %%rdx\n\t"
	"addq %0-48, %%rdx\n\t"
        "movq 0(%%rdx),%%rbx\n\t"	/* restore the registers saved above */
        "movq 8(%%rdx),%%rbp\n\t"
        "movq 16(%%rdx),%%r12\n\t"
        "movq 24(%%rdx),%%r13\n\t"
        "movq 32(%%rdx),%%r14\n\t"
        "movq 40(%%rdx),%%r15\n\t"
	"addq %0, %%rsp\n\t"
	"retq"

	: : "i"(RESERVED_C_STACK_BYTES+48 /*stack frame size*/));
}

#endif /* x86-64 */

/* -----------------------------------------------------------------------------
   Sparc architecture

   --
   OLD COMMENT from GHC-3.02:

{'fraction_non_alphanumeric': 0.2346483704974271, 'fraction_numerical': 0.018610634648370497, 'mean_word_length': 2.0598268171083705, 'pattern_counts': {'":': 3, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4777865', 'n_tokens_mistral': 4284, 'n_tokens_neox': 4018, 'n_words': 1198}