* gdbarch.sh (function_list): Add FETCH_POINTER_ARGUMENT.
[deliverable/binutils-gdb.git] / gdb / rs6000-tdep.c
index 7a692e7b28572f9392460a11957c5a15392a099b..98e1a0ca088ee69f5975627d5dbb4ebe0dfd9f2c 100644 (file)
@@ -230,6 +230,16 @@ rs6000_saved_pc_after_call (struct frame_info *fi)
   return read_register (gdbarch_tdep (current_gdbarch)->ppc_lr_regnum);
 }
 
+/* Get the ith function argument for the current function.  */
+CORE_ADDR
+rs6000_fetch_pointer_argument (struct frame_info *frame, int argi, 
+                              struct type *type)
+{
+  CORE_ADDR addr;
+  frame_read_register (frame, 3 + argi, &addr);
+  return addr;
+}
+
 /* Calculate the destination of a branch/jump.  Return -1 if not a branch.  */
 
 static CORE_ADDR
@@ -305,14 +315,11 @@ branch_dest (int opcode, int instr, CORE_ADDR pc, CORE_ADDR safety)
 
 /* Sequence of bytes for breakpoint instruction.  */
 
-#define BIG_BREAKPOINT { 0x7d, 0x82, 0x10, 0x08 }
-#define LITTLE_BREAKPOINT { 0x08, 0x10, 0x82, 0x7d }
-
 const static unsigned char *
 rs6000_breakpoint_from_pc (CORE_ADDR *bp_addr, int *bp_size)
 {
-  static unsigned char big_breakpoint[] = BIG_BREAKPOINT;
-  static unsigned char little_breakpoint[] = LITTLE_BREAKPOINT;
+  static unsigned char big_breakpoint[] = { 0x7d, 0x82, 0x10, 0x08 };
+  static unsigned char little_breakpoint[] = { 0x08, 0x10, 0x82, 0x7d };
   *bp_size = 4;
   if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
     return big_breakpoint;
@@ -529,13 +536,13 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
 
       if ((op & 0xfc1fffff) == 0x7c0802a6)
        {                       /* mflr Rx */
-         lr_reg = (op & 0x03e00000) | 0x90010000;
+         lr_reg = (op & 0x03e00000);
          continue;
 
        }
       else if ((op & 0xfc1fffff) == 0x7c000026)
        {                       /* mfcr Rx */
-         cr_reg = (op & 0x03e00000) | 0x90010000;
+         cr_reg = (op & 0x03e00000);
          continue;
 
        }
@@ -561,7 +568,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
            {
              fdata->saved_gpr = reg;
              if ((op & 0xfc1f0003) == 0xf8010000)
-               op = (op >> 1) << 1;
+               op &= ~3UL;
              fdata->gpr_offset = SIGNED_SHORT (op) + offset;
            }
          continue;
@@ -593,20 +600,42 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
          continue;
 
        }
