Unify Lua number to FFI integer conversions.

Phew. #1411
This commit is contained in:
Mike Pall
2025-11-27 17:45:17 +01:00
parent 3215838aa7
commit f80b349d54
41 changed files with 1070 additions and 434 deletions

View File

@@ -2113,7 +2113,7 @@ static void build_subroutines(BuildCtx *ctx)
| dinsu CRET2, AT, 21, 21
| slt AT, CARG1, r0
| dsrlv CRET1, CRET2, TMP0
| dsubu CARG1, r0, CRET1
| negu CARG1, CRET1
|.if MIPSR6
| seleqz CRET1, CRET1, AT
| selnez CARG1, CARG1, AT
@@ -2121,20 +2121,12 @@ static void build_subroutines(BuildCtx *ctx)
|.else
| movn CRET1, CARG1, AT
|.endif
| li CARG1, 64
| subu TMP0, CARG1, TMP0
| negu TMP0, TMP0
| dsllv CRET2, CRET2, TMP0 // Integer check.
| sextw AT, CRET1
| xor AT, CRET1, AT // Range check.
|.if MIPSR6
| seleqz AT, AT, CRET2
| selnez CRET2, CRET2, CRET2
| jr ra
|. or CRET2, AT, CRET2
|.else
| jr ra
|. movz CRET2, AT, CRET2
|.endif
|1:
| jr ra
|. li CRET2, 1
@@ -2929,6 +2921,136 @@ static void build_subroutines(BuildCtx *ctx)
| sfmin_max max, vm_sfcmpogt
|
|//-----------------------------------------------------------------------
|//-- Number conversion functions ----------------------------------------
|//-----------------------------------------------------------------------
|
|// int64_t lj_vm_num2int_check(double x)
|->vm_num2int_check:
|.if FPU
| trunc.w.d FARG2, FARG1
| mfc1 CRET1, FARG2
| cvt.d.w FARG2, FARG2
|.if MIPSR6
| cmp.eq.d FARG2, FARG1, FARG2
| bc1eqz FARG2, >2
|.else
| c.eq.d FARG1, FARG2
| bc1f 0, >2
|.endif
|. nop
| jr ra
|. zextw CRET1, CRET1
|
|.else
|
| dsll CRET2, CARG1, 1
| beqz CRET2, >1
|. li TMP0, 1076
| dsrl AT, CRET2, 53
| dsubu TMP0, TMP0, AT
| sltiu AT, TMP0, 54
| beqz AT, >2
|. dextm CRET2, CRET2, 0, 20
| dinsu CRET2, AT, 21, 21
| slt AT, CARG1, r0
| dsrlv CRET1, CRET2, TMP0
| negu CARG1, CRET1
|.if MIPSR6
| seleqz CRET1, CRET1, AT
| selnez CARG1, CARG1, AT
| or CRET1, CRET1, CARG1
|.else
| movn CRET1, CARG1, AT
|.endif
| negu TMP0, TMP0
| dsllv CRET2, CRET2, TMP0 // Integer check.
| sextw AT, CRET1
| xor AT, CRET1, AT // Range check.
| or AT, AT, CRET2
| bnez AT, >2
|. nop
| jr ra
|. zextw CRET1, CRET1
|1:
| jr ra
|. move CRET1, r0
|.endif
|2:
| lui CRET1, 0x8000
| dsll CRET1, CRET1, 16
| ori CRET1, CRET1, 0x8000
| jr ra
|. dsll CRET1, CRET1, 16
|
|// int64_t lj_vm_num2i64(double x)
|->vm_num2i64:
|.if FPU
| trunc.l.d FARG1, FARG1
| jr ra
|. dmfc1 CRET1, FARG1
|.else
|// fallthrough, same as lj_vm_num2u64 for soft-float.
|.endif
|
|// uint64_t lj_vm_num2u64(double x)
|->vm_num2u64:
|.if FPU
| trunc.l.d FARG2, FARG1
| dmfc1 CRET1, FARG2
| li AT, -1
| dsrl AT, AT, 1
| beq CRET1, AT, >1
|. lui AT, 0xdf80 // -2^64 (float).
| jr ra
|. nop
|1:
| mtc1 AT, FARG2
| cvt.d.s FARG2, FARG2
| add.d FARG1, FARG1, FARG2
| trunc.l.d FARG2, FARG1
| jr ra
|. dmfc1 CRET1, FARG2
|
|.else
|
| dextu CARG2, CARG1, 20, 10
| addiu AT, CARG2, -1023
| sltiu AT, AT, 116
| beqz AT, >2 // Exponent out of range.
|. addiu CARG2, CARG2, -1075
| dextm CRET1, CARG1, 0, 19
| dsll AT, AT, 52
| dsra CARG1, CARG1, 63 // sign = 0 or -1.
| bgez CARG2, >1 // Shift mantissa left or right?
|. or CRET1, CRET1, AT // Merge leading 1 into masked mantissa.
| subu CARG2, r0, CARG2
| dsrlv CRET1, CRET1, CARG2 // Shift mantissa right for low exp.
| daddu CRET1, CRET1, CARG1
| jr ra
|. xor CRET1, CRET1, CARG1 // m = sign?-m:m = (m+sign)^sign.
|1:
| dsllv CRET1, CRET1, CARG2 // Shift mantissa left for high exp.
| daddu CRET1, CRET1, CARG1
| jr ra
|. xor CRET1, CRET1, CARG1 // m = sign?-m:m = (m+sign)^sign.
|2:
| jr ra
|. move CRET1, r0
|.endif
|
|// int32_t lj_vm_tobit(double x)
|.if FPU
|->vm_tobit:
| lui AT, 0x59c0 // 2^52 + 2^51 (float).
| mtc1 AT, FARG2
| cvt.d.s FARG2, FARG2
| add.d FARG1, FARG1, FARG2
| mfc1 CRET1, FARG1
| jr ra
|. sextw CRET1, CRET1
|.endif
|
|//-----------------------------------------------------------------------
|//-- Miscellaneous functions --------------------------------------------
|//-----------------------------------------------------------------------
|