[ Home ]
SBCL Internals

The pages on this CLiki-driven site can be edited by anybody at any time. No warranty of any kind can therefore be made; any implied warranties of merchantability or fitness for a particular purpose are expressly disclaimed
[ Home ] [ Recent Changes ] [ About CLiki ] [ Text Formatting ]

There is the beginnings of a Linux/PPC port which Daniel Barlow and Christophe Rhodes have hacked on at various times, based on Gary Byers?' old CMUCL port to said machine.

News: merged in 0.7.1.45

What about MacOS X

News: merged in 0.8.2.10 or so. (Thanks to Pierre Mai?, Brian Mastenbrook and Patrik Nordebo?).

Fun trivia about function calls

This is out of date for SBCL. SBCL uses normal function calling as every other non-x86 port does

CMUCL/PPC renumbered the fundamental type bits for function-pointer and instance-pointer, so that function-pointer is now 5 and instance-pointer is 1 (previously it was the other way around). Also they added a JUMP-INSN slot as the first slot in each callable primitive-object? (function, closure, funcallable-instance).

So: (note this is not a complete transcript)

/funcalling initial_function=0x8338705
ldb> print 0x8338705
$1=       0x08338705: function pointer
            header: 0x00006e7e: function header
            jump-insn: 0x48000018: 301989894
$1=         self: 0x08338705: # < ptr to function header>
$nil=       next: 0x0500000b: NIL
$2=         name: 0x07022497: !COLD-INIT
$3=         arglist: 0x0833758f: "()"
(gdb) x/4x 0x8338700

0x8338700: 0x00006e7e 0x48000018 0x08338705 0x0500000b (gdb) disassemble 0x8338704 0x8338708 Dump of assembler code from 0x8338704 to 0x8338708: 0x8338704: b 0x833871c

Observe that at the function address itself (after masking the tag bits) we have the header word indicating that it's a function (7e) and how long it is (6e). Then we have the JUMP-INSN slot at address+4, which we have also disassembled to show that it's a real ppc instruction that branches to the actual code.

You also need to know that all the jumps in cmucl/ppc are done with mtctr (move (register) to ctr) and bctr (branch to ctr) and that bctr masks off the low two bits of the destination address before jumping to it. This means we can write

        ;; LEXENV holds the function we want to call
	lwz reg_CODE,CLOSURE_FUNCTION_OFFSET(reg_LEXENV)
	mtctr reg_CODE 
	slwi reg_NARGS,reg_NL2,2
	bctr			; masks out lowest two bits

(example taken from call_into_lisp?, but the "call" VOP does pretty much the same thing as well). This is approximately

  1. reg_CODE = *reg_LEXENV+CLOSURE_FUNCTION_OFFSET
  2. CTR = reg_CODE
  3. reg_NARGS = make_fixnum(reg_NL2)
  4. jump to (address in CTR) & ^(#b00)

So, reg_CODE is the function address + 5, masking off the two low bits gets us address+4, which is the branch instruction, so we just jump to it. The tag renumbering has been done in the SBCL mainline somewhere between 0.6.13 and 0.7, because we thouyght at the time that it was going to make a difference. I (Daniel) eventually got fed up with this bitmask hackery, though, and removed it from SBCL thereafter)

Incidentally, the PPC is a bigendian CPU (in theory it swings both ways, but at least in Linux it's bigendian), and the Lisp code is being cross-compiled using an Alpha (little-endian). We had to make a few endianness adjustments, but they're all in the main tree - they were needed for SPARC, too.


Page in this topic: Darwin  


Also linked from: CPU   index   Porting   pseudo-atomic   Registers   SC-OFFSET   SPARC   tag bit   VOP  

CLiki pages can be edited by anyone at any time. Imagine a fearsomely comprehensive disclaimer of liability. Now fear, comprehensively