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>
|
2013-03-05 Yufeng Zhang <yufeng.zhang@arm.com>
|
||||||
|
|
||||||
* config/tc-aarch64.c (aarch64_imm_float_p): Rename 'e' to 'pattern';
|
* 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;
|
static enum x86_elf_abi x86_elf_abi = I386_ABI;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The names used to print error messages. */
|
|
||||||
static const char *flag_code_names[] =
|
|
||||||
{
|
|
||||||
"32",
|
|
||||||
"16",
|
|
||||||
"64"
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 1 for intel syntax,
|
/* 1 for intel syntax,
|
||||||
0 if att syntax. */
|
0 if att syntax. */
|
||||||
static int intel_syntax = 0;
|
static int intel_syntax = 0;
|
||||||
@ -7420,14 +7412,55 @@ i386_finalize_displacement (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp,
|
|||||||
static int
|
static int
|
||||||
i386_index_check (const char *operand_string)
|
i386_index_check (const char *operand_string)
|
||||||
{
|
{
|
||||||
int ok;
|
|
||||||
const char *kind = "base/index";
|
const char *kind = "base/index";
|
||||||
#if INFER_ADDR_PREFIX
|
enum flag_code addr_mode;
|
||||||
int fudged = 0;
|
|
||||||
|
|
||||||
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
|
#endif
|
||||||
ok = 1;
|
}
|
||||||
|
|
||||||
if (current_templates->start->opcode_modifier.isstring
|
if (current_templates->start->opcode_modifier.isstring
|
||||||
&& !current_templates->start->opcode_modifier.immext
|
&& !current_templates->start->opcode_modifier.immext
|
||||||
&& (current_templates->end[-1].opcode_modifier.isstring
|
&& (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
|
/* Memory operands of string insns are special in that they only allow
|
||||||
a single register (rDI, rSI, or rBX) as their memory address. */
|
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";
|
kind = "string address";
|
||||||
|
|
||||||
@ -7448,77 +7488,70 @@ i386_index_check (const char *operand_string)
|
|||||||
&& current_templates->end[-1].operand_types[1]
|
&& current_templates->end[-1].operand_types[1]
|
||||||
.bitfield.baseindex))
|
.bitfield.baseindex))
|
||||||
type = current_templates->end[-1].operand_types[1];
|
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
|
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))
|
|| 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')"),
|
as_warn (_("`%s' is not valid here (expected `%c%s%s%c')"),
|
||||||
operand_string,
|
operand_string,
|
||||||
intel_syntax ? '[' : '(',
|
intel_syntax ? '[' : '(',
|
||||||
register_prefix,
|
register_prefix,
|
||||||
i386_regtab[j].reg_name,
|
expected_reg->reg_name,
|
||||||
intel_syntax ? ']' : ')');
|
intel_syntax ? ']' : ')');
|
||||||
ok = 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else if (flag_code == CODE_64BIT)
|
return 1;
|
||||||
{
|
|
||||||
if ((i.base_reg
|
bad_address:
|
||||||
&& ((i.prefix[ADDR_PREFIX] == 0
|
as_bad (_("`%s' is not a valid %s expression"),
|
||||||
&& !i.base_reg->reg_type.bitfield.reg64)
|
operand_string, kind);
|
||||||
|| (i.prefix[ADDR_PREFIX]
|
return 0;
|
||||||
&& !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
|
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
|
if ((i.base_reg
|
||||||
&& (!i.base_reg->reg_type.bitfield.reg16
|
&& (!i.base_reg->reg_type.bitfield.reg16
|
||||||
|| !i.base_reg->reg_type.bitfield.baseindex))
|
|| !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.base_reg->reg_num < 6
|
||||||
&& i.index_reg->reg_num >= 6
|
&& i.index_reg->reg_num >= 6
|
||||||
&& i.log2_scale_factor == 0))))
|
&& i.log2_scale_factor == 0))))
|
||||||
ok = 0;
|
goto bad_address;
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!ok)
|
return 1;
|
||||||
{
|
|
||||||
#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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse OPERAND_STRING into the i386_insn structure I. Returns zero
|
/* Parse OPERAND_STRING into the i386_insn structure I. Returns zero
|
||||||
|
Loading…
Reference in New Issue
Block a user