diff options
author | Mike Pall <mike> | 2011-02-02 20:53:10 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2011-02-02 21:24:55 +0100 |
commit | a1e0f991d8407b1942be0389332e3f24810f5f7a (patch) | |
tree | 783a750366a41020532f2b66562a4e33082bb071 /src | |
parent | 2c8945d3e734bb42faa60ef0b97a6115a2b099f7 (diff) | |
download | luajit-a1e0f991d8407b1942be0389332e3f24810f5f7a.tar.gz luajit-a1e0f991d8407b1942be0389332e3f24810f5f7a.tar.bz2 luajit-a1e0f991d8407b1942be0389332e3f24810f5f7a.zip |
FFI: Record 64 bit integer divide and modulo.
Diffstat (limited to 'src')
-rw-r--r-- | src/lj_asm.c | 31 | ||||
-rw-r--r-- | src/lj_carith.c | 55 | ||||
-rw-r--r-- | src/lj_carith.h | 4 | ||||
-rw-r--r-- | src/lj_crecord.c | 2 | ||||
-rw-r--r-- | src/lj_ir.h | 18 | ||||
-rw-r--r-- | src/lj_opt_split.c | 10 |
6 files changed, 86 insertions, 34 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c index 441700d4..27c9ac31 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
@@ -3988,7 +3988,23 @@ static void asm_ir(ASMState *as, IRIns *ir) | |||
3988 | else | 3988 | else |
3989 | asm_intarith(as, ir, XOg_X_IMUL); | 3989 | asm_intarith(as, ir, XOg_X_IMUL); |
3990 | break; | 3990 | break; |
3991 | case IR_DIV: asm_fparith(as, ir, XO_DIVSD); break; | 3991 | case IR_DIV: |
3992 | #if LJ_64 && LJ_HASFFI | ||
3993 | if (!irt_isnum(ir->t)) | ||
3994 | asm_arith64(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_divi64 : | ||
3995 | IRCALL_lj_carith_divu64); | ||
3996 | else | ||
3997 | #endif | ||
3998 | asm_fparith(as, ir, XO_DIVSD); | ||
3999 | break; | ||
4000 | case IR_MOD: | ||
4001 | #if LJ_64 && LJ_HASFFI | ||
4002 | asm_arith64(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_modi64 : | ||
4003 | IRCALL_lj_carith_modu64); | ||
4004 | #else | ||
4005 | lua_assert(0); | ||
4006 | #endif | ||
4007 | break; | ||
3992 | 4008 | ||
3993 | case IR_NEG: | 4009 | case IR_NEG: |
3994 | if (irt_isnum(ir->t)) | 4010 | if (irt_isnum(ir->t)) |
@@ -4168,6 +4184,14 @@ static void asm_setup_regsp(ASMState *as, GCtrace *T) | |||
4168 | as->modset = RSET_SCRATCH; | 4184 | as->modset = RSET_SCRATCH; |
4169 | break; | 4185 | break; |
4170 | case IR_POWI: | 4186 | case IR_POWI: |
4187 | if (irt_isnum(ir->t)) { | ||
4188 | ir->prev = REGSP_HINT(RID_XMM0); | ||
4189 | if (inloop) | ||
4190 | as->modset |= RSET_RANGE(RID_XMM0, RID_XMM1+1)|RID2RSET(RID_EAX); | ||
4191 | continue; | ||
4192 | } | ||
4193 | /* fallthrough */ | ||
4194 | case IR_DIV: case IR_MOD: | ||
4171 | #if LJ_64 && LJ_HASFFI | 4195 | #if LJ_64 && LJ_HASFFI |
4172 | if (!irt_isnum(ir->t)) { | 4196 | if (!irt_isnum(ir->t)) { |
4173 | ir->prev = REGSP_HINT(RID_RET); | 4197 | ir->prev = REGSP_HINT(RID_RET); |
@@ -4176,10 +4200,7 @@ static void asm_setup_regsp(ASMState *as, GCtrace *T) | |||
4176 | continue; | 4200 | continue; |
4177 | } | 4201 | } |
4178 | #endif | 4202 | #endif |
4179 | ir->prev = REGSP_HINT(RID_XMM0); | 4203 | break; |
4180 | if (inloop) | ||
4181 | as->modset |= RSET_RANGE(RID_XMM0, RID_XMM1+1)|RID2RSET(RID_EAX); | ||
4182 | continue; | ||
4183 | case IR_FPMATH: | 4204 | case IR_FPMATH: |
4184 | if (ir->op2 == IRFPM_EXP2) { /* May be joined to lj_vm_pow_sse. */ | 4205 | if (ir->op2 == IRFPM_EXP2) { /* May be joined to lj_vm_pow_sse. */ |
4185 | ir->prev = REGSP_HINT(RID_XMM0); | 4206 | ir->prev = REGSP_HINT(RID_XMM0); |
diff --git a/src/lj_carith.c b/src/lj_carith.c index 134a61fb..bba9f6b9 100644 --- a/src/lj_carith.c +++ b/src/lj_carith.c | |||
@@ -148,21 +148,6 @@ static int carith_int64(lua_State *L, CTState *cts, CDArith *ca, MMS mm) | |||
148 | setboolV(L->top-1, | 148 | setboolV(L->top-1, |
149 | id == CTID_INT64 ? ((int64_t)u0 <= (int64_t)u1) : (u0 <= u1)); | 149 | id == CTID_INT64 ? ((int64_t)u0 <= (int64_t)u1) : (u0 <= u1)); |
150 | return 1; | 150 | return 1; |
151 | case MM_div: case MM_mod: | ||
152 | if (u1 == 0) { /* Division by zero. */ | ||
153 | if (u0 == 0) | ||
154 | setnanV(L->top-1); | ||
155 | else if (id == CTID_INT64 && (int64_t)u0 < 0) | ||
156 | setminfV(L->top-1); | ||
157 | else | ||
158 | setpinfV(L->top-1); | ||
159 | return 1; | ||
160 | } else if (id == CTID_INT64 && (int64_t)u1 == -1 && | ||
161 | u0 == U64x(80000000,00000000)) { /* MIN64 / -1. */ | ||
162 | if (mm == MM_div) id = CTID_UINT64; else u0 = 0; | ||
163 | mm = MM_unm; /* Result is 0x8000000000000000ULL or 0LL. */ | ||
164 | } | ||
165 | break; | ||
166 | default: break; | 151 | default: break; |
167 | } | 152 | } |
168 | cd = lj_cdata_new(cts, id, 8); | 153 | cd = lj_cdata_new(cts, id, 8); |
@@ -174,15 +159,15 @@ static int carith_int64(lua_State *L, CTState *cts, CDArith *ca, MMS mm) | |||
174 | case MM_mul: *up = u0 * u1; break; | 159 | case MM_mul: *up = u0 * u1; break; |
175 | case MM_div: | 160 | case MM_div: |
176 | if (id == CTID_INT64) | 161 | if (id == CTID_INT64) |
177 | *up = (uint64_t)((int64_t)u0 / (int64_t)u1); | 162 | *up = (uint64_t)lj_carith_divi64((int64_t)u0, (int64_t)u1); |
178 | else | 163 | else |
179 | *up = u0 / u1; | 164 | *up = lj_carith_divu64(u0, u1); |
180 | break; | 165 | break; |
181 | case MM_mod: | 166 | case MM_mod: |
182 | if (id == CTID_INT64) | 167 | if (id == CTID_INT64) |
183 | *up = (uint64_t)((int64_t)u0 % (int64_t)u1); | 168 | *up = (uint64_t)lj_carith_modi64((int64_t)u0, (int64_t)u1); |
184 | else | 169 | else |
185 | *up = u0 % u1; | 170 | *up = lj_carith_modu64(u0, u1); |
186 | break; | 171 | break; |
187 | case MM_pow: | 172 | case MM_pow: |
188 | if (id == CTID_INT64) | 173 | if (id == CTID_INT64) |
@@ -231,13 +216,43 @@ int lj_carith_op(lua_State *L, MMS mm) | |||
231 | /* -- 64 bit integer arithmetic helpers ----------------------------------- */ | 216 | /* -- 64 bit integer arithmetic helpers ----------------------------------- */ |
232 | 217 | ||
233 | #if LJ_32 | 218 | #if LJ_32 |
234 | /* Signed/unsigned 64 bit multiply. */ | 219 | /* Signed/unsigned 64 bit multiplication. */ |
235 | int64_t lj_carith_mul64(int64_t a, int64_t b) | 220 | int64_t lj_carith_mul64(int64_t a, int64_t b) |
236 | { | 221 | { |
237 | return a * b; | 222 | return a * b; |
238 | } | 223 | } |
239 | #endif | 224 | #endif |
240 | 225 | ||
226 | /* Unsigned 64 bit division. */ | ||
227 | uint64_t lj_carith_divu64(uint64_t a, uint64_t b) | ||
228 | { | ||
229 | if (b == 0) return U64x(80000000,00000000); | ||
230 | return a / b; | ||
231 | } | ||
232 | |||
233 | /* Signed 64 bit division. */ | ||
234 | int64_t lj_carith_divi64(int64_t a, int64_t b) | ||
235 | { | ||
236 | if (b == 0 || (a == (int64_t)U64x(80000000,00000000) && b == -1)) | ||
237 | return U64x(80000000,00000000); | ||
238 | return a / b; | ||
239 | } | ||
240 | |||
241 | /* Unsigned 64 bit modulo. */ | ||
242 | uint64_t lj_carith_modu64(uint64_t a, uint64_t b) | ||
243 | { | ||
244 | if (b == 0) return U64x(80000000,00000000); | ||
245 | return a % b; | ||
246 | } | ||
247 | |||
248 | /* Signed 64 bit modulo. */ | ||
249 | int64_t lj_carith_modi64(int64_t a, int64_t b) | ||
250 | { | ||
251 | if (b == 0) return U64x(80000000,00000000); | ||
252 | if (a == (int64_t)U64x(80000000,00000000) && b == -1) return 0; | ||
253 | return a % b; | ||
254 | } | ||
255 | |||
241 | /* Unsigned 64 bit x^k. */ | 256 | /* Unsigned 64 bit x^k. */ |
242 | uint64_t lj_carith_powu64(uint64_t x, uint64_t k) | 257 | uint64_t lj_carith_powu64(uint64_t x, uint64_t k) |
243 | { | 258 | { |
diff --git a/src/lj_carith.h b/src/lj_carith.h index 14073603..faef7a07 100644 --- a/src/lj_carith.h +++ b/src/lj_carith.h | |||
@@ -15,6 +15,10 @@ LJ_FUNC int lj_carith_op(lua_State *L, MMS mm); | |||
15 | #if LJ_32 | 15 | #if LJ_32 |
16 | LJ_FUNC int64_t lj_carith_mul64(int64_t x, int64_t k); | 16 | LJ_FUNC int64_t lj_carith_mul64(int64_t x, int64_t k); |
17 | #endif | 17 | #endif |
18 | LJ_FUNC uint64_t lj_carith_divu64(uint64_t a, uint64_t b); | ||
19 | LJ_FUNC int64_t lj_carith_divi64(int64_t a, int64_t b); | ||
20 | LJ_FUNC uint64_t lj_carith_modu64(uint64_t a, uint64_t b); | ||
21 | LJ_FUNC int64_t lj_carith_modi64(int64_t a, int64_t b); | ||
18 | LJ_FUNC uint64_t lj_carith_powu64(uint64_t x, uint64_t k); | 22 | LJ_FUNC uint64_t lj_carith_powu64(uint64_t x, uint64_t k); |
19 | LJ_FUNC int64_t lj_carith_powi64(int64_t x, int64_t k); | 23 | LJ_FUNC int64_t lj_carith_powi64(int64_t x, int64_t k); |
20 | 24 | ||
diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 5eafa3a7..cd5c7d49 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c | |||
@@ -700,8 +700,6 @@ static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm) | |||
700 | J->postproc = LJ_POST_FIXGUARD; | 700 | J->postproc = LJ_POST_FIXGUARD; |
701 | return TREF_TRUE; | 701 | return TREF_TRUE; |
702 | } else { | 702 | } else { |
703 | if (mm == MM_div || mm == MM_mod) | ||
704 | return 0; /* NYI: integer div, mod. */ | ||
705 | tr = emitir(IRT(mm+(int)IR_ADD-(int)MM_add, dt), sp[0], sp[1]); | 703 | tr = emitir(IRT(mm+(int)IR_ADD-(int)MM_add, dt), sp[0], sp[1]); |
706 | } | 704 | } |
707 | dp = emitir(IRTG(IR_CNEW, IRT_CDATA), lj_ir_kint(J, id), TREF_NIL); | 705 | dp = emitir(IRTG(IR_CNEW, IRT_CDATA), lj_ir_kint(J, id), TREF_NIL); |
diff --git a/src/lj_ir.h b/src/lj_ir.h index 286eb219..d2ad87f3 100644 --- a/src/lj_ir.h +++ b/src/lj_ir.h | |||
@@ -10,7 +10,7 @@ | |||
10 | 10 | ||
11 | /* -- IR instructions ----------------------------------------------------- */ | 11 | /* -- IR instructions ----------------------------------------------------- */ |
12 | 12 | ||
13 | /* IR instruction definition. Order matters, see below. */ | 13 | /* IR instruction definition. Order matters, see below. ORDER IR */ |
14 | #define IRDEF(_) \ | 14 | #define IRDEF(_) \ |
15 | /* Guarded assertions. */ \ | 15 | /* Guarded assertions. */ \ |
16 | /* Must be properly aligned to flip opposites (^1) and (un)ordered (^4). */ \ | 16 | /* Must be properly aligned to flip opposites (^1) and (un)ordered (^4). */ \ |
@@ -61,21 +61,21 @@ | |||
61 | _(BROL, N , ref, ref) \ | 61 | _(BROL, N , ref, ref) \ |
62 | _(BROR, N , ref, ref) \ | 62 | _(BROR, N , ref, ref) \ |
63 | \ | 63 | \ |
64 | /* Arithmetic ops. ORDER ARITH (FPMATH/POWI take the space for MOD/POW). */ \ | 64 | /* Arithmetic ops. ORDER ARITH */ \ |
65 | _(ADD, C , ref, ref) \ | 65 | _(ADD, C , ref, ref) \ |
66 | _(SUB, N , ref, ref) \ | 66 | _(SUB, N , ref, ref) \ |
67 | _(MUL, C , ref, ref) \ | 67 | _(MUL, C , ref, ref) \ |
68 | _(DIV, N , ref, ref) \ | 68 | _(DIV, N , ref, ref) \ |
69 | \ | 69 | _(MOD, N , ref, ref) \ |
70 | _(FPMATH, N , ref, lit) \ | ||
71 | _(POWI, N , ref, ref) \ | 70 | _(POWI, N , ref, ref) \ |
72 | \ | ||
73 | _(NEG, N , ref, ref) \ | 71 | _(NEG, N , ref, ref) \ |
72 | \ | ||
74 | _(ABS, N , ref, ref) \ | 73 | _(ABS, N , ref, ref) \ |
75 | _(ATAN2, N , ref, ref) \ | 74 | _(ATAN2, N , ref, ref) \ |
76 | _(LDEXP, N , ref, ref) \ | 75 | _(LDEXP, N , ref, ref) \ |
77 | _(MIN, C , ref, ref) \ | 76 | _(MIN, C , ref, ref) \ |
78 | _(MAX, C , ref, ref) \ | 77 | _(MAX, C , ref, ref) \ |
78 | _(FPMATH, N , ref, lit) \ | ||
79 | \ | 79 | \ |
80 | /* Overflow-checking arithmetic ops. */ \ | 80 | /* Overflow-checking arithmetic ops. */ \ |
81 | _(ADDOV, C , ref, ref) \ | 81 | _(ADDOV, C , ref, ref) \ |
@@ -266,6 +266,10 @@ typedef struct CCallInfo { | |||
266 | #endif | 266 | #endif |
267 | #define IRCALLDEF_FFI(_) \ | 267 | #define IRCALLDEF_FFI(_) \ |
268 | IRCALLDEF_FFI32(_) \ | 268 | IRCALLDEF_FFI32(_) \ |
269 | _(lj_carith_divi64, ARG2_64, N, I64, CCI_NOFPRCLOBBER) \ | ||
270 | _(lj_carith_divu64, ARG2_64, N, U64, CCI_NOFPRCLOBBER) \ | ||
271 | _(lj_carith_modi64, ARG2_64, N, I64, CCI_NOFPRCLOBBER) \ | ||
272 | _(lj_carith_modu64, ARG2_64, N, U64, CCI_NOFPRCLOBBER) \ | ||
269 | _(lj_carith_powi64, ARG2_64, N, I64, CCI_NOFPRCLOBBER) \ | 273 | _(lj_carith_powi64, ARG2_64, N, I64, CCI_NOFPRCLOBBER) \ |
270 | _(lj_carith_powu64, ARG2_64, N, U64, CCI_NOFPRCLOBBER) | 274 | _(lj_carith_powu64, ARG2_64, N, U64, CCI_NOFPRCLOBBER) |
271 | #else | 275 | #else |
@@ -584,12 +588,12 @@ typedef union IRIns { | |||
584 | #define ir_kptr(ir) \ | 588 | #define ir_kptr(ir) \ |
585 | check_exp((ir)->o == IR_KPTR || (ir)->o == IR_KKPTR, mref((ir)->ptr, void)) | 589 | check_exp((ir)->o == IR_KPTR || (ir)->o == IR_KKPTR, mref((ir)->ptr, void)) |
586 | 590 | ||
587 | LJ_STATIC_ASSERT((int)IRT_GUARD == (int)IRM_W); | ||
588 | |||
589 | /* A store or any other op with a non-weak guard has a side-effect. */ | 591 | /* A store or any other op with a non-weak guard has a side-effect. */ |
590 | static LJ_AINLINE int ir_sideeff(IRIns *ir) | 592 | static LJ_AINLINE int ir_sideeff(IRIns *ir) |
591 | { | 593 | { |
592 | return (((ir->t.irt | ~IRT_GUARD) & lj_ir_mode[ir->o]) >= IRM_S); | 594 | return (((ir->t.irt | ~IRT_GUARD) & lj_ir_mode[ir->o]) >= IRM_S); |
593 | } | 595 | } |
594 | 596 | ||
597 | LJ_STATIC_ASSERT((int)IRT_GUARD == (int)IRM_W); | ||
598 | |||
595 | #endif | 599 | #endif |
diff --git a/src/lj_opt_split.c b/src/lj_opt_split.c index 3cb30514..f4339e85 100644 --- a/src/lj_opt_split.c +++ b/src/lj_opt_split.c | |||
@@ -197,6 +197,16 @@ static void split_ir(jit_State *J) | |||
197 | case IR_MUL: | 197 | case IR_MUL: |
198 | hi = split_call64(J, hisubst, oir, ir, IRCALL_lj_carith_mul64); | 198 | hi = split_call64(J, hisubst, oir, ir, IRCALL_lj_carith_mul64); |
199 | break; | 199 | break; |
200 | case IR_DIV: | ||
201 | hi = split_call64(J, hisubst, oir, ir, | ||
202 | irt_isi64(ir->t) ? IRCALL_lj_carith_divi64 : | ||
203 | IRCALL_lj_carith_divu64); | ||
204 | break; | ||
205 | case IR_MOD: | ||
206 | hi = split_call64(J, hisubst, oir, ir, | ||
207 | irt_isi64(ir->t) ? IRCALL_lj_carith_modi64 : | ||
208 | IRCALL_lj_carith_modu64); | ||
209 | break; | ||
200 | case IR_POWI: | 210 | case IR_POWI: |
201 | hi = split_call64(J, hisubst, oir, ir, | 211 | hi = split_call64(J, hisubst, oir, ir, |
202 | irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 : | 212 | irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 : |