Kaynağa Gözat

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

Mike Pall 14 yıl önce
ebeveyn
işleme
7bb4b0f570
1 değiştirilmiş dosya ile 75 ekleme ve 21 silme
  1. 75 21
      src/buildvm_arm.dasc

+ 75 - 21
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