gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / opcodes / microblaze-dis.c
index f691740dfd13bd6def7f21a33439a98957049114..be1534c257c8ca2db8f18fe9a80889c092db83ae 100644 (file)
@@ -1,6 +1,6 @@
 /* Disassemble Xilinx microblaze instructions.
 
-   Copyright (C) 2009-2019 Free Software Foundation, Inc.
+   Copyright (C) 2009-2020 Free Software Foundation, Inc.
 
    This file is part of the GNU opcodes library.
 
 #include "microblaze-opc.h"
 #include "microblaze-dis.h"
 
-#define get_field_rd(instr)        get_field (instr, RD_MASK, RD_LOW)
-#define get_field_r1(instr)        get_field (instr, RA_MASK, RA_LOW)
-#define get_field_r2(instr)        get_field (instr, RB_MASK, RB_LOW)
+#define get_field_rd(buf, instr)   get_field (buf, instr, RD_MASK, RD_LOW)
+#define get_field_r1(buf, instr)   get_field (buf, instr, RA_MASK, RA_LOW)
+#define get_field_r2(buf, instr)   get_field (buf, instr, RB_MASK, RB_LOW)
 #define get_int_field_imm(instr)   ((instr & IMM_MASK) >> IMM_LOW)
 #define get_int_field_r1(instr)    ((instr & RA_MASK) >> RA_LOW)
 
+#define NUM_STRBUFS 3
+#define STRBUF_SIZE 25
 
+struct string_buf
+{
+  unsigned int which;
+  char str[NUM_STRBUFS][STRBUF_SIZE];
+};
+
+static inline char *
+strbuf (struct string_buf *buf)
+{
+#ifdef ENABLE_CHECKING
+  if (buf->which >= NUM_STRBUFS)
+    abort ();
+#endif
+  return buf->str[buf->which++];
+}
 
 static char *
-get_field (long instr, long mask, unsigned short low)
+get_field (struct string_buf *buf, long instr, long mask, unsigned short low)
 {
-  char tmpstr[25];
+  char *p = strbuf (buf);
 
-  sprintf (tmpstr, "%s%d", register_prefix, (int)((instr & mask) >> low));
-  return (strdup (tmpstr));
+  sprintf (p, "%s%d", register_prefix, (int)((instr & mask) >> low));
+  return p;
 }
 
 static char *
-get_field_imm (long instr)
+get_field_imm (struct string_buf *buf, long instr)
 {
-  char tmpstr[25];
+  char *p = strbuf (buf);
 
-  sprintf (tmpstr, "%d", (short)((instr & IMM_MASK) >> IMM_LOW));
-  return (strdup (tmpstr));
+  sprintf (p, "%d", (short)((instr & IMM_MASK) >> IMM_LOW));
+  return p;
 }
 
 static char *
-get_field_imm5 (long instr)
+get_field_imm5 (struct string_buf *buf, long instr)
 {
-  char tmpstr[25];
+  char *p = strbuf (buf);
 
-  sprintf (tmpstr, "%d", (short)((instr & IMM5_MASK) >> IMM_LOW));
-  return (strdup (tmpstr));
+  sprintf (p, "%d", (short)((instr & IMM5_MASK) >> IMM_LOW));
+  return p;
 }
 
 static char *
-get_field_imm5_mbar (long instr)
+get_field_imm5_mbar (struct string_buf *buf, long instr)
 {
-  char tmpstr[25];
+  char *p = strbuf (buf);
 
-  sprintf(tmpstr, "%d", (short)((instr & IMM5_MBAR_MASK) >> IMM_MBAR));
-  return(strdup(tmpstr));
+  sprintf (p, "%d", (short)((instr & IMM5_MBAR_MASK) >> IMM_MBAR));
+  return p;
 }
 
 static char *
-get_field_rfsl (long instr)
+get_field_rfsl (struct string_buf *buf, long instr)
 {
-  char tmpstr[25];
+  char *p = strbuf (buf);
 
-  sprintf (tmpstr, "%s%d", fsl_register_prefix,
+  sprintf (p, "%s%d", fsl_register_prefix,
           (short)((instr & RFSL_MASK) >> IMM_LOW));
-  return (strdup (tmpstr));
+  return p;
 }
 
 static char *
-get_field_imm15 (long instr)
+get_field_imm15 (struct string_buf *buf, long instr)
 {
-  char tmpstr[25];
+  char *p = strbuf (buf);
 
-  sprintf (tmpstr, "%d", (short)((instr & IMM15_MASK) >> IMM_LOW));
-  return (strdup (tmpstr));
+  sprintf (p, "%d", (short)((instr & IMM15_MASK) >> IMM_LOW));
+  return p;
 }
 
 static char *
-get_field_special (long instr, struct op_code_struct * op)
+get_field_special (struct string_buf *buf, long instr,
+                  struct op_code_struct *op)
 {
-  char tmpstr[25];
-  char spr[6];
+  char *p = strbuf (buf);
+  char *spr;
 
   switch ((((instr & IMM_MASK) >> IMM_LOW) ^ op->immval_mask))
     {
     case REG_MSR_MASK :
-      strcpy (spr, "msr");
+      spr = "msr";
       break;
     case REG_PC_MASK :
-      strcpy (spr, "pc");
+      spr = "pc";
       break;
     case REG_EAR_MASK :
-      strcpy (spr, "ear");
+      spr = "ear";
       break;
     case REG_ESR_MASK :
-      strcpy (spr, "esr");
+      spr = "esr";
       break;
     case REG_FSR_MASK :
-      strcpy (spr, "fsr");
+      spr = "fsr";
       break;
     case REG_BTR_MASK :
-      strcpy (spr, "btr");
+      spr = "btr";
       break;
     case REG_EDR_MASK :
-      strcpy (spr, "edr");
+      spr = "edr";
       break;
     case REG_PID_MASK :
-      strcpy (spr, "pid");
+      spr = "pid";
       break;
     case REG_ZPR_MASK :
-      strcpy (spr, "zpr");
+      spr = "zpr";
       break;
     case REG_TLBX_MASK :
-      strcpy (spr, "tlbx");
+      spr = "tlbx";
       break;
     case REG_TLBLO_MASK :
-      strcpy (spr, "tlblo");
+      spr = "tlblo";
       break;
     case REG_TLBHI_MASK :
-      strcpy (spr, "tlbhi");
+      spr = "tlbhi";
       break;
     case REG_TLBSX_MASK :
-      strcpy (spr, "tlbsx");
+      spr = "tlbsx";
       break;
     case REG_SHR_MASK :
-      strcpy (spr, "shr");
+      spr = "shr";
       break;
     case REG_SLR_MASK :
-      strcpy (spr, "slr");
+      spr = "slr";
       break;
     default :
       if (((((instr & IMM_MASK) >> IMM_LOW) ^ op->immval_mask) & 0xE000)
-          == REG_PVR_MASK)
-        {
-         sprintf (tmpstr, "%spvr%d", register_prefix,
+         == REG_PVR_MASK)
+       {
+         sprintf (p, "%spvr%d", register_prefix,
                   (unsigned short)(((instr & IMM_MASK) >> IMM_LOW)
-                                    ^ op->immval_mask) ^ REG_PVR_MASK);
-         return (strdup (tmpstr));
-        }
+                                   ^ op->immval_mask) ^ REG_PVR_MASK);
+         return p;
+       }
       else
-        strcpy (spr, "pc");
+       spr = "pc";
       break;
     }
 
-   sprintf (tmpstr, "%s%s", register_prefix, spr);
-   return (strdup (tmpstr));
+   sprintf (p, "%s%s", register_prefix, spr);
+   return p;
 }
 
 static unsigned long
@@ -182,9 +200,11 @@ read_insn_microblaze (bfd_vma memaddr,
     }
 
   if (info->endian == BFD_ENDIAN_BIG)
-    inst = (ibytes[0] << 24) | (ibytes[1] << 16) | (ibytes[2] << 8) | ibytes[3];
+    inst = (((unsigned) ibytes[0] << 24) | (ibytes[1] << 16)
+           | (ibytes[2] << 8) | ibytes[3]);
   else if (info->endian == BFD_ENDIAN_LITTLE)
-    inst = (ibytes[3] << 24) | (ibytes[2] << 16) | (ibytes[1] << 8) | ibytes[0];
+    inst = (((unsigned) ibytes[3] << 24) | (ibytes[2] << 16)
+           | (ibytes[1] << 8) | ibytes[0]);
   else
     abort ();
 
@@ -210,7 +230,9 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
   static bfd_vma      prev_insn_addr = -1; /* Init the prev insn addr.  */
   static int          prev_insn_vma = -1;  /* Init the prev insn vma.  */
   int                 curr_insn_vma = info->buffer_vma;
