32 and 64 bit Linux PPC support

db4
Erik Charlebois 2011-05-20 18:11:50 -04:00
parent 662bc3b07b
commit 64252dbdbc
95 changed files with 4847 additions and 2662 deletions

View File

@ -1,8 +1,6 @@
ifdef CONFIG
CC = gcc
CPP = g++
AR = ar
LD = ld
VERSION = 0.94
@ -85,7 +83,8 @@ help:
@echo "freebsd-x86-64"
@echo "linux-x86-32"
@echo "linux-x86-64"
@echo "linux-ppc"
@echo "linux-ppc-32"
@echo "linux-ppc-64"
@echo "linux-arm"
@echo "openbsd-x86-32"
@echo "openbsd-x86-64"
@ -141,8 +140,11 @@ linux-x86-32:
linux-x86-64:
$(MAKE) $(ALL) CONFIG=vm/Config.linux.x86.64
linux-ppc:
$(MAKE) $(ALL) CONFIG=vm/Config.linux.ppc
linux-ppc-32:
$(MAKE) $(ALL) CONFIG=vm/Config.linux.ppc.32
linux-ppc-64:
$(MAKE) $(ALL) CONFIG=vm/Config.linux.ppc.64
linux-arm:
$(MAKE) $(ALL) CONFIG=vm/Config.linux.arm
@ -197,7 +199,7 @@ vm/ffi_test.o: vm/ffi_test.c
$(TOOLCHAIN_PREFIX)$(CPP) -c $(CFLAGS) -o $@ $<
.S.o:
$(TOOLCHAIN_PREFIX)$(CC) -x assembler-with-cpp -c $(CFLAGS) -o $@ $<
$(TOOLCHAIN_PREFIX)$(CC) -c $(CFLAGS) -o $@ $<
.mm.o:
$(TOOLCHAIN_PREFIX)$(CPP) -c $(CFLAGS) -o $@ $<

View File

@ -436,7 +436,7 @@ M: pointer c-type
\ uint c-type \ size_t typedef
] if
cpu ppc? \ uint \ uchar ? c-type clone
cpu ppc? os macosx? and \ uint \ uchar ? c-type clone
[ >c-bool ] >>unboxer-quot
[ c-bool> ] >>boxer-quot
object >>boxed-class

View File

@ -9,6 +9,8 @@ IN: alien.libraries
: dlsym ( name dll -- alien ) [ string>symbol ] dip (dlsym) ;
: dlsym-raw ( name dll -- alien ) [ string>symbol ] dip (dlsym-raw) ;
SYMBOL: libraries
libraries [ H{ } clone ] initialize
@ -48,7 +50,7 @@ M: library dispose dll>> [ dispose ] when* ;
ERROR: no-such-symbol name library ;
: address-of ( name library -- value )
2dup load-library dlsym [ 2nip ] [ no-such-symbol ] if* ;
2dup load-library dlsym-raw [ 2nip ] [ no-such-symbol ] if* ;
SYMBOL: deploy-libraries

View File

@ -15,10 +15,13 @@ generalizations ;
IN: bootstrap.image
: arch ( os cpu -- arch )
[ "winnt" = "winnt" "unix" ? ] dip "-" glue ;
2dup [ winnt? ] [ ppc? ] bi* or [
[ drop unix ] dip
] unless
[ name>> ] [ name>> ] bi* "-" glue ;
: my-arch ( -- arch )
os name>> cpu name>> arch ;
os cpu arch ;
: boot-image-name ( arch -- string )
"boot." ".image" surround ;
@ -29,6 +32,7 @@ IN: bootstrap.image
: images ( -- seq )
{
"winnt-x86.32" "unix-x86.32"
"linux-ppc.32" "linux-ppc.64"
"winnt-x86.64" "unix-x86.64"
} ;
@ -127,6 +131,9 @@ SYMBOL: jit-literals
: jit-dlsym ( name rc -- )
rt-dlsym jit-rel string>symbol jit-parameter f jit-parameter ;
: jit-dlsym-toc ( name rc -- )
rt-dlsym-toc jit-rel string>symbol jit-parameter f jit-parameter ;
:: jit-conditional ( test-quot false-quot -- )
[ 0 test-quot call ] B{ } make length :> len
building get length jit-offset get + len +

View File

@ -460,8 +460,13 @@ cpu ppc? [
{ y int }
{ x longlong } ;
[ 12 ] [ ppc-align-test-2 heap-size ] unit-test
[ 4 ] [ "x" ppc-align-test-2 offset-of ] unit-test
cpu ppc? 4 cell = and os macosx? and [
[ 12 ] [ ppc-align-test-2 heap-size ] unit-test
[ 4 ] [ "x" ppc-align-test-2 offset-of ] unit-test
] [
[ 16 ] [ ppc-align-test-2 heap-size ] unit-test
[ 8 ] [ "x" ppc-align-test-2 offset-of ] unit-test
] if
] when
STRUCT: struct-test-delegate

View File

@ -39,12 +39,12 @@ IN: compiler.cfg.builder.alien
dup large-struct? [
heap-size cell f ^^local-allot [
'[ _ prefix ]
[ int-rep struct-return-on-stack? 2array prefix ] bi*
[ int-rep struct-return-on-stack? f 3array prefix ] bi*
] keep
] [ drop f ] if ;
: (caller-parameters) ( vregs reps -- )
[ first2 next-parameter ] 2each ;
[ first3 next-parameter ] 2each ;
: caller-parameters ( params -- reg-inputs stack-inputs )
[ abi>> ] [ parameters>> ] [ return>> ] tri
@ -136,16 +136,16 @@ M: #alien-assembly emit-node
[ caller-return ]
bi ;
: callee-parameter ( rep on-stack? -- dst )
[ next-vreg dup ] 2dip next-parameter ;
: callee-parameter ( rep on-stack? odd-register? -- dst )
[ next-vreg dup ] 3dip next-parameter ;
: prepare-struct-callee ( c-type -- vreg )
large-struct?
[ int-rep struct-return-on-stack? callee-parameter ] [ f ] if ;
[ int-rep struct-return-on-stack? f callee-parameter ] [ f ] if ;
: (callee-parameters) ( params -- vregs reps )
[ flatten-parameter-type ] map
[ [ [ first2 callee-parameter ] map ] map ]
[ [ [ first3 callee-parameter ] map ] map ]
[ [ keys ] map ]
bi ;

View File

@ -15,19 +15,23 @@ SYMBOL: struct-return-area
GENERIC: flatten-c-type ( c-type -- pairs )
M: c-type flatten-c-type
rep>> f 2array 1array ;
rep>> f f 3array 1array ;
M: long-long-type flatten-c-type
drop 2 [ int-rep long-long-on-stack? 2array ] replicate ;
drop 2 [ int-rep long-long-on-stack? f 3array ] replicate ;
HOOK: flatten-struct-type cpu ( type -- pairs )
HOOK: flatten-struct-type-return cpu ( type -- pairs )
M: object flatten-struct-type
heap-size cell align cell /i { int-rep f } <repetition> ;
heap-size cell align cell /i { int-rep f f } <repetition> ;
M: struct-c-type flatten-c-type
flatten-struct-type ;
M: object flatten-struct-type-return
flatten-struct-type ;
: stack-size ( c-type -- n )
base-type flatten-c-type keys 0 [ rep-size + ] reduce ;
@ -40,6 +44,12 @@ M: struct-c-type flatten-c-type
[| rep offset | src offset rep f ^^load-memory-imm ] 2map
reps ;
:: explode-struct-return ( src c-type -- vregs reps )
c-type flatten-struct-type-return :> reps
reps keys dup component-offsets
[| rep offset | src offset rep f ^^load-memory-imm ] 2map
reps ;
:: implode-struct ( src vregs reps -- )
vregs reps dup component-offsets
[| vreg rep offset | vreg src offset rep f ##store-memory-imm ] 3each ;
@ -62,11 +72,12 @@ M: c-type unbox
[ swap ^^unbox ]
} case 1array
]
[ drop f 2array 1array ] 2bi ;
[ drop f f 3array 1array ] 2bi ;
M: long-long-type unbox
[ next-vreg next-vreg 2dup ] 2dip unboxer>> ##unbox-long-long 2array
int-rep long-long-on-stack? 2array dup 2array ;
int-rep long-long-on-stack? long-long-odd-register? 3array
int-rep long-long-on-stack? f 3array 2array ;
M: struct-c-type unbox ( src c-type -- vregs reps )
[ ^^unbox-any-c-ptr ] dip explode-struct ;
@ -85,7 +96,7 @@ M: struct-c-type unbox-parameter
[ nip heap-size cell f ^^local-allot dup ]
[ [ ^^unbox-any-c-ptr ] dip explode-struct keys ] 2bi
implode-struct
1array { { int-rep f } }
1array { { int-rep f f } }
] if ;
: store-return ( vregs reps -- triples )
@ -165,6 +176,6 @@ M: struct-c-type box-return
[
[
[ [ { } assert-sequence= ] bi@ struct-return-area get ] dip
explode-struct keys
explode-struct-return keys
] keep box
] if ;

View File

@ -1,15 +1,22 @@
! Copyright (C) 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: cpu.architecture fry kernel layouts math math.order
namespaces sequences vectors assocs arrays ;
namespaces sequences vectors assocs arrays locals ;
IN: compiler.cfg.builder.alien.params
SYMBOL: stack-params
: alloc-stack-param ( rep -- n )
GENERIC: alloc-stack-param ( reg -- n )
M: object alloc-stack-param ( rep -- n )
stack-params get
[ rep-size cell align stack-params +@ ] dip ;
M: float-rep alloc-stack-param ( rep -- n )
stack-params get swap rep-size
[ cell align stack-params +@ ] keep
float-right-align-on-stack? [ + ] [ drop ] if ;
: ?dummy-stack-params ( rep -- )
dummy-stack-params? [ alloc-stack-param drop ] [ drop ] if ;
@ -22,21 +29,29 @@ SYMBOL: stack-params
: ?dummy-fp-params ( rep -- )
drop dummy-fp-params? [ float-regs get [ pop* ] unless-empty ] when ;
GENERIC: next-reg-param ( rep -- reg )
GENERIC: next-reg-param ( odd-register? rep -- reg )
M: int-rep next-reg-param
[ ?dummy-stack-params ] [ ?dummy-fp-params ] bi
int-regs get pop ;
[ nip ?dummy-stack-params ]
[ nip ?dummy-fp-params ]
[ drop [
int-regs get last even?
[ int-regs get pop* ] when
] when ]
2tri int-regs get pop ;
M: float-rep next-reg-param
[ ?dummy-stack-params ] [ ?dummy-int-params ] bi
nip [ ?dummy-stack-params ] [ ?dummy-int-params ] bi
float-regs get pop ;
M: double-rep next-reg-param
[ ?dummy-stack-params ] [ ?dummy-int-params ] bi
nip [ ?dummy-stack-params ] [ ?dummy-int-params ] bi
float-regs get pop ;
: reg-class-full? ( reg-class -- ? ) get empty? ;
:: reg-class-full? ( reg-class odd-register? -- ? )
reg-class get empty?
reg-class get length 1 = odd-register? and
dup [ reg-class get delete-all ] when or ;
: init-reg-class ( abi reg-class -- )
[ swap param-regs at <reversed> >vector ] keep set ;
@ -49,9 +64,10 @@ M: double-rep next-reg-param
SYMBOLS: stack-values reg-values ;
: next-parameter ( vreg rep on-stack? -- )
[ dup dup reg-class-of reg-class-full? ] dip or
[ alloc-stack-param stack-values ] [ next-reg-param reg-values ] if
:: next-parameter ( vreg rep on-stack? odd-register? -- )
vreg rep on-stack?
[ dup dup reg-class-of odd-register? reg-class-full? ] dip or
[ alloc-stack-param stack-values ] [ odd-register? swap next-reg-param reg-values ] if
[ 3array ] dip get push ;
: next-return-reg ( rep -- reg ) reg-class-of get pop ;

View File

