371 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			Factor
		
	
	
		
		
			
		
	
	
			371 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			Factor
		
	
	
| 
								 | 
							
								! Copyright (C) 2007 Slava Pestov.
							 | 
						||
| 
								 | 
							
								! See http://factorcode.org/license.txt for BSD license.
							 | 
						||
| 
								 | 
							
								USING: alien alien.c-types arrays cpu.arm.assembler compiler
							 | 
						||
| 
								 | 
							
								kernel kernel.private math namespaces words words.private
							 | 
						||
| 
								 | 
							
								generator.registers generator.fixup generator cpu.architecture
							 | 
						||
| 
								 | 
							
								system layouts ;
							 | 
						||
| 
								 | 
							
								IN: cpu.arm.architecture
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								TUPLE: arm-backend ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								! ARM register assignments:
							 | 
						||
| 
								 | 
							
								! R0-R4, R7-R10 integer vregs
							 | 
						||
| 
								 | 
							
								! R11, R12 temporary
							 | 
						||
| 
								 | 
							
								! R5 data stack
							 | 
						||
| 
								 | 
							
								! R6 retain stack
							 | 
						||
| 
								 | 
							
								! R7 primitives
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: ds-reg R5 ; inline
							 | 
						||
| 
								 | 
							
								: rs-reg R6 ; inline
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: temp-reg v>operand drop R12 ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: int-regs return-reg drop R0 ;
							 | 
						||
| 
								 | 
							
								M: int-regs param-regs drop { R0 R1 R2 R3 } ;
							 | 
						||
| 
								 | 
							
								M: int-regs vregs drop { R0 R1 R2 R3 R4 R7 R8 R9 R10 } ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								! No FPU support yet
							 | 
						||
| 
								 | 
							
								M: float-regs param-regs drop { } ;
							 | 
						||
| 
								 | 
							
								M: float-regs vregs drop { } ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: <+/-> dup 0 < [ neg <-> ] [ <+> ] if ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								GENERIC: loc>operand ( loc -- reg addressing )
							 | 
						||
| 
								 | 
							
								M: ds-loc loc>operand ds-loc-n cells neg ds-reg swap <+/-> ;
							 | 
						||
| 
								 | 
							
								M: rs-loc loc>operand rs-loc-n cells neg rs-reg swap <+/-> ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: load-cell ( reg -- )
							 | 
						||
| 
								 | 
							
								    [
							 | 
						||
| 
								 | 
							
								        "end" define-label
							 | 
						||
| 
								 | 
							
								        ! Load target address
							 | 
						||
| 
								 | 
							
								        PC 0 <+> LDR
							 | 
						||
| 
								 | 
							
								        ! Skip an instruction
							 | 
						||
| 
								 | 
							
								        "end" get B
							 | 
						||
| 
								 | 
							
								        ! The target address
							 | 
						||
| 
								 | 
							
								        0 ,
							 | 
						||
| 
								 | 
							
								        ! Continue here
							 | 
						||
| 
								 | 
							
								        "end" resolve-label
							 | 
						||
| 
								 | 
							
								    ] with-scope ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: call-cell ( -- )
							 | 
						||
| 
								 | 
							
								    ! Compute return address; we skip 3 instructions
							 | 
						||
| 
								 | 
							
								    LR PC 8 ADD
							 | 
						||
| 
								 | 
							
								    ! Load target address
							 | 
						||
| 
								 | 
							
								    R12 PC 0 <+> LDR
							 | 
						||
| 
								 | 
							
								    ! Jump to target address
							 | 
						||
| 
								 | 
							
								    R12 BX
							 | 
						||
| 
								 | 
							
								    ! The target address
							 | 
						||
| 
								 | 
							
								    0 , ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend load-indirect ( obj reg -- )
							 | 
						||
| 
								 | 
							
								    tuck load-cell rc-absolute-cell rel-literal
							 | 
						||
| 
								 | 
							
								    dup 0 <+> LDR ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: immediate load-literal
							 | 
						||
| 
								 | 
							
								    over v>operand small-enough? [
							 | 
						||
| 
								 | 
							
								        [ v>operand ] bi@ swap MOV
							 | 
						||
| 
								 | 
							
								    ] [
							 | 
						||
| 
								 | 
							
								        v>operand load-indirect
							 | 
						||
| 
								 | 
							
								    ] if ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: lr-save ( n -- i ) cell - ;
							 | 
						||
