Corrections for x86_64 assembly.

This commit is contained in:
Nick Clifton 2004-07-21 16:09:43 +00:00
parent 93a6423143
commit 20f0a1fc7d
11 changed files with 167 additions and 109 deletions

View 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> 2004-07-20 Maciej W. Rozycki <macro@linux-mips.org>
* config/tc-mips.c (append_insn): Handle constant expressions with * config/tc-mips.c (append_insn): Handle constant expressions with

View file

@ -1922,15 +1922,13 @@ optimize_imm ()
i.types[op] = Imm64 | Imm32S; i.types[op] = Imm64 | Imm32S;
break; break;
case LONG_MNEM_SUFFIX: case LONG_MNEM_SUFFIX:
i.types[op] = Imm32 | Imm64; i.types[op] = Imm32;
break; break;
case WORD_MNEM_SUFFIX: case WORD_MNEM_SUFFIX:
i.types[op] = Imm16 | Imm32 | Imm64; i.types[op] = Imm16;
break;
break; break;
case BYTE_MNEM_SUFFIX: case BYTE_MNEM_SUFFIX:
i.types[op] = Imm8 | Imm8S | Imm16 | Imm32S | Imm32; i.types[op] = Imm8 | Imm8S;
break;
break; break;
} }
break; break;
@ -2018,9 +2016,18 @@ match_template ()
: (i.suffix == LONG_DOUBLE_MNEM_SUFFIX : (i.suffix == LONG_DOUBLE_MNEM_SUFFIX
? No_xSuf : 0)))))); ? No_xSuf : 0))))));
for (t = current_templates->start; t = current_templates->start;
t < current_templates->end; if (i.suffix == QWORD_MNEM_SUFFIX
t++) && 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. */ /* Must have right number of operands. */
if (i.operands != t->operands) if (i.operands != t->operands)
@ -2504,7 +2511,7 @@ finalize_imm ()
unsigned int overlap0, overlap1, overlap2; unsigned int overlap0, overlap1, overlap2;
overlap0 = i.types[0] & i.tm.operand_types[0]; 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 != Imm8 && overlap0 != Imm8S
&& overlap0 != Imm16 && overlap0 != Imm32S && overlap0 != Imm16 && overlap0 != Imm32S
&& overlap0 != Imm32 && overlap0 != Imm64) && overlap0 != Imm32 && overlap0 != Imm64)
@ -2733,21 +2740,7 @@ build_modrm_byte ()
if (i.index_reg == 0) if (i.index_reg == 0)
{ {
/* Operand is just <disp> */ /* Operand is just <disp> */
if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0) if (flag_code == CODE_64BIT)
&& (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
{ {
/* 64bit mode overwrites the 32bit absolute /* 64bit mode overwrites the 32bit absolute
addressing by RIP relative addressing and addressing by RIP relative addressing and
@ -2756,8 +2749,17 @@ build_modrm_byte ()
i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
i.sib.base = NO_BASE_REGISTER; i.sib.base = NO_BASE_REGISTER;
i.sib.index = NO_INDEX_REGISTER; i.sib.index = NO_INDEX_REGISTER;
i.types[op] &= ~Disp; i.types[op] = ((i.prefix[ADDR_PREFIX] == 0) ? Disp32S : Disp32);
i.types[op] |= Disp32S; }
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 */ else /* !i.base_reg && i.index_reg */
@ -2779,9 +2781,11 @@ build_modrm_byte ()
else if (i.base_reg->reg_type == BaseIndex) else if (i.base_reg->reg_type == BaseIndex)
{ {
i.rm.regmem = NO_BASE_REGISTER; i.rm.regmem = NO_BASE_REGISTER;
i.types[op] &= ~Disp; i.types[op] &= ~ Disp;
i.types[op] |= Disp32S; i.types[op] |= Disp32S;
i.flags[op] = Operand_PCrel; i.flags[op] = Operand_PCrel;
if (! i.disp_operands)
fake_zero_displacement = 1;
} }
else if (i.base_reg->reg_type & Reg16) else if (i.base_reg->reg_type & Reg16)
{ {
@ -2817,12 +2821,8 @@ build_modrm_byte ()
{ {
if (flag_code == CODE_64BIT if (flag_code == CODE_64BIT
&& (i.types[op] & Disp)) && (i.types[op] & Disp))
{ i.types[op] = (i.types[op] & Disp8) | (i.prefix[ADDR_PREFIX] == 0 ? Disp32S : Disp32);
if (i.types[op] & Disp8)
i.types[op] = Disp8 | Disp32S;
else
i.types[op] = Disp32S;
}
i.rm.regmem = i.base_reg->reg_num; i.rm.regmem = i.base_reg->reg_num;
if ((i.base_reg->reg_flags & RegRex) != 0) if ((i.base_reg->reg_flags & RegRex) != 0)
i.rex |= REX_EXTZ; i.rex |= REX_EXTZ;
@ -3999,30 +3999,18 @@ i386_index_check (operand_string)
tryprefix: tryprefix:
#endif #endif
ok = 1; ok = 1;
if (flag_code == CODE_64BIT) if (flag_code == CODE_64BIT)
{ {
if (i.prefix[ADDR_PREFIX] == 0) unsigned RegXX = (i.prefix[ADDR_PREFIX] == 0 ? Reg64 : Reg32);
{
/* 64bit checks. */ if ((i.base_reg
if ((i.base_reg && ((i.base_reg->reg_type & RegXX) == 0)
&& ((i.base_reg->reg_type & Reg64) == 0) && (i.base_reg->reg_type != BaseIndex
&& (i.base_reg->reg_type != BaseIndex || i.index_reg))
|| i.index_reg)) || (i.index_reg
|| (i.index_reg && ((i.index_reg->reg_type & (RegXX | BaseIndex))
&& ((i.index_reg->reg_type & (Reg64 | BaseIndex)) != (RegXX | BaseIndex))))
!= (Reg64 | BaseIndex)))) ok = 0;
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;
}
} }
else else
{ {
@ -4055,8 +4043,7 @@ i386_index_check (operand_string)
if (!ok) if (!ok)
{ {
#if INFER_ADDR_PREFIX #if INFER_ADDR_PREFIX
if (flag_code != CODE_64BIT if (i.prefix[ADDR_PREFIX] == 0)
&& i.prefix[ADDR_PREFIX] == 0 && stackop_size != '\0')
{ {
i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE; i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;
i.prefixes += 1; i.prefixes += 1;
@ -4065,7 +4052,7 @@ i386_index_check (operand_string)
FIXME. There doesn't seem to be any real need for separate FIXME. There doesn't seem to be any real need for separate
Disp16 and Disp32 flags. The same goes for Imm16 and Imm32. Disp16 and Disp32 flags. The same goes for Imm16 and Imm32.
Removing them would probably clean up the code quite a lot. */ 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); i.types[this_operand] ^= (Disp16 | Disp32);
fudged = 1; fudged = 1;
goto tryprefix; goto tryprefix;
@ -4078,9 +4065,8 @@ i386_index_check (operand_string)
as_bad (_("`%s' is not a valid %s bit base/index expression"), as_bad (_("`%s' is not a valid %s bit base/index expression"),
operand_string, operand_string,
flag_code_names[flag_code]); flag_code_names[flag_code]);
return 0;
} }
return 1; return ok;
} }
/* Parse OPERAND_STRING into the i386_insn structure I. Returns non-zero /* 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 if (r != NULL
&& (r->reg_flags & (RegRex64 | RegRex)) != 0 && ((r->reg_flags & (RegRex64 | RegRex)) | (r->reg_type & Reg64)) != 0
&& flag_code != CODE_64BIT) && flag_code != CODE_64BIT)
{ return (const reg_entry *) NULL;
return (const reg_entry *) NULL;
}
return r; return r;
} }

View 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> 2004-07-20 Maciej W. Rozycki <macro@linux-mips.org>
* gas/mips/elf-rel19.d: Pass -march=mips1 to gas as the test * gas/mips/elf-rel19.d: Pass -march=mips1 to gas as the test

View file

@ -105,7 +105,9 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check]] t
set ASFLAGS "$ASFLAGS --64" set ASFLAGS "$ASFLAGS --64"
run_dump_test "x86_64" run_dump_test "x86_64"
run_dump_test "x86-64-addr32"
run_dump_test "x86-64-opcode" run_dump_test "x86-64-opcode"
run_dump_test "x86-64-rip"
run_list_test "x86-64-inval" "-al" run_list_test "x86-64-inval" "-al"
set ASFLAGS "$old_ASFLAGS" set ASFLAGS "$old_ASFLAGS"

View file

@ -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.*

View file

@ -0,0 +1,5 @@
.text
lea symbol(%eax), %rax
lea symbol(%r8d), %rax
addr32 lea symbol(%rip), %rax
addr32 lea symbol, %rax

View file

@ -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[ ]*(#.*)?

View file

@ -0,0 +1,5 @@
.text
leal symbol(%rip), %eax
leal 0x11111111(%rip), %eax
leal 1(%rip), %eax
leal (%rip), %eax

View file

@ -37,7 +37,7 @@ Disassembly of section .text:
[ ]+5a: 44 0f 20 c0[ ]+mov[ ]+%cr8,%rax [ ]+5a: 44 0f 20 c0[ ]+mov[ ]+%cr8,%rax
[ ]+5e: 44 0f 22 c0[ ]+mov[ ]+%rax,%cr8 [ ]+5e: 44 0f 22 c0[ ]+mov[ ]+%rax,%cr8
[ ]+62: f3 48 a5[ ]+repz movsq %ds:\(%rsi\),%es:\(%rdi\) [ ]+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\) [ ]+68: f3 48 a5[ ]+repz movsq %ds:\(%rsi\),%es:\(%rdi\)
[ ]+6b: b0 11[ ]+mov[ ]+\$0x11,%al [ ]+6b: b0 11[ ]+mov[ ]+\$0x11,%al
[ ]+6d: b4 11[ ]+mov[ ]+\$0x11,%ah [ ]+6d: b4 11[ ]+mov[ ]+\$0x11,%ah

View 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> 2004-07-20 Maciej W. Rozycki <macro@linux-mips.org>
* mips-opc.c (mips_builtin_opcodes): Move coprocessor 2 * mips-opc.c (mips_builtin_opcodes): Move coprocessor 2

View file

@ -2,38 +2,34 @@
Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
2001, 2002, 2003, 2004 Free Software Foundation, Inc. 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GDB. This file is part of GDB.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* /* 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
* 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu) July 1988
* July 1988 modified by John Hassey (hassey@dg-rtp.dg.com)
* modified by John Hassey (hassey@dg-rtp.dg.com) x86-64 support added by Jan Hubicka (jh@suse.cz)
* x86-64 support added by Jan Hubicka (jh@suse.cz) VIA PadLock support by Michal Ludvig (mludvig@suse.cz). */
* VIA PadLock support by Michal Ludvig (mludvig@suse.cz)
*/
/* /* The main tables describing the instructions is essentially a copy
* The main tables describing the instructions is essentially a copy of the "Opcode Map" chapter (Appendix A) of the Intel 80386
* of the "Opcode Map" chapter (Appendix A) of the Intel 80386 Programmers Manual. Usually, there is a capital letter, followed
* Programmers Manual. Usually, there is a capital letter, followed by a small letter. The capital letter tell the addressing mode,
* by a small letter. The capital letter tell the addressing mode, and the small letter tells about the operand size. Refer to
* and the small letter tells about the operand size. Refer to the Intel manual for details. */
* the Intel manual for details.
*/
#include "dis-asm.h" #include "dis-asm.h"
#include "sysdep.h" #include "sysdep.h"
@ -3166,7 +3162,7 @@ OP_E (int bytemode, int sizeflag)
if ((base & 7) == 5) if ((base & 7) == 5)
{ {
havebase = 0; havebase = 0;
if (mode_64bit && !havesib && (sizeflag & AFLAG)) if (mode_64bit && !havesib)
riprel = 1; riprel = 1;
disp = get32s (); disp = get32s ();
} }
@ -3856,8 +3852,8 @@ ptr_reg (int code, int sizeflag)
const char *s; const char *s;
*obufp++ = open_char; *obufp++ = open_char;
USED_REX (REX_MODE64); used_prefixes |= (prefixes & PREFIX_ADDR);
if (rex & REX_MODE64) if (mode_64bit)
{ {
if (!(sizeflag & AFLAG)) if (!(sizeflag & AFLAG))
s = names32[code - eAX_reg]; s = names32[code - eAX_reg];
@ -3939,15 +3935,17 @@ OP_Rd (int bytemode, int sizeflag)
static void static void
OP_MMX (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) 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); used_prefixes |= (prefixes & PREFIX_DATA);
if (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 else
sprintf (scratchbuf, "%%mm%d", reg + add); sprintf (scratchbuf, "%%mm%d", reg);
oappend (scratchbuf + intel_syntax); oappend (scratchbuf + intel_syntax);
} }
@ -3965,24 +3963,27 @@ OP_XMM (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
static void static void
OP_EM (int bytemode, int sizeflag) OP_EM (int bytemode, int sizeflag)
{ {
int add = 0;
if (mod != 3) if (mod != 3)
{ {
OP_E (bytemode, sizeflag); OP_E (bytemode, sizeflag);
return; return;
} }
USED_REX (REX_EXTZ);
if (rex & REX_EXTZ)
add = 8;
/* Skip mod/rm byte. */ /* Skip mod/rm byte. */
MODRM_CHECK; MODRM_CHECK;
codep++; codep++;
used_prefixes |= (prefixes & PREFIX_DATA); used_prefixes |= (prefixes & PREFIX_DATA);
if (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 else
sprintf (scratchbuf, "%%mm%d", rm + add); sprintf (scratchbuf, "%%mm%d", rm);
oappend (scratchbuf + intel_syntax); oappend (scratchbuf + intel_syntax);
} }