* config/tc-i386.h (Seg2ShortForm, Seg3ShortForm): Delete.
	* config/tc-i386.c: Wrap overly long lines, whitespace fixes.
	(process_operands): Move old Seg2ShortForm and Seg3ShortForm
	code, and test for these insns using a combination of
	opcode_modifier and operand_types.
include/opcode/
	* i386.h (i386_optab): Replace all occurrences of Seg2ShortForm
	and Seg3ShortFrom with Shortform.
This commit is contained in:
Alan Modra 2007-02-13 23:23:54 +00:00
parent 97182d3694
commit 4eed87de48
5 changed files with 180 additions and 103 deletions

View File

@ -1,3 +1,11 @@
2007-02-14 Alan Modra <amodra@bigpond.net.au>
* config/tc-i386.h (Seg2ShortForm, Seg3ShortForm): Delete.
* config/tc-i386.c: Wrap overly long lines, whitespace fixes.
(process_operands): Move old Seg2ShortForm and Seg3ShortForm
code, and test for these insns using a combination of
opcode_modifier and operand_types.
2007-02-07 Paul Brook <paul@codesourcery.com>
* configure.tgt: Add arm*-*-uclinux-*eabi.

View File

@ -743,7 +743,8 @@ i386_align_code (fragS *fragP, int count)
1. For PROCESSOR_I486, PROCESSOR_PENTIUM and PROCESSOR_GENERIC32,
f32_patt will be used.
2. For PROCESSOR_K8 and PROCESSOR_AMDFAM10 in 64bit, NOPs with 0x66 prefix will be used.
2. For PROCESSOR_K8 and PROCESSOR_AMDFAM10 in 64bit, NOPs with
0x66 prefix will be used.
3. For PROCESSOR_CORE2, alt_long_patt will be used.
4. For PROCESSOR_PENTIUMPRO, PROCESSOR_PENTIUM4, PROCESSOR_NOCONA,
PROCESSOR_CORE, PROCESSOR_CORE2, PROCESSOR_K6, PROCESSOR_ATHLON
@ -1130,7 +1131,8 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED)
cpu_arch_name = cpu_arch[i].name;
cpu_sub_arch_name = NULL;
cpu_arch_flags = (cpu_arch[i].flags
| (flag_code == CODE_64BIT ? Cpu64 : CpuNo64));
| (flag_code == CODE_64BIT
? Cpu64 : CpuNo64));
cpu_arch_isa = cpu_arch[i].type;
cpu_arch_isa_flags = cpu_arch[i].flags;
if (!cpu_arch_tune_set)
@ -1902,7 +1904,8 @@ md_assemble (line)
{
/* In case it is "hi" register, give up. */
if (i.op[x].regs->reg_num > 3)
as_bad (_("can't encode register '%%%s' in an instruction requiring REX prefix."),
as_bad (_("can't encode register '%%%s' in an "
"instruction requiring REX prefix."),
i.op[x].regs->reg_name);
/* Otherwise it is equivalent to the extended register.
@ -2393,7 +2396,9 @@ optimize_imm (void)
unsigned int mask, allowed = 0;
const template *t;
for (t = current_templates->start; t < current_templates->end; ++t)
for (t = current_templates->start;
t < current_templates->end;
++t)
allowed |= t->operand_types[op];
switch (guess_suffix)
{
@ -2886,7 +2891,8 @@ process_suffix (void)
{
if (i.tm.opcode_modifier & W)
{
as_bad (_("no instruction mnemonic suffix given and no register operands; can't size instruction"));
as_bad (_("no instruction mnemonic suffix given and "
"no register operands; can't size instruction"));
return 0;
}
}
@ -3194,7 +3200,8 @@ finalize_imm (void)
&& overlap0 != Imm16 && overlap0 != Imm32S
&& overlap0 != Imm32 && overlap0 != Imm64)
{
as_bad (_("no instruction mnemonic suffix given; can't determine immediate size"));
as_bad (_("no instruction mnemonic suffix given; "
"can't determine immediate size"));
return 0;
}
}
@ -3227,7 +3234,9 @@ finalize_imm (void)
&& overlap1 != Imm16 && overlap1 != Imm32S
&& overlap1 != Imm32 && overlap1 != Imm64)
{
as_bad (_("no instruction mnemonic suffix given; can't determine immediate size %x %c"),overlap1, i.suffix);
as_bad (_("no instruction mnemonic suffix given; "
"can't determine immediate size %x %c"),
overlap1, i.suffix);
return 0;
}
}
@ -3264,6 +3273,20 @@ process_operands (void)
}
if (i.tm.opcode_modifier & ShortForm)
{
if (i.types[0] & (SReg2 | SReg3))
{
if (i.tm.base_opcode == POP_SEG_SHORT
&& i.op[0].regs->reg_num == 1)
{
as_bad (_("you can't `pop %%cs'"));
return 0;
}
i.tm.base_opcode |= (i.op[0].regs->reg_num << 3);
if ((i.op[0].regs->reg_flags & RegRex) != 0)
i.rex |= REX_EXTZ;
}
else
{
/* The register or float register operand is in operand 0 or 1. */
unsigned int op = (i.types[0] & (Reg | FloatReg)) ? 0 : 1;
@ -3290,6 +3313,7 @@ process_operands (void)
}
}
}
}
else if (i.tm.opcode_modifier & Modrm)
{
/* The opcode is completed (modulo i.tm.extension_opcode which
@ -3298,18 +3322,6 @@ process_operands (void)
default_seg = build_modrm_byte ();
}
else if (i.tm.opcode_modifier & (Seg2ShortForm | Seg3ShortForm))
{
if (i.tm.base_opcode == POP_SEG_SHORT
&& i.op[0].regs->reg_num == 1)
{
as_bad (_("you can't `pop %%cs'"));
return 0;
}
i.tm.base_opcode |= (i.op[0].regs->reg_num << 3);
if ((i.op[0].regs->reg_flags & RegRex) != 0)
i.rex |= REX_EXTZ;
}
else if ((i.tm.base_opcode & ~(D | W)) == MOV_AX_DISP32)
{
default_seg = &ds;
@ -4277,23 +4289,57 @@ lex_got (enum bfd_reloc_code_real *reloc,
const enum bfd_reloc_code_real rel[2];
const unsigned int types64;
} gotrel[] = {
{ "PLTOFF", { 0, BFD_RELOC_X86_64_PLTOFF64 }, Imm64 },
{ "PLT", { BFD_RELOC_386_PLT32, BFD_RELOC_X86_64_PLT32 }, Imm32|Imm32S|Disp32 },
{ "GOTPLT", { 0, BFD_RELOC_X86_64_GOTPLT64 }, Imm64|Disp64 },
{ "GOTOFF", { BFD_RELOC_386_GOTOFF, BFD_RELOC_X86_64_GOTOFF64 }, Imm64|Disp64 },
{ "GOTPCREL", { 0, BFD_RELOC_X86_64_GOTPCREL }, Imm32|Imm32S|Disp32 },
{ "TLSGD", { BFD_RELOC_386_TLS_GD, BFD_RELOC_X86_64_TLSGD }, Imm32|Imm32S|Disp32 },
{ "TLSLDM", { BFD_RELOC_386_TLS_LDM, 0 }, 0 },
{ "TLSLD", { 0, BFD_RELOC_X86_64_TLSLD }, Imm32|Imm32S|Disp32 },
{ "GOTTPOFF", { BFD_RELOC_386_TLS_IE_32, BFD_RELOC_X86_64_GOTTPOFF }, Imm32|Imm32S|Disp32 },
{ "TPOFF", { BFD_RELOC_386_TLS_LE_32, BFD_RELOC_X86_64_TPOFF32 }, Imm32|Imm32S|Imm64|Disp32|Disp64 },
{ "NTPOFF", { BFD_RELOC_386_TLS_LE, 0 }, 0 },
{ "DTPOFF", { BFD_RELOC_386_TLS_LDO_32, BFD_RELOC_X86_64_DTPOFF32 }, Imm32|Imm32S|Imm64|Disp32|Disp64 },
{ "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE, 0 }, 0 },
{ "INDNTPOFF",{ BFD_RELOC_386_TLS_IE, 0 }, 0 },
{ "GOT", { BFD_RELOC_386_GOT32, BFD_RELOC_X86_64_GOT32 }, Imm32|Imm32S|Disp32|Imm64 },
{ "TLSDESC", { BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_X86_64_GOTPC32_TLSDESC }, Imm32|Imm32S|Disp32 },
{ "TLSCALL", { BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_X86_64_TLSDESC_CALL }, Imm32|Imm32S|Disp32 }
{ "PLTOFF", { 0,
BFD_RELOC_X86_64_PLTOFF64 },
Imm64 },
{ "PLT", { BFD_RELOC_386_PLT32,
BFD_RELOC_X86_64_PLT32 },
Imm32 | Imm32S | Disp32 },
{ "GOTPLT", { 0,
BFD_RELOC_X86_64_GOTPLT64 },
Imm64 | Disp64 },
{ "GOTOFF", { BFD_RELOC_386_GOTOFF,
BFD_RELOC_X86_64_GOTOFF64 },
Imm64 | Disp64 },
{ "GOTPCREL", { 0,
BFD_RELOC_X86_64_GOTPCREL },
Imm32 | Imm32S | Disp32 },
{ "TLSGD", { BFD_RELOC_386_TLS_GD,
BFD_RELOC_X86_64_TLSGD },
Imm32 | Imm32S | Disp32 },
{ "TLSLDM", { BFD_RELOC_386_TLS_LDM,
0 },
0 },
{ "TLSLD", { 0,
BFD_RELOC_X86_64_TLSLD },
Imm32 | Imm32S | Disp32 },
{ "GOTTPOFF", { BFD_RELOC_386_TLS_IE_32,
BFD_RELOC_X86_64_GOTTPOFF },
Imm32 | Imm32S | Disp32 },
{ "TPOFF", { BFD_RELOC_386_TLS_LE_32,
BFD_RELOC_X86_64_TPOFF32 },
Imm32 | Imm32S | Imm64 | Disp32 | Disp64 },
{ "NTPOFF", { BFD_RELOC_386_TLS_LE,
0 },
0 },
{ "DTPOFF", { BFD_RELOC_386_TLS_LDO_32,
BFD_RELOC_X86_64_DTPOFF32 },
Imm32 | Imm32S | Imm64 | Disp32 | Disp64 },
{ "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE,
0 },
0 },
{ "INDNTPOFF",{ BFD_RELOC_386_TLS_IE,
0 },
0 },
{ "GOT", { BFD_RELOC_386_GOT32,
BFD_RELOC_X86_64_GOT32 },
Imm32 | Imm32S | Disp32 | Imm64 },
{ "TLSDESC", { BFD_RELOC_386_TLS_GOTDESC,
BFD_RELOC_X86_64_GOTPC32_TLSDESC },
Imm32 | Imm32S | Disp32 },
{ "TLSCALL", { BFD_RELOC_386_TLS_DESC_CALL,
BFD_RELOC_X86_64_TLSDESC_CALL },
Imm32 | Imm32S | Disp32 }
};
char *cp;
unsigned int j;
@ -4483,9 +4529,10 @@ i386_immediate (char *imm_start)
/* Size it properly later. */
i.types[this_operand] |= Imm64;
/* If BFD64, sign extend val. */
if (!use_rela_relocations)
if ((exp->X_add_number & ~(((addressT) 2 << 31) - 1)) == 0)
exp->X_add_number = (exp->X_add_number ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31);
if (!use_rela_relocations
&& (exp->X_add_number & ~(((addressT) 2 << 31) - 1)) == 0)
exp->X_add_number
= (exp->X_add_number ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31);
}
#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
else if (OUTPUT_FLAVOR == bfd_target_aout_flavour
@ -4837,7 +4884,8 @@ i386_index_check (const char *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 (flag_code != CODE_64BIT && (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;
@ -5016,7 +5064,8 @@ i386_operand (char *operand_string)
++base_string;
if (*base_string == ','
|| ((i.base_reg = parse_register (base_string, &end_op)) != NULL))
|| ((i.base_reg = parse_register (base_string, &end_op))
!= NULL))
{
displacement_string_end = temp_string;
@ -5036,7 +5085,8 @@ i386_operand (char *operand_string)
if (is_space_char (*base_string))
++base_string;
if ((i.index_reg = parse_register (base_string, &end_op)) != NULL)
if ((i.index_reg = parse_register (base_string, &end_op))
!= NULL)
{
base_string = end_op;
if (is_space_char (*base_string))
@ -5049,7 +5099,8 @@ i386_operand (char *operand_string)
}
else if (*base_string != ')')
{
as_bad (_("expecting `,' or `)' after index register in `%s'"),
as_bad (_("expecting `,' or `)' "
"after index register in `%s'"),
operand_string);
return 0;
}
@ -5073,21 +5124,24 @@ i386_operand (char *operand_string)
++base_string;
if (*base_string != ')')
{
as_bad (_("expecting `)' after scale factor in `%s'"),
as_bad (_("expecting `)' "
"after scale factor in `%s'"),
operand_string);
return 0;
}
}
else if (!i.index_reg)
{
as_bad (_("expecting index register or scale factor after `,'; got '%c'"),
as_bad (_("expecting index register or scale factor "
"after `,'; got '%c'"),
*base_string);
return 0;
}
}
else if (*base_string != ')')
{
as_bad (_("expecting `,' or `)' after base register in `%s'"),
as_bad (_("expecting `,' or `)' "
"after base register in `%s'"),
operand_string);
return 0;
}
@ -5303,7 +5357,8 @@ md_convert_frag (abfd, sec, fragP)
{
if (no_cond_jump_promotion
&& TYPE_FROM_RELAX_STATE (fragP->fr_subtype) != UNCOND_JUMP)
as_warn_where (fragP->fr_file, fragP->fr_line, _("long jump required"));
as_warn_where (fragP->fr_file, fragP->fr_line,
_("long jump required"));
switch (fragP->fr_subtype)
{
@ -5730,7 +5785,8 @@ parse_register (char *reg_string, char **end_op)
const expressionS *e = symbol_get_value_expression (symbolP);
know (e->X_op == O_register);
know (e->X_add_number >= 0 && (valueT) e->X_add_number < ARRAY_SIZE (i386_regtab));
know (e->X_add_number >= 0
&& (valueT) e->X_add_number < ARRAY_SIZE (i386_regtab));
r = i386_regtab + e->X_add_number;
*end_op = input_line_pointer;
}
@ -6717,7 +6773,9 @@ intel_e05 (void)
if (!intel_e06())
return 0;
if (cur_token.code == '&' || cur_token.code == '|' || cur_token.code == '^')
if (cur_token.code == '&'
|| cur_token.code == '|'
|| cur_token.code == '^')
{
char str[2];
@ -6752,7 +6810,9 @@ intel_e06 (void)
if (!intel_e09())
return 0;
if (cur_token.code == '*' || cur_token.code == '/' || cur_token.code == '%')
if (cur_token.code == '*'
|| cur_token.code == '/'
|| cur_token.code == '%')
{
char str[2];
@ -7064,7 +7124,8 @@ intel_bracket_expr (void)
/* Defer the warning until all of the operand was parsed. */
intel_parser.is_mem = -1;
else if (!quiet_warnings)
as_warn (_("`[%.*s]' taken to mean just `%.*s'"), len, start, len, start);
as_warn (_("`[%.*s]' taken to mean just `%.*s'"),
len, start, len, start);
}
}
intel_parser.op_modifier |= was_offset;
@ -7154,7 +7215,8 @@ intel_e11 (void)
{
if (!(reg->reg_type & (SReg2 | SReg3)))
{
as_bad (_("`%s' is not a valid segment register"), reg->reg_name);
as_bad (_("`%s' is not a valid segment register"),
reg->reg_name);
return 0;
}
else if (i.seg[i.mem_operands])
@ -7344,7 +7406,8 @@ intel_e11 (void)
/* Get the next token to check for register scaling. */
intel_match_token (cur_token.code);
/* Check if this constant is a scaling factor for an index register. */
/* Check if this constant is a scaling factor for an
index register. */
if (cur_token.code == '*')
{
if (intel_match_token ('*') && cur_token.code == T_REG)
@ -7353,14 +7416,17 @@ intel_e11 (void)
if (!intel_parser.in_bracket)
{
as_bad (_("Register scaling only allowed in memory operands"));
as_bad (_("Register scaling only allowed "
"in memory operands"));
return 0;
}
if (reg->reg_type & Reg16) /* Disallow things like [1*si]. */
reg = i386_regtab + REGNAM_AX + 4; /* sp is invalid as index */
/* Disallow things like [1*si].
sp and esp are invalid as index. */
if (reg->reg_type & Reg16)
reg = i386_regtab + REGNAM_AX + 4;
else if (i.index_reg)
reg = i386_regtab + REGNAM_EAX + 4; /* esp is invalid as index */
reg = i386_regtab + REGNAM_EAX + 4;
/* The constant is followed by `* reg', so it must be
a valid scale. */

View File

@ -220,8 +220,6 @@ typedef struct
#define JumpByte 0x100 /* loop and jecxz */
#define JumpInterSegment 0x200 /* special case for intersegment leaps/calls */
#define FloatD 0x400 /* direction for float insns: MUST BE 0x400 */
#define Seg2ShortForm 0x800 /* encoding of load segment reg insns */
#define Seg3ShortForm 0x1000 /* fs/gs segment register insns. */
#define Size16 0x2000 /* needs size prefix if in 32-bit mode */
#define Size32 0x4000 /* needs size prefix if in 16-bit mode */
#define Size64 0x8000 /* needs size prefix if in 64-bit mode */

View File

@ -1,3 +1,8 @@
2007-02-14 Alan Modra <amodra@bigpond.net.au>
* i386.h (i386_optab): Replace all occurrences of Seg2ShortForm
and Seg3ShortFrom with Shortform.
2007-02-11 H.J. Lu <hongjiu.lu@intel.com>
PR gas/4027

View File

@ -1,6 +1,6 @@
/* opcode/i386.h -- Intel 80386 opcode table
Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
2000, 2001, 2002, 2003, 2004, 2005
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler, and GDB, the GNU Debugger.
@ -152,14 +152,14 @@ static const template i386_optab[] =
{"push", 1, 0xff, 6, CpuNo64, wl_Suf|Modrm|DefaultSize, { WordReg|WordMem, 0, 0 } },
{"push", 1, 0x6a, X, Cpu186|CpuNo64, wl_Suf|DefaultSize, { Imm8S, 0, 0} },
{"push", 1, 0x68, X, Cpu186|CpuNo64, wl_Suf|DefaultSize, { Imm16|Imm32, 0, 0} },
{"push", 1, 0x06, X, CpuNo64, wl_Suf|Seg2ShortForm|DefaultSize, { SReg2, 0, 0 } },
{"push", 1, 0x0fa0, X, Cpu386|CpuNo64, wl_Suf|Seg3ShortForm|DefaultSize, { SReg3, 0, 0 } },
{"push", 1, 0x06, X, CpuNo64, wl_Suf|ShortForm|DefaultSize, { SReg2, 0, 0 } },
{"push", 1, 0x0fa0, X, Cpu386|CpuNo64, wl_Suf|ShortForm|DefaultSize, { SReg3, 0, 0 } },
/* In 64bit mode, the operand size is implicitly 64bit. */
{"push", 1, 0x50, X, Cpu64, wq_Suf|ShortForm|DefaultSize|NoRex64, { Reg16|Reg64, 0, 0 } },
{"push", 1, 0xff, 6, Cpu64, wq_Suf|Modrm|DefaultSize|NoRex64, { Reg16|Reg64|WordMem, 0, 0 } },
{"push", 1, 0x6a, X, Cpu64, wq_Suf|DefaultSize|NoRex64, { Imm8S, 0, 0} },
{"push", 1, 0x68, X, Cpu64, wq_Suf|DefaultSize|NoRex64, { Imm32S|Imm16, 0, 0} },
{"push", 1, 0x0fa0, X, Cpu64, wq_Suf|Seg3ShortForm|DefaultSize|NoRex64, { SReg3, 0, 0 } },
{"push", 1, 0x0fa0, X, Cpu64, wq_Suf|ShortForm|DefaultSize|NoRex64, { SReg3, 0, 0 } },
{"pusha", 0, 0x60, X, Cpu186|CpuNo64, wl_Suf|DefaultSize, { 0, 0, 0 } },
@ -167,12 +167,12 @@ static const template i386_optab[] =
{"pop", 1, 0x58, X, CpuNo64, wl_Suf|ShortForm|DefaultSize, { WordReg, 0, 0 } },
{"pop", 1, 0x8f, 0, CpuNo64, wl_Suf|Modrm|DefaultSize, { WordReg|WordMem, 0, 0 } },
#define POP_SEG_SHORT 0x07
{"pop", 1, 0x07, X, CpuNo64, wl_Suf|Seg2ShortForm|DefaultSize, { SReg2, 0, 0 } },
{"pop", 1, 0x0fa1, X, Cpu386|CpuNo64, wl_Suf|Seg3ShortForm|DefaultSize, { SReg3, 0, 0 } },
{"pop", 1, 0x07, X, CpuNo64, wl_Suf|ShortForm|DefaultSize, { SReg2, 0, 0 } },
{"pop", 1, 0x0fa1, X, Cpu386|CpuNo64, wl_Suf|ShortForm|DefaultSize, { SReg3, 0, 0 } },
/* In 64bit mode, the operand size is implicitly 64bit. */
{"pop", 1, 0x58, X, Cpu64, wq_Suf|ShortForm|DefaultSize|NoRex64, { Reg16|Reg64, 0, 0 } },
{"pop", 1, 0x8f, 0, Cpu64, wq_Suf|Modrm|DefaultSize|NoRex64, { Reg16|Reg64|WordMem, 0, 0 } },
{"pop", 1, 0x0fa1, X, Cpu64, wq_Suf|Seg3ShortForm|DefaultSize|NoRex64, { SReg3, 0, 0 } },
{"pop", 1, 0x0fa1, X, Cpu64, wq_Suf|ShortForm|DefaultSize|NoRex64, { SReg3, 0, 0 } },
{"popa", 0, 0x61, X, Cpu186|CpuNo64, wl_Suf|DefaultSize, { 0, 0, 0 } },