Wed Jun 3 18:21:56 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
authorIan Lance Taylor <ian@airs.com>
Wed, 3 Jun 1998 23:11:04 +0000 (23:11 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 3 Jun 1998 23:11:04 +0000 (23:11 +0000)
* 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.

gas/ChangeLog
gas/config/tc-i386.c
gas/config/tc-i386.h

index defb7319f307e7ee2e1516b17c23845582e112a7..7df5bf6cbce59f63c2ef0ed7f312bc5cbbddd385 100644 (file)
@@ -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.
index a08ec9fd6c51467a53ff4fb66e36d27daac428e3..9de4f9ee4f871e605a07c470e34d8cf5965068b3 100644 (file)
@@ -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);
              };
index 42bab6379d11132572696e832b6ecf678e9c946a..1c09dbc4e275fb382284bdf5b6affddb5599ae38 100644 (file)
@@ -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 '$'