Wed Jun 3 18:21:56 1998 Alan Modra <alan@spri.levels.unisa.edu.au>

* config/tc-i386.c (SCALE1_WHEN_NO_INDEX): Define.
	(ebp, esp): Remove static variables.
	(MATCH): Remove test for InOutPortReg.
	(i386_operand): Properly handle InOutPortReg here instead.
	Disallows `inb (%dx,2)', `inb %es:(%dx)' and `mov (%dx),%ax'
	(md_assemble): Simplify and correct modrm and sib generation.
	(i386_operand): Add warning for scale without index.
	Rewrite checks for valid base/index combinations.
This commit is contained in:
Ian Lance Taylor 1998-06-03 22:28:28 +00:00
parent 2edb8195a9
commit ec1e6bb850
2 changed files with 107 additions and 124 deletions

View File

@ -1,3 +1,14 @@
Wed Jun 3 18:21:56 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
* config/tc-i386.c (SCALE1_WHEN_NO_INDEX): Define.
(ebp, esp): Remove static variables.
(MATCH): Remove test for InOutPortReg.
(i386_operand): Properly handle InOutPortReg here instead.
Disallows `inb (%dx,2)', `inb %es:(%dx)' and `mov (%dx),%ax'
(md_assemble): Simplify and correct modrm and sib generation.
(i386_operand): Add warning for scale without index.
Rewrite checks for valid base/index combinations.
Wed Jun 3 15:09:10 1998 Ian Lance Taylor <ian@cygnus.com>
* configure.in: Recognize m5200 as a cpu_type of m68k.

View File

