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 : |
