aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2011-02-02 20:53:10 +0100
committerMike Pall <mike>2011-02-02 21:24:55 +0100
commita1e0f991d8407b1942be0389332e3f24810f5f7a (patch)
tree783a750366a41020532f2b66562a4e33082bb071 /src
parent2c8945d3e734bb42faa60ef0b97a6115a2b099f7 (diff)
downloadluajit-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.c31
-rw-r--r--src/lj_carith.c55
-rw-r--r--src/lj_carith.h4
-rw-r--r--src/lj_crecord.c2
-rw-r--r--src/lj_ir.h18
-rw-r--r--src/lj_opt_split.c10
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. */
235int64_t lj_carith_mul64(int64_t a, int64_t b) 220int64_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. */
227uint64_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. */
234int64_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. */
242uint64_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. */
249int64_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. */
242uint64_t lj_carith_powu64(uint64_t x, uint64_t k) 257uint64_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
16LJ_FUNC int64_t lj_carith_mul64(int64_t x, int64_t k); 16LJ_FUNC int64_t lj_carith_mul64(int64_t x, int64_t k);
17#endif 17#endif
18LJ_FUNC uint64_t lj_carith_divu64(uint64_t a, uint64_t b);
19LJ_FUNC int64_t lj_carith_divi64(int64_t a, int64_t b);
20LJ_FUNC uint64_t lj_carith_modu64(uint64_t a, uint64_t b);
21LJ_FUNC int64_t lj_carith_modi64(int64_t a, int64_t b);
18LJ_FUNC uint64_t lj_carith_powu64(uint64_t x, uint64_t k); 22LJ_FUNC uint64_t lj_carith_powu64(uint64_t x, uint64_t k);
19LJ_FUNC int64_t lj_carith_powi64(int64_t x, int64_t k); 23LJ_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
587LJ_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. */
590static LJ_AINLINE int ir_sideeff(IRIns *ir) 592static 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
597LJ_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 :