dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[dotgnu-pnet-commits] libjit ChangeLog tools/gen-rules-scanner.l tool...


From: Aleksey Demakov
Subject: [dotgnu-pnet-commits] libjit ChangeLog tools/gen-rules-scanner.l tool...
Date: Fri, 29 Dec 2006 23:16:15 +0000

CVSROOT:        /sources/dotgnu-pnet
Module name:    libjit
Changes by:     Aleksey Demakov <avd>   06/12/29 23:16:15

Modified files:
        .              : ChangeLog 
        tools          : gen-rules-scanner.l gen-rules-parser.y 
        jit            : jit-reg-alloc.h jit-reg-alloc.c 
                         jit-rules-alpha.ins jit-rules-x86.ins 

Log message:
        add support for register classes, clean up rule syntax and reg alloc 
interface

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libjit/ChangeLog?cvsroot=dotgnu-pnet&r1=1.288&r2=1.289
http://cvs.savannah.gnu.org/viewcvs/libjit/tools/gen-rules-scanner.l?cvsroot=dotgnu-pnet&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/libjit/tools/gen-rules-parser.y?cvsroot=dotgnu-pnet&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-reg-alloc.h?cvsroot=dotgnu-pnet&r1=1.19&r2=1.20
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-reg-alloc.c?cvsroot=dotgnu-pnet&r1=1.47&r2=1.48
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-rules-alpha.ins?cvsroot=dotgnu-pnet&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-rules-x86.ins?cvsroot=dotgnu-pnet&r1=1.25&r2=1.26

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/ChangeLog,v
retrieving revision 1.288
retrieving revision 1.289
diff -u -b -r1.288 -r1.289
--- ChangeLog   29 Dec 2006 19:08:14 -0000      1.288
+++ ChangeLog   29 Dec 2006 23:16:15 -0000      1.289
@@ -6,6 +6,20 @@
        * jit/jit-rules-x86.c (_jit_init_backend): initialize x86 register
        classes.
 
+       * jit/jit-reg-alloc.h, jit/jit-reg-alloc.c: specify register class
+       for each value and scratch register. Clean up interface.
+
+       * tools/gen-rules-scanner.l, tools/gen-rules-parser.y: add register
+       class declaration; "reg", "lreg", "freg" are not keywords anymore.
+       "scratch" requires register class specification. "clobber" accepts
+       register class which means all registers in the class are clobbered.
+       Remove "only", "spill_before", "unary", and "binary" keywords.
+       Replace "unary_note" and "binary_note" with "note". Also replace
+       "unary_branch" and "binary_branch" with "branch".
+
+       * jit/jit-rules-alpha.ins, jit/jit-rules-x86.ins: update according
+       to the new rule syntax.
+
 2006-12-20  Aleksey Demakov  <address@hidden>
 
        * jit/jit-thread.h, jit/jit-thread.c: add _jit_global_lock mutex.

Index: tools/gen-rules-scanner.l
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/tools/gen-rules-scanner.l,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- tools/gen-rules-scanner.l   30 Aug 2006 18:35:10 -0000      1.4
+++ tools/gen-rules-scanner.l   29 Dec 2006 23:16:15 -0000      1.5
@@ -84,9 +84,7 @@
 
 "->"                   { RETURNTOK(K_PTR); }
 "any"                  { RETURNTOK(K_ANY); }
-"reg"                  { RETURNTOK(K_REG); }
-"lreg"                 { RETURNTOK(K_LREG); }
-"freg"                 { RETURNTOK(K_FREG); }
+"all"                  { RETURNTOK(K_ALL); }
 "imm"                  { RETURNTOK(K_IMM); }
 "immzero"              { RETURNTOK(K_IMMZERO); }
 "imms8"                        { RETURNTOK(K_IMMS8); }
@@ -95,27 +93,24 @@
 "immu16"               { RETURNTOK(K_IMMU16); }
 "local"                        { RETURNTOK(K_LOCAL); }
 "frame"                        { RETURNTOK(K_FRAME); }
-"binary"               { RETURNTOK(K_BINARY); }
-"unary"                        { RETURNTOK(K_UNARY); }
-"unary_branch"         { RETURNTOK(K_UNARY_BRANCH); }
-"binary_branch"                { RETURNTOK(K_BINARY_BRANCH); }
-"unary_note"           { RETURNTOK(K_UNARY_NOTE); }
-"binary_note"          { RETURNTOK(K_BINARY_NOTE); }
 "ternary"              { RETURNTOK(K_TERNARY); }
-"stack"                        { RETURNTOK(K_STACK); }
-"only"                 { RETURNTOK(K_ONLY); }
+"branch"               { RETURNTOK(K_BRANCH); }
+"note"                 { RETURNTOK(K_NOTE); }
 "copy"                 { RETURNTOK(K_COPY); }
-"x87arith"             { RETURNTOK(K_X87ARITH); }
 "commutative"          { RETURNTOK(K_COMMUTATIVE); }
-"reversible"           { RETURNTOK(K_REVERSIBLE); }
 "if"                   { RETURNTOK(K_IF); }
 "clobber"              { RETURNTOK(K_CLOBBER); }
 "scratch"              { RETURNTOK(K_SCRATCH); }
 "space"                        { RETURNTOK(K_SPACE); }
+"stack"                        { RETURNTOK(K_STACK); }
+"x87_arith"            { RETURNTOK(K_X87_ARITH); }
+"x87_arith_reversible" { RETURNTOK(K_X87_ARITH_REVERSIBLE); }
+"%inst_type"           { RETURNTOK(K_INST_TYPE); }
+"%regclass"            { RETURNTOK(K_REG_CLASS); }
+"%lregclass"           { RETURNTOK(K_LREG_CLASS); }
+
 "manual"               { RETURNTOK(K_MANUAL); }
 "more_space"           { RETURNTOK(K_MORE_SPACE); }
-"spill_before"         { RETURNTOK(K_SPILL_BEFORE); }
-"%inst_type"           { RETURNTOK(K_INST_TYPE); }
 
 "!"?{IDALPHA}({DIGIT}|{IDALPHA})*      {
                        yylval.name = gensel_strdup(yytext);

Index: tools/gen-rules-parser.y
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/tools/gen-rules-parser.y,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- tools/gen-rules-parser.y    9 Sep 2006 05:21:03 -0000       1.12
+++ tools/gen-rules-parser.y    29 Dec 2006 23:16:15 -0000      1.13
@@ -103,32 +103,26 @@
 #define MAX_PATTERN                            (MAX_INPUT + MAX_SCRATCH)
 
 /*
- * Options.
+ * Rule Options.
  */
-#define        GENSEL_OPT_BINARY                       1
-#define        GENSEL_OPT_UNARY                        2
-#define        GENSEL_OPT_UNARY_BRANCH                 3
-#define        GENSEL_OPT_BINARY_BRANCH                4
-#define        GENSEL_OPT_UNARY_NOTE                   5
-#define        GENSEL_OPT_BINARY_NOTE                  6
-#define        GENSEL_OPT_TERNARY                      7
-#define        GENSEL_OPT_STACK                        8
-#define        GENSEL_OPT_ONLY                         9
-#define        GENSEL_OPT_COPY                         10
-#define GENSEL_OPT_X87ARITH                    11
-#define GENSEL_OPT_COMMUTATIVE                 12
-#define GENSEL_OPT_REVERSIBLE                  13
-
-#define        GENSEL_OPT_MANUAL                       14
-#define        GENSEL_OPT_MORE_SPACE                   15
-#define        GENSEL_OPT_SPILL_BEFORE                 16
+#define        GENSEL_OPT_TERNARY                      1
+#define GENSEL_OPT_BRANCH                      2
+#define GENSEL_OPT_NOTE                                3
+#define        GENSEL_OPT_COPY                         4
+#define GENSEL_OPT_COMMUTATIVE                 5
+#define        GENSEL_OPT_STACK                        6
+#define GENSEL_OPT_X87_ARITH                   7
+#define GENSEL_OPT_X87_ARITH_REVERSIBLE                8
+
+#define        GENSEL_OPT_MANUAL                       9
+#define        GENSEL_OPT_MORE_SPACE                   10
 
 /*
  * Pattern values.
  */
-#define        GENSEL_PATT_REG                         1
-#define        GENSEL_PATT_LREG                        2
-#define        GENSEL_PATT_FREG                        3
+#define GENSEL_PATT_ANY                                1
+#define        GENSEL_PATT_REG                         2
+#define        GENSEL_PATT_LREG                        3
 #define        GENSEL_PATT_IMM                         4
 #define        GENSEL_PATT_IMMZERO                     5
 #define        GENSEL_PATT_IMMS8                       6
@@ -141,20 +135,27 @@
 #define        GENSEL_PATT_CLOBBER                     13
 #define        GENSEL_PATT_IF                          14
 #define        GENSEL_PATT_SPACE                       15
-#define GENSEL_PATT_ANY                                16
 
 /*
- * Register flags.
+ * Value types.
  */
-#define GENSEL_FLAG_DEST                       1
-#define GENSEL_FLAG_CLOBBER                    2
-#define GENSEL_FLAG_EARLY_CLOBBER              3
+#define GENSEL_VALUE_STRING                    1
+#define GENSEL_VALUE_REGCLASS                  2
+#define        GENSEL_VALUE_ALL                        3
+#define GENSEL_VALUE_CLOBBER                   4
+#define GENSEL_VALUE_EARLY_CLOBBER             5
 
 /*
- * Value Type.
+ * Register class.
  */
-#define GENSEL_VALUE_STRING                    1
-#define GENSEL_VALUE_CHOICE                    2
+typedef struct gensel_regclass *gensel_regclass_t;
+struct gensel_regclass
+{
+       char                    *id;
+       char                    *def;
+       int                     is_long;
+       gensel_regclass_t       next;
+};
 
 /*
  * Option value.
@@ -163,11 +164,7 @@
 struct gensel_value
 {
        int                     type;
-       union
-       {
-               char            *value;
-               gensel_value_t  children;
-       };
+       void                    *value;
        gensel_value_t          next;
 };
 
@@ -178,7 +175,6 @@
 struct gensel_option
 {
        int                     option;
-       int                     flags;
        gensel_value_t          values;
        gensel_option_t         next;
 };
@@ -189,6 +185,7 @@
 typedef struct gensel_clause *gensel_clause_t;
 struct gensel_clause
 {
+       int                     dest;
        gensel_option_t         pattern;
        char                    *filename;
        long                    linenum;
@@ -214,9 +211,55 @@
 static char *gensel_local_names[] = {
        "local_offset", "local_offset2", "local_offset3"
 };
-static char *gensel_reg_flags[] = {
-       "0", "0", "_JIT_REGS_CLOBBER", "_JIT_REGS_EARLY_CLOBBER"
-};
+
+/*
+ * Register classes.
+ */
+static gensel_regclass_t gensel_regclass_list;
+
+/*
+ * Create a register class.
+ */
+static void
+gensel_create_regclass(char *id, char *def, int is_long)
+{
+       gensel_regclass_t rp;
+
+       rp = (gensel_regclass_t) malloc(sizeof(struct gensel_regclass));
+       if(!rp)
+       {
+               exit(1);
+       }
+       
+       rp->id = id;
+       rp->def = def;
+       rp->is_long = is_long;
+       rp->next = gensel_regclass_list;
+
+       gensel_regclass_list = rp;
+}
+
+gensel_regclass_t
+gensel_lookup_regclass(char *id)
+{
+       gensel_regclass_t rp;
+
+       rp = gensel_regclass_list;
+       for(;;)
+       {
+               if(!rp)
+               {
+                       gensel_error(
+                               gensel_filename, gensel_linenum,
+                               "invalid register class");
+               }
+               if(strcmp(id, rp->id) == 0)
+               {
+                       return rp;
+               }
+               rp = rp->next;
+       }
+}
 
 /*
  * Create a value.
@@ -233,7 +276,9 @@
        }
 
        vp->type = type;
+       vp->value = 0;
        vp->next = 0;
+
        return vp;
 }
 
@@ -241,25 +286,27 @@
  * Create string value.
  */
 static gensel_value_t
-gensel_create_string(char *value)
+gensel_create_string_value(char *value)
 {
        gensel_value_t vp;
 
        vp = gensel_create_value(GENSEL_VALUE_STRING);
        vp->value = value;
+
        return vp;
 }
 
 /*
- * Create choice value.
+ * Create string value.
  */
 static gensel_value_t
-gensel_create_choice(gensel_value_t children)
+gensel_create_regclass_value(char *value)
 {
        gensel_value_t vp;
 
-       vp = gensel_create_value(GENSEL_VALUE_CHOICE);
-       vp->children = children;
+       vp = gensel_create_value(GENSEL_VALUE_REGCLASS);
+       vp->value = gensel_lookup_regclass(value);
+
        return vp;
 }
 
@@ -267,7 +314,7 @@
  * Create an option.
  */
 static gensel_option_t
-gensel_create_option_2(int option, int flags, gensel_value_t values)
+gensel_create_option(int option, gensel_value_t values)
 {
        gensel_option_t op;
 
@@ -278,19 +325,48 @@
        }
 
        op->option = option;
-       op->flags = flags;
        op->values = values;
        op->next = 0;
        return op;
 }
 
 /*
- * Create an option with no flags.
+ * Create a register pattern element.
  */
 static gensel_option_t
-gensel_create_option(int option, gensel_value_t values)
+gensel_create_register(
+       int flags,
+       gensel_value_t value,
+       gensel_value_t values)
+{
+       gensel_regclass_t regclass;
+
+       if(flags)
+       {
+               value->next = gensel_create_value(flags);
+               value->next->next = values;
+       }
+       else
+       {
+               value->next = values;
+       }
+
+       regclass = value->value;
+       return gensel_create_option(
+               regclass->is_long ? GENSEL_PATT_LREG : GENSEL_PATT_REG,
+               value);
+}
+
+/*
+ * Create a scratch register pattern element.
+ */
+static gensel_option_t
+gensel_create_scratch(
+       gensel_value_t regclass,
+       gensel_value_t values)
 {
-       return gensel_create_option_2(option, 0, values);
+       regclass->next = values;
+       return gensel_create_option(GENSEL_PATT_SCRATCH, regclass);
 }
 
 /*
@@ -307,10 +383,6 @@
                {
                        free(values->value);
                }
-               else
-               {
-                       gensel_free_values(values->children);
-               }
                free(values);
                values = next;
        }
@@ -365,22 +437,20 @@
 /*
  * Declare the register variables that are needed for a set of clauses.
  */
-static void gensel_declare_regs(gensel_clause_t clauses, gensel_option_t 
options)
+static void
+gensel_declare_regs(gensel_clause_t clauses, gensel_option_t options)
 {
        gensel_option_t pattern;
-       gensel_value_t values;
        int regs, max_regs;
        int other_regs_mask;
        int imms, max_imms;
        int locals, max_locals;
        int scratch, others;
-       int have_regset;
 
        max_regs = 0;
        other_regs_mask = 0;
        max_imms = 0;
        max_locals = 0;
-       have_regset = 0;
        while(clauses != 0)
        {
                regs = 0;
@@ -398,23 +468,12 @@
                                break;
 
                        case GENSEL_PATT_REG:
-                       case GENSEL_PATT_FREG:
                                ++regs;
-                               if(pattern->values
-                                  && pattern->values->type != 
GENSEL_VALUE_STRING)
-                               {
-                                       have_regset = 1;
-                               }
                                break;
 
                        case GENSEL_PATT_LREG:
                                other_regs_mask |= (1 << regs);
                                ++regs;
-                               if(pattern->values
-                                  && pattern->values->type != 
GENSEL_VALUE_STRING)
-                               {
-                                       have_regset = 1;
-                               }
                                break;
 
                        case GENSEL_PATT_IMMZERO:
@@ -435,16 +494,7 @@
                                break;
 
                        case GENSEL_PATT_SCRATCH:
-                               values = pattern->values;
-                               while(values)
-                               {
                                        ++scratch;
-                                       if(values->type != GENSEL_VALUE_STRING)
-                                       {
-                                               have_regset = 1;
-                                       }
-                                       values = values->next;
-                               }
                        }
                        pattern = pattern->next;
                }
@@ -536,10 +586,6 @@
                printf("\tjit_nint local_offset, local_offset2, 
local_offset3;\n");
                break;
        }
-       if(have_regset)
-       {
-               printf("\tjit_regused_t regset;\n");
-       }
 }
 
 /*
@@ -553,7 +599,6 @@
                switch(pattern->option)
                {
                case GENSEL_PATT_REG:
-               case GENSEL_PATT_FREG:
                case GENSEL_PATT_LREG:
                case GENSEL_PATT_SCRATCH:
                case GENSEL_PATT_CLOBBER:
@@ -565,52 +610,22 @@
 }
 
 /*
- * Check if the pattern contains the dest register and if it is
- * defined correctly.
+ * Returns first register in the pattern if any.
  */
