ARM: Normalize results of math.floor()/ceil() fast functions.

This commit is contained in:
Mike Pall 2011-04-17 02:31:00 +02:00
parent 32db4525d9
commit 7bb4b0f570

View File

@ -1203,8 +1203,74 @@ static void build_subroutines(BuildCtx *ctx)
| |
|//-- Math library ------------------------------------------------------- |//-- 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: |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. | .long 0x00000000, 0x41e00000 // 2^31.
| |
|.ffunc_1 math_abs |.ffunc_1 math_abs
@ -1214,7 +1280,7 @@ static void build_subroutines(BuildCtx *ctx)
| bne ->fff_restv | bne ->fff_restv
| cmp CARG1, #0 | cmp CARG1, #0
| rsbslt CARG1, CARG1, #0 | rsbslt CARG1, CARG1, #0
| ldrdvs CARG12, <1 | ldrdvs CARG12, <9
| // Fallthrough. | // Fallthrough.
| |
|->fff_restv: |->fff_restv:
@ -1261,18 +1327,6 @@ static void build_subroutines(BuildCtx *ctx)
| b ->fff_restv | b ->fff_restv
|.endmacro |.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 sqrt
| math_extern log | math_extern log
| math_extern log10 | math_extern log10
@ -1805,18 +1859,18 @@ static void build_subroutines(BuildCtx *ctx)
|//-- Math helper functions ---------------------------------------------- |//-- Math helper functions ----------------------------------------------
|//----------------------------------------------------------------------- |//-----------------------------------------------------------------------
| |
|// FP value rounding. Called by math.floor/math.ceil fast functions |// FP value rounding. Called from JIT code.
|// and from JIT code.
|// |//
|.macro vm_round, name, mode |// double lj_vm_floor/ceil/trunc(double x);
|->name: |.macro vm_round, func
|->vm_ .. func:
| NYI | NYI
|.endmacro |.endmacro
| |
| vm_round vm_floor, 0 | vm_round floor
| vm_round vm_ceil, 1 | vm_round ceil
#if LJ_HASJIT #if LJ_HASJIT
| vm_round vm_trunc, 2 | vm_round trunc
#else #else
|->vm_trunc: |->vm_trunc:
#endif #endif