mirror of
git://c9x.me/qbe.git
synced 2026-05-26 15:34:41 +00:00
Compare commits
4 Commits
ac79f8fd02
...
ac48f83f17
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac48f83f17 | ||
|
|
577b4667db | ||
|
|
bef981e9a1 | ||
|
|
0454fa259b |
7
all.h
7
all.h
@ -293,8 +293,10 @@ struct Use {
|
||||
|
||||
struct Sym {
|
||||
enum {
|
||||
SGlo,
|
||||
SThr,
|
||||
SGlo = 0, /* direct access */
|
||||
SThr = 1, /* local-exec TLS */
|
||||
SExt = 2, /* GOT/PLT access */
|
||||
SExtThr = SExt|SThr, /* initial-exec TLS */
|
||||
} type;
|
||||
uint32_t id;
|
||||
};
|
||||
@ -500,7 +502,6 @@ void emiti(Ins);
|
||||
void idup(Blk *, Ins *, ulong);
|
||||
Ins *icpy(Ins *, Ins *, ulong);
|
||||
int cmpop(int);
|
||||
int cmpneg(int);
|
||||
int cmpwlneg(int);
|
||||
int clsmerge(short *, short);
|
||||
int phicls(int, Tmp *);
|
||||
|
||||
87
amd64/emit.c
87
amd64/emit.c
@ -22,8 +22,8 @@ struct E {
|
||||
X(Ciuge, "ae", "b") \
|
||||
X(Cieq, "z", "nz") \
|
||||
X(Cine, "nz", "z") \
|
||||
X(NCmpI+Cfle, "be", "a") \
|
||||
X(NCmpI+Cflt, "b", "ae") \
|
||||
X(NCmpI+Cfle, "?" , "?") \
|
||||
X(NCmpI+Cflt, "?", "?") \
|
||||
X(NCmpI+Cfgt, "a", "be") \
|
||||
X(NCmpI+Cfge, "ae", "b") \
|
||||
X(NCmpI+Cfo, "np", "p") \
|
||||
@ -196,12 +196,12 @@ emitcon(Con *con, E *e)
|
||||
l = str(con->sym.id);
|
||||
p = l[0] == '"' ? "" : T.assym;
|
||||
if (con->sym.type == SThr) {
|
||||
if (T.apple)
|
||||
fprintf(e->f, "%s%s@TLVP", p, l);
|
||||
else
|
||||
fprintf(e->f, "%%fs:%s%s@tpoff", p, l);
|
||||
} else
|
||||
assert(!T.apple);
|
||||
fprintf(e->f, "%%fs:%s%s@tpoff", p, l);
|
||||
} else {
|
||||
assert((con->sym.type & ~SExt) == SGlo);
|
||||
fprintf(e->f, "%s%s", p, l);
|
||||
}
|
||||
if (con->bits.i)
|
||||
fprintf(e->f, "%+"PRId64, con->bits.i);
|
||||
break;
|
||||
@ -380,7 +380,7 @@ Next:
|
||||
off = e->fn->con[ref.val];
|
||||
emitcon(&off, e);
|
||||
if (off.type == CAddr)
|
||||
if (off.sym.type != SThr || T.apple)
|
||||
if (off.sym.type != SThr)
|
||||
fprintf(e->f, "(%%rip)");
|
||||
break;
|
||||
case RTmp:
|
||||
@ -532,14 +532,22 @@ emitins(Ins i, E *e)
|
||||
emitf("mov%k %0, %=", &i, e);
|
||||
break;
|
||||
case Oaddr:
|
||||
if (!T.apple
|
||||
&& rtype(i.arg[0]) == RCon
|
||||
&& e->fn->con[i.arg[0].val].sym.type == SThr) {
|
||||
if (rtype(i.arg[0]) != RCon)
|
||||
goto Table;
|
||||
con = &e->fn->con[i.arg[0].val];
|
||||
assert(isreg(i.to) && con->type == CAddr);
|
||||
sym = str(con->sym.id);
|
||||
if (T.apple && (con->sym.type & SThr)) {
|
||||
fprintf(e->f,
|
||||
"\tmovq %s%s@tlvp(%%rip), %%%s\n",
|
||||
sym[0] == '"' ? "" : T.assym, sym,
|
||||
regtoa(i.to.val, SLong));
|
||||
break;
|
||||
}
|
||||
switch (con->sym.type) {
|
||||
case SThr:
|
||||
/* derive the symbol address from the TCB
|
||||
* address at offset 0 of %fs */
|
||||
assert(isreg(i.to));
|
||||
con = &e->fn->con[i.arg[0].val];
|
||||
sym = str(con->sym.id);
|
||||
emitf("movq %%fs:0, %L=", &i, e);
|
||||
fprintf(e->f, "\tleaq %s%s@tpoff",
|
||||
sym[0] == '"' ? "" : T.assym, sym);
|
||||
@ -550,15 +558,40 @@ emitins(Ins i, E *e)
|
||||
regtoa(i.to.val, SLong),
|
||||
regtoa(i.to.val, SLong));
|
||||
break;
|
||||
case SExtThr:
|
||||
/* initial-exec TLS: load offset from
|
||||
* GOT, add to thread-base register */
|
||||
assert(!con->bits.i);
|
||||
emitf("movq %%fs:0, %L=", &i, e);
|
||||
fprintf(e->f,
|
||||
"\taddq %s%s@gottpoff(%%rip), %%%s\n",
|
||||
sym[0] == '"' ? "" : T.assym, sym,
|
||||
regtoa(i.to.val, SLong));
|
||||
break;
|
||||
case SExt:
|
||||
/* load address from the GOT */
|
||||
assert(!con->bits.i);
|
||||
fprintf(e->f,
|
||||
"\tmovq %s%s@gotpcrel(%%rip), %%%s\n",
|
||||
sym[0] == '"' ? "" : T.assym, sym,
|
||||
regtoa(i.to.val, SLong));
|
||||
break;
|
||||
default:
|
||||
goto Table;
|
||||
}
|
||||
goto Table;
|
||||
break;
|
||||
case Ocall:
|
||||
/* calls simply have a weird syntax in AT&T
|
||||
* assembly... */
|
||||
switch (rtype(i.arg[0])) {
|
||||
case RCon:
|
||||
con = &e->fn->con[i.arg[0].val];
|
||||
fprintf(e->f, "\tcallq ");
|
||||
emitcon(&e->fn->con[i.arg[0].val], e);
|
||||
emitcon(con, e);
|
||||
if (con->type == CAddr
|
||||
&& (con->sym.type & SExt)
|
||||
&& !T.apple)
|
||||
fprintf(e->f, "@plt");
|
||||
fprintf(e->f, "\n");
|
||||
break;
|
||||
case RTmp:
|
||||
@ -627,8 +660,8 @@ sysv_framesz(E *e)
|
||||
void
|
||||
amd64_sysv_emitfn(Fn *fn, FILE *f)
|
||||
{
|
||||
static char *ctoa[] = {
|
||||
#define X(c, s, _) [c] = s,
|
||||
static char *ctoa[][2] = {
|
||||
#define X(c, s, n) [c] = {s, n},
|
||||
CMP(X)
|
||||
#undef X
|
||||
};
|
||||
@ -714,9 +747,10 @@ amd64_sysv_emitfn(Fn *fn, FILE *f)
|
||||
s = b->s1;
|
||||
b->s1 = b->s2;
|
||||
b->s2 = s;
|
||||
n = 0;
|
||||
} else
|
||||
c = cmpneg(c);
|
||||
fprintf(f, "\tj%s %sbb%d\n", ctoa[c],
|
||||
n = 1;
|
||||
fprintf(f, "\tj%s %sbb%d\n", ctoa[c][n],
|
||||
T.asloc, id0+b->s2->id);
|
||||
goto Jmp;
|
||||
}
|
||||
@ -752,15 +786,15 @@ winabi_framesz(E *e)
|
||||
void
|
||||
amd64_winabi_emitfn(Fn *fn, FILE *f)
|
||||
{
|
||||
static char *ctoa[] = {
|
||||
#define X(c, s, _) [c] = s,
|
||||
static char *ctoa[][2] = {
|
||||
#define X(c, s, n) [c] = {s, n},
|
||||
CMP(X)
|
||||
#undef X
|
||||
};
|
||||
static int id0;
|
||||
Blk *b, *s;
|
||||
Ins *i, itmp;
|
||||
int *r, c, lbl;
|
||||
int *r, c, n, lbl;
|
||||
E *e;
|
||||
|
||||
e = &(E){.f = f, .fn = fn};
|
||||
@ -827,13 +861,14 @@ amd64_winabi_emitfn(Fn *fn, FILE *f)
|
||||
default:
|
||||
c = b->jmp.type - Jjf;
|
||||
if (0 <= c && c <= NCmp) {
|
||||
if (b->link == b->s2) {
|
||||
if (b->link == b->s2 || c >= NCmpI) {
|
||||
s = b->s1;
|
||||
b->s1 = b->s2;
|
||||
b->s2 = s;
|
||||
n = 0;
|
||||
} else
|
||||
c = cmpneg(c);
|
||||
fprintf(f, "\tj%s %sbb%d\n", ctoa[c],
|
||||
n = 1;
|
||||
fprintf(f, "\tj%s %sbb%d\n", ctoa[c][n],
|
||||
T.asloc, id0+b->s2->id);
|
||||
goto Jmp;
|
||||
}
|
||||
|
||||
26
amd64/isel.c
26
amd64/isel.c
@ -120,8 +120,9 @@ fixarg(Ref *r, int k, Ins *i, Fn *fn)
|
||||
r1 = newtmp("isel", Kl, fn);
|
||||
emit(Oaddr, Kl, r1, SLOT(s), R);
|
||||
}
|
||||
else if (T.apple && hascon(r0, &c, fn)
|
||||
&& c->type == CAddr && c->sym.type == SThr) {
|
||||
else if (op != Ocall && hascon(r0, &c, fn)
|
||||
&& c->type == CAddr && ((c->sym.type & SExt)
|
||||
|| (T.apple && c->sym.type == SThr))) {
|
||||
r1 = newtmp("isel", Kl, fn);
|
||||
if (c->bits.i) {
|
||||
r2 = newtmp("isel", Kl, fn);
|
||||
@ -131,16 +132,18 @@ fixarg(Ref *r, int k, Ins *i, Fn *fn)
|
||||
emit(Oadd, Kl, r1, r2, r3);
|
||||
} else
|
||||
r2 = r1;
|
||||
emit(Ocopy, Kl, r2, TMP(RAX), R);
|
||||
r2 = newtmp("isel", Kl, fn);
|
||||
r3 = newtmp("isel", Kl, fn);
|
||||
emit(Ocall, 0, R, r3, CALL(17));
|
||||
emit(Ocopy, Kl, TMP(RDI), r2, R);
|
||||
emit(Oload, Kl, r3, r2, R);
|
||||
if (T.apple && (c->sym.type & SThr)) {
|
||||
emit(Ocopy, Kl, r2, TMP(RAX), R);
|
||||
r2 = newtmp("isel", Kl, fn);
|
||||
r3 = newtmp("isel", Kl, fn);
|
||||
emit(Ocall, 0, R, r3, CALL(17));
|
||||
emit(Ocopy, Kl, TMP(RDI), r2, R);
|
||||
emit(Oload, Kl, r3, r2, R);
|
||||
}
|
||||
cc = *c;
|
||||
cc.bits.i = 0;
|
||||
r3 = newcon(&cc, fn);
|
||||
emit(Oload, Kl, r2, r3, R);
|
||||
emit(Oaddr, Kl, r2, r3, R);
|
||||
if (rtype(r0) == RMem) {
|
||||
m = &fn->mem[r0.val];
|
||||
m->offset.type = CUndef;
|
||||
@ -151,9 +154,8 @@ fixarg(Ref *r, int k, Ins *i, Fn *fn)
|
||||
else if (!(isstore(op) && r == &i->arg[1])
|
||||
&& !isload(op) && op != Ocall && rtype(r0) == RCon
|
||||
&& fn->con[r0.val].type == CAddr) {
|
||||
/* apple as does not support 32-bit
|
||||
* absolute addressing, use a rip-
|
||||
* relative leaq instead
|
||||
/* turn address operands into
|
||||
* lea/mov instructions
|
||||
*/
|
||||
r1 = newtmp("isel", Kl, fn);
|
||||
emit(Oaddr, Kl, r1, r0, R);
|
||||
|
||||
61
arm64/emit.c
61
arm64/emit.c
@ -10,24 +10,24 @@ struct E {
|
||||
};
|
||||
|
||||
#define CMP(X) \
|
||||
X(Cieq, "eq") \
|
||||
X(Cine, "ne") \
|
||||
X(Cisge, "ge") \
|
||||
X(Cisgt, "gt") \
|
||||
X(Cisle, "le") \
|
||||
X(Cislt, "lt") \
|
||||
X(Ciuge, "cs") \
|
||||
X(Ciugt, "hi") \
|
||||
X(Ciule, "ls") \
|
||||
X(Ciult, "cc") \
|
||||
X(NCmpI+Cfeq, "eq") \
|
||||
X(NCmpI+Cfge, "ge") \
|
||||
X(NCmpI+Cfgt, "gt") \
|
||||
X(NCmpI+Cfle, "ls") \
|
||||
X(NCmpI+Cflt, "mi") \
|
||||
X(NCmpI+Cfne, "ne") \
|
||||
X(NCmpI+Cfo, "vc") \
|
||||
X(NCmpI+Cfuo, "vs")
|
||||
X(Cieq, "eq", "ne") \
|
||||
X(Cine, "ne", "eq") \
|
||||
X(Cisge, "ge", "lt") \
|
||||
X(Cisgt, "gt", "le") \
|
||||
X(Cisle, "le", "gt") \
|
||||
X(Cislt, "lt", "ge") \
|
||||
X(Ciuge, "cs", "cc") \
|
||||
X(Ciugt, "hi", "ls") \
|
||||
X(Ciule, "ls", "hi") \
|
||||
X(Ciult, "cc", "cs") \
|
||||
X(NCmpI+Cfeq, "eq", "ne") \
|
||||
X(NCmpI+Cfge, "ge", "lt") \
|
||||
X(NCmpI+Cfgt, "gt", "le") \
|
||||
X(NCmpI+Cfle, "ls", "hi") \
|
||||
X(NCmpI+Cflt, "mi", "pl") \
|
||||
X(NCmpI+Cfne, "ne", "eq") \
|
||||
X(NCmpI+Cfo, "vc", "vs") \
|
||||
X(NCmpI+Cfuo, "vs", "vc")
|
||||
|
||||
enum {
|
||||
Ki = -1, /* matches Kw and Kl */
|
||||
@ -102,7 +102,7 @@ static struct {
|
||||
{ Oacmn, Ki, "cmn %0, %1" },
|
||||
{ Oafcmp, Ka, "fcmpe %0, %1" },
|
||||
|
||||
#define X(c, str) \
|
||||
#define X(c, str, _) \
|
||||
{ Oflag+c, Ki, "cset %=, " str },
|
||||
CMP(X)
|
||||
#undef X
|
||||
@ -278,6 +278,10 @@ loadaddr(Con *c, char *rn, E *e)
|
||||
s = "\tadrp\tR, SO\n"
|
||||
"\tadd\tR, R, #:lo12:SO\n";
|
||||
break;
|
||||
case SExtThr:
|
||||
if (!T.apple)
|
||||
die("extern thread unavailable on arm64");
|
||||
/* fall through */
|
||||
case SThr:
|
||||
if (T.apple)
|
||||
s = "\tadrp\tR, S@tlvppage\n"
|
||||
@ -287,6 +291,14 @@ loadaddr(Con *c, char *rn, E *e)
|
||||
"\tadd\tR, R, #:tprel_hi12:SO, lsl #12\n"
|
||||
"\tadd\tR, R, #:tprel_lo12_nc:SO\n";
|
||||
break;
|
||||
case SExt:
|
||||
if (T.apple)
|
||||
s = "\tadrp\tR, S@gotpageO\n"
|
||||
"\tldr\tR, [R, S@gotpageoffO]\n";
|
||||
else
|
||||
s = "\tadrp\tR, :got:SO\n"
|
||||
"\tldr\tR, [R, #:got_lo12:SO]\n";
|
||||
break;
|
||||
}
|
||||
|
||||
l = str(c->sym.id);
|
||||
@ -468,7 +480,7 @@ emitins(Ins *i, E *e)
|
||||
goto Table;
|
||||
c = &e->fn->con[i->arg[0].val];
|
||||
if (c->type != CAddr
|
||||
|| c->sym.type != SGlo
|
||||
|| (c->sym.type & SThr)
|
||||
|| c->bits.i)
|
||||
die("invalid call argument");
|
||||
l = str(c->sym.id);
|
||||
@ -532,8 +544,8 @@ framelayout(E *e)
|
||||
void
|
||||
arm64_emitfn(Fn *fn, FILE *out)
|
||||
{
|
||||
static char *ctoa[] = {
|
||||
#define X(c, s) [c] = s,
|
||||
static char *ctoa[][2] = {
|
||||
#define X(c, s, n) [c] = {s, n},
|
||||
CMP(X)
|
||||
#undef X
|
||||
};
|
||||
@ -664,11 +676,12 @@ arm64_emitfn(Fn *fn, FILE *out)
|
||||
t = b->s1;
|
||||
b->s1 = b->s2;
|
||||
b->s2 = t;
|
||||
n = 0;
|
||||
} else
|
||||
c = cmpneg(c);
|
||||
n = 1;
|
||||
fprintf(e->f,
|
||||
"\tb%s\t%s%d\n",
|
||||
ctoa[c], T.asloc, id0+b->s2->id
|
||||
ctoa[c][n], T.asloc, id0+b->s2->id
|
||||
);
|
||||
goto Jmp;
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ fixarg(Ref *pr, int k, int phi, Fn *fn)
|
||||
c = &fn->con[r0.val];
|
||||
if (T.apple
|
||||
&& c->type == CAddr
|
||||
&& c->sym.type == SThr) {
|
||||
&& (c->sym.type & SThr)) {
|
||||
r1 = newtmp("isel", Kl, fn);
|
||||
*pr = r1;
|
||||
if (c->bits.i) {
|
||||
|
||||
13
doc/il.txt
13
doc/il.txt
@ -180,7 +180,9 @@ by zero-extension, or by sign-extension.
|
||||
|
||||
DYNCONST :=
|
||||
CONST
|
||||
| 'thread' $IDENT # Thread-local symbol
|
||||
| 'thread' $IDENT # Thread-local symbol
|
||||
| 'extern' $IDENT # Extern symbol (GOT)
|
||||
| 'extern' 'thread' $IDENT # Extern thread-local (initial-exec)
|
||||
|
||||
VAL :=
|
||||
DYNCONST
|
||||
@ -225,6 +227,15 @@ When the `thread` keyword prefixes a symbol name, the
|
||||
symbol's numeric value is resolved at runtime in the
|
||||
thread-local storage.
|
||||
|
||||
When the `extern` keyword prefixes a symbol name, the
|
||||
symbol is accessed indirectly through a table edited
|
||||
by the dynamic linker (e.g., GOT/PLT). This enables
|
||||
PIE/PIC code generation. When `extern` is combined
|
||||
with `thread`, the symbol is accessed using the
|
||||
initial-exec TLS model, suitable for thread-local
|
||||
variables defined in shared objects available at
|
||||
startup time (i.e., not loaded through dlopen).
|
||||
|
||||
Vals are used as arguments in regular, phi, and jump
|
||||
instructions within function definitions. They are
|
||||
either constants or function-scope temporaries.
|
||||
|
||||
28
parse.c
28
parse.c
@ -57,6 +57,7 @@ enum Token {
|
||||
Thlt,
|
||||
Texport,
|
||||
Tthread,
|
||||
Textern,
|
||||
Tcommon,
|
||||
Tfunc,
|
||||
Ttype,
|
||||
@ -116,6 +117,7 @@ static char *kwmap[Ntok] = {
|
||||
[Thlt] = "hlt",
|
||||
[Texport] = "export",
|
||||
[Tthread] = "thread",
|
||||
[Textern] = "extern",
|
||||
[Tcommon] = "common",
|
||||
[Tfunc] = "function",
|
||||
[Ttype] = "type",
|
||||
@ -427,11 +429,10 @@ static Ref
|
||||
parseref()
|
||||
{
|
||||
Con c;
|
||||
int tok;
|
||||
|
||||
memset(&c, 0, sizeof c);
|
||||
switch (next()) {
|
||||
default:
|
||||
return R;
|
||||
switch ((tok = next())) {
|
||||
case Ttmp:
|
||||
return tmpref(tokval.str);
|
||||
case Tint:
|
||||
@ -448,9 +449,20 @@ parseref()
|
||||
c.bits.d = tokval.fltd;
|
||||
c.flt = 2;
|
||||
break;
|
||||
case Tthread:
|
||||
c.sym.type = SThr;
|
||||
expect(Tglo);
|
||||
default:
|
||||
for (;; tok=next()) {
|
||||
switch (tok) {
|
||||
case Textern:
|
||||
c.sym.type |= SExt;
|
||||
continue;
|
||||
case Tthread:
|
||||
c.sym.type |= SThr;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (tok != Tglo)
|
||||
return R;
|
||||
/* fall through */
|
||||
case Tglo:
|
||||
c.type = CAddr;
|
||||
@ -1255,7 +1267,9 @@ printcon(Con *c, FILE *f)
|
||||
case CUndef:
|
||||
break;
|
||||
case CAddr:
|
||||
if (c->sym.type == SThr)
|
||||
if (c->sym.type & SExt)
|
||||
fprintf(f, "extern ");
|
||||
if (c->sym.type & SThr)
|
||||
fprintf(f, "thread ");
|
||||
fprintf(f, "$%s", str(c->sym.id));
|
||||
if (c->bits.i)
|
||||
|
||||
28
rv64/emit.c
28
rv64/emit.c
@ -131,7 +131,7 @@ slot(Ref r, Fn *fn)
|
||||
static void
|
||||
emitaddr(Con *c, FILE *f)
|
||||
{
|
||||
assert(c->sym.type == SGlo);
|
||||
assert((c->sym.type & ~SExt) == SGlo);
|
||||
fputs(str(c->sym.id), f);
|
||||
if (c->bits.i)
|
||||
fprintf(f, "+%"PRIi64, c->bits.i);
|
||||
@ -231,7 +231,20 @@ loadaddr(Con *c, char *rn, FILE *f)
|
||||
{
|
||||
char off[32];
|
||||
|
||||
if (c->sym.type == SThr) {
|
||||
switch (c->sym.type) {
|
||||
case SGlo:
|
||||
fprintf(f, "\tlui %s, %%hi(", rn);
|
||||
emitaddr(c, f);
|
||||
fprintf(f, ")\n\taddi %s, %s, %%lo(", rn, rn);
|
||||
emitaddr(c, f);
|
||||
fputs(")\n", f);
|
||||
break;
|
||||
case SExt:
|
||||
fprintf(f, "\tla %s, ", rn);
|
||||
emitaddr(c, f);
|
||||
fputc('\n', f);
|
||||
break;
|
||||
case SThr:
|
||||
if (c->bits.i)
|
||||
sprintf(off, "+%"PRIi64, c->bits.i);
|
||||
else
|
||||
@ -242,10 +255,9 @@ loadaddr(Con *c, char *rn, FILE *f)
|
||||
rn, rn, str(c->sym.id), off);
|
||||
fprintf(f, "\taddi %s, %s, %%tprel_lo(%s)%s\n",
|
||||
rn, rn, str(c->sym.id), off);
|
||||
} else {
|
||||
fprintf(f, "\tla %s, ", rn);
|
||||
emitaddr(c, f);
|
||||
fputc('\n', f);
|
||||
break;
|
||||
case SExtThr:
|
||||
die("extern thread unavailable on rv64");
|
||||
}
|
||||
}
|
||||
|
||||
@ -282,7 +294,7 @@ fixmem(Ref *pr, Fn *fn, FILE *f)
|
||||
if (rtype(r) == RCon) {
|
||||
c = &fn->con[r.val];
|
||||
if (c->type == CAddr)
|
||||
if (c->sym.type == SThr) {
|
||||
if (c->sym.type != SGlo) {
|
||||
loadcon(c, T6, Kl, f);
|
||||
*pr = TMP(T6);
|
||||
}
|
||||
@ -387,7 +399,7 @@ emitins(Ins *i, Fn *fn, FILE *f)
|
||||
case RCon:
|
||||
con = &fn->con[i->arg[0].val];
|
||||
if (con->type != CAddr
|
||||
|| con->sym.type != SGlo
|
||||
|| (con->sym.type & SThr)
|
||||
|| con->bits.i)
|
||||
goto Invalid;
|
||||
fprintf(f, "\tcall %s\n", str(con->sym.id));
|
||||
|
||||
@ -29,7 +29,7 @@ char *tok[] = {
|
||||
"function", "type", "data", "section", "align", "dbgfile",
|
||||
"blit", "l", "w", "sh", "uh", "h", "sb", "ub", "b",
|
||||
"d", "s", "z", "loadw", "loadl", "loads", "loadd",
|
||||
"alloc1", "alloc2", "thread", "common",
|
||||
"alloc1", "alloc2", "thread", "extern", "common",
|
||||
|
||||
};
|
||||
enum {
|
||||
|
||||
49
util.c
49
util.c
@ -343,34 +343,27 @@ icpy(Ins *d, Ins *s, ulong n)
|
||||
}
|
||||
|
||||
static int cmptab[][2] ={
|
||||
/* negation swap */
|
||||
[Ciule] = {Ciugt, Ciuge},
|
||||
[Ciult] = {Ciuge, Ciugt},
|
||||
[Ciugt] = {Ciule, Ciult},
|
||||
[Ciuge] = {Ciult, Ciule},
|
||||
[Cisle] = {Cisgt, Cisge},
|
||||
[Cislt] = {Cisge, Cisgt},
|
||||
[Cisgt] = {Cisle, Cislt},
|
||||
[Cisge] = {Cislt, Cisle},
|
||||
[Cieq] = {Cine, Cieq},
|
||||
[Cine] = {Cieq, Cine},
|
||||
[NCmpI+Cfle] = {NCmpI+Cfgt, NCmpI+Cfge},
|
||||
[NCmpI+Cflt] = {NCmpI+Cfge, NCmpI+Cfgt},
|
||||
[NCmpI+Cfgt] = {NCmpI+Cfle, NCmpI+Cflt},
|
||||
[NCmpI+Cfge] = {NCmpI+Cflt, NCmpI+Cfle},
|
||||
[NCmpI+Cfeq] = {NCmpI+Cfne, NCmpI+Cfeq},
|
||||
[NCmpI+Cfne] = {NCmpI+Cfeq, NCmpI+Cfne},
|
||||
[NCmpI+Cfo] = {NCmpI+Cfuo, NCmpI+Cfo},
|
||||
[NCmpI+Cfuo] = {NCmpI+Cfo, NCmpI+Cfuo},
|
||||
/* negation swap */
|
||||
[Ciule] = {Ciugt, Ciuge},
|
||||
[Ciult] = {Ciuge, Ciugt},
|
||||
[Ciugt] = {Ciule, Ciult},
|
||||
[Ciuge] = {Ciult, Ciule},
|
||||
[Cisle] = {Cisgt, Cisge},
|
||||
[Cislt] = {Cisge, Cisgt},
|
||||
[Cisgt] = {Cisle, Cislt},
|
||||
[Cisge] = {Cislt, Cisle},
|
||||
[Cieq] = {Cine, Cieq},
|
||||
[Cine] = {Cieq, Cine},
|
||||
[NCmpI+Cfle] = {-1, NCmpI+Cfge},
|
||||
[NCmpI+Cflt] = {-1, NCmpI+Cfgt},
|
||||
[NCmpI+Cfgt] = {-1, NCmpI+Cflt},
|
||||
[NCmpI+Cfge] = {-1, NCmpI+Cfle},
|
||||
[NCmpI+Cfeq] = {-1, NCmpI+Cfeq},
|
||||
[NCmpI+Cfne] = {-1, NCmpI+Cfne},
|
||||
[NCmpI+Cfo] = {-1, NCmpI+Cfo},
|
||||
[NCmpI+Cfuo] = {-1, NCmpI+Cfuo},
|
||||
};
|
||||
|
||||
int
|
||||
cmpneg(int c)
|
||||
{
|
||||
assert(0 <= c && c < NCmp);
|
||||
return cmptab[c][0];
|
||||
}
|
||||
|
||||
int
|
||||
cmpop(int c)
|
||||
{
|
||||
@ -382,9 +375,9 @@ int
|
||||
cmpwlneg(int op)
|
||||
{
|
||||
if (INRANGE(op, Ocmpw, Ocmpw1))
|
||||
return cmpneg(op - Ocmpw) + Ocmpw;
|
||||
return cmptab[op - Ocmpw][0] + Ocmpw;
|
||||
if (INRANGE(op, Ocmpl, Ocmpl1))
|
||||
return cmpneg(op - Ocmpl) + Ocmpl;
|
||||
return cmptab[op - Ocmpl][0] + Ocmpl;
|
||||
die("not a wl comparison");
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user