aboutsummaryrefslogtreecommitdiffhomepage
path: root/amd64/emit.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2025-10-23 10:14:11 +0200
committerlemon <lsof@mailbox.org>2025-10-23 10:14:11 +0200
commit37643338d176c7612bddef054ae46c8cba8e352b (patch)
tree5789e49292bddf1fef57d5fcb3d1585bfef0b43c /amd64/emit.c
parent6149bc3a40e55ec6525aed42c9f2b2d480f20969 (diff)
amd64: load/store from abs address constants; movabs
Diffstat (limited to 'amd64/emit.c')
-rw-r--r--amd64/emit.c43
1 files changed, 32 insertions, 11 deletions
diff --git a/amd64/emit.c b/amd64/emit.c
index 044098d..bf7813f 100644
--- a/amd64/emit.c
+++ b/amd64/emit.c
@@ -140,6 +140,12 @@ mkmemoper(union ref r)
.cindex = addr->index.bits ? mkregoper(addr->index).reg : NOINDEX,
.cshift = addr->shift,
.disp = addr->disp);
+ } else if (isintcon(addr->base)) {
+ assert(!addr->disp);
+ return mkoper(OMEM, .base = NOBASE,
+ .index = addr->index.bits ? mkregoper(addr->index).reg : NOINDEX,
+ .disp = intconval(addr->base),
+ .shift = addr->shift);
} else if (isaddrcon(addr->index)) {
assert(!addr->shift);
return mkoper(OSYM, .con = addr->index.i,
@@ -351,13 +357,21 @@ encode(uchar **pcode, const struct desc *tab, int ntab, enum irclass k, struct o
}
}
- if (mem.index == NOINDEX && mem.shift == 0) sib = 0;
- else sib = 1;
- mod = !mem.disp ? 0 /* disp = 0 -> mod = 00 */
- : (uint)(mem.disp + 128) < 256 ? 1 /* disp8 -> mod = 01 */
- : 2; /* disp32 -> mod = 10 */
- if (mod == 0 && (mem.base == RBP || mem.base == R13)) mod = 1;
- if (mem.base == RSP || mem.base == R12) sib = 1;
+ if (mem.base != NOBASE) {
+ if (mem.index == NOINDEX && mem.shift == 0) sib = 0;
+ else sib = 1;
+ mod = !mem.disp ? 0 /* disp = 0 -> mod = 00 */
+ : (uint)(mem.disp + 128) < 256 ? 1 /* disp8 -> mod = 01 */
+ : 2; /* disp32 -> mod = 10 */
+ if (mod == 0 && (mem.base == RBP || mem.base == R13)) mod = 1;
+ if (mem.base == RSP || mem.base == R12) sib = 1;
+ } else {
+ /* [disp + (index*s)] */
+ sib = 1;
+ mem.base = RBP;
+ mod = 0;
+ assert(mem.index != RSP);
+ }
D(opc, nopc);
B(mod << 6 | (reg & 7) << 3 | (sib ? 4 : (mem.base & 7)));
if (sib) {
@@ -365,7 +379,7 @@ encode(uchar **pcode, const struct desc *tab, int ntab, enum irclass k, struct o
B(mem.shift << 6 | (mem.index & 7) << 3 | (mem.base & 7));
}
if (mod == 1) B(mem.disp);
- else if (mod == 2 || (mod == 0 && mem.base == RBP/*RIP-rel*/)) {
+ else if (mod == 2 || (mod == 0 && mem.base == RBP/*RIP-rel*/) || (mod == 0 && sib && mem.base == RSP/*absolute*/)) {
I32(mem.disp);
}
}
@@ -842,11 +856,18 @@ gencopy(uchar **pcode, enum irclass cls, struct block *blk, int curi, struct ope
Xxor(pcode, kisint(cls) ? KI4 : cls, dst, dst);
} else if (isaddrcon(val)) {
if (ccopt.pic) GOTLoad:
- /* for mov reg, [rip(sym@GOTPCREL)] */
+ /* for mov reg, [rip(sym@GOTPCREL)] */
Xmov(pcode, cls, dst, mkoper(OSYM, .con = val.i, .cindex = NOINDEX));
else
- /* for lea reg, [rip(sym)] */
+ /* for lea reg, [rip(sym)] */
Xlea(pcode, cls, dst, mkoper(OSYM, .con = val.i, .cindex = NOINDEX));
+ } else if (val.t == RXCON && in_range(concls(val), KI8, KPTR)) {
+ /* movabs */
+ assert(dst.t == OREG && in_range(dst.reg, RAX, R15));
+ B(0x48 | (dst.reg >> 3)); /* REX.W (+ REX.B) */
+ B(0xB8 + (dst.reg & 0x7)); /* MOVABS r64, */
+ wr64le(*pcode, intconval(val)); /* imm64 */
+ *pcode += 8;
} else {
struct oper src = mkimmdatregoper(val);
if (memcmp(&dst, &src, sizeof dst) != 0)
@@ -971,7 +992,7 @@ emitinstr(uchar **pcode, struct function *fn, struct block *blk, int curi, struc
assert(ins->reg-1 == dst.reg);
X1(pcode, cls, dst);
break;
- case Omul:
+ case Omul:
if (kisint(cls))
case Oumul:
Ximul(pcode, cls, reg2oper(ins->reg-1), ref2oper(ins->l), ref2oper(ins->r));