diff --git a/src/buildvm_arm.dasc b/src/buildvm_arm.dasc index 905e0ada..68f33d97 100644 --- a/src/buildvm_arm.dasc +++ b/src/buildvm_arm.dasc @@ -1203,8 +1203,74 @@ static void build_subroutines(BuildCtx *ctx) | |//-- Math library ------------------------------------------------------- | - |.align 8 + |.macro math_round, func + | .ffunc_1 math_ .. func + | checktp CARG2, LJ_TISNUM + | beq ->fff_restv + | bhi ->fff_fallback + | // Round FP value and normalize result. + | lsl CARG3, CARG2, #1 + | adds RB, CARG3, #0x00200000 + | bpl >2 // |x| < 1? + | mvn CARG4, #0x3e0 + | subs RB, CARG4, RB, asr #21 + | lsl CARG4, CARG2, #11 + | lsl CARG3, CARG1, #11 + | orr CARG4, CARG4, #0x80000000 + | rsb INS, RB, #32 + | orr CARG4, CARG4, CARG1, lsr #21 + | bls >3 // |x| >= 2^31? + | orr CARG3, CARG3, CARG4, lsl INS + | lsr CARG1, CARG4, RB + |.if "func" == "floor" + | tst CARG3, CARG2, asr #31 + | addne CARG1, CARG1, #1 + |.else + | bics CARG3, CARG3, CARG2, asr #31 + | addsne CARG1, CARG1, #1 + | ldrdvs CARG12, >9 + | bvs ->fff_restv + |.endif + | cmp CARG2, #0 + | rsblt CARG1, CARG1, #0 |1: + | mvn CARG2, #~LJ_TISNUM + | b ->fff_restv + | + |2: // |x| < 1 + | orr CARG3, CARG3, CARG1 // ztest = abs(hi) | lo + |.if "func" == "floor" + | tst CARG3, CARG2, asr #31 // return (ztest & sign) == 0 ? 0 : -1 + | moveq CARG1, #0 + | mvnne CARG1, #0 + |.else + | bics CARG3, CARG3, CARG2, asr #31 // return (ztest & ~sign) == 0 ? 0 : 1 + | moveq CARG1, #0 + | movne CARG1, #1 + |.endif + | mvn CARG2, #~LJ_TISNUM + | b ->fff_restv + | + |3: // |x| >= 2^31. Check for x == -(2^31). + | cmpeq CARG4, #0x80000000 + |.if "func" == "floor" + | cmpeq CARG3, #0 + |.endif + | bne >4 + | cmp CARG2, #0 + | movmi CARG1, #0x80000000 + | bmi <1 + |4: + | // NYI: Use internal implementation. + | bl extern func + | b ->fff_restv + |.endmacro + | + | math_round floor + | math_round ceil + | + |.align 8 + |9: | .long 0x00000000, 0x41e00000 // 2^31. | |.ffunc_1 math_abs @@ -1214,7 +1280,7 @@ static void build_subroutines(BuildCtx *ctx) | bne ->fff_restv | cmp CARG1, #0 | rsbslt CARG1, CARG1, #0 - | ldrdvs CARG12, <1 + | ldrdvs CARG12, <9 | // Fallthrough. | |->fff_restv: @@ -1261,18 +1327,6 @@ static void build_subroutines(BuildCtx *ctx) | b ->fff_restv |.endmacro | - |.macro math_round, func - | .ffunc_1 math_ .. func - | checktp CARG2, LJ_TISNUM - | bhi ->fff_fallback - | bllo extern func // NYI: use internal implementation of floor/ceil. - | // NYI: normalize result. - | b ->fff_restv - |.endmacro - | - | math_round floor - | math_round ceil - | | math_extern sqrt | math_extern log | math_extern log10 @@ -1805,18 +1859,18 @@ static void build_subroutines(BuildCtx *ctx) |//-- Math helper functions ---------------------------------------------- |//----------------------------------------------------------------------- | - |// FP value rounding. Called by math.floor/math.ceil fast functions - |// and from JIT code. + |// FP value rounding. Called from JIT code. |// - |.macro vm_round, name, mode - |->name: + |// double lj_vm_floor/ceil/trunc(double x); + |.macro vm_round, func + |->vm_ .. func: | NYI |.endmacro | - | vm_round vm_floor, 0 - | vm_round vm_ceil, 1 + | vm_round floor + | vm_round ceil #if LJ_HASJIT - | vm_round vm_trunc, 2 + | vm_round trunc #else |->vm_trunc: #endif