-      else if (lr_reg != -1 && (op & 0xffff0000) == lr_reg)
-       {                       /* st Rx,NUM(r1) 
-                                  where Rx == lr */
-         fdata->lr_offset = SIGNED_SHORT (op) + offset;
+      else if (lr_reg != -1 &&
+              /* std Rx, NUM(r1) || stdu Rx, NUM(r1) */
+              (((op & 0xffff0000) == (lr_reg | 0xf8010000)) ||
+               /* stw Rx, NUM(r1) */
+               ((op & 0xffff0000) == (lr_reg | 0x90010000)) ||
+               /* stwu Rx, NUM(r1) */
+               ((op & 0xffff0000) == (lr_reg | 0x94010000))))
+       {       /* where Rx == lr */
+         fdata->lr_offset = offset;
          fdata->nosavedpc = 0;
          lr_reg = 0;
+         if ((op & 0xfc000003) == 0xf8000000 ||        /* std */
+             (op & 0xfc000000) == 0x90000000)          /* stw */
+           {
+             /* Does not update r1, so add displacement to lr_offset.  */
+             fdata->lr_offset += SIGNED_SHORT (op);
+           }
          continue;
 
        }
-      else if (cr_reg != -1 && (op & 0xffff0000) == cr_reg)
-       {                       /* st Rx,NUM(r1) 
-                                  where Rx == cr */
-         fdata->cr_offset = SIGNED_SHORT (op) + offset;
+      else if (cr_reg != -1 &&
+              /* std Rx, NUM(r1) || stdu Rx, NUM(r1) */
+              (((op & 0xffff0000) == (cr_reg | 0xf8010000)) ||
+               /* stw Rx, NUM(r1) */
+               ((op & 0xffff0000) == (cr_reg | 0x90010000)) ||
+               /* stwu Rx, NUM(r1) */
+               ((op & 0xffff0000) == (cr_reg | 0x94010000))))
+       {       /* where Rx == cr */
+         fdata->cr_offset = offset;
          cr_reg = 0;
+         if ((op & 0xfc000003) == 0xf8000000 ||
+             (op & 0xfc000000) == 0x90000000)
+           {
+             /* Does not update r1, so add displacement to cr_offset.  */
+             fdata->cr_offset += SIGNED_SHORT (op);
+           }
          continue;
 
        }
@@ -650,30 +679,41 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
                                   this branch */
          continue;
 
-         /* update stack pointer */
        }
-      else if ((op & 0xffff0000) == 0x94210000 ||      /* stu r1,NUM(r1) */
-              (op & 0xffff0003) == 0xf8210001)         /* stdu r1,NUM(r1) */
-       {
+      /* update stack pointer */
+      else if ((op & 0xfc1f0000) == 0x94010000)
+       {               /* stu rX,NUM(r1) ||  stwu rX,NUM(r1) */
          fdata->frameless = 0;
-         if ((op & 0xffff0003) == 0xf8210001)
-           op = (op >> 1) << 1;
          fdata->offset = SIGNED_SHORT (op);
          offset = fdata->offset;
          continue;
-
        }
-      else if (op == 0x7c21016e)
-       {                       /* stwux 1,1,0 */
+      else if ((op & 0xfc1f016a) == 0x7c01016e)
+       {                       /* stwux rX,r1,rY */
+         /* no way to figure out what r1 is going to be */
          fdata->frameless = 0;
          offset = fdata->offset;
          continue;
-
-         /* Load up minimal toc pointer */
        }
-      else if ((op >> 22) == 0x20f
+      else if ((op & 0xfc1f0003) == 0xf8010001)
+       {                       /* stdu rX,NUM(r1) */
+         fdata->frameless = 0;
+         fdata->offset = SIGNED_SHORT (op & ~3UL);
+         offset = fdata->offset;
+         continue;
+       }
+      else if ((op & 0xfc1f016a) == 0x7c01016a)
+       {                       /* stdux rX,r1,rY */
+         /* no way to figure out what r1 is going to be */
+         fdata->frameless = 0;
+         offset = fdata->offset;
+         continue;
+       }
+      /* Load up minimal toc pointer */
+      else if (((op >> 22) == 0x20f    ||      /* l r31,... or l r30,... */
+              (op >> 22) == 0x3af)             /* ld r31,... or ld r30,... */
               && !minimal_toc_loaded)
-       {                       /* l r31,... or l r30,... */
+       {
          minimal_toc_loaded = 1;
          continue;
 
@@ -984,7 +1024,7 @@ rs6000_pop_frame (void)
     }
 
   /* Make sure that all registers are valid.  */
-  deprecated_read_register_bytes (0, NULL, REGISTER_BYTES);
+  deprecated_read_register_bytes (0, NULL, DEPRECATED_REGISTER_BYTES);
 
   /* Figure out previous %pc value.  If the function is frameless, it is 
      still in the link register, otherwise walk the frames and retrieve the
@@ -1269,7 +1309,7 @@ ran_out_of_registers_for_arguments:
     write_register (SP_REGNUM, sp);
 
   /* set back chain properly */
-  store_address (tmp_buffer, 4, saved_sp);
+  store_unsigned_integer (tmp_buffer, 4, saved_sp);
   write_memory (sp, tmp_buffer, 4);
 
   target_store_registers (-1);
@@ -1739,7 +1779,7 @@ frame_initial_stack_address (struct frame_info *fi)
   /* There is an alloca register, use its value, in the current frame,
      as the initial stack pointer.  */
   {
-    char *tmpbuf = alloca (MAX_REGISTER_RAW_SIZE);
+    char tmpbuf[MAX_REGISTER_SIZE];
     if (frame_register_read (fi, fdata.alloca_reg, tmpbuf))
       {
        get_frame_extra_info (fi)->initial_sp
@@ -1921,7 +1961,7 @@ e500_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 {
   int base_regnum;
   int offset = 0;
-  char *temp_buffer = (char*) alloca (MAX_REGISTER_RAW_SIZE);
+  char temp_buffer[MAX_REGISTER_SIZE];
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 
 
   if (reg_nr >= tdep->ppc_gp0_regnum 
@@ -1944,7 +1984,7 @@ e500_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
 {
   int base_regnum;
   int offset = 0;
-  char *temp_buffer = (char*) alloca (MAX_REGISTER_RAW_SIZE);
+  char temp_buffer[MAX_REGISTER_SIZE];
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 
 
   if (reg_nr >= tdep->ppc_gp0_regnum 
@@ -2879,7 +2919,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   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_register_bytes (gdbarch, off);
+  set_gdbarch_deprecated_register_bytes (gdbarch, off);
   set_gdbarch_register_byte (gdbarch, rs6000_register_byte);
   set_gdbarch_register_raw_size (gdbarch, rs6000_register_raw_size);
   set_gdbarch_deprecated_max_register_raw_size (gdbarch, 16);
@@ -2961,6 +3001,9 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_frame_locals_address (gdbarch, rs6000_frame_args_address);
   set_gdbarch_deprecated_saved_pc_after_call (gdbarch, rs6000_saved_pc_after_call);
 
+  /* Helpers for function argument information.  */
+  set_gdbarch_fetch_pointer_argument (gdbarch, rs6000_fetch_pointer_argument);
+
   /* We can't tell how many args there are
      now that the C compiler delays popping them.  */
   set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
This page took 0.027597 seconds and 4 git commands to generate.