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

View File

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