The sqGnu.h I have reads
#if defined(__i386__) # define IP_REG asm("%esi") # define SP_REG asm("%edi") //# if (__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 95)) # define CB_REG asm("%ebx") //# else //# define CB_REG /* avoid undue register pressure */ //# endif #endif
The first two byte codes assemble to this when done right.
L10161: addl $1, %esi movzbl (%esi), %ebx addl $4, %edi movl _foo, %eax movl 84(%eax), %eax movl 4(%eax), %eax movl %eax, (%edi) movl 512(%esp,%ebx,4), %eax L10421: jmp *%eax
L10162: addl $1, %esi movzbl (%esi), %ebx addl $4, %edi movl _foo, %eax movl 84(%eax), %eax movl 8(%eax), %eax movl %eax, (%edi) movl 512(%esp,%ebx,4), %eax jmp *%eax
sqInt interpret(void) { #ifdef FOO_REG register struct foo * foo FOO_REG = &fum; #endif sqInt localReturnValue; sqInt localReturnContext; sqInt localHomeContext; char* localSP; char* localIP; sqInt currentBytecode; JUMP_TABLE;
Plus use of -DUSE_INLINE_MEMORY_ACCESSORS
However much of this also relies on GCC version, in this case 4.01, usage of SP_REG, etc produced dreadful code with GCC 4.x, but was required for earlier versions.
I noted for PowerPC (Note building with GCC 3.3 PowerPC produces better code than gcc 4.0, gcc 3.1 or gcc 2.95, FYI gcc 3.1 produces lousy code But since you are building on Intel your milage will vary (lots)
On Apr 11, 2008, at 12:22 AM, Andreas Raab wrote:
Yoshiki Ohshima wrote:
Apparently, %esi is used (exclusively) for IP, and %ebx keeps the next byte, and "jmp *" takes you to the next location stored in the table starts at 0x2780.
All of that comes straight out of sqGnu.h:
#define BC_CASE(N) case N: _##N: #define BC_BREAK goto *jumpTable[currentBytecode]
#if defined(__i386__) # define IP_REG asm("%esi") # define SP_REG asm("%edi") # define CB_REG asm("%ebx") #endif
You might want to check if the gnuifier got confused over time - I had to update it to deal correctly with sqInt etc. gnu-interp.c should look like here:
sqInt interpret(void) { sqInt localReturnValue; sqInt localReturnContext; sqInt localHomeContext; register char* localSP SP_REG; register char* localIP IP_REG; register sqInt currentBytecode CB_REG; BC_JUMP_TABLE;
switch (currentBytecode) { BC_CASE(0) /* pushReceiverVariableBytecode */ BC_BREAK;
%esi is almost used for IP but use %eax for fetching the next byte, jmp also seems to use %eax so right before it is spilled and the destination address is brought into %eax.
Sounds more like the static register assignments get ignored.
Cheers,
- Andreas
-- = = = ======================================================================== John M. McIntosh johnmci@smalltalkconsulting.com Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================