-static int
-gensel_contains_free_dest(gensel_clause_t clauses, gensel_option_t pattern)
+static gensel_option_t
+gensel_get_first_register(gensel_option_t pattern)
 {
-       int found, index;
-
-       found = 0;
-       index = 0;
        while(pattern)
        {
                switch(pattern->option)
                {
                case GENSEL_PATT_REG:
-               case GENSEL_PATT_FREG:
                case GENSEL_PATT_LREG:
-               case GENSEL_PATT_LOCAL:
-               case GENSEL_PATT_FRAME:
-                       if(pattern->flags == GENSEL_FLAG_DEST)
-                       {
-                               if(index != 0)
-                               {
-                                       gensel_error(
-                                               clauses->filename,
-                                               clauses->linenum,
-                                               "The destination must be the 
first pattern element.");
-                               }
-                               found = 1;
-                       }
-                       ++index;
-                       break;
-
-               case GENSEL_PATT_ANY:
-               case GENSEL_PATT_IMMZERO:
-               case GENSEL_PATT_IMM:
-               case GENSEL_PATT_IMMS8:
-               case GENSEL_PATT_IMMU8:
-               case GENSEL_PATT_IMMS16:
-               case GENSEL_PATT_IMMU16:
-                       ++index;
-                       break;
+                       return pattern;
                }
                pattern = pattern->next;
        }
-       return found;
+       return 0;
 }
 
 static void
@@ -654,7 +669,6 @@
                        break;
 
                case GENSEL_PATT_REG:
-               case GENSEL_PATT_FREG:
                case GENSEL_PATT_LREG:
                case GENSEL_PATT_LOCAL:
                case GENSEL_PATT_FRAME:
@@ -705,7 +719,6 @@
                {
                case GENSEL_PATT_ANY:
                case GENSEL_PATT_REG:
-               case GENSEL_PATT_FREG:
                case GENSEL_PATT_LREG:
                case GENSEL_PATT_LOCAL:
                case GENSEL_PATT_FRAME:
@@ -748,7 +761,6 @@
        char *names[MAX_PATTERN],
        char *other_names[MAX_PATTERN])
 {
-       gensel_value_t values;
        int regs, imms, locals, index;
 
        gensel_init_names(MAX_PATTERN, names, other_names);
@@ -766,7 +778,6 @@
                        break;
 
                case GENSEL_PATT_REG:
-               case GENSEL_PATT_FREG:
                        names[index] = gensel_reg_names[regs];
                        ++regs;
                        ++index;
@@ -801,14 +812,9 @@
                        break;
 
                case GENSEL_PATT_SCRATCH:
-                       values = pattern->values;
-                       while(values)
-                       {
                                names[index] = gensel_reg_names[regs];
                                ++regs;
                                ++index;
-                               values = values->next;
-                       }
                }
                pattern = pattern->next;
        }
