]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - opcodes/microblaze-dis.c
Use bool in opcodes
[thirdparty/binutils-gdb.git] / opcodes / microblaze-dis.c
index 1bbeeaddc008f75d11f241af74f90918f9ba53aa..aa75c4cc1fd12e01e8078e30f037ac2a4b8e47e3 100644 (file)
@@ -1,6 +1,6 @@
 /* Disassemble Xilinx microblaze instructions.
 
-   Copyright 2009 Free Software Foundation, Inc.
+   Copyright (C) 2009-2021 Free Software Foundation, Inc.
 
    This file is part of the GNU opcodes library.
 
 #define STATIC_TABLE
 #define DEFINE_TABLE
 
-#include "dis-asm.h"
+#include "disassemble.h"
 #include <strings.h>
 #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_rfsl (long instr)
+get_field_imm5_mbar (struct string_buf *buf, long instr)
 {
-  char tmpstr[25];
+  char *p = strbuf (buf);
+
+  sprintf (p, "%d", (short)((instr & IMM5_MBAR_MASK) >> IMM_MBAR));
+  return p;
+}
 
-  sprintf (tmpstr, "%s%d", fsl_register_prefix,
+static char *
+get_field_rfsl (struct string_buf *buf, long instr)
+{
+  char *p = strbuf (buf);
+
+  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 :
+      spr = "shr";
+      break;
+    case REG_SLR_MASK :
+      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
@@ -167,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 ();
 
@@ -186,16 +221,18 @@ read_insn_microblaze (bfd_vma memaddr,
 int
 print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
 {
-  fprintf_ftype       print_func = info->fprintf_func;
-  void *              stream = info->stream;
-  unsigned long       inst, prev_inst;
-  struct op_code_struct * op, *pop;
-  int                 immval = 0;
-  bfd_boolean         immfound = FALSE;
-  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;
-
+  fprintf_ftype print_func = info->fprintf_func;
+  void *stream = info->stream;
+  unsigned long inst, prev_inst;
+  struct op_code_struct *op, *pop;
+  int immval = 0;
+  bool immfound = false;
+  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);
@@ -205,19 +242,19 @@ 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)
            {
              immval = (get_int_field_imm (prev_inst) << 16) & 0xffff0000;
-             immfound = TRUE;
+             immfound = true;
            }
          else
            {
              immval = 0;
-             immfound = FALSE;
+             immfound = false;
            }
        }
     }
@@ -227,163 +264,180 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
   prev_insn_vma = curr_insn_vma;
 
   if (op->name == NULL)
-    print_func (stream, ".short 0x%04x", inst);
+    print_func (stream, ".short 0x%04x", (unsigned int) inst);
   else
     {
       print_func (stream, "%s", op->name);
 
       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_RD_R1_SPECIAL:
-         print_func (stream, "\t%s, %s", get_field_rd (inst), get_field_r2 (inst));
+       case INST_TYPE_R1_R2_SPECIAL:
+         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 (&buf, inst));
+         break;
+         /* For mbar 16 or sleep insn.  */
+       case INST_TYPE_NONE:
          break;
-       /* For tuqula instruction */
+         /* 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", inst);
+         print_func (stream, "\tundecoded operands, inst is 0x%04x",
+                     (unsigned int) inst);
          break;
        }
     }
@@ -394,12 +448,12 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
 
 enum microblaze_instr
 get_insn_microblaze (long inst,
-                    bfd_boolean *isunsignedimm,
+                    bool *isunsignedimm,
                     enum microblaze_instr_type *insn_type,
                     short *delay_slots)
 {
   struct op_code_struct * op;
-  *isunsignedimm = FALSE;
+  *isunsignedimm = false;
 
   /* Just a linear search of the table.  */
   for (op = opcodes; op->name != 0; op ++)
@@ -421,7 +475,7 @@ enum microblaze_instr
 microblaze_decode_insn (long insn, int *rd, int *ra, int *rb, int *immed)
 {
   enum microblaze_instr op;
-  bfd_boolean t1;
+  bool t1;
   enum microblaze_instr_type t2;
   short t3;
 
@@ -435,15 +489,15 @@ microblaze_decode_insn (long insn, int *rd, int *ra, int *rb, int *immed)
 }
 
 unsigned long
-microblaze_get_target_address (long inst, bfd_boolean immfound, int immval,
+microblaze_get_target_address (long inst, bool immfound, int immval,
                               long pcval, long r1val, long r2val,
-                              bfd_boolean *targetvalid,
-                              bfd_boolean *unconditionalbranch)
+                              bool *targetvalid,
+                              bool *unconditionalbranch)
 {
   struct op_code_struct * op;
   long targetaddr = 0;
 
-  *unconditionalbranch = FALSE;
+  *unconditionalbranch = false;
   /* Just a linear search of the table.  */
   for (op = opcodes; op->name != 0; op ++)
     if (op->bit_sequence == (inst & op->opcode_mask))
@@ -451,24 +505,24 @@ microblaze_get_target_address (long inst, bfd_boolean immfound, int immval,
 
   if (op->name == 0)
     {
-      *targetvalid = FALSE;
+      *targetvalid = false;
     }
   else if (op->instr_type == branch_inst)
     {
       switch (op->inst_type)
        {
         case INST_TYPE_R2:
-          *unconditionalbranch = TRUE;
+          *unconditionalbranch = true;
         /* Fall through.  */
         case INST_TYPE_RD_R2:
         case INST_TYPE_R1_R2:
           targetaddr = r2val;
-          *targetvalid = TRUE;
+          *targetvalid = true;
           if (op->inst_offset_type == INST_PC_OFFSET)
            targetaddr += pcval;
           break;
         case INST_TYPE_IMM:
-          *unconditionalbranch = TRUE;
+          *unconditionalbranch = true;
         /* Fall through.  */
         case INST_TYPE_RD_IMM:
         case INST_TYPE_R1_IMM:
@@ -485,10 +539,10 @@ microblaze_get_target_address (long inst, bfd_boolean immfound, int immval,
             }
           if (op->inst_offset_type == INST_PC_OFFSET)
            targetaddr += pcval;
-          *targetvalid = TRUE;
+          *targetvalid = true;
           break;
        default:
-         *targetvalid = FALSE;
+         *targetvalid = false;
          break;
         }
     }
@@ -506,9 +560,9 @@ microblaze_get_target_address (long inst, bfd_boolean immfound, int immval,
            targetaddr |= 0xFFFF0000;
        }
       targetaddr += r1val;
-      *targetvalid = TRUE;
+      *targetvalid = true;
     }
   else
-    *targetvalid = FALSE;
+    *targetvalid = false;
   return targetaddr;
 }