diff options
Diffstat (limited to 'src/lj_emit_x86.h')
-rw-r--r-- | src/lj_emit_x86.h | 121 |
1 files changed, 95 insertions, 26 deletions
diff --git a/src/lj_emit_x86.h b/src/lj_emit_x86.h index 3d6f13f4..f0bca938 100644 --- a/src/lj_emit_x86.h +++ b/src/lj_emit_x86.h | |||
@@ -20,6 +20,11 @@ | |||
20 | #define REX_64 0 | 20 | #define REX_64 0 |
21 | #define VEX_64 0 | 21 | #define VEX_64 0 |
22 | #endif | 22 | #endif |
23 | #if LJ_GC64 | ||
24 | #define REX_GC64 REX_64 | ||
25 | #else | ||
26 | #define REX_GC64 0 | ||
27 | #endif | ||
23 | 28 | ||
24 | #define emit_i8(as, i) (*--as->mcp = (MCode)(i)) | 29 | #define emit_i8(as, i) (*--as->mcp = (MCode)(i)) |
25 | #define emit_i32(as, i) (*(int32_t *)(as->mcp-4) = (i), as->mcp -= 4) | 30 | #define emit_i32(as, i) (*(int32_t *)(as->mcp-4) = (i), as->mcp -= 4) |
@@ -94,26 +99,17 @@ static int32_t ptr2addr(const void *p) | |||
94 | #define ptr2addr(p) (i32ptr((p))) | 99 | #define ptr2addr(p) (i32ptr((p))) |
95 | #endif | 100 | #endif |
96 | 101 | ||
97 | /* op r, [addr] */ | ||
98 | static void emit_rma(ASMState *as, x86Op xo, Reg rr, const void *addr) | ||
99 | { | ||
100 | MCode *p = as->mcp; | ||
101 | *(int32_t *)(p-4) = ptr2addr(addr); | ||
102 | #if LJ_64 | ||
103 | p[-5] = MODRM(XM_SCALE1, RID_ESP, RID_EBP); | ||
104 | as->mcp = emit_opm(xo, XM_OFS0, rr, RID_ESP, p, -5); | ||
105 | #else | ||
106 | as->mcp = emit_opm(xo, XM_OFS0, rr, RID_EBP, p, -4); | ||
107 | #endif | ||
108 | } | ||
109 | |||
110 | /* op r, [base+ofs] */ | 102 | /* op r, [base+ofs] */ |
111 | static void emit_rmro(ASMState *as, x86Op xo, Reg rr, Reg rb, int32_t ofs) | 103 | static void emit_rmro(ASMState *as, x86Op xo, Reg rr, Reg rb, int32_t ofs) |
112 | { | 104 | { |
113 | MCode *p = as->mcp; | 105 | MCode *p = as->mcp; |
114 | x86Mode mode; | 106 | x86Mode mode; |
115 | if (ra_hasreg(rb)) { | 107 | if (ra_hasreg(rb)) { |
116 | if (ofs == 0 && (rb&7) != RID_EBP) { | 108 | if (LJ_GC64 && rb == RID_RIP) { |
109 | mode = XM_OFS0; | ||
110 | p -= 4; | ||
111 | *(int32_t *)p = ofs; | ||
112 | } else if (ofs == 0 && (rb&7) != RID_EBP) { | ||
117 | mode = XM_OFS0; | 113 | mode = XM_OFS0; |
118 | } else if (checki8(ofs)) { | 114 | } else if (checki8(ofs)) { |
119 | *--p = (MCode)ofs; | 115 | *--p = (MCode)ofs; |
@@ -211,6 +207,11 @@ static void emit_mrm(ASMState *as, x86Op xo, Reg rr, Reg rb) | |||
211 | *--p = MODRM(XM_SCALE1, RID_ESP, RID_EBP); | 207 | *--p = MODRM(XM_SCALE1, RID_ESP, RID_EBP); |
212 | rb = RID_ESP; | 208 | rb = RID_ESP; |
213 | #endif | 209 | #endif |
210 | } else if (LJ_GC64 && rb == RID_RIP) { | ||
211 | lua_assert(as->mrm.idx == RID_NONE); | ||
212 | mode = XM_OFS0; | ||
213 | p -= 4; | ||
214 | *(int32_t *)p = as->mrm.ofs; | ||
214 | } else { | 215 | } else { |
215 | if (as->mrm.ofs == 0 && (rb&7) != RID_EBP) { | 216 | if (as->mrm.ofs == 0 && (rb&7) != RID_EBP) { |
216 | mode = XM_OFS0; | 217 | mode = XM_OFS0; |
@@ -264,8 +265,8 @@ static void emit_movmroi(ASMState *as, Reg base, int32_t ofs, int32_t i) | |||
264 | /* Get/set global_State fields. */ | 265 | /* Get/set global_State fields. */ |
265 | #define emit_opgl(as, xo, r, field) \ | 266 | #define emit_opgl(as, xo, r, field) \ |
266 | emit_rma(as, (xo), (r), (void *)&J2G(as->J)->field) | 267 | emit_rma(as, (xo), (r), (void *)&J2G(as->J)->field) |
267 | #define emit_getgl(as, r, field) emit_opgl(as, XO_MOV, (r), field) | 268 | #define emit_getgl(as, r, field) emit_opgl(as, XO_MOV, (r)|REX_GC64, field) |
268 | #define emit_setgl(as, r, field) emit_opgl(as, XO_MOVto, (r), field) | 269 | #define emit_setgl(as, r, field) emit_opgl(as, XO_MOVto, (r)|REX_GC64, field) |
269 | 270 | ||
270 | #define emit_setvmstate(as, i) \ | 271 | #define emit_setvmstate(as, i) \ |
271 | (emit_i32(as, i), emit_opgl(as, XO_MOVmi, 0, vmstate)) | 272 | (emit_i32(as, i), emit_opgl(as, XO_MOVmi, 0, vmstate)) |
@@ -288,9 +289,21 @@ static void emit_loadi(ASMState *as, Reg r, int32_t i) | |||
288 | } | 289 | } |
289 | } | 290 | } |
290 | 291 | ||
292 | #if LJ_GC64 | ||
293 | #define dispofs(as, k) \ | ||
294 | ((intptr_t)((uintptr_t)(k) - (uintptr_t)J2GG(as->J)->dispatch)) | ||
295 | #define mcpofs(as, k) \ | ||
296 | ((intptr_t)((uintptr_t)(k) - (uintptr_t)as->mcp)) | ||
297 | #define mctopofs(as, k) \ | ||
298 | ((intptr_t)((uintptr_t)(k) - (uintptr_t)as->mctop)) | ||
299 | /* mov r, addr */ | ||
300 | #define emit_loada(as, r, addr) \ | ||
301 | emit_loadu64(as, (r), (uintptr_t)(addr)) | ||
302 | #else | ||
291 | /* mov r, addr */ | 303 | /* mov r, addr */ |
292 | #define emit_loada(as, r, addr) \ | 304 | #define emit_loada(as, r, addr) \ |
293 | emit_loadi(as, (r), ptr2addr((addr))) | 305 | emit_loadi(as, (r), ptr2addr((addr))) |
306 | #endif | ||
294 | 307 | ||
295 | #if LJ_64 | 308 | #if LJ_64 |
296 | /* mov r, imm64 or shorter 32 bit extended load. */ | 309 | /* mov r, imm64 or shorter 32 bit extended load. */ |
@@ -302,6 +315,15 @@ static void emit_loadu64(ASMState *as, Reg r, uint64_t u64) | |||
302 | MCode *p = as->mcp; | 315 | MCode *p = as->mcp; |
303 | *(int32_t *)(p-4) = (int32_t)u64; | 316 | *(int32_t *)(p-4) = (int32_t)u64; |
304 | as->mcp = emit_opm(XO_MOVmi, XM_REG, REX_64, r, p, -4); | 317 | as->mcp = emit_opm(XO_MOVmi, XM_REG, REX_64, r, p, -4); |
318 | #if LJ_GC64 | ||
319 | } else if (checki32(dispofs(as, u64))) { | ||
320 | emit_rmro(as, XO_LEA, r|REX_64, RID_DISPATCH, (int32_t)dispofs(as, u64)); | ||
321 | } else if (checki32(mcpofs(as, u64)) && checki32(mctopofs(as, u64))) { | ||
322 | /* Since as->realign assumes the code size doesn't change, check | ||
323 | ** RIP-relative addressing reachability for both as->mcp and as->mctop. | ||
324 | */ | ||
325 | emit_rmro(as, XO_LEA, r|REX_64, RID_RIP, (int32_t)mcpofs(as, u64)); | ||
326 | #endif | ||
305 | } else { /* Full-size 64 bit load. */ | 327 | } else { /* Full-size 64 bit load. */ |
306 | MCode *p = as->mcp; | 328 | MCode *p = as->mcp; |
307 | *(uint64_t *)(p-8) = u64; | 329 | *(uint64_t *)(p-8) = u64; |
@@ -313,22 +335,69 @@ static void emit_loadu64(ASMState *as, Reg r, uint64_t u64) | |||
313 | } | 335 | } |
314 | #endif | 336 | #endif |
315 | 337 | ||
338 | /* op r, [addr] */ | ||
339 | static void emit_rma(ASMState *as, x86Op xo, Reg rr, const void *addr) | ||
340 | { | ||
341 | #if LJ_GC64 | ||
342 | if (checki32(dispofs(as, addr))) { | ||
343 | emit_rmro(as, xo, rr, RID_DISPATCH, (int32_t)dispofs(as, addr)); | ||
344 | } else if (checki32(mcpofs(as, addr)) && checki32(mctopofs(as, addr))) { | ||
345 | emit_rmro(as, xo, rr, RID_RIP, (int32_t)mcpofs(as, addr)); | ||
346 | } else if (!checki32((intptr_t)addr) && (xo == XO_MOV || xo == XO_MOVSD)) { | ||
347 | emit_rmro(as, xo, rr, rr, 0); | ||
348 | emit_loadu64(as, rr, (uintptr_t)addr); | ||
349 | } else | ||
350 | #endif | ||
351 | { | ||
352 | MCode *p = as->mcp; | ||
353 | *(int32_t *)(p-4) = ptr2addr(addr); | ||
354 | #if LJ_64 | ||
355 | p[-5] = MODRM(XM_SCALE1, RID_ESP, RID_EBP); | ||
356 | as->mcp = emit_opm(xo, XM_OFS0, rr, RID_ESP, p, -5); | ||
357 | #else | ||
358 | as->mcp = emit_opm(xo, XM_OFS0, rr, RID_EBP, p, -4); | ||
359 | #endif | ||
360 | } | ||
361 | } | ||
362 | |||
316 | /* Load 64 bit IR constant into register. */ | 363 | /* Load 64 bit IR constant into register. */ |
317 | static void emit_loadk64(ASMState *as, Reg r, IRIns *ir) | 364 | static void emit_loadk64(ASMState *as, Reg r, IRIns *ir) |
318 | { | 365 | { |
366 | Reg r64; | ||
367 | x86Op xo; | ||
319 | const uint64_t *k = &ir_k64(ir)->u64; | 368 | const uint64_t *k = &ir_k64(ir)->u64; |
320 | if (rset_test(RSET_FPR, r)) { | 369 | if (rset_test(RSET_FPR, r)) { |
321 | if (*k == 0) { | 370 | r64 = r; |
322 | emit_rr(as, XO_XORPS, r, r); | 371 | xo = XO_MOVSD; |
323 | } else { | ||
324 | emit_rma(as, XO_MOVSD, r, k); | ||
325 | } | ||
326 | } else { | 372 | } else { |
327 | if (*k == 0) { | 373 | r64 = r | REX_64; |
328 | emit_rr(as, XO_ARITH(XOg_XOR), r, r); | 374 | xo = XO_MOV; |
375 | } | ||
376 | if (*k == 0) { | ||
377 | emit_rr(as, rset_test(RSET_FPR, r) ? XO_XORPS : XO_ARITH(XOg_XOR), r, r); | ||
378 | #if LJ_GC64 | ||
379 | } else if (checki32((intptr_t)k) || checki32(dispofs(as, k)) || | ||
380 | (checki32(mcpofs(as, k)) && checki32(mctopofs(as, k)))) { | ||
381 | emit_rma(as, xo, r64, k); | ||
382 | } else { | ||
383 | if (ir->i) { | ||
384 | lua_assert(*k == *(uint64_t*)(as->mctop - ir->i)); | ||
385 | } else if (as->curins <= as->stopins && rset_test(RSET_GPR, r)) { | ||
386 | emit_loadu64(as, r, *k); | ||
387 | return; | ||
329 | } else { | 388 | } else { |
330 | emit_rma(as, XO_MOV, r | REX_64, k); | 389 | /* If all else fails, add the FP constant at the MCode area bottom. */ |
390 | while ((uintptr_t)as->mcbot & 7) *as->mcbot++ = XI_INT3; | ||
391 | *(uint64_t *)as->mcbot = *k; | ||
392 | ir->i = (int32_t)(as->mctop - as->mcbot); | ||
393 | as->mcbot += 8; | ||
394 | as->mclim = as->mcbot + MCLIM_REDZONE; | ||
331 | } | 395 | } |
396 | emit_rmro(as, xo, r64, RID_RIP, (int32_t)mcpofs(as, as->mctop - ir->i)); | ||
397 | #else | ||
398 | } else { | ||
399 | emit_rma(as, xo, r64, k); | ||
400 | #endif | ||
332 | } | 401 | } |
333 | } | 402 | } |
334 | 403 | ||
@@ -470,9 +539,9 @@ static void emit_addptr(ASMState *as, Reg r, int32_t ofs) | |||
470 | { | 539 | { |
471 | if (ofs) { | 540 | if (ofs) { |
472 | if ((as->flags & JIT_F_LEA_AGU)) | 541 | if ((as->flags & JIT_F_LEA_AGU)) |
473 | emit_rmro(as, XO_LEA, r, r, ofs); | 542 | emit_rmro(as, XO_LEA, r|REX_GC64, r, ofs); |
474 | else | 543 | else |
475 | emit_gri(as, XG_ARITHi(XOg_ADD), r, ofs); | 544 | emit_gri(as, XG_ARITHi(XOg_ADD), r|REX_GC64, ofs); |
476 | } | 545 | } |
477 | } | 546 | } |
478 | 547 | ||