aboutsummaryrefslogtreecommitdiff
path: root/src/lj_emit_x86.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_emit_x86.h')
-rw-r--r--src/lj_emit_x86.h121
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] */
98static 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] */
111static void emit_rmro(ASMState *as, x86Op xo, Reg rr, Reg rb, int32_t ofs) 103static 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] */
339static 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. */
317static void emit_loadk64(ASMState *as, Reg r, IRIns *ir) 364static 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