Add support for _x and _s flags to MSR instruction
authorNick Clifton <nickc@redhat.com>
Mon, 15 May 2000 19:25:22 +0000 (19:25 +0000)
committerNick Clifton <nickc@redhat.com>
Mon, 15 May 2000 19:25:22 +0000 (19:25 +0000)
gas/ChangeLog
gas/config/tc-arm.c
gas/testsuite/ChangeLog
gas/testsuite/gas/arm/arch4t.s
opcodes/ChangeLog
opcodes/arm-dis.c
opcodes/arm-opc.h

index a1d76a9004bba89166e66d754729718647d349d1..439deda19b6075ee328313cd173f98d10b93a08b 100644 (file)
@@ -1,3 +1,19 @@
+2000-05-15  Nick Clifton  <nickc@cygnus.com>
+
+       * config/tc-arm.c (struct asm_psr): Add boolean field
+       distinguishing between CSPR and SPSR.  Rename 'number' field
+       to 'field'.
+       (psrs): Rearrange contents to match new asm_psr structure.
+       (arm_psr_parse): Move next to psr_required_here.  Make it
+       return an asm_psr structure.
+       (psr_required_here): Use asm_psr structure returned by
+       arm_psr_parse.
+       (do_msr): Reorganise to allow psr_required_here to be called
+       only once.
+       (md_undefined_name): Mark 'name' parameter as unused, since
+       the COFF target does not use it.
+       
+
 2000-05-14  David O'Brien  <obrien@FreeBSD.org>
 
        * config/te-386bsd.h:  Clean up comments to adhere to the GNU coding
index 109de30b9ef1b82442d926d9d112da305c360a0d..4c71976c877e1eb0034b94e7bb4fa7483ace18ae 100644 (file)
@@ -381,39 +381,50 @@ static CONST struct asm_flg cplong_flag[] =
 struct asm_psr
 {
   CONST char *  template;
-  unsigned long number;
+  boolean       cpsr;
+  unsigned long field;
 };
 
-#define PSR_FIELD_MASK  0x000f0000
+#define SPSR_BIT   (1 << 22)  /* The bit that distnguishes CPSR and SPSR.  */
+#define PSR_SHIFT  16  /* How many bits to shift the PSR_xxx bits up by.  */
 
-#define PSR_FLAGS      0x00080000
-#define PSR_CONTROL    0x00010000 /* Undocumented instruction, its use is discouraged by ARM */
-#define PSR_ALL                0x00090000
-
-#define CPSR_ALL       0
-#define SPSR_ALL       1
-#define CPSR_FLG       2
-#define SPSR_FLG       3
-#define CPSR_CTL       4
-#define SPSR_CTL       5
+#define PSR_c   (1 << 0)
+#define PSR_x   (1 << 1)
+#define PSR_s   (1 << 2)
+#define PSR_f   (1 << 3)
 
 static CONST struct asm_psr psrs[] =
 {
-  /* Valid <psr>'s */
-  {"cpsr",     CPSR_ALL},
-  {"cpsr_all", CPSR_ALL},
-  {"spsr",     SPSR_ALL},
-  {"spsr_all", SPSR_ALL},
-
-  /* Valid <psrf>'s */
-  {"cpsr_flg", CPSR_FLG},
-  {"spsr_flg", SPSR_FLG},
-  
-  /* Valid <psrc>'s */
-  {"cpsr_c",   CPSR_CTL},
-  {"cpsr_ctl", CPSR_CTL},
-  {"spsr_c",   SPSR_CTL},
-  {"spsr_ctl", SPSR_CTL}
+  {"CPSR",     true,  PSR_c | PSR_f},
+  {"CPSR_all", true,  PSR_c | PSR_f},
+  {"SPSR",     false, PSR_c | PSR_f},
+  {"SPSR_all", false, PSR_c | PSR_f},
+  {"CPSR_flg", true,  PSR_f},
+  {"CPSR_f",    true,  PSR_f},
+  {"SPSR_flg", false, PSR_f},
+  {"SPSR_f",    false, PSR_f}, 
+  {"CPSR_c",   true,  PSR_c},
+  {"CPSR_ctl", true,  PSR_c},
+  {"SPSR_c",   false, PSR_c},
+  {"SPSR_ctl", false, PSR_c},
+  {"CPSR_x",    true,  PSR_x},
+  {"CPSR_s",    true,  PSR_s},
+  {"SPSR_x",    false, PSR_x},
+  {"SPSR_s",    false, PSR_s},
+  /* For backwards compatability with older toolchain we also
+     support lower case versions of some of these flags.  */
+  {"cpsr",     true,  PSR_c | PSR_f},
+  {"cpsr_all", true,  PSR_c | PSR_f},
+  {"spsr",     false, PSR_c | PSR_f},
+  {"spsr_all", false, PSR_c | PSR_f},
+  {"cpsr_flg", true,  PSR_f},
+  {"cpsr_f",    true,  PSR_f},
+  {"spsr_flg", false, PSR_f},
+  {"spsr_f",    false, PSR_f}, 
+  {"cpsr_c",   true,  PSR_c},
+  {"cpsr_ctl", true,  PSR_c},
+  {"spsr_c",   false, PSR_c},
+  {"spsr_ctl", false, PSR_c}
 };
 
 /* Functions called by parser.  */
