diff options
Diffstat (limited to 'amd64')
-rw-r--r-- | amd64/isel.c | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/amd64/isel.c b/amd64/isel.c index 0b0a2df..07e6142 100644 --- a/amd64/isel.c +++ b/amd64/isel.c @@ -165,13 +165,25 @@ seladdr(Ref *r, ANum *an, Fn *fn) } static int -selcmp(Ref arg[2], int k, Fn *fn) +cmpswap(Ref arg[2], int op) +{ + switch (op) { + case NCmpI+Cflt: + case NCmpI+Cfle: + return 1; + case NCmpI+Cfgt: + case NCmpI+Cfge: + return 0; + } + return rtype(arg[0]) == RCon; +} + +static void +selcmp(Ref arg[2], int k, int swap, Fn *fn) { - int swap; Ref r; Ins *icmp; - swap = rtype(arg[0]) == RCon; if (swap) { r = arg[1]; arg[1] = arg[0]; @@ -180,20 +192,20 @@ selcmp(Ref arg[2], int k, Fn *fn) emit(Oxcmp, k, R, arg[1], arg[0]); icmp = curi; if (rtype(arg[0]) == RCon) { - assert(k == Kl); + assert(k != Kw); icmp->arg[1] = newtmp("isel", k, fn); emit(Ocopy, k, icmp->arg[1], arg[0], R); + fixarg(&curi->arg[0], k, curi, fn); } fixarg(&icmp->arg[0], k, icmp, fn); fixarg(&icmp->arg[1], k, icmp, fn); - return swap; } static void sel(Ins i, ANum *an, Fn *fn) { Ref r0, r1; - int x, k, kc; + int x, k, kc, swap; int64_t sz; Ins *i0, *i1; @@ -332,10 +344,11 @@ Emit: if (isload(i.op)) goto case_Oload; if (iscmp(i.op, &kc, &x)) { + swap = cmpswap(i.arg, x); + if (swap) + x = cmpop(x); emit(Oflag+x, k, i.to, R, R); - i1 = curi; - if (selcmp(i.arg, kc, fn)) - i1->op = Oflag + cmpop(x); + selcmp(i.arg, kc, swap, fn); break; } die("unknown instruction %s", optab[i.op].name); @@ -365,7 +378,7 @@ static void seljmp(Blk *b, Fn *fn) { Ref r; - int c, k; + int c, k, swap; Ins *fi; Tmp *t; @@ -384,14 +397,15 @@ seljmp(Blk *b, Fn *fn) } fi = flagi(b->ins, &b->ins[b->nins]); if (!fi || !req(fi->to, r)) { - selcmp((Ref[2]){r, CON_Z}, Kw, fn); /* todo, long jnz */ + selcmp((Ref[2]){r, CON_Z}, Kw, 0, fn); /* todo, long jnz */ b->jmp.type = Jjf + Cine; } else if (iscmp(fi->op, &k, &c)) { - if (rtype(fi->arg[0]) == RCon) + swap = cmpswap(fi->arg, c); + if (swap) c = cmpop(c); if (t->nuse == 1) { - selcmp(fi->arg, k, fn); + selcmp(fi->arg, k, swap, fn); *fi = (Ins){.op = Onop}; } b->jmp.type = Jjf + c; |