aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2004-07-21 16:09:43 +0000
committerNick Clifton <nickc@redhat.com>2004-07-21 16:09:43 +0000
commit20f0a1fc7d3349b326456c16297278dccd2686c9 (patch)
tree02a9ff6b646204104f6a3e3701f22dd7124cac4f /gas
parent93a64231435694f18eaf109859cca2e8225f94e3 (diff)
downloadgdb-20f0a1fc7d3349b326456c16297278dccd2686c9.zip
gdb-20f0a1fc7d3349b326456c16297278dccd2686c9.tar.gz
gdb-20f0a1fc7d3349b326456c16297278dccd2686c9.tar.bz2
Corrections for x86_64 assembly.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog18
-rw-r--r--gas/config/tc-i386.c116
-rw-r--r--gas/testsuite/ChangeLog8
-rw-r--r--gas/testsuite/gas/i386/i386.exp2
-rw-r--r--gas/testsuite/gas/i386/x86-64-addr32.d13
-rw-r--r--gas/testsuite/gas/i386/x86-64-addr32.s5
-rw-r--r--gas/testsuite/gas/i386/x86-64-rip.d13
-rw-r--r--gas/testsuite/gas/i386/x86-64-rip.s5
-rw-r--r--gas/testsuite/gas/i386/x86_64.d2
9 files changed, 115 insertions, 67 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 33ac7fc..977d0d9 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 2dd834e..e73aa95 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -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;
}
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index 81027e4..e5689e6 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -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
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index 1b8c401..bfd7cd5 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -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
index 0000000..c892fb1
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-addr32.d
@@ -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
index 0000000..d18cbb9
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-addr32.s
@@ -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
index 0000000..1b1d6c8
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-rip.d
@@ -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
index 0000000..c6ac195
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-rip.s
@@ -0,0 +1,5 @@
+.text
+ leal symbol(%rip), %eax
+ leal 0x11111111(%rip), %eax
+ leal 1(%rip), %eax
+ leal (%rip), %eax
diff --git a/gas/testsuite/gas/i386/x86_64.d b/gas/testsuite/gas/i386/x86_64.d
index 1af2278..dd4526b 100644
--- a/gas/testsuite/gas/i386/x86_64.d
+++ b/gas/testsuite/gas/i386/x86_64.d
@@ -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