2004-06-07 Randolph Chung <tausq@debian.org>
[deliverable/binutils-gdb.git] / gdb / rs6000-tdep.c
index b6695b5ae4c60ee22d6d7a4de50befded4fe38cd..9cd744b88057e5b53c760c6c13b437fb75d2cd76 100644 (file)
@@ -36,6 +36,7 @@
 #include "value.h"
 #include "parser-defs.h"
 #include "osabi.h"
+#include "infcall.h"
 
 #include "libbfd.h"            /* for bfd_default_set_arch_mach */
 #include "coff/internal.h"     /* for libcoff.h */
@@ -141,6 +142,33 @@ altivec_register_p (int regno)
 }
 
 
+/* Return true if REGNO is an SPE register, false otherwise.  */
+int
+spe_register_p (int regno)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  
+  /* Is it a reference to EV0 -- EV31, and do we have those?  */
+  if (tdep->ppc_ev0_regnum >= 0
+      && tdep->ppc_ev31_regnum >= 0
+      && tdep->ppc_ev0_regnum <= regno && regno <= tdep->ppc_ev31_regnum)
+    return 1;
+
+  /* Is it a reference to the 64-bit accumulator, and do we have that?  */
+  if (tdep->ppc_acc_regnum >= 0
+      && tdep->ppc_acc_regnum == regno)
+    return 1;
+
+  /* Is it a reference to the SPE floating-point status and control register,
+     and do we have that?  */
+  if (tdep->ppc_spefscr_regnum >= 0
+      && tdep->ppc_spefscr_regnum == regno)
+    return 1;
+
+  return 0;
+}
+
+
 /* Return non-zero if the architecture described by GDBARCH has
    floating-point registers (f0 --- f31 and fpscr).  */
 int
@@ -1244,7 +1272,7 @@ rs6000_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
    starting from r4.  */
 
 static CORE_ADDR
-rs6000_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+rs6000_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                        struct regcache *regcache, CORE_ADDR bp_addr,
                        int nargs, struct value **args, CORE_ADDR sp,
                        int struct_return, CORE_ADDR struct_addr)
@@ -1257,6 +1285,7 @@ rs6000_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   char tmp_buffer[50];
   int f_argno = 0;             /* current floating point argno */
   int wordsize = gdbarch_tdep (current_gdbarch)->wordsize;
+  CORE_ADDR func_addr = find_function_addr (function, NULL);
 
   struct value *arg = 0;
   struct type *type;
@@ -1318,8 +1347,8 @@ rs6000_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
             there is no way we would run out of them.  */
 
          if (len > 8)
-           printf_unfiltered (
-                               "Fatal Error: a floating point parameter #%d with a size > 8 is found!\n", argno);
+           printf_unfiltered ("Fatal Error: a floating point parameter "
+                               "#%d with a size > 8 is found!\n", argno);
 
          memcpy (&deprecated_registers[DEPRECATED_REGISTER_BYTE
                                         (tdep->ppc_fp0_regnum + 1 + f_argno)],
@@ -1432,8 +1461,8 @@ ran_out_of_registers_for_arguments:
            {
 
              if (len > 8)
-               printf_unfiltered (
-                                   "Fatal Error: a floating point parameter #%d with a size > 8 is found!\n", argno);
+               printf_unfiltered ("Fatal Error: a floating point parameter"
+                                   " #%d with a size > 8 is found!\n", argno);
 
              memcpy (&(deprecated_registers
                         [DEPRECATED_REGISTER_BYTE
@@ -1443,7 +1472,9 @@ ran_out_of_registers_for_arguments:
              ++f_argno;
            }
 
-         write_memory (sp + 24 + (ii * 4), (char *) VALUE_CONTENTS (arg), len);
+         write_memory (sp + 24 + (ii * 4),
+                        (char *) VALUE_CONTENTS (arg),
+                        len);
          ii += ((len + 3) & -4) / 4;
        }
     }
@@ -1648,33 +1679,13 @@ rs6000_register_name (int n)
   return reg->name;
 }
 
-/* Index within `registers' of the first byte of the space for
-   register N.  */
-
-static int
-rs6000_register_byte (int n)
-{
-  return gdbarch_tdep (current_gdbarch)->regoff[n];
-}
-
-/* Return the number of bytes of storage in the actual machine representation
-   for register N if that register is available, else return 0.  */
-
-static int
-rs6000_register_raw_size (int n)
-{
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-  const struct reg *reg = tdep->regs + n;
-  return regsize (reg, tdep->wordsize);
-}
-
 /* Return the GDB type object for the "standard" data type
    of data in register N.  */
 
 static struct type *
-rs6000_register_virtual_type (int n)
+rs6000_register_type (struct gdbarch *gdbarch, int n)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   const struct reg *reg = tdep->regs + n;
 
   if (reg->fpr)
@@ -1704,49 +1715,49 @@ rs6000_register_virtual_type (int n)
     }
 }
 
