/* ********** Native Code Run-Time System *********** */
/*  part of Honours Thesis, Andy Gill, Edinburgh 1991 */
/* ****************************************************/

LWord *NCtraptop;
Closure *AJG_FP;      /* for dynamic scanning */

/* Register Usage (The master version)
 *
 * 0 %NC USAGE%      | %NC USAGE%
 * 1 %NC USAGE%      | %NC USAGE%
 * 2 %NC USAGE%      | Middle of A Space
 * 3 EndofASpace     | <rts return pointer>
 * 4 TrapTop         | FP
 * 5 CurrentProcess  | AP
 * 6 CurrentState    | - ( for gdb)
 * 7  INTZERO        | CP
 *
 */

#define NCTAG (20081)    /* 4e71 : nop             */
#define BCTAG (20115)    /* 4e93 : jsr a3@, or %BC */
#define NATIVE 1         /* include the native code option, please */
#define PROFILER 1 	 /* profiler is to be used */
#define TRUSTED 1        /* use the trusted one, please */


#ifndef TRUSTED  

LWord FAM_REGS_STR[8];
LWord CPU_REGS_STR[16];
LWord NC_REGS_STR[3]; 
LWord Jump_address;

#define INIT_NC    FAM_REGS_STR[0] = (LWord) INTZERO;     /* d7 */\
		   asm(" lea _OpNCtoBC,a0");\
                   asm(" movl a0,_FAM_REGS_STR+0x04"); /* a3 */

#define DUMP_FAM SaveRegs_ ;\
                 tmpreg = (LWord) ++PC;\
                 Jump_address = (LWord) (0xfffffffe & tmpreg);\

#define LOAD_FAM RestoreRegs_ ;\
                 AJG_FP = (Closure *) FP;


#define DUMP_REGS asm(" moveml d0-d7/a0-a7,_CPU_REGS_STR");
#define LOAD_REGS asm(" moveml _CPU_REGS_STR,d0-d7/a0-a7");
/*

              asm(" subl #0x4,a2");\
              asm(" subl #0x400,d3");\

*/
#define LOAD_NC \
              asm(" movl _FAM_AP,a5");\
              asm(" movl _FAM_CP,a4");\
              asm(" movl _FAM_FP,a7");\
              asm(" movl _FAM_TrapTop,d4");\
              asm(" movl _MidOfASpace,a2");\
              asm(" movl _EndOfASpace,d3");\
              asm(" movl _CurrentState,d6");\
              asm(" movl _CurrentProcess,d5");\
              asm(" moveml _FAM_REGS_STR,d7/a3");\
              asm(" movl _Jump_address,a0");



#define DUMP_NC asm(" subl #0x4,a2");\
                asm(" movl a7,_FAM_CP");\
                asm(" movl a2,_MidOfASpace");\
                asm(" movl a4,_FAM_FP");\
                asm(" movl d4,_FAM_TrapTop");\
                asm(" movl a5,_FAM_AP");\
                asm(" movl a3@+,_FAM_PC");

#define JUMP_NC asm(" jmp a0@");

#else  /* trusted is a hand written one, wired for speed */


LWord FAM_REGS_STR[8];
LWord CPU_REGS_STR[16];
LWord NC_REGS_STR[2]; 
LWord NC_exception;

#define INIT_NC    FAM_REGS_STR[0] = (LWord) INTZERO;     /* d7 */\
		   asm(" lea _OpNCtoBC,a0");\
                   asm(" movl a0,_FAM_REGS_STR+0x04"); /* a3 */


#define DUMP_FAM \
            AJG_FP = (Closure *) 0;\
            NCtraptop = TrapTop;\
            asm(" movw a4,d0");\
            asm(" andw #1,d0");\
            asm(" lea a4@(0,d0:w),a0"); /* cant use odd address */

#define LOAD_FAM    asm(" movl a3@+,a4");\
                    TrapTop = NCtraptop;\
                    AJG_FP = (Closure *) FP;


#define DUMP_REGS asm(" movl a7,_CPU_REGS_STR");
#define LOAD_REGS asm(" movl _CPU_REGS_STR,a7");

#define LOAD_NC asm(" movl a2,a4");\
                asm(" movl a3,a7");\
                asm(" movl _CurrentProcess,d5");\
                asm(" movl _NCtraptop,d4");\
                asm(" movl _MidOfASpace,a2");\
                asm(" movl _EndOfASpace,d3");\
                asm(" moveml _FAM_REGS_STR,d7/a3");\
                asm(" movl _CurrentState,d6");\
                asm(" subl #0x4,a2");\
                asm(" subl #0x400,d3"); 

#define DUMP_NC asm(" movl a7,a3");\
                asm(" addl #0x4,a2");\
                asm(" movl a2,_MidOfASpace");\
                asm(" movl a4,a2");\
                asm(" movl d4,_NCtraptop");

#define JUMP_NC asm(" jmp a0@");

#endif

/* now the combinations , as above */

#define NEXTINNC  DUMP_FAM  DUMP_REGS  LOAD_NC  JUMP_NC
#define NEXTINBC  DUMP_NC  LOAD_REGS  LOAD_FAM  NextInst;
#define RTSHANDLER asm("_OpNCtoBC:");



