Changes between Version 29 and Version 30 of PortToIA-32


Ignore:
Timestamp:
04/20/08 05:04:18 (7 years ago)
Author:
rme
Comment:

update section on register usage

Legend:

Unmodified
Added
Removed
Modified
  • PortToIA-32

    v29 v30  
    3939 
    4040(See also http://openmcl.clozure.com/Doc/index.html#Register-usage-and-tagging) 
     41 
     42The tagging scheme can basically follow the PPC32 port.  An important 
     43difference is that the three-bit tag #b101, which is for NIL on PPC32, 
     44is used for a thing called a tagged return addresses on IA-32. 
     45(More on this later.) 
    4146 
    4247We want to keep the precise GC, but the limited number of registers 
     
    6469contain a node, or arg_y an immediate.) 
    6570 
     71Another potential idea involves the direction flag (DF) in EFLAGS. 
     72The lisp can't use any of the string instructions, so it would be possible to 
     73use this bit for other purposes.  When DF is clear, this could tell the GC that 
     74the normal register partitioning (as above) is in effect. 
     75When DF is set, this could indicate that an alternate register 
     76register partitioning would be in effect, e.g., 
     77 
     78{{{ 
     79eax      imm0 
     80ecx      imm2 
     81edx      imm1 
     82ebx      arg_z 
     83esp      stack pointer 
     84ebp      frame pointer 
     85esi      arg_y 
     86edi      fn 
     87}}} 
     88 
     89We'd need to be careful save the state of the flags and clear DF before calling foreign code. 
     90 
     91(I got the idea of using a bit in EFLAGS to distinguish between two modes of register usage from http://groups.google.com/group/comp.lang.lisp/msg/d5bbe1a9461fe476.) 
     92 
     93One further idea is to arrange that no lisp object can be located at an 
     94address below 2^24^.  Since no valid vector index can be as great as 2^24^ 
     95(the value of ARRAY-TOTAL-SIZE-LIMIT), this means that we could store unboxed 
     96array indicies in node registers and still have the GC reliably distinguish 
     97nodes from other values.  (The main win to this would be making AREF easy. 
     98It wouldn't be necessary to fool around marking registers as immediates.) 
     99 
    66100Callee-saved "non-volatile" registers are probably a non-starter. 
    67101 
    68 The tagging scheme can basically follow the PPC32 port.  An important 
    69 difference is that the three-bit tag #b101, which is for NIL on PPC32, 
    70 would be used for a thing called a tagged return addresses on IA-32. 
    71 (More on this later.) 
     102=== TCR additions === 
     103 
     104==== Node spill area ==== 
     105Since we have so few registers, we have a static spill area of 4 words in 
     106each lisp thread's TCR.  The GC treats these as roots, and the convention 
     107is that they're caller-saved.  (At the moment, the compiler knows nothing 
     108of this spill area, and it's used only from LAP functions and subprimitives.) 
     109 
     110We do have to be careful about clearing out this spill area so that the GC 
     111doesn't hang onto objects that would otherwise be garbage.  PROCESS-INTERRUPT 
     112will need to save and restore these values, and we might need 
     113to say that any callback (including traps) does so as well.  (There's enough 
     114complexity already in traps and callbacks that saving/restoring the spill area isn't likely 
     115to add substantial overhead.) 
     116 
     117==== Unboxed words ==== 
     118There are also a couple of words in the TCR that are used for unboxed values. 
     119We could build a frame on the tsp, but that's rather expensive. 
     120 
     121One situation that comes to mind involves dividing an ''n''-digit bignum by a single 
     122digit:  we need registers 
     123to contain the bignum dividend, the result (the bignum quotient), and an index register.  The 
     124DIV instruction requires the use of EDX:EAX pair.  That means we're out of registers (fn, 
     125ebp, and esp are all in use), and have to store the single digit divisor somewhere else. 
     126We'd typically keep an unboxed value in an MMX register, but we can't use an MMX register as an operand to DIV. 
     127Therefore we have to 
     128use a memory operand: the unboxed word in the TCR. 
     129 
     130==== next-method-context ==== 
     131The CLOS implementation sometimes uses an invisible argument to pass 
     132context information for CALL-NEXT-METHOD.  On other ports, this is a register 
     133that's not part of the normal calling sequence, but on IA-32, all the registers 
     134are spoken for: arg_y and arg_z contain the last two arguments, temp1 is used as 
     135nargs, and temp0 is the function about to be called. 
     136We therefore pass the next-method-context via a slot in the TCR.  (No, it's not pretty.) 
     137The GC will have to 
     138treat this as a root, and we might want to arrange to clear it out somehow so 
     139that it doesn't hang onto something that's otherwise garbage. 
    72140 
    73141==== Comment by gb on Wed Aug  1 22:16:05 2007 ====