+  struct string_buf   buf;
 
+  buf.which = 0;
   info->bytes_per_chunk = 4;
 
   inst = read_insn_microblaze (memaddr, info, &op);
@@ -220,8 +242,8 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
   if (prev_insn_vma == curr_insn_vma)
     {
       if (memaddr-(info->bytes_per_chunk) == prev_insn_addr)
-        {
-          prev_inst = read_insn_microblaze (prev_insn_addr, info, &pop);
+       {
+         prev_inst = read_insn_microblaze (prev_insn_addr, info, &pop);
          if (prev_inst == 0)
            return -1;
          if (pop->instr == imm)
@@ -249,163 +271,173 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
 
       switch (op->inst_type)
        {
-        case INST_TYPE_RD_R1_R2:
-          print_func (stream, "\t%s, %s, %s", get_field_rd (inst),
-                  get_field_r1(inst), get_field_r2 (inst));
-          break;
-        case INST_TYPE_RD_R1_IMM:
-         print_func (stream, "\t%s, %s, %s", get_field_rd (inst),
-                  get_field_r1(inst), get_field_imm (inst));
+       case INST_TYPE_RD_R1_R2:
+         print_func (stream, "\t%s, %s, %s", get_field_rd (&buf, inst),
+                     get_field_r1 (&buf, inst), get_field_r2 (&buf, inst));
+         break;
+       case INST_TYPE_RD_R1_IMM:
+         print_func (stream, "\t%s, %s, %s", get_field_rd (&buf, inst),
+                     get_field_r1 (&buf, inst), get_field_imm (&buf, inst));
          if (info->print_address_func && get_int_field_r1 (inst) == 0
              && info->symbol_at_address_func)
            {
              if (immfound)
-               immval |= (get_int_field_imm (inst) & 0x0000ffff);
+               immval |= (get_int_field_imm (inst) & 0x0000ffff);
              else
                {
-                 immval = get_int_field_imm (inst);
-                 if (immval & 0x8000)
+                 immval = get_int_field_imm (inst);
+                 if (immval & 0x8000)
                    immval |= 0xFFFF0000;
-               }
+               }
              if (immval > 0 && info->symbol_at_address_func (immval, info))
                {
-                 print_func (stream, "\t// ");
-                 info->print_address_func (immval, info);
-               }
+                 print_func (stream, "\t// ");
+                 info->print_address_func (immval, info);
+               }
            }
          break;
        case INST_TYPE_RD_R1_IMM5:
-         print_func (stream, "\t%s, %s, %s", get_field_rd (inst),
-                  get_field_r1(inst), get_field_imm5 (inst));
+         print_func (stream, "\t%s, %s, %s", get_field_rd (&buf, inst),
+                     get_field_r1 (&buf, inst), get_field_imm5 (&buf, inst));
          break;
        case INST_TYPE_RD_RFSL:
-         print_func (stream, "\t%s, %s", get_field_rd (inst), get_field_rfsl (inst));
+         print_func (stream, "\t%s, %s", get_field_rd (&buf, inst),
+                     get_field_rfsl (&buf, inst));
          break;
        case INST_TYPE_R1_RFSL:
-         print_func (stream, "\t%s, %s", get_field_r1 (inst), get_field_rfsl (inst));
+         print_func (stream, "\t%s, %s", get_field_r1 (&buf, inst),
+                     get_field_rfsl (&buf, inst));
          break;
        case INST_TYPE_RD_SPECIAL:
-         print_func (stream, "\t%s, %s", get_field_rd (inst),
-                  get_field_special (inst, op));
+         print_func (stream, "\t%s, %s", get_field_rd (&buf, inst),
+                     get_field_special (&buf, inst, op));
          break;
        case INST_TYPE_SPECIAL_R1:
-         print_func (stream, "\t%s, %s", get_field_special (inst, op),
-                  get_field_r1(inst));
+         print_func (stream, "\t%s, %s", get_field_special (&buf, inst, op),
+                     get_field_r1 (&buf, inst));
          break;
        case INST_TYPE_RD_R1:
-         print_func (stream, "\t%s, %s", get_field_rd (inst), get_field_r1 (inst));
+         print_func (stream, "\t%s, %s", get_field_rd (&buf, inst),
+                     get_field_r1 (&buf, inst));
          break;
        case INST_TYPE_R1_R2:
-         print_func (stream, "\t%s, %s", get_field_r1 (inst), get_field_r2 (inst));
+         print_func (stream, "\t%s, %s", get_field_r1 (&buf, inst),
+                     get_field_r2 (&buf, inst));
          break;
        case INST_TYPE_R1_IMM:
-         print_func (stream, "\t%s, %s", get_field_r1 (inst), get_field_imm (inst));
+         print_func (stream, "\t%s, %s", get_field_r1 (&buf, inst),
+                     get_field_imm (&buf, inst));
          /* The non-pc relative instructions are returns, which shouldn't
             have a label printed.  */
          if (info->print_address_func && op->inst_offset_type == INST_PC_OFFSET
              && info->symbol_at_address_func)
            {
              if (immfound)
-               immval |= (get_int_field_imm (inst) & 0x0000ffff);
+               immval |= (get_int_field_imm (inst) & 0x0000ffff);
              else
                {
-                 immval = get_int_field_imm (inst);
-                 if (immval & 0x8000)
+                 immval = get_int_field_imm (inst);
+                 if (immval & 0x8000)
                    immval |= 0xFFFF0000;
-               }
+               }
              immval += memaddr;
              if (immval > 0 && info->symbol_at_address_func (immval, info))
                {
-                 print_func (stream, "\t// ");
-                 info->print_address_func (immval, info);
-               }
+                 print_func (stream, "\t// ");
+                 info->print_address_func (immval, info);
+               }
              else
                {
-                 print_func (stream, "\t\t// ");
-                 print_func (stream, "%x", immval);
-               }
+                 print_func (stream, "\t\t// ");
+                 print_func (stream, "%x", immval);
+               }
            }
          break;