@@ -458,7 +469,7 @@ static void do_fp_to_reg    PARAMS ((char *, unsigned long));
 
 static void fix_new_arm                PARAMS ((fragS *, int, short, expressionS *, int, int));
 static int arm_reg_parse       PARAMS ((char **));
-static int arm_psr_parse       PARAMS ((char **));
+static CONST struct asm_psr * arm_psr_parse PARAMS ((char **));
 static void symbol_locate      PARAMS ((symbolS *, CONST char *, segT, valueT, fragS *));
 static int add_to_lit_pool     PARAMS ((void));
 static unsigned validate_immediate PARAMS ((unsigned));
@@ -467,7 +478,7 @@ static int validate_offset_imm      PARAMS ((unsigned int, int));
 static void opcode_select      PARAMS ((int));
 static void end_of_line                PARAMS ((char *));
 static int reg_required_here   PARAMS ((char **, int));
-static int psr_required_here   PARAMS ((char **, int, int));
+static int psr_required_here   PARAMS ((char **));
 static int co_proc_number      PARAMS ((char **));
 static int cp_opc_expr         PARAMS ((char **, int, int));
 static int cp_reg_required_here        PARAMS ((char **, int));
@@ -569,8 +580,8 @@ static CONST struct asm_opcode insns[] =
   {"mrs",   0x010f0000, NULL,   NULL,        ARM_6UP,      do_mrs},
   {"msr",   0x0120f000, NULL,   NULL,        ARM_6UP,      do_msr},
 /* ScottB: our code uses 0x0128f000 for msr.
-   NickC:  but this is wrong because the bits 16 and 19 are handled
-           by the PSR_xxx defines above.  */
+   NickC:  but this is wrong because the bits 16 through 19 are
+           handled by the PSR_xxx defines above.  */
 
 /* ARM 7M long multiplies - need signed/unsigned flags! */
   {"smull", 0x00c00090, NULL,   s_flag,      ARM_LONGMUL,  do_mull},
@@ -1562,27 +1573,65 @@ reg_required_here (str, shift)
   return FAIL;
 }
 
+static CONST struct asm_psr *
+arm_psr_parse (ccp)
+     register char ** ccp;
+{
+  char * start = * ccp;
+  char   c;
+  char * p;
+  CONST struct asm_psr * psr;
+
+  p = start;
+
+  /* Skip to the end of the next word in the input stream.  */
+  do
+    {
+      c = *p++;
+    }
+  while (isalpha (c) || c == '_');
+
+  /* Terminate the word.  */
+  *--p = 0;
+
+  /* Now locate the word in the psr hash table.  */
+  psr = (CONST struct asm_psr *) hash_find (arm_psr_hsh, start);
+
+  /* Restore the input stream.  */
+  *p = c;
+
+  /* If we found a valid match, advance the
+     stream pointer past the end of the word.  */
+  *ccp = p;
+
+  return psr;
+}
+
+/* Parse the input looking for a PSR flag.  */
 static int
-psr_required_here (str, cpsr, spsr)
+psr_required_here (str)
      char ** str;
