 M:: ppc %load-param-reg ( stack reg rep -- )
     reg stack local@ rep load-from-frame ;
 
-M: ppc %pop-stack ( n -- )
-    [ 3 ] dip <ds-loc> loc>operand LWZ ;
-
-M: ppc %push-stack ( -- )
-    ds-reg ds-reg 4 ADDI
-    int-regs return-reg ds-reg 0 STW ;
-
-M: ppc %push-context-stack ( -- )
-    11 %context
-    12 11 "datastack" context-field-offset LWZ
-    12 12 4 ADDI
-    12 11 "datastack" context-field-offset STW
-    int-regs return-reg 12 0 STW ;
-
-M: ppc %pop-context-stack ( -- )
-    11 %context
-    12 11 "datastack" context-field-offset LWZ
-    int-regs return-reg 12 0 LWZ
-    12 12 4 SUBI
-    12 11 "datastack" context-field-offset STW ;
-
-M: ppc %unbox ( n rep func -- )
-    ! Value must be in r3
+GENERIC: load-param ( reg src -- )
+
+M: integer load-param int-rep %copy ;
+
+M: spill-slot load-param n>> spill@ LWZ ;
+
+GENERIC: store-param ( reg dst -- )
+
+M: integer store-param swap int-rep %copy ;
+
+M: spill-slot store-param n>> spill@ STW ;
+
+:: call-unbox-func ( src func -- )
+    3 src load-param
     4 %load-vm-addr
-    ! Call the unboxer
-    f %alien-invoke
+    func f %alien-invoke ;
+
+M:: ppc %unbox ( src n rep func -- )
+    src func call-unbox-func
     ! Store the return value on the C stack
-    over [ [ reg-class-of return-reg ] keep %save-param-reg ] [ 2drop ] if ;
-
-M: ppc %unbox-long-long ( n func -- )
-    4 %load-vm-addr
-    ! Call the unboxer
-    f %alien-invoke
+    n [ rep reg-class-of return-reg rep %save-param-reg ] when* ;
+
+M:: ppc %unbox-long-long ( src n func -- )
+    src func call-unbox-func
     ! Store the return value on the C stack
-    [
-        [ [ 3 1 ] dip local@ STW ]
-        [ [ 4 1 ] dip cell + local@ STW ] bi
-    ] when* ;
-
-M: ppc %unbox-large-struct ( n c-type -- )
-    ! Value must be in r3
-    ! Compute destination address and load struct size
-    [ [ 4 1 ] dip local@ ADDI ] [ heap-size 5 LI ] bi*
-    6 %load-vm-addr
-    ! Call the function
-    "to_value_struct" f %alien-invoke ;
-
-M:: ppc %box ( n rep func -- )
-    ! If the source is a stack location, load it into freg #0.
-    ! If the source is f, then we assume the value is already in
-    ! freg #0.
+    n [
+        3 1 n local@ STW
+        4 1 n cell + local@ STW
+    ] when ;
+
+M:: ppc %unbox-large-struct ( src n c-type -- )
+    4 src load-param
+    3 1 n local@ ADDI
+    heap-size 5 LI
+    "memcpy" "libc" load-library %alien-invoke ;
+
+M:: ppc %box ( dst n rep func -- )
     n [ 0 rep reg-class-of cdecl param-reg rep %load-param-reg ] when*
     rep double-rep? 5 4 ? %load-vm-addr
-    func f %alien-invoke ;
-
-M: ppc %box-long-long ( n func -- )
-    [
-        [
-            [ [ 3 1 ] dip local@ LWZ ]
-            [ [ 4 1 ] dip cell + local@ LWZ ] bi
-        ] when*
-        5 %load-vm-addr
-    ] dip f %alien-invoke ;
+    func f %alien-invoke
+    3 dst store-param ;
+
+M:: ppc %box-long-long ( dst n func -- )
+    n [
+        3 1 n local@ LWZ
+        4 1 n cell + local@ LWZ
+    ] when
+    func f %alien-invoke
+    3 dst store-param ;
 
 : struct-return@ ( n -- n )
     [ stack-frame get params>> ] unless* local@ ;

    3 1 f struct-return@ ADDI
    3 1 0 local@ STW ;

M: ppc %box-large-struct ( n c-type -- )
    ! If n = f, then we're boxing a returned struct
    ! Compute destination address and load struct size
    [ [ 3 1 ] dip struct-return@ ADDI ] [ heap-size 4 LI ] bi*
    5 %load-vm-addr
    ! Call the function
    "from_value_struct" f %alien-invoke ;

M:: ppc %restore-context ( temp1 temp2 -- )
    temp1 %context

M: ppc return-struct-in-registers? ( c-type -- ? )
    c-type return-in-registers?>> ;

M:: ppc %box-small-struct ( dst c-type -- )
    #! Box a <= 16-byte struct returned in r3:r4:r5:r6
    c-type heap-size 7 LI
    8 %load-vm-addr
    "from_medium_struct" f %alien-invoke
    3 dst store-param ;

: %unbox-struct-1 ( -- )
    ! Alien must be in r3.
    3 3 0 LWZ ;

: %unbox-struct-2 ( -- )
    ! Alien must be in r3.
    4 3 4 LWZ
    3 3 0 LWZ ;

: %unbox-struct-4 ( -- )
    ! Alien must be in r3.
    6 3 12 LWZ
    5 3 8 LWZ
    4 3 4 LWZ
    3 3 0 LWZ ;

M:: ppc %unbox-small-struct ( src c-type -- )
    src 3 load-param
    c-type heap-size {
        { [ dup 4 <= ] [ drop %unbox-struct-1 ] }
        { [ dup 8 <= ] [ drop %unbox-struct-2 ] }
        { [ dup 16 <= ] [ drop %unbox-struct-4 ] }
    } cond ;

M: ppc %begin-callback ( -- )
    3 %load-vm-addr
    "begin_callback" f %alien-invoke ;

M: ppc %alien-callback ( quot -- )
    3 swap %load-reference
    4 3 quot-entry-point-offset LWZ
    4 MTLR
    BLRL ;

M: ppc %end-callback ( -- )
    3 %load-vm-addr
    "end_callback" f %alien-invoke ;

enable-float-functions

