mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 23:24:09 +00:00
ARM: Add integer variant of modulo operator.
This commit is contained in:
parent
d636a3decd
commit
add553edd8
@ -1821,6 +1821,7 @@ static void build_subroutines(BuildCtx *ctx)
|
|||||||
|->vm_trunc:
|
|->vm_trunc:
|
||||||
#endif
|
#endif
|
||||||
|
|
|
|
||||||
|
| // double lj_vm_mod(double dividend, double divisor);
|
||||||
|->vm_mod:
|
|->vm_mod:
|
||||||
| push {r0, r1, r2, r3, r4, lr}
|
| push {r0, r1, r2, r3, r4, lr}
|
||||||
| bl extern __aeabi_ddiv
|
| bl extern __aeabi_ddiv
|
||||||
@ -1833,6 +1834,41 @@ static void build_subroutines(BuildCtx *ctx)
|
|||||||
| add sp, sp, #20
|
| add sp, sp, #20
|
||||||
| pop {pc}
|
| pop {pc}
|
||||||
|
|
|
|
||||||
|
| // int lj_vm_modi(int dividend, int divisor);
|
||||||
|
|->vm_modi:
|
||||||
|
| ands RB, CARG1, #0x80000000
|
||||||
|
| rsbmi CARG1, CARG1, #0 // a = |dividend|
|
||||||
|
| eor RB, RB, CARG2, asr #1 // Keep signdiff and sign(divisor).
|
||||||
|
| cmp CARG2, #0
|
||||||
|
| rsbmi CARG2, CARG2, #0 // b = |divisor|
|
||||||
|
| subs CARG4, CARG2, #1
|
||||||
|
| cmpne CARG1, CARG2
|
||||||
|
| moveq CARG1, #0 // if (b == 1 || a == b) a = 0
|
||||||
|
| tsthi CARG2, CARG4
|
||||||
|
| andeq CARG1, CARG1, CARG4 // else if ((b & (b-1)) == 0) a &= b-1
|
||||||
|
| bls >1
|
||||||
|
| // Use repeated subtraction to get the remainder.
|
||||||
|
| clz CARG3, CARG1
|
||||||
|
| clz CARG4, CARG2
|
||||||
|
| sub CARG4, CARG4, CARG3
|
||||||
|
| rsbs CARG3, CARG4, #31 // entry = (31-(clz(b)-clz(a)))*8
|
||||||
|
| addne pc, pc, CARG3, lsl #3 // Duff's device.
|
||||||
|
| nop
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 31; i >= 0; i--) {
|
||||||
|
| cmp CARG1, CARG2, lsl #i
|
||||||
|
| subhs CARG1, CARG1, CARG2, lsl #i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|1:
|
||||||
|
| cmp CARG1, #0
|
||||||
|
| cmpne RB, #0
|
||||||
|
| submi CARG1, CARG1, CARG2 // if (y != 0 && signdiff) y = y - b
|
||||||
|
| eors CARG2, CARG1, RB, lsl #1
|
||||||
|
| rsbmi CARG1, CARG1, #0 // if (sign(divisor) != sign(y)) y = -y
|
||||||
|
| bx lr
|
||||||
|
|
|
||||||
|->vm_powi:
|
|->vm_powi:
|
||||||
#if LJ_HASJIT
|
#if LJ_HASJIT
|
||||||
| NYI
|
| NYI
|
||||||
@ -2266,33 +2302,42 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
|
|||||||
|
|
|
|
||||||
|.macro ins_arithdn, intins, fpcall
|
|.macro ins_arithdn, intins, fpcall
|
||||||
| ins_arithpre
|
| ins_arithpre
|
||||||
|
|.if "intins" ~= "vm_modi"
|
||||||
| ins_next1
|
| ins_next1
|
||||||
|
|.endif
|
||||||
| ins_arithcheck_int >5
|
| ins_arithcheck_int >5
|
||||||
|.if "intins" == "smull"
|
|.if "intins" == "smull"
|
||||||
| smull CARG1, RC, CARG3, CARG1
|
| smull CARG1, RC, CARG3, CARG1
|
||||||
| cmp RC, CARG1, asr #31
|
| cmp RC, CARG1, asr #31
|
||||||
| ins_arithfallback bne
|
| ins_arithfallback bne
|
||||||
|
|.elif "intins" == "vm_modi"
|
||||||
|
| movs CARG2, CARG3
|
||||||
|
| ins_arithfallback beq
|
||||||
|
| bl ->vm_modi
|
||||||
|
| mvn CARG2, #~LJ_TISNUM
|
||||||
|.else
|
|.else
|
||||||
| intins CARG1, CARG1, CARG3
|
| intins CARG1, CARG1, CARG3
|
||||||
| ins_arithfallback bvs
|
| ins_arithfallback bvs
|
||||||
|.endif
|
|.endif
|
||||||
|4:
|
|4:
|
||||||
|
|.if "intins" == "vm_modi"
|
||||||
|
| ins_next1
|
||||||
|
|.endif
|
||||||
| ins_next2
|
| ins_next2
|
||||||
| strd CARG12, [BASE, RA]
|
| strd CARG12, [BASE, RA]
|
||||||
| ins_next3
|
| ins_next3
|
||||||
|5: // FP variant.
|
|5: // FP variant.
|
||||||
| ins_arithfallback ins_arithcheck_num
|
| ins_arithfallback ins_arithcheck_num
|
||||||
| bl fpcall
|
| bl fpcall
|
||||||
|
|.if "intins" ~= "vm_modi"
|
||||||
| ins_next1
|
| ins_next1
|
||||||
|
|.endif
|
||||||
| b <4
|
| b <4
|
||||||
|.endmacro
|
|.endmacro
|
||||||
|
|
|
|
||||||
|.macro ins_arithfp, fpcall
|
|.macro ins_arithfp, fpcall
|
||||||
| ins_arithpre
|
| ins_arithpre
|
||||||
| ins_arithfallback ins_arithcheck_num
|
| ins_arithfallback ins_arithcheck_num
|
||||||
||if (op == BC_MODVN) {
|
|
||||||
| ->BC_MODVN_Z:
|
|
||||||
||}
|
|
||||||
| bl fpcall
|
| bl fpcall
|
||||||
| ins_next1
|
| ins_next1
|
||||||
| ins_next2
|
| ins_next2
|
||||||
@ -2312,15 +2357,8 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
|
|||||||
case BC_DIVVN: case BC_DIVNV: case BC_DIVVV:
|
case BC_DIVVN: case BC_DIVNV: case BC_DIVVV:
|
||||||
| ins_arithfp extern __aeabi_ddiv
|
| ins_arithfp extern __aeabi_ddiv
|
||||||
break;
|
break;
|
||||||
case BC_MODVN:
|
case BC_MODVN: case BC_MODNV: case BC_MODVV:
|
||||||
| // NYI: integer arithmetic.
|
| ins_arithdn vm_modi, ->vm_mod
|
||||||
| // Note: __aeabi_idivmod is unsuitable. It uses trunc, not floor.
|
|
||||||
| ins_arithfp ->vm_mod
|
|
||||||
break;
|
|
||||||
case BC_MODNV: case BC_MODVV:
|
|
||||||
| ins_arithpre
|
|
||||||
| ins_arithfallback ins_arithcheck_num
|
|
||||||
| b ->BC_MODVN_Z
|
|
||||||
break;
|
break;
|
||||||
case BC_POW:
|
case BC_POW:
|
||||||
| // NYI: (partial) integer arithmetic.
|
| // NYI: (partial) integer arithmetic.
|
||||||
|
Loading…
Reference in New Issue
Block a user