x86: introduce operand type "class"
authorJan Beulich <jbeulich@suse.com>
Fri, 8 Nov 2019 08:03:23 +0000 (09:03 +0100)
committerJan Beulich <jbeulich@suse.com>
Fri, 8 Nov 2019 08:03:23 +0000 (09:03 +0100)
Many operand types, in particular the various kinds of registers, can't
be combined with one another (neither in templates nor in register
entries), and hence it is not a good use of resources (memory as well as
execution time) to represent them as individual bits of a bit field.

gas/ChangeLog
gas/config/tc-i386.c
opcodes/ChangeLog
opcodes/i386-gen.c
opcodes/i386-init.h
opcodes/i386-opc.h
opcodes/i386-opc.tbl
opcodes/i386-reg.tbl

index 6376ce114ff7f56255703707e92f3c660879124d..a2937f8663aed767c28fe82c2a6fe2f60305243f 100644 (file)
@@ -1,3 +1,17 @@
+2019-11-08  Jan Beulich  <jbeulich@suse.com>
+
+       * config/tc-i386.c (operand_type_set, operand_type_and,
+       operand_type_and_not, operand_type_or, operand_type_xor): Handle
+       "class" field specially.
+       (anyimm): New.
+       (operand_type_check, operand_size_match,
+       operand_type_register_match, pi, md_assemble, is_short_form,
+       process_suffix, check_byte_reg, check_long_reg, check_qword_reg,
+       check_word_reg, process_operands, build_modrm_byte): Use "class"
+       instead of "reg" field.
+       (optimize_imm): Likewise. Reduce redundancy. Adjust calculation
+       of "allowed".
+
 2019-11-07  Mihail Ionescu  <mihail.ionescu@arm.com>
 
        * testsuite/gas/aarch64/dgh.s: New test.
index ad51daf781573c288048e8b50cf0c7f89a517cda..32f855020329498108468657bf25a430548ae5d8 100644 (file)
@@ -1611,6 +1611,8 @@ operand_type_set (union i386_operand_type *x, unsigned int v)
     default:
       abort ();
     }
+
+  x->bitfield.class = ClassNone;
 }
 
 static INLINE int