| 
								 | 
							
								: next-save ( n -- i ) 2 cells - ;
							 | 
						||
| 
								 | 
							
								: xt-save ( n -- i ) 3 cells - ;
							 | 
						||
| 
								 | 
							
								: factor-area-size 5 cells ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend stack-frame ( n -- i )
							 | 
						||
| 
								 | 
							
								    factor-area-size + 8 align ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %save-word-xt ( -- )
							 | 
						||
| 
								 | 
							
								    R12 PC 9 cells SUB ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %save-dispatch-xt ( -- )
							 | 
						||
| 
								 | 
							
								    R12 PC 2 cells SUB ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %prologue ( n -- )
							 | 
						||
| 
								 | 
							
								    SP SP pick SUB
							 | 
						||
| 
								 | 
							
								    R11 over MOV
							 | 
						||
| 
								 | 
							
								    R11 SP pick next-save <+> STR
							 | 
						||
| 
								 | 
							
								    R12 SP pick xt-save <+> STR
							 | 
						||
| 
								 | 
							
								    LR SP rot lr-save <+> STR ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %epilogue ( n -- )
							 | 
						||
| 
								 | 
							
								    LR SP pick lr-save <+> LDR
							 | 
						||
| 
								 | 
							
								    SP SP rot ADD ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: compile-dlsym ( symbol dll reg -- )
							 | 
						||
| 
								 | 
							
								    load-cell rc-absolute rel-dlsym ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: %alien-global ( symbol dll reg -- )
							 | 
						||
| 
								 | 
							
								    [ compile-dlsym ] keep dup 0 <+> LDR ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %profiler-prologue ( -- )
							 | 
						||
| 
								 | 
							
								    #! We can clobber R0 here since it is undefined at the start
							 | 
						||
| 
								 | 
							
								    #! of a word.
							 | 
						||
| 
								 | 
							
								    R12 load-indirect
							 | 
						||
| 
								 | 
							
								    R0 R12 profile-count-offset <+> LDR
							 | 
						||
| 
								 | 
							
								    R0 R0 1 v>operand ADD
							 | 
						||
| 
								 | 
							
								    R0 R12 profile-count-offset <+> STR ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %call-label ( label -- ) BL ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %jump-label ( label -- ) B ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: %prepare-primitive ( -- )
							 | 
						||
| 
								 | 
							
								    #! Save stack pointer to stack_chain->callstack_top, load XT
							 | 
						||
| 
								 | 
							
								    R1 SP 4 SUB ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %call-primitive ( word -- )
							 | 
						||
| 
								 | 
							
								    %prepare-primitive
							 | 
						||
| 
								 | 
							
								    call-cell rc-absolute-cell rel-word ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %jump-primitive ( word -- )
							 | 
						||
| 
								 | 
							
								    %prepare-primitive
							 | 
						||
| 
								 | 
							
								    ! Load target address
							 | 
						||
| 
								 | 
							
								    R12 PC 0 <+> LDR
							 | 
						||
| 
								 | 
							
								    ! Jump to target address
							 | 
						||
| 
								 | 
							
								    R12 BX
							 | 
						||
| 
								 | 
							
								    ! The target address
							 | 
						||
| 
								 | 
							
								    0 , rc-absolute-cell rel-word ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %jump-t ( label -- )
							 | 
						||
