* solib-svr4.c (svr4_truncate_ptr): New function.
[deliverable/binutils-gdb.git] / gdb / mips-tdep.c
index f723e4603f9532f89004c9a15a57cf2298c04b0e..efcc0e71c83cffbe5b865f505103499ac94b64b3 100644 (file)
@@ -239,7 +239,7 @@ int gdb_print_insn_mips (bfd_vma, disassemble_info *);
 static void mips_print_register (int, int);
 
 static mips_extra_func_info_t
-heuristic_proc_desc (CORE_ADDR, CORE_ADDR, struct frame_info *);
+heuristic_proc_desc (CORE_ADDR, CORE_ADDR, struct frame_info *, int);
 
 static CORE_ADDR heuristic_proc_start (CORE_ADDR);
 
@@ -252,7 +252,7 @@ static void mips_show_processor_type_command (char *, int);
 static void reinit_frame_cache_sfunc (char *, int, struct cmd_list_element *);
 
 static mips_extra_func_info_t
-find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame);
+find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame, int cur_frame);
 
 static CORE_ADDR after_prologue (CORE_ADDR pc,
                                 mips_extra_func_info_t proc_desc);
@@ -410,8 +410,9 @@ mips_print_extra_frame_info (struct frame_info *fi)
                     paddr_d (fi->extra_info->proc_desc->pdr.frameoffset));
 }
 
-/* Convert between RAW and VIRTUAL registers.  The RAW register size
-   defines the remote-gdb packet. */
+/* Number of bytes of storage in the actual machine representation for
+   register N.  NOTE: This indirectly defines the register size
+   transfered by the GDB protocol. */
 
 static int mips64_transfers_32bit_regs_p = 0;
 
@@ -429,6 +430,9 @@ mips_register_raw_size (int reg_nr)
     return MIPS_REGSIZE;
 }
 
+/* Convert between RAW and VIRTUAL registers.  The RAW register size
+   defines the remote-gdb packet. */
+
 int
 mips_register_convertible (int reg_nr)
 {
@@ -442,7 +446,7 @@ void
 mips_register_convert_to_virtual (int n, struct type *virtual_type,
                                  char *raw_buf, char *virt_buf)
 {
-  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
     memcpy (virt_buf,
            raw_buf + (REGISTER_RAW_SIZE (n) - TYPE_LENGTH (virtual_type)),
            TYPE_LENGTH (virtual_type));
@@ -457,7 +461,7 @@ mips_register_convert_to_raw (struct type *virtual_type, int n,
                              char *virt_buf, char *raw_buf)
 {
   memset (raw_buf, 0, REGISTER_RAW_SIZE (n));
-  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
     memcpy (raw_buf + (REGISTER_RAW_SIZE (n) - TYPE_LENGTH (virtual_type)),
            virt_buf,
            TYPE_LENGTH (virtual_type));
@@ -561,8 +565,13 @@ after_prologue (CORE_ADDR pc,
   struct symtab_and_line sal;
   CORE_ADDR func_addr, func_end;
 
+  /* Pass cur_frame == 0 to find_proc_desc.  We should not attempt
+     to read the stack pointer from the current machine state, because
+     the current machine state has nothing to do with the information
+     we need from the proc_desc; and the process may or may not exist
+     right now.  */
   if (!proc_desc)
-    proc_desc = find_proc_desc (pc, NULL);
+    proc_desc = find_proc_desc (pc, NULL, 0);
 
   if (proc_desc)
     {
@@ -1858,9 +1867,14 @@ restart:
 
 static mips_extra_func_info_t
 heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
-                    struct frame_info *next_frame)
+                    struct frame_info *next_frame, int cur_frame)
 {
-  CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
+  CORE_ADDR sp;
+
+  if (cur_frame)
+    sp = read_next_frame_reg (next_frame, SP_REGNUM);
+  else
+    sp = 0;
 
   if (start_pc == 0)
     return NULL;
@@ -1919,7 +1933,7 @@ non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr)
 
 
 static mips_extra_func_info_t
-find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame)
+find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame, int cur_frame)
 {
   mips_extra_func_info_t proc_desc;
   CORE_ADDR startaddr;
@@ -1951,7 +1965,7 @@ find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame)
            {
              mips_extra_func_info_t found_heuristic =
              heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
-                                  pc, next_frame);
+                                  pc, next_frame, cur_frame);
              if (found_heuristic)
                proc_desc = found_heuristic;
            }
