This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[PATCH] x86-64 corrections
- From: "Jan Beulich" <JBeulich at novell dot com>
- To: <binutils at sources dot redhat dot com>
- Date: Thu, 03 Jun 2004 17:31:16 +0200
- Subject: [PATCH] x86-64 corrections
2004-06-03 Jan Beulich <jbeulich@novell.com>
* gas/config/tc-i386.c: Adjust immediates to only those
permissible for
the selected instruction suffix. Don't treat 32-bit addressing
in
64-bit mode specially except for the width of the used base
and/or
index registers. Force zero displacement on rip-relative
addressing
when there is no other displacement.
* opcodes/i386-dis.c: Show rip-relative addressing in 64-bit
mode
regardless of address size prefix in effect.
* gas/testsuite/gas/i386/x86-64-addr32.[ds]: New test for
x86-64
32-bit addressing in 64-bit mode.
* gas/testsuite/gas/i386/x86-64-rip.[ds]: New test for x86-64
rip-relative addressing.
* gas/testsuite/gas/i386/i386.exp: Run the two new tests.
---
/home/jbeulich/src/binutils/mainline/2004-06-03.09.12/gas/config/tc-i386.c 2004-04-20
14:17:14.000000000 +0200
+++ 2004-06-03.09.12/gas/config/tc-i386.c 2004-06-03
10:22:33.663347560 +0200
@@ -1914,15 +1930,13 @@
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;
@@ -2496,7 +2516,7 @@
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)
@@ -2529,7 +2549,7 @@
i.types[0] = overlap0;
overlap1 = i.types[1] & i.tm.operand_types[1];
- if ((overlap1 & (Imm8 | Imm8S | Imm16 | Imm32S | Imm32))
+ if ((overlap1 & (Imm8 | Imm8S | Imm16 | Imm32S | Imm32 | Imm64))
&& overlap1 != Imm8 && overlap1 != Imm8S
&& overlap1 != Imm16 && overlap1 != Imm32S
&& overlap1 != Imm32 && overlap1 != Imm64)
@@ -2725,21 +2745,7 @@
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
@@ -2748,8 +2754,17 @@
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 */
@@ -2774,6 +2789,8 @@
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)
{
@@ -2810,10 +2827,7 @@
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)
@@ -3993,28 +4007,16 @@
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;
- }
+ 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
{
@@ -4047,8 +4049,7 @@
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;
@@ -4057,7 +4058,7 @@
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;
@@ -4070,9 +4071,8 @@
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
---
/home/jbeulich/src/binutils/mainline/2004-06-03.09.12/gas/testsuite/gas/i386/i386.exp 2004-05-12
05:06:10.000000000 +0200
+++ 2004-06-03.09.12/gas/testsuite/gas/i386/i386.exp 2004-06-03
10:19:33.595722000 +0200
@@ -105,7 +105,9 @@
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"
---
/home/jbeulich/src/binutils/mainline/2004-06-03.09.12/gas/testsuite/gas/i386/x86-64-addr32.d 1970-01-01
01:00:00.000000000 +0100
+++
2004-06-03.09.12/gas/testsuite/gas/i386/x86-64-addr32.d 2004-06-02
14:45:09.000000000 +0200
@@ -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.*
---
/home/jbeulich/src/binutils/mainline/2004-06-03.09.12/gas/testsuite/gas/i386/x86-64-addr32.s 1970-01-01
01:00:00.000000000 +0100
+++
2004-06-03.09.12/gas/testsuite/gas/i386/x86-64-addr32.s 2004-06-02
14:05:47.000000000 +0200
@@ -0,0 +1,5 @@
+.text
+ lea symbol(%eax), %rax
+ lea symbol(%r8d), %rax
+ addr32 lea symbol(%rip), %rax
+ addr32 lea symbol, %rax
---
/home/jbeulich/src/binutils/mainline/2004-06-03.09.12/gas/testsuite/gas/i386/x86-64-rip.d 1970-01-01
01:00:00.000000000 +0100
+++
2004-06-03.09.12/gas/testsuite/gas/i386/x86-64-rip.d 2004-06-02
14:13:16.000000000 +0200
@@ -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[
]*(#.*)?
---
/home/jbeulich/src/binutils/mainline/2004-06-03.09.12/gas/testsuite/gas/i386/x86-64-rip.s 1970-01-01
01:00:00.000000000 +0100
+++
2004-06-03.09.12/gas/testsuite/gas/i386/x86-64-rip.s 2004-06-02
12:00:40.000000000 +0200
@@ -0,0 +1,5 @@
+.text
+ leal symbol(%rip), %eax
+ leal 0x11111111(%rip), %eax
+ leal 1(%rip), %eax
+ leal (%rip), %eax
---
/home/jbeulich/src/binutils/mainline/2004-06-03.09.12/opcodes/i386-dis.c 2004-03-12
14:38:16.000000000 +0100
+++ 2004-06-03.09.12/opcodes/i386-dis.c 2004-06-03
10:20:39.466708088 +0200
@@ -3094,7 +3096,7 @@
if ((base & 7) == 5)
{
havebase = 0;
- if (mode_64bit && !havesib && (sizeflag & AFLAG))
+ if (mode_64bit && !havesib)
riprel = 1;
disp = get32s ();
}