diff options
author | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2016-02-18 18:13:57 -0500 |
---|---|---|
committer | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2016-02-18 18:13:57 -0500 |
commit | cabad82d729c8ceba8c63880df64804213703e08 (patch) | |
tree | 1b0b2889804e77e0c0cb1f5fc3db63162ac30040 | |
parent | 70d73e2d6eaf0bca7821222b7ba0be41d838080b (diff) | |
download | roux-cabad82d729c8ceba8c63880df64804213703e08.tar.gz |
start completing the fp abi
-rw-r--r-- | lisc/isel.c | 81 |
1 files changed, 51 insertions, 30 deletions
diff --git a/lisc/isel.c b/lisc/isel.c index dff2c4d..7e81a88 100644 --- a/lisc/isel.c +++ b/lisc/isel.c @@ -103,12 +103,23 @@ rslot(Ref r, Fn *fn) } static int -argcls(Ins *i) +argcls(Ins *i, int n) { - /* fixme, not correct for some instructions (bcast) */ - if (OLoad <= i->op && i->op <= OLoad1) + switch (i->op) { + case OStores: + case OStored: + diag("isel: argcls called on fp store"); + case OStoreb: + case OStoreh: + case OStorew: + return n == 0 ? Kw : Kl; + case OStorel: return Kl; - return i->cls; + default: + if (OLoad <= i->op && i->op <= OLoad1) + return Kl; + return i->cls; + } } static void @@ -241,7 +252,11 @@ sel(Ins i, ANum *an, Fn *fn) case ONop: break; case OStored: + if (rtype(i.arg[0]) == RCon) + i.op = OStorel; case OStores: + if (rtype(i.arg[0]) == RCon) + i.op = OStorew; case OStorel: case OStorew: case OStoreh: @@ -263,8 +278,8 @@ sel(Ins i, ANum *an, Fn *fn) case_OExt: Emit: emiti(i); - fixarg(&curi->arg[0], argcls(curi), 0, fn); - fixarg(&curi->arg[1], argcls(curi), 0, fn); + fixarg(&curi->arg[0], argcls(curi, 0), 0, fn); + fixarg(&curi->arg[1], argcls(curi, 1), 0, fn); break; case OAlloc: case OAlloc+1: @@ -566,6 +581,19 @@ calluse(Ins i, int p[2]) return b; } +static Ref +rarg(int ty, int *ni, int *ns) +{ + switch (ty) { + default: + diag("isel: rarg defaulted"); + case RInt: + return TMP(rsave[(*ni)++]); + case RSse: + return TMP(XMM0 + (*ns)++); + } +} + static void selcall(Fn *fn, Ins *i0, Ins *i1) { @@ -573,7 +601,7 @@ selcall(Fn *fn, Ins *i0, Ins *i1) AClass *ac, *a; int ca, ni, ns; uint stk, sz; - Ref r, r1; + Ref r, r1, r2; ac = alloc((i1-i0) * sizeof ac[0]); ca = classify(i0, i1, ac, OArg); @@ -594,32 +622,28 @@ selcall(Fn *fn, Ins *i0, Ins *i1) emit(OSAlloc, Kl, R, r, R); } emit(OCopy, i1->cls, i1->to, TMP(RAX), R); - emit(OCall, i1->cls, R, i1->arg[0], CALL(1 + ca)); + emit(OCall, i1->cls, R, i1->arg[0], CALL(1 | ca)); for (i=i0, a=ac, ni=ns=0; i<i1; i++, a++) { if (a->inmem) continue; + r1 = rarg(a->rty[0], &ni, &ns); if (i->op == OArgc) { - if (a->rty[0] == RSse || a->rty[1] == RSse) - diag("isel: unsupported float struct"); if (a->size > 8) { - r = TMP(rsave[ni+1]); - r1 = newtmp("isel", fn); - emit(OLoadl, Kl, r, r1, R); - r = getcon(8, fn); - emit(OAdd, Kl, r1, i->arg[1], r); - r = TMP(rsave[ni]); - ni += 2; - } else - r = TMP(rsave[ni++]); - emit(OLoadl, Kl, r, i->arg[1], R); - } else { - if (KBASE(i->cls) == 0) - r = TMP(rsave[ni++]); + r2 = rarg(a->rty[1], &ni, &ns); + r = newtmp("isel", fn); + if (a->rty[1] == RInt) /* fixme, add OLoad? */ + emit(OLoadl, Kl, r2, r, R); + else + emit(OLoadd, Kd, r2, r, R); + emit(OAdd, Kl, r, i->arg[1], getcon(8, fn)); + } + if (a->rty[0] == RInt) /* fixme! */ + emit(OLoadl, Kl, r1, i->arg[1], R); else - r = TMP(XMM0 + ns++); - emit(OCopy, i->cls, r, i->arg[0], R); - } + emit(OLoadd, Kd, r1, i->arg[1], R); + } else + emit(OCopy, i->cls, r1, i->arg[0], R); } for (i=i0, a=ac; i<i1; i++, a++) { if (!a->inmem) @@ -665,10 +689,7 @@ selpar(Fn *fn, Ins *i0, Ins *i1) *curi++ = (Ins){OLoad, i->to, {SLOT(stk)}, i->cls}; continue; } - if (KBASE(i->cls) == 0) - r = TMP(rsave[ni++]); - else - r = TMP(XMM0 + ns++); + r = rarg(a->rty[0], &ni, &ns); if (i->op == OParc) { if (a->rty[0] == RSse || a->rty[1] == RSse) diag("isel: unsupported float struct"); |