diff options
author | Quentin Carbonneaux <quentin@c9x.me> | 2019-02-21 14:42:01 +0100 |
---|---|---|
committer | Quentin Carbonneaux <quentin@c9x.me> | 2019-02-21 14:46:18 +0100 |
commit | a877ba986b4c5b24ee07d59b3001d45fd5b3f834 (patch) | |
tree | 64ea16f84451b2e7dd1ce16de68a25acf1b5f61e /amd64 | |
parent | cf9f2e8ef7e775bcedf74b70a3dd35962484f1f1 (diff) | |
download | roux-a877ba986b4c5b24ee07d59b3001d45fd5b3f834.tar.gz |
fix amd64 addressing mode matcher
The numberer made some arranging choices when numbering arguments of an instruction, but these decisions were ignored when matching. The fix is to reconcile numbering and matching.
Diffstat (limited to 'amd64')
-rw-r--r-- | amd64/isel.c | 35 |
1 files changed, 15 insertions, 20 deletions
diff --git a/amd64/isel.c b/amd64/isel.c index 2519ae5..6aea850 100644 --- a/amd64/isel.c +++ b/amd64/isel.c @@ -25,7 +25,7 @@ struct ANum { Ins *i; }; -static void amatch(Addr *, Ref, ANum *, Fn *, int); +static int amatch(Addr *, Ref, int, ANum *, Fn *); static int noimm(Ref r, Fn *fn) @@ -131,8 +131,8 @@ seladdr(Ref *r, ANum *an, Fn *fn) r0 = *r; if (rtype(r0) == RTmp) { - amatch(&a, r0, an, fn, 1); - if (req(a.base, r0)) + memset(&a, 0, sizeof a); + if (!amatch(&a, r0, an[r0.val].n, an, fn)) return; if (a.offset.type == CAddr) if (!req(a.base, R)) { @@ -488,18 +488,16 @@ anumber(ANum *ai, Blk *b, Con *con) } } -static void -amatch(Addr *a, Ref r, ANum *ai, Fn *fn, int top) +static int +amatch(Addr *a, Ref r, int n, ANum *ai, Fn *fn) { Ins *i; int nl, nr, t, s; Ref al, ar; - if (top) - memset(a, 0, sizeof *a); if (rtype(r) == RCon) { addcon(&a->offset, &fn->con[r.val]); - return; + return 1; } assert(rtype(r) == RTmp); i = ai[r.val].i; @@ -515,14 +513,11 @@ amatch(Addr *a, Ref r, ANum *ai, Fn *fn, int top) ar = i->arg[1]; } } - switch (ai[r.val].n) { + switch (n) { case 3: /* s * i */ - if (!top) { - a->index = al; - a->scale = fn->con[ar.val].bits.i; - } else - a->base = r; - break; + a->index = al; + a->scale = fn->con[ar.val].bits.i; + return 0; case 4: /* b + s * i */ switch (nr) { case 0: @@ -534,7 +529,7 @@ amatch(Addr *a, Ref r, ANum *ai, Fn *fn, int top) a->scale = 1; break; case 3: - amatch(a, ar, ai, fn, 0); + amatch(a, ar, nr, ai, fn); break; } r = al; @@ -544,14 +539,14 @@ amatch(Addr *a, Ref r, ANum *ai, Fn *fn, int top) if (s != -1) r = SLOT(s); a->base = r; - break; + return n || s != -1; case 2: /* constants */ case 5: /* o + s * i */ case 6: /* o + b */ case 7: /* o + b + s * i */ - amatch(a, ar, ai, fn, 0); - amatch(a, al, ai, fn, 0); - break; + amatch(a, ar, nr, ai, fn); + amatch(a, al, nl, ai, fn); + return 1; default: die("unreachable"); } |