aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2025-12-10 21:16:54 +0100
committerlemon <lsof@mailbox.org>2025-12-10 21:16:54 +0100
commit97882e8d32fd99e1edaf5361bfd3b6852dbb1a3d (patch)
tree85ddc76b4abc2ecb141b7622d6b02fc517988ff8
parenta550587208c487f9406f38b047731d2275681fb0 (diff)
parallel move; implement reg<->stack swp
-rw-r--r--amd64/emit.c5
-rw-r--r--ir/regalloc.c21
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;