aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1998-06-03 23:11:04 +0000
committerIan Lance Taylor <ian@airs.com>1998-06-03 23:11:04 +0000
commitaa56747a9b90a494f26fd389f8c9d1126a999db3 (patch)
treebf4ebe0da133a70566b1deac6bf95b475d651920
parent06f9c743fc171bca1004e2b8c713982dadc38a77 (diff)
downloadgdb-aa56747a9b90a494f26fd389f8c9d1126a999db3.zip
gdb-aa56747a9b90a494f26fd389f8c9d1126a999db3.tar.gz
gdb-aa56747a9b90a494f26fd389f8c9d1126a999db3.tar.bz2
Wed Jun 3 18:21:56 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
* config/tc-i386.c (END_STRING_AND_SAVE): Protect arguments of macros and enclose in do while(0). (RESTORE_END_STRING): Likewise. (md_assemble): Add one to printed operand number so we start from 1 not 0. Add some more gettext invocations. (i386_operand): Fix `%%s' -> `%%%s'. Inc printed operand number here too. * config/tc-i386.h (WAIT_PREFIX, LOCKREP_PREFIX, ADDR_PREFIX, DATA_PREFIX, SEG_PREFIX): Define. * config/tc-i386.c (struct _i386_insn): Remove wait_prefix field. (check_prefix): Remove function. (add_prefix): New function. Add prefix to i.prefix as well as doing checks. (md_assemble): Changes for add_prefix. Remove hack for wait prefix, instead always output prefixes in fixed order. Test for jcxz/loop when selecting between word & dword operations, and add address size prefix rather than operand size prefix. Remove operand -> address size hack when emitting jcxz/loop. (i386_operand): Remove O_Absent check as it's done in expr.
-rw-r--r--gas/ChangeLog23
-rw-r--r--gas/config/tc-i386.c242
-rw-r--r--gas/config/tc-i386.h13
3 files changed, 132 insertions, 146 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index defb731..7df5bf6 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,4 +1,4 @@
-Wed Jun 3 18:21:56 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+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.
@@ -9,6 +9,27 @@ Wed Jun 3 18:21:56 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
(i386_operand): Add warning for scale without index.
Rewrite checks for valid base/index combinations.
+ * config/tc-i386.c (END_STRING_AND_SAVE): Protect arguments of
+ macros and enclose in do while(0).
+ (RESTORE_END_STRING): Likewise.
+ (md_assemble): Add one to printed operand number so we start
+ from 1 not 0. Add some more gettext invocations.
+ (i386_operand): Fix `%%s' -> `%%%s'. Inc printed operand
+ number here too.
+
+ * config/tc-i386.h (WAIT_PREFIX, LOCKREP_PREFIX, ADDR_PREFIX,
+ DATA_PREFIX, SEG_PREFIX): Define.
+ * config/tc-i386.c (struct _i386_insn): Remove wait_prefix field.
+ (check_prefix): Remove function.
+ (add_prefix): New function. Add prefix to i.prefix as well as
+ doing checks.
+ (md_assemble): Changes for add_prefix. Remove hack for wait
+ prefix, instead always output prefixes in fixed order. Test
+ for jcxz/loop when selecting between word & dword operations,
+ and add address size prefix rather than operand size prefix.
+ Remove operand -> address size hack when emitting jcxz/loop.
+ (i386_operand): Remove O_Absent check as it's done in expr.
+
Wed Jun 3 15:09:10 1998 Ian Lance Taylor <ian@cygnus.com>
* configure.in: Recognize m5200 as a cpu_type of m68k.
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index a08ec9f..9de4f9e 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -52,7 +52,7 @@ static int fits_in_unsigned_byte PARAMS ((long));
static int fits_in_unsigned_word PARAMS ((long));
static int fits_in_signed_word PARAMS ((long));
static int smallest_imm_type PARAMS ((long));
-static int check_prefix PARAMS ((int));
+static int add_prefix PARAMS ((unsigned char));
static void set_16bit_code_flag PARAMS ((int));
#ifdef BFD_ASSEMBLER
static bfd_reloc_code_real_type reloc
@@ -114,11 +114,6 @@ struct _i386_insn
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
- FWait if a wait prefix is given. */
- int wait_prefix;
-
/* RM and BI are the modrm byte and the base index byte where the
addressing modes of this insn are encoded. */
@@ -184,8 +179,10 @@ static char operand_special_chars[] = "%$-+(,)*._~/<>|&^!:[@]";
assembler instruction). */
static char save_stack[32];
static char *save_stack_p; /* stack pointer */
-#define END_STRING_AND_SAVE(s) *save_stack_p++ = *s; *s = '\0'
-#define RESTORE_END_STRING(s) *s = *--save_stack_p
+#define END_STRING_AND_SAVE(s) \
+ do { *save_stack_p++ = *(s); *(s) = '\0'; } while (0)
+#define RESTORE_END_STRING(s) \
+ do { *(s) = *--save_stack_p; } while (0)
/* The instruction we're assembling. */
static i386_insn i;
@@ -434,79 +431,56 @@ smallest_imm_type (num)
: (Imm32));
} /* smallest_imm_type() */
+/* Returns 0 if attempting to add a prefix where one from the same
+ class already exists, 1 if non rep/repne added, 2 if rep/repne
+ added. */
static int
-check_prefix (prefix)
- int prefix;
+add_prefix (prefix)
+ unsigned char prefix;
{
+ int ret = 1;
int q;
- for (q = 0; q < i.prefixes; q++)
+ switch (prefix)
{
- switch (prefix)
- {
- case CS_PREFIX_OPCODE:
- case DS_PREFIX_OPCODE:
- case ES_PREFIX_OPCODE:
- case FS_PREFIX_OPCODE:
- case GS_PREFIX_OPCODE:
- case SS_PREFIX_OPCODE:
- switch (i.prefix[q])
- {
- case CS_PREFIX_OPCODE:
- case DS_PREFIX_OPCODE:
- case ES_PREFIX_OPCODE:
- case FS_PREFIX_OPCODE:
- case GS_PREFIX_OPCODE:
- case SS_PREFIX_OPCODE:
- as_bad ("same type of prefix used twice");
- return 0;
- }
- break;
+ case CS_PREFIX_OPCODE:
+ case DS_PREFIX_OPCODE:
+ case ES_PREFIX_OPCODE:
+ case FS_PREFIX_OPCODE:
+ case GS_PREFIX_OPCODE:
+ case SS_PREFIX_OPCODE:
+ q = SEG_PREFIX;
+ break;
- case REPNE:
- case REPE:
- switch (i.prefix[q])
- {
- case REPNE:
- case REPE:
- as_bad ("same type of prefix used twice");
- return 0;
- }
- break;
+ case REPNE:
+ case REPE:
+ ret = 2;
+ /* fall thru */
+ case LOCK_PREFIX_OPCODE:
+ q = LOCKREP_PREFIX;
+ break;
- case FWAIT_OPCODE:
- if (i.wait_prefix != 0)
- {
- as_bad ("same type of prefix used twice");
- return 0;
- }
- break;
+ case FWAIT_OPCODE:
+ q = WAIT_PREFIX;
+ break;
- default:
- if (i.prefix[q] == prefix)
- {
- as_bad ("same type of prefix used twice");
- return 0;
- }
- }
+ case ADDR_PREFIX_OPCODE:
+ q = ADDR_PREFIX;
+ break;
+
+ case WORD_PREFIX_OPCODE:
+ q = DATA_PREFIX;
}
- if (i.prefixes == MAX_PREFIXES && prefix != FWAIT_OPCODE)
+ if (i.prefix[q])
{
- char *p = "another"; /* paranoia */
-
- for (q = 0;
- q < sizeof (i386_prefixtab) / sizeof (i386_prefixtab[0]);
- q++)
- if (i386_prefixtab[q].prefix_code == prefix)
- p = i386_prefixtab[q].prefix_name;
-
- as_bad ("%d prefixes given and `%%%s' prefix gives too many",
- MAX_PREFIXES, p);
+ as_bad (_("same type of prefix used twice"));
return 0;
}
- return 1;
+ i.prefixes += 1;
+ i.prefix[q] = prefix;
+ return ret;
}
static void
@@ -984,19 +958,13 @@ md_assemble (line)
return;
}
RESTORE_END_STRING (l);
- /* check for repeated prefix */
- if (! check_prefix (prefix->prefix_code))
- return;
- if (prefix->prefix_code == FWAIT_OPCODE)
- {
- i.wait_prefix = FWait;
- }
- else
+ /* add prefix, checking for repeated prefixes */
+ switch (add_prefix (prefix->prefix_code))
{
- i.prefix[i.prefixes++] = prefix->prefix_code;
- if (prefix->prefix_code == REPE
- || prefix->prefix_code == REPNE)
- expecting_string_instruction = prefix->prefix_name;
+ case 0: return;
+ case 2:
+ expecting_string_instruction = prefix->prefix_name;
+ break;
}
/* Skip past PREFIX_SEPARATOR and reset token_start. */
token_start = ++l;
@@ -1057,7 +1025,8 @@ md_assemble (line)
if (!is_space_char (*l))
{
as_bad (_("invalid character %s before operand %d"),
- output_invalid (*l), i.operands);
+ output_invalid (*l),
+ i.operands + 1);
return;
}
l++;
@@ -1071,7 +1040,7 @@ md_assemble (line)
if (paren_not_balanced)
{
as_bad (_("unbalanced parenthesis in operand %d."),
- i.operands);
+ i.operands + 1);
return;
}
else
@@ -1080,7 +1049,8 @@ md_assemble (line)
else if (!is_operand_char (*l) && !is_space_char (*l))
{
as_bad (_("invalid character %s in operand %d"),
- output_invalid (*l), i.operands);
+ output_invalid (*l),
+ i.operands + 1);
return;
}
if (*l == '(')
@@ -1246,7 +1216,9 @@ md_assemble (line)
/* Copy the template we found. */
i.tm = *t;
- i.tm.opcode_modifier |= i.wait_prefix;
+ if (i.tm.opcode_modifier & FWait)
+ if (! add_prefix (FWAIT_OPCODE))
+ return;
if (found_reverse_match)
{
@@ -1262,8 +1234,9 @@ md_assemble (line)
{
if (i.seg[0] != (seg_entry *) 0 && i.seg[0] != (seg_entry *) &es)
{
- as_bad ("`%s' operand %d must use `%%es' segment",
- i.tm.name, mem_op);
+ as_bad (_("`%s' operand %d must use `%%es' segment"),
+ i.tm.name,
+ mem_op + 1);
return;
}
/* There's only ever one segment override allowed per instruction.
@@ -1276,8 +1249,9 @@ md_assemble (line)
{
if (i.seg[1] != (seg_entry *) 0 && i.seg[1] != (seg_entry *) &es)
{
- as_bad ("`%s' operand %d must use `%%es' segment",
- i.tm.name, mem_op + 1);
+ as_bad (_("`%s' operand %d must use `%%es' segment"),
+ i.tm.name,
+ mem_op + 2);
return;
}
}
@@ -1408,9 +1382,12 @@ md_assemble (line)
size prefix. */
if ((i.suffix == WORD_OPCODE_SUFFIX) ^ flag_16bit_code)
{
- if (! check_prefix (WORD_PREFIX_OPCODE))
+ unsigned char prefix = WORD_PREFIX_OPCODE;
+ if (i.tm.opcode_modifier & JumpByte) /* jcxz, loop */
+ prefix = ADDR_PREFIX_OPCODE;
+
+ if (! add_prefix (prefix))
return;
- i.prefix[i.prefixes++] = WORD_PREFIX_OPCODE;
}
}
@@ -1427,9 +1404,9 @@ md_assemble (line)
int uses_mem_addrmode = 0;
- /* If we found a reverse match we must alter the opcode direction bit
- found_reverse_match holds bit to set (different for int &
- float insns). */
+ /* If we found a reverse match we must alter the opcode
+ direction bit. found_reverse_match holds bits to change
+ (different for int & float insns). */
i.tm.base_opcode ^= found_reverse_match;
@@ -1644,7 +1621,7 @@ md_assemble (line)
{
if (i.tm.base_opcode == POP_SEG_SHORT && i.regs[0]->reg_num == 1)
{
- as_bad ("you can't `pop %%cs' on the 386.");
+ as_bad (_("you can't `pop %%cs' on the 386."));
return;
}
i.tm.base_opcode |= (i.regs[0]->reg_num << 3);
@@ -1678,9 +1655,8 @@ md_assemble (line)
always spew out an address size prefix. */
if (uses_mem_addrmode && flag_16bit_code)
{
- if (! check_prefix (ADDR_PREFIX_OPCODE))
+ if (! add_prefix (ADDR_PREFIX_OPCODE))
return;
- i.prefix[i.prefixes++] = ADDR_PREFIX_OPCODE;
}
/* If a segment was explicitly specified,
@@ -1691,9 +1667,8 @@ md_assemble (line)
and the specified segment prefix will always be used. */
if ((i.seg[0]) && (i.seg[0] != default_seg))
{
- if (! check_prefix (i.seg[0]->seg_prefix))
+ if (! add_prefix (i.seg[0]->seg_prefix))
return;
- i.prefix[i.prefixes++] = i.seg[0]->seg_prefix;
}
}
}
@@ -1715,7 +1690,7 @@ md_assemble (line)
unsigned long n = i.disps[0]->X_add_number;
if (i.prefixes != 0)
- as_warn ("skipping prefixes on this instruction");
+ as_warn (_("skipping prefixes on this instruction"));
if (i.disps[0]->X_op == O_constant)
{
@@ -1790,39 +1765,19 @@ md_assemble (line)
unsigned long n = i.disps[0]->X_add_number;
unsigned char *q;
- /* The jcx/jecx instruction might need a data size prefix. */
- for (q = i.prefix; q < i.prefix + i.prefixes; q++)
+ if (size == 1) /* then this is a loop or jecxz type instruction */
{
- if (*q == WORD_PREFIX_OPCODE)
+ if (i.prefix[ADDR_PREFIX])
{
- /* The jcxz/jecxz instructions are marked with Data16
- and Data32, which means that they may get
- WORD_PREFIX_OPCODE added to the list of prefixes.
- However, the are correctly distinguished using
- ADDR_PREFIX_OPCODE. Here we look for
- WORD_PREFIX_OPCODE, and actually emit
- ADDR_PREFIX_OPCODE. This is a hack, but, then, so
- is the instruction itself.
-
- If an explicit suffix is used for the loop
- instruction, that actually controls whether we use
- cx vs. ecx. This is also controlled by
- ADDR_PREFIX_OPCODE.
-
- I don't know if there is any valid case in which we
- want to emit WORD_PREFIX_OPCODE, but I am keeping
- the old behaviour for safety. */
-
- if (IS_JUMP_ON_CX_ZERO (i.tm.base_opcode)
- || IS_LOOP_ECX_TIMES (i.tm.base_opcode))
- FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE);
- else
- FRAG_APPEND_1_CHAR (WORD_PREFIX_OPCODE);
- insn_size += 1;
- break;
+ FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE);
+ i.prefixes -= 1;
+ insn_size += 1;
}
}
+ if (i.prefixes != 0)
+ as_warn (_("skipping prefixes on this instruction"));
+
if ((size == 4) && (flag_16bit_code))
{
FRAG_APPEND_1_CHAR (WORD_PREFIX_OPCODE);
@@ -1864,7 +1819,7 @@ md_assemble (line)
else if (i.tm.opcode_modifier & JumpInterSegment)
{
if (i.prefixes != 0)
- as_warn ("skipping prefixes on this instruction");
+ as_warn (_("skipping prefixes on this instruction"));
if (flag_16bit_code)
{
@@ -1889,21 +1844,17 @@ md_assemble (line)
/* Output normal instructions here. */
unsigned char *q;
- /* Hack for fwait. It must come before any prefixes, as it
- really is an instruction rather than a prefix. */
- if ((i.tm.opcode_modifier & FWait) != 0)
- {
- p = frag_more (1);
- insn_size += 1;
- md_number_to_chars (p, (valueT) FWAIT_OPCODE, 1);
- }
-
/* The prefix bytes. */
- for (q = i.prefix; q < i.prefix + i.prefixes; q++)
+ for (q = i.prefix;
+ q < i.prefix + sizeof (i.prefix) / sizeof (i.prefix[0]);
+ q++)
{
- p = frag_more (1);
- insn_size += 1;
- md_number_to_chars (p, (valueT) *q, 1);
+ if (*q)
+ {
+ p = frag_more (1);
+ insn_size += 1;
+ md_number_to_chars (p, (valueT) *q, 1);
+ }
}
/* Now the opcode; be careful about word order here! */
@@ -2448,6 +2399,7 @@ i386_operand (operand_string)
register expressionS *exp;
segT exp_seg = 0;
char *save_input_line_pointer;
+
exp = &disp_expressions[i.disp_operands];
i.disps[this_operand] = exp;
i.disp_reloc[this_operand] = NO_RELOC;
@@ -2531,6 +2483,7 @@ i386_operand (operand_string)
input_line_pointer);
RESTORE_END_STRING (displacement_string_end);
input_line_pointer = save_input_line_pointer;
+#if 0 /* this is handled in expr */
if (exp->X_op == O_absent)
{
/* missing expr becomes absolute 0 */
@@ -2542,7 +2495,9 @@ i386_operand (operand_string)
exp->X_add_symbol = (symbolS *) 0;
exp->X_op_symbol = (symbolS *) 0;
}
- else if (exp->X_op == O_constant)
+ else
+#endif
+ if (exp->X_op == O_constant)
{
i.types[this_operand] |= SMALLEST_DISP_TYPE (exp->X_add_number);
}
@@ -2589,7 +2544,8 @@ i386_operand (operand_string)
else
{ /* it's not a memory operand; argh! */
as_bad (_("invalid char %s begining operand %d `%s'"),
- output_invalid (*op_string), this_operand,
+ output_invalid (*op_string),
+ this_operand + 1,
op_string);
return 0;
}
@@ -3115,7 +3071,7 @@ md_undefined_symbol (name)
if(!GOT_symbol)
{
if(symbol_find(name))
- as_bad(_("GOT already in symbol table"));
+ as_bad (_("GOT already in symbol table"));
GOT_symbol = symbol_new (name, undefined_section,
(valueT) 0, &zero_address_frag);
};
diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h
index 42bab63..1c09dbc 100644
--- a/gas/config/tc-i386.h
+++ b/gas/config/tc-i386.h
@@ -162,10 +162,19 @@ extern int tc_coff_sizemachdep PARAMS ((fragS *frag));
#define tc_headers_hook(a) {;} /* not used */
#define MAX_OPERANDS 3 /* max operands per insn */
-#define MAX_PREFIXES 5 /* max prefixes per opcode */
-#define MAX_IMMEDIATE_OPERANDS 2/* max immediates per insn */
+#define MAX_IMMEDIATE_OPERANDS 2/* max immediates per insn (lcall, ljmp) */
#define MAX_MEMORY_OPERANDS 2 /* max memory refs per insn (string ops) */
+/* Prefixes will be emitted in the order defined below.
+ WAIT_PREFIX must be the first prefix since FWAIT is really is an
+ instruction, and so must come before any prefixes. */
+#define WAIT_PREFIX 0
+#define LOCKREP_PREFIX 1
+#define ADDR_PREFIX 2
+#define DATA_PREFIX 3
+#define SEG_PREFIX 4
+#define MAX_PREFIXES 5 /* max prefixes per opcode */
+
/* we define the syntax here (modulo base,index,scale syntax) */
#define REGISTER_PREFIX '%'
#define IMMEDIATE_PREFIX '$'