From 2b78832d3e433e08d742011aa5b7f87396b24c7d Mon Sep 17 00:00:00 2001 From: lemon Date: Fri, 7 Jul 2023 19:00:13 +0200 Subject: [PATCH] amd64 codegen fixes --- amd64/emit.c | 31 +++++++++++++++++++------------ amd64/isel.c | 2 +- 2 files changed, 20 insertions(+), 13 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 diff --git a/amd64/isel.c b/amd64/isel.c index da5a128..df972fd 100644 --- a/amd64/isel.c +++ b/amd64/isel.c @@ -403,8 +403,8 @@ seljmp(struct function *fn, struct block *blk) } else { if (!(opflags[instrtab[c.i].op] & ZF) || c.i != blk->ins.p[blk->ins.n - 1]) { blk->jmp.arg[0] = insertinstr(blk, blk->ins.n, mkinstr(Oneq, instrtab[c.i].cls, c, ZEROREF)); + instrtab[blk->jmp.arg[0].i].keep = 1; } - instrtab[blk->jmp.arg[0].i].keep = 1; } } else if (blk->jmp.t == Jret) { if (blk->jmp.arg[0].bits) { -- 2.45.2