-        case INST_TYPE_RD_IMM:
-         print_func (stream, "\t%s, %s", get_field_rd (inst), get_field_imm (inst));
+       case INST_TYPE_RD_IMM:
+         print_func (stream, "\t%s, %s", get_field_rd (&buf, inst),
+                     get_field_imm (&buf, inst));
          if (info->print_address_func && info->symbol_at_address_func)
            {
-           if (immfound)
-             immval |= (get_int_field_imm (inst) & 0x0000ffff);
-           else
-             {
-               immval = get_int_field_imm (inst);
-               if (immval & 0x8000)
-                 immval |= 0xFFFF0000;
-             }
-           if (op->inst_offset_type == INST_PC_OFFSET)
-             immval += (int) memaddr;
-           if (info->symbol_at_address_func (immval, info))
-             {
-               print_func (stream, "\t// ");
-               info->print_address_func (immval, info);
-             }
+             if (immfound)
+               immval |= (get_int_field_imm (inst) & 0x0000ffff);
+             else
+               {
+                 immval = get_int_field_imm (inst);
+                 if (immval & 0x8000)
+                   immval |= 0xFFFF0000;
+               }
+             if (op->inst_offset_type == INST_PC_OFFSET)
+               immval += (int) memaddr;
+             if (info->symbol_at_address_func (immval, info))
+               {
+                 print_func (stream, "\t// ");
+                 info->print_address_func (immval, info);
+               }
            }
          break;
