463 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Factor
		
	
	
		
		
			
		
	
	
			463 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Factor
		
	
	
| 
								 | 
							
								! Copyright (C) 2007 Slava Pestov.
							 | 
						||
| 
								 | 
							
								! See http://factorcode.org/license.txt for BSD license.
							 | 
						||
| 
								 | 
							
								USING: alien arrays cpu.architecture cpu.arm.assembler
							 | 
						||
| 
								 | 
							
								cpu.arm.architecture cpu.arm.allot kernel kernel.private math
							 | 
						||
| 
								 | 
							
								math.private namespaces sequences words
							 | 
						||
| 
								 | 
							
								quotations byte-arrays hashtables.private hashtables generator
							 | 
						||
| 
								 | 
							
								generator.registers generator.fixup sequences.private sbufs
							 | 
						||
| 
								 | 
							
								sbufs.private vectors vectors.private system
							 | 
						||
| 
								 | 
							
								classes.tuple.private layouts strings.private slots.private ;
							 | 
						||
| 
								 | 
							
								IN: cpu.arm.intrinsics
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: %slot-literal-known-tag
							 | 
						||
| 
								 | 
							
								    "val" operand
							 | 
						||
| 
								 | 
							
								    "obj" operand
							 | 
						||
| 
								 | 
							
								    "n" get cells
							 | 
						||
| 
								 | 
							
								    "obj" get operand-tag - <+/-> ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: %slot-literal-any-tag
							 | 
						||
| 
								 | 
							
								    "scratch" operand "obj" operand %untag
							 | 
						||
| 
								 | 
							
								    "val" operand "scratch" operand "n" get cells <+> ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: %slot-any
							 | 
						||
| 
								 | 
							
								    "scratch" operand "obj" operand %untag
							 | 
						||
| 
								 | 
							
								    "n" operand dup 1 <LSR> MOV
							 | 
						||
