diff options
author | Mike Pall <mike> | 2011-04-16 23:29:57 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2011-04-16 23:29:57 +0200 |
commit | add553edd89e8e8472439d17b14c06c1d983ba6b (patch) | |
tree | 299eb6b6ee8587acd2486bbb5b3dbfe7c8819bc6 /src | |
parent | d636a3decdf8dc503e707fad8b0e2745c0cabd21 (diff) | |
download | luajit-add553edd89e8e8472439d17b14c06c1d983ba6b.tar.gz luajit-add553edd89e8e8472439d17b14c06c1d983ba6b.tar.bz2 luajit-add553edd89e8e8472439d17b14c06c1d983ba6b.zip |
ARM: Add integer variant of modulo operator.
Diffstat (limited to 'src')
-rw-r--r-- | src/buildvm_arm.dasc | 62 |
1 files changed, 50 insertions, 12 deletions
diff --git a/src/buildvm_arm.dasc b/src/buildvm_arm.dasc index c12b4da8..b0338702 100644 --- a/src/buildvm_arm.dasc +++ b/src/buildvm_arm.dasc | |||
@@ -1821,6 +1821,7 @@ static void build_subroutines(BuildCtx *ctx) | |||
1821 | |->vm_trunc: | 1821 | |->vm_trunc: |
1822 | #endif | 1822 | #endif |
1823 | | | 1823 | | |
1824 | | // double lj_vm_mod(double dividend, double divisor); | ||
1824 | |->vm_mod: | 1825 | |->vm_mod: |
1825 | | push {r0, r1, r2, r3, r4, lr} | 1826 | | push {r0, r1, r2, r3, r4, lr} |
1826 | | bl extern __aeabi_ddiv | 1827 | | bl extern __aeabi_ddiv |
@@ -1833,6 +1834,41 @@ static void build_subroutines(BuildCtx *ctx) | |||
1833 | | add sp, sp, #20 | 1834 | | add sp, sp, #20 |
1834 | | pop {pc} | 1835 | | pop {pc} |
1835 | | | 1836 | | |
1837 | | // int lj_vm_modi(int dividend, int divisor); | ||
1838 | |->vm_modi: | ||
1839 | | ands RB, CARG1, #0x80000000 | ||
1840 | | rsbmi CARG1, CARG1, #0 // a = |dividend| | ||
1841 | | eor RB, RB, CARG2, asr #1 // Keep signdiff and sign(divisor). | ||
1842 | | cmp CARG2, #0 | ||
1843 | | rsbmi CARG2, CARG2, #0 // b = |divisor| | ||
1844 | | subs CARG4, CARG2, #1 | ||
1845 | | cmpne CARG1, CARG2 | ||
1846 | | moveq CARG1, #0 // if (b == 1 || a == b) a = 0 | ||
1847 | | tsthi CARG2, CARG4 | ||
1848 | | andeq CARG1, CARG1, CARG4 // else if ((b & (b-1)) == 0) a &= b-1 | ||
1849 | | bls >1 | ||
1850 | | // Use repeated subtraction to get the remainder. | ||
1851 | | clz CARG3, CARG1 | ||
1852 | | clz CARG4, CARG2 | ||
1853 | | sub CARG4, CARG4, CARG3 | ||
1854 | | rsbs CARG3, CARG4, #31 // entry = (31-(clz(b)-clz(a)))*8 | ||
1855 | | addne pc, pc, CARG3, lsl #3 // Duff's device. | ||
1856 | | nop | ||
1857 | { | ||
1858 | int i; | ||
1859 | for (i = 31; i >= 0; i--) { | ||
1860 | | cmp CARG1, CARG2, lsl #i | ||
1861 | | subhs CARG1, CARG1, CARG2, lsl #i | ||
1862 | } | ||
1863 | } | ||
1864 | |1: | ||
1865 | | cmp CARG1, #0 | ||
1866 | | cmpne RB, #0 | ||
1867 | | submi CARG1, CARG1, CARG2 // if (y != 0 && signdiff) y = y - b | ||
1868 | | eors CARG2, CARG1, RB, lsl #1 | ||
1869 | | rsbmi CARG1, CARG1, #0 // if (sign(divisor) != sign(y)) y = -y | ||
1870 | | bx lr | ||
1871 | | | ||
1836 | |->vm_powi: | 1872 | |->vm_powi: |
1837 | #if LJ_HASJIT | 1873 | #if LJ_HASJIT |
1838 | | NYI | 1874 | | NYI |
@@ -2266,33 +2302,42 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
2266 | | | 2302 | | |
2267 | |.macro ins_arithdn, intins, fpcall | 2303 | |.macro ins_arithdn, intins, fpcall |
2268 | | ins_arithpre | 2304 | | ins_arithpre |
2305 | |.if "intins" ~= "vm_modi" | ||
2269 | | ins_next1 | 2306 | | ins_next1 |
2307 | |.endif | ||
2270 | | ins_arithcheck_int >5 | 2308 | | ins_arithcheck_int >5 |
2271 | |.if "intins" == "smull" | 2309 | |.if "intins" == "smull" |
2272 | | smull CARG1, RC, CARG3, CARG1 | 2310 | | smull CARG1, RC, CARG3, CARG1 |
2273 | | cmp RC, CARG1, asr #31 | 2311 | | cmp RC, CARG1, asr #31 |
2274 | | ins_arithfallback bne | 2312 | | ins_arithfallback bne |
2313 | |.elif "intins" == "vm_modi" | ||
2314 | | movs CARG2, CARG3 | ||
2315 | | ins_arithfallback beq | ||
2316 | | bl ->vm_modi | ||
2317 | | mvn CARG2, #~LJ_TISNUM | ||
2275 | |.else | 2318 | |.else |
2276 | | intins CARG1, CARG1, CARG3 | 2319 | | intins CARG1, CARG1, CARG3 |
2277 | | ins_arithfallback bvs | 2320 | | ins_arithfallback bvs |
2278 | |.endif | 2321 | |.endif |
2279 | |4: | 2322 | |4: |
2323 | |.if "intins" == "vm_modi" | ||
2324 | | ins_next1 | ||
2325 | |.endif | ||
2280 | | ins_next2 | 2326 | | ins_next2 |
2281 | | strd CARG12, [BASE, RA] | 2327 | | strd CARG12, [BASE, RA] |
2282 | | ins_next3 | 2328 | | ins_next3 |
2283 | |5: // FP variant. | 2329 | |5: // FP variant. |
2284 | | ins_arithfallback ins_arithcheck_num | 2330 | | ins_arithfallback ins_arithcheck_num |
2285 | | bl fpcall | 2331 | | bl fpcall |
2332 | |.if "intins" ~= "vm_modi" | ||
2286 | | ins_next1 | 2333 | | ins_next1 |
2334 | |.endif | ||
2287 | | b <4 | 2335 | | b <4 |
2288 | |.endmacro | 2336 | |.endmacro |
2289 | | | 2337 | | |
2290 | |.macro ins_arithfp, fpcall | 2338 | |.macro ins_arithfp, fpcall |
2291 | | ins_arithpre | 2339 | | ins_arithpre |
2292 | | ins_arithfallback ins_arithcheck_num | 2340 | | ins_arithfallback ins_arithcheck_num |
2293 | ||if (op == BC_MODVN) { | ||
2294 | | ->BC_MODVN_Z: | ||
2295 | ||} | ||
2296 | | bl fpcall | 2341 | | bl fpcall |
2297 | | ins_next1 | 2342 | | ins_next1 |
2298 | | ins_next2 | 2343 | | ins_next2 |
@@ -2312,15 +2357,8 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
2312 | case BC_DIVVN: case BC_DIVNV: case BC_DIVVV: | 2357 | case BC_DIVVN: case BC_DIVNV: case BC_DIVVV: |
2313 | | ins_arithfp extern __aeabi_ddiv | 2358 | | ins_arithfp extern __aeabi_ddiv |
2314 | break; | 2359 | break; |
2315 | case BC_MODVN: | 2360 | case BC_MODVN: case BC_MODNV: case BC_MODVV: |
2316 | | // NYI: integer arithmetic. | 2361 | | ins_arithdn vm_modi, ->vm_mod |
2317 | | // Note: __aeabi_idivmod is unsuitable. It uses trunc, not floor. | ||
2318 | | ins_arithfp ->vm_mod | ||
2319 | break; | ||
2320 | case BC_MODNV: case BC_MODVV: | ||
2321 | | ins_arithpre | ||
2322 | | ins_arithfallback ins_arithcheck_num | ||
2323 | | b ->BC_MODVN_Z | ||
2324 | break; | 2362 | break; |
2325 | case BC_POW: | 2363 | case BC_POW: |
2326 | | // NYI: (partial) integer arithmetic. | 2364 | | // NYI: (partial) integer arithmetic. |