summaryrefslogtreecommitdiff
path: root/lisc
diff options
context:
space:
mode:
Diffstat (limited to 'lisc')
-rw-r--r--lisc/emit.c91
1 files changed, 63 insertions, 28 deletions
diff --git a/lisc/emit.c b/lisc/emit.c
index c4b6356..1a98e0f 100644
--- a/lisc/emit.c
+++ b/lisc/emit.c
@@ -31,16 +31,48 @@ static char *ctoa[NCmp] = {
[Cne ] = "ne",
};
+static int
+slot(int s, Fn *fn)
+{
+ struct { int i:14; } x;
+
+ x.i = s;
+ assert(NAlign == 3);
+ if (x.i < 0)
+ return -4 * x.i;
+ else {
+ assert(fn->slot >= x.i);
+ return -4 * (fn->slot - x.i);
+ }
+}
+
+static void
+emitcon(Con *con, FILE *f)
+{
+ switch (con->type) {
+ default:
+ diag("emit: invalid constant");
+ case CAddr:
+ fputs(con->label, f);
+ if (con->val)
+ fprintf(f, "%+"PRId64, con->val);
+ break;
+ case CNum:
+ fprintf(f, "%"PRId64, con->val);
+ break;
+ }
+}
+
static void
emitf(Fn *fn, FILE *f, char *fmt, ...)
{
static char stoa[] = "qlwb";
va_list ap;
char c, *s, *s1;
- int i, ty, off;
+ int i, ty;
Ref ref;
- Con *con;
- struct { int i:14; } x;
+ Mem *m;
+ Con off;
va_start(ap, fmt);
ty = SWord;
@@ -83,33 +115,32 @@ Next:
fprintf(f, "%%%s", rsub[ref.val][ty]);
break;
case RSlot:
- Slot:
- x.i = ref.val;
- assert(NAlign == 3);
- if (x.i < 0)
- off = -4 * x.i;
- else {
- assert(fn->slot >= x.i);
- off = -4 * (fn->slot - x.i);
+ fprintf(f, "%d(%%rbp)", slot(ref.val, fn));
+ break;
+ case RAMem:
+ Mem:
+ m = &fn->mem[ref.val & AMask];
+ if (rtype(m->base) == RSlot) {
+ off.type = CNum;
+ off.val = slot(m->base.val, fn);
+ addcon(&m->offset, &off);
+ m->base = TMP(RBP);
}
- fprintf(f, "%d(%%rbp)", off);
+ if (m->offset.type != CUndef)
+ emitcon(&m->offset, f);
+ fputc('(', f);
+ if (!req(m->base, R))
+ fprintf(f, "%%%s", rsub[m->base.val][SLong]);
+ if (!req(m->index, R))
+ fprintf(f, ", %%%s, %d",
+ rsub[m->index.val][SLong],
+ m->scale
+ );
+ fputc(')', f);
break;
case RCon:
fputc('$', f);
- Con:
- con = &fn->con[ref.val];
- switch (con->type) {
- default:
- diag("emit: invalid constant");
- case CAddr:
- fputs(con->label, f);
- if (con->val)
- fprintf(f, "%+"PRId64, con->val);
- break;
- case CNum:
- fprintf(f, "%"PRId64, con->val);
- break;
- }
+ emitcon(&fn->con[ref.val], f);
break;
}
break;
@@ -118,10 +149,14 @@ Next:
switch (rtype(ref)) {
default:
diag("emit: invalid memory reference");
+ case RAMem:
+ goto Mem;
case RSlot:
- goto Slot;
+ fprintf(f, "%d(%%rbp)", slot(ref.val, fn));
+ break;
case RCon:
- goto Con;
+ emitcon(&fn->con[ref.val], f);
+ break;
case RTmp:
assert(isreg(ref));
fprintf(f, "(%%%s)", rsub[ref.val][SLong]);