* exec.c (xfer_memory): Add attrib argument.
[deliverable/binutils-gdb.git] / gdb / mips-tdep.c
index 0ca1eaf57adc0650db6929a018c44a2f25c8045d..17b80ca3f19ebe282ffac67b454579117f825de5 100644 (file)
@@ -861,34 +861,23 @@ enum mips16_inst_fmts
   extRi64type,                 /* 20  5,6,5,5,3,3,5 */
   extshift64type               /* 21  5,5,1,1,1,1,1,1,5,1,1,1,3,5 */
 };
-/* I am heaping all the fields of the formats into one structure and then,
-   only the fields which are involved in instruction extension */
+/* I am heaping all the fields of the formats into one structure and
+   then, only the fields which are involved in instruction extension */
 struct upk_mips16
   {
-    unsigned short inst;
-    enum mips16_inst_fmts fmt;
-    unsigned long offset;
+    CORE_ADDR offset;
     unsigned int regx;         /* Function in i8 type */
     unsigned int regy;
   };
 
 
+/* The EXT-I, EXT-ri nad EXT-I8 instructions all have the same format
+   for the bits which make up the immediatate extension.  */
 
-static void
-print_unpack (char *comment,
-             struct upk_mips16 *u)
-{
-  printf ("%s %04x ,f(%d) off(%s) (x(%x) y(%x)\n",
-         comment, u->inst, u->fmt, paddr (u->offset), u->regx, u->regy);
-}
-
-/* The EXT-I, EXT-ri nad EXT-I8 instructions all have the same
-   format for the bits which make up the immediatate extension.
- */
-static unsigned long
-extended_offset (unsigned long extension)
+static CORE_ADDR
+extended_offset (unsigned int extension)
 {
-  unsigned long value;
+  CORE_ADDR value;
   value = (extension >> 21) & 0x3f;    /* * extract 15:11 */
   value = value << 6;
   value |= (extension >> 16) & 0x1f;   /* extrace 10:5 */
@@ -906,7 +895,7 @@ extended_offset (unsigned long extension)
    when the offset is to be used in relative addressing */
 
 
-static unsigned short
+static unsigned int
 fetch_mips_16 (CORE_ADDR pc)
 {
   char buf[8];
@@ -917,36 +906,33 @@ fetch_mips_16 (CORE_ADDR pc)
 
 static void
 unpack_mips16 (CORE_ADDR pc,
+              unsigned int extension,
+              unsigned int inst,
+              enum mips16_inst_fmts insn_format,
               struct upk_mips16 *upk)
 {
-  CORE_ADDR extpc;
-  unsigned long extension;
-  int extended;
-  extpc = (pc - 4) & ~0x01;    /* Extensions are 32 bit instructions */
-  /* Decrement to previous address and loose the 16bit mode flag */
-  /* return if the instruction was extendable, but not actually extended */
-  extended = ((mips32_op (extension) == 30) ? 1 : 0);
-  if (extended)
-    {
-      extension = mips_fetch_instruction (extpc);
-    }
-  switch (upk->fmt)
+  CORE_ADDR offset;
+  int regx;
+  int regy;
+  switch (insn_format)
     {
     case itype:
       {
-       unsigned long value;
-       if (extended)
+       CORE_ADDR value;
+       if (extension)
          {
            value = extended_offset (extension);
            value = value << 11;        /* rom for the original value */
-           value |= upk->inst & 0x7ff;         /* eleven bits from instruction */
+           value |= inst & 0x7ff;              /* eleven bits from instruction */
          }
        else
          {
-           value = upk->inst & 0x7ff;
+           value = inst & 0x7ff;
            /* FIXME : Consider sign extension */
          }
-       upk->offset = value;
+       offset = value;
+       regx = -1;
+       regy = -1;
       }
       break;
     case ritype:
@@ -954,13 +940,13 @@ unpack_mips16 (CORE_ADDR pc,
       {                                /* A register identifier and an offset */
        /* Most of the fields are the same as I type but the
           immediate value is of a different length */
-       unsigned long value;
-       if (extended)
+       CORE_ADDR value;
+       if (extension)
          {
            value = extended_offset (extension);
            value = value << 8; /* from the original instruction */
-           value |= upk->inst & 0xff;  /* eleven bits from instruction */
-           upk->regx = (extension >> 8) & 0x07;        /* or i8 funct */
+           value |= inst & 0xff;       /* eleven bits from instruction */
+           regx = (extension >> 8) & 0x07;     /* or i8 funct */
            if (value & 0x4000) /* test the sign bit , bit 26 */
              {
                value &= ~0x3fff;       /* remove the sign bit */
@@ -969,48 +955,41 @@ unpack_mips16 (CORE_ADDR pc,
          }
        else
          {
-           value = upk->inst & 0xff;   /* 8 bits */
-           upk->regx = (upk->inst >> 8) & 0x07;        /* or i8 funct */
+           value = inst & 0xff;        /* 8 bits */
+           regx = (inst >> 8) & 0x07;  /* or i8 funct */
            /* FIXME: Do sign extension , this format needs it */
            if (value & 0x80)   /* THIS CONFUSES ME */
              {
                value &= 0xef;  /* remove the sign bit */
                value = -value;
              }
-
          }
-       upk->offset = value;
+       offset = value;
+       regy = -1;
        break;
       }
     case jalxtype:
       {
        unsigned long value;
-       unsigned short nexthalf;
-       value = ((upk->inst & 0x1f) << 5) | ((upk->inst >> 5) & 0x1f);
+       unsigned int nexthalf;
+       value = ((inst & 0x1f) << 5) | ((inst >> 5) & 0x1f);
        value = value << 16;
        nexthalf = mips_fetch_instruction (pc + 2);     /* low bit still set */
        value |= nexthalf;
-       upk->offset = value;
+       offset = value;
+       regx = -1;
+       regy = -1;
        break;
       }
     default:
-      printf_filtered ("Decoding unimplemented instruction format type\n");
-      break;
+      internal_error ("%s:%d: bad switch", __FILE__, __LINE__);
     }
-  /* print_unpack("UPK",upk) ; */
+  upk->offset = offset;
+  upk->regx = regx;
+  upk->regy = regy;
 }
 
 
-#define mips16_op(x) (x >> 11)
-
-/* This is a map of the opcodes which ae known to perform branches */
-static unsigned char map16[32] =
-{0, 0, 1, 1, 1, 1, 0, 0,
- 0, 0, 0, 0, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 0
-};
-
 static CORE_ADDR
 add_offset_16 (CORE_ADDR pc, int offset)
 {
@@ -1018,137 +997,147 @@ add_offset_16 (CORE_ADDR pc, int offset)
 
 }
 
-
-
-static struct upk_mips16 upk;
-
-CORE_ADDR
-mips16_next_pc (CORE_ADDR pc)
+static CORE_ADDR
+extended_mips16_next_pc (CORE_ADDR pc,
+                        unsigned int extension,
+                        unsigned int insn)
 {
-  int op;
-  t_inst inst;
-  /* inst = mips_fetch_instruction(pc) ; - This doesnt always work */
-  inst = fetch_mips_16 (pc);
-  upk.inst = inst;
-  op = mips16_op (upk.inst);
-  if (map16[op])
+  int op = (insn >> 11);
+  switch (op)
     {
-      int reg;
-      switch (op)
-       {
-       case 2:         /* Branch */
-         upk.fmt = itype;
-         unpack_mips16 (pc, &upk);
+    case 2:            /* Branch */
+      {
+       CORE_ADDR offset;
+       struct upk_mips16 upk;
+       unpack_mips16 (pc, extension, insn, itype, &upk);
+       offset = upk.offset;
+       if (offset & 0x800)
          {
-           long offset;
-           offset = upk.offset;
-           if (offset & 0x800)
+           offset &= 0xeff;
+           offset = -offset;
+         }
+       pc += (offset << 1) + 2;
+       break;
+      }
+    case 3:            /* JAL , JALX - Watch out, these are 32 bit instruction */
+      {
+       struct upk_mips16 upk;
+       unpack_mips16 (pc, extension, insn, jalxtype, &upk);
+       pc = add_offset_16 (pc, upk.offset);
+       if ((insn >> 10) & 0x01)        /* Exchange mode */
+         pc = pc & ~0x01;      /* Clear low bit, indicate 32 bit mode */
+       else
+         pc |= 0x01;
+       break;
+      }
+    case 4:            /* beqz */
+      {
+       struct upk_mips16 upk;
+       int reg;
+       unpack_mips16 (pc, extension, insn, ritype, &upk);
+       reg = read_signed_register (upk.regx);
+       if (reg == 0)
+         pc += (upk.offset << 1) + 2;
+       else
+         pc += 2;
+       break;
+      }
+    case 5:            /* bnez */
+      {
+       struct upk_mips16 upk;
+       int reg;
+       unpack_mips16 (pc, extension, insn, ritype, &upk);
+       reg = read_signed_register (upk.regx);
+       if (reg != 0)
+         pc += (upk.offset << 1) + 2;
+       else
+         pc += 2;
+       break;
+      }
+    case 12:           /* I8 Formats btez btnez */
+      {
+       struct upk_mips16 upk;
+       int reg;
+       unpack_mips16 (pc, extension, insn, i8type, &upk);
+       /* upk.regx contains the opcode */
+       reg = read_signed_register (24);        /* Test register is 24 */
+       if (((upk.regx == 0) && (reg == 0))     /* BTEZ */
+           || ((upk.regx == 1) && (reg != 0))) /* BTNEZ */
+         /* pc = add_offset_16(pc,upk.offset) ; */
+         pc += (upk.offset << 1) + 2;
+       else
+         pc += 2;
+       break;
+      }
+    case 29:           /* RR Formats JR, JALR, JALR-RA */
+      {
+       struct upk_mips16 upk;
+       /* upk.fmt = rrtype; */
+       op = insn & 0x1f;
+       if (op == 0)
+         {
+           int reg;
+           upk.regx = (insn >> 8) & 0x07;
+           upk.regy = (insn >> 5) & 0x07;
+           switch (upk.regy)
              {
-               offset &= 0xeff;
-               offset = -offset;
+             case 0:
+               reg = upk.regx;
+               break;
+             case 1:
+               reg = 31;
+               break;  /* Function return instruction */
+             case 2:
+               reg = upk.regx;
+               break;
+             default:
+               reg = 31;
+               break;  /* BOGUS Guess */
              }
-           pc += (offset << 1) + 2;
+           pc = read_signed_register (reg);
          }
-         break;
-       case 3:         /* JAL , JALX - Watch out, these are 32 bit instruction */
-         upk.fmt = jalxtype;
-         unpack_mips16 (pc, &upk);
-         pc = add_offset_16 (pc, upk.offset);
-         if ((upk.inst >> 10) & 0x01)  /* Exchange mode */
-           pc = pc & ~0x01;    /* Clear low bit, indicate 32 bit mode */
-         else
-           pc |= 0x01;
-         break;
-       case 4:         /* beqz */
-         upk.fmt = ritype;
-         unpack_mips16 (pc, &upk);
-         reg = read_signed_register (upk.regx);
-         if (reg == 0)
-           pc += (upk.offset << 1) + 2;
-         else
-           pc += 2;
-         break;
-       case 5:         /* bnez */
-         upk.fmt = ritype;
-         unpack_mips16 (pc, &upk);
-         reg = read_signed_register (upk.regx);
-         if (reg != 0)
-           pc += (upk.offset << 1) + 2;
-         else
-           pc += 2;
-         break;
-       case 12:                /* I8 Formats btez btnez */
-         upk.fmt = i8type;
-         unpack_mips16 (pc, &upk);
-         /* upk.regx contains the opcode */
-         reg = read_signed_register (24);      /* Test register is 24 */
-         if (((upk.regx == 0) && (reg == 0))   /* BTEZ */
-             || ((upk.regx == 1) && (reg != 0)))       /* BTNEZ */
-           /* pc = add_offset_16(pc,upk.offset) ; */
-           pc += (upk.offset << 1) + 2;
-         else
-           pc += 2;
-         break;
-       case 29:                /* RR Formats JR, JALR, JALR-RA */
-         upk.fmt = rrtype;
-         op = upk.inst & 0x1f;
-         if (op == 0)
-           {
-             upk.regx = (upk.inst >> 8) & 0x07;
-             upk.regy = (upk.inst >> 5) & 0x07;
-             switch (upk.regy)
-               {
-               case 0:
-                 reg = upk.regx;
-                 break;
-               case 1:
-                 reg = 31;
-                 break;        /* Function return instruction */
-               case 2:
-                 reg = upk.regx;
-                 break;
-               default:
-                 reg = 31;
-                 break;        /* BOGUS Guess */
-               }
-             pc = read_signed_register (reg);
-           }
-         else
-           pc += 2;
-         break;
-       case 30:                /* This is an extend instruction */
-         pc += 4;              /* Dont be setting breakpints on the second half */
-         break;
-       default:
-         printf ("Filtered - next PC probably incorrrect due to jump inst\n");
+       else
          pc += 2;
-         break;
-       }
+       break;
+      }
+    case 30:
+      /* This is an instruction extension.  Fetch the real instruction
+         (which follows the extension) and decode things based on
+         that. */
+      {
+       pc += 2;
+       pc = extended_mips16_next_pc (pc, insn, fetch_mips_16 (pc));
+       break;
+      }
+    default:
+      {
+       pc += 2;
+       break;
+      }
     }
-  else
-    pc += 2;                   /* just a good old instruction */
-  /* See if we CAN actually break on the next instruction */
-  /* printf("NXTm16PC %08x\n",(unsigned long)pc) ; */
   return pc;
-}                              /* mips16_next_pc */
+}
 
-/* The mips_next_pc function supports single_tep when the remote target monitor or
-   stub is not developed enough to so a single_step.
-   It works by decoding the current instruction and predicting where a branch
-   will go. This isnt hard because all the data is available.
-   The MIPS32 and MIPS16 variants are quite different
- */
+CORE_ADDR
+mips16_next_pc (CORE_ADDR pc)
+{
+  unsigned int insn = fetch_mips_16 (pc);
+  return extended_mips16_next_pc (pc, 0, insn);
+}
+
+/* The mips_next_pc function supports single_step when the remote
+   target monitor or stub is not developed enough to do a single_step.
+   It works by decoding the current instruction and predicting where a
+   branch will go. This isnt hard because all the data is available.
+   The MIPS32 and MIPS16 variants are quite different */
 CORE_ADDR
 mips_next_pc (CORE_ADDR pc)
 {
-  t_inst inst;
-  /* inst = mips_fetch_instruction(pc) ; */
-  /* if (pc_is_mips16) <----- This is failing */
   if (pc & 0x01)
     return mips16_next_pc (pc);
   else
     return mips32_next_pc (pc);
-}                              /* mips_next_pc */
+}
 
 /* Guaranteed to set fci->saved_regs to some values (it never leaves it
    NULL).  */
@@ -2559,7 +2548,7 @@ mips_pop_frame (void)
       else
        linked_proc_desc_table = pi_ptr->next;
 
-      free (pi_ptr);
+      xfree (pi_ptr);
 
       write_register (HI_REGNUM,
                      read_memory_integer (new_sp - 2 * MIPS_SAVED_REGSIZE,
@@ -3716,7 +3705,7 @@ mips_call_dummy_address (void)
 }
 
 
-/* If the current gcc for for this target does not produce correct debugging
+/* If the current gcc for this target does not produce correct debugging
    information for float parameters, both prototyped and unprototyped, then
    define this macro.  This forces gdb to  always assume that floats are
    passed as doubles and then converted in the callee.
@@ -3812,6 +3801,29 @@ mips_saved_pc_after_call (struct frame_info *frame)
 }
 
 
+/* Convert a dbx stab register number (from `r' declaration) to a gdb
+   REGNUM */
+
+static int
+mips_stab_reg_to_regnum (int num)
+{
+  if (num < 32)
+    return num;
+  else 
+    return num + FP0_REGNUM - 38;
+}
+
+/* Convert a ecoff register number to a gdb REGNUM */
+
+static int
+mips_ecoff_reg_to_regnum (int num)
+{
+  if (num < 32)
+    return num;
+  else
+    return num + FP0_REGNUM - 32;
+}
+
 static struct gdbarch *
 mips_gdbarch_init (struct gdbarch_info info,
                   struct gdbarch_list *arches)
@@ -4053,6 +4065,10 @@ mips_gdbarch_init (struct gdbarch_info info,
   set_gdbarch_read_sp (gdbarch, generic_target_read_sp);
   set_gdbarch_write_sp (gdbarch, generic_target_write_sp);
 
+  /* Map debug register numbers onto internal register numbers. */
+  set_gdbarch_stab_reg_to_regnum (gdbarch, mips_stab_reg_to_regnum);
+  set_gdbarch_ecoff_reg_to_regnum (gdbarch, mips_ecoff_reg_to_regnum);
+
   /* Initialize a frame */
   set_gdbarch_init_extra_frame_info (gdbarch, mips_init_extra_frame_info);
 
@@ -4565,7 +4581,7 @@ This option can be set to one of:\n\
           "Select single-precision MIPS floating-point coprocessor.",
           &mipsfpulist);
   add_cmd ("double", class_support, set_mipsfpu_double_command,
-          "Select double-precision MIPS floating-point coprocessor .",
+          "Select double-precision MIPS floating-point coprocessor.",
           &mipsfpulist);
   add_alias_cmd ("on", "double", class_support, 1, &mipsfpulist);
   add_alias_cmd ("yes", "double", class_support, 1, &mipsfpulist);
This page took 0.035254 seconds and 4 git commands to generate.