ref: 1eaac761440473141e996d6a0f2516ffbf8f2131
parent: ae7f196364260272698a6bf7c117b7be7c811779
author: Ori Bernstein <[email protected]>
date: Mon May 7 17:29:07 EDT 2012
Add function to take a specific reg. This is needed for funky functions like 'mul' that use specific registers.
--- a/8/asm.h
+++ b/8/asm.h
@@ -10,6 +10,7 @@
#define Reg(r, name, mode) r,
#include "regs.def"
#undef Reg
+ Nreg
} Reg;
@@ -23,10 +24,12 @@
} LocType;
typedef enum {
+ ModeNone,
ModeB,
ModeS,
ModeL,
ModeQ,
+ Nmode
} Mode;
typedef struct Insn Insn;
--- a/8/isel.c
+++ b/8/isel.c
@@ -21,21 +21,48 @@
size_t ni;
Node *ret;
Htab *locs; /* Node => int stkoff */
+
+ /* 6 general purpose regs */
+ Reg rtaken[Nreg];
};
/* string tables */
-char *regnames[] = {
+const char *regnames[] = {
#define Reg(r, name, mode) name,
#include "regs.def"
#undef Reg
};
-Mode regmodes[] = {
+const Mode regmodes[] = {
#define Reg(r, name, mode) mode,
#include "regs.def"
#undef Reg
};
+const Reg reginterferes[][Nmode + 1] = {
+ /* byte */
+ [Ral] = {Ral, Rax, Reax},
+ [Rcl] = {Rcl, Rcx, Recx},
+ [Rdl] = {Rdl, Rdx, Redx},
+ [Rbl] = {Rbl, Rbx, Rebx},
+
+ /* word */
+ [Rax] = {Ral, Rax, Reax},
+ [Rcx] = {Rcl, Rcx, Recx},
+ [Rdx] = {Rdl, Rdx, Redx},
+ [Rbx] = {Rbl, Rbx, Rebx},
+ [Rsi] = {Rsi, Resi},
+ [Rdi] = {Rdi, Redi},
+
+ /* dword */
+ [Reax] = {Ral, Rax, Reax},
+ [Recx] = {Rcl, Rcx, Recx},
+ [Redx] = {Rdl, Rdx, Redx},
+ [Rebx] = {Rbl, Rbx, Rebx},
+ [Resi] = {Rsi, Resi},
+ [Redi] = {Rdi, Redi},
+};
+
char *insnfmts[] = {
#define Insn(val, fmt, attr) fmt,
#include "insns.def"
@@ -148,7 +175,7 @@
{
Loc l;
- Reg crtab[][4] = {
+ Reg crtab[][Nmode + 1] = {
[Ral] = {Ral, Rax, Reax},
[Rcl] = {Rcl, Rcx, Recx},
[Rdl] = {Rdl, Rdx, Redx},
@@ -176,11 +203,35 @@
Loc getreg(Isel *s, Mode m)
{
+
Loc l;
- locreg(&l, Reax);
+ int i;
+
+ for (i = 0; i < Nreg; i++) {
+ if (!s->rtaken[i] && regmodes[i] == m) {
+ locreg(&l, i);
+ break;
+ }
+ }
+ for (i = 0; i < Nmode; i++)
+ s->rtaken[reginterferes[l.reg][i]] = 1;
+
return l;
}
+Loc claimreg(Isel *s, Reg r)
+{
+ Loc l;
+ int i;
+
+ if (s->rtaken[r])
+ die("Reg %s is already taken", regnames[r]);
+ for (i = 0; i < Nmode; i++)
+ s->rtaken[reginterferes[r][i]] = 1;
+ locreg(&l, r);
+ return l;
+}
+
Insn *mkinsnv(AsmOp op, va_list ap)
{
Loc *l;
@@ -297,7 +348,7 @@
a = selexpr(s, x);
b = selexpr(s, y);
- a = inri(s, a);
+ a = inr(s, a);
g(s, op, &b, &a, NULL);
return a;
}
@@ -431,7 +482,12 @@
void modeprint(FILE *fd, Loc *l)
{
- char mode[] = {'b', 's', 'l', 'q'};
+ char mode[] = {
+ [ModeB] = 'b',
+ [ModeS] = 's',
+ [ModeL] = 'l',
+ [ModeQ] = 'q'
+ };
fputc(mode[l->mode], fd);
}
@@ -540,8 +596,10 @@
is.ret = fn->ret;
prologue(&is, fn->stksz);
- for (i = 0; i < fn->nn; i++)
+ for (i = 0; i < fn->nn; i++) {
+ bzero(is.rtaken, sizeof is.rtaken);
isel(&is, fn->nl[i]);
+ }
epilogue(&is);
if (fn->isglobl)