| 
								 | 
							
								    "flag" operand f v>operand CMP NE B ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: (%dispatch) ( word-table# -- )
							 | 
						||
| 
								 | 
							
								    #! Load jump table target address into reg.
							 | 
						||
| 
								 | 
							
								    "scratch" operand PC "n" operand 1 <LSR> ADD
							 | 
						||
| 
								 | 
							
								    "scratch" operand dup 0 <+> LDR
							 | 
						||
| 
								 | 
							
								    rc-indirect-arm rel-dispatch
							 | 
						||
| 
								 | 
							
								    "scratch" operand dup compiled-header-size ADD ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %call-dispatch ( word-table# -- )
							 | 
						||
| 
								 | 
							
								    [
							 | 
						||
| 
								 | 
							
								        (%dispatch)
							 | 
						||
| 
								 | 
							
								        "scratch" operand BLX
							 | 
						||
| 
								 | 
							
								    ] H{
							 | 
						||
| 
								 | 
							
								        { +input+ { { f "n" } } }
							 | 
						||
| 
								 | 
							
								        { +scratch+ { { f "scratch" } } }
							 | 
						||
| 
								 | 
							
								    } with-template ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %jump-dispatch ( word-table# -- )
							 | 
						||
| 
								 | 
							
								    [
							 | 
						||
| 
								 | 
							
								        %epilogue-later
							 | 
						||
| 
								 | 
							
								        (%dispatch)
							 | 
						||
| 
								 | 
							
								        "scratch" operand BX
							 | 
						||
| 
								 | 
							
								    ] H{
							 | 
						||
| 
								 | 
							
								        { +input+ { { f "n" } } }
							 | 
						||
| 
								 | 
							
								        { +scratch+ { { f "scratch" } } }
							 | 
						||
| 
								 | 
							
								    } with-template ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %return ( -- ) %epilogue-later PC LR MOV ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %unwind drop %return ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %peek >r v>operand r> loc>operand LDR ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %replace >r v>operand r> loc>operand STR ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: (%inc) ( n reg -- )
							 | 
						||
| 
								 | 
							
								    dup rot cells dup 0 < [ neg SUB ] [ ADD ] if ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %inc-d ( n -- ) ds-reg (%inc) ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %inc-r ( n -- ) rs-reg (%inc) ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: stack@ SP swap <+> ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: int-regs %save-param-reg drop swap stack@ STR ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: int-regs %load-param-reg drop swap stack@ LDR ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: stack-params %save-param-reg
							 | 
						||
| 
								 | 
							
								    drop
							 | 
						||
| 
								 | 
							
								    R12 swap stack-frame* + stack@ LDR
							 | 
						||
| 
								 | 
							
								    R12 swap stack@ STR ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: stack-params %load-param-reg
							 | 
						||
| 
								 | 
							
								    drop
							 | 
						||
| 
								 | 
							
								    R12 rot stack@ LDR
							 | 
						||
| 
								 | 
							
								    R12 swap stack@ STR ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %prepare-unbox ( -- )
							 | 
						||
| 
								 | 
							
								    ! First parameter is top of stack
							 | 
						||
| 
								 | 
							
								    R0 R5 4 <-!> LDR ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %unbox ( n reg-class func -- )
							 | 
						||
| 
								 | 
							
								    ! Value must be in R0.
							 | 
						||
| 
								 | 
							
								    ! Call the unboxer
							 | 
						||
| 
								 | 
							
								    f %alien-invoke
							 | 
						||
| 
								 | 
							
								    ! Store the return value on the C stack
							 | 
						||
| 
								 | 
							
								    over [ [ return-reg ] keep %save-param-reg ] [ 2drop ] if ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %unbox-long-long ( n func -- )
							 | 
						||
| 
								 | 
							
								    ! Value must be in R0:R1.
							 | 
						||
| 
								 | 
							
								    ! Call the unboxer
							 | 
						||
| 
								 | 
							
								    f %alien-invoke
							 | 
						||
| 
								 | 
							
								    ! Store the return value on the C stack
							 | 
						||
| 
								 | 
							
								    [
							 | 
						||
| 
								 | 
							
								        R0 over stack@ STR
							 | 
						||
| 
								 | 
							
								        R1 swap cell + stack@ STR
							 | 
						||
| 
								 | 
							
								    ] when* ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %unbox-small-struct ( size -- )
							 | 
						||
| 
								 | 
							
								    #! Alien must be in R0.
							 | 
						||
| 
								 | 
							
								    drop
							 | 
						||
| 
								 | 
							
								    "alien_offset" f %alien-invoke
							 | 
						||
| 
								 | 
							
								    ! Load first cell
							 | 
						||
| 
								 | 
							
								    R0 R0 0 <+> LDR ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %unbox-large-struct ( n size -- )
							 | 
						||
| 
								 | 
							
								    #! Alien must be in R0.
							 | 
						||
| 
								 | 
							
								    ! Compute destination address
							 | 
						||
| 
								 | 
							
								    R1 SP roll ADD
							 | 
						||
| 
								 | 
							
								    R2 swap MOV
							 | 
						||
| 
								 | 
							
								    ! Copy the struct to the stack
							 | 
						||
| 
								 | 
							
								    "to_value_struct" f %alien-invoke ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %box ( n reg-class 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.
							 | 
						||
| 
								 | 
							
								    >r
							 | 
						||
| 
								 | 
							
								    over [ 0 over param-reg swap %load-param-reg ] [ 2drop ] if
							 | 
						||
| 
								 | 
							
								    r> f %alien-invoke ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %box-long-long ( n func -- )
							 | 
						||
| 
								 | 
							
								    >r [
							 | 
						||
| 
								 | 
							
								        R0 over stack@ LDR
							 | 
						||
| 
								 | 
							
								        R1 swap cell + stack@ LDR
							 | 
						||
| 
								 | 
							
								    ] when* r> f %alien-invoke ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %box-small-struct ( size -- )
							 | 
						||
| 
								 | 
							
								    #! Box a 4-byte struct returned in R0.
							 | 
						||
| 
								 | 
							
								    R2 swap MOV
							 | 
						||
| 
								 | 
							
								    "box_small_struct" f %alien-invoke ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: temp@ stack-frame* factor-area-size - swap - ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: struct-return@ ( size n -- n )
							 | 
						||
| 
								 | 
							
								    [
							 | 
						||
| 
								 | 
							
								        stack-frame* +
							 | 
						||
| 
								 | 
							
								    ] [
							 | 
						||
| 
								 | 
							
								        stack-frame* factor-area-size - swap -
							 | 
						||
| 
								 | 
							
								    ] ?if ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %prepare-box-struct ( size -- )
							 | 
						||
| 
								 | 
							
								    ! Compute target address for value struct return
							 | 
						||
| 
								 | 
							
								    R0 SP rot f struct-return@ ADD
							 | 
						||
| 
								 | 
							
								    ! Store it as the first parameter
							 | 
						||
| 
								 | 
							
								    R0 0 stack@ STR ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %box-large-struct ( n size -- )
							 | 
						||
| 
								 | 
							
								    ! Compute destination address
							 | 
						||
| 
								 | 
							
								    [ swap struct-return@ ] keep
							 | 
						||
| 
								 | 
							
								    R0 SP roll ADD
							 | 
						||
| 
								 | 
							
								    R1 swap MOV
							 | 
						||
| 
								 | 
							
								    ! Copy the struct from the C stack
							 | 
						||
| 
								 | 
							
								    "box_value_struct" f %alien-invoke ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend struct-small-enough? ( size -- ? )
							 | 
						||
| 
								 | 
							
								    wince? [ drop f ] [ 4 <= ] if ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %prepare-alien-invoke
							 | 
						||
| 
								 | 
							
								    #! Save Factor stack pointers in case the C code calls a
							 | 
						||
| 
								 | 
							
								    #! callback which does a GC, which must reliably trace
							 | 
						||
| 
								 | 
							
								    #! all roots.
							 | 
						||
| 
								 | 
							
								    "stack_chain" f R12 %alien-global
							 | 
						||
| 
								 | 
							
								    SP R12 0 <+> STR
							 | 
						||
| 
								 | 
							
								    ds-reg R12 8 <+> STR
							 | 
						||
| 
								 | 
							
								    rs-reg R12 12 <+> STR ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %alien-invoke ( symbol dll -- )
							 | 
						||
| 
								 | 
							
								    call-cell rc-absolute-cell rel-dlsym ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %prepare-alien-indirect ( -- )
							 | 
						||
| 
								 | 
							
								    "unbox_alien" f %alien-invoke
							 | 
						||
| 
								 | 
							
								    R0 SP cell temp@ <+> STR ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %alien-indirect ( -- )
							 | 
						||
| 
								 | 
							
								    R12 SP cell temp@ <+> LDR
							 | 
						||
| 
								 | 
							
								    R12 BLX ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %alien-callback ( quot -- )
							 | 
						||
| 
								 | 
							
								    R0 load-indirect
							 | 
						||
| 
								 | 
							
								    "c_to_factor" f %alien-invoke ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %callback-value ( ctype -- )
							 | 
						||
| 
								 | 
							
								    ! Save top of data stack
							 | 
						||
| 
								 | 
							
								    %prepare-unbox
							 | 
						||
| 
								 | 
							
								    R0 SP cell temp@ <+> STR
							 | 
						||
| 
								 | 
							
								    ! Restore data/call/retain stacks
							 | 
						||
| 
								 | 
							
								    "unnest_stacks" f %alien-invoke
							 | 
						||
| 
								 | 
							
								    ! Place former top of data stack in R0
							 | 
						||
| 
								 | 
							
								    R0 SP cell temp@ <+> LDR
							 | 
						||
| 
								 | 
							
								    ! Unbox R0
							 | 
						||
| 
								 | 
							
								    unbox-return ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %cleanup ( alien-node -- ) drop ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: %untag ( dest src -- ) BIN: 111 BIC ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: %untag-fixnum ( dest src -- ) tag-bits get <ASR> MOV ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: %tag-fixnum ( dest src -- ) tag-bits get <LSL> MOV ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend value-structs? t ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend small-enough? ( n -- ? ) 0 255 between? ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: long-long-type c-type-stack-align? drop wince? not ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend fp-shadows-int? ( -- ? ) f ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								! Alien intrinsics
							 | 
						||
| 
								 | 
							
								M: arm-backend %unbox-byte-array ( dst src -- )
							 | 
						||
| 
								 | 
							
								    [ v>operand ] bi@ byte-array-offset ADD ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %unbox-alien ( dst src -- )
							 | 
						||
| 
								 | 
							
								    [ v>operand ] bi@ alien-offset <+> LDR ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %unbox-f ( dst src -- )
							 | 
						||
| 
								 | 
							
								    drop v>operand 0 MOV ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: arm-backend %unbox-any-c-ptr ( dst src -- )
							 | 
						||
| 
								 | 
							
								    #! We need three registers here. R11 and R12 are reserved
							 | 
						||
| 
								 | 
							
								    #! temporary registers. The third one is R14, which we have
							 | 
						||
| 
								 | 
							
								    #! to save/restore.
							 | 
						||
| 
								 | 
							
								    "end" define-label
							 | 
						||
| 
								 | 
							
								    "start" define-label
							 | 
						||
| 
								 | 
							
								    ! Save R14.
							 | 
						||
| 
								 | 
							
								    R14 SP 4 <-> STR
							 | 
						||
| 
								 | 
							
								    ! Address is computed in R11
							 | 
						||
| 
								 | 
							
								    R11 0 MOV
							 | 
						||
| 
								 | 
							
								    ! Load object into R12
							 | 
						||
| 
								 | 
							
								    R12 swap v>operand MOV
							 | 
						||
| 
								 | 
							
								    ! We come back here with displaced aliens
							 | 
						||
| 
								 | 
							
								    "start" resolve-label
							 | 
						||
| 
								 | 
							
								    ! Is the object f?
							 | 
						||
| 
								 | 
							
								    R12 f v>operand CMP
							 | 
						||
| 
								 | 
							
								    ! If so, done
							 | 
						||
| 
								 | 
							
								    "end" get EQ B
							 | 
						||
| 
								 | 
							
								    ! Is the object an alien?
							 | 
						||
| 
								 | 
							
								    R14 R12 header-offset <+/-> LDR
							 | 
						||
| 
								 | 
							
								    R14 alien type-number tag-fixnum CMP
							 | 
						||
| 
								 | 
							
								    ! Add byte array address to address being computed
							 | 
						||
| 
								 | 
							
								    R11 R11 R12 NE ADD
							 | 
						||
| 
								 | 
							
								    ! Add an offset to start of byte array's data area
							 | 
						||
| 
								 | 
							
								    R11 R11 byte-array-offset NE ADD
							 | 
						||
| 
								 | 
							
								    "end" get NE B
							 | 
						||
| 
								 | 
							
								    ! If alien, load the offset
							 | 
						||
| 
								 | 
							
								    R14 R12 alien-offset <+/-> LDR
							 | 
						||
| 
								 | 
							
								    ! Add it to address being computed
							 | 
						||
| 
								 | 
							
								    R11 R11 R14 ADD
							 | 
						||
| 
								 | 
							
								    ! Now recurse on the underlying alien
							 | 
						||
| 
								 | 
							
								    R12 R12 underlying-alien-offset <+/-> LDR
							 | 
						||
| 
								 | 
							
								    "start" get B
							 | 
						||
| 
								 | 
							
								    "end" resolve-label
							 | 
						||
| 
								 | 
							
								    ! Done, store address in destination register
							 | 
						||
| 
								 | 
							
								    v>operand R11 MOV
							 | 
						||
| 
								 | 
							
								    ! Restore R14.
							 | 
						||
| 
								 | 
							
								    R14 SP 4 <-> LDR ;
							 |