@ -2080,21 +2080,24 @@ cell 8 = [
} value-numbering-step
] unit-test
[
{
T{ ##peek f 0 D 0 }
T{ ##load-integer f 2 2147483647 }
T{ ##add-imm f 3 0 2147483647 }
T{ ##add-imm f 4 3 2147483647 }
}
] [
{
T{ ##peek f 0 D 0 }
T{ ##load-integer f 2 2147483647 }
T{ ##add f 3 0 2 }
T{ ##add f 4 3 2 }
} value-numbering-step
] unit-test
! PPC ADDI can't hold immediates this big.
cpu ppc? [
[
{
T{ ##peek f 0 D 0 }
T{ ##load-integer f 2 2147483647 }
T{ ##add-imm f 3 0 2147483647 }
T{ ##add-imm f 4 3 2147483647 }
}
] [
{
T{ ##peek f 0 D 0 }
T{ ##load-integer f 2 2147483647 }
T{ ##add f 3 0 2 }
T{ ##add f 4 3 2 }
} value-numbering-step
] unit-test
] unless
] when
[

View File

@ -67,6 +67,9 @@ MEMO: cached-string>symbol ( symbol -- obj ) string>symbol ;
: rel-dlsym ( name dll class -- )
[ add-dlsym-parameters ] dip rt-dlsym rel-fixup ;
: rel-dlsym-toc ( name dll class -- )
[ add-dlsym-parameters ] dip rt-dlsym-toc rel-fixup ;
: rel-word ( word class -- )
[ add-literal ] dip rt-entry-point rel-fixup ;

View File

@ -45,13 +45,14 @@ CONSTANT: rc-absolute 1
CONSTANT: rc-relative 2
CONSTANT: rc-absolute-ppc-2/2 3
CONSTANT: rc-absolute-ppc-2 4
CONSTANT: rc-relative-ppc-2 5
CONSTANT: rc-relative-ppc-3 6
CONSTANT: rc-relative-ppc-2-pc 5
CONSTANT: rc-relative-ppc-3-pc 6
CONSTANT: rc-relative-arm-3 7
CONSTANT: rc-indirect-arm 8
CONSTANT: rc-indirect-arm-pc 9
CONSTANT: rc-absolute-2 10
CONSTANT: rc-absolute-1 11
CONSTANT: rc-absolute-ppc-2/2/2/2 12
! Relocation types
CONSTANT: rt-dlsym 0
@ -67,6 +68,7 @@ CONSTANT: rt-vm 9
CONSTANT: rt-cards-offset 10
CONSTANT: rt-decks-offset 11
CONSTANT: rt-exception-handler 12
CONSTANT: rt-dlsym-toc 13
: rc-absolute? ( n -- ? )
${

View File

@ -575,9 +575,18 @@ HOOK: dummy-fp-params? cpu ( -- ? )
! If t, long longs are never passed in param regs
HOOK: long-long-on-stack? cpu ( -- ? )
! If t, long longs are aligned on an odd register. On Linux
! 32-bit PPC, long longs are 8-byte aligned but passed in
! registers so they need to be aligned on an odd numbered
! (r3, r5, etc) register.
HOOK: long-long-odd-register? cpu ( -- ? )
! If t, floats are never passed in param regs
HOOK: float-on-stack? cpu ( -- ? )
! If t, put floats in the second word of a double word on the stack
HOOK: float-right-align-on-stack? cpu ( -- ? )
! If t, the struct return pointer is never passed in a param reg
HOOK: struct-return-on-stack? cpu ( -- ? )

View File

@ -0,0 +1,3 @@
! Copyright (C) 2011 Erik Charlebois.
! See http://factorcode.org/license.txt for BSD license.
USING: cpu.ppc ;

View File

@ -0,0 +1,73 @@
! Copyright (C) 2011 Erik Charlebois.
! See http://factorcode.org/license.txt for BSD license.
USING: parser system kernel sequences math math.ranges
cpu.ppc.assembler combinators compiler.constants
bootstrap.image.private layouts namespaces ;
IN: bootstrap.ppc
4 \ cell set
big-endian on
: reserved-size ( -- n ) 24 ;
: lr-save ( -- n ) 4 ;
CONSTANT: ds-reg 14
CONSTANT: rs-reg 15
CONSTANT: vm-reg 16
CONSTANT: ctx-reg 17
CONSTANT: frame-reg 31
: nv-int-regs ( -- seq ) 13 31 [a,b] ;
: LOAD32 ( r n -- )
[ -16 shift HEX: ffff bitand LIS ]
[ [ dup ] dip HEX: ffff bitand ORI ] 2bi ;
: jit-trap-null ( src -- ) drop ;
: jit-load-vm ( dst -- )
0 LOAD32 0 rc-absolute-ppc-2/2 jit-vm ;
: jit-load-dlsym ( dst string -- )
[ 0 LOAD32 ] dip rc-absolute-ppc-2/2 jit-dlsym ;
: jit-load-dlsym-toc ( string -- ) drop ;
: jit-load-vm-arg ( dst -- )
0 LOAD32 rc-absolute-ppc-2/2 rt-vm jit-rel ;
: jit-load-entry-point-arg ( dst -- )
0 LOAD32 rc-absolute-ppc-2/2 rt-entry-point jit-rel ;
: jit-load-this-arg ( dst -- )
0 LOAD32 rc-absolute-ppc-2/2 rt-this jit-rel ;
: jit-load-literal-arg ( dst -- )
0 LOAD32 rc-absolute-ppc-2/2 rt-literal jit-rel ;
: jit-load-dlsym-arg ( dst -- )
0 LOAD32 rc-absolute-ppc-2/2 rt-dlsym jit-rel ;
: jit-load-dlsym-toc-arg ( -- ) ;
: jit-load-here-arg ( dst -- )
0 LOAD32 rc-absolute-ppc-2/2 rt-here jit-rel ;
: jit-load-megamorphic-cache-arg ( dst -- )
0 LOAD32 rc-absolute-ppc-2/2 rt-megamorphic-cache-hits jit-rel ;
: jit-load-cell ( dst src offset -- ) LWZ ;
: jit-load-cell-x ( dst src offset -- ) LWZX ;
: jit-load-cell-update ( dst src offset -- ) LWZU ;
: jit-save-cell ( dst src offset -- ) STW ;
: jit-save-cell-x ( dst src offset -- ) STWX ;
: jit-save-cell-update ( dst src offset -- ) STWU ;
: jit-load-int ( dst src offset -- ) LWZ ;
: jit-save-int ( dst src offset -- ) STW ;
: jit-shift-tag-bits ( dst src -- ) tag-bits get SRAWI ;
: jit-mask-tag-bits ( dst src -- ) tag-bits get CLRRWI ;
: jit-shift-fixnum-slot ( dst src -- ) 2 SRAWI ;
: jit-class-hashcode ( dst src -- ) 1 SRAWI ;
: jit-shift-left-logical ( dst src n -- ) SLW ;
: jit-shift-left-logical-imm ( dst src n -- ) SLWI ;
: jit-shift-right-algebraic ( dst src n -- ) SRAW ;
: jit-divide ( dst ra rb -- ) DIVW ;
: jit-multiply-low ( dst ra rb -- ) MULLW ;
: jit-multiply-low-ov-rc ( dst ra rb -- ) MULLWO. ;
: jit-compare-cell ( cr ra rb -- ) CMPW ;
: jit-compare-cell-imm ( cr ra imm -- ) CMPWI ;
: cell-size ( -- n ) 4 ;
: factor-area-size ( -- n ) 16 ;
: param-size ( -- n ) 32 ;
: saved-int-regs-size ( -- n ) 96 ;
<< "vocab:cpu/ppc/bootstrap.factor" parse-file suffix! >>
call

View File

@ -0,0 +1,46 @@
! Copyright (C) 2011 Erik Charlebois
! See http://factorcode.org/license.txt for BSD license.
USING: accessors system kernel layouts combinators
compiler.cfg.builder.alien.boxing sequences arrays
alien.c-types cpu.architecture cpu.ppc alien.complex ;
IN: cpu.ppc.32.linux
M: linux lr-save ( -- n ) 1 cells ;
M: linux has-toc ( -- ? ) f ;
M: linux reserved-area-size ( -- n ) 2 cells ;
M: linux allows-null-dereference ( -- ? ) f ;
M: ppc param-regs
drop {
{ int-regs { 3 4 5 6 7 8 9 10 } }
{ float-regs { 1 2 3 4 5 6 7 8 } }
} ;
M: ppc value-struct?
c-type [ complex-double c-type = ]
[ complex-float c-type = ] bi or ;
M: ppc dummy-stack-params? f ;
M: ppc dummy-int-params? f ;
M: ppc dummy-fp-params? f ;
M: ppc long-long-on-stack? f ;
M: ppc long-long-odd-register? t ;
M: ppc float-right-align-on-stack? f ;
M: ppc flatten-struct-type ( type -- seq )
{
{ [ dup c-type complex-double c-type = ]
[ drop { { int-rep f f } { int-rep f f }
{ int-rep f f } { int-rep f f } } ] }
{ [ dup c-type complex-float c-type = ]
[ drop { { int-rep f f } { int-rep f f } } ] }
[ call-next-method [ first t f 3array ] map ]
} cond ;

View File

@ -0,0 +1,3 @@
! Copyright (C) 2011 Erik Charlebois.
! See http://factorcode.org/license.txt for BSD license.
USING: cpu.ppc ;

View File

@ -0,0 +1,80 @@
! Copyright (C) 2011 Erik Charlebois.
! See http://factorcode.org/license.txt for BSD license.
USING: parser system kernel sequences math math.ranges
cpu.ppc.assembler combinators compiler.constants
bootstrap.image.private layouts namespaces ;
IN: bootstrap.ppc
8 \ cell set
big-endian on
: reserved-size ( -- n ) 48 ;
: lr-save ( -- n ) 16 ;
CONSTANT: ds-reg 14
CONSTANT: rs-reg 15
CONSTANT: vm-reg 16
CONSTANT: ctx-reg 17
CONSTANT: frame-reg 31
: nv-int-regs ( -- seq ) 13 31 [a,b] ;
: LOAD64 ( r n -- )
[ dup ] dip {
[ nip -48 shift HEX: ffff bitand LIS ]
[ -32 shift HEX: ffff bitand ORI ]
[ drop 32 SLDI ]
[ -16 shift HEX: ffff bitand ORIS ]
[ HEX: ffff bitand ORI ]
} 3cleave ;
: jit-trap-null ( src -- ) drop ;
: jit-load-vm ( dst -- )
0 LOAD64 0 rc-absolute-ppc-2/2/2/2 jit-vm ;
: jit-load-dlsym ( dst string -- )
[ 0 LOAD64 ] dip rc-absolute-ppc-2/2/2/2 jit-dlsym ;
: jit-load-dlsym-toc ( string -- )
[ 2 0 LOAD64 ] dip rc-absolute-ppc-2/2/2/2 jit-dlsym-toc ;
: jit-load-vm-arg ( dst -- )
0 LOAD64 rc-absolute-ppc-2/2/2/2 rt-vm jit-rel ;
: jit-load-entry-point-arg ( dst -- )
0 LOAD64 rc-absolute-ppc-2/2/2/2 rt-entry-point jit-rel ;
: jit-load-this-arg ( dst -- )
0 LOAD64 rc-absolute-ppc-2/2/2/2 rt-this jit-rel ;
: jit-load-literal-arg ( dst -- )
0 LOAD64 rc-absolute-ppc-2/2/2/2 rt-literal jit-rel ;
: jit-load-dlsym-arg ( dst -- )
0 LOAD64 rc-absolute-ppc-2/2/2/2 rt-dlsym jit-rel ;
: jit-load-dlsym-toc-arg ( -- )
2 0 LOAD64 rc-absolute-ppc-2/2/2/2 rt-dlsym-toc jit-rel ;
: jit-load-here-arg ( dst -- )
0 LOAD64 rc-absolute-ppc-2/2/2/2 rt-here jit-rel ;
: jit-load-megamorphic-cache-arg ( dst -- )
0 LOAD64 rc-absolute-ppc-2/2/2/2 rt-megamorphic-cache-hits jit-rel ;
: jit-load-cell ( dst src offset -- ) LD ;
: jit-load-cell-x ( dst src offset -- ) LDX ;
: jit-load-cell-update ( dst src offset -- ) LDU ;
: jit-save-cell ( dst src offset -- ) STD ;
: jit-save-cell-x ( dst src offset -- ) STDX ;
: jit-save-cell-update ( dst src offset -- ) STDU ;
: jit-load-int ( dst src offset -- ) LD ;
: jit-save-int ( dst src offset -- ) STD ;
: jit-shift-tag-bits ( dst src -- ) tag-bits get SRADI ;
: jit-mask-tag-bits ( dst src -- ) tag-bits get CLRRDI ;
: jit-shift-fixnum-slot ( dst src -- ) 1 SRADI ;
: jit-class-hashcode ( dst src -- ) 1 SRADI ;
: jit-shift-left-logical ( dst src n -- ) SLD ;
: jit-shift-left-logical-imm ( dst src n -- ) SLDI ;
: jit-shift-right-algebraic ( dst src n -- ) SRAD ;
: jit-divide ( dst ra rb -- ) DIVD ;
: jit-multiply-low ( dst ra rb -- ) MULLD ;
: jit-multiply-low-ov-rc ( dst ra rb -- ) MULLDO. ;
: jit-compare-cell ( cr ra rb -- ) CMPD ;
: jit-compare-cell-imm ( cr ra imm -- ) CMPDI ;
: cell-size ( -- n ) 8 ;
: factor-area-size ( -- n ) 32 ;
: param-size ( -- n ) 64 ;
: saved-int-regs-size ( -- n ) 192 ;
<< "vocab:cpu/ppc/bootstrap.factor" parse-file suffix! >>
call

View File

@ -0,0 +1,52 @@
! Copyright (C) 2011 Erik Charlebois
! See http://factorcode.org/license.txt for BSD license.
USING: accessors system kernel layouts combinators
compiler.cfg.builder.alien.boxing sequences arrays math
alien.c-types cpu.architecture cpu.ppc alien.complex ;
IN: cpu.ppc.64.linux
M: linux lr-save 2 cells ;
M: linux has-toc ( -- ? ) t ;
M: linux reserved-area-size ( -- n ) 6 cells ;
M: linux allows-null-dereference ( -- ? ) f ;
M: ppc param-regs
drop {
{ int-regs { 3 4 5 6 7 8 9 10 } }
{ float-regs { 1 2 3 4 5 6 7 8 9 10 11 12 13 } }
} ;
M: ppc value-struct? drop t ;
M: ppc dummy-stack-params? t ;
M: ppc dummy-int-params? t ;
M: ppc dummy-fp-params? f ;
M: ppc long-long-on-stack? f ;
M: ppc long-long-odd-register? f ;
M: ppc float-right-align-on-stack? t ;
M: ppc flatten-struct-type ( type -- seq )
{
{ [ dup c-type complex-double c-type = ]
[ drop { { double-rep f f } { double-rep f f } } ] }
{ [ dup c-type complex-float c-type = ]
[ drop { { float-rep f f } { float-rep f f } } ] }
[ heap-size cell align cell /i { int-rep f f } <repetition> ]
} cond ;
M: ppc flatten-struct-type-return ( type -- seq )
{
{ [ dup c-type complex-double c-type = ]
[ drop { { double-rep f f } { double-rep f f } } ] }
{ [ dup c-type complex-float c-type = ]
[ drop { { float-rep f f } { float-rep f f } } ] }
[ heap-size cell align cell /i { int-rep t f } <repetition> ]
} cond ;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
Erik Charlebois

View File

@ -0,0 +1,845 @@
! Copyright (C) 2011 Erik Charlebois
! See http://factorcode.org/license.txt for BSD license.
USING: bootstrap.image.private kernel kernel.private namespaces
system cpu.ppc.assembler compiler.units compiler.constants math
math.private math.ranges layouts words vocabs slots.private
locals locals.backend generic.single.private fry sequences
threads.private strings.private ;
FROM: cpu.ppc.assembler => B ;
IN: bootstrap.ppc
: jit-call ( string -- )
dup
0 swap jit-load-dlsym
0 MTLR
jit-load-dlsym-toc
BLRL ;
: jit-call-quot ( -- )
4 quot-entry-point-offset LI
4 3 4 jit-load-cell-x
4 MTLR
BLRL ;
: jit-jump-quot ( -- )
4 quot-entry-point-offset LI
4 3 4 jit-load-cell-x
4 MTCTR
BCTR ;
: stack-frame ( -- n )
reserved-size factor-area-size + 16 align ;
: save-at ( m -- n ) reserved-size + param-size + ;
: save-int ( reg off -- ) [ 1 ] dip save-at jit-save-int ;
: save-fp ( reg off -- ) [ 1 ] dip save-at STFD ;
: save-vec ( reg offt -- ) save-at 11 swap LI 11 1 STVXL ;
: restore-int ( reg off -- ) [ 1 ] dip save-at jit-load-int ;
: restore-fp ( reg off -- ) [ 1 ] dip save-at LFD ;
: restore-vec ( reg offt -- ) save-at 11 swap LI 11 1 LVXL ;
! Stop using intervals here.
: nv-fp-regs ( -- seq ) 14 31 [a,b] ;
: nv-vec-regs ( -- seq ) 20 31 [a,b] ;
: saved-fp-regs-size ( -- n ) 144 ;
: saved-vec-regs-size ( -- n ) 192 ;
: callback-frame-size ( -- n )
reserved-size
param-size +
saved-int-regs-size +
saved-fp-regs-size +
saved-vec-regs-size +
16 align ;
: old-context-save-offset ( -- n )
cell-size 20 * saved-fp-regs-size + saved-vec-regs-size + save-at ;
[
! Save old stack pointer
11 1 MR
0 MFLR ! Get return address
0 1 lr-save jit-save-cell ! Stash return address
1 1 callback-frame-size neg jit-save-cell-update ! Bump stack pointer and set back chain
! Save all non-volatile registers
nv-int-regs [ cell-size * save-int ] each-index
nv-fp-regs [ 8 * saved-int-regs-size + save-fp ] each-index
! nv-vec-regs [ 16 * saved-int-regs-size saved-fp-regs-size + + save-vec ] each-index
! Stick old stack pointer in the frame register so callbacks
! can access their arguments
frame-reg 11 MR
! Load VM into vm-reg
vm-reg jit-load-vm-arg
! Save old context
0 vm-reg vm-context-offset jit-load-cell
0 1 old-context-save-offset jit-save-cell
! Switch over to the spare context
11 vm-reg vm-spare-context-offset jit-load-cell
11 vm-reg vm-context-offset jit-save-cell
! Save C callstack pointer and load Factor callstack
1 11 context-callstack-save-offset jit-save-cell
1 11 context-callstack-bottom-offset jit-load-cell
! Load new data and retain stacks
rs-reg 11 context-retainstack-offset jit-load-cell
ds-reg 11 context-datastack-offset jit-load-cell
! Call into Factor code
0 jit-load-entry-point-arg
0 MTLR
BLRL
! Load VM again, pointlessly
vm-reg jit-load-vm-arg
! Load C callstack pointer
11 vm-reg vm-context-offset jit-load-cell
1 11 context-callstack-save-offset jit-load-cell
! Load old context
0 1 old-context-save-offset jit-load-cell
0 vm-reg vm-context-offset jit-save-cell
! Restore non-volatile registers
! nv-vec-regs [ 16 * saved-int-regs-size saved-float-regs-size + + restore-vec ] each-index
nv-fp-regs [ 8 * saved-int-regs-size + restore-fp ] each-index
nv-int-regs [ cell-size * restore-int ] each-index
1 1 callback-frame-size ADDI ! Bump stack back up
0 1 lr-save jit-load-cell ! Fetch return address
0 MTLR ! Set up return
BLR ! Branch back
] callback-stub jit-define
: jit-conditional* ( test-quot false-quot -- )
[ '[ 4 + @ ] ] dip jit-conditional ; inline
: jit-load-context ( -- )
ctx-reg vm-reg vm-context-offset jit-load-cell ;
: jit-save-context ( -- )
jit-load-context
1 ctx-reg context-callstack-top-offset jit-save-cell
ds-reg ctx-reg context-datastack-offset jit-save-cell
rs-reg ctx-reg context-retainstack-offset jit-save-cell ;
: jit-restore-context ( -- )
ds-reg ctx-reg context-datastack-offset jit-load-cell
rs-reg ctx-reg context-retainstack-offset jit-load-cell ;
[
12 jit-load-literal-arg
0 profile-count-offset LI
11 12 0 jit-load-cell-x
11 11 1 tag-fixnum ADDI
11 12 0 jit-save-cell-x
0 word-code-offset LI
11 12 0 jit-load-cell-x
11 11 compiled-header-size ADDI
11 MTCTR
BCTR
] jit-profiling jit-define
[
0 MFLR
0 1 lr-save jit-save-cell
0 jit-load-this-arg
0 1 cell-size 2 * neg jit-save-cell
0 stack-frame LI
0 1 cell-size 1 * neg jit-save-cell
1 1 stack-frame neg jit-save-cell-update
] jit-prolog jit-define
[
3 jit-load-literal-arg
3 ds-reg cell-size jit-save-cell-update
] jit-push jit-define
[
jit-save-context
3 vm-reg MR
4 jit-load-dlsym-arg
4 MTLR
jit-load-dlsym-toc-arg ! Restore the TOC/GOT
BLRL
jit-restore-context
] jit-primitive jit-define
[ 0 BL rc-relative-ppc-3-pc rt-entry-point-pic jit-rel ] jit-word-call jit-define
[
6 jit-load-here-arg
0 B rc-relative-ppc-3-pc rt-entry-point-pic-tail jit-rel
] jit-word-jump jit-define
[
3 ds-reg 0 jit-load-cell
ds-reg dup cell-size SUBI
0 3 \ f type-number jit-compare-cell-imm
[ 0 swap BEQ ] [ 0 B rc-relative-ppc-3-pc rt-entry-point jit-rel ] jit-conditional*
0 B rc-relative-ppc-3-pc rt-entry-point jit-rel
] jit-if jit-define
: jit->r ( -- )
4 ds-reg 0 jit-load-cell
ds-reg dup cell-size SUBI
4 rs-reg cell-size jit-save-cell-update ;
: jit-2>r ( -- )
4 ds-reg 0 jit-load-cell
5 ds-reg cell-size neg jit-load-cell
ds-reg dup 2 cell-size * SUBI
rs-reg dup 2 cell-size * ADDI
4 rs-reg 0 jit-save-cell
5 rs-reg cell-size neg jit-save-cell ;
: jit-3>r ( -- )
4 ds-reg 0 jit-load-cell
5 ds-reg cell-size neg jit-load-cell
6 ds-reg cell-size neg 2 * jit-load-cell
ds-reg dup 3 cell-size * SUBI
rs-reg dup 3 cell-size * ADDI
4 rs-reg 0 jit-save-cell
5 rs-reg cell-size neg jit-save-cell
6 rs-reg cell-size neg 2 * jit-save-cell ;
: jit-r> ( -- )
4 rs-reg 0 jit-load-cell
rs-reg dup cell-size SUBI
4 ds-reg cell-size jit-save-cell-update ;
: jit-2r> ( -- )
4 rs-reg 0 jit-load-cell
5 rs-reg cell-size neg jit-load-cell
rs-reg dup 2 cell-size * SUBI
ds-reg dup 2 cell-size * ADDI
4 ds-reg 0 jit-save-cell
5 ds-reg cell-size neg jit-save-cell ;
: jit-3r> ( -- )
4 rs-reg 0 jit-load-cell
5 rs-reg cell-size neg jit-load-cell
6 rs-reg cell-size neg 2 * jit-load-cell
rs-reg dup 3 cell-size * SUBI
ds-reg dup 3 cell-size * ADDI
4 ds-reg 0 jit-save-cell
5 ds-reg cell-size neg jit-save-cell
6 ds-reg cell-size neg 2 * jit-save-cell ;
[
jit->r
0 BL rc-relative-ppc-3-pc rt-entry-point jit-rel
jit-r>
] jit-dip jit-define
[
jit-2>r
0 BL rc-relative-ppc-3-pc rt-entry-point jit-rel
jit-2r>
] jit-2dip jit-define
[
jit-3>r
0 BL rc-relative-ppc-3-pc rt-entry-point jit-rel
jit-3r>
] jit-3dip jit-define
[
1 1 stack-frame ADDI
0 1 lr-save jit-load-cell
0 MTLR
] jit-epilog jit-define
[ BLR ] jit-return jit-define
! ! ! Polymorphic inline caches
! Don't touch r6 here; it's used to pass the tail call site
! address for tail PICs
! Load a value from a stack position
[
4 ds-reg 0 jit-load-cell rc-absolute-ppc-2 rt-untagged jit-rel
] pic-load jit-define
[ 4 4 tag-mask get ANDI. ] pic-tag jit-define
[
3 4 MR
4 4 tag-mask get ANDI.
0 4 tuple type-number jit-compare-cell-imm
[ 0 swap BNE ]
[ 4 tuple-class-offset LI 4 3 4 jit-load-cell-x ]
jit-conditional*
] pic-tuple jit-define
[
0 4 0 jit-compare-cell-imm rc-absolute-ppc-2 rt-untagged jit-rel
] pic-check-tag jit-define
[
5 jit-load-literal-arg
0 4 5 jit-compare-cell
] pic-check-tuple jit-define
[
[ 0 swap BNE ] [ 0 B rc-relative-ppc-3-pc rt-entry-point jit-rel ] jit-conditional*
] pic-hit jit-define
! Inline cache miss entry points
: jit-load-return-address ( -- ) 6 MFLR ;
! These are always in tail position with an existing stack
! frame, and the stack. The frame setup takes this into account.
: jit-inline-cache-miss ( -- )
jit-save-context
3 6 MR
4 vm-reg MR
ctx-reg 6 MR
"inline_cache_miss" jit-call
6 ctx-reg MR
jit-load-context
jit-restore-context ;
[ jit-load-return-address jit-inline-cache-miss ]
[ 3 MTLR BLRL ]
[ 3 MTCTR BCTR ]
\ inline-cache-miss define-combinator-primitive
[ jit-inline-cache-miss ]
[ 3 MTLR BLRL ]
[ 3 MTCTR BCTR ]
\ inline-cache-miss-tail define-combinator-primitive
! ! ! Megamorphic caches
[
! class = ...
3 4 MR
4 4 tag-mask get ANDI. ! Mask and...
4 4 tag-bits get jit-shift-left-logical-imm ! shift tag bits to fixnum
0 4 tuple type-number tag-fixnum jit-compare-cell-imm
[ 0 swap BNE ]
[ 4 tuple-class-offset LI 4 3 4 jit-load-cell-x ]
jit-conditional*
! cache = ...
3 jit-load-literal-arg
! key = hashcode(class)
5 4 jit-class-hashcode
! key &= cache.length - 1
5 5 mega-cache-size get 1 - 4 * ANDI.
! cache += array-start-offset
3 3 array-start-offset ADDI
! cache += key
3 3 5 ADD
! if(get(cache) == class)
6 3 0 jit-load-cell
0 6 4 jit-compare-cell
[ 0 swap BNE ]
[
! megamorphic_cache_hits++
4 jit-load-megamorphic-cache-arg
5 4 0 jit-load-cell
5 5 1 ADDI
5 4 0 jit-save-cell
! ... goto get(cache + cell-size)
5 word-entry-point-offset LI
3 3 cell-size jit-load-cell
3 3 5 jit-load-cell-x
3 MTCTR
BCTR
]
jit-conditional*
! fall-through on miss
] mega-lookup jit-define
! ! ! Sub-primitives
! Quotations and words
[
3 ds-reg 0 jit-load-cell
ds-reg dup cell-size SUBI
]
[ jit-call-quot ]
[ jit-jump-quot ] \ (call) define-combinator-primitive
[
3 ds-reg 0 jit-load-cell
ds-reg dup cell-size SUBI
4 word-entry-point-offset LI
4 3 4 jit-load-cell-x
]
[ 4 MTLR BLRL ]
[ 4 MTCTR BCTR ] \ (execute) define-combinator-primitive
[
3 ds-reg 0 jit-load-cell
ds-reg dup cell-size SUBI
4 word-entry-point-offset LI
4 3 4 jit-load-cell-x
4 MTCTR BCTR
] jit-execute jit-define
! Special primitives
[
frame-reg 3 MR
3 vm-reg MR
"begin_callback" jit-call
jit-load-context
jit-restore-context
! Call quotation
3 frame-reg MR
jit-call-quot
jit-save-context
3 vm-reg MR
"end_callback" jit-call
] \ c-to-factor define-sub-primitive
[
! Unwind stack frames
1 4 MR
! Load VM pointer into vm-reg, since we're entering from
! C code
vm-reg jit-load-vm
! Load ds and rs registers
jit-load-context
jit-restore-context
! We have changed the stack; load return address again
0 1 lr-save jit-load-cell
0 MTLR
! Call quotation
jit-jump-quot
] \ unwind-native-frames define-sub-primitive
[
7 0 LI
7 1 lr-save jit-save-cell
! Load callstack object
6 ds-reg 0 jit-load-cell
ds-reg ds-reg cell-size SUBI
! Get ctx->callstack_bottom
jit-load-context
3 ctx-reg context-callstack-bottom-offset jit-load-cell
! Get top of callstack object -- 'src' for memcpy
4 6 callstack-top-offset ADDI
! Get callstack length, in bytes --- 'len' for memcpy
7 callstack-length-offset LI
5 6 7 jit-load-cell-x
5 5 jit-shift-tag-bits
! Compute new stack pointer -- 'dst' for memcpy
3 3 5 SUB
! Install new stack pointer
1 3 MR
! Call memcpy; arguments are now in the correct registers
1 1 -16 cell-size * jit-save-cell-update
"factor_memcpy" jit-call
1 1 0 jit-load-cell
! Return with new callstack
0 1 lr-save jit-load-cell
0 MTLR
BLR
] \ set-callstack define-sub-primitive
[
jit-save-context
4 vm-reg MR
"lazy_jit_compile" jit-call
]
[ jit-call-quot ]
[ jit-jump-quot ]
\ lazy-jit-compile define-combinator-primitive
! Objects
[
3 ds-reg 0 jit-load-cell
3 3 tag-mask get ANDI.
3 3 tag-bits get jit-shift-left-logical-imm
3 ds-reg 0 jit-save-cell
] \ tag define-sub-primitive
[
3 ds-reg 0 jit-load-cell ! Load m
4 ds-reg cell-size neg jit-load-cell-update ! Load obj
3 3 jit-shift-fixnum-slot ! Shift to a cell-size multiple
4 4 jit-mask-tag-bits ! Clear tag bits on obj
3 4 3 jit-load-cell-x ! Load cell at &obj[m]
3 ds-reg 0 jit-save-cell ! Push the result to the stack
] \ slot define-sub-primitive
[
! load string index from stack
3 ds-reg cell-size neg jit-load-cell
3 3 jit-shift-tag-bits
! load string from stack
4 ds-reg 0 jit-load-cell
! load character
4 4 string-offset ADDI
3 3 4 LBZX
3 3 tag-bits get jit-shift-left-logical-imm
! store character to stack
ds-reg ds-reg cell-size SUBI
3 ds-reg 0 jit-save-cell
] \ string-nth-fast define-sub-primitive
! Shufflers
[
ds-reg dup cell-size SUBI
] \ drop define-sub-primitive
[
ds-reg dup 2 cell-size * SUBI
] \ 2drop define-sub-primitive
[
ds-reg dup 3 cell-size * SUBI
] \ 3drop define-sub-primitive
[
3 ds-reg 0 jit-load-cell
3 ds-reg cell-size jit-save-cell-update
] \ dup define-sub-primitive
[
3 ds-reg 0 jit-load-cell
4 ds-reg cell-size neg jit-load-cell
ds-reg dup 2 cell-size * ADDI
3 ds-reg 0 jit-save-cell
4 ds-reg cell-size neg jit-save-cell
] \ 2dup define-sub-primitive
[
3 ds-reg 0 jit-load-cell
4 ds-reg cell-size neg jit-load-cell
5 ds-reg cell-size neg 2 * jit-load-cell
ds-reg dup cell-size 3 * ADDI
3 ds-reg 0 jit-save-cell
4 ds-reg cell-size neg jit-save-cell
5 ds-reg cell-size neg 2 * jit-save-cell
] \ 3dup define-sub-primitive
[
3 ds-reg 0 jit-load-cell
ds-reg dup cell-size SUBI
3 ds-reg 0 jit-save-cell
] \ nip define-sub-primitive
[
3 ds-reg 0 jit-load-cell
ds-reg dup cell-size 2 * SUBI
3 ds-reg 0 jit-save-cell
] \ 2nip define-sub-primitive
[
3 ds-reg cell-size neg jit-load-cell
3 ds-reg cell-size jit-save-cell-update
] \ over define-sub-primitive
[
3 ds-reg cell-size neg 2 * jit-load-cell
3 ds-reg cell-size jit-save-cell-update
] \ pick define-sub-primitive
[
3 ds-reg 0 jit-load-cell
4 ds-reg cell-size neg jit-load-cell
4 ds-reg 0 jit-save-cell
3 ds-reg cell-size jit-save-cell-update
] \ dupd define-sub-primitive
[
3 ds-reg 0 jit-load-cell
4 ds-reg cell-size neg jit-load-cell
3 ds-reg cell-size neg jit-save-cell
4 ds-reg 0 jit-save-cell
] \ swap define-sub-primitive
[
3 ds-reg cell-size neg jit-load-cell
4 ds-reg cell-size neg 2 * jit-load-cell
3 ds-reg cell-size neg 2 * jit-save-cell
4 ds-reg cell-size neg jit-save-cell
] \ swapd define-sub-primitive
[
3 ds-reg 0 jit-load-cell
4 ds-reg cell-size neg jit-load-cell
5 ds-reg cell-size neg 2 * jit-load-cell
4 ds-reg cell-size neg 2 * jit-save-cell
3 ds-reg cell-size neg jit-save-cell
5 ds-reg 0 jit-save-cell
] \ rot define-sub-primitive
[
3 ds-reg 0 jit-load-cell
4 ds-reg cell-size neg jit-load-cell
5 ds-reg cell-size neg 2 * jit-load-cell
3 ds-reg cell-size neg 2 * jit-save-cell
5 ds-reg cell-size neg jit-save-cell
4 ds-reg 0 jit-save-cell
] \ -rot define-sub-primitive
[ jit->r ] \ load-local define-sub-primitive
! Comparisons
: jit-compare ( insn -- )
t jit-literal
3 jit-load-literal-arg
4 ds-reg 0 jit-load-cell
5 ds-reg cell-size neg jit-load-cell-update
0 5 4 jit-compare-cell
[ 0 8 ] dip execute( cr offset -- )
3 \ f type-number LI
3 ds-reg 0 jit-save-cell ;
: define-jit-compare ( insn word -- )
[ [ jit-compare ] curry ] dip define-sub-primitive ;
\ BEQ \ eq? define-jit-compare
\ BGE \ fixnum>= define-jit-compare
\ BLE \ fixnum<= define-jit-compare
\ BGT \ fixnum> define-jit-compare
\ BLT \ fixnum< define-jit-compare
! Math
[
3 ds-reg 0 jit-load-cell
ds-reg ds-reg cell-size SUBI
4 ds-reg 0 jit-load-cell
3 3 4 OR
3 3 tag-mask get ANDI.
4 \ f type-number LI
0 3 0 jit-compare-cell-imm
[ 0 swap BNE ] [ 4 1 tag-fixnum LI ] jit-conditional*
4 ds-reg 0 jit-save-cell
] \ both-fixnums? define-sub-primitive
: jit-math ( insn -- )
3 ds-reg 0 jit-load-cell
4 ds-reg cell-size neg jit-load-cell-update
[ 5 3 4 ] dip execute( dst src1 src2 -- )
5 ds-reg 0 jit-save-cell ;
[ \ ADD jit-math ] \ fixnum+fast define-sub-primitive
[ \ SUBF jit-math ] \ fixnum-fast define-sub-primitive
[
3 ds-reg 0 jit-load-cell
4 ds-reg cell-size neg jit-load-cell-update
4 4 jit-shift-tag-bits
5 3 4 jit-multiply-low
5 ds-reg 0 jit-save-cell
] \ fixnum*fast define-sub-primitive
[ \ AND jit-math ] \ fixnum-bitand define-sub-primitive
[ \ OR jit-math ] \ fixnum-bitor define-sub-primitive
[ \ XOR jit-math ] \ fixnum-bitxor define-sub-primitive
[
3 ds-reg 0 jit-load-cell
3 3 NOT
3 3 tag-mask get XORI
3 ds-reg 0 jit-save-cell
] \ fixnum-bitnot define-sub-primitive
[
3 ds-reg 0 jit-load-cell ! Load amount to shift
3 3 jit-shift-tag-bits ! Shift out tag bits
ds-reg ds-reg cell-size SUBI
4 ds-reg 0 jit-load-cell ! Load value to shift
5 4 3 jit-shift-left-logical ! Shift left
6 3 NEG ! Negate shift amount
7 4 6 jit-shift-right-algebraic ! Shift right
7 7 jit-mask-tag-bits ! Mask out tag bits
0 3 0 jit-compare-cell-imm
[ 0 swap BGT ] [ 5 7 MR ] jit-conditional*
5 ds-reg 0 jit-save-cell
] \ fixnum-shift-fast define-sub-primitive
[
3 ds-reg 0 jit-load-cell
ds-reg ds-reg cell-size SUBI
4 ds-reg 0 jit-load-cell
5 4 3 jit-divide
6 5 3 jit-multiply-low
7 4 6 SUB
7 ds-reg 0 jit-save-cell
] \ fixnum-mod define-sub-primitive
[
3 ds-reg 0 jit-load-cell
ds-reg ds-reg cell-size SUBI
4 ds-reg 0 jit-load-cell
5 4 3 jit-divide
5 5 tag-bits get jit-shift-left-logical-imm
5 ds-reg 0 jit-save-cell
] \ fixnum/i-fast define-sub-primitive
[
3 ds-reg 0 jit-load-cell
4 ds-reg cell-size neg jit-load-cell
5 4 3 jit-divide
6 5 3 jit-multiply-low
7 4 6 SUB
5 5 tag-bits get jit-shift-left-logical-imm
5 ds-reg cell-size neg jit-save-cell
7 ds-reg 0 jit-save-cell
] \ fixnum/mod-fast define-sub-primitive
[
3 ds-reg 0 jit-load-cell
3 3 jit-shift-fixnum-slot
3 rs-reg 3 jit-load-cell-x
3 ds-reg 0 jit-save-cell
] \ get-local define-sub-primitive
[
3 ds-reg 0 jit-load-cell
ds-reg ds-reg cell-size SUBI
3 3 jit-shift-fixnum-slot
rs-reg rs-reg 3 SUB
] \ drop-locals define-sub-primitive
! Overflowing fixnum arithmetic
:: jit-overflow ( insn func -- )
ds-reg ds-reg cell-size SUBI
jit-save-context
3 ds-reg 0 jit-load-cell
4 ds-reg cell-size jit-load-cell
0 0 LI
0 MTXER
6 4 3 insn call( d a s -- )
6 ds-reg 0 jit-save-cell
[ 0 swap BNS ]
[
5 vm-reg MR
func jit-call
]
jit-conditional* ;
[ [ ADDO. ] "overflow_fixnum_add" jit-overflow ] \ fixnum+ define-sub-primitive
[ [ SUBFO. ] "overflow_fixnum_subtract" jit-overflow ] \ fixnum- define-sub-primitive
[
ds-reg ds-reg cell-size SUBI
jit-save-context
3 ds-reg 0 jit-load-cell
3 3 jit-shift-tag-bits
4 ds-reg cell-size jit-load-cell
0 0 LI
0 MTXER
6 3 4 jit-multiply-low-ov-rc
6 ds-reg 0 jit-save-cell
[ 0 swap BNS ]
[
4 4 jit-shift-tag-bits
5 vm-reg MR
"overflow_fixnum_multiply" jit-call
]
jit-conditional*
] \ fixnum* define-sub-primitive
! Contexts
:: jit-switch-context ( reg -- )
7 0 LI
7 1 lr-save jit-save-cell
! Make the new context the current one
ctx-reg reg MR
ctx-reg vm-reg vm-context-offset jit-save-cell
! Load new stack pointer
1 ctx-reg context-callstack-top-offset jit-load-cell
! Load new ds, rs registers
jit-restore-context ;
: jit-pop-context-and-param ( -- )
3 ds-reg 0 jit-load-cell
4 alien-offset LI
3 3 4 jit-load-cell-x
4 ds-reg cell-size neg jit-load-cell
ds-reg ds-reg cell-size 2 * SUBI ;
: jit-push-param ( -- )
ds-reg ds-reg cell-size ADDI
4 ds-reg 0 jit-save-cell ;
: jit-set-context ( -- )
jit-pop-context-and-param
jit-save-context
3 jit-switch-context
jit-push-param ;
[ jit-set-context ] \ (set-context) define-sub-primitive
: jit-pop-quot-and-param ( -- )
3 ds-reg 0 jit-load-cell
4 ds-reg cell-size neg jit-load-cell
ds-reg ds-reg cell-size 2 * SUBI ;
: jit-start-context ( -- )
! Create the new context in return-reg. Have to save context
! twice, first before calling new_context() which may GC,
! and again after popping the two parameters from the stack.
jit-save-context
3 vm-reg MR
"new_context" jit-call
6 3 MR
jit-pop-quot-and-param
jit-save-context
6 jit-switch-context
jit-push-param
jit-jump-quot ;
[ jit-start-context ] \ (start-context) define-sub-primitive
: jit-delete-current-context ( -- )
jit-load-context
3 vm-reg MR
4 ctx-reg MR
"delete_context" jit-call ;
[
jit-delete-current-context
jit-set-context
] \ (set-context-and-delete) define-sub-primitive
: jit-start-context-and-delete ( -- )
jit-load-context
3 vm-reg MR
4 ctx-reg MR
"reset_context" jit-call
jit-pop-quot-and-param
ctx-reg jit-switch-context
jit-push-param
jit-jump-quot ;
[
jit-start-context-and-delete
] \ (start-context-and-delete) define-sub-primitive
[ "bootstrap.ppc" forget-vocab ] with-compilation-unit

1084
basis/cpu/ppc/ppc.factor Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
32-bit and 64-bit PowerPC compiler backends

View File

@ -228,7 +228,7 @@ M: x86.32 long-long-on-stack? t ;
M: x86.32 float-on-stack? t ;
M: x86.32 flatten-struct-type
call-next-method [ first t 2array ] map ;
call-next-method [ first t f 3array ] map ;
M: x86.32 struct-return-on-stack? os linux? not ;

View File

@ -29,12 +29,12 @@ M: x86.64 reserved-stack-space 0 ;
struct-types&offset split-struct [
[ c-type c-type-rep reg-class-of ] map
int-regs swap member? int-rep double-rep ?
f 2array
f f 3array
] map ;
M: x86.64 flatten-struct-type ( c-type -- seq )
dup heap-size 16 <=
[ flatten-small-struct ] [ call-next-method [ first t 2array ] map ] if ;
[ flatten-small-struct ] [ call-next-method [ first t f 3array ] map ] if ;
M: x86.64 return-struct-in-registers? ( c-type -- ? )
heap-size 2 cells <= ;

View File

@ -691,6 +691,10 @@ M:: x86 %save-context ( temp1 temp2 -- )
M: x86 value-struct? drop t ;
M: x86 long-long-odd-register? f ;
M: x86 float-right-align-on-stack? f ;
M: x86 immediate-arithmetic? ( n -- ? )
HEX: -80000000 HEX: 7fffffff between? ;

View File

@ -1,6 +1,7 @@
USING: accessors alien.c-types alien.syntax arrays assocs
USING: accessors alien alien.c-types alien.syntax arrays assocs
biassocs classes.struct combinators kernel literals math
math.bitwise math.floats.env math.floats.env.private system ;
math.bitwise math.floats.env math.floats.env.private system
cpu.ppc.assembler ;
IN: math.floats.env.ppc
STRUCT: ppc-fpu-env
@ -10,12 +11,41 @@ STRUCT: ppc-fpu-env
STRUCT: ppc-vmx-env
{ vscr uint } ;
! defined in the vm, cpu-ppc*.S
FUNCTION: void get_ppc_fpu_env ( ppc-fpu-env* env ) ;
FUNCTION: void set_ppc_fpu_env ( ppc-fpu-env* env ) ;
: get_ppc_fpu_env ( env -- )
void { void* } cdecl [
0 MFFS
0 3 0 STFD
] alien-assembly ;
FUNCTION: void get_ppc_vmx_env ( ppc-vmx-env* env ) ;
FUNCTION: void set_ppc_vmx_env ( ppc-vmx-env* env ) ;
: set_ppc_fpu_env ( env -- )
void { void* } cdecl [
0 3 0 LFD
HEX: ff 0 0 0 MTFSF
] alien-assembly ;
: get_ppc_vmx_env ( env -- )
void { void* } cdecl [
0 MFVSCR
4 1 16 SUBI
5 HEX: f LI
4 4 5 ANDC
0 0 4 STVXL
5 HEX: c LI
6 5 4 LWZX
6 3 0 STW
] alien-assembly ;
: set_ppc_vmx_env ( env -- )
void { void* } cdecl [
3 1 16 SUBI
5 HEX: f LI
4 4 5 ANDC
5 HEX: c LI
6 3 0 LWZ
6 5 4 STWX
0 0 4 LVXL
0 MTVSCR
] alien-assembly ;
: <ppc-fpu-env> ( -- ppc-fpu-env )
ppc-fpu-env (struct)
@ -32,7 +62,7 @@ M: ppc-vmx-env (set-fp-env-register)
set_ppc_vmx_env ;
M: ppc (fp-env-registers)
<ppc-fpu-env> <ppc-vmx-env> 2array ;
<ppc-fpu-env> 1array ;
CONSTANT: ppc-exception-flag-bits HEX: fff8,0700
CONSTANT: ppc-exception-flag>bit

View File

@ -282,6 +282,7 @@ M: object infer-call* \ call bad-macro-input ;
\ (code-blocks) { } { array } define-primitive \ (code-blocks) make-flushable
\ (dlopen) { byte-array } { dll } define-primitive
\ (dlsym) { byte-array object } { c-ptr } define-primitive
\ (dlsym-raw) { byte-array object } { c-ptr } define-primitive
\ (exists?) { string } { object } define-primitive
\ (exit) { integer } { } define-primitive
\ (format-float) { float byte-array } { byte-array } define-primitive \ (format-float) make-foldable

View File

@ -306,8 +306,8 @@ set_build_info() {
MAKE_IMAGE_TARGET=macosx-ppc
MAKE_TARGET=macosx-ppc
elif [[ $OS == linux && $ARCH == ppc ]] ; then
MAKE_IMAGE_TARGET=linux-ppc
MAKE_TARGET=linux-ppc
MAKE_IMAGE_TARGET=linux-ppc.32
MAKE_TARGET=linux-ppc-32
elif [[ $OS == winnt && $ARCH == x86 && $WORD == 64 ]] ; then
MAKE_IMAGE_TARGET=winnt-x86.64
MAKE_TARGET=winnt-x86-64

View File

@ -19,9 +19,11 @@ H{ } clone sub-primitives set
architecture get {
{ "winnt-x86.32" "x86/32/winnt" }
{ "unix-x86.32" "x86/32/unix" }
{ "unix-x86.32" "x86/32/unix" }
{ "winnt-x86.64" "x86/64/winnt" }
{ "unix-x86.64" "x86/64/unix" }
{ "unix-x86.64" "x86/64/unix" }
{ "linux-ppc.32" "ppc/32/linux" }
{ "linux-ppc.64" "ppc/64/linux" }
} ?at [ "Bad architecture: " prepend throw ] unless
"vocab:cpu/" "/bootstrap.factor" surround parse-file
@ -419,6 +421,7 @@ tuple
{ "set-alien-unsigned-cell" "alien.accessors" "primitive_set_alien_unsigned_cell" (( value c-ptr n -- )) }
{ "(dlopen)" "alien.libraries" "primitive_dlopen" (( path -- dll )) }
{ "(dlsym)" "alien.libraries" "primitive_dlsym" (( name dll -- alien )) }
{ "(dlsym-raw)" "alien.libraries" "primitive_dlsym_raw" (( name dll -- alien )) }
{ "dlclose" "alien.libraries" "primitive_dlclose" (( dll -- )) }
{ "dll-valid?" "alien.libraries" "primitive_dll_validp" (( dll -- ? )) }
{ "current-callback" "alien.private" "primitive_current_callback" (( -- n )) }

View File

@ -4,9 +4,10 @@ USING: kernel kernel.private sequences math namespaces
init splitting assocs system.private layouts words ;
IN: system
SINGLETONS: x86.32 x86.64 arm ppc ;
SINGLETONS: x86.32 x86.64 arm ppc.32 ppc.64 ;
UNION: x86 x86.32 x86.64 ;
UNION: ppc ppc.32 ppc.64 ;
: cpu ( -- class ) \ cpu get-global ; foldable
@ -33,7 +34,8 @@ UNION: unix bsd solaris linux haiku ;
{ "x86.32" x86.32 }
{ "x86.64" x86.64 }
{ "arm" arm }
{ "ppc" ppc }
{ "ppc.32" ppc.32 }
{ "ppc.64" ppc.64 }
} at ;
: string>os ( str -- class )

View File

@ -1,128 +0,0 @@
USING: cpu.ppc.assembler tools.test arrays kernel namespaces
make vocabs sequences byte-arrays.hex ;
FROM: cpu.ppc.assembler => B ;
IN: cpu.ppc.assembler.tests
: test-assembler ( expected quot -- )
[ 1array ] [ [ B{ } make ] curry ] bi* unit-test ;
HEX{ 38 22 00 03 } [ 1 2 3 ADDI ] test-assembler
HEX{ 3c 22 00 03 } [ 1 2 3 ADDIS ] test-assembler
HEX{ 30 22 00 03 } [ 1 2 3 ADDIC ] test-assembler
HEX{ 34 22 00 03 } [ 1 2 3 ADDIC. ] test-assembler
HEX{ 38 40 00 01 } [ 1 2 LI ] test-assembler
HEX{ 3c 40 00 01 } [ 1 2 LIS ] test-assembler
HEX{ 38 22 ff fd } [ 1 2 3 SUBI ] test-assembler
HEX{ 1c 22 00 03 } [ 1 2 3 MULI ] test-assembler
HEX{ 7c 22 1a 14 } [ 1 2 3 ADD ] test-assembler
HEX{ 7c 22 1a 15 } [ 1 2 3 ADD. ] test-assembler
HEX{ 7c 22 1e 14 } [ 1 2 3 ADDO ] test-assembler
HEX{ 7c 22 1e 15 } [ 1 2 3 ADDO. ] test-assembler
HEX{ 7c 22 18 14 } [ 1 2 3 ADDC ] test-assembler
HEX{ 7c 22 18 15 } [ 1 2 3 ADDC. ] test-assembler
HEX{ 7c 22 1e 14 } [ 1 2 3 ADDO ] test-assembler
HEX{ 7c 22 1c 15 } [ 1 2 3 ADDCO. ] test-assembler
HEX{ 7c 22 19 14 } [ 1 2 3 ADDE ] test-assembler
HEX{ 7c 41 18 38 } [ 1 2 3 AND ] test-assembler
HEX{ 7c 41 18 39 } [ 1 2 3 AND. ] test-assembler
HEX{ 7c 22 1b d6 } [ 1 2 3 DIVW ] test-assembler
HEX{ 7c 22 1b 96 } [ 1 2 3 DIVWU ] test-assembler
HEX{ 7c 41 1a 38 } [ 1 2 3 EQV ] test-assembler
HEX{ 7c 41 1b b8 } [ 1 2 3 NAND ] test-assembler
HEX{ 7c 41 18 f8 } [ 1 2 3 NOR ] test-assembler
HEX{ 7c 41 10 f8 } [ 1 2 NOT ] test-assembler
HEX{ 60 41 00 03 } [ 1 2 3 ORI ] test-assembler
HEX{ 64 41 00 03 } [ 1 2 3 ORIS ] test-assembler
HEX{ 7c 41 1b 78 } [ 1 2 3 OR ] test-assembler
HEX{ 7c 41 13 78 } [ 1 2 MR ] test-assembler
HEX{ 7c 22 18 96 } [ 1 2 3 MULHW ] test-assembler
HEX{ 1c 22 00 03 } [ 1 2 3 MULLI ] test-assembler
HEX{ 7c 22 18 16 } [ 1 2 3 MULHWU ] test-assembler
HEX{ 7c 22 19 d6 } [ 1 2 3 MULLW ] test-assembler
HEX{ 7c 41 18 30 } [ 1 2 3 SLW ] test-assembler
HEX{ 7c 41 1e 30 } [ 1 2 3 SRAW ] test-assembler
HEX{ 7c 41 1c 30 } [ 1 2 3 SRW ] test-assembler
HEX{ 7c 41 1e 70 } [ 1 2 3 SRAWI ] test-assembler
HEX{ 7c 22 18 50 } [ 1 2 3 SUBF ] test-assembler
HEX{ 7c 22 18 10 } [ 1 2 3 SUBFC ] test-assembler
HEX{ 7c 22 19 10 } [ 1 2 3 SUBFE ] test-assembler
HEX{ 7c 41 07 74 } [ 1 2 EXTSB ] test-assembler
HEX{ 68 41 00 03 } [ 1 2 3 XORI ] test-assembler
HEX{ 7c 41 1a 78 } [ 1 2 3 XOR ] test-assembler
HEX{ 7c 22 00 d0 } [ 1 2 NEG ] test-assembler
HEX{ 2c 22 00 03 } [ 1 2 3 CMPI ] test-assembler
HEX{ 28 22 00 03 } [ 1 2 3 CMPLI ] test-assembler
HEX{ 7c 41 18 00 } [ 1 2 3 CMP ] test-assembler
HEX{ 54 22 19 0a } [ 1 2 3 4 5 RLWINM ] test-assembler
HEX{ 54 22 18 38 } [ 1 2 3 SLWI ] test-assembler
HEX{ 54 22 e8 fe } [ 1 2 3 SRWI ] test-assembler
HEX{ 88 22 00 03 } [ 1 2 3 LBZ ] test-assembler
HEX{ 8c 22 00 03 } [ 1 2 3 LBZU ] test-assembler
HEX{ a8 22 00 03 } [ 1 2 3 LHA ] test-assembler
HEX{ ac 22 00 03 } [ 1 2 3 LHAU ] test-assembler
HEX{ a0 22 00 03 } [ 1 2 3 LHZ ] test-assembler
HEX{ a4 22 00 03 } [ 1 2 3 LHZU ] test-assembler
HEX{ 80 22 00 03 } [ 1 2 3 LWZ ] test-assembler
HEX{ 84 22 00 03 } [ 1 2 3 LWZU ] test-assembler
HEX{ 7c 41 18 ae } [ 1 2 3 LBZX ] test-assembler
HEX{ 7c 41 18 ee } [ 1 2 3 LBZUX ] test-assembler
HEX{ 7c 41 1a ae } [ 1 2 3 LHAX ] test-assembler
HEX{ 7c 41 1a ee } [ 1 2 3 LHAUX ] test-assembler
HEX{ 7c 41 1a 2e } [ 1 2 3 LHZX ] test-assembler
HEX{ 7c 41 1a 6e } [ 1 2 3 LHZUX ] test-assembler
HEX{ 7c 41 18 2e } [ 1 2 3 LWZX ] test-assembler
HEX{ 7c 41 18 6e } [ 1 2 3 LWZUX ] test-assembler
HEX{ 7c 41 1c 2e } [ 1 2 3 LFSX ] test-assembler
HEX{ 7c 41 1c 6e } [ 1 2 3 LFSUX ] test-assembler
HEX{ 7c 41 1c ae } [ 1 2 3 LFDX ] test-assembler
HEX{ 7c 41 1c ee } [ 1 2 3 LFDUX ] test-assembler
HEX{ 7c 41 1d 2e } [ 1 2 3 STFSX ] test-assembler
HEX{ 7c 41 1d 6e } [ 1 2 3 STFSUX ] test-assembler
HEX{ 7c 41 1d ae } [ 1 2 3 STFDX ] test-assembler
HEX{ 7c 41 1d ee } [ 1 2 3 STFDUX ] test-assembler
HEX{ 48 00 00 01 } [ 1 B ] test-assembler
HEX{ 48 00 00 01 } [ 1 BL ] test-assembler
HEX{ 41 80 00 04 } [ 1 BLT ] test-assembler
HEX{ 41 81 00 04 } [ 1 BGT ] test-assembler
HEX{ 40 81 00 04 } [ 1 BLE ] test-assembler
HEX{ 40 80 00 04 } [ 1 BGE ] test-assembler
HEX{ 41 80 00 04 } [ 1 BLT ] test-assembler
HEX{ 40 82 00 04 } [ 1 BNE ] test-assembler
HEX{ 41 82 00 04 } [ 1 BEQ ] test-assembler
HEX{ 41 83 00 04 } [ 1 BO ] test-assembler
HEX{ 40 83 00 04 } [ 1 BNO ] test-assembler
HEX{ 4c 20 00 20 } [ 1 BCLR ] test-assembler
HEX{ 4e 80 00 20 } [ BLR ] test-assembler
HEX{ 4e 80 00 21 } [ BLRL ] test-assembler
HEX{ 4c 20 04 20 } [ 1 BCCTR ] test-assembler
HEX{ 4e 80 04 20 } [ BCTR ] test-assembler
HEX{ 7c 61 02 a6 } [ 3 MFXER ] test-assembler
HEX{ 7c 68 02 a6 } [ 3 MFLR ] test-assembler
HEX{ 7c 69 02 a6 } [ 3 MFCTR ] test-assembler
HEX{ 7c 61 03 a6 } [ 3 MTXER ] test-assembler
HEX{ 7c 68 03 a6 } [ 3 MTLR ] test-assembler
HEX{ 7c 69 03 a6 } [ 3 MTCTR ] test-assembler
HEX{ 7c 61 02 a6 } [ 3 MFXER ] test-assembler
HEX{ 7c 68 02 a6 } [ 3 MFLR ] test-assembler
HEX{ c0 22 00 03 } [ 1 2 3 LFS ] test-assembler
HEX{ c4 22 00 03 } [ 1 2 3 LFSU ] test-assembler
HEX{ c8 22 00 03 } [ 1 2 3 LFD ] test-assembler
HEX{ cc 22 00 03 } [ 1 2 3 LFDU ] test-assembler
HEX{ d0 22 00 03 } [ 1 2 3 STFS ] test-assembler
HEX{ d4 22 00 03 } [ 1 2 3 STFSU ] test-assembler
HEX{ d8 22 00 03 } [ 1 2 3 STFD ] test-assembler
HEX{ dc 22 00 03 } [ 1 2 3 STFDU ] test-assembler
HEX{ fc 20 10 90 } [ 1 2 FMR ] test-assembler
HEX{ fc 40 08 90 } [ 2 1 FMR ] test-assembler
HEX{ fc 20 10 91 } [ 1 2 FMR. ] test-assembler
HEX{ fc 40 08 91 } [ 2 1 FMR. ] test-assembler
HEX{ fc 20 10 1e } [ 1 2 FCTIWZ ] test-assembler
HEX{ fc 22 18 2a } [ 1 2 3 FADD ] test-assembler
HEX{ fc 22 18 2b } [ 1 2 3 FADD. ] test-assembler
HEX{ fc 22 18 28 } [ 1 2 3 FSUB ] test-assembler
HEX{ fc 22 00 f2 } [ 1 2 3 FMUL ] test-assembler
HEX{ fc 22 18 24 } [ 1 2 3 FDIV ] test-assembler
HEX{ fc 20 10 2c } [ 1 2 FSQRT ] test-assembler
HEX{ fc 41 18 00 } [ 1 2 3 FCMPU ] test-assembler
HEX{ fc 41 18 40 } [ 1 2 3 FCMPO ] test-assembler
HEX{ 3c 60 12 34 60 63 56 78 } [ HEX: 12345678 3 LOAD ] test-assembler

View File

@ -1,428 +0,0 @@
! Copyright (C) 2005, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel namespaces words math math.order locals
cpu.ppc.assembler.backend ;
IN: cpu.ppc.assembler
! See the Motorola or IBM documentation for details. The opcode
! names are standard, and the operand order is the same as in
! the docs, except a few differences, namely, in IBM/Motorola
! assembler syntax, loads and stores are written like:
!
! stw r14,10(r15)
!
! In Factor, we write:
!
! 14 15 10 STW
! D-form
D: ADDI 14
D: ADDIC 12
D: ADDIC. 13
D: ADDIS 15
D: CMPI 11
D: CMPLI 10
D: LBZ 34
D: LBZU 35
D: LFD 50
D: LFDU 51
D: LFS 48
D: LFSU 49
D: LHA 42
D: LHAU 43
D: LHZ 40
D: LHZU 41
D: LWZ 32
D: LWZU 33
D: MULI 7
D: MULLI 7
D: STB 38
D: STBU 39
D: STFD 54
D: STFDU 55
D: STFS 52
D: STFSU 53
D: STH 44
D: STHU 45
D: STW 36
D: STWU 37
! SD-form
SD: ANDI 28
SD: ANDIS 29
SD: ORI 24
SD: ORIS 25
SD: XORI 26
SD: XORIS 27
! X-form
X: AND 0 28 31
X: AND. 1 28 31
X: CMP 0 0 31
X: CMPL 0 32 31
X: EQV 0 284 31
X: EQV. 1 284 31
X: FCMPO 0 32 63
X: FCMPU 0 0 63
X: LBZUX 0 119 31
X: LBZX 0 87 31
X: LFDUX 0 631 31
X: LFDX 0 599 31
X: LFSUX 0 567 31
X: LFSX 0 535 31
X: LHAUX 0 375 31
X: LHAX 0 343 31
X: LHZUX 0 311 31
X: LHZX 0 279 31
X: LWZUX 0 55 31
X: LWZX 0 23 31
X: NAND 0 476 31
X: NAND. 1 476 31
X: NOR 0 124 31
X: NOR. 1 124 31
X: OR 0 444 31
X: OR. 1 444 31
X: ORC 0 412 31
X: ORC. 1 412 31
X: SLW 0 24 31
X: SLW. 1 24 31
X: SRAW 0 792 31
X: SRAW. 1 792 31
X: SRAWI 0 824 31
X: SRW 0 536 31
X: SRW. 1 536 31
X: STBUX 0 247 31
X: STBX 0 215 31
X: STFDUX 0 759 31
X: STFDX 0 727 31
X: STFSUX 0 695 31
X: STFSX 0 663 31
X: STHUX 0 439 31
X: STHX 0 407 31
X: STWUX 0 183 31
X: STWX 0 151 31
X: XOR 0 316 31
X: XOR. 1 316 31
X1: EXTSB 0 954 31
X1: EXTSB. 1 954 31
: FRSP ( a s -- ) [ 0 ] 2dip 0 12 63 x-insn ;
: FRSP. ( a s -- ) [ 0 ] 2dip 1 12 63 x-insn ;
: FMR ( a s -- ) [ 0 ] 2dip 0 72 63 x-insn ;
: FMR. ( a s -- ) [ 0 ] 2dip 1 72 63 x-insn ;
: FCTIWZ ( a s -- ) [ 0 ] 2dip 0 15 63 x-insn ;
: FCTIWZ. ( a s -- ) [ 0 ] 2dip 1 15 63 x-insn ;
! XO-form
XO: ADD 0 0 266 31
XO: ADD. 0 1 266 31
XO: ADDC 0 0 10 31
XO: ADDC. 0 1 10 31
XO: ADDCO 1 0 10 31
XO: ADDCO. 1 1 10 31
XO: ADDE 0 0 138 31
XO: ADDE. 0 1 138 31
XO: ADDEO 1 0 138 31
XO: ADDEO. 1 1 138 31
XO: ADDO 1 0 266 31
XO: ADDO. 1 1 266 31
XO: DIVW 0 0 491 31
XO: DIVW. 0 1 491 31
XO: DIVWO 1 0 491 31
XO: DIVWO. 1 1 491 31
XO: DIVWU 0 0 459 31
XO: DIVWU. 0 1 459 31
XO: DIVWUO 1 0 459 31
XO: DIVWUO. 1 1 459 31
XO: MULHW 0 0 75 31
XO: MULHW. 0 1 75 31
XO: MULHWU 0 0 11 31
XO: MULHWU. 0 1 11 31
XO: MULLW 0 0 235 31
XO: MULLW. 0 1 235 31
XO: MULLWO 1 0 235 31
XO: MULLWO. 1 1 235 31
XO: SUBF 0 0 40 31
XO: SUBF. 0 1 40 31
XO: SUBFC 0 0 8 31
XO: SUBFC. 0 1 8 31
XO: SUBFCO 1 0 8 31
XO: SUBFCO. 1 1 8 31
XO: SUBFE 0 0 136 31
XO: SUBFE. 0 1 136 31
XO: SUBFEO 1 0 136 31
XO: SUBFEO. 1 1 136 31
XO: SUBFO 1 0 40 31
XO: SUBFO. 1 1 40 31
XO1: NEG 0 0 104 31
XO1: NEG. 0 1 104 31
XO1: NEGO 1 0 104 31
XO1: NEGO. 1 1 104 31
! A-form
: RLWINM ( d a b c xo -- ) 0 21 a-insn ;
: RLWINM. ( d a b c xo -- ) 1 21 a-insn ;
: FADD ( d a b -- ) 0 21 0 63 a-insn ;
: FADD. ( d a b -- ) 0 21 1 63 a-insn ;
: FSUB ( d a b -- ) 0 20 0 63 a-insn ;
: FSUB. ( d a b -- ) 0 20 1 63 a-insn ;
: FMUL ( d a c -- ) 0 swap 25 0 63 a-insn ;
: FMUL. ( d a c -- ) 0 swap 25 1 63 a-insn ;
: FDIV ( d a b -- ) 0 18 0 63 a-insn ;
: FDIV. ( d a b -- ) 0 18 1 63 a-insn ;
: FSQRT ( d b -- ) 0 swap 0 22 0 63 a-insn ;
: FSQRT. ( d b -- ) 0 swap 0 22 1 63 a-insn ;
! Branches
: B ( dest -- ) 0 0 (B) ;
: BL ( dest -- ) 0 1 (B) ;
BC: LT 12 0
BC: GE 4 0
BC: GT 12 1
BC: LE 4 1
BC: EQ 12 2
BC: NE 4 2
BC: O 12 3
BC: NO 4 3
B: CLR 0 8 0 0 19
B: CLRL 0 8 0 1 19
B: CCTR 0 264 0 0 19
: BLR ( -- ) 20 BCLR ;
: BLRL ( -- ) 20 BCLRL ;
: BCTR ( -- ) 20 BCCTR ;
! Special registers
MFSPR: XER 1
MFSPR: LR 8
MFSPR: CTR 9
MTSPR: XER 1
MTSPR: LR 8
MTSPR: CTR 9
! Pseudo-instructions
: LI ( value dst -- ) swap [ 0 ] dip ADDI ; inline
: SUBI ( dst src1 src2 -- ) neg ADDI ; inline
: LIS ( value dst -- ) swap [ 0 ] dip ADDIS ; inline
: SUBIC ( dst src1 src2 -- ) neg ADDIC ; inline
: SUBIC. ( dst src1 src2 -- ) neg ADDIC. ; inline
: NOT ( dst src -- ) dup NOR ; inline
: NOT. ( dst src -- ) dup NOR. ; inline
: MR ( dst src -- ) dup OR ; inline
: MR. ( dst src -- ) dup OR. ; inline
: (SLWI) ( d a b -- d a b x y ) 0 31 pick - ; inline
: SLWI ( d a b -- ) (SLWI) RLWINM ;
: SLWI. ( d a b -- ) (SLWI) RLWINM. ;
: (SRWI) ( d a b -- d a b x y ) 32 over - swap 31 ; inline
: SRWI ( d a b -- ) (SRWI) RLWINM ;
: SRWI. ( d a b -- ) (SRWI) RLWINM. ;
:: LOAD32 ( n r -- )
n -16 shift HEX: ffff bitand r LIS
r r n HEX: ffff bitand ORI ;
: immediate? ( n -- ? ) HEX: -8000 HEX: 7fff between? ;
: LOAD ( n r -- ) over immediate? [ LI ] [ LOAD32 ] if ;
! Altivec/VMX instructions
VA: VMHADDSHS 32 4
VA: VMHRADDSHS 33 4
VA: VMLADDUHM 34 4
VA: VMSUMUBM 36 4
VA: VMSUMMBM 37 4
VA: VMSUMUHM 38 4
VA: VMSUMUHS 39 4
VA: VMSUMSHM 40 4
VA: VMSUMSHS 41 4
VA: VSEL 42 4
VA: VPERM 43 4
VA: VSLDOI 44 4
VA: VMADDFP 46 4
VA: VNMSUBFP 47 4
VX: VADDUBM 0 4
VX: VADDUHM 64 4
VX: VADDUWM 128 4
VX: VADDCUW 384 4
VX: VADDUBS 512 4
VX: VADDUHS 576 4
VX: VADDUWS 640 4
VX: VADDSBS 768 4
VX: VADDSHS 832 4
VX: VADDSWS 896 4
VX: VSUBUBM 1024 4
VX: VSUBUHM 1088 4
VX: VSUBUWM 1152 4
VX: VSUBCUW 1408 4
VX: VSUBUBS 1536 4
VX: VSUBUHS 1600 4
VX: VSUBUWS 1664 4
VX: VSUBSBS 1792 4
VX: VSUBSHS 1856 4
VX: VSUBSWS 1920 4
VX: VMAXUB 2 4
VX: VMAXUH 66 4
VX: VMAXUW 130 4
VX: VMAXSB 258 4
VX: VMAXSH 322 4
VX: VMAXSW 386 4
VX: VMINUB 514 4
VX: VMINUH 578 4
VX: VMINUW 642 4
VX: VMINSB 770 4
VX: VMINSH 834 4
VX: VMINSW 898 4
VX: VAVGUB 1026 4
VX: VAVGUH 1090 4
VX: VAVGUW 1154 4
VX: VAVGSB 1282 4
VX: VAVGSH 1346 4
VX: VAVGSW 1410 4
VX: VRLB 4 4
VX: VRLH 68 4
VX: VRLW 132 4
VX: VSLB 260 4
VX: VSLH 324 4
VX: VSLW 388 4
VX: VSL 452 4
VX: VSRB 516 4
VX: VSRH 580 4
VX: VSRW 644 4
VX: VSR 708 4
VX: VSRAB 772 4
VX: VSRAH 836 4
VX: VSRAW 900 4
VX: VAND 1028 4
VX: VANDC 1092 4
VX: VOR 1156 4
VX: VNOR 1284 4
VX: VXOR 1220 4
VXD: MFVSCR 1540 4
VXB: MTVSCR 1604 4
VX: VMULOUB 8 4
VX: VMULOUH 72 4
VX: VMULOSB 264 4
VX: VMULOSH 328 4
VX: VMULEUB 520 4
VX: VMULEUH 584 4
VX: VMULESB 776 4
VX: VMULESH 840 4
VX: VSUM4UBS 1544 4
VX: VSUM4SBS 1800 4
VX: VSUM4SHS 1608 4
VX: VSUM2SWS 1672 4
VX: VSUMSWS 1928 4
VX: VADDFP 10 4
VX: VSUBFP 74 4
VXDB: VREFP 266 4
VXDB: VRSQRTEFP 330 4
VXDB: VEXPTEFP 394 4
VXDB: VLOGEFP 458 4
VXDB: VRFIN 522 4
VXDB: VRFIZ 586 4
VXDB: VRFIP 650 4
VXDB: VRFIM 714 4
VX: VCFUX 778 4
VX: VCFSX 842 4
VX: VCTUXS 906 4
VX: VCTSXS 970 4
VX: VMAXFP 1034 4
VX: VMINFP 1098 4
VX: VMRGHB 12 4
VX: VMRGHH 76 4
VX: VMRGHW 140 4
VX: VMRGLB 268 4
VX: VMRGLH 332 4
VX: VMRGLW 396 4
VX: VSPLTB 524 4
VX: VSPLTH 588 4
VX: VSPLTW 652 4
VXA: VSPLTISB 780 4
VXA: VSPLTISH 844 4
VXA: VSPLTISW 908 4
VX: VSLO 1036 4
VX: VSRO 1100 4
VX: VPKUHUM 14 4
VX: VPKUWUM 78 4
VX: VPKUHUS 142 4
VX: VPKUWUS 206 4
VX: VPKSHUS 270 4
VX: VPKSWUS 334 4
VX: VPKSHSS 398 4
VX: VPKSWSS 462 4
VX: VPKPX 782 4
VXDB: VUPKHSB 526 4
VXDB: VUPKHSH 590 4
VXDB: VUPKLSB 654 4
VXDB: VUPKLSH 718 4
VXDB: VUPKHPX 846 4
VXDB: VUPKLPX 974 4
: -T ( strm a b -- strm-t a b ) [ 16 bitor ] 2dip ;
XD: DST 0 342 31
: DSTT ( strm a b -- ) -T DST ;
XD: DSTST 0 374 31
: DSTSTT ( strm a b -- ) -T DSTST ;
XD: (DSS) 0 822 31
: DSS ( strm -- ) 0 0 (DSS) ;
: DSSALL ( -- ) 16 0 0 (DSS) ;
XD: LVEBX 0 7 31
XD: LVEHX 0 39 31
XD: LVEWX 0 71 31
XD: LVSL 0 6 31
XD: LVSR 0 38 31
XD: LVX 0 103 31
XD: LVXL 0 359 31
XD: STVEBX 0 135 31
XD: STVEHX 0 167 31
XD: STVEWX 0 199 31
XD: STVX 0 231 31
XD: STVXL 0 487 31
VXR: VCMPBFP 0 966 4
VXR: VCMPEQFP 0 198 4
VXR: VCMPEQUB 0 6 4
VXR: VCMPEQUH 0 70 4
VXR: VCMPEQUW 0 134 4
VXR: VCMPGEFP 0 454 4
VXR: VCMPGTFP 0 710 4
VXR: VCMPGTSB 0 774 4
VXR: VCMPGTSH 0 838 4
VXR: VCMPGTSW 0 902 4
VXR: VCMPGTUB 0 518 4
VXR: VCMPGTUH 0 582 4
VXR: VCMPGTUW 0 646 4
VXR: VCMPBFP. 1 966 4
VXR: VCMPEQFP. 1 198 4
VXR: VCMPEQUB. 1 6 4
VXR: VCMPEQUH. 1 70 4
VXR: VCMPEQUW. 1 134 4
VXR: VCMPGEFP. 1 454 4
VXR: VCMPGTFP. 1 710 4
VXR: VCMPGTSB. 1 774 4
VXR: VCMPGTSH. 1 838 4
VXR: VCMPGTSW. 1 902 4
VXR: VCMPGTUB. 1 518 4
VXR: VCMPGTUH. 1 582 4
VXR: VCMPGTUW. 1 646 4

View File

@ -1 +0,0 @@
Slava Pestov

View File

@ -1,132 +0,0 @@
! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel namespaces make sequences words math
math.bitwise io.binary parser lexer fry ;
IN: cpu.ppc.assembler.backend
: insn ( operand opcode -- ) { 26 0 } bitfield 4 >be % ;
: a-insn ( d a b c xo rc opcode -- )
[ { 0 1 6 11 16 21 } bitfield ] dip insn ;
: b-insn ( bo bi bd aa lk opcode -- )
[ { 0 1 2 16 21 } bitfield ] dip insn ;
: s>u16 ( s -- u ) HEX: ffff bitand ;
: d-insn ( d a simm opcode -- )
[ s>u16 { 0 16 21 } bitfield ] dip insn ;
: define-d-insn ( word opcode -- )
[ d-insn ] curry (( d a simm -- )) define-declared ;
SYNTAX: D: CREATE scan-word define-d-insn ;
: sd-insn ( d a simm opcode -- )
[ s>u16 { 0 21 16 } bitfield ] dip insn ;
: define-sd-insn ( word opcode -- )
[ sd-insn ] curry (( d a simm -- )) define-declared ;
SYNTAX: SD: CREATE scan-word define-sd-insn ;
: i-insn ( li aa lk opcode -- )
[ { 0 1 0 } bitfield ] dip insn ;
: x-insn ( a s b rc xo opcode -- )
[ { 1 0 11 21 16 } bitfield ] dip insn ;
: xd-insn ( d a b rc xo opcode -- )
[ { 1 0 11 16 21 } bitfield ] dip insn ;
: (X) ( -- word quot )
CREATE scan-word scan-word scan-word [ x-insn ] 3curry ;
: (XD) ( -- word quot )
CREATE scan-word scan-word scan-word [ xd-insn ] 3curry ;
SYNTAX: X: (X) (( a s b -- )) define-declared ;
SYNTAX: XD: (XD) (( d a b -- )) define-declared ;
: (1) ( quot -- quot' ) [ 0 ] prepose ;
SYNTAX: X1: (X) (1) (( a s -- )) define-declared ;
: xfx-insn ( d spr xo opcode -- )
[ { 1 11 21 } bitfield ] dip insn ;
: CREATE-MF ( -- word ) scan "MF" prepend create-in ;
SYNTAX: MFSPR:
CREATE-MF scan-word 5 shift [ 339 31 xfx-insn ] curry
(( d -- )) define-declared ;
: CREATE-MT ( -- word ) scan "MT" prepend create-in ;
SYNTAX: MTSPR:
CREATE-MT scan-word 5 shift [ 467 31 xfx-insn ] curry
(( d -- )) define-declared ;
: xo-insn ( d a b oe rc xo opcode -- )
[ { 1 0 10 11 16 21 } bitfield ] dip insn ;
: (XO) ( -- word quot )
CREATE scan-word scan-word scan-word scan-word
[ xo-insn ] 2curry 2curry ;
SYNTAX: XO: (XO) (( d a b -- )) define-declared ;
SYNTAX: XO1: (XO) (1) (( d a -- )) define-declared ;
GENERIC# (B) 2 ( dest aa lk -- )
M: integer (B) 18 i-insn ;
GENERIC: BC ( a b c -- )
M: integer BC 0 0 16 b-insn ;
: CREATE-B ( -- word ) scan "B" prepend create-in ;
SYNTAX: BC:
CREATE-B scan-word scan-word
'[ [ _ _ ] dip BC ] (( c -- )) define-declared ;
SYNTAX: B:
CREATE-B scan-word scan-word scan-word scan-word scan-word
'[ _ _ _ _ _ b-insn ] (( bo -- )) define-declared ;
: va-insn ( d a b c xo opcode -- )
[ { 0 6 11 16 21 } bitfield ] dip insn ;
: (VA) ( -- word quot )
CREATE scan-word scan-word [ va-insn ] 2curry ;
SYNTAX: VA: (VA) (( d a b c -- )) define-declared ;
: vx-insn ( d a b xo opcode -- )
[ { 0 11 16 21 } bitfield ] dip insn ;
: (VX) ( -- word quot )
CREATE scan-word scan-word [ vx-insn ] 2curry ;
: (VXD) ( -- word quot )
CREATE scan-word scan-word '[ 0 0 _ _ vx-insn ] ;
: (VXA) ( -- word quot )
CREATE scan-word scan-word '[ [ 0 ] dip 0 _ _ vx-insn ] ;
: (VXB) ( -- word quot )
CREATE scan-word scan-word '[ [ 0 0 ] dip _ _ vx-insn ] ;
: (VXDB) ( -- word quot )
CREATE scan-word scan-word '[ [ 0 ] dip _ _ vx-insn ] ;
SYNTAX: VX: (VX) (( d a b -- )) define-declared ;
SYNTAX: VXD: (VXD) (( d -- )) define-declared ;
SYNTAX: VXA: (VXA) (( a -- )) define-declared ;
SYNTAX: VXB: (VXB) (( b -- )) define-declared ;
SYNTAX: VXDB: (VXDB) (( d b -- )) define-declared ;
: vxr-insn ( d a b rc xo opcode -- )
[ { 0 10 11 16 21 } bitfield ] dip insn ;
: (VXR) ( -- word quot )
CREATE scan-word scan-word scan-word [ vxr-insn ] 3curry ;
SYNTAX: VXR: (VXR) (( d a b -- )) define-declared ;

View File

@ -1 +0,0 @@
PowerPC assembler

View File

@ -1 +0,0 @@
Slava Pestov

View File

@ -1,839 +0,0 @@
! Copyright (C) 2007, 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: bootstrap.image.private kernel kernel.private namespaces
system cpu.ppc.assembler compiler.units compiler.constants math
math.private math.ranges layouts words vocabs slots.private
locals locals.backend generic.single.private fry sequences
threads.private strings.private ;
FROM: cpu.ppc.assembler => B ;
IN: bootstrap.ppc
4 \ cell set
big-endian on
CONSTANT: ds-reg 13
CONSTANT: rs-reg 14
CONSTANT: vm-reg 15
CONSTANT: ctx-reg 16
CONSTANT: nv-reg 17
: jit-call ( string -- )
0 2 LOAD32 rc-absolute-ppc-2/2 jit-dlsym
2 MTLR
BLRL ;
: jit-call-quot ( -- )
4 3 quot-entry-point-offset LWZ
4 MTLR
BLRL ;
: jit-jump-quot ( -- )
4 3 quot-entry-point-offset LWZ
4 MTCTR
BCTR ;
: factor-area-size ( -- n ) 16 ;
: stack-frame ( -- n )
reserved-size
factor-area-size +
16 align ;
: next-save ( -- n ) stack-frame 4 - ;
: xt-save ( -- n ) stack-frame 8 - ;
: param-size ( -- n ) 32 ;
: save-at ( m -- n ) reserved-size + param-size + ;
: save-int ( register offset -- ) [ 1 ] dip save-at STW ;
: restore-int ( register offset -- ) [ 1 ] dip save-at LWZ ;
: save-fp ( register offset -- ) [ 1 ] dip save-at STFD ;
: restore-fp ( register offset -- ) [ 1 ] dip save-at LFD ;
: save-vec ( register offset -- ) save-at 2 LI 2 1 STVXL ;
: restore-vec ( register offset -- ) save-at 2 LI 2 1 LVXL ;
: nv-int-regs ( -- seq ) 13 31 [a,b] ;
: nv-fp-regs ( -- seq ) 14 31 [a,b] ;
: nv-vec-regs ( -- seq ) 20 31 [a,b] ;
: saved-int-regs-size ( -- n ) 96 ;
: saved-fp-regs-size ( -- n ) 144 ;
: saved-vec-regs-size ( -- n ) 208 ;
: callback-frame-size ( -- n )
reserved-size
param-size +
saved-int-regs-size +
saved-fp-regs-size +
saved-vec-regs-size +
4 +
16 align ;
: old-context-save-offset ( -- n )
432 save-at ;
[
! Save old stack pointer
11 1 MR
! Create stack frame
0 MFLR
1 1 callback-frame-size SUBI
0 1 callback-frame-size lr-save + STW
! Save all non-volatile registers
nv-int-regs [ 4 * save-int ] each-index
nv-fp-regs [ 8 * 80 + save-fp ] each-index
nv-vec-regs [ 16 * 224 + save-vec ] each-index
! Stick old stack pointer in a non-volatile register so that
! callbacks can access their arguments
nv-reg 11 MR
! Load VM into vm-reg
0 vm-reg LOAD32 rc-absolute-ppc-2/2 rt-vm jit-rel
! Save old context
2 vm-reg vm-context-offset LWZ
2 1 old-context-save-offset STW
! Switch over to the spare context
2 vm-reg vm-spare-context-offset LWZ
2 vm-reg vm-context-offset STW
! Save C callstack pointer
1 2 context-callstack-save-offset STW
! Load Factor callstack pointer
1 2 context-callstack-bottom-offset LWZ
! Call into Factor code
0 2 LOAD32 rc-absolute-ppc-2/2 rt-entry-point jit-rel
2 MTLR
BLRL
! Load VM again, pointlessly
0 vm-reg LOAD32 rc-absolute-ppc-2/2 rt-vm jit-rel
! Load C callstack pointer
2 vm-reg vm-context-offset LWZ
1 2 context-callstack-save-offset LWZ
! Load old context
2 1 old-context-save-offset LWZ
2 vm-reg vm-context-offset STW
! Restore non-volatile registers
nv-vec-regs [ 16 * 224 + restore-vec ] each-index
nv-fp-regs [ 8 * 80 + restore-fp ] each-index
nv-int-regs [ 4 * restore-int ] each-index
! Tear down stack frame and return
0 1 callback-frame-size lr-save + LWZ
1 1 callback-frame-size ADDI
0 MTLR
BLR
] callback-stub jit-define
: jit-conditional* ( test-quot false-quot -- )
[ '[ 4 /i 1 + @ ] ] dip jit-conditional ; inline
: jit-load-context ( -- )
ctx-reg vm-reg vm-context-offset LWZ ;
: jit-save-context ( -- )
jit-load-context
1 ctx-reg context-callstack-top-offset STW
ds-reg ctx-reg context-datastack-offset STW
rs-reg ctx-reg context-retainstack-offset STW ;
: jit-restore-context ( -- )
ds-reg ctx-reg context-datastack-offset LWZ
rs-reg ctx-reg context-retainstack-offset LWZ ;
[
0 12 LOAD32 rc-absolute-ppc-2/2 rt-literal jit-rel
11 12 profile-count-offset LWZ
11 11 1 tag-fixnum ADDI
11 12 profile-count-offset STW
11 12 word-code-offset LWZ
11 11 compiled-header-size ADDI
11 MTCTR
BCTR
] jit-profiling jit-define
[
0 2 LOAD32 rc-absolute-ppc-2/2 rt-this jit-rel
0 MFLR
1 1 stack-frame SUBI
2 1 xt-save STW
stack-frame 2 LI
2 1 next-save STW
0 1 lr-save stack-frame + STW
] jit-prolog jit-define
[
0 3 LOAD32 rc-absolute-ppc-2/2 rt-literal jit-rel
3 ds-reg 4 STWU
] jit-push jit-define
[
jit-save-context
3 vm-reg MR
0 4 LOAD32 rc-absolute-ppc-2/2 rt-dlsym jit-rel
4 MTLR
BLRL
jit-restore-context
] jit-primitive jit-define
[ 0 BL rc-relative-ppc-3 rt-entry-point-pic jit-rel ] jit-word-call jit-define
[
0 6 LOAD32 rc-absolute-ppc-2/2 rt-here jit-rel
0 B rc-relative-ppc-3 rt-entry-point-pic-tail jit-rel
] jit-word-jump jit-define
[
3 ds-reg 0 LWZ
ds-reg dup 4 SUBI
0 3 \ f type-number CMPI
[ BEQ ] [ 0 B rc-relative-ppc-3 rt-entry-point jit-rel ] jit-conditional*
0 B rc-relative-ppc-3 rt-entry-point jit-rel
] jit-if jit-define
: jit->r ( -- )
4 ds-reg 0 LWZ
ds-reg dup 4 SUBI
4 rs-reg 4 STWU ;
: jit-2>r ( -- )
4 ds-reg 0 LWZ
5 ds-reg -4 LWZ
ds-reg dup 8 SUBI
rs-reg dup 8 ADDI
4 rs-reg 0 STW
5 rs-reg -4 STW ;
: jit-3>r ( -- )
4 ds-reg 0 LWZ
5 ds-reg -4 LWZ
6 ds-reg -8 LWZ
ds-reg dup 12 SUBI
rs-reg dup 12 ADDI
4 rs-reg 0 STW
5 rs-reg -4 STW
6 rs-reg -8 STW ;
: jit-r> ( -- )
4 rs-reg 0 LWZ
rs-reg dup 4 SUBI
4 ds-reg 4 STWU ;
: jit-2r> ( -- )
4 rs-reg 0 LWZ
5 rs-reg -4 LWZ
rs-reg dup 8 SUBI
ds-reg dup 8 ADDI
4 ds-reg 0 STW
5 ds-reg -4 STW ;
: jit-3r> ( -- )
4 rs-reg 0 LWZ
5 rs-reg -4 LWZ
6 rs-reg -8 LWZ
rs-reg dup 12 SUBI
ds-reg dup 12 ADDI
4 ds-reg 0 STW
5 ds-reg -4 STW
6 ds-reg -8 STW ;
[
jit->r
0 BL rc-relative-ppc-3 rt-entry-point jit-rel
jit-r>
] jit-dip jit-define
[
jit-2>r
0 BL rc-relative-ppc-3 rt-entry-point jit-rel
jit-2r>
] jit-2dip jit-define
[
jit-3>r
0 BL rc-relative-ppc-3 rt-entry-point jit-rel
jit-3r>
] jit-3dip jit-define
[
0 1 lr-save stack-frame + LWZ
1 1 stack-frame ADDI
0 MTLR
] jit-epilog jit-define
[ BLR ] jit-return jit-define
! ! ! Polymorphic inline caches
! Don't touch r6 here; it's used to pass the tail call site
! address for tail PICs
! Load a value from a stack position
[
4 ds-reg 0 LWZ rc-absolute-ppc-2 rt-untagged jit-rel
] pic-load jit-define
[ 4 4 tag-mask get ANDI ] pic-tag jit-define
[
3 4 MR
4 4 tag-mask get ANDI
0 4 tuple type-number CMPI
[ BNE ]
[ 4 3 tuple-class-offset LWZ ]
jit-conditional*
] pic-tuple jit-define
[
0 4 0 CMPI rc-absolute-ppc-2 rt-untagged jit-rel
] pic-check-tag jit-define
[
0 5 LOAD32 rc-absolute-ppc-2/2 rt-literal jit-rel
4 0 5 CMP
] pic-check-tuple jit-define
[
[ BNE ] [ 0 B rc-relative-ppc-3 rt-entry-point jit-rel ] jit-conditional*
] pic-hit jit-define
! Inline cache miss entry points
: jit-load-return-address ( -- ) 6 MFLR ;
! These are always in tail position with an existing stack
! frame, and the stack. The frame setup takes this into account.
: jit-inline-cache-miss ( -- )
jit-save-context
3 6 MR
4 vm-reg MR
"inline_cache_miss" jit-call
jit-load-context
jit-restore-context ;
[ jit-load-return-address jit-inline-cache-miss ]
[ 3 MTLR BLRL ]
[ 3 MTCTR BCTR ]
\ inline-cache-miss define-combinator-primitive
[ jit-inline-cache-miss ]
[ 3 MTLR BLRL ]
[ 3 MTCTR BCTR ]
\ inline-cache-miss-tail define-combinator-primitive
! ! ! Megamorphic caches
[
! class = ...
3 4 MR
4 4 tag-mask get ANDI
4 4 tag-bits get SLWI
0 4 tuple type-number tag-fixnum CMPI
[ BNE ]
[ 4 3 tuple-class-offset LWZ ]
jit-conditional*
! cache = ...
0 3 LOAD32 rc-absolute-ppc-2/2 rt-literal jit-rel
! key = hashcode(class)
5 4 1 SRAWI
! key &= cache.length - 1
5 5 mega-cache-size get 1 - 4 * ANDI
! cache += array-start-offset
3 3 array-start-offset ADDI
! cache += key
3 3 5 ADD
! if(get(cache) == class)
6 3 0 LWZ
6 0 4 CMP
[ BNE ]
[
! megamorphic_cache_hits++
0 4 LOAD32 rc-absolute-ppc-2/2 rt-megamorphic-cache-hits jit-rel
5 4 0 LWZ
5 5 1 ADDI
5 4 0 STW
! ... goto get(cache + 4)
3 3 4 LWZ
3 3 word-entry-point-offset LWZ
3 MTCTR
BCTR
]
jit-conditional*
! fall-through on miss
] mega-lookup jit-define
! ! ! Sub-primitives
! Quotations and words
[
3 ds-reg 0 LWZ
ds-reg dup 4 SUBI
]
[ jit-call-quot ]
[ jit-jump-quot ] \ (call) define-combinator-primitive
[
3 ds-reg 0 LWZ
ds-reg dup 4 SUBI
4 3 word-entry-point-offset LWZ
]
[ 4 MTLR BLRL ]
[ 4 MTCTR BCTR ] \ (execute) define-combinator-primitive
[
3 ds-reg 0 LWZ
ds-reg dup 4 SUBI
4 3 word-entry-point-offset LWZ
4 MTCTR BCTR
] jit-execute jit-define
! Special primitives
[
nv-reg 3 MR
3 vm-reg MR
"begin_callback" jit-call
jit-load-context
jit-restore-context
! Call quotation
3 nv-reg MR
jit-call-quot
jit-save-context
3 vm-reg MR
"end_callback" jit-call
] \ c-to-factor define-sub-primitive
[
! Unwind stack frames
1 4 MR
! Load VM pointer into vm-reg, since we're entering from
! C code
0 vm-reg LOAD32 0 rc-absolute-ppc-2/2 jit-vm
! Load ds and rs registers
jit-load-context
jit-restore-context
! We have changed the stack; load return address again
0 1 lr-save LWZ
0 MTLR
! Call quotation
jit-call-quot
] \ unwind-native-frames define-sub-primitive
[
! Load callstack object
6 ds-reg 0 LWZ
ds-reg ds-reg 4 SUBI
! Get ctx->callstack_bottom
jit-load-context
3 ctx-reg context-callstack-bottom-offset LWZ
! Get top of callstack object -- 'src' for memcpy
4 6 callstack-top-offset ADDI
! Get callstack length, in bytes --- 'len' for memcpy
5 6 callstack-length-offset LWZ
5 5 tag-bits get SRAWI
! Compute new stack pointer -- 'dst' for memcpy
3 5 3 SUBF
! Install new stack pointer
1 3 MR
! Call memcpy; arguments are now in the correct registers
1 1 -64 STWU
"factor_memcpy" jit-call
1 1 0 LWZ
! Return with new callstack
0 1 lr-save LWZ
0 MTLR
BLR
] \ set-callstack define-sub-primitive
[
jit-save-context
4 vm-reg MR
"lazy_jit_compile" jit-call
]
[ jit-call-quot ]
[ jit-jump-quot ]
\ lazy-jit-compile define-combinator-primitive
! Objects
[
3 ds-reg 0 LWZ
3 3 tag-mask get ANDI
3 3 tag-bits get SLWI
3 ds-reg 0 STW
] \ tag define-sub-primitive
[
3 ds-reg 0 LWZ
4 ds-reg -4 LWZU
3 3 2 SRAWI
4 4 0 0 31 tag-bits get - RLWINM
4 3 3 LWZX
3 ds-reg 0 STW
] \ slot define-sub-primitive
[
! load string index from stack
3 ds-reg -4 LWZ
3 3 tag-bits get SRAWI
! load string from stack
4 ds-reg 0 LWZ
! load character
4 4 string-offset ADDI
3 3 4 LBZX
3 3 tag-bits get SLWI
! store character to stack
ds-reg ds-reg 4 SUBI
3 ds-reg 0 STW
] \ string-nth-fast define-sub-primitive
! Shufflers
[
ds-reg dup 4 SUBI
] \ drop define-sub-primitive
[
ds-reg dup 8 SUBI
] \ 2drop define-sub-primitive
[
ds-reg dup 12 SUBI
] \ 3drop define-sub-primitive
[
3 ds-reg 0 LWZ
3 ds-reg 4 STWU
] \ dup define-sub-primitive
[
3 ds-reg 0 LWZ
4 ds-reg -4 LWZ
ds-reg dup 8 ADDI
3 ds-reg 0 STW
4 ds-reg -4 STW
] \ 2dup define-sub-primitive
[
3 ds-reg 0 LWZ
4 ds-reg -4 LWZ
5 ds-reg -8 LWZ
ds-reg dup 12 ADDI
3 ds-reg 0 STW
4 ds-reg -4 STW
5 ds-reg -8 STW
] \ 3dup define-sub-primitive
[
3 ds-reg 0 LWZ
ds-reg dup 4 SUBI
3 ds-reg 0 STW
] \ nip define-sub-primitive
[
3 ds-reg 0 LWZ
ds-reg dup 8 SUBI
3 ds-reg 0 STW
] \ 2nip define-sub-primitive
[
3 ds-reg -4 LWZ
3 ds-reg 4 STWU
] \ over define-sub-primitive
[
3 ds-reg -8 LWZ
3 ds-reg 4 STWU
] \ pick define-sub-primitive
[
3 ds-reg 0 LWZ
4 ds-reg -4 LWZ
4 ds-reg 0 STW
3 ds-reg 4 STWU
] \ dupd define-sub-primitive
[
3 ds-reg 0 LWZ
4 ds-reg -4 LWZ
3 ds-reg -4 STW
4 ds-reg 0 STW
] \ swap define-sub-primitive
[
3 ds-reg -4 LWZ
4 ds-reg -8 LWZ
3 ds-reg -8 STW
4 ds-reg -4 STW
] \ swapd define-sub-primitive
[
3 ds-reg 0 LWZ
4 ds-reg -4 LWZ
5 ds-reg -8 LWZ
4 ds-reg -8 STW
3 ds-reg -4 STW
5 ds-reg 0 STW
] \ rot define-sub-primitive
[
3 ds-reg 0 LWZ
4 ds-reg -4 LWZ
5 ds-reg -8 LWZ
3 ds-reg -8 STW
5 ds-reg -4 STW
4 ds-reg 0 STW
] \ -rot define-sub-primitive
[ jit->r ] \ load-local define-sub-primitive
! Comparisons
: jit-compare ( insn -- )
t jit-literal
0 3 LOAD32 rc-absolute-ppc-2/2 rt-literal jit-rel
4 ds-reg 0 LWZ
5 ds-reg -4 LWZU
5 0 4 CMP
2 swap execute( offset -- ) ! magic number
\ f type-number 3 LI
3 ds-reg 0 STW ;
: define-jit-compare ( insn word -- )
[ [ jit-compare ] curry ] dip define-sub-primitive ;
\ BEQ \ eq? define-jit-compare
\ BGE \ fixnum>= define-jit-compare
\ BLE \ fixnum<= define-jit-compare
\ BGT \ fixnum> define-jit-compare
\ BLT \ fixnum< define-jit-compare
! Math
[
3 ds-reg 0 LWZ
ds-reg ds-reg 4 SUBI
4 ds-reg 0 LWZ
3 3 4 OR
3 3 tag-mask get ANDI
\ f type-number 4 LI
0 3 0 CMPI
[ BNE ] [ 1 tag-fixnum 4 LI ] jit-conditional*
4 ds-reg 0 STW
] \ both-fixnums? define-sub-primitive
: jit-math ( insn -- )
3 ds-reg 0 LWZ
4 ds-reg -4 LWZU
[ 5 3 4 ] dip execute( dst src1 src2 -- )
5 ds-reg 0 STW ;
[ \ ADD jit-math ] \ fixnum+fast define-sub-primitive
[ \ SUBF jit-math ] \ fixnum-fast define-sub-primitive
[
3 ds-reg 0 LWZ
4 ds-reg -4 LWZU
4 4 tag-bits get SRAWI
5 3 4 MULLW
5 ds-reg 0 STW
] \ fixnum*fast define-sub-primitive
[ \ AND jit-math ] \ fixnum-bitand define-sub-primitive
[ \ OR jit-math ] \ fixnum-bitor define-sub-primitive
[ \ XOR jit-math ] \ fixnum-bitxor define-sub-primitive
[
3 ds-reg 0 LWZ
3 3 NOT
3 3 tag-mask get XORI
3 ds-reg 0 STW
] \ fixnum-bitnot define-sub-primitive
[
3 ds-reg 0 LWZ
3 3 tag-bits get SRAWI
ds-reg ds-reg 4 SUBI
4 ds-reg 0 LWZ
5 4 3 SLW
6 3 NEG
7 4 6 SRAW
7 7 0 0 31 tag-bits get - RLWINM
0 3 0 CMPI
[ BGT ] [ 5 7 MR ] jit-conditional*
5 ds-reg 0 STW
] \ fixnum-shift-fast define-sub-primitive
[
3 ds-reg 0 LWZ
ds-reg ds-reg 4 SUBI
4 ds-reg 0 LWZ
5 4 3 DIVW
6 5 3 MULLW
7 6 4 SUBF
7 ds-reg 0 STW
] \ fixnum-mod define-sub-primitive
[
3 ds-reg 0 LWZ
ds-reg ds-reg 4 SUBI
4 ds-reg 0 LWZ
5 4 3 DIVW
5 5 tag-bits get SLWI
5 ds-reg 0 STW
] \ fixnum/i-fast define-sub-primitive
[
3 ds-reg 0 LWZ
4 ds-reg -4 LWZ
5 4 3 DIVW
6 5 3 MULLW
7 6 4 SUBF
5 5 tag-bits get SLWI
5 ds-reg -4 STW
7 ds-reg 0 STW
] \ fixnum/mod-fast define-sub-primitive
[
3 ds-reg 0 LWZ
3 3 2 SRAWI
rs-reg 3 3 LWZX
3 ds-reg 0 STW
] \ get-local define-sub-primitive
[
3 ds-reg 0 LWZ
ds-reg ds-reg 4 SUBI
3 3 2 SRAWI
rs-reg 3 rs-reg SUBF
] \ drop-locals define-sub-primitive
! Overflowing fixnum arithmetic
:: jit-overflow ( insn func -- )
ds-reg ds-reg 4 SUBI
jit-save-context
3 ds-reg 0 LWZ
4 ds-reg 4 LWZ
0 0 LI
0 MTXER
6 4 3 insn call( d a s -- )
6 ds-reg 0 STW
[ BNO ]
[
5 vm-reg MR
func jit-call
]
jit-conditional* ;
[ [ ADDO. ] "overflow_fixnum_add" jit-overflow ] \ fixnum+ define-sub-primitive
[ [ SUBFO. ] "overflow_fixnum_subtract" jit-overflow ] \ fixnum- define-sub-primitive
[
ds-reg ds-reg 4 SUBI
jit-save-context
3 ds-reg 0 LWZ
3 3 tag-bits get SRAWI
4 ds-reg 4 LWZ
0 0 LI
0 MTXER
6 3 4 MULLWO.
6 ds-reg 0 STW
[ BNO ]
[
4 4 tag-bits get SRAWI
5 vm-reg MR
"overflow_fixnum_multiply" jit-call
]
jit-conditional*
] \ fixnum* define-sub-primitive
! Contexts
: jit-switch-context ( reg -- )
! Save ds, rs registers
jit-save-context
! Make the new context the current one
ctx-reg swap MR
ctx-reg vm-reg vm-context-offset STW
! Load new stack pointer
1 ctx-reg context-callstack-top-offset LWZ
! Load new ds, rs registers
jit-restore-context ;
: jit-pop-context-and-param ( -- )
3 ds-reg 0 LWZ
3 3 alien-offset LWZ
4 ds-reg -4 LWZ
ds-reg ds-reg 8 SUBI ;
: jit-push-param ( -- )
ds-reg ds-reg 4 ADDI
4 ds-reg 0 STW ;
: jit-set-context ( -- )
jit-pop-context-and-param
3 jit-switch-context
jit-push-param ;
[ jit-set-context ] \ (set-context) define-sub-primitive
: jit-pop-quot-and-param ( -- )
3 ds-reg 0 LWZ
4 ds-reg -4 LWZ
ds-reg ds-reg 8 SUBI ;
: jit-start-context ( -- )
! Create the new context in return-reg
3 vm-reg MR
"new_context" jit-call
6 3 MR
jit-pop-quot-and-param
6 jit-switch-context
jit-push-param
jit-jump-quot ;
[ jit-start-context ] \ (start-context) define-sub-primitive
: jit-delete-current-context ( -- )
jit-load-context
3 vm-reg MR
4 ctx-reg MR
"delete_context" jit-call ;
[
jit-delete-current-context
jit-set-context
] \ (set-context-and-delete) define-sub-primitive
[
jit-delete-current-context
jit-start-context
] \ (start-context-and-delete) define-sub-primitive
[ "bootstrap.ppc" forget-vocab ] with-compilation-unit

View File

@ -1,10 +0,0 @@
! Copyright (C) 2007, 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: parser system kernel sequences ;
IN: bootstrap.ppc
: reserved-size ( -- n ) 24 ;
: lr-save ( -- n ) 4 ;
<< "vocab:cpu/ppc/bootstrap.factor" parse-file suffix! >>
call

View File

@ -1,28 +0,0 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors system kernel layouts
alien.c-types cpu.architecture cpu.ppc ;
IN: cpu.ppc.linux
<<
t "longlong" c-type stack-align?<<
t "ulonglong" c-type stack-align?<<
>>
M: linux reserved-area-size 2 cells ;
M: linux lr-save 1 cells ;
M: ppc param-regs
drop {
{ int-regs { 3 4 5 6 7 8 9 10 } }
{ float-regs { 1 2 3 4 5 6 7 8 } }
} ;
M: ppc value-struct? drop f ;
M: ppc dummy-stack-params? f ;
M: ppc dummy-int-params? f ;
M: ppc dummy-fp-params? f ;

View File

@ -1 +0,0 @@
Linux/PPC ABI support

View File

@ -1 +0,0 @@
not loaded

View File

@ -1,10 +0,0 @@
! Copyright (C) 2007, 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: parser system kernel sequences ;
IN: bootstrap.ppc
: reserved-size ( -- n ) 24 ;
: lr-save ( -- n ) 8 ;
<< "vocab:cpu/ppc/bootstrap.factor" parse-file suffix! >>
call

View File

@ -1,23 +0,0 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors system kernel layouts
alien.c-types cpu.architecture cpu.ppc ;
IN: cpu.ppc.macosx
M: macosx reserved-area-size 6 cells ;
M: macosx lr-save 2 cells ;
M: ppc param-regs
drop {
{ int-regs { 3 4 5 6 7 8 9 10 } }
{ float-regs { 1 2 3 4 5 6 7 8 9 10 11 12 13 } }
} ;
M: ppc value-struct? drop t ;
M: ppc dummy-stack-params? t ;
M: ppc dummy-int-params? t ;
M: ppc dummy-fp-params? f ;

View File

@ -1 +0,0 @@
Mac OS X/PPC ABI support

View File

@ -1 +0,0 @@
not loaded

View File

@ -1,826 +0,0 @@
! Copyright (C) 2005, 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs sequences kernel combinators
classes.algebra byte-arrays make math math.order math.ranges
system namespaces locals layouts words alien alien.accessors
alien.c-types alien.complex alien.data alien.libraries
literals cpu.architecture cpu.ppc.assembler cpu.ppc.assembler.backend
compiler.cfg.registers compiler.cfg.instructions
compiler.cfg.comparisons compiler.codegen.fixup
compiler.cfg.intrinsics compiler.cfg.stack-frame
compiler.cfg.build-stack-frame compiler.units compiler.constants
compiler.codegen vm ;
QUALIFIED-WITH: alien.c-types c
FROM: cpu.ppc.assembler => B ;
FROM: layouts => cell ;
FROM: math => float ;
IN: cpu.ppc
! PowerPC register assignments:
! r2-r12: integer vregs
! r13: data stack
! r14: retain stack
! r15: VM pointer
! r16-r29: integer vregs
! r30: integer scratch
! f0-f29: float vregs
! f30: float scratch
! Add some methods to the assembler that are useful to us
M: label (B) [ 0 ] 2dip (B) rc-relative-ppc-3 label-fixup ;
M: label BC [ 0 BC ] dip rc-relative-ppc-2 label-fixup ;
enable-float-intrinsics
M: ppc machine-registers
{
{ int-regs $[ 2 12 [a,b] 16 29 [a,b] append ] }
{ float-regs $[ 0 29 [a,b] ] }
} ;
CONSTANT: scratch-reg 30
CONSTANT: fp-scratch-reg 30
M: ppc complex-addressing? f ;
M: ppc fused-unboxing? f ;
M: ppc %load-immediate ( reg n -- ) swap LOAD ;
M: ppc %load-reference ( reg obj -- )
[ [ 0 swap LOAD32 ] [ rc-absolute-ppc-2/2 rel-literal ] bi* ]
[ \ f type-number swap LI ]
if* ;
M: ppc %alien-global ( register symbol dll -- )
[ 0 swap LOAD32 ] 2dip rc-absolute-ppc-2/2 rel-dlsym ;
CONSTANT: ds-reg 13
CONSTANT: rs-reg 14
CONSTANT: vm-reg 15
: %load-vm-addr ( reg -- ) vm-reg MR ;
M: ppc %vm-field ( dst field -- ) [ vm-reg ] dip LWZ ;
M: ppc %set-vm-field ( src field -- ) [ vm-reg ] dip STW ;
GENERIC: loc-reg ( loc -- reg )
M: ds-loc loc-reg drop ds-reg ;
M: rs-loc loc-reg drop rs-reg ;
: loc>operand ( loc -- reg n )
[ loc-reg ] [ n>> cells neg ] bi ; inline
M: ppc %peek loc>operand LWZ ;
M: ppc %replace loc>operand STW ;
:: (%inc) ( n reg -- ) reg reg n cells ADDI ; inline
M: ppc %inc-d ( n -- ) ds-reg (%inc) ;
M: ppc %inc-r ( n -- ) rs-reg (%inc) ;
HOOK: reserved-area-size os ( -- n )
! The start of the stack frame contains the size of this frame
! as well as the currently executing code block
: factor-area-size ( -- n ) 2 cells ; foldable
: next-save ( n -- i ) cell - ; foldable
: xt-save ( n -- i ) 2 cells - ; foldable
! Next, we have the spill area as well as the FFI parameter area.
! It is safe for them to overlap, since basic blocks with FFI calls
! will never spill -- indeed, basic blocks with FFI calls do not
! use vregs at all, and the FFI call is a stack analysis sync point.
! In the future this will change and the stack frame logic will
! need to be untangled somewhat.
: param@ ( n -- x ) reserved-area-size + ; inline
: param-save-size ( -- n ) 8 cells ; foldable
: local@ ( n -- x )
reserved-area-size param-save-size + + ; inline
: spill@ ( n -- offset )
spill-offset local@ ;
! Some FP intrinsics need a temporary scratch area in the stack
! frame, 8 bytes in size. This is in the param-save area so it
! does not overlap with spill slots.
: scratch@ ( n -- offset )
factor-area-size + ;
! Finally we have the linkage area
HOOK: lr-save os ( -- n )
M: ppc stack-frame-size ( stack-frame -- i )
(stack-frame-size)
param-save-size +
reserved-area-size +
factor-area-size +
4 cells align ;
M: ppc %call ( word -- ) 0 BL rc-relative-ppc-3 rel-word-pic ;
M: ppc %jump ( word -- )
0 6 LOAD32 4 rc-absolute-ppc-2/2 rel-here
0 B rc-relative-ppc-3 rel-word-pic-tail ;
M: ppc %jump-label ( label -- ) B ;
M: ppc %return ( -- ) BLR ;
M:: ppc %dispatch ( src temp -- )
0 temp LOAD32
3 cells rc-absolute-ppc-2/2 rel-here
temp temp src LWZX
temp MTCTR
BCTR ;
: (%slot) ( dst obj slot scale tag -- obj dst slot )
[ 0 assert= ] bi@ swapd ;
M: ppc %slot ( dst obj slot scale tag -- ) (%slot) LWZX ;
M: ppc %slot-imm ( dst obj slot tag -- ) slot-offset LWZ ;
M: ppc %set-slot ( src obj slot scale tag -- ) (%slot) STWX ;
M: ppc %set-slot-imm ( src obj slot tag -- ) slot-offset STW ;
M: ppc %add ADD ;
M: ppc %add-imm ADDI ;
M: ppc %sub swap SUBF ;
M: ppc %sub-imm SUBI ;
M: ppc %mul MULLW ;
M: ppc %mul-imm MULLI ;
M: ppc %and AND ;
M: ppc %and-imm ANDI ;
M: ppc %or OR ;
M: ppc %or-imm ORI ;
M: ppc %xor XOR ;
M: ppc %xor-imm XORI ;
M: ppc %shl SLW ;
M: ppc %shl-imm swapd SLWI ;
M: ppc %shr SRW ;
M: ppc %shr-imm swapd SRWI ;
M: ppc %sar SRAW ;
M: ppc %sar-imm SRAWI ;
M: ppc %not NOT ;
M: ppc %neg NEG ;
:: overflow-template ( label dst src1 src2 cc insn -- )
0 0 LI
0 MTXER
dst src2 src1 insn call
cc {
{ cc-o [ label BO ] }
{ cc/o [ label BNO ] }
} case ; inline
M: ppc %fixnum-add ( label dst src1 src2 cc -- )
[ ADDO. ] overflow-template ;
M: ppc %fixnum-sub ( label dst src1 src2 cc -- )
[ SUBFO. ] overflow-template ;
M: ppc %fixnum-mul ( label dst src1 src2 cc -- )
[ MULLWO. ] overflow-template ;
M: ppc %add-float FADD ;
M: ppc %sub-float FSUB ;
M: ppc %mul-float FMUL ;
M: ppc %div-float FDIV ;
M: ppc integer-float-needs-stack-frame? t ;
M:: ppc %integer>float ( dst src -- )
HEX: 4330 scratch-reg LIS
scratch-reg 1 0 scratch@ STW
scratch-reg src MR
scratch-reg dup HEX: 8000 XORIS
scratch-reg 1 4 scratch@ STW
dst 1 0 scratch@ LFD
scratch-reg 4503601774854144.0 %load-reference
fp-scratch-reg scratch-reg float-offset LFD
dst dst fp-scratch-reg FSUB ;
M:: ppc %float>integer ( dst src -- )
fp-scratch-reg src FCTIWZ
fp-scratch-reg 1 0 scratch@ STFD
dst 1 4 scratch@ LWZ ;
M: ppc %copy ( dst src rep -- )
2over eq? [ 3drop ] [
{
{ tagged-rep [ MR ] }
{ int-rep [ MR ] }
{ double-rep [ FMR ] }
} case
] if ;
GENERIC: float-function-param* ( dst src -- )
M: spill-slot float-function-param* [ 1 ] dip n>> spill@ LFD ;
M: integer float-function-param* FMR ;
: float-function-param ( i src -- )
[ float-regs cdecl param-regs at nth ] dip float-function-param* ;
: float-function-return ( reg -- )
float-regs return-regs at first double-rep %copy ;
M:: ppc %unary-float-function ( dst src func -- )
0 src float-function-param
func f %c-invoke
dst float-function-return ;
M:: ppc %binary-float-function ( dst src1 src2 func -- )
0 src1 float-function-param
1 src2 float-function-param
func f %c-invoke
dst float-function-return ;
! Internal format is always double-precision on PowerPC
M: ppc %single>double-float double-rep %copy ;
M: ppc %double>single-float FRSP ;
M: ppc %unbox-alien ( dst src -- )
alien-offset LWZ ;
M:: ppc %unbox-any-c-ptr ( dst src -- )
[
"end" define-label
0 dst LI
! Is the object f?
0 src \ f type-number CMPI
"end" get BEQ
! Compute tag in dst register
dst src tag-mask get ANDI
! Is the object an alien?
0 dst alien type-number CMPI
! Add an offset to start of byte array's data
dst src byte-array-offset ADDI
"end" get BNE
! If so, load the offset and add it to the address
dst src alien-offset LWZ
"end" resolve-label
] with-scope ;
: alien@ ( n -- n' ) cells alien type-number - ;
M:: ppc %box-alien ( dst src temp -- )
[
"f" define-label
dst \ f type-number %load-immediate
0 src 0 CMPI
"f" get BEQ
dst 5 cells alien temp %allot
temp \ f type-number %load-immediate
temp dst 1 alien@ STW
temp dst 2 alien@ STW
src dst 3 alien@ STW
src dst 4 alien@ STW
"f" resolve-label
] with-scope ;
:: %box-displaced-alien/f ( dst displacement base -- )
base dst 1 alien@ STW
displacement dst 3 alien@ STW
displacement dst 4 alien@ STW ;
:: %box-displaced-alien/alien ( dst displacement base temp -- )
! Set new alien's base to base.base
temp base 1 alien@ LWZ
temp dst 1 alien@ STW
! Compute displacement
temp base 3 alien@ LWZ
temp temp displacement ADD
temp dst 3 alien@ STW
! Compute address
temp base 4 alien@ LWZ
temp temp displacement ADD
temp dst 4 alien@ STW ;
:: %box-displaced-alien/byte-array ( dst displacement base temp -- )
base dst 1 alien@ STW
displacement dst 3 alien@ STW
temp base byte-array-offset ADDI
temp temp displacement ADD
temp dst 4 alien@ STW ;
:: %box-displaced-alien/dynamic ( dst displacement base temp -- )
"not-f" define-label
"not-alien" define-label
! Is base f?
0 base \ f type-number CMPI
"not-f" get BNE
! Yes, it is f. Fill in new object
dst displacement base %box-displaced-alien/f
"end" get B
"not-f" resolve-label
! Check base type
temp base tag-mask get ANDI
! Is base an alien?
0 temp alien type-number CMPI
"not-alien" get BNE
dst displacement base temp %box-displaced-alien/alien
! We are done
"end" get B
! Is base a byte array? It has to be, by now...
"not-alien" resolve-label
dst displacement base temp %box-displaced-alien/byte-array ;
M:: ppc %box-displaced-alien ( dst displacement base temp base-class -- )
! This is ridiculous
[
"end" define-label
! If displacement is zero, return the base
dst base MR
0 displacement 0 CMPI
"end" get BEQ
! Displacement is non-zero, we're going to be allocating a new
! object
dst 5 cells alien temp %allot
! Set expired to f
temp \ f type-number %load-immediate
temp dst 2 alien@ STW
dst displacement base temp
{
{ [ base-class \ f class<= ] [ drop %box-displaced-alien/f ] }
{ [ base-class \ alien class<= ] [ %box-displaced-alien/alien ] }
{ [ base-class \ byte-array class<= ] [ %box-displaced-alien/byte-array ] }
[ %box-displaced-alien/dynamic ]
} cond
"end" resolve-label
] with-scope ;
: (%memory) ( val base displacement scale offset rep c-type -- base val displacement rep c-type )
[ [ 0 assert= ] bi@ swapd ] 2dip ; inline
M: ppc %load-memory-imm ( dst base offset rep c-type -- )
[
{
{ c:char [ [ dup ] 2dip LBZ dup EXTSB ] }
{ c:uchar [ LBZ ] }
{ c:short [ LHA ] }
{ c:ushort [ LHZ ] }
{ c:int [ LWZ ] }
{ c:uint [ LWZ ] }
} case
] [
{
{ int-rep [ LWZ ] }
{ float-rep [ LFS ] }
{ double-rep [ LFD ] }
} case
] ?if ;
M: ppc %load-memory ( dst base displacement scale offset rep c-type -- )
(%memory) [
{
{ c:char [ [ LBZX ] [ drop dup EXTSB ] 2bi ] }
{ c:uchar [ LBZX ] }
{ c:short [ LHAX ] }
{ c:ushort [ LHZX ] }
{ c:int [ LWZX ] }
{ c:uint [ LWZX ] }
} case
] [
{
{ int-rep [ LWZX ] }
{ float-rep [ LFSX ] }
{ double-rep [ LFDX ] }
} case
] ?if ;
M: ppc %store-memory-imm ( src base offset rep c-type -- )
[
{
{ c:char [ STB ] }
{ c:uchar [ STB ] }
{ c:short [ STH ] }
{ c:ushort [ STH ] }
{ c:int [ STW ] }
{ c:uint [ STW ] }
} case
] [
{
{ int-rep [ STW ] }
{ float-rep [ STFS ] }
{ double-rep [ STFD ] }
} case
] ?if ;
M: ppc %store-memory ( src base displacement scale offset rep c-type -- )
(%memory) [
{
{ c:char [ STBX ] }
{ c:uchar [ STBX ] }
{ c:short [ STHX ] }
{ c:ushort [ STHX ] }
{ c:int [ STWX ] }
{ c:uint [ STWX ] }
} case
] [
{
{ int-rep [ STWX ] }
{ float-rep [ STFSX ] }
{ double-rep [ STFDX ] }
} case
] ?if ;
: load-zone-ptr ( reg -- )
vm-reg "nursery" vm-field-offset ADDI ;
: load-allot-ptr ( nursery-ptr allot-ptr -- )
[ drop load-zone-ptr ] [ swap 0 LWZ ] 2bi ;
:: inc-allot-ptr ( nursery-ptr allot-ptr n -- )
scratch-reg allot-ptr n data-alignment get align ADDI
scratch-reg nursery-ptr 0 STW ;
:: store-header ( dst class -- )
class type-number tag-header scratch-reg LI
scratch-reg dst 0 STW ;
: store-tagged ( dst tag -- )
dupd type-number ORI ;
M:: ppc %allot ( dst size class nursery-ptr -- )
nursery-ptr dst load-allot-ptr
nursery-ptr dst size inc-allot-ptr
dst class store-header
dst class store-tagged ;
: load-cards-offset ( dst -- )
0 swap LOAD32 rc-absolute-ppc-2/2 rel-cards-offset ;
: load-decks-offset ( dst -- )
0 swap LOAD32 rc-absolute-ppc-2/2 rel-decks-offset ;
:: (%write-barrier) ( temp1 temp2 -- )
card-mark scratch-reg LI
! Mark the card
temp1 temp1 card-bits SRWI
temp2 load-cards-offset
temp1 scratch-reg temp2 STBX
! Mark the card deck
temp1 temp1 deck-bits card-bits - SRWI
temp2 load-decks-offset
temp1 scratch-reg temp2 STBX ;
M:: ppc %write-barrier ( src slot scale tag temp1 temp2 -- )
scale 0 assert= tag 0 assert=
temp1 src slot ADD
temp1 temp2 (%write-barrier) ;
M:: ppc %write-barrier-imm ( src slot tag temp1 temp2 -- )
temp1 src slot tag slot-offset ADDI
temp1 temp2 (%write-barrier) ;
M:: ppc %check-nursery-branch ( label size cc temp1 temp2 -- )
temp1 vm-reg "nursery" vm-field-offset LWZ
temp2 vm-reg "nursery" vm-field-offset 2 cells + LWZ
temp1 temp1 size ADDI
! is here >= end?
temp1 0 temp2 CMP
cc {
{ cc<= [ label BLE ] }
{ cc/<= [ label BGT ] }
} case ;
: gc-root-offsets ( seq -- seq' )
[ n>> spill@ ] map f like ;
M: ppc %call-gc ( gc-roots -- )
3 swap gc-root-offsets %load-reference
4 %load-vm-addr
"inline_gc" f %c-invoke ;
M: ppc %prologue ( n -- )
0 11 LOAD32 rc-absolute-ppc-2/2 rel-this
0 MFLR
{
[ [ 1 1 ] dip neg ADDI ]
[ [ 11 1 ] dip xt-save STW ]
[ 11 LI ]
[ [ 11 1 ] dip next-save STW ]
[ [ 0 1 ] dip lr-save + STW ]
} cleave ;
M: ppc %epilogue ( n -- )
#! At the end of each word that calls a subroutine, we store
#! the previous link register value in r0 by popping it off
#! the stack, set the link register to the contents of r0,
#! and jump to the link register.
[ [ 0 1 ] dip lr-save + LWZ ]
[ [ 1 1 ] dip ADDI ] bi
0 MTLR ;
:: (%boolean) ( dst temp branch1 branch2 -- )
"end" define-label
dst \ f type-number %load-immediate
"end" get branch1 execute( label -- )
branch2 [ "end" get branch2 execute( label -- ) ] when
dst \ t %load-reference
"end" get resolve-label ; inline
:: %boolean ( dst cc temp -- )
cc negate-cc order-cc {
{ cc< [ dst temp \ BLT f (%boolean) ] }
{ cc<= [ dst temp \ BLE f (%boolean) ] }
{ cc> [ dst temp \ BGT f (%boolean) ] }
{ cc>= [ dst temp \ BGE f (%boolean) ] }
{ cc= [ dst temp \ BEQ f (%boolean) ] }
{ cc/= [ dst temp \ BNE f (%boolean) ] }
} case ;
: (%compare) ( src1 src2 -- ) [ 0 ] dip CMP ; inline
: (%compare-integer-imm) ( src1 src2 -- )
[ 0 ] 2dip CMPI ; inline
: (%compare-imm) ( src1 src2 -- )
[ tag-fixnum ] [ \ f type-number ] if* (%compare-integer-imm) ; inline
: (%compare-float-unordered) ( src1 src2 -- )
[ 0 ] dip FCMPU ; inline
: (%compare-float-ordered) ( src1 src2 -- )
[ 0 ] dip FCMPO ; inline
:: (%compare-float) ( src1 src2 cc compare -- branch1 branch2 )
cc {
{ cc< [ src1 src2 \ compare execute( a b -- ) \ BLT f ] }
{ cc<= [ src1 src2 \ compare execute( a b -- ) \ BLT \ BEQ ] }
{ cc> [ src1 src2 \ compare execute( a b -- ) \ BGT f ] }
{ cc>= [ src1 src2 \ compare execute( a b -- ) \ BGT \ BEQ ] }
{ cc= [ src1 src2 \ compare execute( a b -- ) \ BEQ f ] }
{ cc<> [ src1 src2 \ compare execute( a b -- ) \ BLT \ BGT ] }
{ cc<>= [ src1 src2 \ compare execute( a b -- ) \ BNO f ] }
{ cc/< [ src1 src2 \ compare execute( a b -- ) \ BGE f ] }
{ cc/<= [ src1 src2 \ compare execute( a b -- ) \ BGT \ BO ] }
{ cc/> [ src1 src2 \ compare execute( a b -- ) \ BLE f ] }
{ cc/>= [ src1 src2 \ compare execute( a b -- ) \ BLT \ BO ] }
{ cc/= [ src1 src2 \ compare execute( a b -- ) \ BNE f ] }
{ cc/<> [ src1 src2 \ compare execute( a b -- ) \ BEQ \ BO ] }
{ cc/<>= [ src1 src2 \ compare execute( a b -- ) \ BO f ] }
} case ; inline
M: ppc %compare [ (%compare) ] 2dip %boolean ;
M: ppc %compare-imm [ (%compare-imm) ] 2dip %boolean ;
M: ppc %compare-integer-imm [ (%compare-integer-imm) ] 2dip %boolean ;
M:: ppc %compare-float-ordered ( dst src1 src2 cc temp -- )
src1 src2 cc negate-cc \ (%compare-float-ordered) (%compare-float) :> ( branch1 branch2 )
dst temp branch1 branch2 (%boolean) ;
M:: ppc %compare-float-unordered ( dst src1 src2 cc temp -- )
src1 src2 cc negate-cc \ (%compare-float-unordered) (%compare-float) :> ( branch1 branch2 )
dst temp branch1 branch2 (%boolean) ;
:: %branch ( label cc -- )
cc order-cc {
{ cc< [ label BLT ] }
{ cc<= [ label BLE ] }
{ cc> [ label BGT ] }
{ cc>= [ label BGE ] }
{ cc= [ label BEQ ] }
{ cc/= [ label BNE ] }
} case ;
M:: ppc %compare-branch ( label src1 src2 cc -- )
src1 src2 (%compare)
label cc %branch ;
M:: ppc %compare-imm-branch ( label src1 src2 cc -- )
src1 src2 (%compare-imm)
label cc %branch ;
M:: ppc %compare-integer-imm-branch ( label src1 src2 cc -- )
src1 src2 (%compare-integer-imm)
label cc %branch ;
:: (%branch) ( label branch1 branch2 -- )
label branch1 execute( label -- )
branch2 [ label branch2 execute( label -- ) ] when ; inline
M:: ppc %compare-float-ordered-branch ( label src1 src2 cc -- )
src1 src2 cc \ (%compare-float-ordered) (%compare-float) :> ( branch1 branch2 )
label branch1 branch2 (%branch) ;
M:: ppc %compare-float-unordered-branch ( label src1 src2 cc -- )
src1 src2 cc \ (%compare-float-unordered) (%compare-float) :> ( branch1 branch2 )
label branch1 branch2 (%branch) ;
: load-from-frame ( dst n rep -- )
{
{ int-rep [ [ 1 ] dip LWZ ] }
{ tagged-rep [ [ 1 ] dip LWZ ] }
{ float-rep [ [ 1 ] dip LFS ] }
{ double-rep [ [ 1 ] dip LFD ] }
{ stack-params [ [ 0 1 ] dip LWZ [ 0 1 ] dip param@ STW ] }
} case ;
: next-param@ ( n -- reg x )
[ 17 ] dip param@ ;
: store-to-frame ( src n rep -- )
{
{ int-rep [ [ 1 ] dip STW ] }
{ tagged-rep [ [ 1 ] dip STW ] }
{ float-rep [ [ 1 ] dip STFS ] }
{ double-rep [ [ 1 ] dip STFD ] }
{ stack-params [ [ [ 0 ] dip next-param@ LWZ 0 1 ] dip STW ] }
} case ;
M: ppc %spill ( src rep dst -- )
swap [ n>> spill@ ] dip store-to-frame ;
M: ppc %reload ( dst rep src -- )
swap [ n>> spill@ ] dip load-from-frame ;
M: ppc %loop-entry ;
M: ppc return-regs
{
{ int-regs { 3 4 5 6 } }
{ float-regs { 1 } }
} ;
M:: ppc %save-param-reg ( stack reg rep -- )
reg stack local@ rep store-to-frame ;
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 [ 1 ] dip n>> spill@ LWZ ;
GENERIC: store-param ( reg dst -- )
M: integer store-param swap int-rep %copy ;
M: spill-slot store-param [ 1 ] dip n>> spill@ STW ;
:: call-unbox-func ( src func -- )
3 src load-param
4 %load-vm-addr
func f %c-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-regs at first 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
c-type heap-size 5 LI
"memcpy" "libc" load-library %c-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 %c-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
5 %load-vm-addr
func f %c-invoke
3 dst store-param ;
: struct-return@ ( n -- n )
[ stack-frame get params>> ] unless* local@ ;
M: ppc %prepare-box-struct ( -- )
#! Compute target address for value struct return
3 1 f struct-return@ ADDI
3 1 0 local@ STW ;
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 n struct-return@ ADDI
c-type heap-size 4 LI
5 %load-vm-addr
! Call the function
"from_value_struct" f %c-invoke
3 dst store-param ;
M:: ppc %restore-context ( temp1 temp2 -- )
temp1 %context
ds-reg temp1 "datastack" context-field-offset LWZ
rs-reg temp1 "retainstack" context-field-offset LWZ ;
M:: ppc %save-context ( temp1 temp2 -- )
temp1 %context
1 temp1 "callstack-top" context-field-offset STW
ds-reg temp1 "datastack" context-field-offset STW
rs-reg temp1 "retainstack" context-field-offset STW ;
M: ppc %c-invoke ( symbol dll -- )
[ 11 ] 2dip %alien-global 11 MTLR BLRL ;
M: ppc %alien-indirect ( src -- )
[ 11 ] dip load-param 11 MTLR BLRL ;
M: ppc immediate-arithmetic? ( n -- ? ) -32768 32767 between? ;
M: ppc immediate-bitwise? ( n -- ? ) 0 65535 between? ;
M: ppc immediate-store? drop f ;
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 %c-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 %c-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 %c-invoke ;
enable-float-functions
USE: vocabs.loader
{
{ [ os macosx? ] [ "cpu.ppc.macosx" require ] }
{ [ os linux? ] [ "cpu.ppc.linux" require ] }
} cond
complex-double c-type t >>return-in-registers? drop

View File

@ -1 +0,0 @@
32-bit PowerPC compiler backend

View File

@ -1,2 +0,0 @@
compiler
not loaded

View File

@ -1,4 +1,3 @@
include vm/Config.unix
PLAF_DLL_OBJS += vm/os-genunix.o vm/os-freebsd.o vm/mvm-unix.o
CFLAGS += -export-dynamic
LIBS = -L/usr/local/lib/ -lm -lrt $(X11_UI_LIBS)
LIBS = -L/usr/local/lib/ -lm -lrt $(X11_UI_LIBS) -Wl,--export-dynamic

View File

@ -1,4 +1,3 @@
include vm/Config.unix
PLAF_DLL_OBJS += vm/os-genunix.o vm/os-linux.o vm/mvm-unix.o
CFLAGS += -export-dynamic
LIBS = -ldl -lm -lrt -lpthread $(X11_UI_LIBS)
LIBS = -ldl -lm -lrt -lpthread $(X11_UI_LIBS) -Wl,--export-dynamic

View File

@ -1,3 +0,0 @@
include vm/Config.linux
include vm/Config.ppc
CFLAGS += -mregnames

3
vm/Config.linux.ppc.32 Normal file
View File

@ -0,0 +1,3 @@
include vm/Config.linux
PLAF_DLL_OBJS += vm/cpu-ppc.linux.o
CFLAGS += -m32

3
vm/Config.linux.ppc.64 Normal file
View File

@ -0,0 +1,3 @@
include vm/Config.linux
PLAF_DLL_OBJS += vm/cpu-ppc.linux.o
CFLAGS += -m64

View File

@ -1,3 +1,3 @@
include vm/Config.macosx
include vm/Config.ppc
PLAF_DLL_OBJS += vm/cpu-ppc.macosx.o
CFLAGS += -arch ppc -force_cpusubtype_ALL

View File

@ -1,5 +1,4 @@
include vm/Config.unix
PLAF_DLL_OBJS += vm/os-genunix.o vm/os-netbsd.o vm/mvm-none.o
CFLAGS += -export-dynamic
LIBPATH = -L/usr/X11R7/lib -Wl,-rpath,/usr/X11R7/lib -L/usr/pkg/lib -Wl,-rpath,/usr/pkg/lib
LIBS = -lm -lrt -lssl -lcrypto $(X11_UI_LIBS)
LIBS = -lm -lrt -lssl -lcrypto $(X11_UI_LIBS) -Wl,--export-dynamic

View File

@ -2,5 +2,5 @@ include vm/Config.unix
PLAF_DLL_OBJS += vm/os-genunix.o vm/os-openbsd.o vm/mvm-unix.o
CC = egcc
CPP = eg++
CFLAGS += -export-dynamic -fno-inline-functions
LIBS = -L/usr/local/lib/ -lm $(X11_UI_LIBS) -lz -lssl -lcrypto -lpthread
CFLAGS += -fno-inline-functions
LIBS = -L/usr/local/lib/ -lm $(X11_UI_LIBS) -lz -lssl -lcrypto -lpthread -Wl,--export-dynamic

View File

@ -1 +0,0 @@
PLAF_DLL_OBJS += vm/cpu-ppc.o

View File

@ -1,6 +1,6 @@
include vm/Config.unix
PLAF_DLL_OBJS += vm/os-genunix.o vm/os-solaris.o
CFLAGS += -D_STDC_C99 -Drestrict="" -export-dynamic
CFLAGS += -D_STDC_C99 -Drestrict=""
LIBS += -ldl -lsocket -lnsl -lm -lrt -R/opt/PM/lib -R/opt/csw/lib \
-R/usr/local/lib -R/usr/sfw/lib -R/usr/X11R6/lib \
-R/opt/sfw/lib $(X11_UI_LIBS)
-R/opt/sfw/lib $(X11_UI_LIBS) -Wl,--export-dynamic

View File

@ -138,6 +138,29 @@ void factor_vm::primitive_dlsym()
ctx->push(allot_alien(ffi_dlsym(NULL,sym)));
}
/* look up a symbol in a native library */
void factor_vm::primitive_dlsym_raw()
{
data_root<object> library(ctx->pop(),this);
data_root<byte_array> name(ctx->pop(),this);
name.untag_check(this);
symbol_char *sym = name->data<symbol_char>();
if(to_boolean(library.value()))
{
dll *d = untag_check<dll>(library.value());
if(d->handle == NULL)
ctx->push(false_object);
else
ctx->push(allot_alien(ffi_dlsym_raw(d,sym)));
}
else
ctx->push(allot_alien(ffi_dlsym_raw(NULL,sym)));
}
/* close a native library handle */
void factor_vm::primitive_dlclose()
{

View File

@ -17,9 +17,18 @@ inline cell log2(cell x)
#else
asm ("bsr %1, %0;":"=r"(n):"r"(x));
#endif
#elif defined(FACTOR_PPC)
asm ("cntlzw %1, %0;":"=r"(n):"r"(x));
n = (31 - n);
#elif defined(FACTOR_PPC64)
#if defined(__GNUC__)
n = (63 - __builtin_clzll(x));
#else
#error Unsupported compiler
#endif
#elif defined(FACTOR_PPC32)
#if defined(__GNUC__)
n = (31 - __builtin_clz(x));
#else
#error Unsupported compiler
#endif
#else
#error Unsupported CPU
#endif
@ -38,6 +47,13 @@ inline cell rightmost_set_bit(cell x)
inline cell popcount(cell x)
{
#if defined(__GNUC__)
#ifdef FACTOR_64
return __builtin_popcountll(x);
#else
return __builtin_popcount(x);
#endif
#else
#ifdef FACTOR_64
u64 k1 = 0x5555555555555555ll;
u64 k2 = 0x3333333333333333ll;
@ -58,6 +74,7 @@ inline cell popcount(cell x)
x = (x * kf) >> ks; // returns 8 most significant bits of x + (x<<8) + (x<<16) + (x<<24) + ...
return x;
#endif
}
inline bool bitmap_p(u8 *bitmap, cell index)

View File

@ -140,7 +140,10 @@ void factor_vm::primitive_callback()
tagged<word> w(ctx->pop());
w.untag_check(this);
ctx->push(allot_alien(callbacks->add(w.value(),return_rewind)->entry_point()));
void* func = callbacks->add(w.value(),return_rewind)->entry_point();
CODE_TO_FUNCTION_POINTER_CALLBACK(this, func);
ctx->push(allot_alien(func));
}
}

View File

@ -11,7 +11,7 @@ keep the callstack in a GC root and use relative offsets */
template<typename Iterator> void factor_vm::iterate_callstack_object(callstack *stack_, Iterator &iterator)
{
data_root<callstack> stack(stack_,this);
fixnum frame_offset = untag_fixnum(stack->length) - sizeof(stack_frame);
fixnum frame_offset = factor::untag_fixnum(stack->length) - sizeof(stack_frame);
while(frame_offset >= 0)
{

View File

@ -160,8 +160,10 @@ cell factor_vm::compute_dlsym_address(array *literals, cell index)
dll *d = (to_boolean(library) ? untag<dll>(library) : NULL);
void* undefined_symbol = (void*)factor::undefined_symbol;
undefined_symbol = FUNCTION_CODE_POINTER(undefined_symbol);
if(d != NULL && !d->handle)
return (cell)factor::undefined_symbol;
return (cell)undefined_symbol;
switch(tagged<object>(symbol).type())
{
@ -173,7 +175,7 @@ cell factor_vm::compute_dlsym_address(array *literals, cell index)
if(sym)
return (cell)sym;
else
return (cell)factor::undefined_symbol;
return (cell)undefined_symbol;
}
case ARRAY_TYPE:
{
@ -186,14 +188,59 @@ cell factor_vm::compute_dlsym_address(array *literals, cell index)
if(sym)
return (cell)sym;
}
return (cell)factor::undefined_symbol;
return (cell)undefined_symbol;
}
default:
critical_error("Bad symbol specifier",symbol);
return (cell)factor::undefined_symbol;
return (cell)undefined_symbol;
}
}
#ifdef FACTOR_PPC
cell factor_vm::compute_dlsym_toc_address(array *literals, cell index)
{
cell symbol = array_nth(literals,index);
cell library = array_nth(literals,index + 1);
dll *d = (to_boolean(library) ? untag<dll>(library) : NULL);
void* undefined_toc = (void*)factor::undefined_symbol;
undefined_toc = FUNCTION_TOC_POINTER(undefined_toc);
if(d != NULL && !d->handle)
return (cell)undefined_toc;
switch(tagged<object>(symbol).type())
{
case BYTE_ARRAY_TYPE:
{
symbol_char *name = alien_offset(symbol);
void* toc = ffi_dlsym_toc(d,name);
if(toc)
return (cell)toc;
else
return (cell)undefined_toc;
}
case ARRAY_TYPE:
{
array *names = untag<array>(symbol);
for(cell i = 0; i < array_capacity(names); i++)
{
symbol_char *name = alien_offset(array_nth(names,i));
void *toc = ffi_dlsym_toc(d,name);
if(toc)
return (cell)toc;
}
return (cell)undefined_toc;
}
default:
critical_error("Bad symbol specifier",symbol);
return (cell)undefined_toc;
}
}
#endif
cell factor_vm::compute_vm_address(cell arg)
{
return (cell)this + untag_fixnum(arg);
@ -229,6 +276,11 @@ void factor_vm::store_external_address(instruction_operand op)
case RT_EXCEPTION_HANDLER:
op.store_value((cell)&factor::exception_handler);
break;
#endif
#ifdef FACTOR_PPC
case RT_DLSYM_TOC:
op.store_value(compute_dlsym_toc_address(parameters,index));
break;
#endif
default:
critical_error("Bad rel type in store_external_address()",op.rel_type());

View File

@ -1,73 +0,0 @@
#if defined(__APPLE__)
#define MANGLE(sym) _##sym
#define XX @
#else
#define MANGLE(sym) sym
#define XX ;
#endif
/* The returns and args are just for documentation */
#define DEF(returns,symbol,args) .globl MANGLE(symbol) XX \
MANGLE(symbol)
/* Thanks to Joshua Grams for this code.
On PowerPC processors, we must flush the instruction cache manually
after writing to the code heap. */
DEF(void,flush_icache,(void*, int)):
/* compute number of cache lines to flush */
add r4,r4,r3
/* align addr to next lower cache line boundary */
clrrwi r3,r3,5
/* then n_lines = (len + 0x1f) / 0x20 */
sub r4,r4,r3
addi r4,r4,0x1f
/* note '.' suffix */
srwi. r4,r4,5
/* if n_lines == 0, just return. */
beqlr
/* flush cache lines */
mtctr r4
/* for each line... */
0: dcbf 0,r3
sync
icbi 0,r3
addi r3,r3,0x20
bdnz 0b
/* finish up */
sync
isync
blr
DEF(void,get_ppc_fpu_env,(void*)):
mffs f0
stfd f0,0(r3)
blr
DEF(void,set_ppc_fpu_env,(const void*)):
lfd f0,0(r3)
mtfsf 0xff,f0
blr
DEF(void,get_ppc_vmx_env,(void*)):
mfvscr v0
subi r4,r1,16
li r5,0xf
andc r4,r4,r5
stvxl v0,0,r4
li r5,0xc
lwzx r6,r5,r4
stw r6,0(r3)
blr
DEF(void,set_ppc_vmx_env,(const void*)):
subi r4,r1,16
li r5,0xf
andc r4,r4,r5
li r5,0xc
lwz r6,0(r3)
stwx r6,r5,r4
lvxl v0,0,r4
mtvscr v0
blr

View File

@ -1,7 +1,11 @@
namespace factor
{
#define FACTOR_CPU_STRING "ppc"
#ifdef FACTOR_64
#define FACTOR_CPU_STRING "ppc.64"
#else
#define FACTOR_CPU_STRING "ppc.32"
#endif
#define CALLSTACK_BOTTOM(ctx) (stack_frame *)(ctx->callstack_seg->end - 32)
@ -16,36 +20,36 @@ static const fixnum xt_tail_pic_offset = 4;
inline static void check_call_site(cell return_address)
{
cell insn = *(cell *)return_address;
u32 insn = *(u32 *)return_address;
/* Check that absolute bit is 0 */
assert((insn & 0x2) == 0x0);
/* Check that instruction is branch */
assert((insn >> 26) == 0x12);
}
static const cell b_mask = 0x3fffffc;
static const u32 b_mask = 0x3fffffc;
inline static void *get_call_target(cell return_address)
{
return_address -= sizeof(cell);
return_address -= 4;
check_call_site(return_address);
cell insn = *(cell *)return_address;
cell unsigned_addr = (insn & b_mask);
fixnum signed_addr = (fixnum)(unsigned_addr << 6) >> 6;
u32 insn = *(u32 *)return_address;
u32 unsigned_addr = (insn & b_mask);
s32 signed_addr = (s32)(unsigned_addr << 6) >> 6;
return (void *)(signed_addr + return_address);
}
inline static void set_call_target(cell return_address, void *target)
{
return_address -= sizeof(cell);
return_address -= 4;
check_call_site(return_address);
cell insn = *(cell *)return_address;
u32 insn = *(u32 *)return_address;
fixnum relative_address = ((cell)target - return_address);
insn = ((insn & ~b_mask) | (relative_address & b_mask));
*(cell *)return_address = insn;
*(u32 *)return_address = insn;
/* Flush the cache line containing the call we just patched */
__asm__ __volatile__ ("icbi 0, %0\n" "sync\n"::"r" (return_address):);
@ -53,8 +57,8 @@ inline static void set_call_target(cell return_address, void *target)
inline static bool tail_call_site_p(cell return_address)
{
return_address -= sizeof(cell);
cell insn = *(cell *)return_address;
return_address -= 4;
u32 insn = *(u32 *)return_address;
return (insn & 0x1) == 0;
}

46
vm/cpu-ppc.linux.S Normal file
View File

@ -0,0 +1,46 @@
.file "cpu-ppc.linux.S"
.section ".text"
.align 2
.globl flush_icache
.type flush_icache, @function
flush_icache:
add 4,4,3 # end += ptr
#ifdef _ARCH_PPC64
clrrdi 3,3,5 # ptr &= ~0x1f
#else
clrrwi 3,3,5 # ptr &= ~0x1f
#endif
sub 4,4,3 # end -= aligned_ptr
addi 4,4,0x1f # end += 0x1f
#ifdef _ARCH_PPC64
srdi. 4,4,5 # end >>= 5, set cr
#else
srwi. 4,4,5 # end >>= 5, set cr
#endif
beqlr
# Loop over the buffer by cache line and flush the data cache.
mr 5,3
mtctr 4
loop1:
dcbst 0,5
addi 5,5,0x20
bdnz loop1
# Synchronize to ensure the cache line flushes are complete.
sync
# Loop over the buffer by cache line and flush the instruction cache.
mr 5,3
mtctr 4
loop2:
icbi 0,5
addi 5,5,0x20
bdnz loop2
# Clear instruction pipeline to force reloading of instructions.
isync
blr
.size flush_icache,.-flush_icache
.section .note.GNU-stack,"",@progbits

View File

@ -13,9 +13,10 @@ void factor_vm::c_to_factor(cell quot)
{
tagged<word> c_to_factor_word(special_objects[C_TO_FACTOR_WORD]);
code_block *c_to_factor_block = callbacks->add(c_to_factor_word.value(),0);
c_to_factor_func = (c_to_factor_func_type)c_to_factor_block->entry_point();
void* func = c_to_factor_block->entry_point();
CODE_TO_FUNCTION_POINTER_CALLBACK(this, func);
c_to_factor_func = (c_to_factor_func_type)func;
}
c_to_factor_func(quot);
}
@ -31,17 +32,26 @@ template<typename Func> Func factor_vm::get_entry_point(cell n)
void factor_vm::unwind_native_frames(cell quot, stack_frame *to)
{
get_entry_point<unwind_native_frames_func_type>(UNWIND_NATIVE_FRAMES_WORD)(quot,to);
tagged<word> entry_point_word(special_objects[UNWIND_NATIVE_FRAMES_WORD]);
void *func = entry_point_word->code->entry_point();
CODE_TO_FUNCTION_POINTER(func);
((unwind_native_frames_func_type)func)(quot,to);
}
cell factor_vm::get_fpu_state()
{
return get_entry_point<get_fpu_state_func_type>(GET_FPU_STATE_WORD)();
tagged<word> entry_point_word(special_objects[GET_FPU_STATE_WORD]);
void *func = entry_point_word->code->entry_point();
CODE_TO_FUNCTION_POINTER(func);
return ((get_fpu_state_func_type)func)();
}
void factor_vm::set_fpu_state(cell state)
{
get_entry_point<set_fpu_state_func_type>(GET_FPU_STATE_WORD)(state);
tagged<word> entry_point_word(special_objects[SET_FPU_STATE_WORD]);
void *func = entry_point_word->code->entry_point();
CODE_TO_FUNCTION_POINTER(func);
((set_fpu_state_func_type)func)(state);
}
}

View File

@ -179,8 +179,9 @@ void factor_vm::stop_factor()
char *factor_vm::factor_eval_string(char *string)
{
char *(*callback)(char *) = (char *(*)(char *))alien_offset(special_objects[OBJ_EVAL_CALLBACK]);
return callback(string);
void *func = alien_offset(special_objects[OBJ_EVAL_CALLBACK]);
CODE_TO_FUNCTION_POINTER(func);
return ((char *(*)(char *))func)(string);
}
void factor_vm::factor_eval_free(char *result)
@ -190,14 +191,16 @@ void factor_vm::factor_eval_free(char *result)
void factor_vm::factor_yield()
{
void (*callback)() = (void (*)())alien_offset(special_objects[OBJ_YIELD_CALLBACK]);
callback();
void *func = alien_offset(special_objects[OBJ_YIELD_CALLBACK]);
CODE_TO_FUNCTION_POINTER(func);
((void (*)())func)();
}
void factor_vm::factor_sleep(long us)
{
void (*callback)(long) = (void (*)(long))alien_offset(special_objects[OBJ_SLEEP_CALLBACK]);
callback(us);
void *func = alien_offset(special_objects[OBJ_SLEEP_CALLBACK]);
CODE_TO_FUNCTION_POINTER(func);
((void (*)(long))func)(us);
}
void factor_vm::start_standalone_factor(int argc, vm_char **argv)

View File

@ -9,12 +9,24 @@ instruction_operand::instruction_operand(relocation_entry rel_, code_block *comp
/* Load a 32-bit value from a PowerPC LIS/ORI sequence */
fixnum instruction_operand::load_value_2_2()
{
cell *ptr = (cell *)pointer;
u32 *ptr = (u32 *)pointer;
cell hi = (ptr[-2] & 0xffff);
cell lo = (ptr[-1] & 0xffff);
return hi << 16 | lo;
}
/* Load a 64-bit value from a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence */
fixnum instruction_operand::load_value_2_2_2_2()
{
u32 *ptr = (u32 *)pointer;
u64 hhi = (ptr[-5] & 0xffff);
u64 hlo = (ptr[-4] & 0xffff);
u64 lhi = (ptr[-2] & 0xffff);
u64 llo = (ptr[-1] & 0xffff);
u64 val = hhi << 48 | hlo << 32 | lhi << 16 | llo;
return (cell)val;
}
/* Load a value from a bitfield of a PowerPC instruction */
fixnum instruction_operand::load_value_masked(cell mask, cell bits, cell shift)
{
@ -37,10 +49,10 @@ fixnum instruction_operand::load_value(cell relative_to)
return load_value_2_2();
case RC_ABSOLUTE_PPC_2:
return load_value_masked(rel_absolute_ppc_2_mask,16,0);
case RC_RELATIVE_PPC_2:
return load_value_masked(rel_relative_ppc_2_mask,16,0) + relative_to - sizeof(cell);
case RC_RELATIVE_PPC_3:
return load_value_masked(rel_relative_ppc_3_mask,6,0) + relative_to - sizeof(cell);
case RC_RELATIVE_PPC_2_PC:
return load_value_masked(rel_relative_ppc_2_mask,16,0) + relative_to - 4;
case RC_RELATIVE_PPC_3_PC:
return load_value_masked(rel_relative_ppc_3_mask,6,0) + relative_to - 4;
case RC_RELATIVE_ARM_3:
return load_value_masked(rel_relative_arm_3_mask,6,2) + relative_to + sizeof(cell);
case RC_INDIRECT_ARM:
@ -51,6 +63,8 @@ fixnum instruction_operand::load_value(cell relative_to)
return *(u16 *)(pointer - sizeof(u16));
case RC_ABSOLUTE_1:
return *(u8 *)(pointer - sizeof(u8));
case RC_ABSOLUTE_PPC_2_2_2_2:
return load_value_2_2_2_2();
default:
critical_error("Bad rel class",rel.rel_class());
return 0;
@ -75,11 +89,22 @@ code_block *instruction_operand::load_code_block()
/* Store a 32-bit value into a PowerPC LIS/ORI sequence */
void instruction_operand::store_value_2_2(fixnum value)
{
cell *ptr = (cell *)pointer;
u32 *ptr = (u32 *)pointer;
ptr[-2] = ((ptr[-2] & ~0xffff) | ((value >> 16) & 0xffff));
ptr[-1] = ((ptr[-1] & ~0xffff) | (value & 0xffff));
}
/* Store a 64-bit value into a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence */
void instruction_operand::store_value_2_2_2_2(fixnum value)
{
u64 val = value;
u32 *ptr = (u32 *)pointer;
ptr[-5] = ((ptr[-5] & ~0xffff) | ((val >> 48) & 0xffff));
ptr[-4] = ((ptr[-4] & ~0xffff) | ((val >> 32) & 0xffff));
ptr[-2] = ((ptr[-2] & ~0xffff) | ((val >> 16) & 0xffff));
ptr[-1] = ((ptr[-1] & ~0xffff) | ((val >> 0) & 0xffff));
}
/* Store a value into a bitfield of a PowerPC instruction */
void instruction_operand::store_value_masked(fixnum value, cell mask, cell shift)
{
@ -108,11 +133,11 @@ void instruction_operand::store_value(fixnum absolute_value)
case RC_ABSOLUTE_PPC_2:
store_value_masked(absolute_value,rel_absolute_ppc_2_mask,0);
break;
case RC_RELATIVE_PPC_2:
store_value_masked(relative_value + sizeof(cell),rel_relative_ppc_2_mask,0);
case RC_RELATIVE_PPC_2_PC:
store_value_masked(relative_value + 4,rel_relative_ppc_2_mask,0);
break;
case RC_RELATIVE_PPC_3:
store_value_masked(relative_value + sizeof(cell),rel_relative_ppc_3_mask,0);
case RC_RELATIVE_PPC_3_PC:
store_value_masked(relative_value + 4,rel_relative_ppc_3_mask,0);
break;
case RC_RELATIVE_ARM_3:
store_value_masked(relative_value - sizeof(cell),rel_relative_arm_3_mask,2);
@ -129,6 +154,9 @@ void instruction_operand::store_value(fixnum absolute_value)
case RC_ABSOLUTE_1:
*(u8 *)(pointer - sizeof(u8)) = (u8)absolute_value;
break;
case RC_ABSOLUTE_PPC_2_2_2_2:
store_value_2_2_2_2(absolute_value);
break;
default:
critical_error("Bad rel class",rel.rel_class());
break;

View File

@ -30,7 +30,8 @@ enum relocation_type {
type since its used in a situation where relocation arguments cannot
be passed in, and so RT_DLSYM is inappropriate (Windows only) */
RT_EXCEPTION_HANDLER,
/* arg is a literal table index, holding a pair (symbol/dll) */
RT_DLSYM_TOC,
};
enum relocation_class {
@ -45,9 +46,9 @@ enum relocation_class {
/* absolute address in a PowerPC LWZ instruction */
RC_ABSOLUTE_PPC_2,
/* relative address in a PowerPC LWZ/STW/BC instruction */
RC_RELATIVE_PPC_2,
RC_RELATIVE_PPC_2_PC,
/* relative address in a PowerPC B/BL instruction */
RC_RELATIVE_PPC_3,
RC_RELATIVE_PPC_3_PC,
/* relative address in an ARM B/BL instruction */
RC_RELATIVE_ARM_3,
/* pointer to address in an ARM LDR/STR instruction */
@ -58,13 +59,15 @@ enum relocation_class {
RC_ABSOLUTE_2,
/* absolute address in a 1 byte location */
RC_ABSOLUTE_1,
/* absolute address in a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence */
RC_ABSOLUTE_PPC_2_2_2_2,
};
static const cell rel_absolute_ppc_2_mask = 0xffff;
static const cell rel_relative_ppc_2_mask = 0xfffc;
static const cell rel_relative_ppc_3_mask = 0x3fffffc;
static const cell rel_indirect_arm_mask = 0xfff;
static const cell rel_relative_arm_3_mask = 0xffffff;
static const cell rel_absolute_ppc_2_mask = 0x0000ffff;
static const cell rel_relative_ppc_2_mask = 0x0000fffc;
static const cell rel_relative_ppc_3_mask = 0x03fffffc;
static const cell rel_indirect_arm_mask = 0x00000fff;
static const cell rel_relative_arm_3_mask = 0x00ffffff;
/* code relocation table consists of a table of entries for each fixup */
struct relocation_entry {
@ -101,6 +104,7 @@ struct relocation_entry {
case RT_VM:
return 1;
case RT_DLSYM:
case RT_DLSYM_TOC:
return 2;
case RT_ENTRY_POINT:
case RT_ENTRY_POINT_PIC:
@ -150,6 +154,7 @@ struct instruction_operand {
}
fixnum load_value_2_2();
fixnum load_value_2_2_2_2();
fixnum load_value_masked(cell mask, cell bits, cell shift);
fixnum load_value(cell relative_to);
fixnum load_value();
@ -157,6 +162,7 @@ struct instruction_operand {
code_block *load_code_block();
void store_value_2_2(fixnum value);
void store_value_2_2_2_2(fixnum value);
void store_value_masked(fixnum value, cell mask, cell shift);
void store_value(fixnum value);
void store_code_block(code_block *compiled);

View File

@ -1,8 +1,13 @@
#ifndef __FACTOR_MASTER_H__
#define __FACTOR_MASTER_H__
#ifndef _THREAD_SAFE
#define _THREAD_SAFE
#endif
#ifndef _REENTRANT
#define _REENTRANT
#endif
#ifndef WINCE
#include <errno.h>
@ -21,6 +26,7 @@
#include <string.h>
#include <time.h>
#include <wchar.h>
#include <assert.h>
/* C++ headers */
#include <algorithm>
@ -31,7 +37,8 @@
#include <iostream>
#include <iomanip>
#define FACTOR_STRINGIZE(x) #x
#define FACTOR_STRINGIZE_I(x) #x
#define FACTOR_STRINGIZE(x) FACTOR_STRINGIZE_I(x)
/* Record compiler version */
#if defined(__clang__)
@ -54,7 +61,12 @@
#define FACTOR_64
#elif defined(i386) || defined(__i386) || defined(__i386__) || defined(_M_IX86)
#define FACTOR_X86
#elif (defined(__POWERPC__) || defined(__ppc__) || defined(_ARCH_PPC)) && (defined(__PPC64__) || defined(__64BIT__))
#define FACTOR_PPC64
#define FACTOR_PPC
#define FACTOR_64
#elif defined(__POWERPC__) || defined(__ppc__) || defined(_ARCH_PPC)
#define FACTOR_PPC32
#define FACTOR_PPC
#else
#error "Unsupported architecture"

View File

@ -8,3 +8,9 @@ extern "C" int getosreldate();
#endif
#define UAP_STACK_POINTER_TYPE __register_t
#define CODE_TO_FUNCTION_POINTER(code) (void)0
#define CODE_TO_FUNCTION_POINTER_CALLBACK(vm, code) (void)0
#define FUNCTION_CODE_POINTER(ptr) ptr
#define FUNCTION_TOC_POINTER(ptr) ptr
#define UAP_SET_TOC_POINTER(uap, ptr) (void)0

View File

@ -9,5 +9,11 @@ void flush_icache(cell start, cell len);
#define UAP_STACK_POINTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.arm_sp)
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.arm_pc)
#define UAP_STACK_POINTER_TYPE greg_t
#define UAP_SET_TOC_POINTER(uap, ptr) (void)0
#define CODE_TO_FUNCTION_POINTER(code) (void)0
#define CODE_TO_FUNCTION_POINTER_CALLBACK(vm, code) (void)0
#define FUNCTION_CODE_POINTER(ptr) ptr
#define FUNCTION_TOC_POINTER(ptr) ptr
}

39
vm/os-linux-ppc.32.hpp Normal file
View File

@ -0,0 +1,39 @@
#include <ucontext.h>
namespace factor
{
#define FRAME_RETURN_ADDRESS(frame,vm) *((void **)(vm->frame_successor(frame) + 1) + 1)
#define UAP_STACK_POINTER(ucontext) ((ucontext_t *)ucontext)->uc_mcontext.uc_regs->gregs[1]
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.uc_regs->gregs[32])
#define UAP_SET_TOC_POINTER(uap, ptr) (void)0
#define CODE_TO_FUNCTION_POINTER(code) (void)0
#define CODE_TO_FUNCTION_POINTER_CALLBACK(vm, code) (void)0
#define FUNCTION_CODE_POINTER(ptr) ptr
#define FUNCTION_TOC_POINTER(ptr) ptr
#define UAP_STACK_POINTER_TYPE unsigned long
inline static unsigned int uap_fpu_status(void *uap)
{
union {
double as_double;
unsigned int as_uint[2];
} tmp;
tmp.as_double = ((ucontext_t*) uap)->uc_mcontext.uc_regs->fpregs.fpscr;
return tmp.as_uint[1];
}
inline static void uap_clear_fpu_status(void *uap)
{
union {
double as_double;
unsigned int as_uint[2];
} tmp;
tmp.as_double = ((ucontext_t*) uap)->uc_mcontext.uc_regs->fpregs.fpscr;
tmp.as_uint[1] &= 0x0007f8ff;
((ucontext_t*) uap)->uc_mcontext.uc_regs->fpregs.fpscr = tmp.as_double;
}
}

50
vm/os-linux-ppc.64.hpp Normal file
View File

@ -0,0 +1,50 @@
#include <ucontext.h>
namespace factor
{
#define FRAME_RETURN_ADDRESS(frame,vm) *((void **)(vm->frame_successor(frame) + 1) + 2)
#define UAP_STACK_POINTER(ucontext) ((ucontext_t *)ucontext)->uc_mcontext.gp_regs[1]
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.gp_regs[32])
#define UAP_SET_TOC_POINTER(uap, ptr) (void)0
#define FACTOR_PPC_TOC 1
#define CODE_TO_FUNCTION_POINTER(code) \
void *desc[3]; \
code = fill_function_descriptor(desc, code)
#define CODE_TO_FUNCTION_POINTER_CALLBACK(vm, code) \
code = fill_function_descriptor(new void*[3], code); \
vm->function_descriptors.push_back((void **)code)
#define FUNCTION_CODE_POINTER(ptr) \
(function_descriptor_field((void *)ptr, 0))
#define FUNCTION_TOC_POINTER(ptr) \
(function_descriptor_field((void *)ptr, 1))
#define UAP_STACK_POINTER_TYPE unsigned long
inline static unsigned int uap_fpu_status(void *uap)
{
union {
double as_double;
unsigned int as_uint[2];
} tmp;
tmp.as_double = ((ucontext_t*) uap)->uc_mcontext.fp_regs[32];
return tmp.as_uint[1];
}
inline static void uap_clear_fpu_status(void *uap)
{
union {
double as_double;
unsigned int as_uint[2];
} tmp;
tmp.as_double = ((ucontext_t*) uap)->uc_mcontext.fp_regs[32];
tmp.as_uint[1] &= 0x0007f8ff;
((ucontext_t*) uap)->uc_mcontext.fp_regs[32] = tmp.as_double;
}
}

View File

@ -1,10 +0,0 @@
#include <ucontext.h>
namespace factor
{
#define FRAME_RETURN_ADDRESS(frame,vm) *((void **)(vm->frame_successor(frame) + 1) + 1)
#define UAP_STACK_POINTER(ucontext) ((ucontext_t *)ucontext)->uc_mcontext.uc_regs->gregs[PT_R1]
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.uc_regs->gregs[PT_NIP])
}

View File

@ -51,5 +51,12 @@ inline static void uap_clear_fpu_status(void *uap)
#define UAP_STACK_POINTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.gregs[7])
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.gregs[14])
#define UAP_SET_TOC_POINTER(uap, ptr) (void)0
#define CODE_TO_FUNCTION_POINTER(code) (void)0
#define CODE_TO_FUNCTION_POINTER_CALLBACK(vm, code) (void)0
#define FUNCTION_CODE_POINTER(ptr) ptr
#define FUNCTION_TOC_POINTER(ptr) ptr
#define UAP_STACK_POINTER_TYPE greg_t
}

View File

@ -19,5 +19,12 @@ inline static void uap_clear_fpu_status(void *uap)
#define UAP_STACK_POINTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.gregs[15])
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.gregs[16])
#define UAP_SET_TOC_POINTER(uap, ptr) (void)0
#define CODE_TO_FUNCTION_POINTER(code) (void)0
#define CODE_TO_FUNCTION_POINTER_CALLBACK(vm, code) (void)0
#define FUNCTION_CODE_POINTER(ptr) ptr
#define FUNCTION_TOC_POINTER(ptr) ptr
#define UAP_STACK_POINTER_TYPE greg_t
}

View File

@ -7,6 +7,4 @@ VM_C_API int inotify_init();
VM_C_API int inotify_add_watch(int fd, const char *name, u32 mask);
VM_C_API int inotify_rm_watch(int fd, u32 wd);
#define UAP_STACK_POINTER_TYPE greg_t
}

View File

@ -10,7 +10,13 @@ const char *vm_executable_path();
const char *default_image_path();
#define UAP_STACK_POINTER(ucontext) (((ucontext_t *)ucontext)->uc_stack.ss_sp)
#define UAP_SET_TOC_POINTER(uap, ptr) (void)0
#define UAP_STACK_POINTER_TYPE void*
#define UAP_STACK_POINTER_TYPE void *
#define CODE_TO_FUNCTION_POINTER(code) (void)0
#define CODE_TO_FUNCTION_POINTER_CALLBACK(vm, code) (void)0
#define FUNCTION_CODE_POINTER(ptr) ptr
#define FUNCTION_TOC_POINTER(ptr) ptr
}

View File

@ -3,3 +3,9 @@
#define UAP_PROGRAM_COUNTER(uap) _UC_MACHINE_PC((ucontext_t *)uap)
#define UAP_STACK_POINTER_TYPE __greg_t
#define UAP_SET_TOC_POINTER(uap, ptr) (void)0
#define CODE_TO_FUNCTION_POINTER(code) (void)0
#define CODE_TO_FUNCTION_POINTER_CALLBACK(vm, code) (void)0
#define FUNCTION_CODE_POINTER(ptr) ptr
#define FUNCTION_TOC_POINTER(ptr) ptr

View File

@ -1 +1,7 @@
#define UAP_STACK_POINTER_TYPE __register_t
#define UAP_SET_TOC_POINTER(uap, ptr) (void)0
#define CODE_TO_FUNCTION_POINTER(code) (void)0
#define CODE_TO_FUNCTION_POINTER_CALLBACK(vm, code) (void)0
#define FUNCTION_CODE_POINTER(ptr) ptr
#define FUNCTION_TOC_POINTER(ptr) ptr

View File

@ -6,4 +6,9 @@ namespace factor
#define UAP_STACK_POINTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.gregs[ESP])
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.gregs[EIP])
#define UAP_SET_TOC_POINTER(uap, ptr) (void)0
#define CODE_TO_FUNCTION_POINTER(code) (void)0
#define CODE_TO_FUNCTION_POINTER_CALLBACK(vm, code) (void)0
#define FUNCTION_CODE_POINTER(ptr) ptr
#define FUNCTION_TOC_POINTER(ptr) ptr
}

View File

@ -6,4 +6,9 @@ namespace factor
#define UAP_STACK_POINTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.gregs[RSP])
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.gregs[RIP])
#define UAP_SET_TOC_POINTER(uap, ptr) (void)0
#define CODE_TO_FUNCTION_POINTER(code) (void)0
#define CODE_TO_FUNCTION_POINTER_CALLBACK(vm, code) (void)0
#define FUNCTION_CODE_POINTER(ptr) ptr
#define FUNCTION_TOC_POINTER(ptr) ptr
}

View File

@ -47,12 +47,23 @@ void factor_vm::ffi_dlopen(dll *dll)
dll->handle = dlopen(alien_offset(dll->path), RTLD_LAZY);
}
void *factor_vm::ffi_dlsym_raw(dll *dll, symbol_char *symbol)
{
return dlsym(dll ? dll->handle : null_dll, symbol);
}
void *factor_vm::ffi_dlsym(dll *dll, symbol_char *symbol)
{
void *handle = (dll == NULL ? null_dll : dll->handle);
return dlsym(handle,symbol);
return FUNCTION_CODE_POINTER(ffi_dlsym_raw(dll, symbol));
}
#ifdef FACTOR_PPC
void *factor_vm::ffi_dlsym_toc(dll *dll, symbol_char *symbol)
{
return FUNCTION_TOC_POINTER(ffi_dlsym_raw(dll, symbol));
}
#endif
void factor_vm::ffi_dlclose(dll *dll)
{
if(dlclose(dll->handle))
@ -116,8 +127,8 @@ segment::~segment()
void factor_vm::dispatch_signal(void *uap, void (handler)())
{
UAP_STACK_POINTER(uap) = (UAP_STACK_POINTER_TYPE)fix_callstack_top((stack_frame *)UAP_STACK_POINTER(uap));
UAP_PROGRAM_COUNTER(uap) = (cell)handler;
UAP_PROGRAM_COUNTER(uap) = (cell)FUNCTION_CODE_POINTER(handler);
UAP_SET_TOC_POINTER(uap, (cell)FUNCTION_TOC_POINTER(handler));
ctx->callstack_top = (stack_frame *)UAP_STACK_POINTER(uap);
}
@ -194,6 +205,7 @@ void factor_vm::unix_init_signals()
sigaction_safe(SIGBUS,&memory_sigaction,NULL);
sigaction_safe(SIGSEGV,&memory_sigaction,NULL);
sigaction_safe(SIGTRAP,&memory_sigaction,NULL);
memset(&fpe_sigaction,0,sizeof(struct sigaction));
sigemptyset(&fpe_sigaction.sa_mask);

View File

@ -22,6 +22,11 @@ void *factor_vm::ffi_dlsym(dll *dll, symbol_char *symbol)
return (void *)GetProcAddress(dll ? (HMODULE)dll->handle : hFactorDll, symbol);
}
void *factor_vm::ffi_dlsym_raw(dll *dll, symbol_char *symbol)
{
return ffi_dlsym(dll, symbol);
}
void factor_vm::ffi_dlclose(dll *dll)
{
FreeLibrary((HMODULE)dll->handle);

View File

@ -75,4 +75,8 @@ VM_C_API LONG exception_handler(PEXCEPTION_RECORD e, void *frame, PCONTEXT c, vo
THREADHANDLE start_thread(void *(*start_routine)(void *),void *args);
inline static THREADHANDLE thread_id() { return GetCurrentThread(); }
#define CODE_TO_FUNCTION_POINTER(code) (void)0
#define CODE_TO_FUNCTION_POINTER_CALLBACK(vm, code) (void)0
#define FUNCTION_CODE_POINTER(ptr) ptr
#define FUNCTION_TOC_POINTER(ptr) ptr
}

View File

@ -71,8 +71,10 @@
#if defined(FACTOR_X86)
#include "os-linux-x86.32.hpp"
#elif defined(FACTOR_PPC)
#include "os-linux-ppc.hpp"
#elif defined(FACTOR_PPC64)
#include "os-linux-ppc.64.hpp"
#elif defined(FACTOR_PPC32)
#include "os-linux-ppc.32.hpp"
#elif defined(FACTOR_ARM)
#include "os-linux-arm.hpp"
#elif defined(FACTOR_AMD64)

View File

@ -57,6 +57,7 @@ namespace factor
_(dll_validp) \
_(dlopen) \
_(dlsym) \
_(dlsym_raw) \
_(double_bits) \
_(enable_gc_events) \
_(existsp) \

View File

@ -190,6 +190,10 @@ void quotation_jit::iterate_quotation()
#endif
parameter(obj.value());
parameter(false_object);
#ifdef FACTOR_PPC_TOC
parameter(obj.value());
parameter(false_object);
#endif
emit(parent->special_objects[JIT_PRIMITIVE]);
i++;

View File

@ -3,6 +3,22 @@
namespace factor
{
/* Fill in a PPC function descriptor */
void *fill_function_descriptor(void *ptr, void *code)
{
void **descriptor = (void **)ptr;
descriptor[0] = code;
descriptor[1] = NULL;
descriptor[2] = NULL;
return descriptor;
}
/* Get a field from a PPC function descriptor */
void *function_descriptor_field(void *ptr, size_t idx)
{
return ptr ? ((void **) ptr)[idx] : ptr;
}
/* If memory allocation fails, bail out */
vm_char *safe_strdup(const vm_char *str)
{

View File

@ -46,6 +46,9 @@ inline static void memset_cell(void *dst, cell pattern, size_t size)
#endif
}
void *fill_function_descriptor(void *ptr, void *code);
void *function_descriptor_field(void *ptr, size_t idx);
vm_char *safe_strdup(const vm_char *str);
cell read_cell_hex();
VM_C_API void *factor_memcpy(void *dst, void *src, size_t len);

View File

@ -27,6 +27,13 @@ factor_vm::~factor_vm()
delete signal_callstack_seg;
signal_callstack_seg = NULL;
}
std::list<void **>::const_iterator iter = function_descriptors.begin();
std::list<void **>::const_iterator end = function_descriptors.end();
while(iter != end)
{
delete [] *iter;
iter++;
}
}
}

View File

@ -34,6 +34,9 @@ struct factor_vm
/* Next callback ID */
int callback_id;
/* List of callback function descriptors for PPC */
std::list<void **> function_descriptors;
/* Pooling unused contexts to make context allocation cheaper */
std::list<context *> unused_contexts;
@ -525,6 +528,9 @@ struct factor_vm
void update_word_references(code_block *compiled, bool reset_inline_caches);
void undefined_symbol();
cell compute_dlsym_address(array *literals, cell index);
#ifdef FACTOR_PPC
cell compute_dlsym_toc_address(array *literals, cell index);
#endif
cell compute_vm_address(cell arg);
void store_external_address(instruction_operand op);
cell compute_here_address(cell arg, cell offset, code_block *compiled);
@ -603,6 +609,7 @@ struct factor_vm
void *alien_pointer();
void primitive_dlopen();
void primitive_dlsym();
void primitive_dlsym_raw();
void primitive_dlclose();
void primitive_dll_validp();
char *alien_offset(cell obj);
@ -678,6 +685,10 @@ struct factor_vm
void init_ffi();
void ffi_dlopen(dll *dll);
void *ffi_dlsym(dll *dll, symbol_char *symbol);
void *ffi_dlsym_raw(dll *dll, symbol_char *symbol);
#ifdef FACTOR_PPC
void *ffi_dlsym_toc(dll *dll, symbol_char *symbol);
#endif
void ffi_dlclose(dll *dll);
void c_to_factor_toplevel(cell quot);
void init_signals();