-     int     cpsr;
-     int     spsr;
 {
-  int    psr;
   char * start = *str;
-  psr = arm_psr_parse (str);
+  CONST struct asm_psr * psr;
   
-  if  (psr == cpsr || psr == spsr)
+  psr = arm_psr_parse (str);
+
+  if (psr)
     {
-      if (psr == spsr)
-       inst.instruction |= 1 << 22;
+      /* If this is the SPSR that is being modified, set the R bit.  */
+      if (! psr->cpsr)
+       inst.instruction |= SPSR_BIT;
+
+      /* Set the psr flags in the MSR instruction.  */
+      inst.instruction |= psr->field << PSR_SHIFT;
       
       return SUCCESS;
     }
 
-  /* In the few cases where we might be able to accept something else
-     this error can be overridden.  */
-  inst.error = _("<psr(f)> expected");
+  /* In the few cases where we might be able to accept
+     something else this error can be overridden.  */
+  inst.error = _("flag for {c}psr instruction expected");
 
   /* Restore the start point.  */
   *str = start;
@@ -1874,104 +1923,110 @@ do_mrs (str, flags)
       return;
     }
 
-  if (skip_past_comma (&str) == FAIL
-      || psr_required_here (& str, CPSR_ALL, SPSR_ALL) == FAIL)
+  if (skip_past_comma (&str) == FAIL)
     {
-      inst.error = _("<psr> expected");
+      inst.error = _("comma expected after register name");
       return;
     }
 
+  skip_whitespace (str);
+
+  if (   strcmp (str, "CPSR") == 0
+      || strcmp (str, "SPSR") == 0
+        /* Lower case versions for backwards compatability.  */
+      || strcmp (str, "cpsr") == 0
+      || strcmp (str, "spsr") == 0)
+    str += 4;
+  /* This is for backwards compatability with older toolchains.  */
+  else if (strcmp (str, "cpsr_all") == 0
+          || strcmp (str, "spsr_all") == 0)
+    str += 7;
+  else
+    {
+      inst.error = _("{C|S}PSR expected");
+      return;
+    }
+
+  if (* str == 's' || * str == 'S')
+    inst.instruction |= SPSR_BIT;
+  
   inst.instruction |= flags;
   end_of_line (str);
-  return;
 }
 