@@ -1825,6 +1827,9 @@ cpu_flags_match (const insn_template *t)
 static INLINE i386_operand_type
 operand_type_and (i386_operand_type x, i386_operand_type y)
 {
+  if (x.bitfield.class != y.bitfield.class)
+    x.bitfield.class = ClassNone;
+
   switch (ARRAY_SIZE (x.array))
     {
     case 3:
@@ -1845,6 +1850,8 @@ operand_type_and (i386_operand_type x, i386_operand_type y)
 static INLINE i386_operand_type
 operand_type_and_not (i386_operand_type x, i386_operand_type y)
 {
+  gas_assert (y.bitfield.class == ClassNone);
+
   switch (ARRAY_SIZE (x.array))
     {
     case 3:
@@ -1865,6 +1872,10 @@ operand_type_and_not (i386_operand_type x, i386_operand_type y)
 static INLINE i386_operand_type
 operand_type_or (i386_operand_type x, i386_operand_type y)
 {
+  gas_assert (x.bitfield.class == ClassNone ||
+              y.bitfield.class == ClassNone ||
+              x.bitfield.class == y.bitfield.class);
+
   switch (ARRAY_SIZE (x.array))
     {
     case 3:
@@ -1885,6 +1896,8 @@ operand_type_or (i386_operand_type x, i386_operand_type y)
 static INLINE i386_operand_type
 operand_type_xor (i386_operand_type x, i386_operand_type y)
 {
+  gas_assert (y.bitfield.class == ClassNone);
+
   switch (ARRAY_SIZE (x.array))
     {
     case 3:
@@ -1906,8 +1919,8 @@ static const i386_operand_type disp16 = OPERAND_TYPE_DISP16;
 static const i386_operand_type disp32 = OPERAND_TYPE_DISP32;
 static const i386_operand_type disp32s = OPERAND_TYPE_DISP32S;
 static const i386_operand_type disp16_32 = OPERAND_TYPE_DISP16_32;
-static const i386_operand_type anydisp
-  = OPERAND_TYPE_ANYDISP;
+static const i386_operand_type anydisp = OPERAND_TYPE_ANYDISP;
+static const i386_operand_type anyimm = OPERAND_TYPE_ANYIMM;
 static const i386_operand_type regxmm = OPERAND_TYPE_REGXMM;
 static const i386_operand_type regmask = OPERAND_TYPE_REGMASK;
 static const i386_operand_type imm8 = OPERAND_TYPE_IMM8;
@@ -1934,7 +1947,7 @@ operand_type_check (i386_operand_type t, enum operand_type c)
   switch (c)
     {
     case reg:
-      return t.bitfield.reg;
+      return t.bitfield.class == Reg;
 
     case imm:
       return (t.bitfield.imm8
@@ -2052,11 +2065,11 @@ operand_size_match (const insn_template *t)
   /* Check memory and accumulator operand size.  */
   for (j = 0; j < i.operands; j++)
     {
-      if (!i.types[j].bitfield.reg && !i.types[j].bitfield.regsimd
+      if (i.types[j].bitfield.class != Reg && !i.types[j].bitfield.regsimd
          && t->operand_types[j].bitfield.anysize)
        continue;
 
-      if (t->operand_types[j].bitfield.reg
+      if (t->operand_types[j].bitfield.class == Reg
          && !match_operand_size (t, j, j))
        {
          match = 0;
@@ -2099,7 +2112,7 @@ mismatch:
     {
       unsigned int given = i.operands - j - 1;
 
-      if (t->operand_types[j].bitfield.reg
+      if (t->operand_types[j].bitfield.class == Reg
          && !match_operand_size (t, j, given))
        goto mismatch;
 
@@ -2159,14 +2172,14 @@ operand_type_register_match (i386_operand_type g0,
                             i386_operand_type g1,
                             i386_operand_type t1)
 {
-  if (!g0.bitfield.reg
+  if (g0.bitfield.class != Reg
       && !g0.bitfield.regsimd
       && (!operand_type_check (g0, anymem)
          || g0.bitfield.unspecified
          || !t0.bitfield.regsimd))
     return 1;
 
-  if (!g1.bitfield.reg
+  if (g1.bitfield.class != Reg
       && !g1.bitfield.regsimd
       && (!operand_type_check (g1, anymem)
          || g1.bitfield.unspecified
@@ -3032,7 +3045,7 @@ pi (const char *line, i386_insn *x)
       fprintf (stdout, "    #%d:  ", j + 1);
       pt (x->types[j]);
       fprintf (stdout, "\n");
-      if (x->types[j].bitfield.reg
+      if (x->types[j].bitfield.class == Reg
          || x->types[j].bitfield.regmmx
          || x->types[j].bitfield.regsimd
          || x->types[j].bitfield.sreg
@@ -4506,12 +4519,12 @@ md_assemble (char *line)
      instruction already has a prefix, we need to convert old
      registers to new ones.  */
 
-  if ((i.types[0].bitfield.reg && i.types[0].bitfield.byte
+  if ((i.types[0].bitfield.class == Reg && i.types[0].bitfield.byte
        && (i.op[0].regs->reg_flags & RegRex64) != 0)
-      || (i.types[1].bitfield.reg && i.types[1].bitfield.byte
+      || (i.types[1].bitfield.class == Reg && i.types[1].bitfield.byte
          && (i.op[1].regs->reg_flags & RegRex64) != 0)
-      || (((i.types[0].bitfield.reg && i.types[0].bitfield.byte)
-          || (i.types[1].bitfield.reg && i.types[1].bitfield.byte))
+      || (((i.types[0].bitfield.class == Reg && i.types[0].bitfield.byte)
+          || (i.types[1].bitfield.class == Reg && i.types[1].bitfield.byte))
          && i.rex != 0))
     {
       int x;
@@ -4520,7 +4533,7 @@ md_assemble (char *line)
       for (x = 0; x < 2; x++)
        {
          /* Look for 8 bit operand that uses old registers.  */
-         if (i.types[x].bitfield.reg && i.types[x].bitfield.byte
+         if (i.types[x].bitfield.class == Reg && i.types[x].bitfield.byte
              && (i.op[x].regs->reg_flags & RegRex64) == 0)
            {
              /* In case it is "hi" register, give up.  */
@@ -4545,7 +4558,7 @@ md_assemble (char *line)
         the REX_OPCODE byte.  */
       int x;
       for (x = 0; x < 2; x++)
-       if (i.types[x].bitfield.reg
+       if (i.types[x].bitfield.class == Reg
            && i.types[x].bitfield.byte
            && (i.op[x].regs->reg_flags & RegRex64) == 0
            && i.op[x].regs->reg_num > 3)
@@ -5066,22 +5079,24 @@ optimize_imm (void)
         but the following works for instructions with immediates.
         In any case, we can't set i.suffix yet.  */
       for (op = i.operands; --op >= 0;)
-       if (i.types[op].bitfield.reg && i.types[op].bitfield.byte)
+       if (i.types[op].bitfield.class != Reg)
+         continue;
+       else if (i.types[op].bitfield.byte)
          {
            guess_suffix = BYTE_MNEM_SUFFIX;
            break;
          }
-       else if (i.types[op].bitfield.reg && i.types[op].bitfield.word)
+       else if (i.types[op].bitfield.word)
          {
            guess_suffix = WORD_MNEM_SUFFIX;
            break;
          }
-       else if (i.types[op].bitfield.reg && i.types[op].bitfield.dword)
+       else if (i.types[op].bitfield.dword)
          {
            guess_suffix = LONG_MNEM_SUFFIX;
            break;
          }
-       else if (i.types[op].bitfield.reg && i.types[op].bitfield.qword)
+       else if (i.types[op].bitfield.qword)
          {
            guess_suffix = QWORD_MNEM_SUFFIX;
            break;
@@ -5170,8 +5185,10 @@ optimize_imm (void)
              for (t = current_templates->start;
                   t < current_templates->end;
                   ++t)
-               allowed = operand_type_or (allowed,
-                                          t->operand_types[op]);
+               {
+                 allowed = operand_type_or (allowed, t->operand_types[op]);
+                 allowed = operand_type_and (allowed, anyimm);
+               }
              switch (guess_suffix)
                {
                case QWORD_MNEM_SUFFIX:
@@ -6248,7 +6265,8 @@ process_suffix (void)
             Destination register type is more significant than source
             register type.  crc32 in SSE4.2 prefers source register
             type. */
-         if (i.tm.base_opcode == 0xf20f38f0 && i.types[0].bitfield.reg)
+         if (i.tm.base_opcode == 0xf20f38f0
+             && i.types[0].bitfield.class == Reg)
            {
              if (i.types[0].bitfield.byte)
                i.suffix = BYTE_MNEM_SUFFIX;
@@ -6276,7 +6294,7 @@ process_suffix (void)
                if (!i.tm.operand_types[op].bitfield.inoutportreg
                    && !i.tm.operand_types[op].bitfield.shiftcount)
                  {
-                   if (!i.types[op].bitfield.reg)
+                   if (i.types[op].bitfield.class != Reg)
                      continue;
                    if (i.types[op].bitfield.byte)
                      i.suffix = BYTE_MNEM_SUFFIX;
@@ -6451,7 +6469,7 @@ process_suffix (void)
         size prefix, except for instructions that will ignore this
         prefix anyway.  */
       if (i.reg_operands > 0
-         && i.types[0].bitfield.reg
+         && i.types[0].bitfield.class == Reg
          && i.tm.opcode_modifier.addrprefixopreg
          && (i.tm.opcode_modifier.immext
              || i.operands == 1))
@@ -6519,7 +6537,7 @@ process_suffix (void)
        }
 
       for (op = 0; op < i.operands; op++)
-       if (i.types[op].bitfield.reg
+       if (i.types[op].bitfield.class == Reg
            && ((need == need_word
                 && !i.op[op].regs->reg_type.bitfield.word)
                || (need == need_dword
@@ -6544,7 +6562,7 @@ check_byte_reg (void)
   for (op = i.operands; --op >= 0;)
     {
       /* Skip non-register operands. */
-      if (!i.types[op].bitfield.reg)
+      if (i.types[op].bitfield.class != Reg)
        continue;
 
       /* If this is an eight bit register, it's OK.  If it's the 16 or
@@ -6583,7 +6601,7 @@ check_byte_reg (void)
          continue;
        }
       /* Any other register is bad.  */
-      if (i.types[op].bitfield.reg
+      if (i.types[op].bitfield.class == Reg
          || i.types[op].bitfield.regmmx
          || i.types[op].bitfield.regsimd
          || i.types[op].bitfield.sreg
@@ -6609,12 +6627,12 @@ check_long_reg (void)
 
   for (op = i.operands; --op >= 0;)
     /* Skip non-register operands. */
-    if (!i.types[op].bitfield.reg)
+    if (i.types[op].bitfield.class != Reg)
       continue;
     /* Reject eight bit registers, except where the template requires
        them. (eg. movzb)  */
     else if (i.types[op].bitfield.byte
-            && (i.tm.operand_types[op].bitfield.reg
+            && (i.tm.operand_types[op].bitfield.class == Reg
                 || i.tm.operand_types[op].bitfield.acc)
             && (i.tm.operand_types[op].bitfield.word
                 || i.tm.operand_types[op].bitfield.dword))
@@ -6629,7 +6647,7 @@ check_long_reg (void)
     /* Warn if the e prefix on a general reg is missing.  */
     else if ((!quiet_warnings || flag_code == CODE_64BIT)
             && i.types[op].bitfield.word
-            && (i.tm.operand_types[op].bitfield.reg
+            && (i.tm.operand_types[op].bitfield.class == Reg
                 || i.tm.operand_types[op].bitfield.acc)
             && i.tm.operand_types[op].bitfield.dword)
       {
@@ -6651,7 +6669,7 @@ check_long_reg (void)
       }
     /* Warn if the r prefix on a general reg is present.  */
     else if (i.types[op].bitfield.qword
-            && (i.tm.operand_types[op].bitfield.reg
+            && (i.tm.operand_types[op].bitfield.class == Reg
                 || i.tm.operand_types[op].bitfield.acc)
             && i.tm.operand_types[op].bitfield.dword)
       {
@@ -6680,12 +6698,12 @@ check_qword_reg (void)
 
   for (op = i.operands; --op >= 0; )
     /* Skip non-register operands. */
-    if (!i.types[op].bitfield.reg)
+    if (i.types[op].bitfield.class != Reg)
       continue;
     /* Reject eight bit registers, except where the template requires
        them. (eg. movzb)  */
     else if (i.types[op].bitfield.byte
-            && (i.tm.operand_types[op].bitfield.reg
+            && (i.tm.operand_types[op].bitfield.class == Reg
                 || i.tm.operand_types[op].bitfield.acc)
             && (i.tm.operand_types[op].bitfield.word
                 || i.tm.operand_types[op].bitfield.dword))
@@ -6700,7 +6718,7 @@ check_qword_reg (void)
     /* Warn if the r prefix on a general reg is missing.  */
     else if ((i.types[op].bitfield.word
              || i.types[op].bitfield.dword)
-            && (i.tm.operand_types[op].bitfield.reg
+            && (i.tm.operand_types[op].bitfield.class == Reg
                 || i.tm.operand_types[op].bitfield.acc)
             && i.tm.operand_types[op].bitfield.qword)
       {
@@ -6730,12 +6748,12 @@ check_word_reg (void)
   int op;
   for (op = i.operands; --op >= 0;)
     /* Skip non-register operands. */
-    if (!i.types[op].bitfield.reg)
+    if (i.types[op].bitfield.class != Reg)
       continue;
     /* Reject eight bit registers, except where the template requires
        them. (eg. movzb)  */
     else if (i.types[op].bitfield.byte
-            && (i.tm.operand_types[op].bitfield.reg
+            && (i.tm.operand_types[op].bitfield.class == Reg
                 || i.tm.operand_types[op].bitfield.acc)
             && (i.tm.operand_types[op].bitfield.word
                 || i.tm.operand_types[op].bitfield.dword))
@@ -6751,7 +6769,7 @@ check_word_reg (void)
     else if ((!quiet_warnings || flag_code == CODE_64BIT)
             && (i.types[op].bitfield.dword
                 || i.types[op].bitfield.qword)
-            && (i.tm.operand_types[op].bitfield.reg
+            && (i.tm.operand_types[op].bitfield.class == Reg
                 || i.tm.operand_types[op].bitfield.acc)
             && i.tm.operand_types[op].bitfield.word)
       {
@@ -7049,7 +7067,7 @@ duplicate:
     {
       /* The register or float register operand is in operand
         0 or 1.  */
-      unsigned int op = !i.tm.operand_types[0].bitfield.reg;
+      unsigned int op = i.tm.operand_types[0].bitfield.class != Reg;
 
       /* Register goes in low 3 bits of opcode.  */
       i.tm.base_opcode |= i.op[op].regs->reg_num;
@@ -7284,7 +7302,7 @@ build_modrm_byte (void)
 
              op = i.tm.operand_types[vvvv];
              if ((dest + 1) >= i.operands
-                 || ((!op.bitfield.reg
+                 || ((op.bitfield.class != Reg
                       || (!op.bitfield.dword && !op.bitfield.qword))
                      && !op.bitfield.regsimd
                      && !operand_type_equal (&op, &regmask)))
@@ -7661,7 +7679,7 @@ build_modrm_byte (void)
 
          for (op = 0; op < i.operands; op++)
            {
-             if (i.types[op].bitfield.reg
+             if (i.types[op].bitfield.class == Reg
                  || i.types[op].bitfield.regbnd
                  || i.types[op].bitfield.regmask
                  || i.types[op].bitfield.sreg
@@ -7743,7 +7761,7 @@ build_modrm_byte (void)
            {
              i386_operand_type *type = &i.tm.operand_types[vex_reg];
 
-             if ((!type->bitfield.reg
+             if ((type->bitfield.class != Reg
                   || (!type->bitfield.dword && !type->bitfield.qword))
                  && !type->bitfield.regsimd
                  && !operand_type_equal (type, &regmask))
index 9bd41c01af24f2ddcd9136494c62a8841f0f8cd0..fab75c4d83385063806733c06949a433b7606e4e 100644 (file)
@@ -1,3 +1,21 @@
+2019-11-08  Jan Beulich  <jbeulich@suse.com>
+
+       * i386-gen.c (operand_type_init): Add Class=. New
+       OPERAND_TYPE_ANYIMM entry.
+       (operand_classes): New.
+       (operand_types): Drop Reg entry.
+       (output_operand_type): New parameter "class". Process it.
+       (process_i386_operand_type): New local variable "class".
+       (main): Adjust static assertions.
+       * i386-opc.h (CLASS_WIDTH): Define.
+       (enum operand_class): New.
+       (Reg): Replace by Class. Adjust comment.
+       (union i386_operand_type): Replace reg by class.
+       * i386-opc.tbl (Reg8, Reg16, Reg32, Reg64, FloatReg): Add
+       Class=.
+       * i386-reg.tbl: Replace Reg by Class=Reg.
+       * i386-init.h: Re-generate.
+
 2019-11-07  Mihail Ionescu  <mihail.ionescu@arm.com>
 
        * opcodes/aarch64-tbl.h (V8_6_INSN): New macro for v8.6 instructions.
index d33e665ed15cb65ca96117554cb8d9cf4cfe8969..a15be805a86e446d92377adc14ad26e9c0a9cbc2 100644 (file)
@@ -388,13 +388,13 @@ static initializer operand_type_init[] =
   { "OPERAND_TYPE_NONE",
     "0" },
   { "OPERAND_TYPE_REG8",
-    "Reg|Byte" },
+    "Class=Reg|Byte" },
   { "OPERAND_TYPE_REG16",
-    "Reg|Word" },
+    "Class=Reg|Word" },
   { "OPERAND_TYPE_REG32",
-    "Reg|Dword" },
+    "Class=Reg|Dword" },
   { "OPERAND_TYPE_REG64",
-    "Reg|Qword" },
+    "Class=Reg|Qword" },
   { "OPERAND_TYPE_IMM1",
     "Imm1" },
   { "OPERAND_TYPE_IMM8",
@@ -432,7 +432,7 @@ static initializer operand_type_init[] =
   { "OPERAND_TYPE_DEBUG",
     "Debug" },
   { "OPERAND_TYPE_FLOATREG",
-    "Reg|Tbyte" },
+    "Class=Reg|Tbyte" },
   { "OPERAND_TYPE_FLOATACC",
     "Acc|Tbyte" },
   { "OPERAND_TYPE_SREG",
@@ -479,6 +479,8 @@ static initializer operand_type_init[] =
     "Imm32|Imm32S|Imm64|Disp32" },
   { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
     "Imm32|Imm32S|Imm64|Disp32|Disp64" },
+  { "OPERAND_TYPE_ANYIMM",
+    "Imm1|Imm8|Imm8S|Imm16|Imm32|Imm32S|Imm64" },
   { "OPERAND_TYPE_REGBND",
     "RegBND" },
 };
@@ -674,9 +676,19 @@ static bitfield opcode_modifiers[] =
   BITFIELD (Intel64),
 };
 
+#define CLASS(n) #n, n
+
+static const struct {
+  const char *name;
+  enum operand_class value;
+} operand_classes[] = {
+  CLASS (Reg),
+};
+
+#undef CLASS
+
 static bitfield operand_types[] =
 {
-  BITFIELD (Reg),
   BITFIELD (RegMMX),
   BITFIELD (RegSIMD),
   BITFIELD (RegMask),
@@ -1134,20 +1146,21 @@ enum stage {
 };
 
 static void
-output_operand_type (FILE *table, bitfield *types, unsigned int size,
+output_operand_type (FILE *table, enum operand_class class,
+                    const bitfield *types, unsigned int size,
                     enum stage stage, const char *indent)
 {
   unsigned int i;
 
-  fprintf (table, "{ { ");
+  fprintf (table, "{ { %d, ", class);
 
   for (i = 0; i < size - 1; i++)
     {
-      if (((i + 1) % 20) != 0)
+      if (((i + 2) % 20) != 0)
        fprintf (table, "%d, ", types[i].value);
       else
        fprintf (table, "%d,", types[i].value);
-      if (((i + 1) % 20) == 0)
+      if (((i + 2) % 20) == 0)
        {
          /* We need \\ for macro.  */
          if (stage == stage_macros)
@@ -1165,6 +1178,7 @@ process_i386_operand_type (FILE *table, char *op, enum stage stage,
                           const char *indent, int lineno)
 {
   char *str, *next, *last;
+  enum operand_class class = ClassNone;
   bitfield types [ARRAY_SIZE (operand_types)];
 
   /* Copy the default operand type.  */
@@ -1178,6 +1192,21 @@ process_i386_operand_type (FILE *table, char *op, enum stage stage,
       for (next = op; next && next < last; )
        {
          str = next_field (next, '|', &next, last);
+         if (str)
+           {
+             unsigned int i;
+
+             if (!strncmp(str, "Class=", 6))
+               {
+                 for (i = 0; i < ARRAY_SIZE(operand_classes); ++i)
+                   if (!strcmp(str + 6, operand_classes[i].name))
+                     {
+                       class = operand_classes[i].value;
+                       str = NULL;
+                       break;
+                     }
+               }
+           }
          if (str)
            {
              set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
@@ -1197,7 +1226,7 @@ process_i386_operand_type (FILE *table, char *op, enum stage stage,
            set_bitfield("Disp32S", types, 1, ARRAY_SIZE (types), lineno);
        }
     }
-  output_operand_type (table, types, ARRAY_SIZE (types), stage,
+  output_operand_type (table, class, types, ARRAY_SIZE (types), stage,
                       indent);
 }
 
@@ -1688,9 +1717,9 @@ main (int argc, char **argv)
 
   /* Check the unused bitfield in i386_operand_type.  */
 #ifdef OTUnused
-  static_assert (ARRAY_SIZE (operand_types) == OTNum + 1);
+  static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH == OTNum + 1);
 #else
-  static_assert (ARRAY_SIZE (operand_types) == OTNum);
+  static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH == OTNum);
 
   c = OTNumOfBits - OTMax - 1;
   if (c)
index f67e534c3a39b0e9abd7b54cf155adbc67d9577f..66e5f11b2367327ff3383ff2eaa37fbd3c1efe5f 100644 (file)
   { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, \
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
 
+#define OPERAND_TYPE_ANYIMM \
+  { { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, \
+      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
+
 #define OPERAND_TYPE_REGBND \
   { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 } }
index e9b1f9280ed9f87237d866f3b6d2864b00cabac6..5c49ac1a528f590acc38203352dd262d04fafefa 100644 (file)
@@ -702,12 +702,21 @@ typedef struct i386_opcode_modifier
   unsigned int intel64:1;
 } i386_opcode_modifier;
 
+/* Operand classes.  */
+
+#define CLASS_WIDTH 4
+enum operand_class
+{
+  ClassNone,
+  Reg, /* GPRs and FP regs, distinguished by operand size */
+};
+
 /* Position of operand_type bits.  */
 
 enum
 {
-  /* Register (qualified by Byte, Word, etc) */
-  Reg = 0,
+  /* Class */
+  Class = CLASS_WIDTH - 1,
   /* MMX register */
   RegMMX,
   /* Vector registers */
@@ -791,7 +800,7 @@ enum
   /* Bound register.  */
   RegBND,
 
-  /* The number of bitfields in i386_operand_type.  */
+  /* The number of bits in i386_operand_type.  */
   OTNum
 };
 
@@ -808,7 +817,7 @@ typedef union i386_operand_type
 {
   struct
     {
-      unsigned int reg:1;
+      unsigned int class:CLASS_WIDTH;
       unsigned int regmmx:1;
       unsigned int regsimd:1;
       unsigned int regmask:1;
index 115c6f1cd817f08e0e679ce07ec1bcb1c7a47910..e4a3d7c2e806c742f55a566c1672af2914d6d5b3 100644 (file)
 #include "i386-opc.h"
 #undef None
 
-#define Reg8  Reg|Byte
-#define Reg16 Reg|Word
-#define Reg32 Reg|Dword
-#define Reg64 Reg|Qword
+#define Reg8  Class=Reg|Byte
+#define Reg16 Class=Reg|Word
+#define Reg32 Class=Reg|Dword
+#define Reg64 Class=Reg|Qword
 
 #define FloatAcc Acc|Tbyte
-#define FloatReg Reg|Tbyte
+#define FloatReg Class=Reg|Tbyte
 
 #define RegXMM RegSIMD|Xmmword
 #define RegYMM RegSIMD|Ymmword
index 61e9fe07c201296249a3c1f69c20e12da5bfb93f..8e6a2df2ee5e92f572d1c030f1a563ec068abb28 100644 (file)
 // 02110-1301, USA.
 
 // Make %st first as we test for it.
-st, Reg|Acc|Tbyte, 0, 0, 11, 33
+st, Class=Reg|Acc|Tbyte, 0, 0, 11, 33
 // 8 bit regs
-al, Reg|Acc|Byte, 0, 0, Dw2Inval, Dw2Inval
-cl, Reg|Byte|ShiftCount, 0, 1, Dw2Inval, Dw2Inval
-dl, Reg|Byte, 0, 2, Dw2Inval, Dw2Inval
-bl, Reg|Byte, 0, 3, Dw2Inval, Dw2Inval
-ah, Reg|Byte, 0, 4, Dw2Inval, Dw2Inval
-ch, Reg|Byte, 0, 5, Dw2Inval, Dw2Inval
-dh, Reg|Byte, 0, 6, Dw2Inval, Dw2Inval
-bh, Reg|Byte, 0, 7, Dw2Inval, Dw2Inval
-axl, Reg|Byte, RegRex64, 0, Dw2Inval, Dw2Inval
-cxl, Reg|Byte, RegRex64, 1, Dw2Inval, Dw2Inval
-dxl, Reg|Byte, RegRex64, 2, Dw2Inval, Dw2Inval
-bxl, Reg|Byte, RegRex64, 3, Dw2Inval, Dw2Inval
-spl, Reg|Byte, RegRex64, 4, Dw2Inval, Dw2Inval
-bpl, Reg|Byte, RegRex64, 5, Dw2Inval, Dw2Inval
-sil, Reg|Byte, RegRex64, 6, Dw2Inval, Dw2Inval
-dil, Reg|Byte, RegRex64, 7, Dw2Inval, Dw2Inval
-r8b, Reg|Byte, RegRex|RegRex64, 0, Dw2Inval, Dw2Inval
-r9b, Reg|Byte, RegRex|RegRex64, 1, Dw2Inval, Dw2Inval
-r10b, Reg|Byte, RegRex|RegRex64, 2, Dw2Inval, Dw2Inval
-r11b, Reg|Byte, RegRex|RegRex64, 3, Dw2Inval, Dw2Inval
-r12b, Reg|Byte, RegRex|RegRex64, 4, Dw2Inval, Dw2Inval
-r13b, Reg|Byte, RegRex|RegRex64, 5, Dw2Inval, Dw2Inval
-r14b, Reg|Byte, RegRex|RegRex64, 6, Dw2Inval, Dw2Inval
-r15b, Reg|Byte, RegRex|RegRex64, 7, Dw2Inval, Dw2Inval
+al, Class=Reg|Acc|Byte, 0, 0, Dw2Inval, Dw2Inval
+cl, Class=Reg|Byte|ShiftCount, 0, 1, Dw2Inval, Dw2Inval
+dl, Class=Reg|Byte, 0, 2, Dw2Inval, Dw2Inval
+bl, Class=Reg|Byte, 0, 3, Dw2Inval, Dw2Inval
+ah, Class=Reg|Byte, 0, 4, Dw2Inval, Dw2Inval
+ch, Class=Reg|Byte, 0, 5, Dw2Inval, Dw2Inval
+dh, Class=Reg|Byte, 0, 6, Dw2Inval, Dw2Inval
+bh, Class=Reg|Byte, 0, 7, Dw2Inval, Dw2Inval
+axl, Class=Reg|Byte, RegRex64, 0, Dw2Inval, Dw2Inval
+cxl, Class=Reg|Byte, RegRex64, 1, Dw2Inval, Dw2Inval
+dxl, Class=Reg|Byte, RegRex64, 2, Dw2Inval, Dw2Inval
+bxl, Class=Reg|Byte, RegRex64, 3, Dw2Inval, Dw2Inval
+spl, Class=Reg|Byte, RegRex64, 4, Dw2Inval, Dw2Inval
+bpl, Class=Reg|Byte, RegRex64, 5, Dw2Inval, Dw2Inval
+sil, Class=Reg|Byte, RegRex64, 6, Dw2Inval, Dw2Inval
+dil, Class=Reg|Byte, RegRex64, 7, Dw2Inval, Dw2Inval
+r8b, Class=Reg|Byte, RegRex|RegRex64, 0, Dw2Inval, Dw2Inval
+r9b, Class=Reg|Byte, RegRex|RegRex64, 1, Dw2Inval, Dw2Inval
+r10b, Class=Reg|Byte, RegRex|RegRex64, 2, Dw2Inval, Dw2Inval
+r11b, Class=Reg|Byte, RegRex|RegRex64, 3, Dw2Inval, Dw2Inval
+r12b, Class=Reg|Byte, RegRex|RegRex64, 4, Dw2Inval, Dw2Inval
+r13b, Class=Reg|Byte, RegRex|RegRex64, 5, Dw2Inval, Dw2Inval
+r14b, Class=Reg|Byte, RegRex|RegRex64, 6, Dw2Inval, Dw2Inval
+r15b, Class=Reg|Byte, RegRex|RegRex64, 7, Dw2Inval, Dw2Inval
 // 16 bit regs
-ax, Reg|Acc|Word, 0, 0, Dw2Inval, Dw2Inval
-cx, Reg|Word, 0, 1, Dw2Inval, Dw2Inval
-dx, Reg|Word|InOutPortReg, 0, 2, Dw2Inval, Dw2Inval
-bx, Reg|Word|BaseIndex, 0, 3, Dw2Inval, Dw2Inval
-sp, Reg|Word, 0, 4, Dw2Inval, Dw2Inval
-bp, Reg|Word|BaseIndex, 0, 5, Dw2Inval, Dw2Inval
-si, Reg|Word|BaseIndex, 0, 6, Dw2Inval, Dw2Inval
-di, Reg|Word|BaseIndex, 0, 7, Dw2Inval, Dw2Inval
-r8w, Reg|Word, RegRex, 0, Dw2Inval, Dw2Inval
-r9w, Reg|Word, RegRex, 1, Dw2Inval, Dw2Inval
-r10w, Reg|Word, RegRex, 2, Dw2Inval, Dw2Inval
-r11w, Reg|Word, RegRex, 3, Dw2Inval, Dw2Inval
-r12w, Reg|Word, RegRex, 4, Dw2Inval, Dw2Inval
-r13w, Reg|Word, RegRex, 5, Dw2Inval, Dw2Inval
-r14w, Reg|Word, RegRex, 6, Dw2Inval, Dw2Inval
-r15w, Reg|Word, RegRex, 7, Dw2Inval, Dw2Inval
+ax, Class=Reg|Acc|Word, 0, 0, Dw2Inval, Dw2Inval
+cx, Class=Reg|Word, 0, 1, Dw2Inval, Dw2Inval
+dx, Class=Reg|Word|InOutPortReg, 0, 2, Dw2Inval, Dw2Inval
+bx, Class=Reg|Word|BaseIndex, 0, 3, Dw2Inval, Dw2Inval
+sp, Class=Reg|Word, 0, 4, Dw2Inval, Dw2Inval
+bp, Class=Reg|Word|BaseIndex, 0, 5, Dw2Inval, Dw2Inval
+si, Class=Reg|Word|BaseIndex, 0, 6, Dw2Inval, Dw2Inval
+di, Class=Reg|Word|BaseIndex, 0, 7, Dw2Inval, Dw2Inval
+r8w, Class=Reg|Word, RegRex, 0, Dw2Inval, Dw2Inval
+r9w, Class=Reg|Word, RegRex, 1, Dw2Inval, Dw2Inval
+r10w, Class=Reg|Word, RegRex, 2, Dw2Inval, Dw2Inval
+r11w, Class=Reg|Word, RegRex, 3, Dw2Inval, Dw2Inval
+r12w, Class=Reg|Word, RegRex, 4, Dw2Inval, Dw2Inval
+r13w, Class=Reg|Word, RegRex, 5, Dw2Inval, Dw2Inval
+r14w, Class=Reg|Word, RegRex, 6, Dw2Inval, Dw2Inval
+r15w, Class=Reg|Word, RegRex, 7, Dw2Inval, Dw2Inval
 // 32 bit regs
-eax, Reg|Acc|Dword|BaseIndex, 0, 0, 0, Dw2Inval
-ecx, Reg|Dword|BaseIndex, 0, 1, 1, Dw2Inval
-edx, Reg|Dword|BaseIndex, 0, 2, 2, Dw2Inval
-ebx, Reg|Dword|BaseIndex, 0, 3, 3, Dw2Inval
-esp, Reg|Dword, 0, 4, 4, Dw2Inval
-ebp, Reg|Dword|BaseIndex, 0, 5, 5, Dw2Inval
-esi, Reg|Dword|BaseIndex, 0, 6, 6, Dw2Inval
-edi, Reg|Dword|BaseIndex, 0, 7, 7, Dw2Inval
-r8d, Reg|Dword|BaseIndex, RegRex, 0, Dw2Inval, Dw2Inval
-r9d, Reg|Dword|BaseIndex, RegRex, 1, Dw2Inval, Dw2Inval
-r10d, Reg|Dword|BaseIndex, RegRex, 2, Dw2Inval, Dw2Inval
-r11d, Reg|Dword|BaseIndex, RegRex, 3, Dw2Inval, Dw2Inval
-r12d, Reg|Dword|BaseIndex, RegRex, 4, Dw2Inval, Dw2Inval
-r13d, Reg|Dword|BaseIndex, RegRex, 5, Dw2Inval, Dw2Inval
-r14d, Reg|Dword|BaseIndex, RegRex, 6, Dw2Inval, Dw2Inval
-r15d, Reg|Dword|BaseIndex, RegRex, 7, Dw2Inval, Dw2Inval
-rax, Reg|Acc|Qword|BaseIndex, 0, 0, Dw2Inval, 0
-rcx, Reg|Qword|BaseIndex, 0, 1, Dw2Inval, 2
-rdx, Reg|Qword|BaseIndex, 0, 2, Dw2Inval, 1
-rbx, Reg|Qword|BaseIndex, 0, 3, Dw2Inval, 3
-rsp, Reg|Qword, 0, 4, Dw2Inval, 7
-rbp, Reg|Qword|BaseIndex, 0, 5, Dw2Inval, 6
-rsi, Reg|Qword|BaseIndex, 0, 6, Dw2Inval, 4
-rdi, Reg|Qword|BaseIndex, 0, 7, Dw2Inval, 5
-r8, Reg|Qword|BaseIndex, RegRex, 0, Dw2Inval, 8
-r9, Reg|Qword|BaseIndex, RegRex, 1, Dw2Inval, 9
-r10, Reg|Qword|BaseIndex, RegRex, 2, Dw2Inval, 10
-r11, Reg|Qword|BaseIndex, RegRex, 3, Dw2Inval, 11
-r12, Reg|Qword|BaseIndex, RegRex, 4, Dw2Inval, 12
-r13, Reg|Qword|BaseIndex, RegRex, 5, Dw2Inval, 13
-r14, Reg|Qword|BaseIndex, RegRex, 6, Dw2Inval, 14
-r15, Reg|Qword|BaseIndex, RegRex, 7, Dw2Inval, 15
+eax, Class=Reg|Acc|Dword|BaseIndex, 0, 0, 0, Dw2Inval
+ecx, Class=Reg|Dword|BaseIndex, 0, 1, 1, Dw2Inval
+edx, Class=Reg|Dword|BaseIndex, 0, 2, 2, Dw2Inval
+ebx, Class=Reg|Dword|BaseIndex, 0, 3, 3, Dw2Inval
+esp, Class=Reg|Dword, 0, 4, 4, Dw2Inval
+ebp, Class=Reg|Dword|BaseIndex, 0, 5, 5, Dw2Inval
+esi, Class=Reg|Dword|BaseIndex, 0, 6, 6, Dw2Inval
+edi, Class=Reg|Dword|BaseIndex, 0, 7, 7, Dw2Inval
+r8d, Class=Reg|Dword|BaseIndex, RegRex, 0, Dw2Inval, Dw2Inval
+r9d, Class=Reg|Dword|BaseIndex, RegRex, 1, Dw2Inval, Dw2Inval
+r10d, Class=Reg|Dword|BaseIndex, RegRex, 2, Dw2Inval, Dw2Inval
+r11d, Class=Reg|Dword|BaseIndex, RegRex, 3, Dw2Inval, Dw2Inval
+r12d, Class=Reg|Dword|BaseIndex, RegRex, 4, Dw2Inval, Dw2Inval
+r13d, Class=Reg|Dword|BaseIndex, RegRex, 5, Dw2Inval, Dw2Inval
+r14d, Class=Reg|Dword|BaseIndex, RegRex, 6, Dw2Inval, Dw2Inval
+r15d, Class=Reg|Dword|BaseIndex, RegRex, 7, Dw2Inval, Dw2Inval
+rax, Class=Reg|Acc|Qword|BaseIndex, 0, 0, Dw2Inval, 0
+rcx, Class=Reg|Qword|BaseIndex, 0, 1, Dw2Inval, 2
+rdx, Class=Reg|Qword|BaseIndex, 0, 2, Dw2Inval, 1
+rbx, Class=Reg|Qword|BaseIndex, 0, 3, Dw2Inval, 3
+rsp, Class=Reg|Qword, 0, 4, Dw2Inval, 7
+rbp, Class=Reg|Qword|BaseIndex, 0, 5, Dw2Inval, 6
+rsi, Class=Reg|Qword|BaseIndex, 0, 6, Dw2Inval, 4
+rdi, Class=Reg|Qword|BaseIndex, 0, 7, Dw2Inval, 5
+r8, Class=Reg|Qword|BaseIndex, RegRex, 0, Dw2Inval, 8
+r9, Class=Reg|Qword|BaseIndex, RegRex, 1, Dw2Inval, 9
+r10, Class=Reg|Qword|BaseIndex, RegRex, 2, Dw2Inval, 10
+r11, Class=Reg|Qword|BaseIndex, RegRex, 3, Dw2Inval, 11
+r12, Class=Reg|Qword|BaseIndex, RegRex, 4, Dw2Inval, 12
+r13, Class=Reg|Qword|BaseIndex, RegRex, 5, Dw2Inval, 13
+r14, Class=Reg|Qword|BaseIndex, RegRex, 6, Dw2Inval, 14
+r15, Class=Reg|Qword|BaseIndex, RegRex, 7, Dw2Inval, 15
 // Vector mask registers.
 k0, RegMask, 0, 0, 93, 118
 k1, RegMask, 0, 1, 94, 119
@@ -283,23 +283,23 @@ bnd0, RegBND, 0, 0, Dw2Inval, Dw2Inval
 bnd1, RegBND, 0, 1, Dw2Inval, Dw2Inval
 bnd2, RegBND, 0, 2, Dw2Inval, Dw2Inval
 bnd3, RegBND, 0, 3, Dw2Inval, Dw2Inval
-// No Reg will make these registers rejected for all purposes except
+// No Class=Reg will make these registers rejected for all purposes except
 // for addressing.  This saves creating one extra type for RIP/EIP.
 rip, Qword, RegRex64, RegIP, Dw2Inval, 16
 eip, Dword, RegRex64, RegIP, 8, Dw2Inval
-// No Reg will make these registers rejected for all purposes except
+// No Class=Reg will make these registers rejected for all purposes except
 // for addressing.
 riz, Qword|BaseIndex, RegRex64, RegIZ, Dw2Inval, Dw2Inval
 eiz, Dword|BaseIndex, 0, RegIZ, Dw2Inval, Dw2Inval
 // fp regs.
-st(0), Reg|Acc|Tbyte, 0, 0, 11, 33
-st(1), Reg|Tbyte, 0, 1, 12, 34
-st(2), Reg|Tbyte, 0, 2, 13, 35
-st(3), Reg|Tbyte, 0, 3, 14, 36
-st(4), Reg|Tbyte, 0, 4, 15, 37
-st(5), Reg|Tbyte, 0, 5, 16, 38
-st(6), Reg|Tbyte, 0, 6, 17, 39
-st(7), Reg|Tbyte, 0, 7, 18, 40
+st(0), Class=Reg|Acc|Tbyte, 0, 0, 11, 33
+st(1), Class=Reg|Tbyte, 0, 1, 12, 34
+st(2), Class=Reg|Tbyte, 0, 2, 13, 35
+st(3), Class=Reg|Tbyte, 0, 3, 14, 36
+st(4), Class=Reg|Tbyte, 0, 4, 15, 37
+st(5), Class=Reg|Tbyte, 0, 5, 16, 38
+st(6), Class=Reg|Tbyte, 0, 6, 17, 39
+st(7), Class=Reg|Tbyte, 0, 7, 18, 40
 // Pseudo-register names only used in .cfi_* directives
 eflags, 0, 0, 0, 9, 49
 rflags, 0, 0, 0, Dw2Inval, 49