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.