From 246a48ba94b92e6c1e02964d46269e0903b7a723 Mon Sep 17 00:00:00 2001 From: Quentin Carbonneaux Date: Wed, 5 Aug 2015 11:37:10 -0400 Subject: start work on comparisons There are two things I overlooked so far. 1. Binary instructions like cmp that do not have a result in registers need the size suffix sometimes, for example when comparing a spill location with a constant. 2. The register allocator needs to be adapted to support the comparison instruction: it is not possible to compare two spill locations without using a register. --- lisc/isel.c | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) (limited to 'lisc/isel.c') diff --git a/lisc/isel.c b/lisc/isel.c index f08288d..6fdf5ff 100644 --- a/lisc/isel.c +++ b/lisc/isel.c @@ -40,15 +40,16 @@ newtmp(int type, Fn *fn) } static void -sel(Ins *i, Fn *fn) +sel(Ins i, Fn *fn) { Ref r0, r1, ra, rd; - int t; + int t, ty, c; - switch (i->op) { + switch (i.op) { case ODiv: case ORem: - switch (fn->tmp[i->to.val].type) { + ty = fn->tmp[i.to.val].type; + switch (ty) { default: diag("isel: invalid division"); case TWord: @@ -60,35 +61,42 @@ sel(Ins *i, Fn *fn) rd = REG(RDX); break; } - r0 = i->op == ODiv ? ra : rd; - r1 = i->op == ODiv ? rd : ra; - emit(OCopy, i->to, r0, R); + r0 = i.op == ODiv ? ra : rd; + r1 = i.op == ODiv ? rd : ra; + emit(OCopy, i.to, r0, R); emit(OCopy, R, r1, R); - if (rtype(i->arg[1]) == RCon) { + if (rtype(i.arg[1]) == RCon) { /* immediates not allowed for * divisions in x86 */ - t = newtmp(fn->tmp[i->to.val].type, fn); + t = newtmp(ty, fn); r0 = TMP(t); } else - r0 = i->arg[1]; + r0 = i.arg[1]; emit(OXDiv, R, r0, R); emit(OSign, rd, ra, R); - emit(OCopy, ra, i->arg[0], R); - if (rtype(i->arg[1]) == RCon) - emit(OCopy, r0, i->arg[1], R); + emit(OCopy, ra, i.arg[0], R); + if (rtype(i.arg[1]) == RCon) + emit(OCopy, r0, i.arg[1], R); break; case OAdd: case OSub: case OCopy: - emit(i->op, i->to, i->arg[0], i->arg[1]); + emit(i.op, i.to, i.arg[0], i.arg[1]); break; default: + if (OCmp <= i.op && i.op <= OCmp1) { + c = i.op - OCmp; + emit(OXSet+c, i.to, R, R); + emit(OXCmp, R, i.arg[0], i.arg[1]); + break; + } diag("isel: non-exhaustive implementation"); } } /* instruction selection + * requires use counts (as given by parsing) */ void isel(Fn *fn) @@ -100,7 +108,7 @@ isel(Fn *fn) for (b=fn->start; b; b=b->link) { curi = &insb[NIns]; for (i=&b->ins[b->nins]; i!=b->ins;) { - sel(--i, fn); + sel(*--i, fn); } nins = &insb[NIns] - curi; free(b->ins); -- cgit 1.4.1