Corrections for x86_64 assembly.
authorNick Clifton <nickc@redhat.com>
Wed, 21 Jul 2004 16:09:43 +0000 (16:09 +0000)
committerNick Clifton <nickc@redhat.com>
Wed, 21 Jul 2004 16:09:43 +0000 (16:09 +0000)
gas/ChangeLog
gas/config/tc-i386.c
gas/testsuite/ChangeLog
gas/testsuite/gas/i386/i386.exp
gas/testsuite/gas/i386/x86-64-addr32.d [new file with mode: 0644]
gas/testsuite/gas/i386/x86-64-addr32.s [new file with mode: 0644]
gas/testsuite/gas/i386/x86-64-rip.d [new file with mode: 0644]
gas/testsuite/gas/i386/x86-64-rip.s [new file with mode: 0644]
gas/testsuite/gas/i386/x86_64.d
opcodes/ChangeLog
opcodes/i386-dis.c

index 33ac7fc..977d0d9 100644 (file)
@@ -1,3 +1,21 @@
+2004-07-21  Jan Beulich <jbeulich@novell.com>
+
+       * config/tc-i386.c (optimize_imm): Adjust immediates to only those
+       permissible for the selected instruction suffix.
+       (match_template): Don't permit 64-bit general purpose operands in
+       32-bit mode.
+       (finalize_imm): Permit 64-bit immediates.
+       (build_modrm_byte): Don't treat 32-bit addressing in 64-bit mode
+       specially except for the width of the used base and/or index
+       registers.  For 32-bit displacements, use sign-extended
+       relocations only when using 64-bit addressing.
+       Force zero displacement on rip-relative addressing when there is
+       no other displacement.
+       (i386_index_check): Don't treat 32-bit addressing in 64-bit mode
+       specially except for the width of the used base and/or index
+       registers.
+       (parse_register): Disallow Reg64 registers in 32-bit mode.
+
 2004-07-20  Maciej W. Rozycki  <macro@linux-mips.org>
 
        * config/tc-mips.c (append_insn): Handle constant expressions with
index 2dd834e..e73aa95 100644 (file)
@@ -1922,15 +1922,13 @@ optimize_imm ()
                i.types[op] = Imm64 | Imm32S;
                break;
              case LONG_MNEM_SUFFIX:
-               i.types[op] = Imm32 | Imm64;
+               i.types[op] = Imm32;
                break;
              case WORD_MNEM_SUFFIX:
-               i.types[op] = Imm16 | Imm32 | Imm64;
-               break;
+               i.types[op] = Imm16;
                break;
              case BYTE_MNEM_SUFFIX:
-               i.types[op] = Imm8 | Imm8S | Imm16 | Imm32S | Imm32;
-               break;
+               i.types[op] = Imm8 | Imm8S;
                break;
              }
            break;
@@ -2018,9 +2016,18 @@ match_template ()
                              : (i.suffix == LONG_DOUBLE_MNEM_SUFFIX
                                 ? No_xSuf : 0))))));
 
