Rewrote i386_index_check

* config/tc-i386.c (flag_code_names): Removed.
	(i386_index_check): Rewrote.
This commit is contained in:
H.J. Lu 2013-03-07 21:40:06 +00:00
parent ac91cd701e
commit be05d20139
2 changed files with 109 additions and 119 deletions

View File

@ -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';

View File

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