-/* Return whether register N requires conversion when moving from raw format
-   to virtual format.
-
-   The register format for RS/6000 floating point registers is always
+/* The register format for RS/6000 floating point registers is always
    double, we need a conversion if the memory format is float.  */
 
 static int
-rs6000_register_convertible (int n)
+rs6000_convert_register_p (int regnum, struct type *type)
 {
-  const struct reg *reg = gdbarch_tdep (current_gdbarch)->regs + n;
-  return reg->fpr;
+  const struct reg *reg = gdbarch_tdep (current_gdbarch)->regs + regnum;
+  
+  return (reg->fpr
+          && TYPE_CODE (type) == TYPE_CODE_FLT
+          && TYPE_LENGTH (type) != TYPE_LENGTH (builtin_type_double));
 }
 
-/* Convert data from raw format for register N in buffer FROM
-   to virtual format with type TYPE in buffer TO.  */
-
 static void
-rs6000_register_convert_to_virtual (int n, struct type *type,
-                                   char *from, char *to)
+rs6000_register_to_value (struct frame_info *frame,
+                          int regnum,
+                          struct type *type,
+                          void *to)
 {
-  if (TYPE_LENGTH (type) != DEPRECATED_REGISTER_RAW_SIZE (n))
-    {
-      double val = deprecated_extract_floating (from, DEPRECATED_REGISTER_RAW_SIZE (n));
-      deprecated_store_floating (to, TYPE_LENGTH (type), val);
-    }
-  else
-    memcpy (to, from, DEPRECATED_REGISTER_RAW_SIZE (n));
-}
+  const struct reg *reg = gdbarch_tdep (current_gdbarch)->regs + regnum;
+  char from[MAX_REGISTER_SIZE];
+  
+  gdb_assert (reg->fpr);
+  gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
 
-/* Convert data from virtual format with type TYPE in buffer FROM
-   to raw format for register N in buffer TO.  */
+  get_frame_register (frame, regnum, from);
+  convert_typed_floating (from, builtin_type_double, to, type);
+}
 
 static void
-rs6000_register_convert_to_raw (struct type *type, int n,
-                               const char *from, char *to)
+rs6000_value_to_register (struct frame_info *frame,
+                          int regnum,
+                          struct type *type,
+                          const void *from)
 {
-  if (TYPE_LENGTH (type) != DEPRECATED_REGISTER_RAW_SIZE (n))
-    {
-      double val = deprecated_extract_floating (from, TYPE_LENGTH (type));
-      deprecated_store_floating (to, DEPRECATED_REGISTER_RAW_SIZE (n), val);
-    }
-  else
-    memcpy (to, from, DEPRECATED_REGISTER_RAW_SIZE (n));
+  const struct reg *reg = gdbarch_tdep (current_gdbarch)->regs + regnum;
+  char to[MAX_REGISTER_SIZE];
+
+  gdb_assert (reg->fpr);
+  gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
+
+  convert_typed_floating (from, type, to, builtin_type_double);
+  put_frame_register (frame, regnum, to);
 }
 
 static void
@@ -1800,10 +1811,9 @@ e500_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
     }
 }
 
-/* Convert a dbx stab or Dwarf 2 register number (from `r'
-   declaration) to a gdb REGNUM.  */
+/* Convert a DBX STABS register number to a GDB register number.  */
 static int
-rs6000_dwarf2_stab_reg_to_regnum (int num)
+rs6000_stab_reg_to_regnum (int num)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
 
@@ -1814,6 +1824,8 @@ rs6000_dwarf2_stab_reg_to_regnum (int num)
        specifies registers the architecture doesn't have?  Our
        callers don't check the value we return.  */
     return tdep->ppc_fp0_regnum + (num - 32);
+  else if (77 <= num && num <= 108)
+    return tdep->ppc_vr0_regnum + (num - 77);
   else if (1200 <= num && num < 1200 + 32)
     return tdep->ppc_ev0_regnum + (num - 1200);
   else
@@ -1829,56 +1841,109 @@ rs6000_dwarf2_stab_reg_to_regnum (int num)
         return tdep->ppc_xer_regnum;
       case 109:
         return tdep->ppc_vrsave_regnum;