@ -38,6 +38,14 @@
#define TC_RELOC(X,Y) (Y)
#endif
#ifndef SCALE1_WHEN_NO_INDEX
/* Specifying a scale factor besides 1 when there is no index is
futile. eg. `mov (%ebx,2),%al' does exactly the same as
`mov (%ebx),%al'. To slavishly follow what the programmer
specified, set SCALE1_WHEN_NO_INDEX to 0. */
#define SCALE1_WHEN_NO_INDEX 1
#endif
static unsigned long mode_from_disp_size PARAMS ((unsigned long));
static int fits_in_signed_byte PARAMS ((long));
static int fits_in_unsigned_byte PARAMS ((long));
@ -102,10 +110,9 @@ struct _i386_insn
const seg_entry *seg[2]; /* segments for memory operands (if given) */
/* PREFIX holds all the given prefix opcodes (usually null).
PREFIXES is the size of PREFIX. */
/* richfix: really unsigned? */
unsigned char prefix[MAX_PREFIXES];
PREFIXES is the number of prefix opcodes. */
unsigned int prefixes;
unsigned char prefix[MAX_PREFIXES];
/* Wait prefix needs to come before any other prefixes, so handle
it specially. wait_prefix will hold the opcode modifier flag
@ -189,9 +196,6 @@ static templates *current_templates;
/* Per instruction expressionS buffers: 2 displacements & 2 immediate max. */
static expressionS disp_expressions[2], im_expressions[2];
/* Pointers to ebp & esp entries in reg_hash hash table. */
static reg_entry *ebp, *esp;
static int this_operand; /* current operand we are working on */
static int flag_do_long_jump; /* FIXME what does this do? */
@ -609,9 +613,6 @@ md_begin ()
}
}
esp = (reg_entry *) hash_find (reg_hash, "esp");
ebp = (reg_entry *) hash_find (reg_hash, "ebp");
/* initialize reg_hash hash table */
prefix_hash = hash_new ();
{
@ -967,7 +968,6 @@ md_assemble (line)
else
{
/* This opcode's got a prefix. */
unsigned int q;
prefix_entry *prefix;
if (l == token_start)
@ -1143,11 +1143,9 @@ md_assemble (line)
with the template operand types. */
#define MATCH(overlap,given_type) \
(overlap && \
(((overlap & (JumpAbsolute|BaseIndex|Mem8)) \
== (given_type & (JumpAbsolute|BaseIndex|Mem8))) \
|| (overlap == InOutPortReg)))
(overlap \
&& ((overlap & (JumpAbsolute|BaseIndex|Mem8)) \
== (given_type & (JumpAbsolute|BaseIndex|Mem8))))
/* If m0 and m1 are register matches they must be consistent
with the expected operand types t0 and t1.
@ -1524,85 +1522,72 @@ md_assemble (line)
? 0
: (i.types[1] & Mem) ? 1 : 2);
/* Encode memory operand into modrm byte and base index
byte. */
default_seg = &ds;
if (i.base_reg == esp && !i.index_reg)
if (! i.base_reg)
{
/* <disp>(%esp) becomes two byte modrm with no index
register. */
i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
i.rm.mode = mode_from_disp_size (i.types[op]);
i.bi.base = ESP_REG_NUM;
i.bi.index = NO_INDEX_REGISTER;
i.bi.scale = 0; /* Must be zero! */
}
else if (i.base_reg == ebp && !i.index_reg)
{
if (!(i.types[op] & Disp))
i.rm.mode = 0;
if (! i.disp_operands)
fake_zero_displacement = 1;
if (! i.index_reg)
{
/* Must fake a zero byte displacement. There is
no direct way to code '(%ebp)' directly. */
fake_zero_displacement = 1;
/* fake_zero_displacement code does not set this. */
i.types[op] |= Disp8;
}
i.rm.mode = mode_from_disp_size (i.types[op]);
i.rm.regmem = EBP_REG_NUM;
}
else if (!i.base_reg && (i.types[op] & BaseIndex))
{
/* There are three cases here.
Case 1: '<32bit disp>(,1)' -- indirect absolute.
(Same as cases 2 & 3 with NO index register)
Case 2: <32bit disp> (,<index>) -- no base register with disp
Case 3: (, <index>) --- no base register;
no disp (must add 32bit 0 disp). */
i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
i.rm.mode = 0; /* 32bit mode */
i.bi.base = NO_BASE_REGISTER;
i.types[op] &= ~Disp;
i.types[op] |= Disp32; /* Must be 32bit! */
if (i.index_reg)
{ /* case 2 or case 3 */
i.bi.index = i.index_reg->reg_num;
i.bi.scale = i.log2_scale_factor;
if (i.disp_operands == 0)
fake_zero_displacement = 1; /* case 3 */
/* Operand is just <disp> */
i.rm.regmem = NO_BASE_REGISTER;
i.types[op] &= ~Disp;
i.types[op] |= Disp32;
}
else
{
i.bi.index = NO_INDEX_REGISTER;
i.bi.scale = 0;
i.bi.index = i.index_reg->reg_num;
i.bi.base = NO_BASE_REGISTER;
i.bi.scale = i.log2_scale_factor;
i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
i.types[op] &= ~Disp;
i.types[op] |= Disp32; /* Must be 32 bit */
}
}
else if (i.disp_operands && !i.base_reg && !i.index_reg)
else /* i.base_reg */
{
/* Operand is just <32bit disp> */
i.rm.regmem = EBP_REG_NUM;
i.rm.mode = 0;
i.types[op] &= ~Disp;
i.types[op] |= Disp32;
}
else
{
/* It's not a special case; rev'em up. */
i.rm.regmem = i.base_reg->reg_num;
i.rm.mode = mode_from_disp_size (i.types[op]);
if (i.index_reg)
i.bi.base = i.base_reg->reg_num;
if (i.base_reg->reg_num == EBP_REG_NUM)
{
i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
i.bi.base = i.base_reg->reg_num;
i.bi.index = i.index_reg->reg_num;
i.bi.scale = i.log2_scale_factor;
if (i.base_reg == ebp && i.disp_operands == 0)
{ /* pace */
default_seg = &ss;
if (i.disp_operands == 0)
{
fake_zero_displacement = 1;
i.types[op] |= Disp8;
i.rm.mode = mode_from_disp_size (i.types[op]);
}
}
else if (i.base_reg->reg_num == ESP_REG_NUM)
{
default_seg = &ss;
}
i.bi.scale = i.log2_scale_factor;
if (! i.index_reg)
{
/* <disp>(%esp) becomes two byte modrm
with no index register. We've already
stored the code for esp in i.rm.regmem
ie. ESCAPE_TO_TWO_BYTE_ADDRESSING. Any
base register besides %esp will not use
the extra modrm byte. */
i.bi.index = NO_INDEX_REGISTER;
#if ! SCALE1_WHEN_NO_INDEX
/* Another case where we force the second
modrm byte. */
if (i.log2_scale_factor)
i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
#endif
}
else
{
i.bi.index = i.index_reg->reg_num;
i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
}
i.rm.mode = mode_from_disp_size (i.types[op]);
}
if (fake_zero_displacement)
{
/* Fakes a zero displacement assuming that i.types[op]
@ -1614,24 +1599,6 @@ md_assemble (line)
exp->X_add_symbol = (symbolS *) 0;
exp->X_op_symbol = (symbolS *) 0;
}
/* Find the default segment for the memory operand.
Used to optimize out explicit segment specifications. */
if (i.seg[0])
{
unsigned int seg_index;
if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING)
{
seg_index = (i.rm.mode << 3) | i.bi.base;
default_seg = two_byte_segment_defaults[seg_index];
}
else
{
seg_index = (i.rm.mode << 3) | i.rm.regmem;
default_seg = one_byte_segment_defaults[seg_index];
}
}
}
/* Fill in i.rm.reg or i.rm.regmem field with register
@ -1984,7 +1951,8 @@ md_assemble (line)
1);
/* If i.rm.regmem == ESP (4) && i.rm.mode != Mode 3 (Register mode)
==> need second modrm byte. */
if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING && i.rm.mode != 3)
if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING
&& i.rm.mode != 3)
{
p = frag_more (1);
insn_size += 1;
@ -2202,7 +2170,7 @@ i386_operand (operand_string)
}
goto do_memory_reference;
}
i.types[this_operand] |= r->reg_type;
i.types[this_operand] |= r->reg_type & ~BaseIndex;
i.regs[this_operand] = r;
i.reg_operands++;
}
@ -2292,7 +2260,7 @@ i386_operand (operand_string)
{
/* This is a memory reference of some sort. */
register char *base_string;
unsigned int found_base_index_form;
int found_base_index_form;
do_memory_reference:
if ((i.mem_operands == 1
@ -2303,7 +2271,6 @@ i386_operand (operand_string)
current_templates->start->name);
return 0;
}
i.mem_operands++;
/* Determine type of memory operand from opcode_suffix;
no opcode suffix implies general memory references. */
@ -2453,6 +2420,14 @@ i386_operand (operand_string)
as_bad (_("expecting scale factor of 1, 2, 4, 8; got %d"), num);
return 0;
}
if (num != 1 && ! i.index_reg)
{
as_warn (_("scale factor of %d without an index register"),
num);
#if SCALE1_WHEN_NO_INDEX
i.log2_scale_factor = 0;
#endif
}
}
else
{
@ -2588,35 +2563,28 @@ i386_operand (operand_string)
}
}
/* Make sure the memory operand we've been dealt is valid. */
if (i.base_reg && i.index_reg &&
!(i.base_reg->reg_type & i.index_reg->reg_type & Reg))
/* Special case for (%dx) while doing input/output op. */
if (i.base_reg &&
i.base_reg->reg_type == (Reg16 | InOutPortReg) &&
i.index_reg == 0 &&
i.log2_scale_factor == 0 &&
i.seg[i.mem_operands] == 0)
{
as_bad (_("register size mismatch in (base,index,scale) expression"));
return 0;
}
/*
* special case for (%dx) while doing input/output op
*/
if ((i.base_reg &&
(i.base_reg->reg_type == (Reg16 | InOutPortReg)) &&
(i.index_reg == 0)))
{
i.types[this_operand] |= InOutPortReg;
i.types[this_operand] = InOutPortReg;
return 1;
}
if ((i.base_reg && (i.base_reg->reg_type & Reg32) == 0) ||
(i.index_reg && (i.index_reg->reg_type & Reg32) == 0))
/* Make sure the memory operand we've been dealt is valid. */
if ((i.base_reg && (i.base_reg->reg_type & BaseIndex) == 0)
|| (i.index_reg && ((i.index_reg->reg_type & BaseIndex) == 0
|| i.index_reg->reg_num == ESP_REG_NUM))
|| (i.base_reg && i.index_reg
&& (i.base_reg->reg_type & i.index_reg->reg_type & Reg) == 0))
{
as_bad (_("base/index register must be 32 bit register"));
return 0;
}
if (i.index_reg && i.index_reg == esp)
{
as_bad (_("`%%s' may not be used as an index register"),
esp->reg_name);
as_bad (_("`%s' is not a valid base/index expression"),
operand_string);
return 0;
}
i.mem_operands++;
}
else
{ /* it's not a memory operand; argh! */
@ -2867,7 +2835,11 @@ md_apply_fix3 (fixP, valp, seg)
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
if (OUTPUT_FLAVOR == bfd_target_elf_flavour
&& (S_GET_SEGMENT (fixP->fx_addsy) == seg
|| (fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0))
|| (fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
&& ! S_IS_EXTERNAL (fixP->fx_addsy)
&& ! S_IS_WEAK (fixP->fx_addsy)
&& S_IS_DEFINED (fixP->fx_addsy)
&& ! S_IS_COMMON (fixP->fx_addsy))
{
/* Yes, we add the values in twice. This is because
bfd_perform_relocation subtracts them out again. I think