gas/
authorH.J. Lu <hjl.tools@gmail.com>
Sat, 23 Sep 2006 23:10:14 +0000 (23:10 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Sat, 23 Sep 2006 23:10:14 +0000 (23:10 +0000)
2006-09-23  H.J. Lu  <hongjiu.lu@intel.com>

PR binutils/3235
* config/tc-i386.c (match_template): Check address size prefix
to turn Disp64/Disp32/Disp16 operand into Disp32/Disp16/Disp32
operand.

gas/testsuite/

2006-09-23  H.J. Lu  <hongjiu.lu@intel.com>

PR binutils/3235
* gas/i386/addr16.d: New file.
* gas/i386/addr16.s: Likewise.
* gas/i386/addr32.d: Likewise.
* gas/i386/addr32.s: Likewise.

* gas/i386/i386.exp: Add "addr16" and "addr32".

* gas/i386/x86-64-addr32.s: Add tests for "add32 mov".
* gas/i386/x86-64-addr32.d: Updated.

opcodes/

2006-09-23  H.J. Lu  <hongjiu.lu@intel.com>

PR binutils/3235
* i386-dis.c (OP_OFF64): Get 32bit offset if there is an
address size prefix.

12 files changed:
gas/ChangeLog
gas/config/tc-i386.c
gas/testsuite/ChangeLog
gas/testsuite/gas/i386/addr16.d [new file with mode: 0644]
gas/testsuite/gas/i386/addr16.s [new file with mode: 0644]
gas/testsuite/gas/i386/addr32.d [new file with mode: 0644]
gas/testsuite/gas/i386/addr32.s [new file with mode: 0644]
gas/testsuite/gas/i386/i386.exp
gas/testsuite/gas/i386/x86-64-addr32.d
gas/testsuite/gas/i386/x86-64-addr32.s
opcodes/ChangeLog
opcodes/i386-dis.c

index 9fe98d45f2e4de883d8a7962125a85e8951b6ac1..8648384a2b983fe8b68d7511b2a1f0df94490e55 100644 (file)
@@ -1,3 +1,10 @@
+2006-09-23  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR binutils/3235
+       * config/tc-i386.c (match_template): Check address size prefix
+       to turn Disp64/Disp32/Disp16 operand into Disp32/Disp16/Disp32
+       operand.
+
 2006-09-22  Alan Modra  <amodra@bigpond.net.au>
 
        * config/tc-ppc.c (ppc_symbol_chars): Remove '+' and '-'.
index 1e8534aea61a5c89b7c9a90f0e41c29a33f6dc68..7cf514bc38b93ea293f14e5faa47122ab6aa642d 100644 (file)
@@ -2563,6 +2563,8 @@ match_template ()
   unsigned int overlap0, overlap1, overlap2;
   unsigned int found_reverse_match;
   int suffix_check;
+  unsigned int operand_types [3];
+  int addr_prefix_disp;
 
 #define MATCH(overlap, given, template)                                \
   ((overlap & ~JumpAbsolute)                                   \
@@ -2581,6 +2583,10 @@ match_template ()
   overlap1 = 0;
   overlap2 = 0;
   found_reverse_match = 0;
+  operand_types [0] = 0;
+  operand_types [1] = 0;
+  operand_types [2] = 0;
+  addr_prefix_disp = -1;
   suffix_check = (i.suffix == BYTE_MNEM_SUFFIX
                  ? No_bSuf
                  : (i.suffix == WORD_MNEM_SUFFIX
@@ -2596,6 +2602,8 @@ match_template ()
 
   for (t = current_templates->start; t < current_templates->end; t++)
     {
+      addr_prefix_disp = -1;
+
       /* Must have right number of operands.  */
       if (i.operands != t->operands)
        continue;
@@ -2606,6 +2614,10 @@ match_template ()
               && (t->opcode_modifier & IgnoreSize)))
        continue;
 
+      operand_types [0] = t->operand_types [0];
+      operand_types [1] = t->operand_types [1];
+      operand_types [2] = t->operand_types [2];
+
       /* In general, don't allow 64-bit operands in 32-bit mode.  */
       if (i.suffix == QWORD_MNEM_SUFFIX
          && flag_code != CODE_64BIT
@@ -2613,8 +2625,8 @@ match_template ()
              ? (!(t->opcode_modifier & IgnoreSize)
                 && !intel_float_operand (t->name))
              : intel_float_operand (t->name) != 2)
-         && (!(t->operand_types[0] & (RegMMX | RegXMM))
-             || !(t->operand_types[t->operands > 1] & (RegMMX | RegXMM)))
+         && (!(operand_types[0] & (RegMMX | RegXMM))
+             || !(operand_types[t->operands > 1] & (RegMMX | RegXMM)))
          && (t->base_opcode != 0x0fc7
              || t->extension_opcode != 1 /* cmpxchg8b */))
        continue;
@@ -2628,41 +2640,76 @@ match_template ()
          break;
        }
 
-      overlap0 = i.types[0] & t->operand_types[0];
+      /* Address size prefix will turn Disp64/Disp32/Disp16 operand
+        into Disp32/Disp16/Disp32 operand.  */
+      if (i.prefix[ADDR_PREFIX] != 0)
+         {
+           unsigned int j, DispOn = 0, DispOff = 0;
+
+           switch (flag_code)
+           {
+           case CODE_16BIT:
+             DispOn = Disp32;
+             DispOff = Disp16;
+             break;
+           case CODE_32BIT:
+             DispOn = Disp16;
+             DispOff = Disp32;
+             break;
+           case CODE_64BIT:
+             DispOn = Disp32;
+             DispOff = Disp64;
+             break;
+           }
+
+           for (j = 0; j < 3; j++)
+             {
+               /* There should be only one Disp operand.  */
+               if ((operand_types[j] & DispOff))
+                 {
+                   addr_prefix_disp = j;
+                   operand_types[j] |= DispOn;
+                   operand_types[j] &= ~DispOff;
+                   break;
+                 }
+             }
+         }
+
+      overlap0 = i.types[0] & operand_types[0];
       switch (t->operands)
        {
        case 1:
-         if (!MATCH (overlap0, i.types[0], t->operand_types[0]))
+         if (!MATCH (overlap0, i.types[0], operand_types[0]))
            continue;
          break;
        case 2:
        case 3:
-         overlap1 = i.types[1] & t->operand_types[1];
-         if (!MATCH (overlap0, i.types[0], t->operand_types[0])
-             || !MATCH (overlap1, i.types[1], t->operand_types[1])
+         overlap1 = i.types[1] & operand_types[1];
+         if (!MATCH (overlap0, i.types[0], operand_types[0])
+             || !MATCH (overlap1, i.types[1], operand_types[1])
              /* monitor in SSE3 is a very special case.  The first
                 register and the second register may have different
                 sizes.  */
              || !((t->base_opcode == 0x0f01
                    && t->extension_opcode == 0xc8)
                   || CONSISTENT_REGISTER_MATCH (overlap0, i.types[0],
-                                                t->operand_types[0],
+                                                operand_types[0],
                                                 overlap1, i.types[1],
-                                                t->operand_types[1])))
+                                                operand_types[1])))
            {
              /* Check if other direction is valid ...  */
              if ((t->opcode_modifier & (D | FloatD)) == 0)
                continue;
 
              /* Try reversing direction of operands.  */
-             overlap0 = i.types[0] & t->operand_types[1];
-             overlap1 = i.types[1] & t->operand_types[0];
-             if (!MATCH (overlap0, i.types[0], t->operand_types[1])
-                 || !MATCH (overlap1, i.types[1], t->operand_types[0])
+             overlap0 = i.types[0] & operand_types[1];
+             overlap1 = i.types[1] & operand_types[0];
+             if (!MATCH (overlap0, i.types[0], operand_types[1])
+                 || !MATCH (overlap1, i.types[1], operand_types[0])
                  || !CONSISTENT_REGISTER_MATCH (overlap0, i.types[0],
-                                                t->operand_types[1],
+                                                operand_types[1],
                                                 overlap1, i.types[1],
-                                                t->operand_types[0]))
+                                                operand_types[0]))
                {
                  /* Does not match either direction.  */
                  continue;
@@ -2678,12 +2725,12 @@ match_template ()
                 reverse match 3 operand instructions, and all 3
                 operand instructions only need to be checked for
                 register consistency between operands 2 and 3.  */
-             overlap2 = i.types[2] & t->operand_types[2];
-             if (!MATCH (overlap2, i.types[2], t->operand_types[2])
+             overlap2 = i.types[2] & operand_types[2];
+             if (!MATCH (overlap2, i.types[2], operand_types[2])
                  || !CONSISTENT_REGISTER_MATCH (overlap1, i.types[1],
-                                                t->operand_types[1],
+                                                operand_types[1],
                                                 overlap2, i.types[2],
-                                                t->operand_types[2]))
+                                                operand_types[2]))
 
                continue;
            }
