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>
* config/tc-mips.c (append_insn): Handle constant expressions with

View 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;
}

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>
* 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"
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"

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
[ ]+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

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>
* 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,
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
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 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.
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. */
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)
*/
/* 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.
*/
/* 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);
}