* ld-powerpc/tocopt4a.s, * ld-powerpc/tocopt4b.s,
[deliverable/binutils-gdb.git] / opcodes / arm-dis.c
index 831b26c909da04c261c6b416422fb331e67595bf..fafa7f6853d8ecf242ef2164e2ad5edb491890ba 100644 (file)
 #define NUM_ELEM(a)     (sizeof (a) / sizeof (a)[0])
 #endif
 
+/* Cached mapping symbol state.  */
+enum map_type
+{
+  MAP_ARM,
+  MAP_THUMB,
+  MAP_DATA
+};
+
 struct arm_private_data
 {
   /* The features to use when disassembling optional instructions.  */
@@ -53,6 +61,13 @@ struct arm_private_data
   /* Whether any mapping symbols are present in the provided symbol
      table.  -1 if we do not know yet, otherwise 0 or 1.  */
   int has_mapping_symbols;
+
+  /* Track the last type (although this doesn't seem to be useful) */
+  enum map_type last_type;
+
+  /* Tracking symbol table information */
+  int last_mapping_sym;
+  bfd_vma last_mapping_addr;
 };
 
 struct opcode32
@@ -816,7 +831,8 @@ static const struct opcode32 neon_opcodes[] =
 
    %e                   print arm SMI operand (bits 0..7,8..19).
    %E                  print the LSB and WIDTH fields of a BFI or BFC instruction.
