2000-12-04 Michael Snyder <msnyder@cleaver.cygnus.com>
[deliverable/binutils-gdb.git] / gdb / mips-tdep.c
index 1745e78191ed350c638bcccf99b2c1363ce11c37..61c9b95316d0097303ab97c9199f461f94dace1e 100644 (file)
@@ -224,6 +224,13 @@ mips_stack_argsize (void)
 #define GDB_TARGET_IS_MIPS64 (gdbarch_tdep (current_gdbarch)->gdb_target_is_mips64 + 0)
 #endif
 
+#if GDB_MULTI_ARCH
+#undef MIPS_DEFAULT_MASK_ADDRESS_P
+#define MIPS_DEFAULT_MASK_ADDRESS_P (gdbarch_tdep (current_gdbarch)->default_mask_address_p)
+#elif !defined (MIPS_DEFAULT_MASK_ADDRESS_P)
+#define MIPS_DEFAULT_MASK_ADDRESS_P (0)
+#endif
+
 #define VM_MIN_ADDRESS (CORE_ADDR)0x400000
 
 int gdb_print_insn_mips (bfd_vma, disassemble_info *);
@@ -268,8 +275,7 @@ char *mips_generic_reg_names[] = MIPS_REGISTER_NAMES;
 char **mips_processor_reg_names = mips_generic_reg_names;
 
 char *
-mips_register_name (i)
-     int i;
+mips_register_name (int i)
 {
   return mips_processor_reg_names[i];
 }
@@ -469,7 +475,7 @@ mips_mask_address_p (void)
       return 0;
       break;
     case CMD_AUTO_BOOLEAN_AUTO:
-      return gdbarch_tdep (current_gdbarch)->default_mask_address_p;
+      return MIPS_DEFAULT_MASK_ADDRESS_P;
     default:
       internal_error ("mips_mask_address_p: bad switch");
       return -1;
@@ -499,9 +505,7 @@ show_mask_address (char *cmd, int from_tty)
 
 /* Should call_function allocate stack space for a struct return?  */
 int
-mips_use_struct_convention (gcc_p, type)
-     int gcc_p;
-     struct type *type;
+mips_use_struct_convention (int gcc_p, struct type *type)
 {
   if (MIPS_EABI)
     return (TYPE_LENGTH (type) > 2 * MIPS_SAVED_REGSIZE);
@@ -822,7 +826,7 @@ mips32_next_pc (CORE_ADDR pc)
 }                              /* mips32_next_pc */
 
 /* Decoding the next place to set a breakpoint is irregular for the
-   mips 16 variant, but fortunatly, there fewer instructions. We have to cope
+   mips 16 variant, but fortunately, there fewer instructions. We have to cope
    ith extensions for 16 bit instructions and a pair of actual 32 bit instructions.
    We dont want to set a single step instruction on the extend instruction
    either.
@@ -857,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 */
@@ -902,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];
@@ -913,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:
@@ -950,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 */
@@ -965,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)
 {
@@ -1014,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).  */
@@ -1714,10 +1707,8 @@ mips16_heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
 }
 
 static void
-mips32_heuristic_proc_desc (start_pc, limit_pc, next_frame, sp)
-     CORE_ADDR start_pc, limit_pc;
-     struct frame_info *next_frame;
-     CORE_ADDR sp;
+mips32_heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
+                           struct frame_info *next_frame, CORE_ADDR sp)
 {
   CORE_ADDR cur_pc;
   CORE_ADDR frame_addr = 0;    /* Value of $r30. Used by gcc for frame-pointer */
@@ -3810,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)
@@ -3889,9 +3903,9 @@ mips_gdbarch_init (struct gdbarch_info info,
     {
       /* MIPS needs to be pedantic about which ABI the object is
          using. */
-      if (gdbarch_tdep (current_gdbarch)->elf_flags != elf_flags)
+      if (gdbarch_tdep (arches->gdbarch)->elf_flags != elf_flags)
        continue;
-      if (gdbarch_tdep (current_gdbarch)->mips_abi != mips_abi)
+      if (gdbarch_tdep (arches->gdbarch)->mips_abi != mips_abi)
        continue;
       return arches->gdbarch;
     }
@@ -4051,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);
 
@@ -4563,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.029575 seconds and 4 git commands to generate.