-/* Three possible forms: "<psr>, Rm", "<psrf>, Rm", "<psrf>, #expression".  */
+/* Two possible forms:
+      "{C|S}PSR_<field>, Rm",
+      "{C|S}PSR_f, #expression".  */
 static void
 do_msr (str, flags)
      char * str;
      unsigned long flags;
 {
-  int reg;
+  skip_whitespace (str);
+
+  if (psr_required_here (& str) == FAIL)
+    return;
+    
+  if (skip_past_comma (& str) == FAIL)
+    {
+      inst.error = _("comma missing after psr flags");
+      return;
+    }
 
   skip_whitespace (str);
 
-  if (psr_required_here (&str, CPSR_ALL, SPSR_ALL) == SUCCESS)
+  if (reg_required_here (& str, 0) != FAIL)
     {
-      inst.instruction |= PSR_ALL;
+      inst.error = NULL; 
+      inst.instruction |= flags;
+      end_of_line (str);
+      return;
+    }
 
-      /* Sytax should be "<psr>, Rm" */
-      if (skip_past_comma (&str) == FAIL
-         || (reg = reg_required_here (&str, 0)) == FAIL)
-       {
-         inst.error = BAD_ARGS;
-         return;
-       }
+  if (! is_immediate_prefix (* str))
+    {
+      inst.error = _("only a register or immediate value can follow a psr flag");
+      return;
+    }
+
+  str ++;
+  inst.error = NULL;
+  
+  if (my_get_expression (& inst.reloc.exp, & str))
+    {
+      inst.error = _("only a register or immediate value can follow a psr flag");
+      return;
+    }
+  
+  if (inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
+    {
+      inst.error = _("can only set flag field with immediate value");
+      return;
+    }
+  
+  flags |= INST_IMMEDIATE;
+         
+  if (inst.reloc.exp.X_add_symbol)
+    {
+      inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
+      inst.reloc.pc_rel = 0;
     }
   else
     {
-      if (psr_required_here (& str, CPSR_FLG, SPSR_FLG) == SUCCESS)
-       inst.instruction |= PSR_FLAGS;
-      else if (psr_required_here (& str, CPSR_CTL, SPSR_CTL) == SUCCESS)
-       inst.instruction |= PSR_CONTROL;
-      else
-       {
-         inst.error = BAD_ARGS;
-         return;
-       }
+      unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
       
-      if (skip_past_comma (&str) == FAIL)
+      if (value == (unsigned) FAIL)
        {
-         inst.error = BAD_ARGS;
+         inst.error = _("Invalid constant");
          return;
        }
       
-      /* Syntax could be "<psrf>, rm", "<psrf>, #expression" */
-      
-      if ((reg = reg_required_here (& str, 0)) != FAIL)
-       ;
-      /* Immediate expression.  */
-      else if (is_immediate_prefix (* str))
-       {
-         str ++;
-         inst.error = NULL;
-         
-         if (my_get_expression (& inst.reloc.exp, & str))
-           {
-             inst.error = _("Register or shift expression expected");
-             return;
-           }
-
-         if (inst.reloc.exp.X_add_symbol)
-           {
-             inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
-             inst.reloc.pc_rel = 0;
-           }
-         else
-           {
-             unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
-             if (value == (unsigned) FAIL)
-               {
-                 inst.error = _("Invalid constant");
-                 return;
-               }
-
-             inst.instruction |= value;
-           }
-
-         flags |= INST_IMMEDIATE;
-       }
-      else
-       {
-         inst.error = _("Error: unrecognised syntax for second argument to msr instruction");
-         return;
-       }
+      inst.instruction |= value;
     }
 
   inst.error = NULL; 
   inst.instruction |= flags;
   end_of_line (str);
-  return;
 }
 
 /* Long Multiply Parser
@@ -5241,7 +5296,7 @@ md_section_align (segment, size)
 /* ARGSUSED */
 symbolS *
 md_undefined_symbol (name)
-     char * name;
+     char * name ATTRIBUTE_UNUSED;
 {
 #ifdef OBJ_ELF
   if (name[0] == '_' && name[1] == 'G'
@@ -5306,33 +5361,6 @@ arm_reg_parse (ccp)
   return FAIL;
 }
 
-static int
-arm_psr_parse (ccp)
-     register char ** ccp;
-{
-  char * start = * ccp;
-  char   c;
-  char * p;
-  CONST struct asm_psr * psr;
-
-  p = start;
-  c = *p++;
-  while (isalpha (c) || c == '_')
-    c = *p++;
-
-  *--p = 0;  
-  psr = (CONST struct asm_psr *) hash_find (arm_psr_hsh, start);
-  *p = c;
-
-  if (psr)
-    {
-      *ccp = p;
-      return psr->number;
-    }
-
-  return FAIL;
-}
-
 int
 md_apply_fix3 (fixP, val, seg)
      fixS *      fixP;
@@ -6411,7 +6439,7 @@ _("Warning: Use of the 'nv' conditional is deprecated\n"));
  *            -m[arm]8[10]            Arm 8 processors
  *            -m[arm]9[20][tdmi]      Arm 9 processors
  *            -mstrongarm[110[0]]     StrongARM processors
- *            -m[arm]v[2345]         Arm architectures
+ *            -m[arm]v[2345[t]]       Arm architectures
  *            -mall                   All (except the ARM1)
  *    FP variants:
  *            -mfpa10, -mfpa11        FPA10 and 11 co-processor instructions
index e121ed4e8e5ee739c32c923c05fbad3e913ee24f..5e0f39bbf32b107ceecd75bf87bfc580c8e419e4 100644 (file)
@@ -1,3 +1,7 @@
+2000-05-15  Nick Clifton  <nickc@cygnus.com>
+
+       * gas/arm/arch4t.s: Add tests of new fields to msr instruction.
+
 2000-05-11  Ulf Carlsson  <ulfc@engr.sgi.com>
 
        * gas/mips/mips.exp: Include *-*-linux* in svr4pic.
index 8d28f7f3ec1c6d24fae821e4254e5f94f306d99b..417b3c6beecbe3ff5e9ec8b0a1a045a3b0819003 100644 (file)
@@ -18,4 +18,18 @@ foo:
 
        strh    r2, bar
        strneh  r3, [r3]
+
+       msr     CPSR_f, #2
+       msr     CPSR_c, r3
+       msr     CPSR_x, r4
+       msr     CPSR_s, r5
+       msr     CPSR_f, r6
+       msr     CPSR_all, r7
+       
+       msr     SPSR_f, #4
+       msr     SPSR_c, r8
+       msr     SPSR_x, r9
+       msr     SPSR_s, r10
+       msr     SPSR_f, r11
+       msr     SPSR_all, r12
 bar:
index c183c60f179bbe581bd82221126f1b09e937af9d..199e30f3702d551b44dc0f2b762bdbba373f3ba0 100644 (file)
@@ -1,3 +1,12 @@
+2000-05-15  Nick Clifton  <nickc@cygnus.com>
+
+       * arm-opc.h: Use upper case for flasg in MSR and MRS
+       instructions.  Allow any bit to be set in the field_mask of
+       the MSR instruction.
+
+       * arm-dis.c (print_insn_arm): Decode _x and _s bits of the
+       field_mask of an MSR instruction.
+
 2000-05-11  Thomas de Lellis  <tdel@windriver.com>
 
         * arm-opc.c: Disassembly of thumb ldsb/ldsh
index f131adafebfbb5f6f88d59e8472d13c4deeb9bad..a3e7112b3fc1767447fbd02e6afa586f56406d1e 100644 (file)
@@ -420,7 +420,7 @@ print_insn_arm (pc, info, given)
                      break;
 
                    case 'C':
-                     switch (given & 0x00090000)
+                     switch (given & 0x000f0000)
                        {
                        default:
                          func (stream, "_???");
@@ -429,10 +429,16 @@ print_insn_arm (pc, info, given)
                          func (stream, "_all");
                          break;
                        case 0x10000:
-                         func (stream, "_ctl");
+                         func (stream, "_c");
+                         break;
+                       case 0x20000:
+                         func (stream, "_x");
+                         break;
+                       case 0x40000:
+                         func (stream, "_s");
                          break;
                        case 0x80000:
-                         func (stream, "_flg");
+                         func (stream, "_f");
                          break;
                        }
                      break;
index 8beb65f9f9b4d7ab5bfe4f1f259f0d0dff7191ef..5ecde4be6add149301f118904b3c2b5c527e9516 100644 (file)
@@ -1,6 +1,6 @@
 /* Opcode table for the ARM.
 
-   Copyright 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+   Copyright 1994, 1995, 1996, 1997, 2000 Free Software Foundation, Inc.
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -93,8 +93,8 @@ static struct arm_opcode arm_opcodes[] =
     {0x00a00000, 0x0de00000, "adc%c%20's\t%12-15r, %16-19r, %o"},
     {0x00c00000, 0x0de00000, "sbc%c%20's\t%12-15r, %16-19r, %o"},
     {0x00e00000, 0x0de00000, "rsc%c%20's\t%12-15r, %16-19r, %o"},
-    {0x0120f000, 0x0db6f000, "msr%c\t%22?scpsr%C, %o"},
-    {0x010f0000, 0x0fbf0fff, "mrs%c\t%12-15r, %22?scpsr"},
+    {0x0120f000, 0x0db0f000, "msr%c\t%22?SCPSR%C, %o"},
+    {0x010f0000, 0x0fbf0fff, "mrs%c\t%12-15r, %22?SCPSR"},
     {0x01000000, 0x0de00000, "tst%c%p\t%16-19r, %o"},
     {0x01200000, 0x0de00000, "teq%c%p\t%16-19r, %o"},
     {0x01400000, 0x0de00000, "cmp%c%p\t%16-19r, %o"},
@@ -164,7 +164,7 @@ static struct arm_opcode arm_opcodes[] =
     {0x0e000010, 0x0f100010, "mcr%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
     {0x0c000000, 0x0e100000, "stc%c%22'l\t%8-11d, cr%12-15d, %A"},
     {0x0c100000, 0x0e100000, "ldc%c%22'l\t%8-11d, cr%12-15d, %A"},
-    
+
     /* The rest.  */
     {0x00000000, 0x00000000, "undefined instruction %0-31x"},
     {0x00000000, 0x00000000, 0}