aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-i386.c
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2008-08-28 09:42:11 +0000
committerJan Beulich <jbeulich@novell.com>2008-08-28 09:42:11 +0000
commitfc0763e65af9240d302c14f3bbab5e3e0f3b7364 (patch)
treec3a3f767048ce397556d20f3c20cad35e79b86e5 /gas/config/tc-i386.c
parent6bba1048d63e0476b94b9934527defd81c590a13 (diff)
downloadgdb-fc0763e65af9240d302c14f3bbab5e3e0f3b7364.zip
gdb-fc0763e65af9240d302c14f3bbab5e3e0f3b7364.tar.gz
gdb-fc0763e65af9240d302c14f3bbab5e3e0f3b7364.tar.bz2
gas/
2008-08-28 Jan Beulich <jbeulich@novell.com> * config/tc-i386.c (md_assemble): Force number of displacement operands to zero when processing string instruction. (i386_index_check): Special-case string instruction operands. Don't fudge address prefix if there already was a memory operand. Fix error message to correctly reflect the addressing mode used. (i386_att_operand): Fix comment. (i386_intel_operand): Snapshot, clear, and restore base and index reg for each operand processed. Increment count of memory operands later. gas/testsuite/ 2008-08-28 Jan Beulich <jbeulich@novell.com> * gas/i386/string-bad.{l,s}, gas/i386/string-ok.{d,e,s}: New. * gas/i386/i386.exp: Run new tests.
Diffstat (limited to 'gas/config/tc-i386.c')
-rw-r--r--gas/config/tc-i386.c109
1 files changed, 100 insertions, 9 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 3083f28..86ef49c 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -2762,6 +2762,7 @@ md_assemble (char *line)
{
if (!check_string ())
return;
+ i.disp_operands = 0;
}
if (!process_suffix ())
@@ -6890,13 +6891,77 @@ static int
i386_index_check (const char *operand_string)
{
int ok;
+ const char *kind = "base/index";
#if INFER_ADDR_PREFIX
int fudged = 0;
tryprefix:
#endif
ok = 1;
- if (flag_code == CODE_64BIT)
+ if (current_templates->start->opcode_modifier.isstring
+ && !current_templates->start->opcode_modifier.immext
+ && (current_templates->end[-1].opcode_modifier.isstring
+ || i.mem_operands))
+ {
+ /* 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;
+
+ kind = "string address";
+
+ if (current_templates->start->opcode_modifier.w)
+ {
+ i386_operand_type type = current_templates->end[-1].operand_types[0];
+
+ if (!type.bitfield.baseindex
+ || ((!i.mem_operands != !intel_syntax)
+ && 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 */;
+ }
+ else
+ expected = 3 /* rBX */;
+
+ if (!i.base_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 (i.base_reg->reg_num != expected)
+ ok = -1;
+
+ if (ok < 0)
+ {
+ unsigned int j;
+
+ 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)
+ && i386_regtab[j].reg_num == expected)
+ break;
+ 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,
+ intel_syntax ? ']' : ')');
+ ok = 1;
+ }
+ }
+ else if (flag_code == CODE_64BIT)
{
if ((i.base_reg
&& ((i.prefix[ADDR_PREFIX] == 0
@@ -6949,7 +7014,7 @@ i386_index_check (const char *operand_string)
if (!ok)
{
#if INFER_ADDR_PREFIX
- if (i.prefix[ADDR_PREFIX] == 0)
+ if (!i.mem_operands && !i.prefix[ADDR_PREFIX])
{
i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;
i.prefixes += 1;
@@ -6967,18 +7032,24 @@ i386_index_check (const char *operand_string)
goto tryprefix;
}
if (fudged)
- as_bad (_("`%s' is not a valid base/index expression"),
- operand_string);
+ as_bad (_("`%s' is not a valid %s expression"),
+ operand_string,
+ kind);
else
#endif
- as_bad (_("`%s' is not a valid %s bit base/index expression"),
+ as_bad (_("`%s' is not a valid %s-bit %s expression"),
operand_string,
- flag_code_names[flag_code]);
+ 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 non-zero
+/* Parse OPERAND_STRING into the i386_insn structure I. Returns zero
on error. */
static int
@@ -8795,6 +8866,8 @@ i386_intel_operand (char *operand_string, int got_a_float)
{
int ret;
char *p;
+ const reg_entry *final_base = i.base_reg;
+ const reg_entry *final_index = i.index_reg;
p = intel_parser.op_string = xstrdup (operand_string);
intel_parser.disp = (char *) xmalloc (strlen (operand_string) + 1);
@@ -8816,6 +8889,9 @@ i386_intel_operand (char *operand_string, int got_a_float)
intel_parser.disp[0] = '\0';
intel_parser.next_operand = NULL;
+ i.base_reg = NULL;
+ i.index_reg = NULL;
+
/* Read the first token and start the parser. */
intel_get_token ();
ret = intel_expr ();
@@ -8844,8 +8920,6 @@ i386_intel_operand (char *operand_string, int got_a_float)
else
{
char *s = intel_parser.disp;
- i.types[this_operand].bitfield.mem = 1;
- i.mem_operands++;
if (!quiet_warnings && intel_parser.is_mem < 0)
/* See the comments in intel_bracket_expr. */
@@ -8873,6 +8947,11 @@ i386_intel_operand (char *operand_string, int got_a_float)
}
ret = i386_index_check (operand_string);
}
+ if (ret)
+ {
+ i.types[this_operand].bitfield.mem = 1;
+ i.mem_operands++;
+ }
}
}
@@ -8889,6 +8968,12 @@ i386_intel_operand (char *operand_string, int got_a_float)
ret = i386_immediate (intel_parser.disp);
}
+ if (!final_base && !final_index)
+ {
+ final_base = i.base_reg;
+ final_index = i.index_reg;
+ }
+
if (intel_parser.next_operand && this_operand >= MAX_OPERANDS - 1)
ret = 0;
if (!ret || !intel_parser.next_operand)
@@ -8901,6 +8986,12 @@ i386_intel_operand (char *operand_string, int got_a_float)
free (p);
free (intel_parser.disp);
+ if (final_base || final_index)
+ {
+ i.base_reg = final_base;
+ i.index_reg = final_index;
+ }
+
return ret;
}