diff options
| author | 2023-06-12 18:20:12 +0200 | |
|---|---|---|
| committer | 2023-06-12 18:20:12 +0200 | |
| commit | 1b56e5832e54a0fe8876bf12013b8164f0c05a92 (patch) | |
| tree | 596edb72a0ad3a5c45788c998b4569051cd373eb /amd64 | |
| parent | 3ea93dd6d7df07b1c46d3a07c997890a511db0c1 (diff) | |
amd64/emit: emit LEA for 3-address ADD
Diffstat (limited to 'amd64')
| -rw-r--r-- | amd64/emit.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/amd64/emit.c b/amd64/emit.c index cf8d325..a89b021 100644 --- a/amd64/emit.c +++ b/amd64/emit.c @@ -461,11 +461,22 @@ emitinstr(uchar **pcode, uint *stktop, struct function *fn, struct block *blk, i case Oloadu4: src = mkmemoper(ins->l); Movzx4: Xmov(pcode, 4, reg2oper(ins->reg-1), src); break; case Oloadf4: case Oloadf8: case Oloadi8: Xmov(pcode, ksiz, reg2oper(ins->reg-1), mkmemoper(ins->l)); break; - case Oadd: X = Xadd; goto ALU2; + case Oadd: + dst = mkregoper(ins->l); + if (ins->reg-1 == dst.reg) { /* two-address add */ + Xadd(pcode, ksiz, dst, mkimmdatregoper(ins->r)); + } else { /* three-address add (lea) */ + struct oper mem = { OMEM, .index = NOINDEX }; + dst = mkoper(OREG, .reg = ins->reg-1); + if (isregref(ins->r)) mem.base = mkregoper(ins->r).reg; + else mem.disp = mkimmoper(ins->r).imm; + Xlea(pcode, ksiz, dst, mem); + } + break; case Oshl: X = Xshl; goto ALU2; ALU2: - dst = ref2oper(ins->l); - assert(dst.t == OREG && ins->reg-1 == dst.reg); + dst = mkregoper(ins->l); + assert(ins->reg-1 == dst.reg); X(pcode, ksiz, dst, mkimmdatregoper(ins->r)); break; case Odiv: case Orem: |