-        case INST_TYPE_IMM:
-         print_func (stream, "\t%s", get_field_imm (inst));
+       case INST_TYPE_IMM:
+         print_func (stream, "\t%s", get_field_imm (&buf, inst));
          if (info->print_address_func && info->symbol_at_address_func
              && op->instr != imm)
            {
              if (immfound)
-               immval |= (get_int_field_imm (inst) & 0x0000ffff);
+               immval |= (get_int_field_imm (inst) & 0x0000ffff);
              else
                {
-                 immval = get_int_field_imm (inst);
-                 if (immval & 0x8000)
+                 immval = get_int_field_imm (inst);
+                 if (immval & 0x8000)
                    immval |= 0xFFFF0000;
-               }
+               }
              if (op->inst_offset_type == INST_PC_OFFSET)
-               immval += (int) memaddr;
+               immval += (int) memaddr;
              if (immval > 0 && info->symbol_at_address_func (immval, info))
                {
-                 print_func (stream, "\t// ");
-                 info->print_address_func (immval, info);
-               }
+                 print_func (stream, "\t// ");
+                 info->print_address_func (immval, info);
+               }
              else if (op->inst_offset_type == INST_PC_OFFSET)
                {
-                 print_func (stream, "\t\t// ");
-                 print_func (stream, "%x", immval);
-               }
+                 print_func (stream, "\t\t// ");
+                 print_func (stream, "%x", immval);
+               }
            }
          break;