@@ -1975,7 +1989,7 @@ find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame)
        startaddr = heuristic_proc_start (pc);
 
       proc_desc =
-       heuristic_proc_desc (startaddr, pc, next_frame);
+       heuristic_proc_desc (startaddr, pc, next_frame, cur_frame);
     }
   return proc_desc;
 }
@@ -2007,7 +2021,7 @@ mips_frame_chain (struct frame_info *frame)
     saved_pc = tmp;
 
   /* Look up the procedure descriptor for this PC.  */
-  proc_desc = find_proc_desc (saved_pc, frame);
+  proc_desc = find_proc_desc (saved_pc, frame, 1);
   if (!proc_desc)
     return 0;
 
@@ -2033,7 +2047,7 @@ mips_init_extra_frame_info (int fromleaf, struct frame_info *fci)
 
   /* Use proc_desc calculated in frame_chain */
   mips_extra_func_info_t proc_desc =
-  fci->next ? cached_proc_desc : find_proc_desc (fci->pc, fci->next);
+  fci->next ? cached_proc_desc : find_proc_desc (fci->pc, fci->next, 1);
 
   fci->extra_info = (struct frame_extra_info *)
     frame_obstack_alloc (sizeof (struct frame_extra_info));
@@ -2126,9 +2140,38 @@ fp_register_arg_p (enum type_code typecode, struct type *arg_type)
           && MIPS_FPU_TYPE != MIPS_FPU_NONE);
 }
 
+/* On o32, argument passing in GPRs depends on the alignment of the type being
+   passed.  Return 1 if this type must be aligned to a doubleword boundary. */
+
+static int
+mips_type_needs_double_align (struct type *type)
+{
+  enum type_code typecode = TYPE_CODE (type);
+  
+  if (typecode == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8)
+    return 1;
+  else if (typecode == TYPE_CODE_STRUCT)
+    {
+      if (TYPE_NFIELDS (type) < 1)
+       return 0;
+      return mips_type_needs_double_align (TYPE_FIELD_TYPE (type, 0));
+    }
+  else if (typecode == TYPE_CODE_UNION)
+    {
+      int i, n;    
+
+      n = TYPE_NFIELDS (type);
+      for (i = 0; i < n; i++)
+       if (mips_type_needs_double_align (TYPE_FIELD_TYPE (type, i)))
+         return 1;
+      return 0;
+    }
+  return 0;
+}
+
 CORE_ADDR
 mips_push_arguments (int nargs,
-                    value_ptr *args,
+                    struct value **args,
                     CORE_ADDR sp,
                     int struct_return,
                     CORE_ADDR struct_addr)
