This is sqMachDep.h in view mode; [Download] [Up]
/* Platform/compiler dependent support for dynamic translation. */ #if defined(__GNUC__) /* GNU C on any platform */ # define initOp(O) (opcodeAddress= (int)(&&_op_##O) + 1) # if defined(JUMP_ALIGN_BYTE) /* guarantee an even address for opcode start, then 1-byte no-op */ # define beginOp(O) asm (".align 2"); _op_##O: asm("nop") # else # define beginOp(O) _op_##O: # endif # if defined(JUMP_ALIGN_STRICT) # define nextOp() ({ goto *(void *)(*(int *)(localIP+= 4)-1); 0; }) # else # define nextOp() ({ goto *(void *)(*(int *)(localIP+= 4)); 0; }) # endif # define endOp(O) nextOp() #elif defined (macintosh) # if defined (__POWERPC__) /* PowerMac: assumes CodeWarrior 8 or later (other compilers might barf) */ # pragma internal on static asm int _setLabel(register int *ap, register int tmp) { mflr tmp // address of insn after call site addi tmp, tmp, 9 // address of opcode start + tag bit stw tmp, 0(ap) // &opcode -> *store li r3, 1 // answer "true" blr } static asm int _gotoLabel(register int ip) { mtlr ip // destination address blr // dispatch } # pragma internal off # else /*!__POWERPC__*/ /* 68K Mac: assumes CodeWarrior 8 or later (other compilers might barf) */ static asm int _setLabel(register int *ap, int ignored) { // the following is gross, but the 68K has a short branch range // that is just large enough to be used in a few cases. we have // to find the opcode start address by "disassembling" the code // following the call to _setLabel. (efficiency is irrelevant.) move.l (sp), a0 // insn after call site l:move.w (a0)+, d0 // next insn and.w #0xFF00, d0 // lose disp8 cmp.w #0x6600, d0 // BNE[.S]? bne.s l // not yet move.w -2(a0), d0 // BNE[.S] tst.b d0 // disp = 0? bne.s s // no [disp8] addq.l #2, a0 // yes [disp16] s:move.l a0, d0 // opcode addq.l #1, d0 // + tag move.l 4(sp), a0 // &store move.l d0, (a0) // op -> *store rts // ^true } static asm int _gotoLabel(register int ip) { // I think this is optimal (speedwise), but my 68k is very rusty. // (the 68020 can probably do the double indirection with index in // a single instruction, but I'm not convinced it's any faster.) // please submit a better (i.e. faster) solution if you have one! addq.l #4, sp // drop ret addr move.l (sp)+, a0 // pop ip jmp -1(a0) // dispatch = ip - tag } # endif /*!__POWERPC__*/ # define initOp(O) _setLabel(&opcodeAddress, 0) # define beginOp(O) # define nextOp() _gotoLabel(*(int *)(localIP+= 4)) # define endOp(O) nextOp() #elif defined(ACORN) # define initOp(O) _setLabel(&opcodeAddress, 0) # define beginOp(O) # define nextOp() _gotoLabel(*(int *)(localIP+= 4)) # define endOp(O) nextOp() #elif defined(WIN32) # if defined(_MSC_VER) && defined(_M_IX86) /* MS VC++ on Intel x86 machines */ int __fastcall set_label(int *address); int __fastcall goto_label_and_patch_sender(int ip); int __fastcall goto_label(int ip); # define initOp(O) set_label(&opcodeAddress) /* the four nops give us a label after which the opcode sequence starts */ # define beginOp(O) __asm nop __asm nop __asm nop __asm nop # define nextOp() goto_label_and_patch_sender(*(int*) (localIP += 4)) # define endOp(O) nextOp() # else /* Drop me a note for your configuration -- ar */ # error "your win32 processor/compiler is not supported" # endif #else # error your platform/compiler is not supported #endif
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.