-        case INST_TYPE_RD_R2:
-         print_func (stream, "\t%s, %s", get_field_rd (inst), get_field_r2 (inst));
+       case INST_TYPE_RD_R2:
+         print_func (stream, "\t%s, %s", get_field_rd (&buf, inst),
+                     get_field_r2 (&buf, inst));
          break;
        case INST_TYPE_R2:
-         print_func (stream, "\t%s", get_field_r2 (inst));
+         print_func (stream, "\t%s", get_field_r2 (&buf, inst));
          break;
        case INST_TYPE_R1:
-         print_func (stream, "\t%s", get_field_r1 (inst));
+         print_func (stream, "\t%s", get_field_r1 (&buf, inst));
          break;
        case INST_TYPE_R1_R2_SPECIAL:
-         print_func (stream, "\t%s, %s", get_field_r1 (inst), get_field_r2 (inst));
+         print_func (stream, "\t%s, %s", get_field_r1 (&buf, inst),
+                     get_field_r2 (&buf, inst));
          break;
        case INST_TYPE_RD_IMM15:
-         print_func (stream, "\t%s, %s", get_field_rd (inst), get_field_imm15 (inst));
+         print_func (stream, "\t%s, %s", get_field_rd (&buf, inst),
+                     get_field_imm15 (&buf, inst));
          break;
-        /* For mbar insn.  */
-        case INST_TYPE_IMM5:
-          print_func (stream, "\t%s", get_field_imm5_mbar (inst));
-          break;
-        /* For mbar 16 or sleep insn.  */
-        case INST_TYPE_NONE:
-          break;
-       /* For tuqula instruction */
+         /* For mbar insn.  */
+       case INST_TYPE_IMM5:
+         print_func (stream, "\t%s", get_field_imm5_mbar (&buf, inst));
+         break;
+         /* For mbar 16 or sleep insn.  */
+       case INST_TYPE_NONE:
+         break;
+         /* For tuqula instruction */
        case INST_TYPE_RD:
-         print_func (stream, "\t%s", get_field_rd (inst));
+         print_func (stream, "\t%s", get_field_rd (&buf, inst));
          break;
        case INST_TYPE_RFSL:
-         print_func (stream, "\t%s", get_field_rfsl (inst));
+         print_func (stream, "\t%s", get_field_rfsl (&buf, inst));
          break;
        default:
          /* If the disassembler lags the instruction set.  */
-         print_func (stream, "\tundecoded operands, inst is 0x%04x", (unsigned int) inst);
+         print_func (stream, "\tundecoded operands, inst is 0x%04x",
+                     (unsigned int) inst);
          break;
        }
     }
This page took 0.033381 seconds and 4 git commands to generate.