@@ -2186,7 +2229,7 @@ mips_push_arguments (int nargs,
     {
       char *val;
       char valbuf[MAX_REGISTER_RAW_SIZE];
-      value_ptr arg = args[argnum];
+      struct value *arg = args[argnum];
       struct type *arg_type = check_typedef (VALUE_TYPE (arg));
       int len = TYPE_LENGTH (arg_type);
       enum type_code typecode = TYPE_CODE (arg_type);
@@ -2241,7 +2284,7 @@ mips_push_arguments (int nargs,
        {
          if (!FP_REGISTER_DOUBLE && len == 8)
            {
-             int low_offset = TARGET_BYTE_ORDER == BIG_ENDIAN ? 4 : 0;
+             int low_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
              unsigned long regval;
 
              /* Write the low word of the double to the even register(s).  */
@@ -2312,6 +2355,14 @@ mips_push_arguments (int nargs,
             compatibility, we will put them in both places.  */
          int odd_sized_struct = ((len > MIPS_SAVED_REGSIZE) &&
                                  (len % MIPS_SAVED_REGSIZE != 0));
+         /* Structures should be aligned to eight bytes (even arg registers)
+            on MIPS_ABI_O32 if their first member has double precision. */
+         if (gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_O32
+             && mips_type_needs_double_align (arg_type))
+           {
+             if ((argreg & 1))
+               argreg++;
+           }
          /* Note: Floating-point values that didn't fit into an FP
              register are only written to memory. */
          while (len > 0)
@@ -2334,7 +2385,7 @@ mips_push_arguments (int nargs,
                  int longword_offset = 0;
                  CORE_ADDR addr;
                  stack_used_p = 1;
-                 if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+                 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
                    {
                      if (MIPS_STACK_ARGSIZE == 8 &&
                          (typecode == TYPE_CODE_INT ||
@@ -2389,11 +2440,24 @@ mips_push_arguments (int nargs,
                     same for integral types.
 
                     Also don't do this adjustment on EABI and O64
-                    binaries. */
+                    binaries.
+
+                    cagney/2001-07-23: gdb/179: Also, GCC, when
+                    outputting LE O32 with sizeof (struct) <
+                    MIPS_SAVED_REGSIZE, generates a left shift as
+                    part of storing the argument in a register a
+                    register (the left shift isn't generated when
+                    sizeof (struct) >= MIPS_SAVED_REGSIZE).  Since it
+                    is quite possible that this is GCC contradicting
+                    the LE/O32 ABI, GDB has not been adjusted to
+                    accommodate this.  Either someone needs to
+                    demonstrate that the LE/O32 ABI specifies such a
+                    left shift OR this new ABI gets identified as
+                    such and GDB gets tweaked accordingly.  */
 
                  if (!MIPS_EABI
                      && MIPS_SAVED_REGSIZE < 8
-                     && TARGET_BYTE_ORDER == BIG_ENDIAN
+                     && TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
                      && partial_len < MIPS_SAVED_REGSIZE
                      && (typecode == TYPE_CODE_STRUCT ||
                          typecode == TYPE_CODE_UNION))
@@ -2458,7 +2522,7 @@ mips_push_register (CORE_ADDR * sp, int regno)
   if (MIPS_SAVED_REGSIZE < REGISTER_RAW_SIZE (regno))
     {
       regsize = MIPS_SAVED_REGSIZE;
-      offset = (TARGET_BYTE_ORDER == BIG_ENDIAN
+      offset = (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
                ? REGISTER_RAW_SIZE (regno) - MIPS_SAVED_REGSIZE
                : 0);
     }
@@ -2655,7 +2719,7 @@ mips_print_register (int regnum, int all)
   if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
     if (FP_REGISTER_DOUBLE)
       {                                /* show 8-byte floats as float AND double: */
-       int offset = 4 * (TARGET_BYTE_ORDER == BIG_ENDIAN);
+       int offset = 4 * (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG);
 
        printf_filtered (" (float) ");
        val_print (builtin_type_float, raw_buffer + offset, 0, 0,
@@ -2672,7 +2736,7 @@ mips_print_register (int regnum, int all)
     {
       int offset;
 
-      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
         offset = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
       else
        offset = 0;
@@ -2692,8 +2756,8 @@ do_fp_register_row (int regnum)
   char *raw_buffer[2];
   char *dbl_buffer;
   /* use HI and LO to control the order of combining two flt regs */
-  int HI = (TARGET_BYTE_ORDER == BIG_ENDIAN);
-  int LO = (TARGET_BYTE_ORDER != BIG_ENDIAN);
+  int HI = (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG);
+  int LO = (TARGET_BYTE_ORDER != BFD_ENDIAN_BIG);
   double doub, flt1, flt2;     /* doubles extracted from raw hex data */
   int inv1, inv2, inv3;
 
@@ -2742,7 +2806,7 @@ do_fp_register_row (int regnum)
     }
   else
     {                          /* eight byte registers: print each one as float AND as double. */
-      int offset = 4 * (TARGET_BYTE_ORDER == BIG_ENDIAN);
+      int offset = 4 * (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG);
 
       memcpy (dbl_buffer, raw_buffer[HI], 2 * REGISTER_RAW_SIZE (FP0_REGNUM));
       flt1 = unpack_double (builtin_type_float,
@@ -2811,7 +2875,7 @@ do_gp_register_row (int regnum)
       for (byte = 0; byte < (MIPS_REGSIZE - REGISTER_VIRTUAL_SIZE (regnum)); byte++)
        printf_filtered ("  ");
       /* Now print the register value in hex, endian order. */
-      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
        for (byte = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
             byte < REGISTER_RAW_SIZE (regnum);
             byte++)
@@ -3154,9 +3218,9 @@ return_value_location (struct type *valtype,
        {
          /* We need to break a 64bit float in two 32 bit halves and
             spread them across a floating-point register pair. */
-         lo->buf_offset = TARGET_BYTE_ORDER == BIG_ENDIAN ? 4 : 0;
-         hi->buf_offset = TARGET_BYTE_ORDER == BIG_ENDIAN ? 0 : 4;
-         lo->reg_offset = ((TARGET_BYTE_ORDER == BIG_ENDIAN
+         lo->buf_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
+         hi->buf_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 0 : 4;
+         lo->reg_offset = ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
                             && REGISTER_RAW_SIZE (FP0_REGNUM) == 8)
                            ? 4 : 0);
          hi->reg_offset = lo->reg_offset;
@@ -3169,7 +3233,7 @@ return_value_location (struct type *valtype,
        {
          /* The floating point value fits in a single floating-point
             register. */
-         lo->reg_offset = ((TARGET_BYTE_ORDER == BIG_ENDIAN
+         lo->reg_offset = ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
                             && REGISTER_RAW_SIZE (FP0_REGNUM) == 8
                             && len == 4)
                            ? 4 : 0);
@@ -3188,7 +3252,7 @@ return_value_location (struct type *valtype,
       int regnum = 2;
       lo->reg = regnum + 0;
       hi->reg = regnum + 1;
-      if (TARGET_BYTE_ORDER == BIG_ENDIAN
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
          && len < MIPS_SAVED_REGSIZE)
        {
          /* "un-left-justify" the value in the low register */
@@ -3197,7 +3261,7 @@ return_value_location (struct type *valtype,
          hi->reg_offset = 0;
          hi->len = 0;
        }
-      else if (TARGET_BYTE_ORDER == BIG_ENDIAN
+      else if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
               && len > MIPS_SAVED_REGSIZE      /* odd-size structs */
               && len < MIPS_SAVED_REGSIZE * 2
               && (TYPE_CODE (valtype) == TYPE_CODE_STRUCT ||
@@ -3225,7 +3289,7 @@ return_value_location (struct type *valtype,
              hi->len = 0;
            }
        }
-      if (TARGET_BYTE_ORDER == BIG_ENDIAN
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
          && REGISTER_RAW_SIZE (regnum) == 8
          && MIPS_SAVED_REGSIZE == 4)
        {
@@ -3499,7 +3563,7 @@ gdb_print_insn_mips (bfd_vma memaddr, disassemble_info *info)
   memaddr &= (info->mach == bfd_mach_mips16 ? ~1 : ~3);
 
   /* Call the appropriate disassembler based on the target endian-ness.  */
-  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
     return print_insn_big_mips (memaddr, info);
   else
     return print_insn_little_mips (memaddr, info);
@@ -3528,7 +3592,7 @@ gdb_print_insn_mips (bfd_vma memaddr, disassemble_info *info)
 unsigned char *
 mips_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
 {
-  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
     {
       if (pc_is_mips16 (*pcptr))
        {
@@ -3900,6 +3964,20 @@ mips_ecoff_reg_to_regnum (int num)
     return num + FP0_REGNUM - 32;
 }
 
+/* Convert an integer into an address.  By first converting the value
+   into a pointer and then extracting it signed, the address is
+   guarenteed to be correctly sign extended.  */
+
+static CORE_ADDR
+mips_integer_to_address (struct type *type, void *buf)
+{
+  char *tmp = alloca (TYPE_LENGTH (builtin_type_void_data_ptr));
+  LONGEST val = unpack_long (type, buf);
+  store_signed_integer (tmp, TYPE_LENGTH (builtin_type_void_data_ptr), val);
+  return extract_signed_integer (tmp,
+                                TYPE_LENGTH (builtin_type_void_data_ptr));
+}
+
 static struct gdbarch *
 mips_gdbarch_init (struct gdbarch_info info,
                   struct gdbarch_list *arches)
@@ -4001,12 +4079,13 @@ mips_gdbarch_init (struct gdbarch_info info,
   gdbarch = gdbarch_alloc (&info, tdep);
   tdep->elf_flags = elf_flags;
 
-  /* Initially set everything according to the ABI. */
+  /* Initially set everything according to the default ABI/ISA. */
   set_gdbarch_short_bit (gdbarch, 16);
   set_gdbarch_int_bit (gdbarch, 32);
   set_gdbarch_float_bit (gdbarch, 32);
   set_gdbarch_double_bit (gdbarch, 64);
   set_gdbarch_long_double_bit (gdbarch, 64);
+  set_gdbarch_register_raw_size (gdbarch, mips_register_raw_size);
   tdep->mips_abi = mips_abi;
 
   switch (mips_abi)
@@ -4204,11 +4283,13 @@ mips_gdbarch_init (struct gdbarch_info info,
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   set_gdbarch_breakpoint_from_pc (gdbarch, mips_breakpoint_from_pc);
   set_gdbarch_decr_pc_after_break (gdbarch, 0);
-  set_gdbarch_ieee_float (gdbarch, 1);
 
   set_gdbarch_skip_prologue (gdbarch, mips_skip_prologue);
   set_gdbarch_saved_pc_after_call (gdbarch, mips_saved_pc_after_call);
 
+  set_gdbarch_pointer_to_address (gdbarch, signed_pointer_to_address);
+  set_gdbarch_address_to_pointer (gdbarch, address_to_signed_pointer);
+  set_gdbarch_integer_to_address (gdbarch, mips_integer_to_address);
   return gdbarch;
 }
 
@@ -4705,9 +4786,9 @@ This option can be set to one of:\n\
 Set this to be able to access processor-type-specific registers.\n\
 ",
                   &setlist);
-  c->function.cfunc = mips_set_processor_type_command;
+  set_cmd_cfunc (c, mips_set_processor_type_command);
   c = add_show_from_set (c, &showlist);
-  c->function.cfunc = mips_show_processor_type_command;
+  set_cmd_cfunc (c, mips_show_processor_type_command);
 
   tmp_mips_processor_type = xstrdup (DEFAULT_MIPS_TYPE);
   mips_set_processor_type_command (xstrdup (DEFAULT_MIPS_TYPE), 0);
@@ -4726,7 +4807,7 @@ search.  The only need to set it is when debugging a stripped executable.",
                   &setlist);
   /* We need to throw away the frame cache when we set this, since it
      might change our ability to get backtraces.  */
-  c->function.sfunc = reinit_frame_cache_sfunc;
+  set_cmd_sfunc (c, reinit_frame_cache_sfunc);
   add_show_from_set (c, &showlist);
 
   /* Allow the user to control whether the upper bits of 64-bit
This page took 0.029432 seconds and 4 git commands to generate.