shithub: mc

Download patch

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)