     3 1 f struct-return@ ADDI
     3 1 0 local@ STW ;
 
-M: ppc %box-large-struct ( n c-type -- )
+M:: ppc %box-large-struct ( dst 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*
+    3 1 n struct-return@ ADDI
+    c-type heap-size 4 LI
     5 %load-vm-addr
     ! Call the function
-    "from_value_struct" f %alien-invoke ;
+    "from_value_struct" f %alien-invoke
+    3 dst store-param ;
 
 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 ( c-type -- )
    #! Box a <= 16-byte struct returned in r3:r4:r5:r6
    heap-size 7 LI
    8 %load-vm-addr
    "from_medium_struct" f %alien-invoke ;

: %unbox-struct-1 ( -- )
    ! Alien must be in r3.
    4 %load-vm-addr
    "alien_offset" f %alien-invoke
    3 3 0 LWZ ;

: %unbox-struct-2 ( -- )
    ! Alien must be in r3.
    4 %load-vm-addr
    "alien_offset" f %alien-invoke
    4 3 4 LWZ
    3 3 0 LWZ ;

: %unbox-struct-4 ( -- )
    ! Alien must be in r3.
    4 %load-vm-addr
    "alien_offset" f %alien-invoke
    6 3 12 LWZ
    5 3 8 LWZ
    4 3 4 LWZ
    3 3 0 LWZ ;

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

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

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

M: ppc %to-nv ( -- ) 16 3 MR ;

M: ppc %from-nv ( -- ) 3 16 MR ;

M: ppc %unbox-small-struct ( size -- )
    heap-size cell align cell /i {
        { 1 [ %unbox-struct-1 ] }
        { 2 [ %unbox-struct-2 ] }
        { 4 [ %unbox-struct-4 ] }
    } case ;

enable-float-functions


M:: ppc %load-param-reg ( stack reg rep -- )
    reg stack local@ rep load-from-frame ;

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
    func f %alien-invoke ;

M:: ppc %unbox ( src n rep func -- )
    src func call-unbox-func
    ! Store the return value on the C stack
    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
    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
    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@ ;
