mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-25 19:14:52 +08:00
Rewrote i386_index_check
* config/tc-i386.c (flag_code_names): Removed. (i386_index_check): Rewrote.
This commit is contained in:
parent
ac91cd701e
commit
be05d20139
@ -1,3 +1,8 @@
|
||||
2013-03-07 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* config/tc-i386.c (flag_code_names): Removed.
|
||||
(i386_index_check): Rewrote.
|
||||
|
||||
2013-03-05 Yufeng Zhang <yufeng.zhang@arm.com>
|
||||
|
||||
* config/tc-aarch64.c (aarch64_imm_float_p): Rename 'e' to 'pattern';
|
||||
|
@ -425,14 +425,6 @@ enum x86_elf_abi
|
||||
static enum x86_elf_abi x86_elf_abi = I386_ABI;
|
||||
#endif
|
||||
|
||||
/* The names used to print error messages. */
|
||||
static const char *flag_code_names[] =
|
||||
{
|
||||
"32",
|
||||
"16",
|
||||
"64"
|
||||
};
|
||||
|
||||
/* 1 for intel syntax,
|
||||
0 if att syntax. */
|
||||
static int intel_syntax = 0;
|
||||
@ -7420,14 +7412,55 @@ i386_finalize_displacement (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp,
|
||||
static int
|
||||
i386_index_check (const char *operand_string)
|
||||
{
|
||||
int ok;
|
||||
const char *kind = "base/index";
|
||||
#if INFER_ADDR_PREFIX
|
||||
int fudged = 0;
|
||||
enum flag_code addr_mode;
|
||||
|
||||
tryprefix:
|
||||
if (i.prefix[ADDR_PREFIX])
|
||||
addr_mode = flag_code == CODE_32BIT ? CODE_16BIT : CODE_32BIT;
|
||||
else
|
||||
{
|
||||
addr_mode = flag_code;
|
||||
|
||||
#if INFER_ADDR_PREFIX
|
||||
if (i.mem_operands == 0)
|
||||
{
|
||||
/* Infer address prefix from the first memory operand. */
|
||||
const reg_entry *addr_reg = i.base_reg;
|
||||
|
||||
if (addr_reg == NULL)
|
||||
addr_reg = i.index_reg;
|
||||
|
||||
if (addr_reg)
|
||||
{
|
||||
if (addr_reg->reg_num == RegEip
|
||||
|| addr_reg->reg_num == RegEiz
|
||||
|| addr_reg->reg_type.bitfield.reg32)
|
||||
addr_mode = CODE_32BIT;
|
||||
else if (flag_code != CODE_64BIT
|
||||
&& addr_reg->reg_type.bitfield.reg16)
|
||||
addr_mode = CODE_16BIT;
|
||||
|
||||
if (addr_mode != flag_code)
|
||||
{
|
||||
i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;
|
||||
i.prefixes += 1;
|
||||
/* Change the size of any displacement too. At most one
|
||||
of Disp16 or Disp32 is set.
|
||||
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].bitfield.disp16
|
||||
|| i.types[this_operand].bitfield.disp32))
|
||||
i.types[this_operand]
|
||||
= operand_type_xor (i.types[this_operand], disp16_32);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ok = 1;
|
||||
}
|
||||
|
||||
if (current_templates->start->opcode_modifier.isstring
|
||||
&& !current_templates->start->opcode_modifier.immext
|
||||
&& (current_templates->end[-1].opcode_modifier.isstring
|
||||
@ -7435,7 +7468,14 @@ i386_index_check (const char *operand_string)
|
||||
{
|
||||
/* Memory operands of string insns are special in that they only allow
|
||||
a single register (rDI, rSI, or rBX) as their memory address. */
|
||||
unsigned int expected;
|
||||
const reg_entry *expected_reg;
|
||||
static const char *di_si[][2] =
|
||||
{
|
||||
{ "esi", "edi" },
|
||||
{ "si", "di" },
|
||||
{ "rsi", "rdi" }
|
||||
};
|
||||
static const char *bx[] = { "ebx", "bx", "rbx" };
|
||||
|
||||
kind = "string address";
|
||||
|
||||
@ -7448,77 +7488,70 @@ i386_index_check (const char *operand_string)
|
||||
&& current_templates->end[-1].operand_types[1]
|
||||
.bitfield.baseindex))
|
||||
type = current_templates->end[-1].operand_types[1];
|
||||
expected = type.bitfield.esseg ? 7 /* rDI */ : 6 /* rSI */;
|
||||
expected_reg = hash_find (reg_hash,
|
||||
di_si[addr_mode][type.bitfield.esseg]);
|
||||
|
||||
}
|
||||
else
|
||||
expected = 3 /* rBX */;
|
||||
expected_reg = hash_find (reg_hash, bx[addr_mode]);
|
||||
|
||||
if (!i.base_reg || i.index_reg
|
||||
if (i.base_reg != expected_reg
|
||||
|| i.index_reg
|
||||
|| operand_type_check (i.types[this_operand], disp))
|
||||
ok = -1;
|
||||
else if (!(flag_code == CODE_64BIT
|
||||
? i.prefix[ADDR_PREFIX]
|
||||
? i.base_reg->reg_type.bitfield.reg32
|
||||
: i.base_reg->reg_type.bitfield.reg64
|
||||
: (flag_code == CODE_16BIT) ^ !i.prefix[ADDR_PREFIX]
|
||||
? i.base_reg->reg_type.bitfield.reg32
|
||||
: i.base_reg->reg_type.bitfield.reg16))
|
||||
ok = 0;
|
||||
else if (register_number (i.base_reg) != expected)
|
||||
ok = -1;
|
||||
|
||||
if (ok < 0)
|
||||
{
|
||||
unsigned int j;
|
||||
/* The second memory operand must have the same size as
|
||||
the first one. */
|
||||
if (i.mem_operands
|
||||
&& i.base_reg
|
||||
&& !((addr_mode == CODE_64BIT
|
||||
&& i.base_reg->reg_type.bitfield.reg64)
|
||||
|| (addr_mode == CODE_32BIT
|
||||
? i.base_reg->reg_type.bitfield.reg32
|
||||
: i.base_reg->reg_type.bitfield.reg16)))
|
||||
goto bad_address;
|
||||
|
||||
for (j = 0; j < i386_regtab_size; ++j)
|
||||
if ((flag_code == CODE_64BIT
|
||||
? i.prefix[ADDR_PREFIX]
|
||||
? i386_regtab[j].reg_type.bitfield.reg32
|
||||
: i386_regtab[j].reg_type.bitfield.reg64
|
||||
: (flag_code == CODE_16BIT) ^ !i.prefix[ADDR_PREFIX]
|
||||
? i386_regtab[j].reg_type.bitfield.reg32
|
||||
: i386_regtab[j].reg_type.bitfield.reg16)
|
||||
&& register_number(i386_regtab + j) == expected)
|
||||
break;
|
||||
gas_assert (j < i386_regtab_size);
|
||||
as_warn (_("`%s' is not valid here (expected `%c%s%s%c')"),
|
||||
operand_string,
|
||||
intel_syntax ? '[' : '(',
|
||||
register_prefix,
|
||||
i386_regtab[j].reg_name,
|
||||
expected_reg->reg_name,
|
||||
intel_syntax ? ']' : ')');
|
||||
ok = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (flag_code == CODE_64BIT)
|
||||
{
|
||||
if ((i.base_reg
|
||||
&& ((i.prefix[ADDR_PREFIX] == 0
|
||||
&& !i.base_reg->reg_type.bitfield.reg64)
|
||||
|| (i.prefix[ADDR_PREFIX]
|
||||
&& !i.base_reg->reg_type.bitfield.reg32))
|
||||
&& (i.index_reg
|
||||
|| i.base_reg->reg_num !=
|
||||
(i.prefix[ADDR_PREFIX] == 0 ? RegRip : RegEip)))
|
||||
|| (i.index_reg
|
||||
&& !(i.index_reg->reg_type.bitfield.regxmm
|
||||
|| i.index_reg->reg_type.bitfield.regymm)
|
||||
&& (!i.index_reg->reg_type.bitfield.baseindex
|
||||
|| (i.prefix[ADDR_PREFIX] == 0
|
||||
&& i.index_reg->reg_num != RegRiz
|
||||
&& !i.index_reg->reg_type.bitfield.reg64
|
||||
)
|
||||
|| (i.prefix[ADDR_PREFIX]
|
||||
&& i.index_reg->reg_num != RegEiz
|
||||
&& !i.index_reg->reg_type.bitfield.reg32))))
|
||||
ok = 0;
|
||||
else
|
||||
return 1;
|
||||
|
||||
bad_address:
|
||||
as_bad (_("`%s' is not a valid %s expression"),
|
||||
operand_string, kind);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0))
|
||||
if (addr_mode != CODE_16BIT)
|
||||
{
|
||||
/* 16bit checks. */
|
||||
/* 32-bit/64-bit checks. */
|
||||
if ((i.base_reg
|
||||
&& (addr_mode == CODE_64BIT
|
||||
? !i.base_reg->reg_type.bitfield.reg64
|
||||
: !i.base_reg->reg_type.bitfield.reg32)
|
||||
&& (i.index_reg
|
||||
|| (i.base_reg->reg_num
|
||||
!= (addr_mode == CODE_64BIT ? RegRip : RegEip))))
|
||||
|| (i.index_reg
|
||||
&& !i.index_reg->reg_type.bitfield.regxmm
|
||||
&& !i.index_reg->reg_type.bitfield.regymm
|
||||
&& ((addr_mode == CODE_64BIT
|
||||
? !(i.index_reg->reg_type.bitfield.reg64
|
||||
|| i.index_reg->reg_num == RegRiz)
|
||||
: !(i.index_reg->reg_type.bitfield.reg32
|
||||
|| i.index_reg->reg_num == RegEiz))
|
||||
|| !i.index_reg->reg_type.bitfield.baseindex)))
|
||||
goto bad_address;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 16-bit checks. */
|
||||
if ((i.base_reg
|
||||
&& (!i.base_reg->reg_type.bitfield.reg16
|
||||
|| !i.base_reg->reg_type.bitfield.baseindex))
|
||||
@ -7529,58 +7562,10 @@ i386_index_check (const char *operand_string)
|
||||
&& i.base_reg->reg_num < 6
|
||||
&& i.index_reg->reg_num >= 6
|
||||
&& i.log2_scale_factor == 0))))
|
||||
ok = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 32bit checks. */
|
||||
if ((i.base_reg
|
||||
&& !i.base_reg->reg_type.bitfield.reg32)
|
||||
|| (i.index_reg
|
||||
&& !i.index_reg->reg_type.bitfield.regxmm
|
||||
&& !i.index_reg->reg_type.bitfield.regymm
|
||||
&& ((!i.index_reg->reg_type.bitfield.reg32
|
||||
&& i.index_reg->reg_num != RegEiz)
|
||||
|| !i.index_reg->reg_type.bitfield.baseindex)))
|
||||
ok = 0;
|
||||
goto bad_address;
|
||||
}
|
||||
}
|
||||
if (!ok)
|
||||
{
|
||||
#if INFER_ADDR_PREFIX
|
||||
if (!i.mem_operands && !i.prefix[ADDR_PREFIX])
|
||||
{
|
||||
i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;
|
||||
i.prefixes += 1;
|
||||
/* Change the size of any displacement too. At most one of
|
||||
Disp16 or Disp32 is set.
|
||||
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].bitfield.disp16
|
||||
|| i.types[this_operand].bitfield.disp32))
|
||||
i.types[this_operand]
|
||||
= operand_type_xor (i.types[this_operand], disp16_32);
|
||||
fudged = 1;
|
||||
goto tryprefix;
|
||||
}
|
||||
if (fudged)
|
||||
as_bad (_("`%s' is not a valid %s expression"),
|
||||
operand_string,
|
||||
kind);
|
||||
else
|
||||
#endif
|
||||
as_bad (_("`%s' is not a valid %s-bit %s expression"),
|
||||
operand_string,
|
||||
flag_code_names[i.prefix[ADDR_PREFIX]
|
||||
? flag_code == CODE_32BIT
|
||||
? CODE_16BIT
|
||||
: CODE_32BIT
|
||||
: flag_code],
|
||||
kind);
|
||||
}
|
||||
return ok;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Parse OPERAND_STRING into the i386_insn structure I. Returns zero
|
||||
|
Loading…
Reference in New Issue
Block a user