-  for (t = current_templates->start;
-       t < current_templates->end;
-       t++)
+  t = current_templates->start;
+  if (i.suffix == QWORD_MNEM_SUFFIX
+      && flag_code != CODE_64BIT
+      && (!intel_syntax
+         || (!(t->opcode_modifier & IgnoreSize)
+             && ! intel_float_operand (t->name)))
+      && (!(t->operand_types[0] & (RegMMX | RegXMM))
+         || !(t->operand_types[t->operands > 1] & (RegMMX | RegXMM)))
+      && (t->base_opcode != 0x0fc7
+         || t->extension_opcode != 1 /* cmpxchg8b */))
+    t = current_templates->end;
+  for (; t < current_templates->end; t++)
     {
       /* Must have right number of operands.  */
       if (i.operands != t->operands)
@@ -2504,7 +2511,7 @@ finalize_imm ()
   unsigned int overlap0, overlap1, overlap2;
 
   overlap0 = i.types[0] & i.tm.operand_types[0];
-  if ((overlap0 & (Imm8 | Imm8S | Imm16 | Imm32 | Imm32S))
+  if ((overlap0 & (Imm8 | Imm8S | Imm16 | Imm32 | Imm32S | Imm64))
       && overlap0 != Imm8 && overlap0 != Imm8S
       && overlap0 != Imm16 && overlap0 != Imm32S
       && overlap0 != Imm32 && overlap0 != Imm64)
@@ -2733,21 +2740,7 @@ build_modrm_byte ()
              if (i.index_reg == 0)
                {
                  /* Operand is just <disp>  */
-                 if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0)
-                     && (flag_code != CODE_64BIT))
-                   {
-                     i.rm.regmem = NO_BASE_REGISTER_16;
-                     i.types[op] &= ~Disp;
-                     i.types[op] |= Disp16;
-                   }
-                 else if (flag_code != CODE_64BIT
-                          || (i.prefix[ADDR_PREFIX] != 0))
-                   {
-                     i.rm.regmem = NO_BASE_REGISTER;
-                     i.types[op] &= ~Disp;
-                     i.types[op] |= Disp32;
-                   }
-                 else
+                 if (flag_code == CODE_64BIT)
                    {
                      /* 64bit mode overwrites the 32bit absolute
                         addressing by RIP relative addressing and
@@ -2756,8 +2749,17 @@ build_modrm_byte ()
                      i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
                      i.sib.base = NO_BASE_REGISTER;
                      i.sib.index = NO_INDEX_REGISTER;
-                     i.types[op] &= ~Disp;
-                     i.types[op] |= Disp32S;
+                     i.types[op] = ((i.prefix[ADDR_PREFIX] == 0) ? Disp32S : Disp32);
+                   }
+                 else if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0))
+                   {
+                     i.rm.regmem = NO_BASE_REGISTER_16;
+                     i.types[op] = Disp16;
+                   }
+                 else
+                   {
+                     i.rm.regmem = NO_BASE_REGISTER;
+                     i.types[op] = Disp32;
                    }
                }
              else /* !i.base_reg && i.index_reg  */
@@ -2779,9 +2781,11 @@ build_modrm_byte ()
          else if (i.base_reg->reg_type == BaseIndex)
            {
              i.rm.regmem = NO_BASE_REGISTER;
-             i.types[op] &= ~Disp;
+             i.types[op] &= ~ Disp;
              i.types[op] |= Disp32S;
              i.flags[op] = Operand_PCrel;
+             if (! i.disp_operands)
+               fake_zero_displacement = 1;
            }
          else if (i.base_reg->reg_type & Reg16)
            {
@@ -2817,12 +2821,8 @@ build_modrm_byte ()
            {
              if (flag_code == CODE_64BIT
                  && (i.types[op] & Disp))
-               {
-                 if (i.types[op] & Disp8)
-                   i.types[op] = Disp8 | Disp32S;
-                 else
-                   i.types[op] = Disp32S;
-               }
+               i.types[op] = (i.types[op] & Disp8) | (i.prefix[ADDR_PREFIX] == 0 ? Disp32S : Disp32);
+
              i.rm.regmem = i.base_reg->reg_num;
              if ((i.base_reg->reg_flags & RegRex) != 0)
                i.rex |= REX_EXTZ;
@@ -3999,30 +3999,18 @@ i386_index_check (operand_string)
  tryprefix:
 #endif
   ok = 1;
-  if (flag_code == CODE_64BIT)
-    {
-      if (i.prefix[ADDR_PREFIX] == 0)
-       {
-         /* 64bit checks.  */
-         if ((i.base_reg
-              && ((i.base_reg->reg_type & Reg64) == 0)
-                  && (i.base_reg->reg_type != BaseIndex
-                      || i.index_reg))
-             || (i.index_reg
-                 && ((i.index_reg->reg_type & (Reg64 | BaseIndex))
-                     != (Reg64 | BaseIndex))))
-           ok = 0;
-       }
-      else
-       {
-         /* 32bit checks.  */
-         if ((i.base_reg
-              && (i.base_reg->reg_type & (Reg32 | RegRex)) != Reg32)
-             || (i.index_reg
-                 && ((i.index_reg->reg_type & (Reg32 | BaseIndex | RegRex))
-                     != (Reg32 | BaseIndex))))
-           ok = 0;
-       }
+   if (flag_code == CODE_64BIT)
+     {
+       unsigned RegXX = (i.prefix[ADDR_PREFIX] == 0 ? Reg64 : Reg32);
+
+       if ((i.base_reg
+           && ((i.base_reg->reg_type & RegXX) == 0)
+           && (i.base_reg->reg_type != BaseIndex
+               || i.index_reg))
+          || (i.index_reg
+              && ((i.index_reg->reg_type & (RegXX | BaseIndex))
+                  != (RegXX | BaseIndex))))
+        ok = 0;
     }
   else
     {
@@ -4055,8 +4043,7 @@ i386_index_check (operand_string)
   if (!ok)
     {
 #if INFER_ADDR_PREFIX
-      if (flag_code != CODE_64BIT
-         && i.prefix[ADDR_PREFIX] == 0 && stackop_size != '\0')
+      if (i.prefix[ADDR_PREFIX] == 0)
        {
          i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;
          i.prefixes += 1;
@@ -4065,7 +4052,7 @@ i386_index_check (operand_string)
             FIXME.  There doesn't seem to be any real need for separate
             Disp16 and Disp32 flags.  The same goes for Imm16 and Imm32.
             Removing them would probably clean up the code quite a lot.  */
-         if (i.types[this_operand] & (Disp16 | Disp32))
+         if (flag_code != CODE_64BIT && (i.types[this_operand] & (Disp16 | Disp32)))
             i.types[this_operand] ^= (Disp16 | Disp32);
          fudged = 1;
          goto tryprefix;
@@ -4078,9 +4065,8 @@ i386_index_check (operand_string)
        as_bad (_("`%s' is not a valid %s bit base/index expression"),
                operand_string,
                flag_code_names[flag_code]);
-      return 0;
     }
-  return 1;
+  return ok;
 }
 
 /* Parse OPERAND_STRING into the i386_insn structure I.  Returns non-zero
@@ -4904,11 +4890,9 @@ parse_register (reg_string, end_op)
     }
 
   if (r != NULL
-      && (r->reg_flags & (RegRex64 | RegRex)) != 0
+      && ((r->reg_flags & (RegRex64 | RegRex)) | (r->reg_type & Reg64)) != 0
       && flag_code != CODE_64BIT)
-    {
-      return (const reg_entry *) NULL;
-    }
+    return (const reg_entry *) NULL;
 
   return r;
 }
index 81027e4..e5689e6 100644 (file)
@@ -1,3 +1,11 @@
+2004-07-21  Jan Beulich <jbeulich@novell.com>
+
+       * testsuite/gas/i386/x86-64-addr32.[ds]: New test for x86-64
+       32-bit addressing in 64-bit mode.
+       * testsuite/gas/i386/x86-64-rip.[ds]: New test for x86-64
+       rip-relative addressing.
+       * testsuite/gas/i386/i386.exp: Run the two new tests.
+
 2004-07-20  Maciej W. Rozycki  <macro@linux-mips.org>
 
        * gas/mips/elf-rel19.d: Pass -march=mips1 to gas as the test
index 1b8c401..bfd7cd5 100644 (file)
@@ -105,7 +105,9 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check]] t
     set ASFLAGS "$ASFLAGS --64"
 
     run_dump_test "x86_64"
+    run_dump_test "x86-64-addr32"
     run_dump_test "x86-64-opcode"
+    run_dump_test "x86-64-rip"
     run_list_test "x86-64-inval" "-al"
 
     set ASFLAGS "$old_ASFLAGS"
diff --git a/gas/testsuite/gas/i386/x86-64-addr32.d b/gas/testsuite/gas/i386/x86-64-addr32.d
new file mode 100644 (file)
index 0000000..c892fb1
--- /dev/null
@@ -0,0 +1,13 @@
+#as: -J
+#objdump: -drw
+#name: x86-64 32-bit addressing
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .text:
+
+0+000 <.text>:
+[       ]*0:[   ]+67 48 8d 80 00 00 00 00[      ]+addr32[       ]+lea[         ]+0x0\(%[re]ax\),%rax.*
+[       ]*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.*
diff --git a/gas/testsuite/gas/i386/x86-64-addr32.s b/gas/testsuite/gas/i386/x86-64-addr32.s
new file mode 100644 (file)
index 0000000..d18cbb9
--- /dev/null
@@ -0,0 +1,5 @@
+.text
+       lea             symbol(%eax), %rax
+       lea             symbol(%r8d), %rax
+       addr32 lea      symbol(%rip), %rax
+       addr32 lea      symbol, %rax
diff --git a/gas/testsuite/gas/i386/x86-64-rip.d b/gas/testsuite/gas/i386/x86-64-rip.d
new file mode 100644 (file)
index 0000000..1b1d6c8
--- /dev/null
@@ -0,0 +1,13 @@
+#as: -J
+#objdump: -drw
+#name: x86-64 rip addressing
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .text:
+
+0+000 <.text>:
+[       ]*0:[   ]+8d 05 00 00 00 00[    ]+lea[  ]+0\(%rip\),%eax[      ]*(#.*)?
+[       ]*6:[   ]+8d 05 11 11 11 11[    ]+lea[  ]+286331153\(%rip\),%eax[      ]*(#.*)?
+[       ]*c:[   ]+8d 05 01 00 00 00[    ]+lea[  ]+1\(%rip\),%eax[      ]*(#.*)?
+[       ]*12:[  ]+8d 05 00 00 00 00[    ]+lea[  ]+0\(%rip\),%eax[      ]*(#.*)?
diff --git a/gas/testsuite/gas/i386/x86-64-rip.s b/gas/testsuite/gas/i386/x86-64-rip.s
new file mode 100644 (file)
index 0000000..c6ac195
--- /dev/null
@@ -0,0 +1,5 @@
+.text
+       leal    symbol(%rip), %eax
+       leal    0x11111111(%rip), %eax
+       leal    1(%rip), %eax
+       leal    (%rip), %eax
index 1af2278..dd4526b 100644 (file)
@@ -37,7 +37,7 @@ Disassembly of section .text:
 [      ]+5a:   44 0f 20 c0[    ]+mov[  ]+%cr8,%rax
 [      ]+5e:   44 0f 22 c0[    ]+mov[  ]+%rax,%cr8
 [      ]+62:   f3 48 a5[       ]+repz movsq %ds:\(%rsi\),%es:\(%rdi\)
-[      ]+65:   f3 66 a5[       ]+repz movsw %ds:\(%esi\),%es:\(%edi\)
+[      ]+65:   f3 66 a5[       ]+repz movsw %ds:\(%rsi\),%es:\(%rdi\)
 [      ]+68:   f3 48 a5[       ]+repz movsq %ds:\(%rsi\),%es:\(%rdi\)
 [      ]+6b:   b0 11[  ]+mov[  ]+\$0x11,%al
 [      ]+6d:   b4 11[  ]+mov[  ]+\$0x11,%ah
index 23f2e1d..65fd78c 100644 (file)
@@ -1,3 +1,12 @@
+2004-07-21  Jan Beulich <jbeulich@novell.com>
+
+       * i386-dis.c (OP_E): Show rip-relative addressing in 64-bit mode
+       regardless of address size prefix in effect.
+       (ptr_reg): Size or address registers does not depend on rex64, but
+       on the presence of an address size override.
+       (OP_MMX): Use rex.x only for xmm registers.
+       (OP_EM): Use rex.z only for xmm registers.
+
 2004-07-20  Maciej W. Rozycki  <macro@linux-mips.org>
 
        * mips-opc.c (mips_builtin_opcodes): Move coprocessor 2
index 0bcd107..733267c 100644 (file)
@@ -2,38 +2,34 @@
    Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
    2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
-This file is part of GDB.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-/*
- * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
- * July 1988
- *  modified by John Hassey (hassey@dg-rtp.dg.com)
- *  x86-64 support added by Jan Hubicka (jh@suse.cz)
- *  VIA PadLock support by Michal Ludvig (mludvig@suse.cz)
- */
-
-/*
- * The main tables describing the instructions is essentially a copy
- * of the "Opcode Map" chapter (Appendix A) of the Intel 80386
- * Programmers Manual.  Usually, there is a capital letter, followed
- * by a small letter.  The capital letter tell the addressing mode,
- * and the small letter tells about the operand size.  Refer to
- * the Intel manual for details.
- */
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
+   July 1988
+    modified by John Hassey (hassey@dg-rtp.dg.com)
+    x86-64 support added by Jan Hubicka (jh@suse.cz)
+    VIA PadLock support by Michal Ludvig (mludvig@suse.cz).  */
+
+/* The main tables describing the instructions is essentially a copy
+   of the "Opcode Map" chapter (Appendix A) of the Intel 80386
+   Programmers Manual.  Usually, there is a capital letter, followed
+   by a small letter.  The capital letter tell the addressing mode,
+   and the small letter tells about the operand size.  Refer to
+   the Intel manual for details.  */
 
 #include "dis-asm.h"
 #include "sysdep.h"
@@ -3166,7 +3162,7 @@ OP_E (int bytemode, int sizeflag)
          if ((base & 7) == 5)
            {
              havebase = 0;
-             if (mode_64bit && !havesib && (sizeflag & AFLAG))
+             if (mode_64bit && !havesib)
                riprel = 1;
              disp = get32s ();
            }
@@ -3856,8 +3852,8 @@ ptr_reg (int code, int sizeflag)
   const char *s;
 
   *obufp++ = open_char;
-  USED_REX (REX_MODE64);
-  if (rex & REX_MODE64)
+  used_prefixes |= (prefixes & PREFIX_ADDR);
+  if (mode_64bit)
     {
       if (!(sizeflag & AFLAG))
        s = names32[code - eAX_reg];
@@ -3939,15 +3935,17 @@ OP_Rd (int bytemode, int sizeflag)
 static void
 OP_MMX (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
 {
-  int add = 0;
-  USED_REX (REX_EXTX);
-  if (rex & REX_EXTX)
-    add = 8;
   used_prefixes |= (prefixes & PREFIX_DATA);
   if (prefixes & PREFIX_DATA)
-    sprintf (scratchbuf, "%%xmm%d", reg + add);
+    {
+      int add = 0;
+      USED_REX (REX_EXTX);
+      if (rex & REX_EXTX)
+       add = 8;
+      sprintf (scratchbuf, "%%xmm%d", reg + add);
+    }
   else
-    sprintf (scratchbuf, "%%mm%d", reg + add);
+    sprintf (scratchbuf, "%%mm%d", reg);
   oappend (scratchbuf + intel_syntax);
 }
 
@@ -3965,24 +3963,27 @@ OP_XMM (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
 static void
 OP_EM (int bytemode, int sizeflag)
 {
-  int add = 0;
   if (mod != 3)
     {
       OP_E (bytemode, sizeflag);
       return;
     }
-  USED_REX (REX_EXTZ);
-  if (rex & REX_EXTZ)
-    add = 8;
 
   /* Skip mod/rm byte.  */
   MODRM_CHECK;
   codep++;
   used_prefixes |= (prefixes & PREFIX_DATA);
   if (prefixes & PREFIX_DATA)
-    sprintf (scratchbuf, "%%xmm%d", rm + add);
+    {
+      int add = 0;
+
+      USED_REX (REX_EXTZ);
+      if (rex & REX_EXTZ)
+       add = 8;
+      sprintf (scratchbuf, "%%xmm%d", rm + add);
+    }
   else
-    sprintf (scratchbuf, "%%mm%d", rm + add);
+    sprintf (scratchbuf, "%%mm%d", rm);
   oappend (scratchbuf + intel_syntax);
 }