-   %V                   print the 16-bit immediate field of a MOVT or MOVW instruction.  */
+   %V                   print the 16-bit immediate field of a MOVT or MOVW instruction.
+   %R                  print the SPSR/CPSR or banked register of an MRS.  */
 
 static const struct opcode32 arm_opcodes[] =
 {
@@ -829,6 +845,17 @@ static const struct opcode32 arm_opcodes[] =
   {ARM_EXT_V3M, 0x00800090, 0x0fa000f0, "%22?sumull%20's%c\t%12-15Ru, %16-19Ru, %0-3R, %8-11R"},
   {ARM_EXT_V3M, 0x00a00090, 0x0fa000f0, "%22?sumlal%20's%c\t%12-15Ru, %16-19Ru, %0-3R, %8-11R"},
 
+  /* Virtualization Extension instructions.  */
+  {ARM_EXT_VIRT, 0x0160006e, 0x0fffffff, "eret%c"},
+  {ARM_EXT_VIRT, 0x01400070, 0x0ff000f0, "hvc%c\t%e"},
+
+  /* Integer Divide Extension instructions.  */
+  {ARM_EXT_ADIV, 0x0710f010, 0x0ff0f0f0, "sdiv%c\t%16-19r, %0-3r, %8-11r"},
+  {ARM_EXT_ADIV, 0x0730f010, 0x0ff0f0f0, "udiv%c\t%16-19r, %0-3r, %8-11r"},
+
+  /* MP Extension instructions.  */
+  {ARM_EXT_MP, 0xf410f000, 0xfc70f000, "pldw\t%a"},
+
   /* V7 instructions.  */
   {ARM_EXT_V7, 0xf450f000, 0xfd70f000, "pli\t%P"},
   {ARM_EXT_V7, 0x0320f0f0, 0x0ffffff0, "dbg%c\t#%0-3d"},
@@ -850,8 +877,8 @@ static const struct opcode32 arm_opcodes[] =
   {ARM_EXT_V6T2, 0x06ff0f30, 0x0fff0ff0, "rbit%c\t%12-15R, %0-3R"},
   {ARM_EXT_V6T2, 0x07a00050, 0x0fa00070, "%22?usbfx%c\t%12-15r, %0-3r, #%7-11d, #%16-20W"},
 
-  /* ARM V6Z instructions.  */
-  {ARM_EXT_V6Z, 0x01600070, 0x0ff000f0, "smc%c\t%e"},
+  /* ARM Security extension instructions.  */
+  {ARM_EXT_SEC, 0x01600070, 0x0ff000f0, "smc%c\t%e"},
 
   /* ARM V6K instructions.  */
   {ARM_EXT_V6K, 0xf57ff01f, 0xffffffff, "clrex"},
@@ -1084,8 +1111,9 @@ static const struct opcode32 arm_opcodes[] =
   {ARM_EXT_V1, 0x00e00000, 0x0fe00010, "rsc%20's%c\t%12-15r, %16-19r, %o"},
   {ARM_EXT_V1, 0x00e00010, 0x0fe00090, "rsc%20's%c\t%12-15R, %16-19R, %o"},
 
-  {ARM_EXT_V3, 0x0120f000, 0x0db0f000, "msr%c\t%22?SCPSR%C, %o"},
-  {ARM_EXT_V3, 0x010f0000, 0x0fbf0fff, "mrs%c\t%12-15R, %22?SCPSR"},
+  {ARM_EXT_VIRT, 0x0120f200, 0x0fb0f200, "msr%c\t%C, %0-3r"},
+  {ARM_EXT_V3, 0x0120f000, 0x0db0f000, "msr%c\t%C, %o"},
+  {ARM_EXT_V3, 0x01000000, 0x0fb00cff, "mrs%c\t%12-15R, %R"},
 
   {ARM_EXT_V1, 0x03000000, 0x0fe00000, "tst%p%c\t%16-19r, %o"},
   {ARM_EXT_V1, 0x01000000, 0x0fe00010, "tst%p%c\t%16-19r, %o"},
@@ -1096,7 +1124,6 @@ static const struct opcode32 arm_opcodes[] =
   {ARM_EXT_V1, 0x01200010, 0x0fe00090, "teq%p%c\t%16-19R, %o"},
 
   {ARM_EXT_V1, 0x03400000, 0x0fe00000, "cmp%p%c\t%16-19r, %o"},
-  {ARM_EXT_V3, 0x01400000, 0x0ff00010, "mrs%c\t%12-15R, %22?SCPSR"},
   {ARM_EXT_V1, 0x01400000, 0x0fe00010, "cmp%p%c\t%16-19r, %o"},
   {ARM_EXT_V1, 0x01400010, 0x0fe00090, "cmp%p%c\t%16-19R, %o"},
 
@@ -1306,8 +1333,10 @@ static const struct opcode16 thumb_opcodes[] =
        %M              print a modified 12-bit immediate (same location)
        %J              print a 16-bit immediate from hw1[3:0,10],hw2[14:12,7:0]
        %K              print a 16-bit immediate from hw2[3:0],hw1[3:0],hw2[11:4]
+       %H              print a 16-bit immediate from hw2[3:0],hw1[11:0]
        %S              print a possibly-shifted Rm
 
+       %L              print address for a ldrd/strd instruction
        %a              print the address of a plain load/store
        %w              print the width and signedness of a core load/store
        %m              print register mask for ldm/stm
@@ -1353,6 +1382,16 @@ static const struct opcode32 thumb32_opcodes[] =
   {ARM_EXT_DIV, 0xfb90f0f0, 0xfff0f0f0, "sdiv%c\t%8-11r, %16-19r, %0-3r"},
   {ARM_EXT_DIV, 0xfbb0f0f0, 0xfff0f0f0, "udiv%c\t%8-11r, %16-19r, %0-3r"},
 
+  /* Virtualization Extension instructions.  */
+  {ARM_EXT_VIRT, 0xf7e08000, 0xfff0f000, "hvc%c\t%V"},
+  /* We skip ERET as that is SUBS pc, lr, #0.  */
+
+  /* MP Extension instructions.  */
+  {ARM_EXT_MP,   0xf830f000, 0xff70f000, "pldw%c\t%a"},
+
+  /* Security extension instructions.  */
+  {ARM_EXT_SEC,  0xf7f08000, 0xfff0f000, "smc%c\t%K"},
+
   /* Instructions defined in the basic V6T2 set.  */
   {ARM_EXT_V6T2, 0xf3af8000, 0xffffffff, "nop%c.w"},
   {ARM_EXT_V6T2, 0xf3af8001, 0xffffffff, "yield%c.w"},
@@ -1367,7 +1406,7 @@ static const struct opcode32 thumb32_opcodes[] =
   {ARM_EXT_V6T2, 0xf3c08f00, 0xfff0ffff, "bxj%c\t%16-19r%x"},
   {ARM_EXT_V6T2, 0xe810c000, 0xffd0ffff, "rfedb%c\t%16-19r%21'!"},
   {ARM_EXT_V6T2, 0xe990c000, 0xffd0ffff, "rfeia%c\t%16-19r%21'!"},
-  {ARM_EXT_V6T2, 0xf3ef8000, 0xffeff000, "mrs%c\t%8-11r, %D"},
+  {ARM_EXT_V6T2, 0xf3e08000, 0xffe0f000, "mrs%c\t%8-11r, %D"},
   {ARM_EXT_V6T2, 0xf3af8100, 0xffffffe0, "cps\t#%0-4d%X"},
   {ARM_EXT_V6T2, 0xe8d0f000, 0xfff0fff0, "tbb%c\t[%16-19r, %0-3r]%x"},
   {ARM_EXT_V6T2, 0xe8d0f010, 0xfff0fff0, "tbh%c\t[%16-19r, %0-3r, lsl #1]%x"},
@@ -1474,7 +1513,6 @@ static const struct opcode32 thumb32_opcodes[] =
   {ARM_EXT_V6T2, 0xfbe00000, 0xfff000f0, "umlal%c\t%12-15R, %8-11R, %16-19R, %0-3R"},
   {ARM_EXT_V6T2, 0xfbe00060, 0xfff000f0, "umaal%c\t%12-15R, %8-11R, %16-19R, %0-3R"},
   {ARM_EXT_V6T2, 0xe8500f00, 0xfff00f00, "ldrex%c\t%12-15r, [%16-19r, #%0-7W]"},
-  {ARM_EXT_V6T2, 0xf7f08000, 0xfff0f000, "smc%c\t%K"},
   {ARM_EXT_V6T2, 0xf04f0000, 0xfbef8000, "mov%20's%c.w\t%8-11r, %M"},
   {ARM_EXT_V6T2, 0xf06f0000, 0xfbef8000, "mvn%20's%c.w\t%8-11r, %M"},
   {ARM_EXT_V6T2, 0xf810f000, 0xff70f000, "pld%c\t%a"},
@@ -1527,10 +1565,10 @@ static const struct opcode32 thumb32_opcodes[] =
   {ARM_EXT_V6T2, 0xe9100000, 0xffd00000, "ldmdb%c\t%16-19r%21'!, %m"},
   {ARM_EXT_V6T2, 0xe9c00000, 0xffd000ff, "strd%c\t%12-15r, %8-11r, [%16-19r]"},
   {ARM_EXT_V6T2, 0xe9d00000, 0xffd000ff, "ldrd%c\t%12-15r, %8-11r, [%16-19r]"},
-  {ARM_EXT_V6T2, 0xe9400000, 0xff500000, "strd%c\t%12-15r, %8-11r, [%16-19r, #%23`-%0-7W]%21'!"},
-  {ARM_EXT_V6T2, 0xe9500000, 0xff500000, "ldrd%c\t%12-15r, %8-11r, [%16-19r, #%23`-%0-7W]%21'!"},
-  {ARM_EXT_V6T2, 0xe8600000, 0xff700000, "strd%c\t%12-15r, %8-11r, [%16-19r], #%23`-%0-7W"},
-  {ARM_EXT_V6T2, 0xe8700000, 0xff700000, "ldrd%c\t%12-15r, %8-11r, [%16-19r], #%23`-%0-7W"},
+  {ARM_EXT_V6T2, 0xe9400000, 0xff500000, "strd%c\t%12-15r, %8-11r, [%16-19r, #%23`-%0-7W]%21'!%L"},
+  {ARM_EXT_V6T2, 0xe9500000, 0xff500000, "ldrd%c\t%12-15r, %8-11r, [%16-19r, #%23`-%0-7W]%21'!%L"},
+  {ARM_EXT_V6T2, 0xe8600000, 0xff700000, "strd%c\t%12-15r, %8-11r, [%16-19r], #%23`-%0-7W%L"},
+  {ARM_EXT_V6T2, 0xe8700000, 0xff700000, "ldrd%c\t%12-15r, %8-11r, [%16-19r], #%23`-%0-7W%L"},
   {ARM_EXT_V6T2, 0xf8000000, 0xff100000, "str%w%c.w\t%12-15r, %a"},
   {ARM_EXT_V6T2, 0xf8100000, 0xfe100000, "ldr%w%c.w\t%12-15r, %a"},
 
@@ -1541,7 +1579,7 @@ static const struct opcode32 thumb32_opcodes[] =
   {ARM_EXT_V6T2, 0xf0009000, 0xf800d000, "b%c.w\t%B%x"},
 
   /* These have been 32-bit since the invention of Thumb.  */
-  {ARM_EXT_V4T,  0xf000c000, 0xf800d000, "blx%c\t%B%x"},
+  {ARM_EXT_V4T,  0xf000c000, 0xf800d001, "blx%c\t%B%x"},
   {ARM_EXT_V4T,  0xf000d000, 0xf800d000, "bl%c\t%B%x"},
 
   /* Fallback.  */
@@ -1620,18 +1658,6 @@ static unsigned int ifthen_next_state;
 static bfd_vma ifthen_address;
 #define IFTHEN_COND ((ifthen_state >> 4) & 0xf)
 
-/* Cached mapping symbol state.  */
-enum map_type
-{
-  MAP_ARM,
-  MAP_THUMB,
-  MAP_DATA
-};
-
-enum map_type last_type;
-int last_mapping_sym = -1;
-bfd_vma last_mapping_addr = 0;
-
 \f
 /* Functions.  */
 int
@@ -1847,7 +1873,7 @@ print_insn_coprocessor (bfd_vma pc,
                case 'A':
                  {
                    int rn = (given >> 16) & 0xf;
-                   int offset = given & 0xff;
+                   bfd_vma offset = given & 0xff;
 
                    func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
 
@@ -1867,6 +1893,8 @@ print_insn_coprocessor (bfd_vma pc,
                          func (stream, ", #%d]%s",
                                offset,
                                WRITEBACK_BIT_SET ? "!" : "");
+                       else if (NEGATIVE_BIT_SET)
+                         func (stream, ", #-0]");
                        else
                          func (stream, "]");
                      }
@@ -1878,18 +1906,26 @@ print_insn_coprocessor (bfd_vma pc,
                          {
                            if (offset)
                              func (stream, ", #%d", offset);
+                           else if (NEGATIVE_BIT_SET)
+                             func (stream, ", #-0");
                          }
                        else
                          {
-                           func (stream, ", {%d}", offset);
+                           func (stream, ", {%s%d}",
+                                 (NEGATIVE_BIT_SET && !offset) ? "-" : "",
+                                 offset);
                            value_in_comment = offset;
                          }
                      }
                    if (rn == 15 && (PRE_BIT_SET || WRITEBACK_BIT_SET))
                      {
                        func (stream, "\t; ");
-                       info->print_address_func (offset + pc
-                                                 + info->bytes_per_chunk * 2, info);
+                       /* For unaligned PCs, apply off-by-alignment
+                          correction.  */
+                       info->print_address_func (offset + pc 
+                                                 + info->bytes_per_chunk * 2
+                                                 - (pc & 3),
+                                                 info);
                      }
                  }
                  break;
@@ -2299,7 +2335,7 @@ print_arm_address (bfd_vma pc, struct disassemble_info *info, long given)
 {
   void *stream = info->stream;
   fprintf_ftype func = info->fprintf_func;
-  int offset = 0;
+  bfd_vma offset = 0;
 
   if (((given & 0x000f0000) == 0x000f0000)
       && ((given & 0x02000000) == 0))
@@ -2308,13 +2344,15 @@ print_arm_address (bfd_vma pc, struct disassemble_info *info, long given)
 
       func (stream, "[pc");
 
-      if (NEGATIVE_BIT_SET)
-       offset = - offset;
-
       if (PRE_BIT_SET)
        {
-         /* Pre-indexed.  */
-         func (stream, ", #%d]", offset);
+         /* Pre-indexed.  Elide offset of positive zero when
+            non-writeback.  */
+         if (WRITEBACK_BIT_SET || NEGATIVE_BIT_SET || offset)
+           func (stream, ", #%s%d", NEGATIVE_BIT_SET ? "-" : "", offset);
+
+         if (NEGATIVE_BIT_SET)
+           offset = -offset;
 
          offset += pc + 8;
 
@@ -2322,12 +2360,11 @@ print_arm_address (bfd_vma pc, struct disassemble_info *info, long given)
             being used.  Probably a very dangerous thing
             for the programmer to do, but who are we to
             argue ?  */
-         if (WRITEBACK_BIT_SET)
-           func (stream, "!");
+         func (stream, "]%s", WRITEBACK_BIT_SET ? "!" : "");
        }
       else  /* Post indexed.  */
        {
-         func (stream, "], #%d", offset);
+         func (stream, "], #%s%d", NEGATIVE_BIT_SET ? "-" : "", offset);
 
          /* Ie ignore the offset.  */
          offset = pc + 8;
@@ -2346,15 +2383,14 @@ print_arm_address (bfd_vma pc, struct disassemble_info *info, long given)
        {
          if ((given & 0x02000000) == 0)
            {
+             /* Elide offset of positive zero when non-writeback.  */
              offset = given & 0xfff;
-             if (offset)
-               func (stream, ", #%s%d",
-                     NEGATIVE_BIT_SET ? "-" : "", offset);
+             if (WRITEBACK_BIT_SET || NEGATIVE_BIT_SET || offset)
+               func (stream, ", #%s%d", NEGATIVE_BIT_SET ? "-" : "", offset);
            }
          else
            {
-             func (stream, ", %s",
-                   NEGATIVE_BIT_SET ? "-" : "");
+             func (stream, ", %s", NEGATIVE_BIT_SET ? "-" : "");
              arm_decode_shift (given, func, stream, TRUE);
            }
 
@@ -2365,12 +2401,10 @@ print_arm_address (bfd_vma pc, struct disassemble_info *info, long given)
        {
          if ((given & 0x02000000) == 0)
            {
+             /* Always show offset.  */
              offset = given & 0xfff;
-             if (offset)
-               func (stream, "], #%s%d",
-                     NEGATIVE_BIT_SET ? "-" : "", offset);
-             else
-               func (stream, "]");
+             func (stream, "], #%s%d",
+                   NEGATIVE_BIT_SET ? "-" : "", offset);
            }
          else
            {
@@ -2850,6 +2884,52 @@ print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb)
   return FALSE;
 }
 
+/* Return the name of a v7A special register.  */
+
+static const char * 
+banked_regname (unsigned reg)
+{
+  switch (reg)
+    {
+      case 15: return "CPSR";
+      case 32: return "R8_usr"; 
+      case 33: return "R9_usr";
+      case 34: return "R10_usr";
+      case 35: return "R11_usr";
+      case 36: return "R12_usr";
+      case 37: return "SP_usr";
+      case 38: return "LR_usr";
+      case 40: return "R8_fiq"; 
+      case 41: return "R9_fiq";
+      case 42: return "R10_fiq";
+      case 43: return "R11_fiq";
+      case 44: return "R12_fiq";
+      case 45: return "SP_fiq";
+      case 46: return "LR_fiq";
+      case 48: return "LR_irq";
+      case 49: return "SP_irq";
+      case 50: return "LR_svc";
+      case 51: return "SP_svc";
+      case 52: return "LR_abt";
+      case 53: return "SP_abt";
+      case 54: return "LR_und";
+      case 55: return "SP_und";
+      case 60: return "LR_mon";
+      case 61: return "SP_mon";
+      case 62: return "ELR_hyp";
+      case 63: return "SP_hyp";
+      case 79: return "SPSR";
+      case 110: return "SPSR_fiq";
+      case 112: return "SPSR_irq";
+      case 114: return "SPSR_svc";
+      case 116: return "SPSR_abt";
+      case 118: return "SPSR_und";
+      case 124: return "SPSR_mon";
+      case 126: return "SPSR_hyp";
+      default: return NULL;
+    }
+}
+
 /* Print one ARM instruction from PC on INFO->STREAM.  */
 
 static void
@@ -2915,22 +2995,25 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
                       if ((given & 0x004f0000) == 0x004f0000)
                        {
                           /* PC relative with immediate offset.  */
-                         int offset = ((given & 0xf00) >> 4) | (given & 0xf);
-
-                         if (NEGATIVE_BIT_SET)
-                           offset = - offset;
+                         bfd_vma offset = ((given & 0xf00) >> 4) | (given & 0xf);
 
                          if (PRE_BIT_SET)
                            {
-                             if (offset)
-                               func (stream, "[pc, #%d]\t; ", offset);
+                             /* Elide positive zero offset.  */
+                             if (offset || NEGATIVE_BIT_SET)
+                               func (stream, "[pc, #%s%d]\t; ",
+                                     NEGATIVE_BIT_SET ? "-" : "", offset);
                              else
-                               func (stream, "[pc]\t; ");                              
+                               func (stream, "[pc]\t; ");
+                             if (NEGATIVE_BIT_SET)
+                               offset = -offset;
                              info->print_address_func (offset + pc + 8, info);
                            }
                          else
                            {
-                             func (stream, "[pc], #%d", offset);
+                             /* Always show the offset.  */
+                             func (stream, "[pc], #%s%d",
+                                   NEGATIVE_BIT_SET ? "-" : "", offset);
                              if (! allow_unpredictable)
                                is_unpredictable = TRUE;
                            }
@@ -2939,9 +3022,6 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
                        {
                          int offset = ((given & 0xf00) >> 4) | (given & 0xf);
 
-                         if (NEGATIVE_BIT_SET)
-                           offset = - offset;
-
                          func (stream, "[%s",
                                arm_regnames[(given >> 16) & 0xf]);
 
@@ -2949,13 +3029,15 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
                            {
                              if (IMMEDIATE_BIT_SET)
                                {
-                                 if (WRITEBACK_BIT_SET)
-                                   /* Immediate Pre-indexed.  */
-                                   /* PR 10924: Offset must be printed, even if it is zero.  */
-                                   func (stream, ", #%d", offset);
-                                 else if (offset)
-                                   /* Immediate Offset: printing zero offset is optional.  */
-                                   func (stream, ", #%d", offset);
+                                 /* Elide offset for non-writeback
+                                    positive zero.  */
+                                 if (WRITEBACK_BIT_SET || NEGATIVE_BIT_SET
+                                     || offset)
+                                   func (stream, ", #%s%d",
+                                         NEGATIVE_BIT_SET ? "-" : "", offset);
+
+                                 if (NEGATIVE_BIT_SET)
+                                   offset = -offset;
 
                                  value_in_comment = offset;
                                }
@@ -2983,7 +3065,10 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
                                {
                                  /* Immediate Post-indexed.  */
                                  /* PR 10924: Offset must be printed, even if it is zero.  */
-                                 func (stream, "], #%d", offset);
+                                 func (stream, "], #%s%d",
+                                       NEGATIVE_BIT_SET ? "-" : "", offset);
+                                 if (NEGATIVE_BIT_SET)
+                                   offset = -offset;
                                  value_in_comment = offset;
                                }
                              else
@@ -3017,7 +3102,7 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
 
                    case 'b':
                      {
-                       int disp = (((given & 0xffffff) ^ 0x800000) - 0x800000);
+                       bfd_vma disp = (((given & 0xffffff) ^ 0x800000) - 0x800000);
                        info->print_address_func (disp * 4 + pc + 8, info);
                      }
                      break;
@@ -3144,15 +3229,32 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
                      break;
 
                    case 'C':
-                     func (stream, "_");
-                     if (given & 0x80000)
-                       func (stream, "f");
-                     if (given & 0x40000)
-                       func (stream, "s");
-                     if (given & 0x20000)
-                       func (stream, "x");
-                     if (given & 0x10000)
-                       func (stream, "c");
+                     if ((given & 0x02000200) == 0x200)
+                       {
+                         const char * name;
+                         unsigned sysm = (given & 0x004f0000) >> 16;
+
+                         sysm |= (given & 0x300) >> 4;
+                         name = banked_regname (sysm);
+
+                         if (name != NULL)
+                           func (stream, "%s", name);
+                         else
+                           func (stream, "(UNDEF: %lu)", sysm);
+                       }
+                     else
+                       {
+                         func (stream, "%cPSR_", 
+                               (given & 0x00400000) ? 'S' : 'C');
+                         if (given & 0x80000)
+                           func (stream, "f");
+                         if (given & 0x40000)
+                           func (stream, "s");
+                         if (given & 0x20000)
+                           func (stream, "x");
+                         if (given & 0x10000)
+                           func (stream, "c");
+                       }
                      break;
 
                    case 'U':
@@ -3290,6 +3392,22 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
                        }
                        break;
 
+                     case 'R':
+                       /* Get the PSR/banked register name.  */
+                       {
+                         const char * name;
+                         unsigned sysm = (given & 0x004f0000) >> 16;
+
+                         sysm |= (given & 0x300) >> 4;
+                         name = banked_regname (sysm);
+
+                         if (name != NULL)
+                           func (stream, "%s", name);
+                         else
+                           func (stream, "(UNDEF: %lu)", sysm);
+                       }
+                       break;
+
                      case 'V':
                        /* 16-bit unsigned immediate from a MOVT or MOVW
                           instruction, encoded in bits 0:11 and 15:19.  */
@@ -3501,7 +3619,7 @@ print_insn_thumb16 (bfd_vma pc, struct disassemble_info *info, long given)
                    {
                    case '-':
                      {
-                       long reg;
+                       bfd_vma reg;
 
                        c++;
                        while (*c >= '0' && *c <= '9')
@@ -3613,7 +3731,7 @@ psr_name (int regno)
     case 9: return "PSP";
     case 16: return "PRIMASK";
     case 17: return "BASEPRI";
-    case 18: return "BASEPRI_MASK";
+    case 18: return "BASEPRI_MAX";
     case 19: return "FAULTMASK";
     case 20: return "CONTROL";
     default: return "<unknown>";
@@ -3734,6 +3852,17 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
                }
                break;
 
+             case 'V':
+               {
+                 unsigned int imm = 0;
+
+                 imm |= (given & 0x00000fffu);
+                 imm |= (given & 0x000f0000u) >> 4;
+                 func (stream, "#%u", imm);
+                 value_in_comment = imm;
+               }
+               break;
+
              case 'S':
                {
                  unsigned int reg = (given & 0x0000000fu);
@@ -3779,7 +3908,7 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
                  unsigned int i12 = (given & 0x00000fff);
                  unsigned int i8  = (given & 0x000000ff);
                  bfd_boolean writeback = FALSE, postind = FALSE;
-                 int offset = 0;
+                 bfd_vma offset = 0;
 
                  func (stream, "[%s", arm_regnames[Rn]);
                  if (U) /* 12-bit positive immediate offset.  */
@@ -3956,7 +4085,7 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
                  unsigned int S = (given & 0x04000000u) >> 26;
                  unsigned int J1 = (given & 0x00002000u) >> 13;
                  unsigned int J2 = (given & 0x00000800u) >> 11;
-                 int offset = 0;
+                 bfd_vma offset = 0;
 
                  offset |= !S << 20;
                  offset |= J2 << 19;
@@ -3974,7 +4103,7 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
                  unsigned int S = (given & 0x04000000u) >> 26;
                  unsigned int I1 = (given & 0x00002000u) >> 13;
                  unsigned int I2 = (given & 0x00000800u) >> 11;
-                 int offset = 0;
+                 bfd_vma offset = 0;
 
                  offset |= !S << 24;
                  offset |= !(I1 ^ S) << 23;
@@ -4058,6 +4187,20 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
                    if (given & 0x100)
                      func (stream, "c");
                  }
+               else if ((given & 0x20) == 0x20)
+                 {
+                   char const* name;
+                   unsigned sysm = (given & 0xf00) >> 8;
+
+                   sysm |= (given & 0x30);
+                   sysm |= (given & 0x00100000) >> 14;
+                   name = banked_regname (sysm);
+                   
+                   if (name != NULL)
+                     func (stream, "%s", name);
+                   else
+                     func (stream, "(UNDEF: %lu)", sysm);
+                 }
                else
                  {
                    func (stream, psr_name (given & 0xff));
@@ -4065,8 +4208,21 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
                break;
 
              case 'D':
-               if ((given & 0xff) == 0)
-                 func (stream, "%cPSR", (given & 0x100000) ? 'S' : 'C');
+               if (((given & 0xff) == 0)
+                   || ((given & 0x20) == 0x20))
+                 {
+                   char const* name;
+                   unsigned sm = (given & 0xf0000) >> 16;
+
+                   sm |= (given & 0x30);
+                   sm |= (given & 0x00100000) >> 14;
+                   name = banked_regname (sm);
+
+                   if (name != NULL)
+                     func (stream, "%s", name);
+                   else
+                     func (stream, "(UNDEF: %lu)", sm);
+                 }
                else
                  func (stream, psr_name (given & 0xff));
                break;
@@ -4130,6 +4286,21 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
                }
                break;
 
+             case 'L':
+               /* PR binutils/12534
+                  If we have a PC relative offset in an LDRD or STRD
+                  instructions then display the decoded address.  */
+               if (((given >> 16) & 0xf) == 0xf)
+                 {
+                   bfd_vma offset = (given & 0xff) * 4;
+
+                   if ((given & (1 << 23)) == 0)
+                     offset = - offset;
+                   func (stream, "\t; ");
+                   info->print_address_func ((pc & ~3) + 4 + offset, info);
+                 }
+               break;
+
              default:
                abort ();
              }
@@ -4382,9 +4553,12 @@ get_sym_code_type (struct disassemble_info *info,
   type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
 
   /* If the symbol has function type then use that.  */
-  if (type == STT_FUNC || type == STT_ARM_TFUNC)
+  if (type == STT_FUNC || type == STT_GNU_IFUNC)
     {
-      *map_type = (type == STT_ARM_TFUNC) ? MAP_THUMB : MAP_ARM;
+      if (ARM_SYM_BRANCH_TYPE (&es->internal_elf_sym) == ST_BRANCH_TO_THUMB)
+       *map_type = MAP_THUMB;
+      else
+       *map_type = MAP_ARM;
       return TRUE;
     }
 
@@ -4489,6 +4663,8 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
       select_arm_features (info->mach, & private.features);
 
       private.has_mapping_symbols = -1;
+      private.last_mapping_sym = -1;
+      private.last_mapping_addr = 0;
 
       info->private_data = & private;
     }
@@ -4512,8 +4688,8 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
       /* Start scanning at the start of the function, or wherever
         we finished last time.  */
       start = info->symtab_pos + 1;
-      if (start < last_mapping_sym)
-       start = last_mapping_sym;
+      if (start < private_data->last_mapping_sym)
+       start = private_data->last_mapping_sym;
       found = FALSE;
 
       /* First, look for mapping symbols.  */
@@ -4535,7 +4711,7 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
          if (!found)
            {
              /* No mapping symbol found at this address.  Look backwards
-                for a preceeding one.  */
+                for a preceding one.  */
              for (n = start - 1; n >= 0; n--)
                {
                  if (get_map_sym_type (info, n, &type))
@@ -4595,7 +4771,7 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
          if (!found)
            {
              /* No mapping symbol found at this address.  Look backwards
-                for a preceeding one.  */
+                for a preceding one.  */
              for (n = start - 1; n >= 0; n--)
                {
                  if (get_sym_code_type (info, n, &type))
@@ -4608,10 +4784,10 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
            }
        }
 
-      last_mapping_sym = last_sym;
-      last_type = type;
-      is_thumb = (last_type == MAP_THUMB);
-      is_data = (last_type == MAP_DATA);
+      private_data->last_mapping_sym = last_sym;
+      private_data->last_type = type;
+      is_thumb = (private_data->last_type == MAP_THUMB);
+      is_data = (private_data->last_type == MAP_DATA);
 
       /* Look a little bit ahead to see if we should print out
         two or four bytes of data.  If there's a symbol,
@@ -4664,7 +4840,9 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
          es = *(elf_symbol_type **)(info->symbols);
          type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
 
-         is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
+         is_thumb = ((ARM_SYM_BRANCH_TYPE (&es->internal_elf_sym)
+                      == ST_BRANCH_TO_THUMB)
+                     || type == STT_ARM_16BIT);
        }
     }
 
@@ -4815,5 +4993,5 @@ the -M switch:\n"));
             regnames[i].description);
 
   fprintf (stream, "  force-thumb              Assume all insns are Thumb insns\n");
-  fprintf (stream, "  no-force-thumb           Examine preceeding label to determine an insn's type\n\n");
+  fprintf (stream, "  no-force-thumb           Examine preceding label to determine an insn's type\n\n");
 }
This page took 0.034994 seconds and 4 git commands to generate.