[Openmcl-devel] CCL LAP info...
Jon S. Anthony
j-anthony at comcast.net
Sun Feb 14 12:48:17 UTC 2010
On Sat, 2010-02-13 at 16:41 -0500, R. Matthew Emerson wrote:
> On Feb 13, 2010, at 2:01 PM, Jon S. Anthony wrote:
> > So, any overview on this stuff available?
> Well, not really.
I guess of all the things that could use some more documentation this
would rank fairly low on the urgency list ...
> > I suppose my major concerns
> > are about proper protocol of using registers.
> > BTW, are all registers
> > saved on the stack at point of call?
> On x8664, the registers save0 through save3 must be saved by the callee. And on some ports (win64, darwin), save3 (aka r11) is the TCR pointer, so you shouldn't mess with that.
> Another register you don't mess with is %fn. An instruction to "establish fn" is automatically inserted at the beginning of a LAP function.
> We also don't try to use ebp for anything other than the frame pointer.
> Otherwise, you can use the registers as you please.
Thanks, that is some valuable info! BTW, I've seen TCR and this fn
being "established" and such, and have wondered what they are being used
for/as. Couple sentence description?
> > I suppose that is an x86 question
> > more than a CCL lap question, but if you know the answer, that would be
> > cool! Also, any info on return results from function. I have been able
> > (by reading, getting an idea and then cribbing some example code) to
> > return single values in arg_z, but don't know if that is the standard
> > return reg or what.
> Yes, arg_z is where a single value is returned.
> If your LAP function has more than 2 args (or 3 on x8664), then some of the args will be passed on the stack, and when you return, you need to pop those off the stack. Another probably non-obvious thing is that when a function takes args on the stack, the *caller* pushes space for a frame. Many LAP functions don't bother to set up a stack frame, though. That's why (on x8632) you'll see (single-value-return 3) when a function takes 1 stack arg. The 3 is the number of extra words to discard from the stack (the arg, and the two reserved words for the stack frame).
More really useful info!
> (defx8632lapfunction 3-arg-taker ((stack-arg1 4) #|(ra 0)|#
What is the annotation #|(ra 0)|# here?
> (arg2 arg_y) (arg3 arg_z))
> ;; last two args passed in registers, others are on the stack
> (movl (@ stack-arg1 (% esp)) (% temp0))
> (movl (% temp0) (% arg_z))
> (single-value-return 3))
So, this just returns the stack arg (arg1) in standard return reg argz
and then pops off the arg1 and 2 extra reserved (alignment??) words.
> ? (defun 3-arg-caller ()
> (3-arg-taker 1 2 3)
> ? (df *)
Simple, but handy!
> ;;; (defun 3-arg-caller () (3-arg-taker 1 2 3) 'foo)
>  (recover-fn)
>  (testl (% temp1) (% temp1))
>  (jne L66)
>  (pushl (% ebp))
>  (movl (% esp) (% ebp))
> ;;; (3-arg-taker 1 2 3)
> ;; here the caller reserves space for a frame
>  (pushl ($ -21))
>  (pushl ($ -21))
> ;; pass the first parameter on the stack
> ;; (the number 4 represents fixnum 1)
>  (pushl ($ 4))
This is very interesting - this seems to indicate that CCL uses the
_low_ order bits as the tag bits? That would explain some things...
> ;; pass last two parameters in registers
>  (movl ($ 8) (% arg_y))
>  (movl ($ 12) (% arg_z))
> ;; number of arguments, as a fixnum
> ;; on x8632, temp1 doubles as nargs
>  (movl ($ 12) (% temp1))
>  (movl (@ '3-ARG-TAKER (% fn)) (% temp0))
Out of curiosity, what's in fn here?
> ;; nops for proper alignment of return address
>  (nop)
>  (leal (@ 0 (% arg_y)) (% arg_y))
>  (calll (@ 6 (% temp0)))
>  (recover-fn)
> ;;; 'foo
>  (movl (@ 'FOO (% fn)) (% arg_z))
>  (leavel)
>  (retl)
> ;;; #<no source text>
>  (uuo-error-wrong-number-of-args)
> Multiple values are more complicated: you save the current stack pointer in temp0, push your values on the stack, set nargs to the (fixnum) number of values you pushed, and then do (jmp-subprim .SPvalues). Look at %fixnum-truncate for a fairly simple example of doing this.
Thanks I'll check this out. Don't need multiple value returns -
basically I am keeping the LAPs as simple as possible and most stuff is
still done in user level lisp.
Thanks for the info!
More information about the Openmcl-devel