diff --git a/basis/compiler/cfg/builder/builder.factor b/basis/compiler/cfg/builder/builder.factor index 7bad44f7a6..fdc0032a10 100755 --- a/basis/compiler/cfg/builder/builder.factor +++ b/basis/compiler/cfg/builder/builder.factor @@ -21,8 +21,6 @@ IN: compiler.cfg.builder ! Convert tree SSA IR to CFG SSA IR. -: stop-iterating ( -- next ) end-basic-block f ; - SYMBOL: procedures SYMBOL: current-word SYMBOL: current-label @@ -211,7 +209,7 @@ M: #dispatch emit-node ! #call M: #call emit-node dup word>> dup "intrinsic" word-prop - [ emit-intrinsic iterate-next ] [ nip emit-call ] if ; + [ emit-intrinsic ] [ nip emit-call ] if ; ! #call-recursive M: #call-recursive emit-node label>> id>> emit-call ; diff --git a/basis/compiler/cfg/def-use/def-use.factor b/basis/compiler/cfg/def-use/def-use.factor index 7584931cf7..7e97961eb3 100644 --- a/basis/compiler/cfg/def-use/def-use.factor +++ b/basis/compiler/cfg/def-use/def-use.factor @@ -34,6 +34,7 @@ M: ##compare-imm-branch uses-vregs src1>> 1array ; M: ##dispatch uses-vregs src>> 1array ; M: ##alien-getter uses-vregs src>> 1array ; M: ##alien-setter uses-vregs [ src>> ] [ value>> ] bi 2array ; +M: ##fixnum-overflow uses-vregs [ src1>> ] [ src2>> ] bi 2array ; M: _conditional-branch uses-vregs [ src1>> ] [ src2>> ] bi 2array ; M: _compare-imm-branch uses-vregs src1>> 1array ; M: insn uses-vregs drop f ; @@ -43,6 +44,7 @@ UNION: vreg-insn ##write-barrier ##dispatch ##effect +##fixnum-overflow ##conditional-branch ##compare-imm-branch _conditional-branch diff --git a/basis/compiler/cfg/instructions/instructions.factor b/basis/compiler/cfg/instructions/instructions.factor index ce1f6b7e85..9e82851c12 100644 --- a/basis/compiler/cfg/instructions/instructions.factor +++ b/basis/compiler/cfg/instructions/instructions.factor @@ -92,6 +92,15 @@ INSN: ##shr-imm < ##binary-imm ; INSN: ##sar-imm < ##binary-imm ; INSN: ##not < ##unary ; +! Overflowing arithmetic +TUPLE: ##fixnum-overflow < insn src1 src2 ; +INSN: ##fixnum-add < ##fixnum-overflow ; +INSN: ##fixnum-add-tail < ##fixnum-overflow ; +INSN: ##fixnum-sub < ##fixnum-overflow ; +INSN: ##fixnum-sub-tail < ##fixnum-overflow ; +INSN: ##fixnum-mul < ##fixnum-overflow ; +INSN: ##fixnum-mul-tail < ##fixnum-overflow ; + : ##tag-fixnum ( dst src -- ) tag-bits get ##shl-imm ; inline : ##untag-fixnum ( dst src -- ) tag-bits get ##sar-imm ; inline diff --git a/basis/compiler/cfg/intrinsics/fixnum/fixnum.factor b/basis/compiler/cfg/intrinsics/fixnum/fixnum.factor index 04c9097725..68ee7489f8 100644 --- a/basis/compiler/cfg/intrinsics/fixnum/fixnum.factor +++ b/basis/compiler/cfg/intrinsics/fixnum/fixnum.factor @@ -3,10 +3,22 @@ USING: sequences accessors layouts kernel math namespaces combinators fry locals compiler.tree.propagation.info -compiler.cfg.stacks compiler.cfg.hats compiler.cfg.instructions -compiler.cfg.utilities ; +compiler.cfg.hats +compiler.cfg.stacks +compiler.cfg.iterator +compiler.cfg.instructions +compiler.cfg.utilities +compiler.cfg.registers ; IN: compiler.cfg.intrinsics.fixnum +: emit-both-fixnums? ( -- ) + D 0 ^^peek + D 1 ^^peek + ^^or + tag-mask get ^^and-imm + 0 cc= ^^compare-imm + ds-push ; + : (emit-fixnum-imm-op) ( infos insn -- dst ) ds-drop [ ds-pop ] @@ -64,3 +76,16 @@ IN: compiler.cfg.intrinsics.fixnum : emit-fixnum>bignum ( -- ) ds-pop ^^untag-fixnum ^^integer>bignum ds-push ; + +: emit-fixnum-overflow-op ( quot quot-tail -- next ) + [ 2inputs 1 ##inc-d ] 2dip + tail-call? [ + ##epilogue + nip call + stop-iterating + ] [ + drop call + ##branch + begin-basic-block + iterate-next + ] if ; inline diff --git a/basis/compiler/cfg/intrinsics/intrinsics.factor b/basis/compiler/cfg/intrinsics/intrinsics.factor index ef1cde337a..6c6c2955c9 100644 --- a/basis/compiler/cfg/intrinsics/intrinsics.factor +++ b/basis/compiler/cfg/intrinsics/intrinsics.factor @@ -8,7 +8,8 @@ compiler.cfg.intrinsics.alien compiler.cfg.intrinsics.allot compiler.cfg.intrinsics.fixnum compiler.cfg.intrinsics.float -compiler.cfg.intrinsics.slots ; +compiler.cfg.intrinsics.slots +compiler.cfg.iterator ; QUALIFIED: kernel QUALIFIED: arrays QUALIFIED: byte-arrays @@ -22,6 +23,9 @@ IN: compiler.cfg.intrinsics { kernel.private:tag + math.private:both-fixnums? + math.private:fixnum+ + math.private:fixnum- math.private:fixnum+fast math.private:fixnum-fast math.private:fixnum-bitand @@ -85,60 +89,67 @@ IN: compiler.cfg.intrinsics alien.accessors:set-alien-double } [ t "intrinsic" set-word-prop ] each ; -: emit-intrinsic ( node word -- ) +: enable-fixnum*-intrinsic ( -- ) + \ math.private:fixnum* t "intrinsic" set-word-prop ; + +: emit-intrinsic ( node word -- node/f ) { - { \ kernel.private:tag [ drop emit-tag ] } - { \ math.private:fixnum+fast [ [ ^^add ] [ ^^add-imm ] emit-fixnum-op ] } - { \ math.private:fixnum-fast [ [ ^^sub ] [ ^^sub-imm ] emit-fixnum-op ] } - { \ math.private:fixnum-bitand [ [ ^^and ] [ ^^and-imm ] emit-fixnum-op ] } - { \ math.private:fixnum-bitor [ [ ^^or ] [ ^^or-imm ] emit-fixnum-op ] } - { \ math.private:fixnum-bitxor [ [ ^^xor ] [ ^^xor-imm ] emit-fixnum-op ] } - { \ math.private:fixnum-shift-fast [ emit-fixnum-shift-fast ] } - { \ math.private:fixnum-bitnot [ drop emit-fixnum-bitnot ] } - { \ math.private:fixnum*fast [ emit-fixnum*fast ] } - { \ math.private:fixnum< [ cc< emit-fixnum-comparison ] } - { \ math.private:fixnum<= [ cc<= emit-fixnum-comparison ] } - { \ math.private:fixnum>= [ cc>= emit-fixnum-comparison ] } - { \ math.private:fixnum> [ cc> emit-fixnum-comparison ] } - { \ kernel:eq? [ cc= emit-fixnum-comparison ] } - { \ math.private:bignum>fixnum [ drop emit-bignum>fixnum ] } - { \ math.private:fixnum>bignum [ drop emit-fixnum>bignum ] } - { \ math.private:float+ [ drop [ ^^add-float ] emit-float-op ] } - { \ math.private:float- [ drop [ ^^sub-float ] emit-float-op ] } - { \ math.private:float* [ drop [ ^^mul-float ] emit-float-op ] } - { \ math.private:float/f [ drop [ ^^div-float ] emit-float-op ] } - { \ math.private:float< [ drop cc< emit-float-comparison ] } - { \ math.private:float<= [ drop cc<= emit-float-comparison ] } - { \ math.private:float>= [ drop cc>= emit-float-comparison ] } - { \ math.private:float> [ drop cc> emit-float-comparison ] } - { \ math.private:float= [ drop cc= emit-float-comparison ] } - { \ math.private:float>fixnum [ drop emit-float>fixnum ] } - { \ math.private:fixnum>float [ drop emit-fixnum>float ] } - { \ slots.private:slot [ emit-slot ] } - { \ slots.private:set-slot [ emit-set-slot ] } - { \ strings.private:string-nth [ drop emit-string-nth ] } - { \ classes.tuple.private: [ emit- ] } - { \ arrays: [ emit- ] } - { \ byte-arrays: [ emit- ] } - { \ math.private: [ emit-simple-allot ] } - { \ math.private: [ emit-simple-allot ] } - { \ kernel: [ emit-simple-allot ] } - { \ alien.accessors:alien-unsigned-1 [ 1 emit-alien-unsigned-getter ] } - { \ alien.accessors:set-alien-unsigned-1 [ 1 emit-alien-integer-setter ] } - { \ alien.accessors:alien-signed-1 [ 1 emit-alien-signed-getter ] } - { \ alien.accessors:set-alien-signed-1 [ 1 emit-alien-integer-setter ] } - { \ alien.accessors:alien-unsigned-2 [ 2 emit-alien-unsigned-getter ] } - { \ alien.accessors:set-alien-unsigned-2 [ 2 emit-alien-integer-setter ] } - { \ alien.accessors:alien-signed-2 [ 2 emit-alien-signed-getter ] } - { \ alien.accessors:set-alien-signed-2 [ 2 emit-alien-integer-setter ] } - { \ alien.accessors:alien-unsigned-4 [ 4 emit-alien-unsigned-getter ] } - { \ alien.accessors:set-alien-unsigned-4 [ 4 emit-alien-integer-setter ] } - { \ alien.accessors:alien-signed-4 [ 4 emit-alien-signed-getter ] } - { \ alien.accessors:set-alien-signed-4 [ 4 emit-alien-integer-setter ] } - { \ alien.accessors:alien-cell [ emit-alien-cell-getter ] } - { \ alien.accessors:set-alien-cell [ emit-alien-cell-setter ] } - { \ alien.accessors:alien-float [ single-float-regs emit-alien-float-getter ] } - { \ alien.accessors:set-alien-float [ single-float-regs emit-alien-float-setter ] } - { \ alien.accessors:alien-double [ double-float-regs emit-alien-float-getter ] } - { \ alien.accessors:set-alien-double [ double-float-regs emit-alien-float-setter ] } + { \ kernel.private:tag [ drop emit-tag iterate-next ] } + { \ math.private:both-fixnums? [ drop emit-both-fixnums? iterate-next ] } + { \ math.private:fixnum+ [ drop [ ##fixnum-add ] [ ##fixnum-add-tail ] emit-fixnum-overflow-op ] } + { \ math.private:fixnum- [ drop [ ##fixnum-sub ] [ ##fixnum-sub-tail ] emit-fixnum-overflow-op ] } + { \ math.private:fixnum* [ drop [ ##fixnum-mul ] [ ##fixnum-mul-tail ] emit-fixnum-overflow-op ] } + { \ math.private:fixnum+fast [ [ ^^add ] [ ^^add-imm ] emit-fixnum-op iterate-next ] } + { \ math.private:fixnum-fast [ [ ^^sub ] [ ^^sub-imm ] emit-fixnum-op iterate-next ] } + { \ math.private:fixnum-bitand [ [ ^^and ] [ ^^and-imm ] emit-fixnum-op iterate-next ] } + { \ math.private:fixnum-bitor [ [ ^^or ] [ ^^or-imm ] emit-fixnum-op iterate-next ] } + { \ math.private:fixnum-bitxor [ [ ^^xor ] [ ^^xor-imm ] emit-fixnum-op iterate-next ] } + { \ math.private:fixnum-shift-fast [ emit-fixnum-shift-fast iterate-next ] } + { \ math.private:fixnum-bitnot [ drop emit-fixnum-bitnot iterate-next ] } + { \ math.private:fixnum*fast [ emit-fixnum*fast iterate-next ] } + { \ math.private:fixnum< [ cc< emit-fixnum-comparison iterate-next ] } + { \ math.private:fixnum<= [ cc<= emit-fixnum-comparison iterate-next ] } + { \ math.private:fixnum>= [ cc>= emit-fixnum-comparison iterate-next ] } + { \ math.private:fixnum> [ cc> emit-fixnum-comparison iterate-next ] } + { \ kernel:eq? [ cc= emit-fixnum-comparison iterate-next ] } + { \ math.private:bignum>fixnum [ drop emit-bignum>fixnum iterate-next ] } + { \ math.private:fixnum>bignum [ drop emit-fixnum>bignum iterate-next ] } + { \ math.private:float+ [ drop [ ^^add-float ] emit-float-op iterate-next ] } + { \ math.private:float- [ drop [ ^^sub-float ] emit-float-op iterate-next ] } + { \ math.private:float* [ drop [ ^^mul-float ] emit-float-op iterate-next ] } + { \ math.private:float/f [ drop [ ^^div-float ] emit-float-op iterate-next ] } + { \ math.private:float< [ drop cc< emit-float-comparison iterate-next ] } + { \ math.private:float<= [ drop cc<= emit-float-comparison iterate-next ] } + { \ math.private:float>= [ drop cc>= emit-float-comparison iterate-next ] } + { \ math.private:float> [ drop cc> emit-float-comparison iterate-next ] } + { \ math.private:float= [ drop cc= emit-float-comparison iterate-next ] } + { \ math.private:float>fixnum [ drop emit-float>fixnum iterate-next ] } + { \ math.private:fixnum>float [ drop emit-fixnum>float iterate-next ] } + { \ slots.private:slot [ emit-slot iterate-next ] } + { \ slots.private:set-slot [ emit-set-slot iterate-next ] } + { \ strings.private:string-nth [ drop emit-string-nth iterate-next ] } + { \ classes.tuple.private: [ emit- iterate-next ] } + { \ arrays: [ emit- iterate-next ] } + { \ byte-arrays: [ emit- iterate-next ] } + { \ math.private: [ emit-simple-allot iterate-next ] } + { \ math.private: [ emit-simple-allot iterate-next ] } + { \ kernel: [ emit-simple-allot iterate-next ] } + { \ alien.accessors:alien-unsigned-1 [ 1 emit-alien-unsigned-getter iterate-next ] } + { \ alien.accessors:set-alien-unsigned-1 [ 1 emit-alien-integer-setter iterate-next ] } + { \ alien.accessors:alien-signed-1 [ 1 emit-alien-signed-getter iterate-next ] } + { \ alien.accessors:set-alien-signed-1 [ 1 emit-alien-integer-setter iterate-next ] } + { \ alien.accessors:alien-unsigned-2 [ 2 emit-alien-unsigned-getter iterate-next ] } + { \ alien.accessors:set-alien-unsigned-2 [ 2 emit-alien-integer-setter iterate-next ] } + { \ alien.accessors:alien-signed-2 [ 2 emit-alien-signed-getter iterate-next ] } + { \ alien.accessors:set-alien-signed-2 [ 2 emit-alien-integer-setter iterate-next ] } + { \ alien.accessors:alien-unsigned-4 [ 4 emit-alien-unsigned-getter iterate-next ] } + { \ alien.accessors:set-alien-unsigned-4 [ 4 emit-alien-integer-setter iterate-next ] } + { \ alien.accessors:alien-signed-4 [ 4 emit-alien-signed-getter iterate-next ] } + { \ alien.accessors:set-alien-signed-4 [ 4 emit-alien-integer-setter iterate-next ] } + { \ alien.accessors:alien-cell [ emit-alien-cell-getter iterate-next ] } + { \ alien.accessors:set-alien-cell [ emit-alien-cell-setter iterate-next ] } + { \ alien.accessors:alien-float [ single-float-regs emit-alien-float-getter iterate-next ] } + { \ alien.accessors:set-alien-float [ single-float-regs emit-alien-float-setter iterate-next ] } + { \ alien.accessors:alien-double [ double-float-regs emit-alien-float-getter iterate-next ] } + { \ alien.accessors:set-alien-double [ double-float-regs emit-alien-float-setter iterate-next ] } } case ; diff --git a/basis/compiler/cfg/stack-frame/stack-frame.factor b/basis/compiler/cfg/stack-frame/stack-frame.factor index ec9ffaba49..d545b6d15c 100644 --- a/basis/compiler/cfg/stack-frame/stack-frame.factor +++ b/basis/compiler/cfg/stack-frame/stack-frame.factor @@ -34,6 +34,12 @@ M: insn compute-stack-frame* \ _gc t frame-required? set-word-prop \ _spill t frame-required? set-word-prop +\ ##fixnum-add t frame-required? set-word-prop +\ ##fixnum-sub t frame-required? set-word-prop +\ ##fixnum-mul t frame-required? set-word-prop +\ ##fixnum-add-tail f frame-required? set-word-prop +\ ##fixnum-sub-tail f frame-required? set-word-prop +\ ##fixnum-mul-tail f frame-required? set-word-prop : compute-stack-frame ( insns -- ) frame-required? off diff --git a/basis/compiler/cfg/utilities/utilities.factor b/basis/compiler/cfg/utilities/utilities.factor index cef14d06e4..99a138a763 100644 --- a/basis/compiler/cfg/utilities/utilities.factor +++ b/basis/compiler/cfg/utilities/utilities.factor @@ -33,5 +33,7 @@ IN: compiler.cfg.utilities building off basic-block off ; +: stop-iterating ( -- next ) end-basic-block f ; + : emit-primitive ( node -- ) word>> ##call ##branch begin-basic-block ; diff --git a/basis/compiler/cfg/value-numbering/propagate/propagate.factor b/basis/compiler/cfg/value-numbering/propagate/propagate.factor index a3c9725838..d5c9830c0b 100644 --- a/basis/compiler/cfg/value-numbering/propagate/propagate.factor +++ b/basis/compiler/cfg/value-numbering/propagate/propagate.factor @@ -62,4 +62,8 @@ M: ##compare-imm-branch propagate M: ##dispatch propagate [ resolve ] change-src ; +M: ##fixnum-overflow propagate + [ resolve ] change-src1 + [ resolve ] change-src2 ; + M: insn propagate ; diff --git a/basis/compiler/codegen/codegen.factor b/basis/compiler/codegen/codegen.factor index bfb47ba330..b66b6a11c7 100644 --- a/basis/compiler/codegen/codegen.factor +++ b/basis/compiler/codegen/codegen.factor @@ -156,6 +156,16 @@ M: ##shr-imm generate-insn dst/src1/src2 %shr-imm ; M: ##sar-imm generate-insn dst/src1/src2 %sar-imm ; M: ##not generate-insn dst/src %not ; +: src1/src2 ( insn -- src1 src2 ) + [ src1>> register ] [ src2>> register ] bi ; inline + +M: ##fixnum-add generate-insn src1/src2 %fixnum-add ; +M: ##fixnum-add-tail generate-insn src1/src2 %fixnum-add-tail ; +M: ##fixnum-sub generate-insn src1/src2 %fixnum-sub ; +M: ##fixnum-sub-tail generate-insn src1/src2 %fixnum-sub-tail ; +M: ##fixnum-mul generate-insn src1/src2 %fixnum-mul ; +M: ##fixnum-mul-tail generate-insn src1/src2 %fixnum-mul-tail ; + : dst/src/temp ( insn -- dst src temp ) [ dst/src ] [ temp>> register ] bi ; inline diff --git a/basis/compiler/tests/codegen.factor b/basis/compiler/tests/codegen.factor index dd6f99ead1..eb818972fc 100644 --- a/basis/compiler/tests/codegen.factor +++ b/basis/compiler/tests/codegen.factor @@ -254,3 +254,10 @@ TUPLE: id obj ; { 1 2 3 4 } [ { array } declare 2 length ] compile-call ] unit-test + +! Oops with new intrinsics +: fixnum-overflow-control-flow-test ( a b -- c ) + [ 1 fixnum- ] [ 2 fixnum- ] if 3 fixnum+fast ; + +[ 3 ] [ 1 t fixnum-overflow-control-flow-test ] unit-test +[ 2 ] [ 1 f fixnum-overflow-control-flow-test ] unit-test diff --git a/basis/compiler/tree/debugger/debugger.factor b/basis/compiler/tree/debugger/debugger.factor index a1d8773484..e9bf77b188 100644 --- a/basis/compiler/tree/debugger/debugger.factor +++ b/basis/compiler/tree/debugger/debugger.factor @@ -93,7 +93,7 @@ M: #shuffle node>quot [ drop "COMPLEX SHUFFLE" , ] } cond ; -M: #push node>quot literal>> , ; +M: #push node>quot literal>> literalize , ; M: #call node>quot word>> , ; diff --git a/basis/cpu/architecture/architecture.factor b/basis/cpu/architecture/architecture.factor index 3d6195d9eb..2fdad0132a 100644 --- a/basis/cpu/architecture/architecture.factor +++ b/basis/cpu/architecture/architecture.factor @@ -77,6 +77,13 @@ HOOK: %shr-imm cpu ( dst src1 src2 -- ) HOOK: %sar-imm cpu ( dst src1 src2 -- ) HOOK: %not cpu ( dst src -- ) +HOOK: %fixnum-add cpu ( src1 src2 -- ) +HOOK: %fixnum-add-tail cpu ( src1 src2 -- ) +HOOK: %fixnum-sub cpu ( src1 src2 -- ) +HOOK: %fixnum-sub-tail cpu ( src1 src2 -- ) +HOOK: %fixnum-mul cpu ( src1 src2 -- ) +HOOK: %fixnum-mul-tail cpu ( src1 src2 -- ) + HOOK: %integer>bignum cpu ( dst src temp -- ) HOOK: %bignum>integer cpu ( dst src temp -- ) diff --git a/basis/cpu/ppc/bootstrap.factor b/basis/cpu/ppc/bootstrap.factor index 6b1a1014ee..d22ff4d615 100644 --- a/basis/cpu/ppc/bootstrap.factor +++ b/basis/cpu/ppc/bootstrap.factor @@ -327,6 +327,18 @@ big-endian on \ BLT \ fixnum< define-jit-compare ! Math +[ + 3 ds-reg 0 LWZ + 4 ds-reg -4 LWZ + 3 3 4 OR + 3 3 tag-mask get ANDI + \ f tag-number 4 LI + 0 3 0 CMPI + 2 BNE + 1 tag-fixnum 4 LI + 4 ds-reg 4 STWU +] f f f \ both-fixnums? define-sub-primitive + : jit-math ( insn -- ) 3 ds-reg 0 LWZ 4 ds-reg -4 LWZU diff --git a/basis/cpu/ppc/ppc.factor b/basis/cpu/ppc/ppc.factor index 6a42ffdf77..aa9126fef0 100644 --- a/basis/cpu/ppc/ppc.factor +++ b/basis/cpu/ppc/ppc.factor @@ -17,6 +17,7 @@ IN: cpu.ppc ! f30, f31: float scratch enable-float-intrinsics +enable-fixnum*-intrinsic << \ ##integer>float t frame-required? set-word-prop \ ##float>integer t frame-required? set-word-prop >> @@ -37,6 +38,9 @@ M: ppc %load-immediate ( reg n -- ) swap LOAD ; M: ppc %load-indirect ( reg obj -- ) [ 0 swap LOAD32 ] [ rc-absolute-ppc-2/2 rel-immediate ] bi* ; +: %load-dlsym ( symbol dll register -- ) + 0 swap LOAD32 rc-absolute-ppc-2/2 rel-dlsym ; + : ds-reg 29 ; inline : rs-reg 30 ; inline @@ -164,6 +168,91 @@ M: ppc %shr-imm swapd SRWI ; M: ppc %sar-imm SRAWI ; M: ppc %not NOT ; +: %alien-invoke-tail ( func dll -- ) + scratch-reg %load-dlsym scratch-reg MTCTR BCTR ; + +:: exchange-regs ( r1 r2 -- ) + scratch-reg r1 MR + r1 r2 MR + r2 scratch-reg MR ; + +: ?MR ( r1 r2 -- ) 2dup = [ 2drop ] [ MR ] if ; + +:: move>args ( src1 src2 -- ) + { + { [ src1 4 = ] [ 3 src2 ?MR 3 4 exchange-regs ] } + { [ src1 3 = ] [ 4 src2 ?MR ] } + { [ src2 3 = ] [ 4 src1 ?MR 3 4 exchange-regs ] } + { [ src2 4 = ] [ 3 src1 ?MR ] } + [ 3 src1 MR 4 src2 MR ] + } cond ; + +:: overflow-template ( src1 src2 insn func -- ) + "no-overflow" define-label + 0 0 LI + 0 MTXER + scratch-reg src2 src1 insn call + scratch-reg ds-reg 0 STW + "no-overflow" get BNO + src2 src1 move>args + %prepare-alien-invoke + func f %alien-invoke + "no-overflow" resolve-label ; inline + +:: overflow-template-tail ( src1 src2 insn func -- ) + "overflow" define-label + 0 0 LI + 0 MTXER + scratch-reg src2 src1 insn call + "overflow" get BO + scratch-reg ds-reg 0 STW + BLR + "overflow" resolve-label + src2 src1 move>args + %prepare-alien-invoke + func f %alien-invoke-tail ; + +M: ppc %fixnum-add ( src1 src2 -- ) + [ ADDO. ] "overflow_fixnum_add" overflow-template ; + +M: ppc %fixnum-add-tail ( src1 src2 -- ) + [ ADDO. ] "overflow_fixnum_add" overflow-template-tail ; + +M: ppc %fixnum-sub ( src1 src2 -- ) + [ SUBFO. ] "overflow_fixnum_subtract" overflow-template ; + +M: ppc %fixnum-sub-tail ( src1 src2 -- ) + [ SUBFO. ] "overflow_fixnum_subtract" overflow-template-tail ; + +M:: ppc %fixnum-mul ( src1 src2 -- ) + "no-overflow" define-label + 0 0 LI + 0 MTXER + src1 src1 tag-bits get SRAWI + scratch-reg src1 src2 MULLWO. + scratch-reg ds-reg 0 STW + "no-overflow" get BNO + src2 src2 tag-bits get SRAWI + src1 src2 move>args + %prepare-alien-invoke + "overflow_fixnum_multiply" f %alien-invoke + "no-overflow" resolve-label ; + +M:: ppc %fixnum-mul-tail ( src1 src2 -- ) + "overflow" define-label + 0 0 LI + 0 MTXER + src1 src1 tag-bits get SRAWI + scratch-reg src1 src2 MULLWO. + "overflow" get BO + scratch-reg ds-reg 0 STW + BLR + "overflow" resolve-label + src2 src2 tag-bits get SRAWI + src1 src2 move>args + %prepare-alien-invoke + "overflow_fixnum_multiply" f %alien-invoke-tail ; + : bignum@ ( n -- offset ) cells bignum tag-number - ; inline M:: ppc %integer>bignum ( dst src temp -- ) @@ -318,9 +407,6 @@ M: ppc %set-alien-cell swap 0 STW ; M: ppc %set-alien-float swap 0 STFS ; M: ppc %set-alien-double swap 0 STFD ; -: %load-dlsym ( symbol dll register -- ) - 0 swap LOAD32 rc-absolute-ppc-2/2 rel-dlsym ; - : load-zone-ptr ( reg -- ) [ "nursery" f ] dip %load-dlsym ; @@ -538,11 +624,11 @@ M: ppc %prepare-alien-invoke #! Save Factor stack pointers in case the C code calls a #! callback which does a GC, which must reliably trace #! all roots. - "stack_chain" f 11 %load-dlsym - 11 11 0 LWZ - 1 11 0 STW - ds-reg 11 8 STW - rs-reg 11 12 STW ; + "stack_chain" f scratch-reg %load-dlsym + scratch-reg scratch-reg 0 LWZ + 1 scratch-reg 0 STW + ds-reg scratch-reg 8 STW + rs-reg scratch-reg 12 STW ; M: ppc %alien-invoke ( symbol dll -- ) 11 %load-dlsym 11 MTLR BLRL ; diff --git a/basis/cpu/x86/32/32.factor b/basis/cpu/x86/32/32.factor old mode 100644 new mode 100755 index 217047e4b6..9fd1330757 --- a/basis/cpu/x86/32/32.factor +++ b/basis/cpu/x86/32/32.factor @@ -23,8 +23,8 @@ M: x86.32 machine-registers M: x86.32 ds-reg ESI ; M: x86.32 rs-reg EDI ; M: x86.32 stack-reg ESP ; -M: x86.32 temp-reg-1 EAX ; -M: x86.32 temp-reg-2 ECX ; +M: x86.32 temp-reg-1 ECX ; +M: x86.32 temp-reg-2 EDX ; M:: x86.32 %dispatch ( src temp offset -- ) ! Load jump table base. @@ -38,12 +38,18 @@ M:: x86.32 %dispatch ( src temp offset -- ) [ align-code ] bi ; +! Registers for fastcall +M: x86.32 param-reg-1 EAX ; +M: x86.32 param-reg-2 EDX ; + M: x86.32 reserved-area-size 0 ; M: x86.32 %alien-global 0 [] MOV rc-absolute-cell rel-dlsym ; M: x86.32 %alien-invoke (CALL) rel-dlsym ; +M: x86.32 %alien-invoke-tail (JMP) rel-dlsym ; + M: x86.32 struct-small-enough? ( size -- ? ) heap-size { 1 2 4 8 } member? os { linux netbsd solaris } member? not and ; diff --git a/basis/cpu/x86/64/64.factor b/basis/cpu/x86/64/64.factor index 9ddad23004..b6c76a78fd 100644 --- a/basis/cpu/x86/64/64.factor +++ b/basis/cpu/x86/64/64.factor @@ -21,8 +21,8 @@ M: x86.64 machine-registers M: x86.64 ds-reg R14 ; M: x86.64 rs-reg R15 ; M: x86.64 stack-reg RSP ; -M: x86.64 temp-reg-1 RAX ; -M: x86.64 temp-reg-2 RCX ; +M: x86.64 temp-reg-1 R8 ; +M: x86.64 temp-reg-2 R9 ; M:: x86.64 %dispatch ( src temp offset -- ) ! Load jump table base. @@ -37,8 +37,8 @@ M:: x86.64 %dispatch ( src temp offset -- ) [ align-code ] bi ; -: param-reg-1 int-regs param-regs first ; inline -: param-reg-2 int-regs param-regs second ; inline +M: x86.64 param-reg-1 int-regs param-regs first ; +M: x86.64 param-reg-2 int-regs param-regs second ; : param-reg-3 int-regs param-regs third ; inline M: int-regs return-reg drop RAX ; @@ -168,6 +168,11 @@ M: x86.64 %alien-invoke rc-absolute-cell rel-dlsym R11 CALL ; +M: x86.64 %alien-invoke-tail + R11 0 MOV + rc-absolute-cell rel-dlsym + R11 JMP ; + M: x86.64 %prepare-alien-indirect ( -- ) "unbox_alien" f %alien-invoke RBP RAX MOV ; diff --git a/basis/cpu/x86/bootstrap.factor b/basis/cpu/x86/bootstrap.factor index 3272015848..42df1c8437 100644 --- a/basis/cpu/x86/bootstrap.factor +++ b/basis/cpu/x86/bootstrap.factor @@ -379,6 +379,17 @@ big-endian off ds-reg bootstrap-cell neg [+] div-arg MOV ] f f f \ fixnum/mod-fast define-sub-primitive +[ + arg0 ds-reg [] MOV + arg0 ds-reg bootstrap-cell neg [+] OR + ds-reg bootstrap-cell ADD + arg0 tag-mask get AND + arg0 \ f tag-number MOV + arg1 1 tag-fixnum MOV + arg0 arg1 CMOVE + ds-reg [] arg0 MOV +] f f f \ both-fixnums? define-sub-primitive + [ arg0 ds-reg [] MOV ! load local number fixnum>slot@ ! turn local number into offset diff --git a/basis/cpu/x86/x86.factor b/basis/cpu/x86/x86.factor index f0f156a57d..104a1f155b 100644 --- a/basis/cpu/x86/x86.factor +++ b/basis/cpu/x86/x86.factor @@ -14,6 +14,9 @@ M: x86 two-operand? t ; HOOK: temp-reg-1 cpu ( -- reg ) HOOK: temp-reg-2 cpu ( -- reg ) +HOOK: param-reg-1 cpu ( -- reg ) +HOOK: param-reg-2 cpu ( -- reg ) + M: x86 %load-immediate MOV ; M: x86 %load-indirect swap 0 MOV rc-absolute-cell rel-immediate ; @@ -90,6 +93,58 @@ M: x86 %shr-imm nip SHR ; M: x86 %sar-imm nip SAR ; M: x86 %not drop NOT ; +: ?MOV ( dst src -- ) + 2dup = [ 2drop ] [ MOV ] if ; inline + +:: move>args ( src1 src2 -- ) + { + { [ src1 param-reg-2 = ] [ param-reg-1 src2 ?MOV param-reg-1 param-reg-2 XCHG ] } + { [ src1 param-reg-1 = ] [ param-reg-2 src2 ?MOV ] } + { [ src2 param-reg-1 = ] [ param-reg-2 src1 ?MOV param-reg-1 param-reg-2 XCHG ] } + { [ src2 param-reg-2 = ] [ param-reg-1 src1 ?MOV ] } + [ + param-reg-1 src1 MOV + param-reg-2 src2 MOV + ] + } cond ; + +HOOK: %alien-invoke-tail cpu ( func dll -- ) + +:: overflow-template ( src1 src2 insn inverse func -- ) +