diff options
Diffstat (limited to 'src/lj_asm.c')
-rw-r--r-- | src/lj_asm.c | 90 |
1 files changed, 32 insertions, 58 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c index 215dfb13..27ccfe9a 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
@@ -2283,55 +2283,12 @@ static void asm_tdup(ASMState *as, IRIns *ir) | |||
2283 | } | 2283 | } |
2284 | 2284 | ||
2285 | #if LJ_HASFFI | 2285 | #if LJ_HASFFI |
2286 | static RegSet asm_cnew_init(ASMState *as, IRRef ref, int32_t ofs, RegSet allow) | ||
2287 | { | ||
2288 | IRIns *ir = IR(ref); | ||
2289 | if (irref_isk(ref)) { | ||
2290 | #if LJ_64 | ||
2291 | if (ir->o == IR_KNUM || ir->o == IR_KINT64) { | ||
2292 | uint64_t k = ir_k64(ir)->u64; | ||
2293 | if (checki32((int64_t)k)) { | ||
2294 | emit_i32(as, (int32_t)k); | ||
2295 | emit_rmro(as, XO_MOVmi, REX_64, RID_RET, ofs); | ||
2296 | } else { | ||
2297 | emit_movtomro(as, RID_ECX|REX_64, RID_RET, ofs); | ||
2298 | emit_loadu64(as, RID_ECX, k); | ||
2299 | } | ||
2300 | } else { | ||
2301 | emit_movmroi(as, RID_RET, ofs, ir->i); | ||
2302 | } | ||
2303 | #else | ||
2304 | if (ir->o == IR_KNUM) { | ||
2305 | emit_rmro(as, XO_MOVSDto, RID_XMM0, RID_RET, ofs); | ||
2306 | emit_loadn(as, RID_XMM0, ir_k64(ir)); | ||
2307 | } else if (ir->o == IR_KINT64) { | ||
2308 | uint64_t k = ir_k64(ir)->u64; | ||
2309 | emit_movmroi(as, RID_RET, ofs, (int32_t)k); | ||
2310 | emit_movmroi(as, RID_RET, ofs+4, (int32_t)(k >> 32)); | ||
2311 | } else { | ||
2312 | emit_movmroi(as, RID_RET, ofs, ir->i); | ||
2313 | } | ||
2314 | #endif | ||
2315 | } else { | ||
2316 | Reg r; | ||
2317 | if (irt_isnum(ir->t)) { | ||
2318 | r = ra_alloc1(as, ref, (RSET_FPR & allow)); | ||
2319 | emit_rmro(as, XO_MOVSDto, r, RID_RET, ofs); | ||
2320 | } else { | ||
2321 | r = ra_alloc1(as, ref, (RSET_GPR & allow)); | ||
2322 | emit_movtomro(as, REX_64IR(ir, r), RID_RET, ofs); | ||
2323 | } | ||
2324 | rset_clear(allow, r); | ||
2325 | } | ||
2326 | return allow; | ||
2327 | } | ||
2328 | |||
2329 | static void asm_cnew(ASMState *as, IRIns *ir) | 2286 | static void asm_cnew(ASMState *as, IRIns *ir) |
2330 | { | 2287 | { |
2331 | CTState *cts = ctype_ctsG(J2G(as->J)); | 2288 | CTState *cts = ctype_ctsG(J2G(as->J)); |
2332 | CTypeID typeid = (CTypeID)IR(ir->op2)->i; | 2289 | CTypeID typeid = (CTypeID)IR(ir->op1)->i; |
2333 | CTSize sz = (ir->o == IR_CNEWI || ir->op1 == REF_NIL) ? | 2290 | CTSize sz = (ir->o == IR_CNEWP || ir->op2 == REF_NIL) ? |
2334 | lj_ctype_size(cts, typeid) : (CTSize)IR(ir->op1)->i; | 2291 | lj_ctype_size(cts, typeid) : (CTSize)IR(ir->op2)->i; |
2335 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco]; | 2292 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco]; |
2336 | IRRef args[2]; | 2293 | IRRef args[2]; |
2337 | lua_assert(sz != CTSIZE_INVALID); | 2294 | lua_assert(sz != CTSIZE_INVALID); |
@@ -2339,18 +2296,35 @@ static void asm_cnew(ASMState *as, IRIns *ir) | |||
2339 | args[0] = ASMREF_L; /* lua_State *L */ | 2296 | args[0] = ASMREF_L; /* lua_State *L */ |
2340 | args[1] = ASMREF_TMP1; /* MSize size */ | 2297 | args[1] = ASMREF_TMP1; /* MSize size */ |
2341 | as->gcsteps++; | 2298 | as->gcsteps++; |
2342 | asm_setupresult(as, ir, ci); /* GCobj * */ | 2299 | asm_setupresult(as, ir, ci); /* GCcdata * */ |
2343 | 2300 | ||
2344 | /* Initialize immutable cdata object. */ | 2301 | /* Initialize pointer cdata object. */ |
2345 | if (ir->o == IR_CNEWI) { | 2302 | if (ir->o == IR_CNEWP) { |
2346 | RegSet allow = ~RSET_SCRATCH; | 2303 | if (irref_isk(ir->op2)) { |
2347 | IRRef ref = ir->op1; | 2304 | IRIns *irk = IR(ir->op2); |
2348 | if (IR(ref)->o == IR_CARG) { /* 2nd initializer. */ | 2305 | #if LJ_64 |
2349 | IRIns *ira = IR(ref); | 2306 | if (irk->o == IR_KINT64) { |
2350 | allow = asm_cnew_init(as, ira->op2, sizeof(GCcdata) + (sz>>1), allow); | 2307 | uint64_t k = ir_k64(irk)->u64; |
2351 | ref = ira->op1; | 2308 | lua_assert(sz == 8); |
2309 | if (checki32((int64_t)k)) { | ||
2310 | emit_i32(as, (int32_t)k); | ||
2311 | emit_rmro(as, XO_MOVmi, REX_64, RID_RET, sizeof(GCcdata)); | ||
2312 | } else { | ||
2313 | emit_movtomro(as, RID_ECX|REX_64, RID_RET, sizeof(GCcdata)); | ||
2314 | emit_loadu64(as, RID_ECX, k); | ||
2315 | } | ||
2316 | } else { | ||
2317 | #endif | ||
2318 | lua_assert(sz == 4); | ||
2319 | emit_movmroi(as, RID_RET, sizeof(GCcdata), irk->i); | ||
2320 | #if LJ_64 | ||
2321 | } | ||
2322 | #endif | ||
2323 | } else { | ||
2324 | Reg r = ra_alloc1(as, ir->op2, (RSET_GPR & ~RSET_SCRATCH)); | ||
2325 | emit_movtomro(as, r + ((LJ_64 && sz == 8) ? REX_64 : 0), | ||
2326 | RID_RET, sizeof(GCcdata)); | ||
2352 | } | 2327 | } |
2353 | asm_cnew_init(as, ref, sizeof(GCcdata), allow); /* 1st initializer. */ | ||
2354 | } | 2328 | } |
2355 | 2329 | ||
2356 | /* Combine initialization of marked, gct and typeid. */ | 2330 | /* Combine initialization of marked, gct and typeid. */ |
@@ -3675,7 +3649,7 @@ static void asm_ir(ASMState *as, IRIns *ir) | |||
3675 | case IR_SNEW: asm_snew(as, ir); break; | 3649 | case IR_SNEW: asm_snew(as, ir); break; |
3676 | case IR_TNEW: asm_tnew(as, ir); break; | 3650 | case IR_TNEW: asm_tnew(as, ir); break; |
3677 | case IR_TDUP: asm_tdup(as, ir); break; | 3651 | case IR_TDUP: asm_tdup(as, ir); break; |
3678 | case IR_CNEW: case IR_CNEWI: asm_cnew(as, ir); break; | 3652 | case IR_CNEW: case IR_CNEWP: asm_cnew(as, ir); break; |
3679 | 3653 | ||
3680 | /* Write barriers. */ | 3654 | /* Write barriers. */ |
3681 | case IR_TBAR: asm_tbar(as, ir); break; | 3655 | case IR_TBAR: asm_tbar(as, ir); break; |
@@ -3793,7 +3767,7 @@ static void asm_setup_regsp(ASMState *as, GCtrace *T) | |||
3793 | if (as->evenspill < 3) /* lj_str_new and lj_tab_newkey need 3 args. */ | 3767 | if (as->evenspill < 3) /* lj_str_new and lj_tab_newkey need 3 args. */ |
3794 | as->evenspill = 3; | 3768 | as->evenspill = 3; |
3795 | #endif | 3769 | #endif |
3796 | case IR_TNEW: case IR_TDUP: case IR_CNEW: case IR_CNEWI: case IR_TOSTR: | 3770 | case IR_TNEW: case IR_TDUP: case IR_CNEW: case IR_CNEWP: case IR_TOSTR: |
3797 | ir->prev = REGSP_HINT(RID_RET); | 3771 | ir->prev = REGSP_HINT(RID_RET); |
3798 | if (inloop) | 3772 | if (inloop) |
3799 | as->modset = RSET_SCRATCH; | 3773 | as->modset = RSET_SCRATCH; |