| 
								 | 
							
								    "val" operand "scratch" operand "n" operand <+> ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ slot {
							 | 
						||
| 
								 | 
							
								    ! Slot number is literal and the tag is known
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        [ %slot-literal-known-tag LDR ] H{
							 | 
						||
| 
								 | 
							
								            { +input+ { { f "obj" known-tag } { [ small-slot? ] "n" } } }
							 | 
						||
| 
								 | 
							
								            { +scratch+ { { f "val" } } }
							 | 
						||
| 
								 | 
							
								            { +output+ { "val" } }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    ! Slot number is literal
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        [ %slot-literal-any-tag LDR ] H{
							 | 
						||
| 
								 | 
							
								            { +input+ { { f "obj" } { [ small-slot? ] "n" } } }
							 | 
						||
| 
								 | 
							
								            { +scratch+ { { f "scratch" } { f "val" } } }
							 | 
						||
| 
								 | 
							
								            { +output+ { "val" } }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    ! Slot number in a register
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        [ %slot-any LDR ] H{
							 | 
						||
| 
								 | 
							
								            { +input+ { { f "obj" } { f "n" } } }
							 | 
						||
| 
								 | 
							
								            { +scratch+ { { f "val" } { f "scratch" } } }
							 | 
						||
| 
								 | 
							
								            { +output+ { "val" } }
							 | 
						||
| 
								 | 
							
								            { +clobber+ { "n" } }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								} define-intrinsics
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: %write-barrier ( -- )
							 | 
						||
| 
								 | 
							
								    "val" get operand-immediate? "obj" get fresh-object? or [
							 | 
						||
| 
								 | 
							
								        "cards_offset" f R12 %alien-global
							 | 
						||
| 
								 | 
							
								        "scratch" operand R12 "obj" operand card-bits <LSR> ADD
							 | 
						||
| 
								 | 
							
								        "val" operand "scratch" operand 0 <+> LDRB
							 | 
						||
| 
								 | 
							
								        "val" operand dup card-mark ORR
							 | 
						||
| 
								 | 
							
								        "val" operand "scratch" operand 0 <+> STRB
							 | 
						||
| 
								 | 
							
								    ] unless ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ set-slot {
							 | 
						||
| 
								 | 
							
								    ! Slot number is literal and tag is known
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        [ %slot-literal-known-tag STR %write-barrier ] H{
							 | 
						||
| 
								 | 
							
								            { +input+ { { f "val" } { f "obj" known-tag } { [ small-slot? ] "n" } } }
							 | 
						||
| 
								 | 
							
								            { +scratch+ { { f "scratch" } } }
							 | 
						||
| 
								 | 
							
								            { +clobber+ { "val" } }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    ! Slot number is literal
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        [ %slot-literal-any-tag STR %write-barrier ] H{
							 | 
						||
| 
								 | 
							
								            { +input+ { { f "val" } { f "obj" } { [ small-slot? ] "n" } } }
							 | 
						||
| 
								 | 
							
								            { +scratch+ { { f "scratch" } } }
							 | 
						||
| 
								 | 
							
								            { +clobber+ { "val" } }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    ! Slot number is in a register
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        [ %slot-any STR %write-barrier ] H{
							 | 
						||
| 
								 | 
							
								            { +input+ { { f "val" } { f "obj" } { f "n" } } }
							 | 
						||
| 
								 | 
							
								            { +scratch+ { { f "scratch" } } }
							 | 
						||
| 
								 | 
							
								            { +clobber+ { "val" "n" } }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								} define-intrinsics
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: fixnum-op ( op -- quot )
							 | 
						||
| 
								 | 
							
								    [ "out" operand "x" operand "y" operand ] swap add ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: fixnum-register-op ( op -- pair )
							 | 
						||
| 
								 | 
							
								    fixnum-op H{
							 | 
						||
| 
								 | 
							
								        { +input+ { { f "x" } { f "y" } } }
							 | 
						||
| 
								 | 
							
								        { +scratch+ { { f "out" } } }
							 | 
						||
| 
								 | 
							
								        { +output+ { "out" } }
							 | 
						||
| 
								 | 
							
								    } 2array ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: fixnum-value-op ( op -- pair )
							 | 
						||
| 
								 | 
							
								    fixnum-op H{
							 | 
						||
| 
								 | 
							
								        { +input+ { { f "x" } { [ small-tagged? ] "y" } } }
							 | 
						||
| 
								 | 
							
								        { +scratch+ { { f "out" } } }
							 | 
						||
| 
								 | 
							
								        { +output+ { "out" } }
							 | 
						||
| 
								 | 
							
								    } 2array ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: define-fixnum-op ( word op -- )
							 | 
						||
| 
								 | 
							
								    [ fixnum-value-op ] keep fixnum-register-op 2array
							 | 
						||
| 
								 | 
							
								    define-intrinsics ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    { fixnum+fast ADD }
							 | 
						||
| 
								 | 
							
								    { fixnum-fast SUB }
							 | 
						||
| 
								 | 
							
								    { fixnum-bitand AND }
							 | 
						||
| 
								 | 
							
								    { fixnum-bitor ORR }
							 | 
						||
| 
								 | 
							
								    { fixnum-bitxor EOR }
							 | 
						||
| 
								 | 
							
								} [
							 | 
						||
| 
								 | 
							
								    first2 define-fixnum-op
							 | 
						||
| 
								 | 
							
								] each
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ fixnum-bitnot [
							 | 
						||
| 
								 | 
							
								    "x" operand dup MVN
							 | 
						||
| 
								 | 
							
								    "x" operand dup %untag
							 | 
						||
| 
								 | 
							
								] H{
							 | 
						||
| 
								 | 
							
								    { +input+ { { f "x" } } }
							 | 
						||
| 
								 | 
							
								    { +output+ { "x" } }
							 | 
						||
| 
								 | 
							
								} define-intrinsic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ fixnum*fast [
							 | 
						||
| 
								 | 
							
								    "out" operand "y" operand %untag-fixnum
							 | 
						||
| 
								 | 
							
								    "out" operand "x" operand "out" operand MUL
							 | 
						||
| 
								 | 
							
								] H{
							 | 
						||
| 
								 | 
							
								    { +input+ { { f "x" } { f "y" } } }
							 | 
						||
| 
								 | 
							
								    { +scratch+ { { f "out" } } }
							 | 
						||
| 
								 | 
							
								    { +output+ { "out" } }
							 | 
						||
| 
								 | 
							
								} define-intrinsic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ fixnum-shift [
							 | 
						||
| 
								 | 
							
								    "out" operand "x" operand "y" get neg <ASR> MOV
							 | 
						||
| 
								 | 
							
								    ! Mask off low bits
							 | 
						||
| 
								 | 
							
								    "out" operand dup %untag
							 | 
						||
| 
								 | 
							
								] H{
							 | 
						||
| 
								 | 
							
								    { +input+ { { f "x" } { [ -31 0 between? ] "y" } } }
							 | 
						||
| 
								 | 
							
								    { +scratch+ { { f "out" } } }
							 | 
						||
| 
								 | 
							
								    { +output+ { "out" } }
							 | 
						||
| 
								 | 
							
								} define-intrinsic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: %untag-fixnums ( seq -- )
							 | 
						||
| 
								 | 
							
								    [ dup %untag-fixnum ] unique-operands ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: overflow-check ( insn -- )
							 | 
						||
| 
								 | 
							
								    [
							 | 
						||
| 
								 | 
							
								        "end" define-label
							 | 
						||
| 
								 | 
							
								        [ "out" operand "x" operand "y" operand roll S execute ] keep
							 | 
						||
| 
								 | 
							
								        "end" get VC B
							 | 
						||
| 
								 | 
							
								        { "x" "y" } %untag-fixnums
							 | 
						||
| 
								 | 
							
								        "x" operand "x" operand "y" operand roll execute
							 | 
						||
| 
								 | 
							
								        "out" get "x" get %allot-bignum-signed-1
							 | 
						||
| 
								 | 
							
								        "end" resolve-label
							 | 
						||
| 
								 | 
							
								    ] with-scope ; inline
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: overflow-template ( word insn -- )
							 | 
						||
| 
								 | 
							
								    [ overflow-check ] curry H{
							 | 
						||
| 
								 | 
							
								        { +input+ { { f "x" } { f "y" } } }
							 | 
						||
| 
								 | 
							
								        { +scratch+ { { f "out" } } }
							 | 
						||
| 
								 | 
							
								        { +output+ { "out" } }
							 | 
						||
| 
								 | 
							
								        { +clobber+ { "x" "y" } }
							 | 
						||
| 
								 | 
							
								    } define-intrinsic ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ fixnum+ \ ADD overflow-template
							 | 
						||
| 
								 | 
							
								\ fixnum- \ SUB overflow-template
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ fixnum>bignum [
							 | 
						||
| 
								 | 
							
								    "x" operand dup %untag-fixnum
							 | 
						||
| 
								 | 
							
								    "out" get "x" get %allot-bignum-signed-1
							 | 
						||
| 
								 | 
							
								] H{
							 | 
						||
| 
								 | 
							
								    { +input+ { { f "x" } } }
							 | 
						||
| 
								 | 
							
								    { +scratch+ { { f "out" } } }
							 | 
						||
| 
								 | 
							
								    { +clobber+ { "x" } }
							 | 
						||
| 
								 | 
							
								    { +output+ { "out" } }
							 | 
						||
| 
								 | 
							
								} define-intrinsic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ bignum>fixnum [
							 | 
						||
| 
								 | 
							
								    "end" define-label
							 | 
						||
| 
								 | 
							
								    "x" operand dup %untag
							 | 
						||
| 
								 | 
							
								    "y" operand "x" operand cell <+> LDR
							 | 
						||
| 
								 | 
							
								     ! if the length is 1, its just the sign and nothing else,
							 | 
						||
| 
								 | 
							
								     ! so output 0
							 | 
						||
| 
								 | 
							
								    "y" operand 1 v>operand CMP
							 | 
						||
| 
								 | 
							
								    "y" operand 0 EQ MOV
							 | 
						||
| 
								 | 
							
								    "end" get EQ B
							 | 
						||
| 
								 | 
							
								    ! load the value
							 | 
						||
| 
								 | 
							
								    "y" operand "x" operand 3 cells <+> LDR
							 | 
						||
| 
								 | 
							
								    ! load the sign
							 | 
						||
| 
								 | 
							
								    "x" operand "x" operand 2 cells <+> LDR
							 | 
						||
| 
								 | 
							
								    ! is the sign negative?
							 | 
						||
| 
								 | 
							
								    "x" operand 0 CMP
							 | 
						||
| 
								 | 
							
								    ! Negate the value
							 | 
						||
| 
								 | 
							
								    "y" operand "y" operand 0 NE RSB
							 | 
						||
| 
								 | 
							
								    "y" operand dup %tag-fixnum
							 | 
						||
| 
								 | 
							
								    "end" resolve-label
							 | 
						||
| 
								 | 
							
								] H{
							 | 
						||
| 
								 | 
							
								    { +input+ { { f "x" } } }
							 | 
						||
| 
								 | 
							
								    { +scratch+ { { f "y" } } }
							 | 
						||
| 
								 | 
							
								    { +clobber+ { "x" } }
							 | 
						||
| 
								 | 
							
								    { +output+ { "y" } }
							 | 
						||
| 
								 | 
							
								} define-intrinsic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: fixnum-jump ( op -- quo )
							 | 
						||
| 
								 | 
							
								    [ "x" operand "y" operand CMP ] swap
							 | 
						||
| 
								 | 
							
								    1quotation [ B ] 3append ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: fixnum-register-jump ( op -- pair )
							 | 
						||
| 
								 | 
							
								   fixnum-jump { { f "x" } { f "y" } } 2array ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: fixnum-value-jump ( op -- pair )
							 | 
						||
| 
								 | 
							
								    fixnum-jump { { f "x" } { [ small-tagged? ] "y" } } 2array ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: define-fixnum-jump ( word op -- )
							 | 
						||
| 
								 | 
							
								    [ fixnum-value-jump ] keep fixnum-register-jump
							 | 
						||
| 
								 | 
							
								    2array define-if-intrinsics ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    { fixnum< LT }
							 | 
						||
| 
								 | 
							
								    { fixnum<= LE }
							 | 
						||
| 
								 | 
							
								    { fixnum> GT }
							 | 
						||
| 
								 | 
							
								    { fixnum>= GE }
							 | 
						||
| 
								 | 
							
								    { eq? EQ }
							 | 
						||
| 
								 | 
							
								} [
							 | 
						||
| 
								 | 
							
								    first2 define-fixnum-jump
							 | 
						||
| 
								 | 
							
								] each
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ tag [
							 | 
						||
| 
								 | 
							
								    "out" operand "in" operand tag-mask get AND
							 | 
						||
| 
								 | 
							
								    "out" operand dup %tag-fixnum
							 | 
						||
| 
								 | 
							
								] H{
							 | 
						||
| 
								 | 
							
								    { +input+ { { f "in" } } }
							 | 
						||
| 
								 | 
							
								    { +scratch+ { { f "out" } } }
							 | 
						||
| 
								 | 
							
								    { +output+ { "out" } }
							 | 
						||
| 
								 | 
							
								} define-intrinsic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ type [
							 | 
						||
| 
								 | 
							
								    ! Get the tag
							 | 
						||
| 
								 | 
							
								    "out" operand "obj" operand tag-mask get AND
							 | 
						||
| 
								 | 
							
								    ! Compare with object tag number (3).
							 | 
						||
| 
								 | 
							
								    "out" operand object tag-number CMP
							 | 
						||
| 
								 | 
							
								    ! Tag the tag if it is not equal to 3
							 | 
						||
| 
								 | 
							
								    "out" operand dup NE %tag-fixnum
							 | 
						||
| 
								 | 
							
								    ! Load the object header if tag is equal to 3
							 | 
						||
| 
								 | 
							
								    "out" operand "obj" operand object tag-number <-> EQ LDR
							 | 
						||
| 
								 | 
							
								] H{
							 | 
						||
| 
								 | 
							
								    { +input+ { { f "obj" } } }
							 | 
						||
| 
								 | 
							
								    { +scratch+ { { f "out" } } }
							 | 
						||
| 
								 | 
							
								    { +output+ { "out" } }
							 | 
						||
| 
								 | 
							
								} define-intrinsic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ class-hash [
							 | 
						||
| 
								 | 
							
								    "end" define-label
							 | 
						||
| 
								 | 
							
								    ! Get the tag
							 | 
						||
| 
								 | 
							
								    "out" operand "obj" operand tag-mask get AND
							 | 
						||
| 
								 | 
							
								    ! Compare with tuple tag number (2).
							 | 
						||
| 
								 | 
							
								    "out" operand tuple tag-number CMP
							 | 
						||
| 
								 | 
							
								    "out" operand "obj" operand tuple-class-offset <+/-> EQ LDR
							 | 
						||
| 
								 | 
							
								    "out" operand dup class-hash-offset <+/-> EQ LDR
							 | 
						||
| 
								 | 
							
								    "end" get EQ B
							 | 
						||
| 
								 | 
							
								    ! Compare with object tag number (3).
							 | 
						||
| 
								 | 
							
								    "out" operand object tag-number CMP
							 | 
						||
| 
								 | 
							
								    "out" operand "obj" operand object tag-number <-> EQ LDR
							 | 
						||
| 
								 | 
							
								    ! Tag the tag
							 | 
						||
| 
								 | 
							
								    "out" operand dup NE %tag-fixnum
							 | 
						||
| 
								 | 
							
								    "end" resolve-label
							 | 
						||
| 
								 | 
							
								] H{
							 | 
						||
| 
								 | 
							
								    { +input+ { { f "obj" } } }
							 | 
						||
| 
								 | 
							
								    { +scratch+ { { f "out" } } }
							 | 
						||
| 
								 | 
							
								    { +output+ { "out" } }
							 | 
						||
| 
								 | 
							
								} define-intrinsic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: userenv ( reg -- )
							 | 
						||
| 
								 | 
							
								    #! Load the userenv pointer in a register.
							 | 
						||
| 
								 | 
							
								    "userenv" f rot compile-dlsym ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ getenv [
							 | 
						||
| 
								 | 
							
								    "n" operand dup 1 <ASR> MOV
							 | 
						||
| 
								 | 
							
								    "x" operand userenv
							 | 
						||
| 
								 | 
							
								    "x" operand "x" operand "n" operand <+> LDR
							 | 
						||
| 
								 | 
							
								] H{
							 | 
						||
| 
								 | 
							
								    { +input+ { { f "n" } } }
							 | 
						||
| 
								 | 
							
								    { +scratch+ { { f "x" } } }
							 | 
						||
| 
								 | 
							
								    { +output+ { "x" } }
							 | 
						||
| 
								 | 
							
								    { +clobber+ { "n" } }
							 | 
						||
| 
								 | 
							
								} define-intrinsic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ setenv [
							 | 
						||
| 
								 | 
							
								    "n" operand dup 1 <ASR> MOV
							 | 
						||
| 
								 | 
							
								    "x" operand userenv
							 | 
						||
| 
								 | 
							
								    "val" operand "x" operand "n" operand <+> STR
							 | 
						||
| 
								 | 
							
								] H{
							 | 
						||
| 
								 | 
							
								    { +input+ { { f "val" } { f "n" } } }
							 | 
						||
| 
								 | 
							
								    { +scratch+ { { f "x" } } }
							 | 
						||
| 
								 | 
							
								    { +clobber+ { "n" } }
							 | 
						||
| 
								 | 
							
								} define-intrinsic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: %set-slot R11 swap cells <+> STR ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: %store-length
							 | 
						||
| 
								 | 
							
								    R12 "n" operand MOV
							 | 
						||
| 
								 | 
							
								    R12 1 %set-slot ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: %fill-array swap 2 + %set-slot ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ <tuple> [
							 | 
						||
| 
								 | 
							
								    tuple "n" get 2 + cells %allot
							 | 
						||
| 
								 | 
							
								    %store-length
							 | 
						||
| 
								 | 
							
								    ! Store class
							 | 
						||
| 
								 | 
							
								    "class" operand 2 %set-slot
							 | 
						||
| 
								 | 
							
								    ! Zero out the rest of the tuple
							 | 
						||
| 
								 | 
							
								    "initial" operand f v>operand MOV
							 | 
						||
| 
								 | 
							
								    "n" get 1- [ 1+ "initial" operand %fill-array ] each
							 | 
						||
| 
								 | 
							
								    "out" get tuple %store-tagged
							 | 
						||
| 
								 | 
							
								] H{
							 | 
						||
| 
								 | 
							
								    { +input+ { { f "class" } { [ inline-array? ] "n" } } }
							 | 
						||
| 
								 | 
							
								    { +scratch+ { { f "out" } { f "initial" } } }
							 | 
						||
| 
								 | 
							
								    { +output+ { "out" } }
							 | 
						||
| 
								 | 
							
								} define-intrinsic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ <array> [
							 | 
						||
| 
								 | 
							
								    array "n" get 2 + cells %allot
							 | 
						||
| 
								 | 
							
								    %store-length
							 | 
						||
| 
								 | 
							
								    ! Store initial element
							 | 
						||
| 
								 | 
							
								    "n" get [ "initial" operand %fill-array ] each
							 | 
						||
| 
								 | 
							
								    "out" get object %store-tagged
							 | 
						||
| 
								 | 
							
								] H{
							 | 
						||
| 
								 | 
							
								    { +input+ { { [ inline-array? ] "n" } { f "initial" } } }
							 | 
						||
| 
								 | 
							
								    { +scratch+ { { f "out" } } }
							 | 
						||
| 
								 | 
							
								    { +output+ { "out" } }
							 | 
						||
| 
								 | 
							
								} define-intrinsic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ <byte-array> [
							 | 
						||
| 
								 | 
							
								    byte-array "n" get 2 cells + %allot
							 | 
						||
| 
								 | 
							
								    %store-length
							 | 
						||
| 
								 | 
							
								    ! Store initial element
							 | 
						||
| 
								 | 
							
								    R12 0 MOV
							 | 
						||
| 
								 | 
							
								    "n" get cell align cell /i [ R12 %fill-array ] each
							 | 
						||
| 
								 | 
							
								    "out" get object %store-tagged
							 | 
						||
| 
								 | 
							
								] H{
							 | 
						||
| 
								 | 
							
								    { +input+ { { [ inline-array? ] "n" } } }
							 | 
						||
| 
								 | 
							
								    { +scratch+ { { f "out" } } }
							 | 
						||
| 
								 | 
							
								    { +output+ { "out" } }
							 | 
						||
| 
								 | 
							
								} define-intrinsic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ <ratio> [
							 | 
						||
| 
								 | 
							
								    ratio 3 cells %allot
							 | 
						||
| 
								 | 
							
								    "numerator" operand 1 %set-slot
							 | 
						||
| 
								 | 
							
								    "denominator" operand 2 %set-slot
							 | 
						||
| 
								 | 
							
								    "out" get ratio %store-tagged
							 | 
						||
| 
								 | 
							
								] H{
							 | 
						||
| 
								 | 
							
								    { +input+ { { f "numerator" } { f "denominator" } } }
							 | 
						||
| 
								 | 
							
								    { +scratch+ { { f "out" } } }
							 | 
						||
| 
								 | 
							
								    { +output+ { "out" } }
							 | 
						||
| 
								 | 
							
								} define-intrinsic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ <complex> [
							 | 
						||
| 
								 | 
							
								    complex 3 cells %allot
							 | 
						||
| 
								 | 
							
								    "real" operand 1 %set-slot
							 | 
						||
| 
								 | 
							
								    "imaginary" operand 2 %set-slot
							 | 
						||
| 
								 | 
							
								    ! Store tagged ptr in reg
							 | 
						||
| 
								 | 
							
								    "out" get complex %store-tagged
							 | 
						||
| 
								 | 
							
								] H{
							 | 
						||
| 
								 | 
							
								    { +input+ { { f "real" } { f "imaginary" } } }
							 | 
						||
| 
								 | 
							
								    { +scratch+ { { f "out" } } }
							 | 
						||
| 
								 | 
							
								    { +output+ { "out" } }
							 | 
						||
| 
								 | 
							
								} define-intrinsic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ <wrapper> [
							 | 
						||
| 
								 | 
							
								    wrapper 2 cells %allot
							 | 
						||
| 
								 | 
							
								    "obj" operand 1 %set-slot
							 | 
						||
| 
								 | 
							
								    ! Store tagged ptr in reg
							 | 
						||
| 
								 | 
							
								    "out" get object %store-tagged
							 | 
						||
| 
								 | 
							
								] H{
							 | 
						||
| 
								 | 
							
								    { +input+ { { f "obj" } } }
							 | 
						||
| 
								 | 
							
								    { +scratch+ { { f "out" } } }
							 | 
						||
| 
								 | 
							
								    { +output+ { "out" } }
							 | 
						||
| 
								 | 
							
								} define-intrinsic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								! Alien intrinsics
							 | 
						||
| 
								 | 
							
								: %alien-accessor ( quot -- )
							 | 
						||
| 
								 | 
							
								    "offset" operand dup %untag-fixnum
							 | 
						||
| 
								 | 
							
								    "offset" operand dup "alien" operand ADD
							 | 
						||
| 
								 | 
							
								    "value" operand "offset" operand 0 <+> roll call ; inline
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: alien-integer-get-template
							 | 
						||
| 
								 | 
							
								    H{
							 | 
						||
| 
								 | 
							
								        { +input+ {
							 | 
						||
| 
								 | 
							
								            { unboxed-c-ptr "alien" c-ptr }
							 | 
						||
| 
								 | 
							
								            { f "offset" fixnum }
							 | 
						||
| 
								 | 
							
								        } }
							 | 
						||
| 
								 | 
							
								        { +scratch+ { { f "value" } } }
							 | 
						||
| 
								 | 
							
								        { +output+ { "value" } }
							 | 
						||
| 
								 | 
							
								        { +clobber+ { "offset" } }
							 | 
						||
| 
								 | 
							
								    } ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: %alien-integer-get ( quot -- )
							 | 
						||
| 
								 | 
							
								    %alien-accessor
							 | 
						||
| 
								 | 
							
								    "value" operand dup %tag-fixnum ; inline
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: alien-integer-set-template
							 | 
						||
| 
								 | 
							
								    H{
							 | 
						||
| 
								 | 
							
								        { +input+ {
							 | 
						||
| 
								 | 
							
								            { f "value" fixnum }
							 | 
						||
| 
								 | 
							
								            { unboxed-c-ptr "alien" c-ptr }
							 | 
						||
| 
								 | 
							
								            { f "offset" fixnum }
							 | 
						||
| 
								 | 
							
								        } }
							 | 
						||
| 
								 | 
							
								        { +clobber+ { "value" "offset" } }
							 | 
						||
| 
								 | 
							
								    } ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: %alien-integer-set ( quot -- )
							 | 
						||
| 
								 | 
							
								    "offset" get "value" get = [
							 | 
						||
| 
								 | 
							
								        "value" operand dup %untag-fixnum
							 | 
						||
| 
								 | 
							
								    ] unless
							 | 
						||
| 
								 | 
							
								    %alien-accessor ; inline
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: define-alien-integer-intrinsics ( word get-quot word set-quot -- )
							 | 
						||
| 
								 | 
							
								    [ %alien-integer-set ] curry
							 | 
						||
| 
								 | 
							
								    alien-integer-set-template
							 | 
						||
| 
								 | 
							
								    define-intrinsic
							 | 
						||
| 
								 | 
							
								    [ %alien-integer-get ] curry
							 | 
						||
| 
								 | 
							
								    alien-integer-get-template
							 | 
						||
| 
								 | 
							
								    define-intrinsic ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ alien-unsigned-1 [ LDRB ]
							 | 
						||
| 
								 | 
							
								\ set-alien-unsigned-1 [ STRB ]
							 | 
						||
| 
								 | 
							
								define-alien-integer-intrinsics
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: alien-cell-template
							 | 
						||
| 
								 | 
							
								    H{
							 | 
						||
| 
								 | 
							
								        { +input+ {
							 | 
						||
| 
								 | 
							
								            { unboxed-c-ptr "alien" c-ptr }
							 | 
						||
| 
								 | 
							
								            { f "offset" fixnum }
							 | 
						||
| 
								 | 
							
								        } }
							 | 
						||
| 
								 | 
							
								        { +scratch+ { { unboxed-alien "value" } } }
							 | 
						||
| 
								 | 
							
								        { +output+ { "value" } }
							 | 
						||
| 
								 | 
							
								        { +clobber+ { "offset" } }
							 | 
						||
| 
								 | 
							
								    } ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ alien-cell
							 | 
						||
| 
								 | 
							
								[ [ LDR ] %alien-accessor ]
							 | 
						||
| 
								 | 
							
								alien-cell-template define-intrinsic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: set-alien-cell-template
							 | 
						||
| 
								 | 
							
								    H{
							 | 
						||
| 
								 | 
							
								        { +input+ {
							 | 
						||
| 
								 | 
							
								            { unboxed-c-ptr "value" pinned-c-ptr }
							 | 
						||
| 
								 | 
							
								            { unboxed-c-ptr "alien" c-ptr }
							 | 
						||
| 
								 | 
							
								            { f "offset" fixnum }
							 | 
						||
| 
								 | 
							
								        } }
							 | 
						||
| 
								 | 
							
								        { +clobber+ { "offset" } }
							 | 
						||
| 
								 | 
							
								    } ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\ set-alien-cell
							 | 
						||
| 
								 | 
							
								[ [ STR ] %alien-accessor ]
							 | 
						||
| 
								 | 
							
								set-alien-cell-template define-intrinsic
							 |