@@ -836,11 +842,7 @@
        }
        while(*code != '\0')
        {
-#if 0
-               first = free_dest ? '0' : '1';
-#else
                first = '1';
-#endif
                if(*code == '$' && code[1] >= first && code[1] < (first + 
MAX_PATTERN))
                {
                        index = code[1] - first;
@@ -889,30 +891,75 @@
        gensel_output_code(clause->pattern, clause->code, names, other_names, 
free_dest, 0);
 }
 
+static void
+gensel_output_register(char *name, gensel_regclass_t regclass, gensel_value_t 
values)
+{
+       printf("\t\t_jit_regs_init_%s(&regs, insn, ", name);
+       switch(values ? values->type : 0)
+       {
+       case GENSEL_VALUE_CLOBBER:
+               printf("_JIT_REGS_CLOBBER");
+               values = values->next;
+               break;
+       case GENSEL_VALUE_EARLY_CLOBBER:
+               printf("_JIT_REGS_EARLY_CLOBBER");
+               values = values->next;
+               break;
+       default:
+               printf("0");
+               break;
+       }
+       printf(", %s);\n", regclass->def);
+       if(values && values->value)
+       {
+               char *reg;
+               reg = values->value;
+               if(values->next && values->next->value)
+               {
+                       char *other_reg;
+                       other_reg = values->next->value;
+                       printf("\t\t_jit_regs_set_%s(gen, &regs, 
_jit_regs_lookup(\"%s\"), _jit_regs_lookup(\"%s\"));\n",
+                              name, reg, other_reg);
+               }
+               else
+               {
+                       printf("\t\t_jit_regs_set_%s(gen, &regs, 
_jit_regs_lookup(\"%s\"), -1);\n",
+                              name, reg);
+               }
+       }
+}
+
+/*
+ * Output value initialization code.
+ */
+static void
+gensel_output_register_pattern(char *name, gensel_option_t pattern)
+{
+       gensel_output_register(name, pattern->values->value, 
pattern->values->next);
+}
+
 /*
  * Output the clauses for a rule.
  */
 static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t 
options)
 {
+       char *name;
        char *args[MAX_INPUT];
        char *names[MAX_PATTERN];
        char *other_names[MAX_PATTERN];
        gensel_clause_t clause;
        gensel_option_t pattern;
        gensel_option_t space, more_space;
-       gensel_value_t values, child;
-       int first, seen_option;
+       gensel_value_t values;
        int regs, imms, locals, scratch, index;
-       int clobber_all, ternary, free_dest;
+       int first, seen_option;
+       int ternary, free_dest;
        int contains_registers;
+       gensel_regclass_t regclass;
 
        /* If the clause is manual, then output it as-is */
        if(gensel_search_option(options, GENSEL_OPT_MANUAL))
        {
-               if(gensel_search_option(options, GENSEL_OPT_SPILL_BEFORE))
-               {
-                       printf("\t_jit_regs_spill_all(gen);\n");
-               }
                gensel_init_names(MAX_PATTERN, names, other_names);
                gensel_output_clause_code(clauses, names, other_names, 0);
                return;
@@ -936,10 +983,6 @@
                printf("\t_jit_regs_t regs;\n");
        }
        gensel_declare_regs(clauses, options);
-       if(gensel_search_option(options, GENSEL_OPT_SPILL_BEFORE))
-       {
-               printf("\t_jit_regs_spill_all(gen);\n");
-       }
 
        ternary = (0 != gensel_search_option(options, GENSEL_OPT_TERNARY));
 
@@ -949,23 +992,7 @@
        while(clause)
        {
                contains_registers = gensel_contains_registers(clause->pattern);
-               free_dest = gensel_contains_free_dest(clauses, clause->pattern);
-
-               clobber_all = 0;
-               pattern = gensel_search_option(clause->pattern, 
GENSEL_PATT_CLOBBER);
-               if(pattern)
-               {
-                       values = pattern->values;
-                       while(values)
-                       {
-                               if(values->value && strcmp(values->value, "*") 
== 0)
-                               {
-                                       clobber_all = 1;
-                                       break;
-                               }
-                               values = values->next;
-                       }
-               }
+               free_dest = clause->dest;
 
                gensel_build_arg_index(clause->pattern, 3, args, 0, ternary, 
free_dest);
 
@@ -989,7 +1016,6 @@
 
                                case GENSEL_PATT_REG:
                                case GENSEL_PATT_LREG:
-                               case GENSEL_PATT_FREG:
                                        /* Do not check if the value is in
                                           a register as the allocator will
                                           load them anyway as long as other
@@ -1128,55 +1154,21 @@
                        printf("\telse\n\t{\n");
                }
 
-               if(gensel_search_option(options, GENSEL_OPT_BINARY_BRANCH)
-                  || gensel_search_option(options, GENSEL_OPT_UNARY_BRANCH))
-               {
-                       /* Spill all other registers back to their original 
positions */
-                       if(contains_registers)
-                       {
-                               clobber_all = 1;
-                       }
-                       else
-                       {
-                               printf("\t\t_jit_regs_spill_all(gen);\n");
-                       }
-               }
-
                if(contains_registers)
                {
                        seen_option = 0;
                        printf("\t\t_jit_regs_init(gen, &regs, ");
-                       if(clobber_all)
-                       {
-                               seen_option = 1;
-                               printf("_JIT_REGS_CLOBBER_ALL");
-                       }
                        if(ternary)
                        {
-                               if(seen_option)
-                               {
-                                       printf(" | ");
-                               }
-                               else
-                               {
                                        seen_option = 1;
-                               }
                                printf("_JIT_REGS_TERNARY");
                        }
-                       if(free_dest)
-                       {
-                               if(seen_option)
-                               {
-                                       printf(" | ");
-                               }
-                               else
+                       else if(free_dest)
                                {
                                        seen_option = 1;
-                               }
                                printf("_JIT_REGS_FREE_DEST");
                        }
-                       if(gensel_search_option(options, 
GENSEL_OPT_BINARY_BRANCH)
-                          || gensel_search_option(options, 
GENSEL_OPT_UNARY_BRANCH))
+                       if(gensel_search_option(options, GENSEL_OPT_BRANCH))
                        {
                                if(seen_option)
                                {
@@ -1212,7 +1204,7 @@
                                }
                                printf("_JIT_REGS_STACK");
                        }
-                       if(gensel_search_option(options, GENSEL_OPT_ONLY))
+                       if(gensel_search_option(options, 
GENSEL_OPT_COMMUTATIVE))
                        {
                                if(seen_option)
                                {
@@ -1222,9 +1214,10 @@
                                {
                                        seen_option = 1;
                                }
-                               printf("_JIT_REGS_CLOBBER_STACK");
+                               printf("_JIT_REGS_COMMUTATIVE");
                        }
-                       if(gensel_search_option(options, GENSEL_OPT_X87ARITH))
+                       /* x87 options */
+                       if(gensel_search_option(options, GENSEL_OPT_X87_ARITH))
                        {
                                if(seen_option)
                                {
@@ -1236,19 +1229,7 @@
                                }
                                printf("_JIT_REGS_X87_ARITH");
                        }
-                       if(gensel_search_option(options, 
GENSEL_OPT_COMMUTATIVE))
-                       {
-                               if(seen_option)
-                               {
-                                       printf(" | ");
-                               }
-                               else
-                               {
-                                       seen_option = 1;
-                               }
-                               printf("_JIT_REGS_COMMUTATIVE");
-                       }
-                       if(gensel_search_option(options, GENSEL_OPT_REVERSIBLE))
+                       else if(gensel_search_option(options, 
GENSEL_OPT_X87_ARITH_REVERSIBLE))
                        {
                                if(seen_option)
                                {
@@ -1258,7 +1239,7 @@
                                {
                                        seen_option = 1;
                                }
-                               printf("_JIT_REGS_REVERSIBLE");
+                               printf("_JIT_REGS_X87_ARITH_REVERSIBLE");
                        }
                        if(!seen_option)
                        {
@@ -1267,17 +1248,17 @@
                        printf(");\n");
 
                        if(!(ternary || free_dest
-                            || gensel_search_option(options, 
GENSEL_OPT_BINARY_NOTE)
-                            || gensel_search_option(options, 
GENSEL_OPT_BINARY_BRANCH)
-                            || gensel_search_option(options, 
GENSEL_OPT_UNARY_NOTE)
-                            || gensel_search_option(options, 
GENSEL_OPT_UNARY_BRANCH)))
+                            || gensel_search_option(options, GENSEL_OPT_NOTE)
+                            || gensel_search_option(options, 
GENSEL_OPT_BRANCH)))
                        {
-                               printf("\t\t_jit_regs_init_dest(&regs, insn, 
0);\n");
+                               pattern = 
gensel_get_first_register(clause->pattern);
+                               gensel_output_register("dest", pattern ? 
pattern->values->value : 0, 0);
                        }
                }
 
                regs = 0;
                index = 0;
+               scratch = 0;
                pattern = clause->pattern;
                while(pattern)
                {
@@ -1288,72 +1269,8 @@
                                break;
 
                        case GENSEL_PATT_REG:
-                       case GENSEL_PATT_FREG:
-                               printf("\t\t_jit_regs_init_%s(&regs, insn, 
%s);\n",
-                                      args[index], 
gensel_reg_flags[pattern->flags]);
-                               if(pattern->values && pattern->values->value)
-                               {
-                                       if(pattern->values->type == 
GENSEL_VALUE_STRING)
-                                       {
-                                               
printf("\t\t_jit_regs_set_%s(gen, &regs, _jit_regs_lookup(\"%s\"), -1);\n",
-                                                      args[index], 
pattern->values->value);
-                                       }
-                                       else
-                                       {
-                                               printf("\t\tregset = 
jit_regused_init;\n");
-                                               child = 
pattern->values->children;
-                                               while(child)
-                                               {
-                                                       printf("\t\t%s = 
_jit_regs_lookup(\"%s\");\n",
-                                                              
gensel_reg_names[regs], child->value);
-                                                       printf("\t\tif(%s >= 
0)\n", gensel_reg_names[regs]);
-                                                       
printf("\t\t\tjit_reg_set_used(regset, %s);\n",
-                                                              
gensel_reg_names[regs]);
-                                                       child = child->next;
-                                               }
-                                               
printf("\t\t_jit_regs_set_%s_from(&regs, regset);\n",
-                                                      args[index]);
-                                       }
-                               }
-                               ++regs;
-                               ++index;
-                               break;
-
                        case GENSEL_PATT_LREG:
-                               printf("\t\t_jit_regs_init_%s(&regs, insn, 
%s);\n",
-                                      args[index], 
gensel_reg_flags[pattern->flags]);
-                               if(pattern->values && pattern->values->value)
-                               {
-                                       if(pattern->values->type == 
GENSEL_VALUE_STRING)
-                                       {
-                                               if(pattern->values->next && 
pattern->values->next->value)
-                                               {
-                                                       
printf("\t\t_jit_regs_set_%s(gen, &regs, _jit_regs_lookup(\"%s\"), 
_jit_regs_lookup(\"%s\"));\n",
-                                                              args[index], 
pattern->values->value, pattern->values->next->value);
-                                               }
-                                               else
-                                               {
-                                                       
printf("\t\t_jit_regs_set_%s(gen, &regs, _jit_regs_lookup(\"%s\"), -1);\n",
-                                                              args[index], 
pattern->values->value);
-                                               }
-                                       }
-                                       else
-                                       {
-                                               printf("\t\tregset = 
jit_regused_init;\n");
-                                               child = 
pattern->values->children;
-                                               while(child)
-                                               {
-                                                       printf("\t\t%s = 
_jit_regs_lookup(\"%s\");\n",
-                                                              
gensel_reg_names[regs], child->value);
-                                                       printf("\t\tif(%s >= 
0)\n", gensel_reg_names[regs]);
-                                                       
printf("\t\t\tjit_reg_set_used(regset, %s);\n",
-                                                              
gensel_reg_names[regs]);
-                                                       child = child->next;
-                                               }
-                                               
printf("\t\t_jit_regs_set_%s_from(&regs, regset);\n",
-                                                      args[index]);
-                                       }
-                               }
+                               gensel_output_register_pattern(args[index], 
pattern);
                                ++regs;
                                ++index;
                                break;
@@ -1370,59 +1287,52 @@
 
                        case GENSEL_PATT_FRAME:
                                printf("\t\t_jit_regs_force_out(gen, insn->%s, 
%d);\n",
-                                      args[index], (pattern->flags == 
GENSEL_FLAG_DEST));
+                                      args[index], (free_dest && index == 0));
                                printf("\t\t_jit_gen_fix_value(insn->%s);\n",
                                       args[index]);
                                ++index;
                                break;
 
                        case GENSEL_PATT_SCRATCH:
-                               values = pattern->values;
-                               while(values)
-                               {
-                                       if(values->value
-                                          && (values->type != 
GENSEL_VALUE_STRING
-                                              || strcmp(values->value, "?") != 
0))
-                                       {
-                                               if(values->type == 
GENSEL_VALUE_STRING)
-                                               {
-                                                       
printf("\t\t_jit_regs_add_scratch(gen, &regs, _jit_regs_lookup(\"%s\"));\n",
-                                                              values->value);
-                                               }
-                                               else
-                                               {
-                                                       printf("\t\tregset = 
jit_regused_init;\n");
-                                                       child = 
values->children;
-                                                       while(child)
-                                                       {
-                                                               printf("\t\t%s 
= _jit_regs_lookup(\"%s\");\n",
-                                                                      
gensel_reg_names[regs], child->value);
-                                                               
printf("\t\tif(%s >= 0)\n", gensel_reg_names[regs]);
-                                                               
printf("\t\t\tjit_reg_set_used(regset, %s);\n",
-                                                                      
gensel_reg_names[regs]);
-                                                               child = 
child->next;
-                                                       }
-                                                       
printf("\t\t_jit_regs_add_scratch_from(&regs, regset);\n");
-                                               }
-                                       }
-                                       else
+                               regclass = pattern->values->value;
+                               printf("\t\t_jit_regs_add_scratch(&regs, 
%s);\n",
+                                      regclass->def);
+                               if(pattern->values->next && 
pattern->values->next->value)
                                        {
-                                               
printf("\t\t_jit_regs_add_scratch(gen, &regs, -1);\n");
+                                       name = pattern->values->next->value;
+                                       printf("\t\t_jit_regs_set_scratch(gen, 
&regs, %d, _jit_regs_lookup(\"%s\"));\n",
+                                              scratch, name);
                                        }
                                        ++regs;
+                               ++scratch;
                                        ++index;
-                                       values = values->next;
-                               }
                                break;
 
                        case GENSEL_PATT_CLOBBER:
                                values = pattern->values;
                                while(values)
                                {
-                                       if(values->value && 
strcmp(values->value, "*") != 0)
+                                       if(!values->value)
                                        {
-                                               
printf("\t\t_jit_regs_set_clobber(gen, &regs, _jit_regs_lookup(\"%s\"));\n",
-                                                      values->value);
+                                               continue;
+                                       }
+                                       switch(values->type)
+                                       {
+                                       case GENSEL_VALUE_STRING:
+                                               name = values->value;
+                                               
printf("\t\t_jit_regs_clobber(&regs, _jit_regs_lookup(\"%s\"));\n",
+                                                      name);
+                                               break;
+
+                                       case GENSEL_VALUE_REGCLASS:
+                                               regclass = values->value;
+                                               
printf("\t\t_jit_regs_clobber_class(gen, &regs, %s);\n",
+                                                       regclass->def);
+                                               break;
+
+                                       case GENSEL_VALUE_ALL:
+                                               
printf("\t\t_jit_regs_clobber_all(gen, &regs);\n");
+                                               break;
                                        }
                                        values = values->next;
                                }
@@ -1431,6 +1341,19 @@
                        pattern = pattern->next;
                }
 
+               if(gensel_search_option(options, GENSEL_OPT_BRANCH))
+               {
+                       /* Spill all other registers back to their original 
positions */
+                       if(contains_registers)
+                       {
+                               printf("\t\t_jit_regs_clobber_all(gen, 
&regs);\n");
+                       }
+                       else
+                       {
+                               printf("\t\t_jit_regs_spill_all(gen);\n");
+                       }
+               }
+
                if(gensel_new_inst_type)
                {
                        if(contains_registers)
@@ -1510,17 +1433,16 @@
                                break;
 
                        case GENSEL_PATT_REG:
-                       case GENSEL_PATT_FREG:
-                               printf("\t\t%s = 
_jit_reg_info[_jit_regs_%s(&regs)].cpu_reg;\n",
+                               printf("\t\t%s = 
_jit_reg_info[_jit_regs_get_%s(&regs)].cpu_reg;\n",
                                       gensel_reg_names[regs], args[index]);
                                ++regs;
                                ++index;
                                break;
 
                        case GENSEL_PATT_LREG:
-                               printf("\t\t%s = 
_jit_reg_info[_jit_regs_%s(&regs)].cpu_reg;\n",
+                               printf("\t\t%s = 
_jit_reg_info[_jit_regs_get_%s(&regs)].cpu_reg;\n",
                                       gensel_reg_names[regs], args[index]);
-                               printf("\t\t%s = 
_jit_reg_info[_jit_regs_%s_other(&regs)].cpu_reg;\n",
+                               printf("\t\t%s = 
_jit_reg_info[_jit_regs_get_%s_other(&regs)].cpu_reg;\n",
                                       gensel_other_reg_names[regs], 
args[index]);
                                ++regs;
                                ++index;
@@ -1550,15 +1472,11 @@
                                break;
 
                        case GENSEL_PATT_SCRATCH:
-                               values = pattern->values;
-                               while(values)
-                               {
-                                       printf("\t\t%s = 
_jit_reg_info[_jit_regs_scratch(&regs, %d)].cpu_reg;\n",
+                               printf("\t\t%s = 
_jit_reg_info[_jit_regs_get_scratch(&regs, %d)].cpu_reg;\n",
                                               gensel_reg_names[regs], scratch);
                                        ++regs;
                                        ++scratch;
-                                       values = values->next;
-                               }
+                               ++index;
                                break;
 
                        }
@@ -1693,10 +1611,8 @@
 %token CODE_BLOCK              "a code block"
 %token LITERAL                 "literal string"
 %token K_PTR                   "`->'"
-%token K_ANY                   "any variable"
-%token K_REG                   "word register"
-%token K_LREG                  "long register"
-%token K_FREG                  "float register"
+%token K_ANY                   "any value"
+%token K_ALL                   "all registers"
 %token K_IMM                   "immediate value"
 %token K_IMMZERO               "immediate zero value"
 %token K_IMMS8                 "immediate signed 8-bit value"
@@ -1705,30 +1621,26 @@
 %token K_IMMU16                        "immediate unsigned 16-bit value"
 %token K_LOCAL                 "local variable"
 %token K_FRAME                 "local variable forced out into the stack frame"
-%token K_BINARY                        "`binary'"
-%token K_UNARY                 "`unary'"
-%token K_UNARY_BRANCH          "`unary_branch'"
-%token K_BINARY_BRANCH         "`binary_branch'"
-%token K_UNARY_NOTE            "`unary_note'"
-%token K_BINARY_NOTE           "`binary_note'"
+%token K_NOTE                  "`note'"
 %token K_TERNARY               "`ternary'"
-%token K_STACK                 "`stack'"
-%token K_ONLY                  "`only'"
+%token K_BRANCH                        "`branch'"
 %token K_COPY                  "`copy'"
-%token K_X87ARITH              "`x87arith'"
 %token K_COMMUTATIVE           "`commutative'"
-%token K_REVERSIBLE            "`reversible'"
 %token K_IF                    "`if'"
 %token K_CLOBBER               "`clobber'"
 %token K_SCRATCH               "`scratch'"
 %token K_SPACE                 "`space'"
+%token K_STACK                 "`stack'"
+%token K_X87_ARITH             "`x87_arith'"
+%token K_X87_ARITH_REVERSIBLE  "`x87_arith_reversible'"
 %token K_INST_TYPE             "`%inst_type'"
+%token K_REG_CLASS             "`%reg_class'"
+%token K_LREG_CLASS            "`%lreg_class'"
 
 /* deperecated keywords */
 
 %token K_MANUAL                        "`manual'"
 %token K_MORE_SPACE            "`more_space'"
-%token K_SPILL_BEFORE          "`spill_before'"
 
 /*
  * Define the yylval types of the various non-terminals.
@@ -1736,12 +1648,12 @@
 %type <code>                   CODE_BLOCK
 %type <name>                   IDENTIFIER LITERAL
 %type <name>                   IfClause IdentifierList Literal
-%type <tag>                    OptionTag InputTag RegTag LRegTag RegFlag 
LocalTag LocalFlag
+%type <tag>                    OptionTag InputTag DestFlag RegFlag
 %type <clauses>                        Clauses Clause
-%type <options>                        Options OptionList Pattern Pattern2
-%type <option>                 Option PatternElement Scratch Clobber If Space
-%type <values>                 ValuePair ValueList ValueChoice ValueChoiceList
-%type <value>                  Value
+%type <options>                        Options Pattern
+%type <option>                 Option PatternElement
+%type <values>                 ValuePair ClobberList ClobberSpec
+%type <value>                  Value ClobberEntry RegClass
 
 %expect 0
 
@@ -1787,6 +1699,12 @@
                    gensel_inst_type = $2;
                    gensel_new_inst_type = 1;
                }
+       | K_REG_CLASS IDENTIFIER IDENTIFIER {
+                       gensel_create_regclass($2, $3, 0);
+               }
+       | K_LREG_CLASS IDENTIFIER IDENTIFIER {
+                       gensel_create_regclass($2, $3, 1);
+               }
        ;
 
 IdentifierList
@@ -1812,16 +1730,15 @@
        ;
 
 Options
-       : /* empty */                   { $$.head = $$.tail = 0; }
-       |  OptionList                   { $$ = $1; }
-       ;
-
-OptionList
-       : Option                        {
+       : /* empty */                   {
+                       $$.head = 0;
+                       $$.tail = 0;
+               }
+       | Option                        {
                        $$.head = $1;
                        $$.tail = $1;
                }
-       | OptionList ',' Option         {
+       | Options ',' Option            {
                        $1.tail->next = $3;
                        $$.head = $1.head;
                        $$.tail = $3;
@@ -1829,7 +1746,9 @@
        ;
 
 Option
-       : OptionTag                     { $$ = gensel_create_option($1, 0); }
+       : OptionTag                     {
+                       $$ = gensel_create_option($1, 0);
+               }
        ;
 
 Clauses
@@ -1842,17 +1761,18 @@
        ;
 
 Clause
-       : '[' Pattern ']' K_PTR CODE_BLOCK      {
+       : '[' DestFlag Pattern ']' K_PTR CODE_BLOCK {
                        gensel_clause_t clause;
                        clause = (gensel_clause_t)malloc(sizeof(struct 
gensel_clause));
                        if(!clause)
                        {
                                exit(1);
                        }
-                       clause->pattern = $2.head;
-                       clause->filename = $5.filename;
-                       clause->linenum = $5.linenum;
-                       clause->code = $5.block;
+                       clause->dest = $2;
+                       clause->pattern = $3.head;
+                       clause->filename = $6.filename;
+                       clause->linenum = $6.linenum;
+                       clause->code = $6.block;
                        clause->next = 0;
                        $$.head = clause;
                        $$.tail = clause;
@@ -1860,19 +1780,15 @@
        ;
 
 Pattern
-       : /* empty */                   { $$.head = $$.tail = 0; }
-       | Pattern2                      {
-                       $$.head = $1.head;
-                       $$.tail = $1.tail;
+       : /* empty */                   {
+                       $$.head = 0;
+                       $$.tail = 0;
                }
-       ;
-
-Pattern2
-       : PatternElement                {
+       | PatternElement                {
                        $$.head = $1;
                        $$.tail = $1;
                }
-       | Pattern2 ',' PatternElement   {
+       | Pattern ',' PatternElement    {
                        $1.tail->next = $3;
                        $$.head = $1.head;
                        $$.tail = $3;
@@ -1883,147 +1799,115 @@
        : InputTag                      {
                        $$ = gensel_create_option($1, 0);
                }
-       | LocalFlag LocalTag            {
-                       $$ = gensel_create_option_2($2, $1, 0);
-               }
-       | RegFlag RegTag                {
-                       $$ = gensel_create_option_2($2, $1, 0);
+       | RegFlag RegClass              {
+                       $$ = gensel_create_register($1, $2, 0);
                }
-       | RegFlag RegTag '(' Value ')'  {
-                       $$ = gensel_create_option_2($2, $1, $4);
+       | RegFlag RegClass '(' Value ')'        {
+                       $$ = gensel_create_register($1, $2, $4);
                }
-       | RegFlag RegTag '(' ValueChoice ')'    {
-                       gensel_value_t cp;
-                       cp = gensel_create_choice($4.head);
-                       $$ = gensel_create_option_2($2, $1, cp);
+       | RegFlag RegClass '(' ValuePair ')'    {
+                       gensel_regclass_t regclass;
+                       regclass = $2->value;
+                       if(!regclass->is_long)
+                       {
+                               gensel_error(
+                                       gensel_filename, gensel_linenum,
+                                       "not a long pair register");
                }
-       | RegFlag LRegTag               {
-                       $$ = gensel_create_option_2($2, $1, 0);
+                       $$ = gensel_create_register($1, $2, $4.head);
                }
-       | RegFlag LRegTag '(' Value ')' {
-                       $$ = gensel_create_option_2($2, $1, $4);
+       | K_SCRATCH RegClass {
+                       gensel_regclass_t regclass;
+                       regclass = $2->value;
+                       if(regclass->is_long)
+                       {
+                               gensel_error(
+                                       gensel_filename, gensel_linenum,
+                                       "scratch register cannot be a long 
pair");
                }
-       | RegFlag LRegTag '(' ValuePair ')'     {
-                       $$ = gensel_create_option_2($2, $1, $4.head);
+                       $$ = gensel_create_scratch($2, 0);
                }
-       | RegFlag LRegTag '(' ValueChoice ')'   {
-                       gensel_value_t cp;
-                       cp = gensel_create_choice($4.head);
-                       $$ = gensel_create_option_2($2, $1, cp);
+       | K_SCRATCH RegClass '(' Value ')' {
+                       gensel_regclass_t regclass;
+                       regclass = $2->value;
+                       if(regclass->is_long)
+                       {
+                               gensel_error(
+                                       gensel_filename, gensel_linenum,
+                                       "scratch register cannot be a long 
pair");
                }
-       | Scratch
-       | Clobber
-       | If
-       | Space
-       ;
-
-Scratch
-       : K_SCRATCH '(' ValueChoiceList ')'     {
-                       $$ = gensel_create_option(GENSEL_PATT_SCRATCH, $3.head);
+                       $$ = gensel_create_scratch($2, $4);
                }
-       ;
-
-Clobber
-       : K_CLOBBER '(' ValueList ')'   {
+       | K_CLOBBER '(' ClobberSpec ')' {
                        $$ = gensel_create_option(GENSEL_PATT_CLOBBER, $3.head);
                }
-       ;
-       
-If
-       : K_IF '(' Value ')'            {
+       | K_IF '(' Value ')'            {
                        $$ = gensel_create_option(GENSEL_PATT_IF, $3);
                }
-       ;
-
-Space
-       : K_SPACE '(' Value ')'         {
+       | K_SPACE '(' Value ')'         {
                        $$ = gensel_create_option(GENSEL_PATT_SPACE, $3);
                }
        ;
 
-ValueChoiceList
-       : Value                         {
-                       $$.head = $1;
-                       $$.tail = $1;
+ClobberSpec
+       : K_ALL                         {
+                       $$.head = $$.tail = 
gensel_create_value(GENSEL_VALUE_ALL);
                }
-       | ValueChoice                   {
-                       gensel_value_t cp;
-                       cp = gensel_create_choice($1.head);
-                       $$.head = cp;
-                       $$.tail = cp;
-               }
-       | ValueChoiceList ',' Value             {
-                       $1.tail->next = $3;
-                       $$.head = $1.head;
-                       $$.tail = $3;
-               }
-       | ValueChoiceList ',' ValueChoice       {
-                       gensel_value_t cp;
-                       cp = gensel_create_choice($3.head);
-                       $1.tail->next = cp;
-                       $$.head = $1.head;
-                       $$.tail = cp;
+       | ClobberList                   {
+                       $$ = $1;
                }
        ;
 
-ValueChoice
-       : Value '|' Value               {
-                       $1->next = $3;
+ClobberList
+       : ClobberEntry                  {
                        $$.head = $1;
-                       $$.tail = $3;
+                       $$.tail = $1;
                }
-       | ValueChoice '|' Value         {
+       | ClobberList ',' ClobberEntry  {
                        $1.tail->next = $3;
                        $$.head = $1.head;
                        $$.tail = $3;
                }
        ;
 
-ValuePair
-       : Value ':' Value               {
-                       $1->next = $3;
-                       $$.head = $1;
-                       $$.tail = $3;
-               }
+ClobberEntry
+       : RegClass                      { $$ = $1; }
+       | Value                         { $$ = $1; }
        ;
 
-ValueList
-       : Value                         {
-                       $$.head = $1;
-                       $$.tail = $1;
-               }
-       | ValueList ',' Value           {
-                       $1.tail->next = $3;
-                       $$.head = $1.head;
-                       $$.tail = $3;
+RegClass
+       : IDENTIFIER                    {
+                       $$ = gensel_create_regclass_value($1);
                }
        ;
 
 Value
        : Literal                       {
-                       $$ = gensel_create_string($1);
+                       $$ = gensel_create_string_value($1);
+               }
+       ;
+
+ValuePair
+       : Value ':' Value               {
+                       $1->next = $3;
+                       $$.head = $1;
+                       $$.tail = $3;
                }
        ;
 
 OptionTag
-       : K_BINARY                      { $$ = GENSEL_OPT_BINARY; }
-       | K_UNARY                       { $$ = GENSEL_OPT_UNARY; }
-       | K_UNARY_BRANCH                { $$ = GENSEL_OPT_UNARY_BRANCH; }
-       | K_BINARY_BRANCH               { $$ = GENSEL_OPT_BINARY_BRANCH; }
-       | K_UNARY_NOTE                  { $$ = GENSEL_OPT_UNARY_NOTE; }
-       | K_BINARY_NOTE                 { $$ = GENSEL_OPT_BINARY_NOTE; }
-       | K_TERNARY                     { $$ = GENSEL_OPT_TERNARY; }
-       | K_STACK                       { $$ = GENSEL_OPT_STACK; }
-       | K_ONLY                        { $$ = GENSEL_OPT_ONLY; }
+       : K_TERNARY                     { $$ = GENSEL_OPT_TERNARY; }
+       | K_BRANCH                      { $$ = GENSEL_OPT_BRANCH; }
+       | K_NOTE                        { $$ = GENSEL_OPT_NOTE; }
        | K_COPY                        { $$ = GENSEL_OPT_COPY; }
-       | K_X87ARITH                    { $$ = GENSEL_OPT_X87ARITH; }
        | K_COMMUTATIVE                 { $$ = GENSEL_OPT_COMMUTATIVE; }
-       | K_REVERSIBLE                  { $$ = GENSEL_OPT_REVERSIBLE; }
+       | K_STACK                       { $$ = GENSEL_OPT_STACK; }
+       | K_X87_ARITH                   { $$ = GENSEL_OPT_X87_ARITH; }
+       | K_X87_ARITH_REVERSIBLE        { $$ = GENSEL_OPT_X87_ARITH_REVERSIBLE; 
}
 
        /* deprecated: */
        | K_MANUAL                      { $$ = GENSEL_OPT_MANUAL; }
        | K_MORE_SPACE                  { $$ = GENSEL_OPT_MORE_SPACE; }
-       | K_SPILL_BEFORE                { $$ = GENSEL_OPT_SPILL_BEFORE; }
        ;
        
 InputTag
@@ -2033,33 +1917,20 @@
        | K_IMMU8                       { $$ = GENSEL_PATT_IMMU8; }
        | K_IMMS16                      { $$ = GENSEL_PATT_IMMS16; }
        | K_IMMU16                      { $$ = GENSEL_PATT_IMMU16; }
-       | K_ANY                         { $$ = GENSEL_PATT_ANY; }
-       ;
-
-LocalTag
-       : K_LOCAL                       { $$ = GENSEL_PATT_LOCAL; }
+       | K_LOCAL                       { $$ = GENSEL_PATT_LOCAL; }
        | K_FRAME                       { $$ = GENSEL_PATT_FRAME; }
+       | K_ANY                         { $$ = GENSEL_PATT_ANY; }
        ;
 
-RegTag
-       : K_REG                         { $$ = GENSEL_PATT_REG; }
-       | K_FREG                        { $$ = GENSEL_PATT_FREG; }
-       ;
-
-LRegTag
-       : K_LREG                        { $$ = GENSEL_PATT_LREG; }
-       ;
-
-LocalFlag
+DestFlag
        : /* empty */                   { $$ = 0; }
-       | '='                           { $$ = GENSEL_FLAG_DEST; }
+       | '='                           { $$ = 1; }
        ;
 
 RegFlag
        : /* empty */                   { $$ = 0; }
-       | '='                           { $$ = GENSEL_FLAG_DEST; }
-       | '*'                           { $$ = GENSEL_FLAG_CLOBBER; }
-       | '+'                           { $$ = GENSEL_FLAG_EARLY_CLOBBER; }
+       | '*'                           { $$ = GENSEL_VALUE_CLOBBER; }
+       | '+'                           { $$ = GENSEL_VALUE_EARLY_CLOBBER; }
        ;
 
 Literal

Index: jit/jit-reg-alloc.h
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-reg-alloc.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -b -r1.19 -r1.20
--- jit/jit-reg-alloc.h 14 Sep 2006 06:27:08 -0000      1.19
+++ jit/jit-reg-alloc.h 29 Dec 2006 23:16:15 -0000      1.20
@@ -22,6 +22,7 @@
 #define        _JIT_REG_ALLOC_H
 
 #include "jit-rules.h"
+#include "jit-reg-class.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -40,16 +41,14 @@
 /*
  * Flags for _jit_regs_init().
  */
-#define _JIT_REGS_CLOBBER_ALL          0x0001
-#define _JIT_REGS_TERNARY              0x0002
-#define _JIT_REGS_BRANCH               0x0004
-#define _JIT_REGS_COPY                 0x0008
-#define _JIT_REGS_STACK                        0x0010
-#define _JIT_REGS_X87_ARITH            0x0020
-#define _JIT_REGS_COMMUTATIVE          0x0040
-#define _JIT_REGS_REVERSIBLE           0x0080
-#define _JIT_REGS_FREE_DEST            0x0100
-#define _JIT_REGS_CLOBBER_STACK                0x0200
+#define _JIT_REGS_TERNARY              0x0001
+#define _JIT_REGS_BRANCH               0x0002
+#define _JIT_REGS_COPY                 0x0004
+#define _JIT_REGS_FREE_DEST            0x0008
+#define _JIT_REGS_COMMUTATIVE          0x0010
+#define _JIT_REGS_STACK                        0x0020
+#define _JIT_REGS_X87_ARITH            0x0040
+#define _JIT_REGS_REVERSIBLE           0X0080
 
 /*
  * Flags for _jit_regs_init_dest(), _jit_regs_init_value1(), and
@@ -74,14 +73,14 @@
        int             reg;
        int             other_reg;
        int             stack_reg;
-       jit_regused_t   regset;
+       _jit_regclass_t *regclass;
        unsigned        live : 1;
        unsigned        used : 1;
        unsigned        clobber : 1;
        unsigned        early_clobber : 1;
        unsigned        duplicate : 1;
        unsigned        thrash : 1;
-       unsigned        save : 1;
+       unsigned        store : 1;
        unsigned        load : 1;
        unsigned        copy : 1;
        unsigned        kill : 1;
@@ -94,7 +93,7 @@
 typedef struct
 {
        int             reg;
-       jit_regused_t   regset;
+       _jit_regclass_t *regclass;
 
 } _jit_scratch_t;
 
@@ -108,19 +107,23 @@
        int             num_scratch;
 
        unsigned        clobber_all : 1;
-       unsigned        clobber_stack : 1;
+
        unsigned        ternary : 1;
        unsigned        branch : 1;
        unsigned        copy : 1;
        unsigned        commutative : 1;
+       unsigned        free_dest : 1;
+
+#ifdef JIT_REG_STACK
        unsigned        on_stack : 1;
        unsigned        x87_arith : 1;
        unsigned        reversible : 1;
-       unsigned        free_dest : 1;
+       unsigned        clobber_stack : 1;
 
        unsigned        no_pop : 1;
        unsigned        reverse_dest : 1;
        unsigned        reverse_args : 1;
+#endif
 
        /* The input value index that is going to be overwritten
           by the destination value. For ordinary binary and unary
@@ -132,8 +135,10 @@
        jit_regused_t   assigned;
        jit_regused_t   clobber;
 
+#ifdef JIT_REG_STACK
        int             wanted_stack_count;
        int             loaded_stack_count;
+#endif
 
 } _jit_regs_t;
 
@@ -150,39 +155,44 @@
 int _jit_regs_load_value(jit_gencode_t gen, jit_value_t value, int destroy, 
int used_again);
 
 void _jit_regs_init(jit_gencode_t gen, _jit_regs_t *regs, int flags);
-void _jit_regs_init_dest(_jit_regs_t *regs, jit_insn_t insn, int flags);
-void _jit_regs_init_value1(_jit_regs_t *regs, jit_insn_t insn, int flags);
-void _jit_regs_init_value2(_jit_regs_t *regs, jit_insn_t insn, int flags);
+
+void _jit_regs_init_dest(_jit_regs_t *regs, jit_insn_t insn,
+                        int flags, _jit_regclass_t *regclass);
+void _jit_regs_init_value1(_jit_regs_t *regs, jit_insn_t insn,
+                          int flags, _jit_regclass_t *regclass);
+void _jit_regs_init_value2(_jit_regs_t *regs, jit_insn_t insn,
+                          int flags, _jit_regclass_t *regclass);
+void _jit_regs_add_scratch(_jit_regs_t *regs, _jit_regclass_t *regclass);
 
 void _jit_regs_set_dest(jit_gencode_t gen, _jit_regs_t *regs, int reg, int 
other_reg);
 void _jit_regs_set_value1(jit_gencode_t gen, _jit_regs_t *regs, int reg, int 
other_reg);
 void _jit_regs_set_value2(jit_gencode_t gen, _jit_regs_t *regs, int reg, int 
other_reg);
-void _jit_regs_add_scratch(jit_gencode_t gen, _jit_regs_t *regs, int reg);
-void _jit_regs_set_clobber(jit_gencode_t gen, _jit_regs_t *regs, int reg);
+void _jit_regs_set_scratch(jit_gencode_t gen, _jit_regs_t *regs, int index, 
int reg);
 
-void _jit_regs_set_dest_from(_jit_regs_t *regs, jit_regused_t regset);
-void _jit_regs_set_value1_from(_jit_regs_t *regs, jit_regused_t regset);
-void _jit_regs_set_value2_from(_jit_regs_t *regs, jit_regused_t regset);
-void _jit_regs_add_scratch_from(_jit_regs_t *regs, jit_regused_t regset);
+void _jit_regs_clobber(_jit_regs_t *regs, int reg);
+void _jit_regs_clobber_class(jit_gencode_t gen, _jit_regs_t *regs, 
_jit_regclass_t *regclass);
+void _jit_regs_clobber_all(jit_gencode_t gen, _jit_regs_t *regs);
 
 int _jit_regs_assign(jit_gencode_t gen, _jit_regs_t *regs);
 int _jit_regs_gen(jit_gencode_t gen, _jit_regs_t *regs);
+#ifdef JIT_REG_STACK
 int _jit_regs_select(_jit_regs_t *regs);
+#endif
 void _jit_regs_commit(jit_gencode_t gen, _jit_regs_t *regs);
 void _jit_regs_abort(jit_gencode_t gen, _jit_regs_t *regs);
 
+int _jit_regs_get_dest(_jit_regs_t *regs);
+int _jit_regs_get_value1(_jit_regs_t *regs);
+int _jit_regs_get_value2(_jit_regs_t *regs);
+int _jit_regs_get_dest_other(_jit_regs_t *regs);
+int _jit_regs_get_value1_other(_jit_regs_t *regs);
+int _jit_regs_get_value2_other(_jit_regs_t *regs);
+int _jit_regs_get_scratch(_jit_regs_t *regs, int index);
+
 unsigned char *_jit_regs_inst_ptr(jit_gencode_t gen, int space);
 unsigned char *_jit_regs_begin(jit_gencode_t gen, _jit_regs_t *regs, int 
space);
 void _jit_regs_end(jit_gencode_t gen, _jit_regs_t *regs, unsigned char *inst);
 
-int _jit_regs_dest(_jit_regs_t *regs);
-int _jit_regs_value1(_jit_regs_t *regs);
-int _jit_regs_value2(_jit_regs_t *regs);
-int _jit_regs_dest_other(_jit_regs_t *regs);
-int _jit_regs_value1_other(_jit_regs_t *regs);
-int _jit_regs_value2_other(_jit_regs_t *regs);
-int _jit_regs_scratch(_jit_regs_t *regs, int index);
-
 #ifdef __cplusplus
 };
 #endif

Index: jit/jit-reg-alloc.c
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-reg-alloc.c,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -b -r1.47 -r1.48
--- jit/jit-reg-alloc.c 28 Nov 2006 20:26:42 -0000      1.47
+++ jit/jit-reg-alloc.c 29 Dec 2006 23:16:15 -0000      1.48
@@ -62,11 +62,11 @@
 
 #define COST_COPY              4
 #define COST_SPILL_DIRTY       16
-#define COST_SPILL_DIRTY_GLOBAL        2
+#define COST_SPILL_DIRTY_GLOBAL        4
 #define COST_SPILL_CLEAN       1
 #define COST_SPILL_CLEAN_GLOBAL        1
-#define COST_GLOBAL_BIAS       1
-#define COST_THRASH            32
+#define COST_GLOBAL_BIAS       2
+#define COST_THRASH            100
 #define COST_CLOBBER_GLOBAL    1000
 
 #ifdef JIT_BACKEND_X86
@@ -398,10 +398,16 @@
        if(regs->ternary || !regs->descs[0].value)
        {
                /* this is either a ternary or binary or unary note */
-               if(IS_STACK_REG(reg) || regs->descs[index].clobber)
+               if(regs->descs[index].clobber)
                {
                        flags = CLOBBER_INPUT_VALUE;
                }
+#ifdef JIT_REG_STACK
+               else if(IS_STACK_REG(reg) && !regs->no_pop)
+               {
+                       flags = CLOBBER_INPUT_VALUE;
+               }
+#endif
                else
                {
                        flags = CLOBBER_NONE;
@@ -439,12 +445,14 @@
        {
                flags = CLOBBER_NONE;
        }
-       else if(regs->on_stack && !regs->no_pop)
+#ifdef JIT_REG_STACK
+       else if(IS_STACK_REG(reg) && !regs->no_pop)
        {
                /* this is a binary or unary stack op -- the input value
                   is either popped or overwritten by the output */
                flags = CLOBBER_INPUT_VALUE;
        }
+#endif
        else if(reg == regs->descs[0].reg
                || reg == regs->descs[0].other_reg
                || other_reg == regs->descs[0].reg)
@@ -504,36 +512,17 @@
 }
 
 /*
- * Initialize value descriptor.
- */
-static void
-init_regdesc(_jit_regs_t *regs, int index)
-{
-       _jit_regdesc_t *desc;
-
-       desc = &regs->descs[index];
-       desc->value = 0;
-       desc->reg = -1;
-       desc->other_reg = -1;
-       desc->stack_reg = -1;
-       desc->regset = jit_regused_init_used;
-       desc->live = 0;
-       desc->used = 0;
-       desc->clobber = 0;
-       desc->early_clobber = 0;
-       desc->duplicate = 0;
-       desc->thrash = 0;
-       desc->save = 0;
-       desc->load = 0;
-       desc->copy = 0;
-       desc->kill = 0;
-}
-
-/*
  * Set value information.
  */
 static void
-set_regdesc_value(_jit_regs_t *regs, int index, jit_value_t value, int flags, 
int live, int used)
+set_regdesc_value(
+       _jit_regs_t *regs,
+       int index,
+       jit_value_t value,
+       int flags,
+       _jit_regclass_t *regclass,
+       int live,
+       int used)
 {
        _jit_regdesc_t *desc;
 
@@ -551,6 +540,7 @@
                        desc->clobber = 1;
                }
        }
+       desc->regclass = regclass;
        desc->live = live;
        desc->used = used;
 }
@@ -595,6 +585,7 @@
        _jit_regdesc_t *desc;
        int reg, other_reg;
        int clobber, clobber_input;
+       int is_input, is_live_input, is_used_input;
 
 #ifdef JIT_REG_DEBUG
        printf("set_regdesc_flags(index = %d)\n", index);
@@ -606,61 +597,64 @@
                return 1;
        }
 
-       /* Find the register the value is already in (if any). */
-       if(desc->value->in_register)
+       /* See if the value clobbers the register it is assigned to. */
+       clobber = clobbers_register(gen, regs, index, desc->reg, 
desc->other_reg);
+
+       /* See if this is an input value and whether it is alive. */
+       if(regs->ternary)
        {
-               reg = desc->value->reg;
-               if(gen->contents[reg].is_long_start)
+               is_input = 1;
+               is_live_input = desc->live;
+               is_used_input = desc->used;
+       }
+       else if(index > 0)
                {
-                       other_reg = OTHER_REG(reg);
+               is_input = 1;
+               if(regs->descs[0].value == desc->value)
+               {
+                       is_live_input = is_used_input = 0;
                }
                else
                {
-                       other_reg = -1;
+                       is_live_input = desc->live;
+                       is_used_input = desc->used;
                }
        }
        else
        {
-               reg = -1;
-               other_reg = -1;
+               is_input = is_live_input = is_used_input = 0;
        }
 
-       /* See if the value clobbers the register it is assigned to. */
-       clobber = clobbers_register(gen, regs, index, desc->reg, 
desc->other_reg);
-       if((clobber & CLOBBER_INPUT_VALUE) != 0)
+       if(is_input)
        {
-               clobber_input = 1;
-       }
-       else if(jit_reg_is_used(regs->clobber, desc->reg))
+               /* Find the register the value is already in (if any). */
+               if(desc->value->in_register)
        {
-               clobber_input = 1;
-       }
-       else if(desc->other_reg >= 0 && jit_reg_is_used(regs->clobber, 
desc->other_reg))
+                       reg = desc->value->reg;
+                       if(gen->contents[reg].is_long_start)
        {
-               clobber_input = 1;
+                               other_reg = OTHER_REG(reg);
        }
        else
        {
-               clobber_input = 0;
+                               other_reg = -1;
        }
-       if((clobber & CLOBBER_REG) != 0)
-       {
-               jit_reg_set_used(regs->clobber, desc->reg);
        }
-       if((clobber & CLOBBER_OTHER_REG) != 0)
+               else
        {
-               jit_reg_set_used(regs->clobber, desc->other_reg);
+                       reg = -1;
+                       other_reg = -1;
        }
 
-       /* See if the input value is thrashed by other inputs or clobbered
-          by the output. The allocator tries to avoid thrashing so it may
-          only take place if the register is assigned explicitly. For x87
-          registers the problem of thrashing may be best solved with fxch
-          but as the stack registers are never assigned explicitely there
-          is no such problem for them at all. */
-       if(reg >= 0 && (index > 0 || regs->ternary))
+               /* See if the input value is thrashed by other inputs. The 
allocator
+                  tries to avoid thrashing so it may only take place if the 
register
+                  is assigned explicitly. For x87 registers the problem of 
thrashing
+                  may be best solved with fxch but as the stack registers are 
never
+                  assigned explicitely there is no such problem for them at 
all. */
+               if(reg >= 0)
        {
-               if(index != 0 && regs->ternary && !are_values_equal(desc, 
&regs->descs[0]))
+                       if(index != 0 && regs->ternary
+                          && !are_values_equal(desc, &regs->descs[0]))
                {
                        if(reg == regs->descs[0].reg
                           || reg == regs->descs[0].other_reg
@@ -698,31 +692,41 @@
                {
                        reg = -1;
                        other_reg = -1;
-                       desc->save = 1;
+                               desc->store = 1;
                }
        }
 
-       if(index > 0 || regs->ternary)
-       {
                /* See if the value needs to be loaded or copied or none. */
-               if(desc->value->has_global_register)
+               if(reg != desc->reg)
                {
-                       if(desc->value->global_reg != desc->reg
-                          && !(reg >= 0 && reg == desc->reg))
+                       if(desc->value->has_global_register)
                        {
-                               desc->copy = 1;
+                               desc->copy = (desc->value->global_reg != 
desc->reg);
                        }
+                       else if(reg < 0)
+                       {
+                               desc->load = 1;
                }
                else
                {
-                       if(reg < 0)
+                               desc->copy = 1;
+                       }
+               }
+
+               /* See if the input value is destroyed by the instruction. */
+               if(desc->copy)
                        {
-                               desc->load = 1;
+                       clobber_input = 0;
                        }
-                       else if(reg != desc->reg)
+               else if(jit_reg_is_used(regs->clobber, desc->reg)
+                       || (desc->other_reg >= 0
+                           && jit_reg_is_used(regs->clobber, desc->other_reg)))
                        {
-                               desc->copy = 1;
+                       clobber_input = 1;
                        }
+               else
+               {
+                       clobber_input = ((clobber & CLOBBER_INPUT_VALUE) != 0);
                }
 
                /* See if the input value needs to be saved before the
@@ -732,32 +736,28 @@
                {
                        desc->kill = 1;
                }
-               else if(reg >= 0)
+               else if(clobber_input)
                {
-                       if(desc->used)
-                       {
-                               if(!desc->copy && clobber_input)
-                               {
-                                       desc->save = 1;
+                       desc->store = (is_live_input || is_used_input);
                                        desc->kill = 1;
                                }
-                       }
-                       else
+               else if(!is_used_input)
                        {
-                               if(desc->live)
-                               {
-                                       desc->save = 1;
-                               }
+                       desc->store = is_live_input;
                                desc->kill = 1;
                        }
-               }
-               else if(desc->load)
+
+#ifdef JIT_REG_STACK
+               /* Count stack registers. */
+               if(IS_STACK_REG(desc->reg))
                {
-                       if(!desc->used || clobber_input)
+                       ++(regs->wanted_stack_count);
+                       if(!desc->load && !desc->copy)
                        {
-                               desc->kill = 1;
+                               ++(regs->loaded_stack_count);
                        }
                }
+#endif
        }
 
        /* See if the value clobbers a global register. In this case the global
@@ -771,16 +771,14 @@
                desc->kill = 1;
        }
 
-       if(IS_STACK_REG(desc->reg))
-       {
-               if(index > 0 || regs->ternary)
-               {
-                       ++(regs->wanted_stack_count);
-                       if(!(desc->load || desc->copy))
+       /* Set clobber flags (this indicates registers to be spilled). */
+       if((clobber & CLOBBER_REG) != 0)
                        {
-                               ++(regs->loaded_stack_count);
-                       }
+               jit_reg_set_used(regs->clobber, desc->reg);
                }
+       if((clobber & CLOBBER_OTHER_REG) != 0)
+       {
+               jit_reg_set_used(regs->clobber, desc->other_reg);
        }
 
 #ifdef JIT_REG_DEBUG
@@ -801,7 +799,7 @@
        printf("early_clobber = %d\n", desc->early_clobber);
        printf("duplicate = %d\n", desc->duplicate);
        printf("thrash = %d\n", desc->thrash);
-       printf("save = %d\n", desc->save);
+       printf("store = %d\n", desc->store);
        printf("load = %d\n", desc->load);
        printf("copy = %d\n", desc->copy);
        printf("kill = %d\n", desc->kill);
@@ -983,31 +981,25 @@
 static int
 choose_scratch_register(jit_gencode_t gen, _jit_regs_t *regs, int index)
 {
-       int reg, type;
+       _jit_regclass_t *regclass;
+       int reg_index, reg;
        int use_cost;
        int suitable_reg;
        int suitable_cost;
        int suitable_age;
 
-       type = JIT_REG_WORD;
+       regclass = regs->scratch[index].regclass;
 
        suitable_reg = -1;
        suitable_cost = COST_TOO_MUCH;
        suitable_age = -1;
-       for(reg = 0; reg < JIT_NUM_REGS; reg++)
-       {
-               if((_jit_reg_info[reg].flags & type) == 0)
+       for(reg_index = 0; reg_index < regclass->num_regs; reg_index++)
                {
-                       continue;
-               }
+               reg = regclass->regs[reg_index];
                if(jit_reg_is_used(regs->assigned, reg))
                {
                        continue;
                }
-               if(!jit_reg_is_used(regs->scratch[index].regset, reg))
-               {
-                       continue;
-               }
 
 #if ALLOW_CLOBBER_GLOBAL
                if(jit_reg_is_used(gen->permanent, reg))
@@ -1067,38 +1059,28 @@
 static int
 choose_output_register(jit_gencode_t gen, _jit_regs_t *regs)
 {
-       int type, need_pair;
-       int reg, other_reg;
+       _jit_regclass_t *regclass;
+       int need_pair;
+       int reg_index, reg, other_reg;
        int use_cost;
        int suitable_reg, suitable_other_reg;
        int suitable_cost;
        int suitable_age;
 
+       regclass = regs->descs[0].regclass;
        need_pair = _jit_regs_needs_long_pair(regs->descs[0].value->type);
-       type = get_register_type(regs->descs[0].value, need_pair);
-       if(!type)
-       {
-               return 0;
-       }
 
        suitable_reg = -1;
        suitable_other_reg = -1;
        suitable_cost = COST_TOO_MUCH;
        suitable_age = -1;
-       for(reg = 0; reg < JIT_NUM_REGS; reg++)
-       {
-               if((_jit_reg_info[reg].flags & type) == 0)
+       for(reg_index = 0; reg_index < regclass->num_regs; reg_index++)
                {
-                       continue;
-               }
+               reg = regclass->regs[reg_index];
                if(jit_reg_is_used(gen->inhibit, reg))
                {
                        continue;
                }
-               if(!jit_reg_is_used(regs->descs[0].regset, reg))
-               {
-                       continue;
-               }
 
                if(need_pair)
                {
@@ -1174,10 +1156,16 @@
                                && regs->descs[2].value->in_register
                                && regs->descs[2].value->reg == reg)
                        {
-                               if(regs->commutative || regs->x87_arith)
+                               if(regs->commutative)
+                               {
+                                       use_cost = 0;
+                               }
+#ifdef JIT_REG_STACK
+                               else if(regs->x87_arith)
                                {
                                        use_cost = 0;
                                }
+#endif
                                else
                                {
                                        use_cost = COST_THRASH;
@@ -1227,26 +1215,21 @@
 choose_input_order(jit_gencode_t gen, _jit_regs_t *regs)
 {
        _jit_regdesc_t temp_desc;
-       int keep1, keep2;
-
-       if(regs->ternary || regs->free_dest || !regs->descs[0].value)
-       {
-               regs->dest_input_index = 0;
-               return;
-       }
 
        if(regs->descs[2].value
           && regs->descs[2].value->in_register
           && regs->descs[2].value->reg == regs->descs[0].reg
           && regs->descs[2].value != regs->descs[1].value)
        {
-               if(regs->on_stack && regs->x87_arith)
+#ifdef JIT_REG_STACK
+               if(regs->x87_arith)
                {
                        regs->no_pop = 1;
                        regs->reverse_dest = 1;
                        regs->dest_input_index = 2;
                }
                else
+#endif
                {
                        if(regs->commutative)
                        {
@@ -1266,11 +1249,14 @@
                regs->dest_input_index = 0;
        }
 
+#ifdef JIT_REG_STACK
        /* Choose between pop and no-pop instructions. */
-       if(regs->on_stack && regs->x87_arith && !regs->no_pop
+       if(!regs->no_pop && regs->x87_arith
           && !regs->clobber_all && !regs->clobber_stack
           && regs->descs[1].value && regs->descs[2].value)
        {
+               int keep1, keep2;
+
                /* Determine if we might want to keep either of input values
                   in registers after the instruction completion. */
                if(regs->descs[1].value->in_register)
@@ -1296,15 +1282,17 @@
 
                regs->no_pop = (keep1 || keep2);
        }
+#endif
 }
 
 static int
 choose_input_register(jit_gencode_t gen, _jit_regs_t *regs, int index)
 {
+       _jit_regclass_t *regclass;
        _jit_regdesc_t *desc;
        _jit_regdesc_t *desc2;
-       int type, need_pair;
-       int reg, other_reg;
+       int need_pair;
+       int reg_index, reg, other_reg;
        int use_cost;
        int suitable_reg, suitable_other_reg;
        int suitable_cost;
@@ -1317,12 +1305,8 @@
                return 0;
        }
 
+       regclass = regs->descs[index].regclass;
        need_pair = _jit_regs_needs_long_pair(desc->value->type);
-       type = get_register_type(desc->value, need_pair);
-       if(!type)
-       {
-               return 0;
-       }
 
        if(index == regs->dest_input_index)
        {
@@ -1337,20 +1321,13 @@
        suitable_other_reg = -1;
        suitable_cost = COST_TOO_MUCH;
        suitable_age = -1;
-       for(reg = 0; reg < JIT_NUM_REGS; reg++)
-       {
-               if((_jit_reg_info[reg].flags & type) == 0)
+       for(reg_index = 0; reg_index < regclass->num_regs; reg_index++)
                {
-                       continue;
-               }
+               reg = regclass->regs[reg_index];
                if(jit_reg_is_used(regs->assigned, reg))
                {
                        continue;
                }
-               if(!jit_reg_is_used(desc->regset, reg))
-               {
-                       continue;
-               }
 
                if(need_pair)
                {
@@ -1463,9 +1440,10 @@
 static void
 check_duplicate_value(_jit_regs_t *regs, _jit_regdesc_t *desc1, _jit_regdesc_t 
*desc2)
 {
-       if((!regs->on_stack || regs->x87_arith)
-          && are_values_equal(desc1, desc2)
-          && desc1->reg >= 0 && desc2->reg < 0
+       if(desc2->reg < 0 && desc1->reg >= 0 && are_values_equal(desc1, desc2)
+#ifdef JIT_REG_STACK
+          && (!IS_STACK_REG(desc1->reg) || regs->x87_arith)
+#endif
           && !desc1->early_clobber && !desc2->early_clobber)
        {
                desc2->reg = desc1->reg;
@@ -1501,7 +1479,7 @@
                        index = regs->dest_input_index;
                }
 
-               if(regs->x87_arith && desc->value->in_register && !desc->copy)
+               if(desc->value->in_register && !desc->copy && regs->x87_arith)
                {
                        desc->reg = desc->value->reg;
                }
@@ -1523,7 +1501,8 @@
        int top_index;
 
        /* Choose instruction that results into fewer exchanges. */
-       if(regs->on_stack && regs->no_pop && (regs->commutative || 
regs->reversible))
+       if(regs->wanted_stack_count > 1 && regs->no_pop
+          && (regs->commutative || regs->reversible))
        {
                desc1 = &regs->descs[1];
                desc2 = &regs->descs[2];
@@ -1806,7 +1785,7 @@
 #ifdef JIT_REG_DEBUG
        printf("free_value(value = ");
        jit_dump_value(stdout, jit_value_get_function(value), value, 0);
-       printf(", reg = %d, other_reg = %d)\n", reg, other_reg);
+       printf(", reg = %d, other_reg = %d, temp = %d)\n", reg, other_reg, 
temp);
 #endif
 
        /* Never free global registers. */
@@ -1847,7 +1826,7 @@
 #ifdef JIT_REG_DEBUG
        printf("save_value(value = ");
        jit_dump_value(stdout, jit_value_get_function(value), value, 0);
-       printf(", reg = %d, other_reg = %d)\n", reg, other_reg);
+       printf(", reg = %d, other_reg = %d, free=%d)\n", reg, other_reg, free);
 #endif
        /* First take care of values that reside in global registers. */
        if(value->has_global_register)
@@ -2066,7 +2045,7 @@
 #endif
 
        desc = &regs->descs[index];
-       if(!(desc->value && desc->value->in_register && desc->save))
+       if(!desc->value || !desc->value->in_register || !desc->store)
        {
                return;
        }
@@ -2291,13 +2270,16 @@
 }
 
 static void
-commit_input_value(jit_gencode_t gen, _jit_regs_t *regs, int index)
+commit_input_value(jit_gencode_t gen, _jit_regs_t *regs, int index, int 
go_down_stack)
 {
        _jit_regdesc_t *desc;
        int reg, other_reg;
+#ifdef JIT_REG_STACK
+       int is_down_stack = 0;
+#endif
 
 #ifdef JIT_REG_DEBUG
-       printf("commit_input_value(%d)\n", index);
+       printf("commit_input_value(%d, %d)\n", index, go_down_stack);
 #endif
 
        desc = &regs->descs[index];
@@ -2309,19 +2291,34 @@
        if(desc->copy)
        {
 #ifdef JIT_REG_STACK
-               if(IS_STACK_REG(desc->reg) && !regs->copy)
+               if(IS_STACK_REG(desc->reg))
+               {
+                       if(!go_down_stack)
+                       {
+                               if(1/*!regs->copy*/)
                {
                        --(gen->reg_stack_top);
                }
+                               gen->contents[desc->reg].used_for_temp = 0;
+                       }
+                       is_down_stack = 1;
+               }
+               else
 #endif
+               {
                gen->contents[desc->reg].used_for_temp = 0;
                if(desc->other_reg >= 0)
                {
                        gen->contents[desc->other_reg].used_for_temp = 0;
                }
        }
+       }
 
+#ifdef JIT_REG_STACK
+       if(desc->kill && desc->value->in_register && is_down_stack == 
go_down_stack)
+#else
        if(desc->kill && desc->value->in_register)
+#endif
        {
                reg = desc->value->reg;
                if(gen->contents[reg].is_long_start)
@@ -2332,12 +2329,21 @@
                {
                        other_reg = -1;
                }
-               unbind_value(gen, desc->value, reg, other_reg);
 #ifdef JIT_REG_STACK
-               if(IS_STACK_REG(reg) && !regs->copy)
+               if(is_down_stack)
+               {
+                       free_value(gen, desc->value, reg, other_reg, 0);
+               }
+               else
+               {
+                       unbind_value(gen, desc->value, reg, other_reg);
+                       if(IS_STACK_REG(reg) /*&& !regs->copy*/)
                {
                        --(gen->reg_stack_top);
                }
+               }
+#else
+               unbind_value(gen, desc->value, reg, other_reg);
 #endif
        }
 
@@ -2369,7 +2375,7 @@
        }
 
 #ifdef JIT_REG_STACK
-       if(IS_STACK_REG(desc->reg) && !regs->copy)
+       if(IS_STACK_REG(desc->reg) /*&& !regs->copy*/)
        {
                ++(gen->reg_stack_top);
        }
@@ -2951,91 +2957,80 @@
 {
        int index;
 
-       regs->clobber_all = (flags & _JIT_REGS_CLOBBER_ALL) != 0;
-       regs->clobber_stack = (flags & _JIT_REGS_CLOBBER_STACK) != 0;
+       jit_memset(regs, 0, sizeof(_jit_regs_t));
+
        regs->ternary = (flags & _JIT_REGS_TERNARY) != 0;
        regs->branch = (flags & _JIT_REGS_BRANCH) != 0;
        regs->copy = (flags & _JIT_REGS_COPY) != 0;
        regs->commutative = (flags & _JIT_REGS_COMMUTATIVE) != 0;
+       regs->free_dest = (flags & _JIT_REGS_FREE_DEST) != 0;
+#ifdef JIT_REG_STACK
        regs->on_stack = (flags & _JIT_REGS_STACK) != 0;
        regs->x87_arith = (flags & _JIT_REGS_X87_ARITH) != 0;
        regs->reversible = (flags & _JIT_REGS_REVERSIBLE) != 0;
-       regs->free_dest = (flags & _JIT_REGS_FREE_DEST) != 0;
-
-       regs->no_pop = 0;
-       regs->reverse_dest = 0;
-       regs->reverse_args = 0;
+       regs->no_pop = (regs->on_stack & regs->copy) != 0;
+#endif
 
        for(index = 0; index < _JIT_REGS_VALUE_MAX; index++)
        {
-               init_regdesc(regs, index);
+               regs->descs[index].reg = -1;
+               regs->descs[index].other_reg = -1;
+               regs->descs[index].stack_reg = -1;
        }
        for(index = 0; index < _JIT_REGS_SCRATCH_MAX; index++)
        {
                regs->scratch[index].reg = -1;
-               regs->scratch[index].regset = jit_regused_init_used;
        }
-       regs->num_scratch = 0;
-       regs->dest_input_index = 0;
 
-       /* Set clobber flags. */
        regs->clobber = jit_regused_init;
-       if(regs->clobber_all || regs->clobber_stack)
-       {
-               for(index = 0; index < JIT_NUM_REGS; index++)
-               {
-                       if((_jit_reg_info[index].flags & JIT_REG_FIXED)
-                          || jit_reg_is_used(gen->permanent, index))
-                       {
-                               continue;
-                       }
-                       if(regs->clobber_all || IS_STACK_REG(index))
-                       {
-                               jit_reg_set_used(regs->clobber, index);
-                       }
-               }
-       }
-
        regs->assigned = gen->inhibit;
-
-       regs->wanted_stack_count = 0;
-       regs->loaded_stack_count = 0;
 }
 
 void
-_jit_regs_init_dest(_jit_regs_t *regs, jit_insn_t insn, int flags)
+_jit_regs_init_dest(_jit_regs_t *regs, jit_insn_t insn, int flags, 
_jit_regclass_t *regclass)
 {
        if((insn->flags & JIT_INSN_DEST_OTHER_FLAGS) == 0)
        {
-               set_regdesc_value(regs, 0, insn->dest, flags,
+               set_regdesc_value(regs, 0, insn->dest, flags, regclass,
                                  (insn->flags & JIT_INSN_DEST_LIVE) != 0,
                                  (insn->flags & JIT_INSN_DEST_NEXT_USE) != 0);
        }
 }
 
 void
-_jit_regs_init_value1(_jit_regs_t *regs, jit_insn_t insn, int flags)
+_jit_regs_init_value1(_jit_regs_t *regs, jit_insn_t insn, int flags, 
_jit_regclass_t *regclass)
 {
        if((insn->flags & JIT_INSN_VALUE1_OTHER_FLAGS) == 0)
        {
-               set_regdesc_value(regs, 1, insn->value1, flags,
+               set_regdesc_value(regs, 1, insn->value1, flags, regclass,
                                  (insn->flags & JIT_INSN_VALUE1_LIVE) != 0,
                                  (insn->flags & JIT_INSN_VALUE1_NEXT_USE) != 
0);
        }
 }
 
 void
-_jit_regs_init_value2(_jit_regs_t *regs, jit_insn_t insn, int flags)
+_jit_regs_init_value2(_jit_regs_t *regs, jit_insn_t insn, int flags, 
_jit_regclass_t *regclass)
 {
        if((insn->flags & JIT_INSN_VALUE2_OTHER_FLAGS) == 0)
        {
-               set_regdesc_value(regs, 2, insn->value2, flags,
+               set_regdesc_value(regs, 2, insn->value2, flags, regclass,
                                  (insn->flags & JIT_INSN_VALUE2_LIVE) != 0,
                                  (insn->flags & JIT_INSN_VALUE2_NEXT_USE) != 
0);
        }
 }
 
 void
+_jit_regs_add_scratch(_jit_regs_t *regs, _jit_regclass_t *regclass)
+{
+       if(regs->num_scratch < _JIT_REGS_SCRATCH_MAX)
+       {
+               regs->scratch[regs->num_scratch].reg = -1;
+               regs->scratch[regs->num_scratch].regclass = regclass;
+               ++regs->num_scratch;
+       }
+}
+
+void
 _jit_regs_set_dest(jit_gencode_t gen, _jit_regs_t *regs, int reg, int 
other_reg)
 {
        if(reg >= 0 && !IS_STACK_REG(reg))
@@ -3063,95 +3058,52 @@
 }
 
 void
-_jit_regs_add_scratch(jit_gencode_t gen, _jit_regs_t *regs, int reg)
+_jit_regs_set_scratch(jit_gencode_t gen, _jit_regs_t *regs, int index, int reg)
 {
-       if(regs->num_scratch < _JIT_REGS_SCRATCH_MAX)
+       if(index < regs->num_scratch && index >= 0 && reg >= 0 && 
!IS_STACK_REG(reg))
        {
-               if(reg < 0)
-               {
-                       ++regs->num_scratch;
-               }
-               else if(!IS_STACK_REG(reg))
-               {
-                       set_scratch_register(gen, regs, regs->num_scratch++, 
reg);
-               }
-       }
-}
-
-void
-_jit_regs_set_clobber(jit_gencode_t gen, _jit_regs_t *regs, int reg)
-{
-       if(reg >= 0)
-       {
-               jit_reg_set_used(regs->clobber, reg);
-       }
-}
-
-void
-_jit_regs_set_dest_from(_jit_regs_t *regs, jit_regused_t regset)
-{
-       regs->descs[0].regset = regset;
-}
-
-void
-_jit_regs_set_value1_from(_jit_regs_t *regs, jit_regused_t regset)
-{
-       regs->descs[1].regset = regset;
-}
-
-void
-_jit_regs_set_value2_from(_jit_regs_t *regs, jit_regused_t regset)
-{
-       regs->descs[2].regset = regset;
-}
-
-void
-_jit_regs_add_scratch_from(_jit_regs_t *regs, jit_regused_t regset)
-{
-       if(regs->num_scratch < _JIT_REGS_SCRATCH_MAX)
-       {
-               regs->scratch[regs->num_scratch++].regset = regset;
+               set_scratch_register(gen, regs, index, reg);
        }
 }
 
 int
-_jit_regs_dest(_jit_regs_t *regs)
+_jit_regs_get_dest(_jit_regs_t *regs)
 {
        return regs->descs[0].reg;
 }
 
 int
-_jit_regs_value1(_jit_regs_t *regs)
+_jit_regs_get_value1(_jit_regs_t *regs)
 {
        return regs->descs[1].reg;
 }
 
 int
-_jit_regs_value2(_jit_regs_t *regs)
+_jit_regs_get_value2(_jit_regs_t *regs)
 {
        return regs->descs[2].reg;
 }
 
 int
-_jit_regs_dest_other(_jit_regs_t *regs)
+_jit_regs_get_dest_other(_jit_regs_t *regs)
 {
        return regs->descs[0].other_reg;
 }
 
 int
-_jit_regs_value1_other(_jit_regs_t *regs)
+_jit_regs_get_value1_other(_jit_regs_t *regs)
 {
        return regs->descs[1].other_reg;
 }
 
 int
-_jit_regs_value2_other(_jit_regs_t *regs)
+_jit_regs_get_value2_other(_jit_regs_t *regs)
 {
        return regs->descs[2].other_reg;
 }
 
 int
-_jit_regs_scratch(_jit_regs_t *regs, int index)
+_jit_regs_get_scratch(_jit_regs_t *regs, int index)
 {
        if(index < regs->num_scratch && index >= 0)
        {
@@ -3160,6 +3112,58 @@
        return -1;
 }
 
+void
+_jit_regs_clobber(_jit_regs_t *regs, int reg)
+{
+       if(reg >= 0)
+       {
+               jit_reg_set_used(regs->clobber, reg);
+       }
+}
+
+void
+_jit_regs_clobber_class(jit_gencode_t gen, _jit_regs_t *regs, _jit_regclass_t 
*regclass)
+{
+       int index;
+
+#ifdef JIT_REG_STACK
+       if((regclass->flags & JIT_REG_IN_STACK) != 0)
+       {
+               regs->clobber_stack = 1;
+       }
+#endif
+
+       for(index = 0; index < regclass->num_regs; index++)
+       {
+               if(jit_reg_is_used(gen->permanent, index))
+               {
+                       continue;
+               }
+               jit_reg_set_used(regs->clobber, regclass->regs[index]);
+       }
+}
+
+void
+_jit_regs_clobber_all(jit_gencode_t gen, _jit_regs_t *regs)
+{
+       int index;
+
+       regs->clobber_all = 1;
+
+       for(index = 0; index < JIT_NUM_REGS; index++)
+       {
+               if((_jit_reg_info[index].flags & JIT_REG_FIXED) != 0)
+               {
+                       continue;
+               }
+               if(jit_reg_is_used(gen->permanent, index))
+               {
+                       continue;
+               }
+               jit_reg_set_used(regs->clobber, index);
+       }
+}
+
 int
 _jit_regs_assign(jit_gencode_t gen, _jit_regs_t *regs)
 {
@@ -3172,8 +3176,9 @@
        /* For binary or unary ops with explicitely assigned registers
           the output always goes to the same register as the first input
           value unless this is a three-address instruction. */
-       if(!(regs->ternary || regs->free_dest)
-          && regs->descs[0].value && regs->descs[1].value)
+       if(!regs->ternary && !regs->free_dest
+          && regs->descs[0].value
+          && regs->descs[1].value)
        {
                if(regs->descs[0].reg >= 0)
                {
@@ -3412,6 +3417,7 @@
        return 1;
 }
 
+#ifdef JIT_REG_STACK
 int
 _jit_regs_select(_jit_regs_t *regs)
 {
@@ -3433,6 +3439,7 @@
 
        return flags;
 }
+#endif
 
 void
 _jit_regs_commit(jit_gencode_t gen, _jit_regs_t *regs)
@@ -3444,26 +3451,74 @@
 #endif
 
 #ifdef JIT_REG_STACK
+       if(regs->wanted_stack_count > 0)
+       {
+               int reg1, reg2;
+
+               /* The stack registers has to be freed from the top down. It is
+                  assumed that only binary instructions may have more than one
+                  stack register. The unary instruction may not do that for
+                  obvious reasons. The practical observation is that no ternary
+                  instruction in libjit does that as well. */
        if(regs->reverse_args)
        {
-               commit_input_value(gen, regs, 1);
-               commit_input_value(gen, regs, 2);
+                       commit_input_value(gen, regs, 1, 0);
+                       commit_input_value(gen, regs, 2, 0);
        }
        else
-#endif
        {
-               commit_input_value(gen, regs, 2);
-               commit_input_value(gen, regs, 1);
+                       commit_input_value(gen, regs, 2, 0);
+                       commit_input_value(gen, regs, 1, 0);
        }
        if(regs->ternary)
        {
-               commit_input_value(gen, regs, 0);
+                       commit_input_value(gen, regs, 0, 0);
        }
        else
        {
                commit_output_value(gen, regs);
        }
 
+               /* If the allocator makes a copy of a value that was already on
+                  the stack we might need to free the original register as 
well.
+                  In general, the allocator makes a copy if the value is going
+                  to be destroyed by the instruction while it is still used
+                  (according to the liveness analysis). But the original value
+                  needs to be freed only if it is no longer used. So this extra
+                  code seems useless. But there were cases when the allocator
+                  miscalculated the cost of spilling and made a copy when it
+                  was not needed. So this code serves as a precaution against
+                  such problematic cases. */
+               reg1 = ((regs->descs[1].value && 
regs->descs[1].value->in_register)
+                       ? regs->descs[1].value->reg : -1);
+               reg2 = ((regs->descs[2].value && 
regs->descs[2].value->in_register)
+                       ? regs->descs[2].value->reg : -1);
+               if(reg1 > reg2)
+               {
+                       commit_input_value(gen, regs, 1, 1);
+                       commit_input_value(gen, regs, 2, 1);
+               }
+               else
+               {
+                       commit_input_value(gen, regs, 2, 1);
+                       commit_input_value(gen, regs, 1, 1);
+               }
+       }
+       else
+#endif
+       {
+               commit_input_value(gen, regs, 2, 0);
+               commit_input_value(gen, regs, 1, 0);
+               if(regs->ternary)
+               {
+                       commit_input_value(gen, regs, 0, 0);
+               }
+               else
+               {
+                       commit_output_value(gen, regs);
+               }
+       }
+
        /* Load clobbered global registers. */
        for(reg = JIT_NUM_REGS - 1; reg >= 0; reg--)
        {

Index: jit/jit-rules-alpha.ins
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-rules-alpha.ins,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- jit/jit-rules-alpha.ins     20 Aug 2006 15:47:54 -0000      1.5
+++ jit/jit-rules-alpha.ins     29 Dec 2006 23:16:15 -0000      1.6
@@ -20,29 +20,32 @@
 
 %inst_type alpha_inst
 
+%regclass reg alpha_reg
+%regclass lreg alpha_reg
+
 /*
  * Conversion opcodes.
  */
 
-JIT_OP_TRUNC_SBYTE: unary
+JIT_OP_TRUNC_SBYTE:
        [reg] -> {
                alpha_slli(inst,$1,56,$1);
                alpha_srai(inst,$1,56,$1);
        }
 
-JIT_OP_TRUNC_UBYTE: unary
+JIT_OP_TRUNC_UBYTE:
        [reg] -> {
                _alpha_li8(inst,ALPHA_AT,0xff);
                alpha_and(inst,$1,ALPHA_AT,$1);
        }
 
-JIT_OP_TRUNC_SHORT: unary
+JIT_OP_TRUNC_SHORT:
        [reg] -> {
                alpha_slli(inst,$1,56,$1);
                alpha_srai(inst,$1,56,$1);
        }
 
-JIT_OP_TRUNC_USHORT: unary
+JIT_OP_TRUNC_USHORT:
        [reg] -> {
                alpha_slli(inst,$1,56,$1);
                alpha_srli(inst,$1,56,$1);
@@ -69,7 +72,7 @@
  */
 
 /* return value1 + value2; */
-JIT_OP_IADD: binary
+JIT_OP_IADD:
        [=reg, reg, imm, if("$3 == 0")] -> {
                alpha_mov(inst,$2,$1);
        }
@@ -78,7 +81,7 @@
        }
 
 /* return value1 - value2; */
-JIT_OP_ISUB: binary
+JIT_OP_ISUB:
        [=reg, reg, imm, if("$3 == 0")] -> {
                alpha_mov(inst,$2,$1);
        }
@@ -88,7 +91,7 @@
 
 /* return value1 * value2; */
 /* TODO add more trivial IMUL imm rules */
-JIT_OP_IMUL: binary
+JIT_OP_IMUL:
        [=reg, reg, imm, if("$3 == 1")] -> {
                alpha_mov(inst,$2,$1);
        }
@@ -113,27 +116,27 @@
  */
 
 /* return -value1; */
-JIT_OP_INEG: unary
+JIT_OP_INEG:
        [reg] -> {
                /* Alpha has no neg operation, do $1 = 0 - $1; instead */
                alpha_subl(inst,ALPHA_ZERO,$1,$1);
        }
 
 /* return value1 + value2 */
-JIT_OP_LADD: binary
+JIT_OP_LADD:
        [=lreg, lreg, lreg] -> {
                alpha_addq(inst,$3,$2,$1);
        }
 
 /* return value1 - value2 */
-JIT_OP_LSUB: binary
+JIT_OP_LSUB:
        [=lreg, lreg, lreg] -> {
                alpha_subq(inst,$3,$2,$1);
        }
 
 /* return value1 * value2 */
 /* TODO add more trivial LMUL imm rules */
-JIT_OP_LMUL: binary
+JIT_OP_LMUL:
        [=lreg, lreg, imm, if("$3 == 1")] -> {
                alpha_mov(inst,$2,$1);
        }
@@ -147,7 +150,7 @@
                alpha_mulq(inst,$3,$2,$1);
        }
 
-JIT_OP_LNEG: unary
+JIT_OP_LNEG:
        [lreg] -> {
                /* Alpha has no neg operation, do $1 = 0 - $1; instead */
                alpha_subq(inst,ALPHA_ZERO,$1,$1);
@@ -167,22 +170,22 @@
 /*
  * Bitwise opcodes.
  */
-JIT_OP_IAND: binary
+JIT_OP_IAND:
        [=reg, reg, reg] -> {
                alpha_and(inst,$3,$2,$1);
        }
 
-JIT_OP_IOR: binary
+JIT_OP_IOR:
        [=reg, reg, reg] -> {
                alpha_or(inst,$3,$2,$1);
        }
 
-JIT_OP_IXOR: binary
+JIT_OP_IXOR:
        [=reg, reg, reg] -> {
                alpha_xor(inst,$3,$2,$1);
        }
 
-JIT_OP_INOT: unary
+JIT_OP_INOT:
        [reg] -> {
                _alpha_li32(inst,ALPHA_AT,0xffffffff);
                alpha_xor(inst,ALPHA_AT,$1,$1);
@@ -196,38 +199,38 @@
  * these to work properly.
  */
 
-JIT_OP_LAND: binary
+JIT_OP_LAND:
        [=reg, reg, reg] -> {
                alpha_and(inst,$3,$2,$1);
        }
 
-JIT_OP_LOR: binary
+JIT_OP_LOR:
        [=reg, reg, reg] -> {
                alpha_or(inst,$3,$2,$1);
        }
 
-JIT_OP_LXOR: binary
+JIT_OP_LXOR:
        [=reg, reg, reg] -> {
                alpha_xor(inst,$3,$2,$1);
        }
 
-JIT_OP_LNOT: unary
+JIT_OP_LNOT:
        [reg] -> {
                _alpha_li64(inst,ALPHA_AT,0xffffffff);
                alpha_xor(inst,ALPHA_AT,$1,$1);
        }
 
-JIT_OP_LSHL: binary
+JIT_OP_LSHL:
        [=reg, reg, reg] -> {
                alpha_sll(inst,$3,$2,$1);
        }
 
-JIT_OP_LSHR: binary
+JIT_OP_LSHR:
        [=reg, reg, reg] -> {
                alpha_srl(inst,$3,$2,$1);
        }
 
-JIT_OP_LSHR_UN: binary
+JIT_OP_LSHR_UN:
        [=reg, reg, reg] -> {
                alpha_sra(inst,$3,$2,$1);
        }
@@ -236,25 +239,25 @@
  * Branch opcodes
  */
 
-JIT_OP_BR: spill_before
+JIT_OP_BR: branch
        [] -> {
                /* branch if ALPHA_ZERO is zero (this is always true) */
                alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_ZERO);
        }
 
-JIT_OP_BR_IFALSE: unary_branch
+JIT_OP_BR_IFALSE: branch
        [reg] -> {
                /* banch if $1 == 0 */
                alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, $1);
        }
 
-JIT_OP_BR_ITRUE: unary_branch
+JIT_OP_BR_ITRUE: branch
        [reg] -> {
                /* branch if $1 != 0 */
                alpha_output_branch(func, inst, ALPHA_OP_BNE, insn, $1);
        }
 
-JIT_OP_BR_IEQ: binary_branch
+JIT_OP_BR_IEQ: branch
        [reg, reg] -> {
                /* $1 == $2 -> $at */
                alpha_cmpeq(inst, $1, $2, ALPHA_AT);
@@ -263,7 +266,7 @@
                alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_AT);
        }
 
-JIT_OP_BR_INE: binary_branch
+JIT_OP_BR_INE: branch
        [reg, reg] -> {
                /* $1 == $2 -> $at */
                alpha_cmpeq(inst, $1, $2, ALPHA_AT);
@@ -271,7 +274,8 @@
                /* branch if $at == 0 */
                alpha_output_branch(func, inst, ALPHA_OP_BNE, insn, ALPHA_AT);
        }
-JIT_OP_BR_ILT: binary_branch
+
+JIT_OP_BR_ILT: branch
        [reg, reg] -> {
                /* $1 < $2 -> $at */
                alpha_cmplt(inst, $1, $2, ALPHA_AT);
@@ -280,7 +284,7 @@
                alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_AT);
        }
 
-JIT_OP_BR_ILT_UN: binary_branch
+JIT_OP_BR_ILT_UN: branch
        [reg, reg] -> {
                /* $1 < $2 -> $at */
                alpha_cmpult(inst, $1, $2, ALPHA_AT);
@@ -289,7 +293,7 @@
                alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_AT);
        }
 
-JIT_OP_BR_ILE: binary_branch
+JIT_OP_BR_ILE: branch
        [reg, reg] -> {
                /* $1 <= $2 -> $at */
                alpha_cmple(inst, $1, $2, ALPHA_AT);
@@ -298,7 +302,7 @@
                alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_AT);
        }
 
-JIT_OP_BR_ILE_UN: binary_branch
+JIT_OP_BR_ILE_UN: branch
        [reg, reg] -> {
                /* $1 <= $2 -> $at */
                alpha_cmpule(inst, $1, $2, ALPHA_AT);
@@ -307,7 +311,7 @@
                alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_AT);
        }
 
-JIT_OP_BR_IGT:
+JIT_OP_BR_IGT: branch
        [reg, reg] -> {
                /* $1 <= $2 -> $at */
                alpha_cmpgt(inst, $1, $2, ALPHA_AT);
@@ -316,7 +320,7 @@
                alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_AT);
        }
 
-JIT_OP_BR_IGT_UN:
+JIT_OP_BR_IGT_UN: branch
        [reg, reg] -> {
                /* $1 > $2 -> $at */
                alpha_cmpugt(inst, $1, $2, ALPHA_AT);
@@ -325,7 +329,7 @@
                alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_AT);
        }
 
-JIT_OP_BR_IGE:
+JIT_OP_BR_IGE: branch
        [reg, reg] -> {
                /* $1 >= $2 -> $at */
                alpha_cmpge(inst, $1, $2, ALPHA_AT);
@@ -334,7 +338,7 @@
                alpha_output_branch(func, inst, ALPHA_OP_BEQ, insn, ALPHA_AT);
        }
 
-JIT_OP_BR_IGE_UN:
+JIT_OP_BR_IGE_UN: branch
        [reg, reg] -> {
                /* $1 >= $2 -> $at */
                alpha_cmpuge(inst, $1, $2, ALPHA_AT);
@@ -348,34 +352,34 @@
  * Comparison opcodes.
  */
 
-JIT_OP_IEQ: binary
+JIT_OP_IEQ:
        [=reg, reg, reg] -> {
                alpha_cmpeq(inst,$3,$2,$1);
        }
 
-JIT_OP_INE: binary
+JIT_OP_INE:
        [=reg, reg, reg] -> {
                alpha_cmpeq(inst,$3,$2,$1);
                alpha_cmpeq(inst,$1,ALPHA_ZERO,$1);
        }
 
-JIT_OP_ILT: binary
+JIT_OP_ILT:
        [=reg, reg, reg] -> {
                alpha_cmplt(inst,$3,$2,$1);
        }
 
 
-JIT_OP_ILT_UN: binary
+JIT_OP_ILT_UN:
        [=reg, reg, reg] -> {
                alpha_cmpult(inst,$3,$2,$1);
        }
 
-JIT_OP_ILE: binary
+JIT_OP_ILE:
        [=reg, reg, reg] -> {
                alpha_cmple(inst,$3,$2,$1);
        }
 
-JIT_OP_ILE_UN: binary
+JIT_OP_ILE_UN:
        [=reg, reg, reg] -> {
                alpha_cmpule(inst,$3,$2,$1);
        }
@@ -396,7 +400,7 @@
  * Pointer check opcodes.
  */
 
-/* TODO: JIT_OP_CHECK_NULL: unary_note */
+/* TODO: JIT_OP_CHECK_NULL: note */
 
 /*
  * Function calls.
@@ -415,13 +419,13 @@
                jump_to_epilog(gen, inst, block);
        }
 
-JIT_OP_RETURN_INT: unary_branch
+JIT_OP_RETURN_INT: branch
        [reg] -> {
                alpha_mov(inst,$1,ALPHA_V0);
                jump_to_epilog(gen, inst, block);
        }
 
-JIT_OP_RETURN_LONG: unary_branch
+JIT_OP_RETURN_LONG: branch
        [reg] -> {
                alpha_mov(inst,$1,ALPHA_V0);
                jump_to_epilog(gen, inst, block);
@@ -443,7 +447,7 @@
                /* Nothing to do here */;
        }
 
-JIT_OP_PUSH_INT: unary_note
+JIT_OP_PUSH_INT: note
        [imm] -> {
                alpha_li(inst,ALPHA_AT,$1);
                alpha_stq(inst,ALPHA_AT,ALPHA_SP,0);
@@ -454,7 +458,7 @@
                alpha_lda(inst,ALPHA_SP,ALPHA_SP,-8);
        }
 
-JIT_OP_PUSH_LONG: unary_note
+JIT_OP_PUSH_LONG: note
        [imm] -> {
                alpha_li(inst,ALPHA_AT,$1);
                alpha_stq(inst,ALPHA_AT,ALPHA_SP,0);

Index: jit/jit-rules-x86.ins
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-rules-x86.ins,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -b -r1.25 -r1.26
--- jit/jit-rules-x86.ins       28 Nov 2006 16:10:07 -0000      1.25
+++ jit/jit-rules-x86.ins       29 Dec 2006 23:16:15 -0000      1.26
@@ -18,17 +18,22 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+%regclass reg x86_reg
+%regclass breg x86_breg
+%regclass freg x86_freg
+%lregclass lreg x86_lreg
+
 /*
  * Conversion opcodes.
  */
 
 JIT_OP_TRUNC_SBYTE:
-       [=reg, reg("eax"|"ecx"|"edx"|"ebx")] -> {
+       [=reg, breg] -> {
                x86_widen_reg(inst, $1, $2, 1, 0);
        }
 
 JIT_OP_TRUNC_UBYTE:
-       [=reg, reg("eax"|"ecx"|"edx"|"ebx")] -> {
+       [=reg, breg] -> {
                x86_widen_reg(inst, $1, $2, 0, 0);
        }
 
@@ -147,7 +152,7 @@
        }
 
 JIT_OP_UINT_TO_NFLOAT:
-       [=freg, reg, scratch("?")] -> {
+       [=freg, reg, scratch reg] -> {
                x86_clear_reg(inst, $3);
                x86_push_reg(inst, $3);
                x86_push_reg(inst, $2);
@@ -189,7 +194,7 @@
        }
 
 JIT_OP_NFLOAT_TO_FLOAT32: stack
-       [=freg, freg] -> {
+       [freg] -> {
                x86_alu_reg_imm(inst, X86_SUB, X86_ESP, sizeof(void *));
                x86_fst_membase(inst, X86_ESP, 0, 0, 1);
                x86_fld_membase(inst, X86_ESP, 0, 0);
@@ -197,7 +202,7 @@
        }
 
 JIT_OP_NFLOAT_TO_FLOAT64: stack
-       [=freg, freg] -> {
+       [freg] -> {
                x86_alu_reg_imm(inst, X86_SUB, X86_ESP, sizeof(jit_float64));
                x86_fst_membase(inst, X86_ESP, 0, 1, 1);
                x86_fld_membase(inst, X86_ESP, 0, 1);
@@ -224,7 +229,7 @@
                x86_alu_reg_reg(inst, X86_ADD, $1, $2);
        }
 
-JIT_OP_ISUB: binary
+JIT_OP_ISUB:
        [reg, imm] -> {
                x86_alu_reg_imm(inst, X86_SUB, $1, $2);
        }
@@ -543,12 +548,12 @@
                }
                x86_shift_reg_imm(inst, X86_SAR, $1, shift);
        }
-       [reg("eax"), imm, scratch("?", "edx")] -> {
+       [reg("eax"), imm, scratch reg, scratch reg("edx")] -> {
                x86_mov_reg_imm(inst, $3, $2);
                x86_cdq(inst);
                x86_div_reg(inst, $3, 1);
        }
-       [reg("eax"), reg, scratch("edx")] -> {
+       [reg("eax"), reg, scratch reg("edx")] -> {
                unsigned char *patch, *patch2;
 #ifndef JIT_USE_SIGNALS
                x86_alu_reg_reg(inst, X86_OR, $2, $2);
@@ -585,12 +590,12 @@
                }
                x86_shift_reg_imm(inst, X86_SHR, $1, shift);
        }
-       [reg("eax"), imm, scratch("?", "edx")] -> {
+       [reg("eax"), imm, scratch reg, scratch reg("edx")] -> {
                x86_mov_reg_imm(inst, $3, $2);
                x86_clear_reg(inst, X86_EDX);
                x86_div_reg(inst, $3, 0);
        }
-       [reg("eax"), reg, scratch("edx")] -> {
+       [reg("eax"), reg, scratch reg("edx")] -> {
 #ifndef JIT_USE_SIGNALS
                unsigned char *patch;
                x86_alu_reg_reg(inst, X86_OR, $2, $2);
@@ -621,12 +626,12 @@
                x86_patch(patch, inst);
                x86_clear_reg(inst, $1);
        }
-       [=reg("edx"), *reg("eax"), imm, scratch("?", "edx")] -> {
+       [=reg("edx"), *reg("eax"), imm, scratch reg, scratch reg("edx")] -> {
                x86_mov_reg_imm(inst, $4, $3);
                x86_cdq(inst);
                x86_div_reg(inst, $4, 1);
        }
-       [=reg("edx"), *reg("eax"), reg, scratch("edx")] -> {
+       [=reg("edx"), *reg("eax"), reg, scratch reg("edx")] -> {
                unsigned char *patch, *patch2;
 #ifndef JIT_USE_SIGNALS
                x86_alu_reg_reg(inst, X86_OR, $3, $3);
@@ -659,12 +664,12 @@
                /* x & (x - 1) is equal to zero if x is a power of 2  */
                x86_alu_reg_imm(inst, X86_AND, $1, $2 - 1);
        }
-       [=reg("edx"), *reg("eax"), imm, scratch("?", "edx")] -> {
+       [=reg("edx"), *reg("eax"), imm, scratch reg, scratch reg("edx")] -> {
                x86_mov_reg_imm(inst, $4, $3);
                x86_clear_reg(inst, X86_EDX);
                x86_div_reg(inst, $4, 0);
        }
-       [=reg("edx"), *reg("eax"), reg, scratch("edx")] -> {
+       [=reg("edx"), *reg("eax"), reg, scratch reg("edx")] -> {
 #ifndef JIT_USE_SIGNALS
                unsigned char *patch;
                x86_alu_reg_reg(inst, X86_OR, $3, $3);
@@ -677,7 +682,7 @@
                x86_div_reg(inst, $3, 0);
        }
 
-JIT_OP_INEG: unary
+JIT_OP_INEG:
        [reg] -> {
                x86_neg_reg(inst, $1);
        }
@@ -705,7 +710,7 @@
                x86_alu_reg_reg(inst, X86_ADC, %1, %2);
        }
 
-JIT_OP_LSUB: binary
+JIT_OP_LSUB:
        [lreg, imm] -> {
                jit_int value1 = ((jit_int *)($2))[0];
                jit_int value2 = ((jit_int *)($2))[1];
@@ -728,7 +733,7 @@
                x86_alu_reg_reg(inst, X86_SBB, %1, %2);
        }
 
-JIT_OP_LNEG: unary
+JIT_OP_LNEG:
        [lreg] -> {
                /* TODO: gcc generates the first variant while
                   AoA suggests the second. Figure out if one
@@ -744,36 +749,29 @@
 #endif
        }
 
-JIT_OP_FADD, JIT_OP_DADD, JIT_OP_NFADD: binary, stack
+JIT_OP_FADD, JIT_OP_DADD, JIT_OP_NFADD: stack
        [freg, freg] -> {
                x86_fp_op_reg(inst, X86_FADD, 1, 1);
        }
 
-JIT_OP_FSUB, JIT_OP_DSUB, JIT_OP_NFSUB: binary, stack
+JIT_OP_FSUB, JIT_OP_DSUB, JIT_OP_NFSUB: stack
        [freg, freg] -> {
                x86_fp_op_reg(inst, X86_FSUB, 1, 1);
        }
 
-JIT_OP_FMUL, JIT_OP_DMUL, JIT_OP_NFMUL: binary, stack
+JIT_OP_FMUL, JIT_OP_DMUL, JIT_OP_NFMUL: stack
        [freg, freg] -> {
                x86_fp_op_reg(inst, X86_FMUL, 1, 1);
        }
 
-JIT_OP_FDIV, JIT_OP_DDIV, JIT_OP_NFDIV: binary, stack
+JIT_OP_FDIV, JIT_OP_DDIV, JIT_OP_NFDIV: stack
        [freg, freg] -> {
                x86_fp_op_reg(inst, X86_FDIV, 1, 1);
        }
 
-JIT_OP_FREM, JIT_OP_DREM, JIT_OP_NFREM: binary, stack
-       [freg, freg] -> {
+JIT_OP_FREM, JIT_OP_DREM, JIT_OP_NFREM: stack
+       [freg, freg, scratch reg("eax")] -> {
                unsigned char *label;
-               int save_eax = 0;
-               if(gen->contents[X86_REG_EAX].num_values > 0 ||
-                  gen->contents[X86_REG_EAX].used_for_temp)
-               {
-                       save_eax = 1;
-                       x86_push_reg(inst, X86_EAX);
-               }
                x86_fxch(inst, 1);
                label = inst;
                x86_fprem(inst);
@@ -781,13 +779,9 @@
                x86_alu_reg_imm(inst, X86_AND, X86_EAX, 0x0400);
                x86_branch(inst, X86_CC_NZ, label, 0);
                x86_fstp(inst, 1);
-               if(save_eax)
-               {
-                       x86_pop_reg(inst, X86_EAX);
-               }
        }
 
-JIT_OP_FNEG, JIT_OP_DNEG, JIT_OP_NFNEG: unary, stack
+JIT_OP_FNEG, JIT_OP_DNEG, JIT_OP_NFNEG: stack
        [freg] -> {
                x86_fchs(inst);
        }
@@ -829,12 +823,12 @@
                x86_alu_reg_reg(inst, X86_XOR, $1, $2);
        }
 
-JIT_OP_INOT: unary
+JIT_OP_INOT:
        [reg] -> {
                x86_not_reg(inst, $1);
        }
 
-JIT_OP_ISHL: binary
+JIT_OP_ISHL:
        [reg, imm] -> {
                x86_shift_reg_imm(inst, X86_SHL, $1, ($2 & 0x1F));
        }
@@ -842,7 +836,7 @@
                inst = shift_reg(inst, X86_SHL, $1, $2);
        }
 
-JIT_OP_ISHR: binary
+JIT_OP_ISHR:
        [reg, imm] -> {
                x86_shift_reg_imm(inst, X86_SAR, $1, ($2 & 0x1F));
        }
@@ -850,7 +844,7 @@
                inst = shift_reg(inst, X86_SAR, $1, $2);
        }
 
-JIT_OP_ISHR_UN: binary
+JIT_OP_ISHR_UN:
        [reg, imm] -> {
                x86_shift_reg_imm(inst, X86_SHR, $1, ($2 & 0x1F));
        }
@@ -906,7 +900,7 @@
                x86_alu_reg_reg(inst, X86_XOR, %1, %2);
        }
 
-JIT_OP_LNOT: binary
+JIT_OP_LNOT:
        [lreg] -> {
                x86_not_reg(inst, $1);
                x86_not_reg(inst, %1);
@@ -916,24 +910,24 @@
  * Branch opcodes.
  */
 
-JIT_OP_BR: spill_before
+JIT_OP_BR: branch
        [] -> {
                inst = output_branch(func, inst, 0xEB /* jmp */, insn);
        }
 
-JIT_OP_BR_IFALSE: unary_branch
+JIT_OP_BR_IFALSE: branch
        [reg] -> {
                x86_alu_reg_reg(inst, X86_OR, $1, $1);
                inst = output_branch(func, inst, 0x74 /* eq */, insn);
        }
 
-JIT_OP_BR_ITRUE: unary_branch
+JIT_OP_BR_ITRUE: branch
        [reg] -> {
                x86_alu_reg_reg(inst, X86_OR, $1, $1);
                inst = output_branch(func, inst, 0x75 /* ne */, insn);
        }
 
-JIT_OP_BR_IEQ: binary_branch
+JIT_OP_BR_IEQ: branch
        [reg, immzero] -> {
                x86_alu_reg_reg(inst, X86_OR, $1, $1);
                inst = output_branch(func, inst, 0x74 /* eq */, insn);
@@ -951,7 +945,7 @@
                inst = output_branch(func, inst, 0x74 /* eq */, insn);
        }
 
-JIT_OP_BR_INE: binary_branch
+JIT_OP_BR_INE: branch
        [reg, immzero] -> {
                x86_alu_reg_reg(inst, X86_OR, $1, $1);
                inst = output_branch(func, inst, 0x75 /* ne */, insn);
@@ -969,7 +963,7 @@
                inst = output_branch(func, inst, 0x75 /* ne */, insn);
        }
 
-JIT_OP_BR_ILT: binary_branch
+JIT_OP_BR_ILT: branch
        [reg, imm] -> {
                x86_alu_reg_imm(inst, X86_CMP, $1, $2);
                inst = output_branch(func, inst, 0x7C /* lt */, insn);
@@ -983,7 +977,7 @@
                inst = output_branch(func, inst, 0x7C /* lt */, insn);
        }
 
-JIT_OP_BR_ILT_UN: binary_branch
+JIT_OP_BR_ILT_UN: branch
        [reg, imm] -> {
                x86_alu_reg_imm(inst, X86_CMP, $1, $2);
                inst = output_branch(func, inst, 0x72 /* lt_un */, insn);
@@ -997,7 +991,7 @@
                inst = output_branch(func, inst, 0x72 /* lt_un */, insn);
        }
 
-JIT_OP_BR_ILE: binary_branch
+JIT_OP_BR_ILE: branch
        [reg, imm] -> {
                x86_alu_reg_imm(inst, X86_CMP, $1, $2);
                inst = output_branch(func, inst, 0x7E /* le */, insn);
@@ -1011,7 +1005,7 @@
                inst = output_branch(func, inst, 0x7E /* le */, insn);
        }
 
-JIT_OP_BR_ILE_UN: binary_branch
+JIT_OP_BR_ILE_UN: branch
        [reg, imm] -> {
                x86_alu_reg_imm(inst, X86_CMP, $1, $2);
                inst = output_branch(func, inst, 0x76 /* le_un */, insn);
@@ -1025,7 +1019,7 @@
                inst = output_branch(func, inst, 0x76 /* le_un */, insn);
        }
 
-JIT_OP_BR_IGT: binary_branch
+JIT_OP_BR_IGT: branch
        [reg, imm] -> {
                x86_alu_reg_imm(inst, X86_CMP, $1, $2);
                inst = output_branch(func, inst, 0x7F /* gt */, insn);
@@ -1039,7 +1033,7 @@
                inst = output_branch(func, inst, 0x7F /* gt */, insn);
        }
 
-JIT_OP_BR_IGT_UN: binary_branch
+JIT_OP_BR_IGT_UN: branch
        [reg, imm] -> {
                x86_alu_reg_imm(inst, X86_CMP, $1, $2);
                inst = output_branch(func, inst, 0x77 /* gt_un */, insn);
@@ -1053,7 +1047,7 @@
                inst = output_branch(func, inst, 0x77 /* gt_un */, insn);
        }
 
-JIT_OP_BR_IGE: binary_branch
+JIT_OP_BR_IGE: branch
        [reg, imm] -> {
                x86_alu_reg_imm(inst, X86_CMP, $1, $2);
                inst = output_branch(func, inst, 0x7D /* ge */, insn);
@@ -1067,7 +1061,7 @@
                inst = output_branch(func, inst, 0x7D /* ge */, insn);
        }
 
-JIT_OP_BR_IGE_UN: binary_branch
+JIT_OP_BR_IGE_UN: branch
        [reg, imm] -> {
                x86_alu_reg_imm(inst, X86_CMP, $1, $2);
                inst = output_branch(func, inst, 0x73 /* ge_un */, insn);
@@ -1237,29 +1231,29 @@
  * Mathematical opcodes.
  */
 
-JIT_OP_FATAN, JIT_OP_DATAN, JIT_OP_NFATAN: unary, stack, only
-       [freg] -> {
+JIT_OP_FATAN, JIT_OP_DATAN, JIT_OP_NFATAN: stack
+       [freg, clobber(freg)] -> {
                x86_fld1(inst);
                x86_fpatan(inst);
                x86_fldz(inst);
                x86_fp_op_reg(inst, X86_FADD, 1, 1);
        }
 
-JIT_OP_FCOS, JIT_OP_DCOS, JIT_OP_NFCOS: unary, stack, only
-       [freg] -> {
+JIT_OP_FCOS, JIT_OP_DCOS, JIT_OP_NFCOS: stack
+       [freg, clobber(freg)] -> {
                x86_fcos(inst);
                x86_fldz(inst);
                x86_fp_op_reg(inst, X86_FADD, 1, 1);
        }
 
-JIT_OP_FSIN, JIT_OP_DSIN, JIT_OP_NFSIN: unary, stack, only
-       [freg] -> {
+JIT_OP_FSIN, JIT_OP_DSIN, JIT_OP_NFSIN: stack
+       [freg, clobber(freg)] -> {
                x86_fsin(inst);
                x86_fldz(inst);
                x86_fp_op_reg(inst, X86_FADD, 1, 1);
        }
 
-JIT_OP_FSQRT, JIT_OP_DSQRT, JIT_OP_NFSQRT: unary, stack
+JIT_OP_FSQRT, JIT_OP_DSQRT, JIT_OP_NFSQRT: stack
        [freg] -> {
                x86_fsqrt(inst);
        }
@@ -1269,14 +1263,14 @@
  */
 
 JIT_OP_IABS:
-       [reg("eax"), scratch("edx")] -> {
+       [reg("eax"), scratch reg("edx")] -> {
                x86_cdq(inst);
                x86_alu_reg_reg(inst, X86_XOR, $1, $2);
                x86_alu_reg_reg(inst, X86_SUB, $1, $2);
        }
 
 JIT_OP_LABS:
-       [lreg, scratch("?")] -> {
+       [lreg, scratch reg] -> {
                x86_mov_reg_reg(inst, $2, %1, 4);
                x86_shift_reg_imm(inst, X86_SAR, $2, 31);
                x86_alu_reg_reg(inst, X86_XOR, $1, $2);
@@ -1285,7 +1279,7 @@
                x86_alu_reg_reg(inst, X86_SBB, %1, $2);
        }
 
-JIT_OP_FABS, JIT_OP_DABS, JIT_OP_NFABS: unary, stack
+JIT_OP_FABS, JIT_OP_DABS, JIT_OP_NFABS: stack
        [freg] -> {
                x86_fabs(inst);
        }
@@ -1329,7 +1323,7 @@
  * Pointer check opcodes.
  */
 
-JIT_OP_CHECK_NULL: unary_note
+JIT_OP_CHECK_NULL: note
        [reg] -> {
                unsigned char *patch;
                x86_alu_reg_reg(inst, X86_OR, $1, $1);
@@ -1398,32 +1392,35 @@
                inst = jump_to_epilog(gen, inst, block);
        }
 
-JIT_OP_RETURN_INT: unary_note
+JIT_OP_RETURN_INT: note
        [reg("eax")] -> {
                inst = jump_to_epilog(gen, inst, block);
        }
 
-JIT_OP_RETURN_LONG: unary_note
+JIT_OP_RETURN_LONG: note
        [lreg("eax":"edx")] -> {
                inst = jump_to_epilog(gen, inst, block);
        }
 
-JIT_OP_RETURN_FLOAT32: unary_note, stack, only
-       [freg] -> {
+JIT_OP_RETURN_FLOAT32: note, stack
+       [freg, clobber(freg)] -> {
+               /* clobber(freg) frees all registers on the fp stack */
                inst = jump_to_epilog(gen, inst, block);
        }
 
-JIT_OP_RETURN_FLOAT64: unary_note, stack, only
-       [freg] -> {
+JIT_OP_RETURN_FLOAT64: note, stack
+       [freg, clobber(freg)] -> {
+               /* clobber(freg) frees all registers on the fp stack */
                inst = jump_to_epilog(gen, inst, block);
        }
 
-JIT_OP_RETURN_NFLOAT: unary_note, stack, only
-       [freg] -> {
+JIT_OP_RETURN_NFLOAT: note, stack
+       [freg, clobber(freg)] -> {
+               /* clobber(freg) frees all registers on the fp stack */
                inst = jump_to_epilog(gen, inst, block);
        }
 
-JIT_OP_RETURN_SMALL_STRUCT: binary_note
+JIT_OP_RETURN_SMALL_STRUCT: note
        [reg, imm] -> {
                switch($2)
                {
@@ -1520,7 +1517,7 @@
                inst = jump_to_epilog(gen, inst, block);
        }
 
-JIT_OP_SETUP_FOR_NESTED: spill_before
+JIT_OP_SETUP_FOR_NESTED: branch
        [] -> {
                jit_nint nest_reg = jit_value_get_nint_constant(insn->value1);
                if(nest_reg == -1)
@@ -1534,7 +1531,7 @@
                }
        }
 
-JIT_OP_SETUP_FOR_SIBLING: spill_before
+JIT_OP_SETUP_FOR_SIBLING: branch
        [] -> {
                jit_value_t parent;
                jit_nint level = jit_value_get_nint_constant(insn->value1);
@@ -1615,7 +1612,7 @@
  * Exception handling.
  */
 
-JIT_OP_THROW: unary_branch
+JIT_OP_THROW: branch
        [reg] -> {
                x86_push_reg(inst, $1);
                if(func->builder->setjmp_value != 0)
@@ -1664,13 +1661,13 @@
 JIT_OP_ENTER_FINALLY: manual
        [] -> { /* Nothing to do here: return address on the stack */ }
 
-JIT_OP_LEAVE_FINALLY: spill_before
+JIT_OP_LEAVE_FINALLY: branch
        [] -> {
                /* The "finally" return address is on the stack */
                x86_ret(inst);
        }
 
-JIT_OP_CALL_FINALLY: spill_before
+JIT_OP_CALL_FINALLY: branch
        [] -> {
                jit_block_t block;
 
@@ -1769,28 +1766,17 @@
 JIT_OP_COPY_NFLOAT: copy, stack
        [freg] -> {}
 
-JIT_OP_COPY_STRUCT: manual, spill_before
-       [] -> {
-               unsigned char *inst;
-               _jit_gen_fix_value(insn->dest);
-               _jit_gen_fix_value(insn->value1);
-               inst = gen->posn.ptr;
-               if(!jit_cache_check_for_n(&(gen->posn), 128))
-               {
-                       jit_cache_mark_full(&(gen->posn));
-                       return;
-               }
-               inst = memory_copy(gen, inst, X86_EBP, insn->dest->frame_offset,
-                                                  X86_EBP, 
insn->value1->frame_offset,
+JIT_OP_COPY_STRUCT:
+       [=frame, frame, clobber(reg)] -> {
+               inst = memory_copy(gen, inst, X86_EBP, $1, X86_EBP, $2,
                                                   
jit_type_get_size(jit_value_get_type(insn->dest)));
-               gen->posn.ptr = inst;
        }
 
 JIT_OP_COPY_STORE_BYTE:
        [=frame, imm] -> {
                x86_mov_membase_imm(inst, X86_EBP, $1, $2, 1);
        }
-       [=frame, reg("eax"|"ecx"|"edx"|"ebx")] -> {
+       [=frame, breg] -> {
                x86_mov_membase_reg(inst, X86_EBP, $1, $2, 1);
        }
 
@@ -1812,9 +1798,11 @@
  */
 
 JIT_OP_RETURN_REG: manual
-       [] -> { /* Nothing to do here */ }
+        [] -> {
+               /* Nothing to do here */;
+       }
 
-JIT_OP_PUSH_INT: unary_note
+JIT_OP_PUSH_INT: note
        [imm] -> {
                x86_push_imm(inst, $1);
                gen->stack_changed = 1;
@@ -1828,7 +1816,7 @@
                gen->stack_changed = 1;
        }
 
-JIT_OP_PUSH_LONG: unary_note
+JIT_OP_PUSH_LONG: note
        [imm] -> {
                x86_push_imm(inst, ((jit_int *)($1))[1]);
                x86_push_imm(inst, ((jit_int *)($1))[0]);
@@ -1845,7 +1833,7 @@
                gen->stack_changed = 1;
        }
 
-JIT_OP_PUSH_FLOAT32: unary_note, stack
+JIT_OP_PUSH_FLOAT32: note, stack
        [imm] -> {
                jit_int *ptr = (jit_int *)($1);
                x86_push_imm(inst, ptr[0]);
@@ -1861,7 +1849,7 @@
                gen->stack_changed = 1;
        }
 
-JIT_OP_PUSH_FLOAT64: unary_note, stack
+JIT_OP_PUSH_FLOAT64: note, stack
        [imm] -> {
                jit_int *ptr = (jit_int *)($1);
                x86_push_imm(inst, ptr[1]);
@@ -1879,7 +1867,7 @@
                gen->stack_changed = 1;
        }
 
-JIT_OP_PUSH_NFLOAT: unary_note, stack
+JIT_OP_PUSH_NFLOAT: note, stack
        [imm] -> {
                jit_int *ptr = (jit_int *)($1);
                if(sizeof(jit_nfloat) != sizeof(jit_float64))
@@ -1913,8 +1901,8 @@
                gen->stack_changed = 1;
        }
 
-JIT_OP_PUSH_STRUCT: unary_branch, more_space
-       [reg] -> {
+JIT_OP_PUSH_STRUCT: note, more_space
+       [reg, clobber(reg)] -> {
                jit_nuint size;
                size = (jit_nuint)jit_value_get_nint_constant(insn->value2);
                if((size % sizeof(void *)) == 0 && size <= 4 * sizeof(void *))
@@ -2013,11 +2001,9 @@
                x86_fld_membase(inst, $2, $3, 1);
        }
 
-JIT_OP_LOAD_RELATIVE_STRUCT: unary_branch, more_space
-       [reg] -> {
-               _jit_gen_fix_value(insn->dest);
-               inst = memory_copy(gen, inst, X86_EBP, insn->dest->frame_offset,
-                                                  $1, 
jit_value_get_nint_constant(insn->value2),
+JIT_OP_LOAD_RELATIVE_STRUCT: more_space
+       [=frame, reg, imm, clobber(reg)] -> {
+               inst = memory_copy(gen, inst, X86_EBP, $1, $2, $3,
                                                   
jit_type_get_size(jit_value_get_type(insn->dest)));
        }
 
@@ -2025,13 +2011,13 @@
        [imm, imm, imm] -> {
                x86_mov_mem_imm(inst, $1 + $3, $2, 1);
        }
-       [imm, reg("eax"|"ecx"|"edx"|"ebx"), imm] -> {
+       [imm, breg, imm] -> {
                x86_mov_mem_reg(inst, $1 + $3, $2, 1);
        }
        [reg, imm, imm] -> {
                x86_mov_membase_imm(inst, $1, $3, $2, 1);
        }
-       [reg, reg("eax"|"ecx"|"edx"|"ebx"), imm] -> {
+       [reg, breg, imm] -> {
                x86_mov_membase_reg(inst, $1, $3, $2, 1);
        }
 
@@ -2068,7 +2054,7 @@
                x86_mov_membase_imm(inst, $1, $3, *(int *)($2), 4);
                x86_mov_membase_imm(inst, $1, $3 + 4, *(int *)($2 + 4), 4);
        }
-       [reg, local, imm, scratch("?")] -> {
+       [reg, local, imm, scratch reg] -> {
                x86_mov_reg_membase(inst, $4, X86_EBP, $2, 4);
                x86_mov_membase_reg(inst, $1, $3, $4, 4);
                x86_mov_reg_membase(inst, $4, X86_EBP, $2 + 4, 4);
@@ -2138,11 +2124,11 @@
                gen->posn.ptr = inst;
        }
 
-JIT_OP_ADD_RELATIVE: unary
-       [reg] -> {
+JIT_OP_ADD_RELATIVE:
+       [reg, imm] -> {
                if(insn->value2->address != 0)
                {
-                       x86_alu_reg_imm(inst, X86_ADD, $1, 
insn->value2->address);
+                       x86_alu_reg_imm(inst, X86_ADD, $1, $2);
                }
        }
 
@@ -2211,7 +2197,7 @@
        }
 
 JIT_OP_STORE_ELEMENT_BYTE: ternary
-       [reg, reg, reg("eax"|"ecx"|"edx"|"ebx")] -> {
+       [reg, reg, breg] -> {
                x86_mov_memindex_reg(inst, $1, 0, $2, 0, $3, 1);
        }
 
@@ -2230,7 +2216,7 @@
                x86_mov_memindex_imm(inst, $1, 0, $2, 3, *(int *)($3), 4);
                x86_mov_memindex_imm(inst, $1, 4, $2, 3, *(int *)($3 + 4), 4);
        }
-       [reg, reg, local, scratch("?")] -> {
+       [reg, reg, local, scratch reg] -> {
                x86_mov_reg_membase(inst, $4, X86_EBP, $3, 4);
                x86_mov_memindex_reg(inst, $1, 0, $2, 3, $4, 4);
                x86_mov_reg_membase(inst, $4, X86_EBP, $3 + 4, 4);
@@ -2268,8 +2254,7 @@
 
 JIT_OP_MEMCPY: ternary
        [any, any, imm, if("$3 <= 0")] -> { }
-       [reg, reg, imm, if("$3 <= 32"),
-        scratch("eax" | "ecx" | "edx" | "ebx"), space("32 + $3 * 4")] -> {
+       [reg, reg, imm, scratch breg, if("$3 <= 32"), space("32 + $3 * 4")] -> {
                int disp;
                disp = 0;
                while($3 >= (disp + 4))
@@ -2328,7 +2313,7 @@
                        x86_mov_membase_imm(inst, $1, disp, $2, 1);
                }
        }
-       [reg, reg("eax"|"ecx"|"edx"|"ebx"), imm, if("$3 < 4")] -> {
+       [reg, breg, imm, if("$3 < 4")] -> {
                x86_mov_membase_reg(inst, $1, 0, $2, 1);
                if($3 > 1)
                {
@@ -2339,7 +2324,7 @@
                        }
                }
        }
-       [reg, +reg, imm, scratch("?"),
+       [reg, +reg, imm, scratch reg,
         if("$3 <= 32 && ($3 % 2) == 0"), space("32 + $3 * 4")] -> {
                int disp;
                x86_mov_reg_reg(inst, $4, $2, 4);
@@ -2359,7 +2344,7 @@
                        x86_mov_membase_reg(inst, $1, disp, $2, 2);
                }
        }
-       [reg, +reg("eax"|"ecx"|"edx"|"ebx"), imm, scratch("?"),
+       [reg, +breg, imm, scratch reg,
         if("$3 <= 32 && ($3 % 2) != 0"), space("32 + $3 * 4")] -> {
                int disp;
                x86_mov_reg_reg(inst, $4, $2, 4);
@@ -2396,7 +2381,7 @@
  * Allocate memory from the stack.
  */
 
-JIT_OP_ALLOCA: unary
+JIT_OP_ALLOCA:
        [reg] -> {
                x86_alu_reg_imm(inst, X86_ADD, $1, 15);
                x86_alu_reg_imm(inst, X86_AND, $1, ~15);
@@ -2405,8 +2390,8 @@
                gen->stack_changed = 1;
        }
 
-JIT_OP_JUMP_TABLE: ternary
-       [reg, imm, imm, clobber("*"), space("32 + sizeof(void) * $3")] -> {
+JIT_OP_JUMP_TABLE: ternary, branch
+       [reg, imm, imm, space("32 + sizeof(void) * $3")] -> {
                unsigned char *patch_jump_table;
                unsigned char *patch_fall_through;
                int index;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]