+      case 110:
+        return tdep->ppc_vrsave_regnum - 1; /* vscr */
+      case 111:
+        return tdep->ppc_acc_regnum;
+      case 112:
+        return tdep->ppc_spefscr_regnum;
       default: 
         return num;
       }
+}
 
-  /* FIXME: jimb/2004-03-28: Doesn't something need to be done here
-     for the Altivec registers, too?
 
-     Looking at GCC, the headers in config/rs6000 never define a
-     DBX_REGISTER_NUMBER macro, so the debug info uses the same
-     numbers GCC does internally.  Then, looking at the REGISTER_NAMES
-     macro defined in config/rs6000/rs6000.h, it seems that GCC gives
-     v0 -- v31 the numbers 77 -- 108.  But we number them 119 -- 150.
+/* Convert a Dwarf 2 register number to a GDB register number.  */
+static int
+rs6000_dwarf2_reg_to_regnum (int num)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
 
-     I don't have a way to test this ready to hand, but I noticed it
-     and thought I should include a note.  */
+  if (0 <= num && num <= 31)
+    return tdep->ppc_gp0_regnum + num;
+  else if (32 <= num && num <= 63)
+    /* FIXME: jimb/2004-05-05: What should we do when the debug info
+       specifies registers the architecture doesn't have?  Our
+       callers don't check the value we return.  */
+    return tdep->ppc_fp0_regnum + (num - 32);
+  else if (1124 <= num && num < 1124 + 32)
+    return tdep->ppc_vr0_regnum + (num - 1124);
+  else if (1200 <= num && num < 1200 + 32)
+    return tdep->ppc_ev0_regnum + (num - 1200);
+  else
+    switch (num)
+      {
+      case 67:
+        return tdep->ppc_vrsave_regnum - 1; /* vscr */
+      case 99:
+        return tdep->ppc_acc_regnum;
+      case 100:
+        return tdep->ppc_mq_regnum;
+      case 101:
+        return tdep->ppc_xer_regnum;
+      case 108:
+        return tdep->ppc_lr_regnum;
+      case 109:
+        return tdep->ppc_ctr_regnum;
+      case 356:
+        return tdep->ppc_vrsave_regnum;
+      case 612:
+        return tdep->ppc_spefscr_regnum;
+      default:
+        return num;
+      }
 }
 
+
 static void
-rs6000_store_return_value (struct type *type, char *valbuf)
+rs6000_store_return_value (struct type *type,
+                           struct regcache *regcache,
+                           const void *valbuf)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int regnum = -1;
 
   /* The calling convention this function implements assumes the
      processor has floating-point registers.  We shouldn't be using it
      on PPC variants that lack them.  */
-  gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
+  gdb_assert (ppc_floating_point_unit_p (gdbarch));
 
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
-
     /* Floating point values are returned starting from FPR1 and up.
        Say a double_double_double type could be returned in
        FPR1/FPR2/FPR3 triple.  */
-
-    deprecated_write_register_bytes
-      (DEPRECATED_REGISTER_BYTE (tdep->ppc_fp0_regnum + 1),
-       valbuf,
-       TYPE_LENGTH (type));
+    regnum = tdep->ppc_fp0_regnum + 1;
   else if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
     {
       if (TYPE_LENGTH (type) == 16
           && TYPE_VECTOR (type))
-       deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (tdep->ppc_vr0_regnum + 2),
-                                        valbuf, TYPE_LENGTH (type));
+        regnum = tdep->ppc_vr0_regnum + 2;
+      else
+        gdb_assert (0);
     }
   else
     /* Everything else is returned in GPR3 and up.  */
-    deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (gdbarch_tdep (current_gdbarch)->ppc_gp0_regnum + 3),
-                                    valbuf, TYPE_LENGTH (type));
+    regnum = tdep->ppc_gp0_regnum + 3;
+
+  {
+    size_t bytes_written = 0;
+
+    while (bytes_written < TYPE_LENGTH (type))
+      {
+        /* How much of this value can we write to this register?  */
+        size_t bytes_to_write = min (TYPE_LENGTH (type) - bytes_written,
+                                     register_size (gdbarch, regnum));
+        regcache_cooked_write_part (regcache, regnum,
+                                    0, bytes_to_write,
+                                    (char *) valbuf + bytes_written);
+        regnum++;
+        bytes_written += bytes_to_write;
+      }
+  }
 }
 
