M: float-regs (%replace) drop swap %allot-float ;
-! Floats
: define-float-op ( word op -- )
[ "x" operand "y" operand ] swap add H{
{ +input+ { { float "x" } { float "y" } } }
{ +clobber+ { "y" } }
} define-intrinsic
-! \ fixnum>bignum [
-! "nonzero" define-label
-! "end" define-label
-! 0 "x" operand 0 CMPI ! is it zero?
-! "nonzero" get BNE
-! 0 >bignum "x" get load-literal
-! "end" get B
-! "nonzero" resolve-label
-! "x" operand dup %untag-fixnum
-! "x" operand %allot-bignum-signed-1
-! "end" resolve-label
-! ] H{
-! { +input+ { { f "x" } } }
-! { +output+ { "x" } }
-! } define-intrinsic
-!
+\ fixnum>bignum [
+ "nonzero" define-label
+ "end" define-label
+ 0 "x" operand 0 CMPI ! is it zero?
+ "nonzero" get BNE
+ 0 >bignum "x" get load-literal
+ "end" get B
+ "nonzero" resolve-label
+ "x" operand dup %untag-fixnum
+ "x" operand %allot-bignum-signed-1
+ "end" resolve-label
+] H{
+ { +input+ { { f "x" } } }
+ { +output+ { "x" } }
+} define-intrinsic
+
! \ bignum>fixnum [
! "nonzero" define-label
! "end" define-label
] %allot-bignum
] with-scope ;
+: bignum-radix-mask 1 cell 2 - shift 1- ;
+
: %allot-bignum-signed-2 ( reg1 reg2 -- )
- #! on entry, reg1 and reg2 together form a signed 64-bit
- #! quantity.
+ #! this word has some hairy restrictions; its really only
+ #! intended to be used by fixnum*.
+ #! - reg1 and reg2 together form a 60-bit signed quantity
+ #! (product of two 29-bit fixnums cannot exceed this)
+ #! - the quantity must be non-zero
+ #! (if the product of two fixnums is zero, there's no
+ #! overflow so this word won't be called in that case)
#! exits with tagged ptr to bignum in reg1
[
+ "positive" define-label
+ "end" define-label
2 [
- ! todo: neg
- allot-tmp-reg 2 cells [+] 0 MOV ! positive sign
+ 0 pick CMP
+ "positive" get JGE
+ allot-tmp-reg 2 cells [+] 1 MOV
+ over NOT
+ dup -1 IMUL
+ "end" get JMP
+ "positive" resolve-label
+ allot-tmp-reg 2 cells [+] 0 MOV
+ "end" resolve-label
+ dup bignum-radix-mask AND
allot-tmp-reg 3 cells [+] swap MOV
+ dup bignum-radix-mask AND
allot-tmp-reg 4 cells [+] over MOV
allot-tmp-reg bignum-tag OR
allot-tmp-reg MOV
"x" operand "y" operand %allot-bignum-signed-1 ! Yes, box bignum
;
-\ fixnum* [
- "overflow-1" define-label
- "overflow-2" define-label
- "end" define-label
- { "y" "x" } %untag-fixnums
- "y" operand IMUL
- "overflow-1" get JNO
- "x" operand "r" operand %allot-bignum-signed-2
- "end" get JMP
- "overflow-1" resolve-label
- %tag-overflow
- "end" resolve-label
-] H{
- { +input+ { { 0 "x" } { 1 "y" } } }
- { +output+ { "x" } }
- { +scratch+ { { 2 "r" } } }
- { +clobber+ { "y" } }
-} define-intrinsic
+! \ fixnum* [
+! "overflow-1" define-label
+! "overflow-2" define-label
+! "end" define-label
+! { "y" "x" } %untag-fixnums
+! "y" operand IMUL
+! "overflow-1" get JNO
+! "x" operand "r" operand %allot-bignum-signed-2
+! "end" get JMP
+! "overflow-1" resolve-label
+! %tag-overflow
+! "end" resolve-label
+! ] H{
+! { +input+ { { 0 "x" } { 1 "y" } } }
+! { +output+ { "x" } }
+! { +scratch+ { { 2 "r" } } }
+! { +clobber+ { "y" } }
+! } define-intrinsic
: generate-fixnum/mod
#! The same code is used for fixnum/i and fixnum/mod.