mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-27 14:39:09 +08:00
* config/tc-i386.c: Add INFER_ADDR_PREFIX code. Fix 16 bit mode nop.
This commit is contained in:
@ -1,3 +1,12 @@
|
|||||||
|
1999-08-03 Etienne Lorrain <etienne.lorrain@ibm.net>
|
||||||
|
|
||||||
|
* config/tc-i386.c (f16_3): New. Fixes 16 bit 3 byte nop.
|
||||||
|
|
||||||
|
1999-08-03 Alan Modra <alan@spri.levels.unisa.edu.au>
|
||||||
|
|
||||||
|
* config/tc-i386.c (i386_operand): Add INFER_ADDR_PREFIX code, but
|
||||||
|
don't enable it by default. White space changes.
|
||||||
|
|
||||||
1999-07-30 Jakub Jelinek <jj@ultra.linux.cz>
|
1999-07-30 Jakub Jelinek <jj@ultra.linux.cz>
|
||||||
|
|
||||||
* config/tc-sparc.c (md_longopts): Add --no-undeclared-regs option.
|
* config/tc-sparc.c (md_longopts): Add --no-undeclared-regs option.
|
||||||
|
@ -40,6 +40,10 @@
|
|||||||
#define REGISTER_WARNINGS 1
|
#define REGISTER_WARNINGS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef INFER_ADDR_PREFIX
|
||||||
|
#define INFER_ADDR_PREFIX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef SCALE1_WHEN_NO_INDEX
|
#ifndef SCALE1_WHEN_NO_INDEX
|
||||||
/* Specifying a scale factor besides 1 when there is no index is
|
/* Specifying a scale factor besides 1 when there is no index is
|
||||||
futile. eg. `mov (%ebx,2),%al' does exactly the same as
|
futile. eg. `mov (%ebx,2),%al' does exactly the same as
|
||||||
@ -343,6 +347,8 @@ i386_align_code (fragP, count)
|
|||||||
static const char f32_15[] =
|
static const char f32_15[] =
|
||||||
{0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */
|
{0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */
|
||||||
0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90};
|
0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90};
|
||||||
|
static const char f16_3[] =
|
||||||
|
{0x8d,0x74,0x00}; /* lea 0(%esi),%esi */
|
||||||
static const char f16_4[] =
|
static const char f16_4[] =
|
||||||
{0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */
|
{0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */
|
||||||
static const char f16_5[] =
|
static const char f16_5[] =
|
||||||
@ -362,7 +368,7 @@ i386_align_code (fragP, count)
|
|||||||
f32_9, f32_10, f32_11, f32_12, f32_13, f32_14, f32_15
|
f32_9, f32_10, f32_11, f32_12, f32_13, f32_14, f32_15
|
||||||
};
|
};
|
||||||
static const char *const f16_patt[] = {
|
static const char *const f16_patt[] = {
|
||||||
f32_1, f32_2, f32_3, f16_4, f16_5, f16_6, f16_7, f16_8,
|
f32_1, f32_2, f16_3, f16_4, f16_5, f16_6, f16_7, f16_8,
|
||||||
f32_15, f32_15, f32_15, f32_15, f32_15, f32_15, f32_15
|
f32_15, f32_15, f32_15, f32_15, f32_15, f32_15, f32_15
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3241,71 +3247,71 @@ i386_intel_operand (operand_string, got_a_float)
|
|||||||
case SHORT:
|
case SHORT:
|
||||||
|
|
||||||
case NONE_FOUND:
|
case NONE_FOUND:
|
||||||
/* Should be register or immediate */
|
/* Should be register or immediate */
|
||||||
if (is_digit_char (*op_string)
|
if (is_digit_char (*op_string)
|
||||||
&& strchr (op_string, '[') == 0)
|
&& strchr (op_string, '[') == 0)
|
||||||
{
|
{
|
||||||
if (!i386_immediate (op_string))
|
if (!i386_immediate (op_string))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (*op_string == REGISTER_PREFIX
|
else if (*op_string == REGISTER_PREFIX
|
||||||
|| (allow_naked_reg
|
|| (allow_naked_reg
|
||||||
&& i386_is_reg (op_string)))
|
&& i386_is_reg (op_string)))
|
||||||
{
|
{
|
||||||
|
|
||||||
register const reg_entry * r;
|
register const reg_entry * r;
|
||||||
char *end_op;
|
char *end_op;
|
||||||
|
|
||||||
r = parse_register (op_string, &end_op);
|
r = parse_register (op_string, &end_op);
|
||||||
if (r == NULL)
|
if (r == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Check for a segment override by searching for ':' after a
|
/* Check for a segment override by searching for ':' after a
|
||||||
segment register. */
|
segment register. */
|
||||||
op_string = end_op;
|
op_string = end_op;
|
||||||
if (is_space_char (*op_string))
|
if (is_space_char (*op_string))
|
||||||
++op_string;
|
++op_string;
|
||||||
if (*op_string == ':' && (r->reg_type & (SReg2 | SReg3)))
|
if (*op_string == ':' && (r->reg_type & (SReg2 | SReg3)))
|
||||||
{
|
{
|
||||||
switch (r->reg_num)
|
switch (r->reg_num)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
i.seg[i.mem_operands] = &es;
|
i.seg[i.mem_operands] = &es;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
i.seg[i.mem_operands] = &cs;
|
i.seg[i.mem_operands] = &cs;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
i.seg[i.mem_operands] = &ss;
|
i.seg[i.mem_operands] = &ss;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
i.seg[i.mem_operands] = &ds;
|
i.seg[i.mem_operands] = &ds;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
i.seg[i.mem_operands] = &fs;
|
i.seg[i.mem_operands] = &fs;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
i.seg[i.mem_operands] = &gs;
|
i.seg[i.mem_operands] = &gs;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
i.types[this_operand] |= r->reg_type & ~BaseIndex;
|
i.types[this_operand] |= r->reg_type & ~BaseIndex;
|
||||||
i.regs[this_operand] = r;
|
i.regs[this_operand] = r;
|
||||||
i.reg_operands++;
|
i.reg_operands++;
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!i386_intel_memory_operand (op_string))
|
if (!i386_intel_memory_operand (op_string))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
i.mem_operands++;
|
i.mem_operands++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
} /* end switch */
|
} /* end switch */
|
||||||
/* Special case for (%dx) while doing input/output op. */
|
/* Special case for (%dx) while doing input/output op. */
|
||||||
if (i.base_reg
|
if (i.base_reg
|
||||||
&& i.base_reg->reg_type == (Reg16 | InOutPortReg)
|
&& i.base_reg->reg_type == (Reg16 | InOutPortReg)
|
||||||
@ -3313,42 +3319,42 @@ i386_intel_operand (operand_string, got_a_float)
|
|||||||
&& i.log2_scale_factor == 0
|
&& i.log2_scale_factor == 0
|
||||||
&& i.seg[i.mem_operands] == 0
|
&& i.seg[i.mem_operands] == 0
|
||||||
&& (i.types[this_operand] & Disp) == 0)
|
&& (i.types[this_operand] & Disp) == 0)
|
||||||
{
|
{
|
||||||
i.types[this_operand] = InOutPortReg;
|
i.types[this_operand] = InOutPortReg;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* Make sure the memory operand we've been dealt is valid. */
|
/* Make sure the memory operand we've been dealt is valid. */
|
||||||
if (flag_16bit_code ^ (i.prefix[ADDR_PREFIX] != 0))
|
if (flag_16bit_code ^ (i.prefix[ADDR_PREFIX] != 0))
|
||||||
{
|
{
|
||||||
if ((i.base_reg
|
if ((i.base_reg
|
||||||
&& ((i.base_reg->reg_type & (Reg16|BaseIndex))
|
&& ((i.base_reg->reg_type & (Reg16|BaseIndex))
|
||||||
!= (Reg16|BaseIndex)))
|
!= (Reg16|BaseIndex)))
|
||||||
|| (i.index_reg
|
|| (i.index_reg
|
||||||
&& (((i.index_reg->reg_type & (Reg16|BaseIndex))
|
&& (((i.index_reg->reg_type & (Reg16|BaseIndex))
|
||||||
!= (Reg16|BaseIndex))
|
!= (Reg16|BaseIndex))
|
||||||
|| ! (i.base_reg
|
|| ! (i.base_reg
|
||||||
&& 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))))
|
||||||
{
|
|
||||||
as_bad (_("`%s' is not a valid %s bit base/index expression"),
|
|
||||||
operand_string, "16");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if ((i.base_reg
|
as_bad (_("`%s' is not a valid %s bit base/index expression"),
|
||||||
&& (i.base_reg->reg_type & Reg32) == 0)
|
operand_string, "16");
|
||||||
|| (i.index_reg
|
return 0;
|
||||||
&& ((i.index_reg->reg_type & (Reg32|BaseIndex))
|
|
||||||
!= (Reg32|BaseIndex))))
|
|
||||||
{
|
|
||||||
as_bad (_("`%s' is not a valid %s bit base/index expression"),
|
|
||||||
operand_string, "32");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((i.base_reg
|
||||||
|
&& (i.base_reg->reg_type & Reg32) == 0)
|
||||||
|
|| (i.index_reg
|
||||||
|
&& ((i.index_reg->reg_type & (Reg32|BaseIndex))
|
||||||
|
!= (Reg32|BaseIndex))))
|
||||||
|
{
|
||||||
|
as_bad (_("`%s' is not a valid %s bit base/index expression"),
|
||||||
|
operand_string, "32");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3361,335 +3367,361 @@ static int
|
|||||||
i386_operand (operand_string)
|
i386_operand (operand_string)
|
||||||
char *operand_string;
|
char *operand_string;
|
||||||
{
|
{
|
||||||
char *op_string = operand_string;
|
char *op_string = operand_string;
|
||||||
|
|
||||||
if (is_space_char (*op_string))
|
if (is_space_char (*op_string))
|
||||||
++op_string;
|
++op_string;
|
||||||
|
|
||||||
/* We check for an absolute prefix (differentiating,
|
/* We check for an absolute prefix (differentiating,
|
||||||
for example, 'jmp pc_relative_label' from 'jmp *absolute_label'. */
|
for example, 'jmp pc_relative_label' from 'jmp *absolute_label'. */
|
||||||
if (*op_string == ABSOLUTE_PREFIX)
|
if (*op_string == ABSOLUTE_PREFIX)
|
||||||
{
|
{
|
||||||
++op_string;
|
++op_string;
|
||||||
if (is_space_char (*op_string))
|
if (is_space_char (*op_string))
|
||||||
++op_string;
|
++op_string;
|
||||||
i.types[this_operand] |= JumpAbsolute;
|
i.types[this_operand] |= JumpAbsolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if operand is a register. */
|
/* Check if operand is a register. */
|
||||||
if (*op_string == REGISTER_PREFIX
|
if (*op_string == REGISTER_PREFIX
|
||||||
|| (allow_naked_reg && i386_is_reg (op_string)))
|
|| (allow_naked_reg && i386_is_reg (op_string)))
|
||||||
{
|
{
|
||||||
register const reg_entry *r;
|
register const reg_entry *r;
|
||||||
char *end_op;
|
char *end_op;
|
||||||
|
|
||||||
r = parse_register (op_string, &end_op);
|
r = parse_register (op_string, &end_op);
|
||||||
if (r == NULL)
|
if (r == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Check for a segment override by searching for ':' after a
|
/* Check for a segment override by searching for ':' after a
|
||||||
segment register. */
|
segment register. */
|
||||||
op_string = end_op;
|
op_string = end_op;
|
||||||
if (is_space_char (*op_string))
|
if (is_space_char (*op_string))
|
||||||
++op_string;
|
++op_string;
|
||||||
if (*op_string == ':' && (r->reg_type & (SReg2 | SReg3)))
|
if (*op_string == ':' && (r->reg_type & (SReg2 | SReg3)))
|
||||||
{
|
{
|
||||||
switch (r->reg_num)
|
switch (r->reg_num)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
i.seg[i.mem_operands] = &es;
|
i.seg[i.mem_operands] = &es;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
i.seg[i.mem_operands] = &cs;
|
i.seg[i.mem_operands] = &cs;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
i.seg[i.mem_operands] = &ss;
|
i.seg[i.mem_operands] = &ss;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
i.seg[i.mem_operands] = &ds;
|
i.seg[i.mem_operands] = &ds;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
i.seg[i.mem_operands] = &fs;
|
i.seg[i.mem_operands] = &fs;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
i.seg[i.mem_operands] = &gs;
|
i.seg[i.mem_operands] = &gs;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip the ':' and whitespace. */
|
/* Skip the ':' and whitespace. */
|
||||||
|
++op_string;
|
||||||
|
if (is_space_char (*op_string))
|
||||||
|
++op_string;
|
||||||
|
|
||||||
|
/* Pretend given string starts here. */
|
||||||
|
operand_string = op_string;
|
||||||
|
if (!is_digit_char (*op_string)
|
||||||
|
&& !is_identifier_char (*op_string)
|
||||||
|
&& *op_string != '('
|
||||||
|
&& *op_string != ABSOLUTE_PREFIX)
|
||||||
|
{
|
||||||
|
as_bad (_("bad memory operand `%s'"), op_string);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Handle case of %es:*foo. */
|
||||||
|
if (*op_string == ABSOLUTE_PREFIX)
|
||||||
|
{
|
||||||
++op_string;
|
++op_string;
|
||||||
if (is_space_char (*op_string))
|
if (is_space_char (*op_string))
|
||||||
++op_string;
|
++op_string;
|
||||||
|
i.types[this_operand] |= JumpAbsolute;
|
||||||
|
}
|
||||||
|
goto do_memory_reference;
|
||||||
|
}
|
||||||
|
if (*op_string)
|
||||||
|
{
|
||||||
|
as_bad (_("Junk `%s' after register"), op_string);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
i.types[this_operand] |= r->reg_type & ~BaseIndex;
|
||||||
|
i.regs[this_operand] = r;
|
||||||
|
i.reg_operands++;
|
||||||
|
}
|
||||||
|
else if (*op_string == IMMEDIATE_PREFIX)
|
||||||
|
{ /* ... or an immediate */
|
||||||
|
++op_string;
|
||||||
|
if (i.types[this_operand] & JumpAbsolute)
|
||||||
|
{
|
||||||
|
as_bad (_("Immediate operand illegal with absolute jump"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!i386_immediate (op_string))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (is_digit_char (*op_string)
|
||||||
|
|| is_identifier_char (*op_string)
|
||||||
|
|| *op_string == '(' )
|
||||||
|
{
|
||||||
|
/* This is a memory reference of some sort. */
|
||||||
|
char *end_of_operand_string;
|
||||||
|
register char *base_string;
|
||||||
|
int found_base_index_form;
|
||||||
|
|
||||||
/* Pretend given string starts here. */
|
/* Start and end of displacement string expression (if found). */
|
||||||
operand_string = op_string;
|
char *displacement_string_start = NULL;
|
||||||
if (!is_digit_char (*op_string)
|
char *displacement_string_end = NULL;
|
||||||
&& !is_identifier_char (*op_string)
|
|
||||||
&& *op_string != '('
|
|
||||||
&& *op_string != ABSOLUTE_PREFIX)
|
|
||||||
{
|
|
||||||
as_bad (_("bad memory operand `%s'"), op_string);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* Handle case of %es:*foo. */
|
|
||||||
if (*op_string == ABSOLUTE_PREFIX)
|
|
||||||
{
|
|
||||||
++op_string;
|
|
||||||
if (is_space_char (*op_string))
|
|
||||||
++op_string;
|
|
||||||
i.types[this_operand] |= JumpAbsolute;
|
|
||||||
}
|
|
||||||
goto do_memory_reference;
|
|
||||||
}
|
|
||||||
if (*op_string)
|
|
||||||
{
|
|
||||||
as_bad (_("Junk `%s' after register"), op_string);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
i.types[this_operand] |= r->reg_type & ~BaseIndex;
|
|
||||||
i.regs[this_operand] = r;
|
|
||||||
i.reg_operands++;
|
|
||||||
}
|
|
||||||
else if (*op_string == IMMEDIATE_PREFIX)
|
|
||||||
{ /* ... or an immediate */
|
|
||||||
++op_string;
|
|
||||||
if (i.types[this_operand] & JumpAbsolute)
|
|
||||||
{
|
|
||||||
as_bad (_("Immediate operand illegal with absolute jump"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!i386_immediate (op_string))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (is_digit_char (*op_string)
|
|
||||||
|| is_identifier_char (*op_string)
|
|
||||||
|| *op_string == '(' )
|
|
||||||
{
|
|
||||||
/* This is a memory reference of some sort. */
|
|
||||||
char *end_of_operand_string;
|
|
||||||
register char *base_string;
|
|
||||||
int found_base_index_form;
|
|
||||||
|
|
||||||
/* Start and end of displacement string expression (if found). */
|
do_memory_reference:
|
||||||
char *displacement_string_start = NULL;
|
|
||||||
char *displacement_string_end = NULL;
|
|
||||||
|
|
||||||
do_memory_reference:
|
if ((i.mem_operands == 1
|
||||||
|
&& (current_templates->start->opcode_modifier & IsString) == 0)
|
||||||
|
|| i.mem_operands == 2)
|
||||||
|
{
|
||||||
|
as_bad (_("too many memory references for `%s'"),
|
||||||
|
current_templates->start->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ((i.mem_operands == 1
|
/* Check for base index form. We detect the base index form by
|
||||||
&& (current_templates->start->opcode_modifier & IsString) == 0)
|
looking for an ')' at the end of the operand, searching
|
||||||
|| i.mem_operands == 2)
|
for the '(' matching it, and finding a REGISTER_PREFIX or ','
|
||||||
{
|
after the '('. */
|
||||||
as_bad (_("too many memory references for `%s'"),
|
found_base_index_form = 0;
|
||||||
current_templates->start->name);
|
end_of_operand_string = op_string + strlen (op_string);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for base index form. We detect the base index form by
|
--end_of_operand_string;
|
||||||
looking for an ')' at the end of the operand, searching
|
if (is_space_char (*end_of_operand_string))
|
||||||
for the '(' matching it, and finding a REGISTER_PREFIX or ','
|
--end_of_operand_string;
|
||||||
after the '('. */
|
|
||||||
found_base_index_form = 0;
|
|
||||||
end_of_operand_string = op_string + strlen (op_string);
|
|
||||||
|
|
||||||
--end_of_operand_string;
|
base_string = end_of_operand_string;
|
||||||
if (is_space_char (*end_of_operand_string))
|
|
||||||
--end_of_operand_string;
|
|
||||||
|
|
||||||
base_string = end_of_operand_string;
|
if (*base_string == ')')
|
||||||
|
{
|
||||||
|
unsigned int parens_balanced = 1;
|
||||||
|
/* We've already checked that the number of left & right ()'s are
|
||||||
|
equal, so this loop will not be infinite. */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
base_string--;
|
||||||
|
if (*base_string == ')')
|
||||||
|
parens_balanced++;
|
||||||
|
if (*base_string == '(')
|
||||||
|
parens_balanced--;
|
||||||
|
}
|
||||||
|
while (parens_balanced);
|
||||||
|
|
||||||
if (*base_string == ')')
|
/* If there is a displacement set-up for it to be parsed later. */
|
||||||
{
|
displacement_string_start = op_string;
|
||||||
unsigned int parens_balanced = 1;
|
displacement_string_end = base_string;
|
||||||
/* We've already checked that the number of left & right ()'s are
|
|
||||||
equal, so this loop will not be infinite. */
|
|
||||||
do
|
|
||||||
{
|
|
||||||
base_string--;
|
|
||||||
if (*base_string == ')')
|
|
||||||
parens_balanced++;
|
|
||||||
if (*base_string == '(')
|
|
||||||
parens_balanced--;
|
|
||||||
}
|
|
||||||
while (parens_balanced);
|
|
||||||
|
|
||||||
/* If there is a displacement set-up for it to be parsed later. */
|
/* Skip past '(' and whitespace. */
|
||||||
displacement_string_start = op_string;
|
++base_string;
|
||||||
displacement_string_end = base_string;
|
if (is_space_char (*base_string))
|
||||||
|
++base_string;
|
||||||
|
|
||||||
/* Skip past '(' and whitespace. */
|
if (*base_string == REGISTER_PREFIX
|
||||||
|
|| (allow_naked_reg && i386_is_reg (base_string))
|
||||||
|
|| *base_string == ',')
|
||||||
|
found_base_index_form = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we can't parse a base index register expression, we've found
|
||||||
|
a pure displacement expression. We set up displacement_string_start
|
||||||
|
and displacement_string_end for the code below. */
|
||||||
|
if (!found_base_index_form)
|
||||||
|
{
|
||||||
|
displacement_string_start = op_string;
|
||||||
|
displacement_string_end = end_of_operand_string + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i.types[this_operand] |= BaseIndex;
|
||||||
|
|
||||||
|
/* Find base register (if any). */
|
||||||
|
if (*base_string != ',')
|
||||||
|
{
|
||||||
|
char *end_op;
|
||||||
|
|
||||||
|
/* Trim off the closing ')' so that parse_register won't
|
||||||
|
see it. */
|
||||||
|
END_STRING_AND_SAVE (end_of_operand_string);
|
||||||
|
i.base_reg = parse_register (base_string, &end_op);
|
||||||
|
RESTORE_END_STRING (end_of_operand_string);
|
||||||
|
|
||||||
|
if (i.base_reg == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
base_string = end_op;
|
||||||
|
if (is_space_char (*base_string))
|
||||||
|
++base_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There may be an index reg or scale factor here. */
|
||||||
|
if (*base_string == ',')
|
||||||
|
{
|
||||||
++base_string;
|
++base_string;
|
||||||
if (is_space_char (*base_string))
|
if (is_space_char (*base_string))
|
||||||
++base_string;
|
++base_string;
|
||||||
|
|
||||||
if (*base_string == REGISTER_PREFIX
|
if (*base_string == REGISTER_PREFIX
|
||||||
|| (allow_naked_reg && i386_is_reg (base_string))
|
|| (allow_naked_reg && i386_is_reg (base_string)))
|
||||||
|| *base_string == ',')
|
|
||||||
found_base_index_form = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we can't parse a base index register expression, we've found
|
|
||||||
a pure displacement expression. We set up displacement_string_start
|
|
||||||
and displacement_string_end for the code below. */
|
|
||||||
if (!found_base_index_form)
|
|
||||||
{
|
|
||||||
displacement_string_start = op_string;
|
|
||||||
displacement_string_end = end_of_operand_string + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i.types[this_operand] |= BaseIndex;
|
|
||||||
|
|
||||||
/* Find base register (if any). */
|
|
||||||
if (*base_string != ',')
|
|
||||||
{
|
{
|
||||||
char *end_op;
|
char *end_op;
|
||||||
|
|
||||||
/* Trim off the closing ')' so that parse_register won't
|
END_STRING_AND_SAVE (end_of_operand_string);
|
||||||
see it. */
|
i.index_reg = parse_register (base_string, &end_op);
|
||||||
END_STRING_AND_SAVE (end_of_operand_string);
|
RESTORE_END_STRING (end_of_operand_string);
|
||||||
i.base_reg = parse_register (base_string, &end_op);
|
|
||||||
RESTORE_END_STRING (end_of_operand_string);
|
|
||||||
|
|
||||||
if (i.base_reg == NULL)
|
if (i.index_reg == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
base_string = end_op;
|
base_string = end_op;
|
||||||
if (is_space_char (*base_string))
|
if (is_space_char (*base_string))
|
||||||
++base_string;
|
++base_string;
|
||||||
}
|
if (*base_string == ',')
|
||||||
|
{
|
||||||
/* There may be an index reg or scale factor here. */
|
|
||||||
if (*base_string == ',')
|
|
||||||
{
|
|
||||||
++base_string;
|
|
||||||
if (is_space_char (*base_string))
|
|
||||||
++base_string;
|
++base_string;
|
||||||
|
if (is_space_char (*base_string))
|
||||||
if (*base_string == REGISTER_PREFIX
|
++base_string;
|
||||||
|| (allow_naked_reg && i386_is_reg (base_string)))
|
}
|
||||||
{
|
else if (*base_string != ')' )
|
||||||
char *end_op;
|
{
|
||||||
|
as_bad (_("expecting `,' or `)' after index register in `%s'"),
|
||||||
END_STRING_AND_SAVE (end_of_operand_string);
|
operand_string);
|
||||||
i.index_reg = parse_register (base_string, &end_op);
|
return 0;
|
||||||
RESTORE_END_STRING (end_of_operand_string);
|
}
|
||||||
|
|
||||||
if (i.index_reg == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
base_string = end_op;
|
|
||||||
if (is_space_char (*base_string))
|
|
||||||
++base_string;
|
|
||||||
if (*base_string == ',')
|
|
||||||
{
|
|
||||||
++base_string;
|
|
||||||
if (is_space_char (*base_string))
|
|
||||||
++base_string;
|
|
||||||
}
|
|
||||||
else if (*base_string != ')' )
|
|
||||||
{
|
|
||||||
as_bad (_("expecting `,' or `)' after index register in `%s'"),
|
|
||||||
operand_string);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for scale factor. */
|
|
||||||
if (isdigit ((unsigned char) *base_string))
|
|
||||||
{
|
|
||||||
if (!i386_scale (base_string))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
++base_string;
|
|
||||||
if (is_space_char (*base_string))
|
|
||||||
++base_string;
|
|
||||||
if (*base_string != ')')
|
|
||||||
{
|
|
||||||
as_bad (_("expecting `)' after scale factor in `%s'"),
|
|
||||||
operand_string);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!i.index_reg)
|
|
||||||
{
|
|
||||||
as_bad (_("expecting index register or scale factor after `,'; got '%c'"),
|
|
||||||
*base_string);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (*base_string != ')')
|
|
||||||
|
/* Check for scale factor. */
|
||||||
|
if (isdigit ((unsigned char) *base_string))
|
||||||
{
|
{
|
||||||
as_bad (_("expecting `,' or `)' after base register in `%s'"),
|
if (!i386_scale (base_string))
|
||||||
operand_string);
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there's an expression beginning the operand, parse it,
|
++base_string;
|
||||||
assuming displacement_string_start and
|
if (is_space_char (*base_string))
|
||||||
displacement_string_end are meaningful. */
|
++base_string;
|
||||||
if (displacement_string_start != displacement_string_end)
|
if (*base_string != ')')
|
||||||
{
|
{
|
||||||
if (!i386_displacement (displacement_string_start,
|
as_bad (_("expecting `)' after scale factor in `%s'"),
|
||||||
displacement_string_end))
|
operand_string);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (!i.index_reg)
|
||||||
|
{
|
||||||
|
as_bad (_("expecting index register or scale factor after `,'; got '%c'"),
|
||||||
|
*base_string);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (*base_string != ')')
|
||||||
|
{
|
||||||
|
as_bad (_("expecting `,' or `)' after base register in `%s'"),
|
||||||
|
operand_string);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Special case for (%dx) while doing input/output op. */
|
/* If there's an expression beginning the operand, parse it,
|
||||||
if (i.base_reg
|
assuming displacement_string_start and
|
||||||
&& i.base_reg->reg_type == (Reg16 | InOutPortReg)
|
displacement_string_end are meaningful. */
|
||||||
&& i.index_reg == 0
|
if (displacement_string_start != displacement_string_end)
|
||||||
&& i.log2_scale_factor == 0
|
{
|
||||||
&& i.seg[i.mem_operands] == 0
|
if (!i386_displacement (displacement_string_start,
|
||||||
&& (i.types[this_operand] & Disp) == 0)
|
displacement_string_end))
|
||||||
{
|
return 0;
|
||||||
i.types[this_operand] = InOutPortReg;
|
}
|
||||||
return 1;
|
|
||||||
}
|
/* Special case for (%dx) while doing input/output op. */
|
||||||
/* Make sure the memory operand we've been dealt is valid. */
|
if (i.base_reg
|
||||||
if (flag_16bit_code ^ (i.prefix[ADDR_PREFIX] != 0))
|
&& i.base_reg->reg_type == (Reg16 | InOutPortReg)
|
||||||
{
|
&& i.index_reg == 0
|
||||||
if ((i.base_reg
|
&& i.log2_scale_factor == 0
|
||||||
&& ((i.base_reg->reg_type & (Reg16|BaseIndex))
|
&& i.seg[i.mem_operands] == 0
|
||||||
!= (Reg16|BaseIndex)))
|
&& (i.types[this_operand] & Disp) == 0)
|
||||||
|| (i.index_reg
|
{
|
||||||
&& (((i.index_reg->reg_type & (Reg16|BaseIndex))
|
i.types[this_operand] = InOutPortReg;
|
||||||
!= (Reg16|BaseIndex))
|
return 1;
|
||||||
|| ! (i.base_reg
|
}
|
||||||
&& i.base_reg->reg_num < 6
|
/* Make sure the memory operand we've been dealt is valid. */
|
||||||
&& i.index_reg->reg_num >= 6
|
if (flag_16bit_code ^ (i.prefix[ADDR_PREFIX] != 0))
|
||||||
&& i.log2_scale_factor == 0))))
|
{
|
||||||
|
#if INFER_ADDR_PREFIX
|
||||||
|
try16:
|
||||||
|
#endif
|
||||||
|
if ((i.base_reg
|
||||||
|
&& ((i.base_reg->reg_type & (Reg16|BaseIndex))
|
||||||
|
!= (Reg16|BaseIndex)))
|
||||||
|
|| (i.index_reg
|
||||||
|
&& (((i.index_reg->reg_type & (Reg16|BaseIndex))
|
||||||
|
!= (Reg16|BaseIndex))
|
||||||
|
|| ! (i.base_reg
|
||||||
|
&& i.base_reg->reg_num < 6
|
||||||
|
&& i.index_reg->reg_num >= 6
|
||||||
|
&& i.log2_scale_factor == 0))))
|
||||||
|
{
|
||||||
|
#if INFER_ADDR_PREFIX
|
||||||
|
if (i.prefix[ADDR_PREFIX] == 0)
|
||||||
{
|
{
|
||||||
as_bad (_("`%s' is not a valid %s bit base/index expression"),
|
i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;
|
||||||
operand_string, "16");
|
goto try32;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else
|
#endif
|
||||||
{
|
|
||||||
if ((i.base_reg
|
|
||||||
&& (i.base_reg->reg_type & Reg32) == 0)
|
|
||||||
|| (i.index_reg
|
|
||||||
&& ((i.index_reg->reg_type & (Reg32|BaseIndex))
|
|
||||||
!= (Reg32|BaseIndex))))
|
|
||||||
{
|
{
|
||||||
as_bad (_("`%s' is not a valid %s bit base/index expression"),
|
as_bad (_("`%s' is not a valid %s bit base/index expression"),
|
||||||
operand_string, "32");
|
operand_string, "16");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i.mem_operands++;
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{ /* it's not a memory operand; argh! */
|
#if INFER_ADDR_PREFIX
|
||||||
as_bad (_("invalid char %s beginning operand %d `%s'"),
|
try32:
|
||||||
output_invalid (*op_string),
|
#endif
|
||||||
this_operand + 1,
|
if ((i.base_reg
|
||||||
op_string);
|
&& (i.base_reg->reg_type & Reg32) == 0)
|
||||||
return 0;
|
|| (i.index_reg
|
||||||
}
|
&& ((i.index_reg->reg_type & (Reg32|BaseIndex))
|
||||||
return 1; /* normal return */
|
!= (Reg32|BaseIndex))))
|
||||||
|
{
|
||||||
|
#if INFER_ADDR_PREFIX
|
||||||
|
if (i.prefix[ADDR_PREFIX] == 0)
|
||||||
|
{
|
||||||
|
i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;
|
||||||
|
goto try16;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
as_bad (_("`%s' is not a valid %s bit base/index expression"),
|
||||||
|
operand_string, "32");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i.mem_operands++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* it's not a memory operand; argh! */
|
||||||
|
as_bad (_("invalid char %s beginning operand %d `%s'"),
|
||||||
|
output_invalid (*op_string),
|
||||||
|
this_operand + 1,
|
||||||
|
op_string);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1; /* normal return */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user