@@ -2711,7 +2758,7 @@ match_template ()
     {
       if (!intel_syntax
          && ((i.types[0] & JumpAbsolute)
-             != (t->operand_types[0] & JumpAbsolute)))
+             != (operand_types[0] & JumpAbsolute)))
        {
          as_warn (_("indirect %s without `*'"), t->name);
        }
@@ -2727,6 +2774,11 @@ match_template ()
 
   /* Copy the template we found.  */
   i.tm = *t;
+
+  if (addr_prefix_disp != -1)
+    i.tm.operand_types[addr_prefix_disp]
+      = operand_types[addr_prefix_disp];
+
   if (found_reverse_match)
     {
       /* If we found a reverse match we must alter the opcode
@@ -2735,8 +2787,8 @@ match_template ()
 
       i.tm.base_opcode ^= found_reverse_match;
 
-      i.tm.operand_types[0] = t->operand_types[1];
-      i.tm.operand_types[1] = t->operand_types[0];
+      i.tm.operand_types[0] = operand_types[1];
+      i.tm.operand_types[1] = operand_types[0];
     }
 
   return 1;
index 89892f7753da4889231eec9e2c59db1cf325a81a..fe1f119bdac751d901eec76b5fd7ed1d858dc8b4 100644 (file)
@@ -1,3 +1,16 @@
+2006-09-23  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR binutils/3235
+       * gas/i386/addr16.d: New file.
+       * gas/i386/addr16.s: Likewise.
+       * gas/i386/addr32.d: Likewise.
+       * gas/i386/addr32.s: Likewise.
+
+       * gas/i386/i386.exp: Add "addr16" and "addr32".
+
+       * gas/i386/x86-64-addr32.s: Add tests for "add32 mov".
+       * gas/i386/x86-64-addr32.d: Updated.
+
 2006-09-20  Kai Tietz  <Kai.Tietz@onevision.com>
 
        * gas/all/gas.exp: Add support for x86_64-*-mingw64.
diff --git a/gas/testsuite/gas/i386/addr16.d b/gas/testsuite/gas/i386/addr16.d
new file mode 100644 (file)
index 0000000..910d725
--- /dev/null
@@ -0,0 +1,15 @@
+#objdump: -drw
+#name: i386 16-bit addressing in 32-bit mode.
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <.text>:
+[       ]*0:[   ]+67 a0 98 08 [         ]+addr16[       ]+mov[         ]+0x898,%al
+[       ]*4:[   ]+67 66 a1 98 08 [      ]+addr16[       ]+mov[         ]+0x898,%ax
+[       ]*9:[   ]+67 a1 98 08 [         ]+addr16[       ]+mov[         ]+0x898,%eax
+[       ]*d:[   ]+67 a2 98 08 [         ]+addr16[       ]+mov[         ]+%al,0x898
+[       ]*11:[  ]+67 66 a3 98 08 [      ]+addr16[       ]+mov[         ]+%ax,0x898
+[       ]*16:[  ]+67 a3 98 08[  ]+addr16[       ]+mov[         ]+%eax,0x898
+#pass
diff --git a/gas/testsuite/gas/i386/addr16.s b/gas/testsuite/gas/i386/addr16.s
new file mode 100644 (file)
index 0000000..b1510e7
--- /dev/null
@@ -0,0 +1,7 @@
+       .text
+       addr16 mov      0x0898,%al
+       addr16 mov      0x0898,%ax
+       addr16 mov      0x0898,%eax
+       addr16 mov      %al,0x0898
+       addr16 mov      %ax,0x0898
+       addr16 mov      %eax,0x0898
diff --git a/gas/testsuite/gas/i386/addr32.d b/gas/testsuite/gas/i386/addr32.d
new file mode 100644 (file)
index 0000000..5866a30
--- /dev/null
@@ -0,0 +1,15 @@
+#objdump: -drw -mi8086
+#name: i386 32-bit addressing in 16-bit mode.
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <.text>:
+[       ]*0:[   ]+67 a0 98 08 60 00[    ]+addr32[       ]+mov[         ]+0x600898,%al
+[       ]*6:[   ]+67 a1 98 08 60 00[    ]+addr32[       ]+mov[         ]+0x600898,%ax
+[       ]*c:[   ]+67 66 a1 98 08 60 00[         ]+addr32[       ]+mov[         ]+0x600898,%eax
+[       ]*13:[  ]+67 a2 98 08 60 00[    ]+addr32[       ]+mov[         ]+%al,0x600898
+[       ]*19:[  ]+67 a3 98 08 60 00[    ]+addr32[       ]+mov[         ]+%ax,0x600898
+[       ]*1f:[  ]+67 66 a3 98 08 60 00[         ]+addr32[       ]+mov[         ]+%eax,0x600898
+#pass
diff --git a/gas/testsuite/gas/i386/addr32.s b/gas/testsuite/gas/i386/addr32.s
new file mode 100644 (file)
index 0000000..3dab339
--- /dev/null
@@ -0,0 +1,8 @@
+       .text
+       .code16
+       addr32 mov      0x600898,%al
+       addr32 mov      0x600898,%ax
+       addr32 mov      0x600898,%eax
+       addr32 mov      %al,0x600898
+       addr32 mov      %ax,0x600898
+       addr32 mov      %eax,0x600898
index 096b58ae64971df2cb849dd52c408c188539b0a3..aa2558ecd538e74c9c09d952825950e9acbe4b19 100644 (file)
@@ -81,6 +81,8 @@ if [expr ([istarget "i*86-*-*"] ||  [istarget "x86_64-*-*"]) && [gas_32_check]]
     run_dump_test "nops-2"
     run_dump_test "nops-2-i386"
     run_dump_test "nops-2-merom"
+    run_dump_test "addr16"
+    run_dump_test "addr32"
 
     # These tests require support for 8 and 16 bit relocs,
     # so we only run them for ELF and COFF targets.
index d22cff9c7048f0c2ca5fd3e63389424cab28bb10..6cb20dc87194f4cd582ccec1f9e34a5afc9e4f5f 100644 (file)
@@ -11,4 +11,12 @@ Disassembly of section .text:
 [       ]*8:[   ]+67 49 8d 80 00 00 00 00[      ]+addr32[       ]+lea[         ]+0x0\(%r8d?\),%rax.*
 [       ]*10:[  ]+67 48 8d 05 00 00 00 00[      ]+addr32[       ]+lea[         ]+0\(%[re]ip\),%rax.*
 [       ]*18:[  ]+67 48 8d 04 25 00 00 00 00[   ]+addr32[       ]+lea[         ]+0x0,%rax.*
+[       ]*21:[  ]+67 a0 98 08 60 00[    ]+addr32[       ]+mov[         ]+0x600898,%al
+[       ]*27:[  ]+67 66 a1 98 08 60 00[         ]+addr32[       ]+mov[         ]+0x600898,%ax
+[       ]*2e:[  ]+67 a1 98 08 60 00[    ]+addr32[       ]+mov[         ]+0x600898,%eax
+[       ]*34:[  ]+67 48 a1 98 08 60 00[         ]+addr32[       ]+mov[         ]+0x600898,%rax
+[       ]*3b:[  ]+67 a2 98 08 60 00[    ]+addr32[       ]+mov[         ]+%al,0x600898
+[       ]*41:[  ]+67 66 a3 98 08 60 00[         ]+addr32[       ]+mov[         ]+%ax,0x600898
+[       ]*48:[  ]+67 a3 98 08 60 00[    ]+addr32[       ]+mov[         ]+%eax,0x600898
+[       ]*4e:[  ]+67 48 a3 98 08 60 00[         ]+addr32[       ]+mov[         ]+%rax,0x600898
 #pass
index d18cbb91bcfc71de7457669c8d274c9182bdf94e..c32525ffa1fef397080311f6ba52f8e27247dea9 100644 (file)
@@ -3,3 +3,11 @@
        lea             symbol(%r8d), %rax
        addr32 lea      symbol(%rip), %rax
        addr32 lea      symbol, %rax
+       addr32 mov      0x600898,%al
+       addr32 mov      0x600898,%ax
+       addr32 mov      0x600898,%eax
+       addr32 mov      0x600898,%rax
+       addr32 mov      %al,0x600898
+       addr32 mov      %ax,0x600898
+       addr32 mov      %eax,0x600898
+       addr32 mov      %rax,0x600898
index b48077def72af25811e4b1f5dbdc89f32f1d582d..83c16bd3d9a0bac161f5f550aaa4e241cfbf846e 100644 (file)
@@ -1,3 +1,9 @@
+2006-09-23  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR binutils/3235
+       * i386-dis.c (OP_OFF64): Get 32bit offset if there is an
+       address size prefix.
+
 2006-09-17  Mei Ligang  <ligang@sunnorth.com.cn>
 
        * score-dis.c: New file.
index bcf30802297dbc09712d51a81b9a628cfb10b20a..5172fc5cb9a5db55cadafa9cc8c71c7bec4b161f 100644 (file)
@@ -4693,7 +4693,8 @@ OP_OFF64 (int bytemode, int sizeflag)
 {
   bfd_vma off;
 
-  if (address_mode != mode_64bit)
+  if (address_mode != mode_64bit
+      || (prefixes & PREFIX_ADDR))
     {
       OP_OFF (bytemode, sizeflag);
       return;