aboutsummaryrefslogtreecommitdiffhomepage
path: root/amd64/emit.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2023-07-07 19:00:13 +0200
committerlemon <lsof@mailbox.org>2023-07-07 19:00:13 +0200
commit2b78832d3e433e08d742011aa5b7f87396b24c7d (patch)
tree8f5e25f203b54872cde9492245d42a2af60da02b /amd64/emit.c
parent3a7675d100c8559bf53ef8043d446661b72f2e4e (diff)
amd64 codegen fixes
Diffstat (limited to 'amd64/emit.c')
-rw-r--r--amd64/emit.c31
1 files changed, 19 insertions, 12 deletions
diff --git a/amd64/emit.c b/amd64/emit.c
index 088809d..6d6d70b 100644
--- a/amd64/emit.c
+++ b/amd64/emit.c
@@ -127,14 +127,14 @@ mkmemoper(union ref r)
}
if (isaddrcon(addr->base)) {
return mkoper(OSYM, .con = addr->base.i,
- .cindex = addr->index.bits ? mkregoper(addr->index).reg : NOINDEX,
- .cshift = addr->shift,
- .disp = addr->disp);
+ .cindex = addr->index.bits ? mkregoper(addr->index).reg : NOINDEX,
+ .cshift = addr->shift,
+ .disp = addr->disp);
} else if (isaddrcon(addr->index)) {
assert(!addr->shift);
return mkoper(OSYM, .con = addr->index.i,
- .cindex = addr->base.bits ? mkregoper(addr->base).reg : NOINDEX,
- .disp = addr->disp);
+ .cindex = addr->base.bits ? mkregoper(addr->base).reg : NOINDEX,
+ .disp = addr->disp);
}
return mkoper(OMEM, .base = addr->base.bits ? mkregoper(addr->base).reg : NOBASE,
.index = addr->index.bits ? mkregoper(addr->index).reg : NOINDEX,
@@ -192,6 +192,7 @@ enum operenc {
EN_I8, /* imm8 */
EN_I32, /* imm32 */
EN_R32, /* rel32 */
+ NOPERENC,
};
struct desc {
uchar psiz; /* subset of {1,2,4,8} */
@@ -307,8 +308,10 @@ encode(uchar **pcode, const struct desc *tab, int ntab, enum irclass k, struct o
D(opc, nopc);
if (mem.cindex == NOINDEX) {
/* %rip(var) */
+ static uchar offs[NOPERENC] = { [EN_MI8] = 1, [EN_MI16] = 2, [EN_MI32] = 4 };
+ int off = -4 - offs[en->operenc];
B(/*mod 0*/ (reg & 7) << 3 | RBP);
- objreloc(xcon2sym(mem.con), REL_PCREL32, Stext, *pcode - objout.textbegin, -4 + mem.disp);
+ objreloc(xcon2sym(mem.con), REL_PCREL32, Stext, *pcode - objout.textbegin, mem.disp + off);
} else {
/* var(,%reg,shift) */
B(/*mod 0*/ (reg & 7) << 3 | RSP);
@@ -917,14 +920,18 @@ emitbranch(uchar **pcode, struct block *blk)
struct instr *ins;
assert(arg.t == RTMP);
ins = &instrtab[arg.i];
- assert(oiscmp(ins->op) || ins->op == Oand || ins->op == Osub);
/* TODO handle float cmps */
- if (ins->r.bits != ZEROREF.bits) {
- /* for CMP instr */
- cc = icmpop2cc[ins->op];
+ if ((oiscmp(ins->op) || ins->op == Oand || ins->op == Osub)) {
+ if (ins->r.bits != ZEROREF.bits) {
+ /* for CMP instr */
+ cc = icmpop2cc[ins->op];
+ } else {
+ /* for TEST instr, which modifies ZF and SF and sets CF = OF = 0 */
+ cc = icmpzero2cc[ins->op];
+ }
} else {
- /* for TEST instr, which modifies ZF and SF and sets CF = OF = 0 */
- cc = icmpzero2cc[ins->op];
+ /* implicit by ZF */
+ cc = CCNZ;
}
if (blk->s1 == blk->lnext) {
/* if s1 is next adjacent block, swap s1,s2 and flip condition to emit a