+
 /* Extract from an array REGBUF containing the (raw) register state
    the address in which a function should return its structure value,
    as a CORE_ADDR (or an expression that can be used as one).  */
@@ -2825,6 +2890,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->ppc_vrsave_regnum = -1;
   tdep->ppc_ev0_regnum = -1;
   tdep->ppc_ev31_regnum = -1;
+  tdep->ppc_acc_regnum = -1;
+  tdep->ppc_spefscr_regnum = -1;
 
   set_gdbarch_pc_regnum (gdbarch, 64);
   set_gdbarch_sp_regnum (gdbarch, 1);
@@ -2836,7 +2903,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   else
     {
       set_gdbarch_deprecated_extract_return_value (gdbarch, rs6000_extract_return_value);
-      set_gdbarch_deprecated_store_return_value (gdbarch, rs6000_store_return_value);
+      set_gdbarch_store_return_value (gdbarch, rs6000_store_return_value);
     }
 
   /* Set lr_frame_offset.  */
@@ -2847,14 +2914,6 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   else
     tdep->lr_frame_offset = 8;
 
-  /* Calculate byte offsets in raw register array.  */
-  tdep->regoff = xmalloc (v->num_tot_regs * sizeof (int));
-  for (i = off = 0; i < v->num_tot_regs; i++)
-    {
-      tdep->regoff[i] = off;
-      off += regsize (v->regs + i, wordsize);
-    }
-
   if (v->arch == bfd_arch_powerpc)
     switch (v->mach)
       {
@@ -2878,6 +2937,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        tdep->ppc_ev31_regnum = 38;
         tdep->ppc_fp0_regnum = -1;
         tdep->ppc_fpscr_regnum = -1;
+        tdep->ppc_acc_regnum = 39;
+        tdep->ppc_spefscr_regnum = 40;
         set_gdbarch_pc_regnum (gdbarch, 0);
         set_gdbarch_sp_regnum (gdbarch, tdep->ppc_gp0_regnum + 1);
         set_gdbarch_deprecated_fp_regnum (gdbarch, tdep->ppc_gp0_regnum + 1);
@@ -2900,11 +2961,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_num_regs (gdbarch, v->nregs);
   set_gdbarch_num_pseudo_regs (gdbarch, v->npregs);
   set_gdbarch_register_name (gdbarch, rs6000_register_name);
-  set_gdbarch_deprecated_register_size (gdbarch, wordsize);
-  set_gdbarch_deprecated_register_bytes (gdbarch, off);
-  set_gdbarch_deprecated_register_byte (gdbarch, rs6000_register_byte);
-  set_gdbarch_deprecated_register_raw_size (gdbarch, rs6000_register_raw_size);
-  set_gdbarch_deprecated_register_virtual_type (gdbarch, rs6000_register_virtual_type);
+  set_gdbarch_register_type (gdbarch, rs6000_register_type);
 
   set_gdbarch_ptr_bit (gdbarch, wordsize * TARGET_CHAR_BIT);
   set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
@@ -2930,11 +2987,12 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        224.  */
     set_gdbarch_frame_red_zone_size (gdbarch, 224);
 
-  set_gdbarch_deprecated_register_convertible (gdbarch, rs6000_register_convertible);
-  set_gdbarch_deprecated_register_convert_to_virtual (gdbarch, rs6000_register_convert_to_virtual);
-  set_gdbarch_deprecated_register_convert_to_raw (gdbarch, rs6000_register_convert_to_raw);
-  set_gdbarch_stab_reg_to_regnum (gdbarch, rs6000_dwarf2_stab_reg_to_regnum);
-  set_gdbarch_dwarf2_reg_to_regnum (gdbarch, rs6000_dwarf2_stab_reg_to_regnum);
+  set_gdbarch_convert_register_p (gdbarch, rs6000_convert_register_p);
+  set_gdbarch_register_to_value (gdbarch, rs6000_register_to_value);
+  set_gdbarch_value_to_register (gdbarch, rs6000_value_to_register);
+
+  set_gdbarch_stab_reg_to_regnum (gdbarch, rs6000_stab_reg_to_regnum);
+  set_gdbarch_dwarf2_reg_to_regnum (gdbarch, rs6000_dwarf2_reg_to_regnum);
   /* Note: kevinb/2002-04-12: I'm not convinced that rs6000_push_arguments()
      is correct for the SysV ABI when the wordsize is 8, but I'm also
      fairly certain that ppc_sysv_abi_push_arguments() will give even
This page took 0.02825 seconds and 4 git commands to generate.