diff options
| -rw-r--r-- | amd64/emit.c | 5 | ||||
| -rw-r--r-- | ir/regalloc.c | 21 |
2 files changed, 21 insertions, 5 deletions
diff --git a/amd64/emit.c b/amd64/emit.c index 8f29cfc..e7dd724 100644 --- a/amd64/emit.c +++ b/amd64/emit.c @@ -529,7 +529,8 @@ DEFINSTR2(Xmovaps, ) DEFINSTR2(Xxchg, {4|8, PGPR, PGPR, "\x87", EN_RR}, /* XCHG r32/64, r32/64 */ - //{4|8, PGPR, PMEM, "\x87", EN_RM}, /* XCHG r32/64, m32/64 */ + {4|8, PGPR, PMEM, "\x87", EN_RM}, /* XCHG r32/64, m32/64 */ + {4|8, PMEM, PGPR, "\x87", EN_MR}, /* XCHG r32/64, m32/64 */ ) DEFINSTR2(Xlea, {4|8, PGPR, PMEM, "\x8D", EN_RM}, /* LEA r32/64,m32/64 */ @@ -1146,7 +1147,7 @@ emitinstr(uchar **pcode, struct function *fn, struct block *blk, int curi, struc break; case Oswap: if (kisint(cls)) - Xxchg(pcode, cls, mkregoper(ins->l), mkregoper(ins->r)); + Xxchg(pcode, cls, ref2oper(ins->l), mkregoper(ins->r)); else { struct oper l = mkregoper(ins->l), r = mkregoper(ins->r); Xxor(pcode, cls, l, r); diff --git a/ir/regalloc.c b/ir/regalloc.c index 51ccdab..cf40266 100644 --- a/ir/regalloc.c +++ b/ir/regalloc.c @@ -296,9 +296,24 @@ pmrec(int i, struct block *blk, int curi, enum irclass *k) case PMMOVING: c = j; Swap: - assert(pmove[i].src.t == AREG && pmove[i].dst.t == AREG); - insertinstr(blk, curi, - mkinstr(Oswap, *k, mkref(RREG, pmove[i].dst.a), mkref(RREG, pmove[i].src.a), .keep = 1)); + if (pmove[i].src.t == AREG && pmove[i].dst.t == AREG) { + insertinstr(blk, curi, + mkinstr(Oswap, *k, mkref(RREG, pmove[i].dst.a), mkref(RREG, pmove[i].src.a), .keep = 1)); + } else { + /* FIXME this case should be very uncommon, but this is bad and not portable */ + struct alloc reg, stk; + if (pmove[i].src.t == AREG) { + reg = pmove[i].src, stk = pmove[i].dst; + } else { + stk = pmove[i].src, reg = pmove[i].dst; + } + assert(reg.t == AREG && stk.t == ASTACK); + emitmove(siz2intcls[cls2siz[*k]], areg(mctarg->gprscratch), reg, blk, curi++); + union ref t = insertinstr(blk, curi++, mkinstr(Oswap, siz2intcls[cls2siz[*k]], + mkref(RICON, stk.a*8), mkref(RREG, mctarg->gprscratch), .keep = 1)); + vpush(&stkslotrefs, &instrtab[t.i].l); + emitmove(siz2intcls[cls2siz[*k]], reg, areg(mctarg->gprscratch), blk, curi++); + } break; case PMTOMOVE: pmove[i].stat = PMMOVING; |