2002-11-18 Andrew Cagney <ac131313@redhat.com>
[deliverable/binutils-gdb.git] / gdb / rs6000-tdep.c
index ca094c74cf322af46537ad07a065a8d0afb66cb6..57de0832e03d06cacc81c7690795fe1134c7b208 100644 (file)
@@ -1,5 +1,6 @@
 /* Target-dependent code for GDB, the GNU debugger.
-   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+   1998, 1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
 
    This file is part of GDB.
 #include "gdbcmd.h"
 #include "symfile.h"
 #include "objfiles.h"
-#include "xcoffsolib.h"
+#include "arch-utils.h"
+#include "regcache.h"
+#include "doublest.h"
+#include "value.h"
+#include "parser-defs.h"
+
+#include "libbfd.h"            /* for bfd_default_set_arch_mach */
+#include "coff/internal.h"     /* for libcoff.h */
+#include "libcoff.h"           /* for xcoff_data */
+#include "coff/xcoff.h"
+#include "libxcoff.h"
+
+#include "elf-bfd.h"
+
+#include "solib-svr4.h"
+#include "ppc-tdep.h"
+
+/* If the kernel has to deliver a signal, it pushes a sigcontext
+   structure on the stack and then calls the signal handler, passing
+   the address of the sigcontext in an argument register. Usually
+   the signal handler doesn't save this register, so we have to
+   access the sigcontext structure via an offset from the signal handler
+   frame.
+   The following constants were determined by experimentation on AIX 3.2.  */
+#define SIG_FRAME_PC_OFFSET 96
+#define SIG_FRAME_LR_OFFSET 108
+#define SIG_FRAME_FP_OFFSET 284
+
+/* To be used by skip_prologue. */
+
+struct rs6000_framedata
+  {
+    int offset;                        /* total size of frame --- the distance
+                                  by which we decrement sp to allocate
+                                  the frame */
+    int saved_gpr;             /* smallest # of saved gpr */
+    int saved_fpr;             /* smallest # of saved fpr */
+    int saved_vr;               /* smallest # of saved vr */
+    int saved_ev;               /* smallest # of saved ev */
+    int alloca_reg;            /* alloca register number (frame ptr) */
+    char frameless;            /* true if frameless functions. */
+    char nosavedpc;            /* true if pc not saved. */
+    int gpr_offset;            /* offset of saved gprs from prev sp */
+    int fpr_offset;            /* offset of saved fprs from prev sp */
+    int vr_offset;              /* offset of saved vrs from prev sp */
+    int ev_offset;              /* offset of saved evs from prev sp */
+    int lr_offset;             /* offset of saved lr */
+    int cr_offset;             /* offset of saved cr */
+    int vrsave_offset;          /* offset of saved vrsave register */
+  };
 
-extern int errno;
+/* Description of a single register. */
+
+struct reg
+  {
+    char *name;                        /* name of register */
+    unsigned char sz32;                /* size on 32-bit arch, 0 if nonextant */
+    unsigned char sz64;                /* size on 64-bit arch, 0 if nonextant */
+    unsigned char fpr;         /* whether register is floating-point */
+    unsigned char pseudo;       /* whether register is pseudo */
+  };
 
 /* Breakpoint shadows for the single step instructions will be kept here. */
 
@@ -47,26 +106,47 @@ stepBreaks[2];
    inferior under AIX. The initialization code in rs6000-nat.c sets
    this hook to point to find_toc_address.  */
 
-CORE_ADDR (*find_toc_address_hook) PARAMS ((CORE_ADDR)) = NULL;
+CORE_ADDR (*rs6000_find_toc_address_hook) (CORE_ADDR) = NULL;
+
+/* Hook to set the current architecture when starting a child process. 
+   rs6000-nat.c sets this. */
+
+void (*rs6000_set_host_arch_hook) (int) = NULL;
 
 /* Static function prototypes */
 
-     static CORE_ADDR branch_dest PARAMS ((int opcode, int instr, CORE_ADDR pc,
-                                          CORE_ADDR safety));
+static CORE_ADDR branch_dest (int opcode, int instr, CORE_ADDR pc,
+                             CORE_ADDR safety);
+static CORE_ADDR skip_prologue (CORE_ADDR, CORE_ADDR,
+                                struct rs6000_framedata *);
+static void frame_get_saved_regs (struct frame_info * fi,
+                                 struct rs6000_framedata * fdatap);
+static CORE_ADDR frame_initial_stack_address (struct frame_info *);
 
-     static void frame_get_saved_regs PARAMS ((struct frame_info * fi,
-                                        struct rs6000_framedata * fdatap));
+/* Is REGNO an AltiVec register?  Return 1 if so, 0 otherwise.  */
+int
+altivec_register_p (int regno)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  if (tdep->ppc_vr0_regnum < 0 || tdep->ppc_vrsave_regnum < 0)
+    return 0;
+  else
+    return (regno >= tdep->ppc_vr0_regnum && regno <= tdep->ppc_vrsave_regnum);
+}
 
-     static void pop_dummy_frame PARAMS ((void));
+/* Read a LEN-byte address from debugged memory address MEMADDR. */
 
-     static CORE_ADDR frame_initial_stack_address PARAMS ((struct frame_info *));
+static CORE_ADDR
+read_memory_addr (CORE_ADDR memaddr, int len)
+{
+  return read_memory_unsigned_integer (memaddr, len);
+}
 
-CORE_ADDR
-rs6000_skip_prologue (pc)
-     CORE_ADDR pc;
+static CORE_ADDR
+rs6000_skip_prologue (CORE_ADDR pc)
 {
   struct rs6000_framedata frame;
-  pc = skip_prologue (pc, &frame);
+  pc = skip_prologue (pc, 0, &frame);
   return pc;
 }
 
@@ -84,9 +164,7 @@ struct frame_extra_info
 };
 
 void
-rs6000_init_extra_frame_info (fromleaf, fi)
-     int fromleaf;
-     struct frame_info *fi;
+rs6000_init_extra_frame_info (int fromleaf, struct frame_info *fi)
 {
   fi->extra_info = (struct frame_extra_info *)
     frame_obstack_alloc (sizeof (struct frame_extra_info));
@@ -97,20 +175,27 @@ rs6000_init_extra_frame_info (fromleaf, fi)
     /* and this is a special signal frame.  */
     /* (fi->pc will be some low address in the kernel, */
     /*  to which the signal handler returns).  */
-    fi->signal_handler_caller = 1;
+    deprecated_set_frame_type (fi, SIGTRAMP_FRAME);
 }
 
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
+/* In this implementation for RS/6000, we do *not* save sp. I am
+   not sure if it will be needed. The following function takes care of gpr's
+   and fpr's only. */
 
 void
-rs6000_frame_init_saved_regs (fi)
-     struct frame_info *fi;
+rs6000_frame_init_saved_regs (struct frame_info *fi)
 {
   frame_get_saved_regs (fi, NULL);
 }
 
-CORE_ADDR
-rs6000_frame_args_address (fi)
-     struct frame_info *fi;
+static CORE_ADDR
+rs6000_frame_args_address (struct frame_info *fi)
 {
   if (fi->extra_info->initial_sp != 0)
     return fi->extra_info->initial_sp;
@@ -118,15 +203,21 @@ rs6000_frame_args_address (fi)
     return frame_initial_stack_address (fi);
 }
 
+/* Immediately after a function call, return the saved pc.
+   Can't go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  */
+
+static CORE_ADDR
+rs6000_saved_pc_after_call (struct frame_info *fi)
+{
+  return read_register (gdbarch_tdep (current_gdbarch)->ppc_lr_regnum);
+}
 
 /* Calculate the destination of a branch/jump.  Return -1 if not a branch.  */
 
 static CORE_ADDR
-branch_dest (opcode, instr, pc, safety)
-     int opcode;
-     int instr;
-     CORE_ADDR pc;
-     CORE_ADDR safety;
+branch_dest (int opcode, int instr, CORE_ADDR pc, CORE_ADDR safety)
 {
   CORE_ADDR dest;
   int immediate;
@@ -158,7 +249,7 @@ branch_dest (opcode, instr, pc, safety)
 
       if (ext_op == 16)                /* br conditional register */
        {
-         dest = read_register (LR_REGNUM) & ~3;
+          dest = read_register (gdbarch_tdep (current_gdbarch)->ppc_lr_regnum) & ~3;
 
          /* If we are about to return from a signal handler, dest is
             something like 0x3c90.  The current frame is a signal handler
@@ -170,20 +261,20 @@ branch_dest (opcode, instr, pc, safety)
 
              fi = get_current_frame ();
              if (fi != NULL)
-               dest = read_memory_integer (fi->frame + SIG_FRAME_PC_OFFSET,
-                                           4);
+               dest = read_memory_addr (fi->frame + SIG_FRAME_PC_OFFSET,
+                                        gdbarch_tdep (current_gdbarch)->wordsize);
            }
        }
 
       else if (ext_op == 528)  /* br cond to count reg */
        {
-         dest = read_register (CTR_REGNUM) & ~3;
+          dest = read_register (gdbarch_tdep (current_gdbarch)->ppc_ctr_regnum) & ~3;
 
          /* If we are about to execute a system call, dest is something
             like 0x22fc or 0x3b00.  Upon completion the system call
             will return to the address in the link register.  */
          if (dest < TEXT_SEGMENT_BASE)
-           dest = read_register (LR_REGNUM) & ~3;
+            dest = read_register (gdbarch_tdep (current_gdbarch)->ppc_lr_regnum) & ~3;
        }
       else
        return -1;
@@ -201,15 +292,13 @@ branch_dest (opcode, instr, pc, safety)
 #define BIG_BREAKPOINT { 0x7d, 0x82, 0x10, 0x08 }
 #define LITTLE_BREAKPOINT { 0x08, 0x10, 0x82, 0x7d }
 
-unsigned char *
-rs6000_breakpoint_from_pc (bp_addr, bp_size)
-     CORE_ADDR *bp_addr;
-     int *bp_size;
+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;
   *bp_size = 4;
-  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
     return big_breakpoint;
   else
     return little_breakpoint;
@@ -219,15 +308,12 @@ rs6000_breakpoint_from_pc (bp_addr, bp_size)
 /* AIX does not support PT_STEP. Simulate it. */
 
 void
-rs6000_software_single_step (signal, insert_breakpoints_p)
-     unsigned int signal;
-     int insert_breakpoints_p;
+rs6000_software_single_step (enum target_signal signal,
+                            int insert_breakpoints_p)
 {
-#define        INSNLEN(OPCODE)  4
-
-  static char le_breakp[] = LITTLE_BREAKPOINT;
-  static char be_breakp[] = BIG_BREAKPOINT;
-  char *breakp = TARGET_BYTE_ORDER == BIG_ENDIAN ? be_breakp : le_breakp;
+  CORE_ADDR dummy;
+  int breakp_sz;
+  const char *breakp = rs6000_breakpoint_from_pc (&dummy, &breakp_sz);
   int ii, insn;
   CORE_ADDR loc;
   CORE_ADDR breaks[2];
@@ -240,7 +326,7 @@ rs6000_software_single_step (signal, insert_breakpoints_p)
 
       insn = read_memory_integer (loc, 4);
 
-      breaks[0] = loc + INSNLEN (insn);
+      breaks[0] = loc + breakp_sz;
       opcode = insn >> 26;
       breaks[1] = branch_dest (opcode, insn, loc, breaks[0]);
 
@@ -256,10 +342,7 @@ rs6000_software_single_step (signal, insert_breakpoints_p)
          /* ignore invalid breakpoint. */
          if (breaks[ii] == -1)
            continue;
-
-         read_memory (breaks[ii], stepBreaks[ii].data, 4);
-
-         write_memory (breaks[ii], breakp, 4);
+         target_insert_breakpoint (breaks[ii], stepBreaks[ii].data);
          stepBreaks[ii].address = breaks[ii];
        }
 
@@ -270,9 +353,8 @@ rs6000_software_single_step (signal, insert_breakpoints_p)
       /* remove step breakpoints. */
       for (ii = 0; ii < 2; ++ii)
        if (stepBreaks[ii].address != 0)
-         write_memory
-           (stepBreaks[ii].address, stepBreaks[ii].data, 4);
-
+         target_remove_breakpoint (stepBreaks[ii].address,
+                                   stepBreaks[ii].data);
     }
   errno = 0;                   /* FIXME, don't ignore errors! */
   /* What errors?  {read,write}_memory call error().  */
@@ -289,12 +371,17 @@ rs6000_software_single_step (signal, insert_breakpoints_p)
    which we decrement the sp to allocate the frame.
    - saved_gpr is the number of the first saved gpr.
    - saved_fpr is the number of the first saved fpr.
+   - saved_vr is the number of the first saved vr.
+   - saved_ev is the number of the first saved ev.
    - alloca_reg is the number of the register used for alloca() handling.
    Otherwise -1.
    - gpr_offset is the offset of the first saved gpr from the previous frame.
    - fpr_offset is the offset of the first saved fpr from the previous frame.
+   - vr_offset is the offset of the first saved vr from the previous frame.
+   - ev_offset is the offset of the first saved ev from the previous frame.
    - lr_offset is the offset of the saved lr
    - cr_offset is the offset of the saved cr
+   - vrsave_offset is the offset of the saved vrsave register
  */
 
 #define SIGNED_SHORT(x)                                                \
@@ -304,38 +391,125 @@ rs6000_software_single_step (signal, insert_breakpoints_p)
 
 #define GET_SRC_REG(x) (((x) >> 21) & 0x1f)
 
-CORE_ADDR
-skip_prologue (pc, fdata)
-     CORE_ADDR pc;
-     struct rs6000_framedata *fdata;
+/* Limit the number of skipped non-prologue instructions, as the examining
+   of the prologue is expensive.  */
+static int max_skip_non_prologue_insns = 10;
+
+/* Given PC representing the starting address of a function, and
+   LIM_PC which is the (sloppy) limit to which to scan when looking
+   for a prologue, attempt to further refine this limit by using
+   the line data in the symbol table.  If successful, a better guess
+   on where the prologue ends is returned, otherwise the previous
+   value of lim_pc is returned.  */
+static CORE_ADDR
+refine_prologue_limit (CORE_ADDR pc, CORE_ADDR lim_pc)
+{
+  struct symtab_and_line prologue_sal;
+
+  prologue_sal = find_pc_line (pc, 0);
+  if (prologue_sal.line != 0)
+    {
+      int i;
+      CORE_ADDR addr = prologue_sal.end;
+
+      /* Handle the case in which compiler's optimizer/scheduler
+         has moved instructions into the prologue.  We scan ahead
+        in the function looking for address ranges whose corresponding
+        line number is less than or equal to the first one that we
+        found for the function.  (It can be less than when the
+        scheduler puts a body instruction before the first prologue
+        instruction.)  */
+      for (i = 2 * max_skip_non_prologue_insns; 
+           i > 0 && (lim_pc == 0 || addr < lim_pc);
+          i--)
+        {
+         struct symtab_and_line sal;
+
+         sal = find_pc_line (addr, 0);
+         if (sal.line == 0)
+           break;
+         if (sal.line <= prologue_sal.line 
+             && sal.symtab == prologue_sal.symtab)
+           {
+             prologue_sal = sal;
+           }
+         addr = sal.end;
+       }
+
+      if (lim_pc == 0 || prologue_sal.end < lim_pc)
+       lim_pc = prologue_sal.end;
+    }
+  return lim_pc;
+}
+
+
+static CORE_ADDR
+skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
 {
   CORE_ADDR orig_pc = pc;
+  CORE_ADDR last_prologue_pc = pc;
+  CORE_ADDR li_found_pc = 0;
   char buf[4];
   unsigned long op;
   long offset = 0;
+  long vr_saved_offset = 0;
   int lr_reg = -1;
   int cr_reg = -1;
+  int vr_reg = -1;
+  int ev_reg = -1;
+  long ev_offset = 0;
+  int vrsave_reg = -1;
   int reg;
   int framep = 0;
   int minimal_toc_loaded = 0;
-  static struct rs6000_framedata zero_frame;
-
-  *fdata = zero_frame;
+  int prev_insn_was_prologue_insn = 1;
+  int num_skip_non_prologue_insns = 0;
+  const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (current_gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  
+  /* Attempt to find the end of the prologue when no limit is specified.
+     Note that refine_prologue_limit() has been written so that it may
+     be used to "refine" the limits of non-zero PC values too, but this
+     is only safe if we 1) trust the line information provided by the
+     compiler and 2) iterate enough to actually find the end of the
+     prologue.  
+     
+     It may become a good idea at some point (for both performance and
+     accuracy) to unconditionally call refine_prologue_limit().  But,
+     until we can make a clear determination that this is beneficial,
+     we'll play it safe and only use it to obtain a limit when none
+     has been specified.  */
+  if (lim_pc == 0)
+    lim_pc = refine_prologue_limit (pc, lim_pc);
+
+  memset (fdata, 0, sizeof (struct rs6000_framedata));
   fdata->saved_gpr = -1;
   fdata->saved_fpr = -1;
+  fdata->saved_vr = -1;
+  fdata->saved_ev = -1;
   fdata->alloca_reg = -1;
   fdata->frameless = 1;
   fdata->nosavedpc = 1;
 
-  if (target_read_memory (pc, buf, 4))
-    return pc;                 /* Can't access it -- assume no prologue. */
-
-  /* Assume that subsequent fetches can fail with low probability.  */
-  pc -= 4;
-  for (;;)
+  for (;; pc += 4)
     {
-      pc += 4;
-      op = read_memory_integer (pc, 4);
+      /* Sometimes it isn't clear if an instruction is a prologue
+         instruction or not.  When we encounter one of these ambiguous
+        cases, we'll set prev_insn_was_prologue_insn to 0 (false).
+        Otherwise, we'll assume that it really is a prologue instruction. */
+      if (prev_insn_was_prologue_insn)
+       last_prologue_pc = pc;
+
+      /* Stop scanning if we've hit the limit.  */
+      if (lim_pc != 0 && pc >= lim_pc)
+       break;
+
+      prev_insn_was_prologue_insn = 1;
+
+      /* Fetch the instruction and convert it to an integer.  */
+      if (target_read_memory (pc, buf, 4))
+       break;
+      op = extract_signed_integer (buf, 4);
 
       if ((op & 0xfc1fffff) == 0x7c0802a6)
        {                       /* mflr Rx */
@@ -361,19 +535,31 @@ skip_prologue (pc, fdata)
 
        }
       else if (((op & 0xfc1f0000) == 0xbc010000) ||    /* stm Rx, NUM(r1) */
-              ((op & 0xfc1f0000) == 0x90010000 &&      /* st rx,NUM(r1), 
-                                                          rx >= r13 */
-               (op & 0x03e00000) >= 0x01a00000))
+              (((op & 0xfc1f0000) == 0x90010000 ||     /* st rx,NUM(r1) */
+                (op & 0xfc1f0003) == 0xf8010000) &&    /* std rx,NUM(r1) */
+               (op & 0x03e00000) >= 0x01a00000))       /* rx >= r13 */
        {
 
          reg = GET_SRC_REG (op);
          if (fdata->saved_gpr == -1 || fdata->saved_gpr > reg)
            {
              fdata->saved_gpr = reg;
+             if ((op & 0xfc1f0003) == 0xf8010000)
+               op = (op >> 1) << 1;
              fdata->gpr_offset = SIGNED_SHORT (op) + offset;
            }
          continue;
 
+       }
+      else if ((op & 0xffff0000) == 0x60000000)
+        {
+         /* nop */
+         /* Allow nops in the prologue, but do not consider them to
+            be part of the prologue unless followed by other prologue
+            instructions. */
+         prev_insn_was_prologue_insn = 0;
+         continue;
+
        }
       else if ((op & 0xffff0000) == 0x3c000000)
        {                       /* addis 0,0,NUM, used
@@ -419,17 +605,8 @@ skip_prologue (pc, fdata)
          break;
 
        }
-      else if (((op & 0xffff0000) == 0x801e0000 ||     /* lwz 0,NUM(r30), used
-                                                          in V.4 -mrelocatable */
-               op == 0x7fc0f214) &&    /* add r30,r0,r30, used
-                                          in V.4 -mrelocatable */
-              lr_reg == 0x901e0000)
-       {
-         continue;
-
-       }
-      else if ((op & 0xffff0000) == 0x3fc00000 ||      /* addis 30,0,foo@ha, used
-                                                          in V.4 -mminimal-toc */
+      else if ((op & 0xffff0000) == 0x3fc00000 ||  /* addis 30,0,foo@ha, used
+                                                     in V.4 -mminimal-toc */
               (op & 0xffff0000) == 0x3bde0000)
        {                       /* addi 30,30,foo@l */
          continue;
@@ -440,17 +617,17 @@ skip_prologue (pc, fdata)
                                   to save fprs??? */
 
          fdata->frameless = 0;
-         /* Don't skip over the subroutine call if it is not within the first
-            three instructions of the prologue.  */
+         /* Don't skip over the subroutine call if it is not within
+            the first three instructions of the prologue.  */
          if ((pc - orig_pc) > 8)
            break;
 
          op = read_memory_integer (pc + 4, 4);
 
-         /* At this point, make sure this is not a trampoline function
-            (a function that simply calls another functions, and nothing else).
-            If the next is not a nop, this branch was part of the function
-            prologue. */
+         /* At this point, make sure this is not a trampoline
+            function (a function that simply calls another functions,
+            and nothing else).  If the next is not a nop, this branch
+            was part of the function prologue. */
 
          if (op == 0x4def7b82 || op == 0)      /* crorc 15, 15, 15 */
            break;              /* don't skip over 
@@ -459,9 +636,12 @@ skip_prologue (pc, fdata)
 
          /* update stack pointer */
        }
-      else if ((op & 0xffff0000) == 0x94210000)
-       {                       /* stu r1,NUM(r1) */
+      else if ((op & 0xffff0000) == 0x94210000 ||      /* stu r1,NUM(r1) */
+              (op & 0xffff0003) == 0xf8210001)         /* stdu r1,NUM(r1) */
+       {
          fdata->frameless = 0;
+         if ((op & 0xffff0003) == 0xf8210001)
+           op = (op >> 1) << 1;
          fdata->offset = SIGNED_SHORT (op);
          offset = fdata->offset;
          continue;
@@ -487,16 +667,16 @@ skip_prologue (pc, fdata)
       else if ((op & 0xfc0007fe) == 0x7c000378 &&      /* mr(.)  Rx,Ry */
                (((op >> 21) & 31) >= 3) &&              /* R3 >= Ry >= R10 */
                (((op >> 21) & 31) <= 10) &&
-               (((op >> 16) & 31) >= fdata->saved_gpr)) /* Rx: local var reg */
+               ((long) ((op >> 16) & 31) >= fdata->saved_gpr)) /* Rx: local var reg */
        {
          continue;
 
          /* store parameters in stack */
        }
-      else if ((op & 0xfc1f0000) == 0x90010000 ||      /* st rx,NUM(r1) */
+      else if ((op & 0xfc1f0003) == 0xf8010000 ||      /* std rx,NUM(r1) */
               (op & 0xfc1f0000) == 0xd8010000 ||       /* stfd Rx,NUM(r1) */
-              (op & 0xfc1f0000) == 0xfc010000)
-       {                       /* frsp, fp?,NUM(r1) */
+              (op & 0xfc1f0000) == 0xfc010000)         /* frsp, fp?,NUM(r1) */
+       {
          continue;
 
          /* store parameters in stack via frame pointer */
@@ -515,7 +695,7 @@ skip_prologue (pc, fdata)
        {                       /* mr r31, r1 */
          fdata->frameless = 0;
          framep = 1;
-         fdata->alloca_reg = 31;
+         fdata->alloca_reg = (tdep->ppc_gp0_regnum + 31);
          continue;
 
          /* Another way to set up the frame pointer.  */
@@ -524,13 +704,204 @@ skip_prologue (pc, fdata)
        {                       /* addi rX, r1, 0x0 */
          fdata->frameless = 0;
          framep = 1;
-         fdata->alloca_reg = (op & ~0x38010000) >> 21;
+         fdata->alloca_reg = (tdep->ppc_gp0_regnum
+                              + ((op & ~0x38010000) >> 21));
+         continue;
+       }
+      /* AltiVec related instructions.  */
+      /* Store the vrsave register (spr 256) in another register for
+        later manipulation, or load a register into the vrsave
+        register.  2 instructions are used: mfvrsave and
+        mtvrsave.  They are shorthand notation for mfspr Rn, SPR256
+        and mtspr SPR256, Rn.  */
+      /* mfspr Rn SPR256 == 011111 nnnnn 0000001000 01010100110
+        mtspr SPR256 Rn == 011111 nnnnn 0000001000 01110100110  */
+      else if ((op & 0xfc1fffff) == 0x7c0042a6)    /* mfvrsave Rn */
+       {
+          vrsave_reg = GET_SRC_REG (op);
          continue;
+       }
+      else if ((op & 0xfc1fffff) == 0x7c0043a6)     /* mtvrsave Rn */
+        {
+          continue;
+        }
+      /* Store the register where vrsave was saved to onto the stack:
+         rS is the register where vrsave was stored in a previous
+        instruction.  */
+      /* 100100 sssss 00001 dddddddd dddddddd */
+      else if ((op & 0xfc1f0000) == 0x90010000)     /* stw rS, d(r1) */
+        {
+          if (vrsave_reg == GET_SRC_REG (op))
+           {
+             fdata->vrsave_offset = SIGNED_SHORT (op) + offset;
+             vrsave_reg = -1;
+           }
+          continue;
+        }
+      /* Compute the new value of vrsave, by modifying the register
+         where vrsave was saved to.  */
+      else if (((op & 0xfc000000) == 0x64000000)    /* oris Ra, Rs, UIMM */
+              || ((op & 0xfc000000) == 0x60000000))/* ori Ra, Rs, UIMM */
+       {
+         continue;
+       }
+      /* li r0, SIMM (short for addi r0, 0, SIMM).  This is the first
+        in a pair of insns to save the vector registers on the
+        stack.  */
+      /* 001110 00000 00000 iiii iiii iiii iiii  */
+      /* 001110 01110 00000 iiii iiii iiii iiii  */
+      else if ((op & 0xffff0000) == 0x38000000         /* li r0, SIMM */
+               || (op & 0xffff0000) == 0x39c00000)     /* li r14, SIMM */
+       {
+         li_found_pc = pc;
+         vr_saved_offset = SIGNED_SHORT (op);
+       }
+      /* Store vector register S at (r31+r0) aligned to 16 bytes.  */      
+      /* 011111 sssss 11111 00000 00111001110 */
+      else if ((op & 0xfc1fffff) == 0x7c1f01ce)   /* stvx Vs, R31, R0 */
+        {
+         if (pc == (li_found_pc + 4))
+           {
+             vr_reg = GET_SRC_REG (op);
+             /* If this is the first vector reg to be saved, or if
+                it has a lower number than others previously seen,
+                reupdate the frame info.  */
+             if (fdata->saved_vr == -1 || fdata->saved_vr > vr_reg)
+               {
+                 fdata->saved_vr = vr_reg;
+                 fdata->vr_offset = vr_saved_offset + offset;
+               }
+             vr_saved_offset = -1;
+             vr_reg = -1;
+             li_found_pc = 0;
+           }
+       }
+      /* End AltiVec related instructions.  */
+
+      /* Start BookE related instructions.  */
+      /* Store gen register S at (r31+uimm).
+         Any register less than r13 is volatile, so we don't care.  */
+      /* 000100 sssss 11111 iiiii 01100100001 */
+      else if (arch_info->mach == bfd_mach_ppc_e500
+              && (op & 0xfc1f07ff) == 0x101f0321)    /* evstdd Rs,uimm(R31) */
+       {
+          if ((op & 0x03e00000) >= 0x01a00000) /* Rs >= r13 */
+           {
+              unsigned int imm;
+             ev_reg = GET_SRC_REG (op);
+              imm = (op >> 11) & 0x1f;
+             ev_offset = imm * 8;
+             /* If this is the first vector reg to be saved, or if
+                it has a lower number than others previously seen,
+                reupdate the frame info.  */
+             if (fdata->saved_ev == -1 || fdata->saved_ev > ev_reg)
+               {
+                 fdata->saved_ev = ev_reg;
+                 fdata->ev_offset = ev_offset + offset;
+               }
+           }
+          continue;
+        }
+      /* Store gen register rS at (r1+rB).  */
+      /* 000100 sssss 00001 bbbbb 01100100000 */
+      else if (arch_info->mach == bfd_mach_ppc_e500
+              && (op & 0xffe007ff) == 0x13e00320)     /* evstddx RS,R1,Rb */
+       {
+          if (pc == (li_found_pc + 4))
+            {
+              ev_reg = GET_SRC_REG (op);
+             /* If this is the first vector reg to be saved, or if
+                 it has a lower number than others previously seen,
+                 reupdate the frame info.  */
+              /* We know the contents of rB from the previous instruction.  */
+             if (fdata->saved_ev == -1 || fdata->saved_ev > ev_reg)
+               {
+                  fdata->saved_ev = ev_reg;
+                  fdata->ev_offset = vr_saved_offset + offset;
+               }
+             vr_saved_offset = -1;
+             ev_reg = -1;
+             li_found_pc = 0;
+            }
+          continue;
+        }
+      /* Store gen register r31 at (rA+uimm).  */
+      /* 000100 11111 aaaaa iiiii 01100100001 */
+      else if (arch_info->mach == bfd_mach_ppc_e500
+              && (op & 0xffe007ff) == 0x13e00321)   /* evstdd R31,Ra,UIMM */
+        {
+          /* Wwe know that the source register is 31 already, but
+             it can't hurt to compute it.  */
+         ev_reg = GET_SRC_REG (op);
+          ev_offset = ((op >> 11) & 0x1f) * 8;
+         /* If this is the first vector reg to be saved, or if
+            it has a lower number than others previously seen,
+            reupdate the frame info.  */
+         if (fdata->saved_ev == -1 || fdata->saved_ev > ev_reg)
+           {
+             fdata->saved_ev = ev_reg;
+             fdata->ev_offset = ev_offset + offset;
+           }
 
+         continue;
+       }
+      /* Store gen register S at (r31+r0).
+         Store param on stack when offset from SP bigger than 4 bytes.  */
+      /* 000100 sssss 11111 00000 01100100000 */
+      else if (arch_info->mach == bfd_mach_ppc_e500
+              && (op & 0xfc1fffff) == 0x101f0320)     /* evstddx Rs,R31,R0 */
+       {
+          if (pc == (li_found_pc + 4))
+            {
+              if ((op & 0x03e00000) >= 0x01a00000)
+               {
+                 ev_reg = GET_SRC_REG (op);
+                 /* If this is the first vector reg to be saved, or if
+                    it has a lower number than others previously seen,
+                    reupdate the frame info.  */
+                  /* We know the contents of r0 from the previous
+                     instruction.  */
+                 if (fdata->saved_ev == -1 || fdata->saved_ev > ev_reg)
+                   {
+                     fdata->saved_ev = ev_reg;
+                     fdata->ev_offset = vr_saved_offset + offset;
+                   }
+                 ev_reg = -1;
+               }
+             vr_saved_offset = -1;
+             li_found_pc = 0;
+             continue;
+            }
        }
+      /* End BookE related instructions.  */
+
       else
        {
-         break;
+         /* Not a recognized prologue instruction.
+            Handle optimizer code motions into the prologue by continuing
+            the search if we have no valid frame yet or if the return
+            address is not yet saved in the frame.  */
+         if (fdata->frameless == 0
+             && (lr_reg == -1 || fdata->nosavedpc == 0))
+           break;
+
+         if (op == 0x4e800020          /* blr */
+             || op == 0x4e800420)      /* bctr */
+           /* Do not scan past epilogue in frameless functions or
+              trampolines.  */
+           break;
+         if ((op & 0xf4000000) == 0x40000000) /* bxx */
+           /* Never skip branches.  */
+           break;
+
+         if (num_skip_non_prologue_insns++ > max_skip_non_prologue_insns)
+           /* Do not scan too many insns, scanning insns is expensive with
+              remote targets.  */
+           break;
+
+         /* Continue scanning.  */
+         prev_insn_was_prologue_insn = 0;
+         continue;
        }
     }
 
@@ -541,9 +912,9 @@ skip_prologue (pc, fdata)
 
   /* If the first thing after skipping a prolog is a branch to a function,
      this might be a call to an initializer in main(), introduced by gcc2.
-     We'd like to skip over it as well. Fortunately, xlc does some extra
+     We'd like to skip over it as well.  Fortunately, xlc does some extra
      work before calling a function right after a prologue, thus we can
-     single out such gcc2 behaviour. */
+     single out such gcc2 behaviour.  */
 
 
   if ((op & 0xfc000001) == 0x48000001)
@@ -553,18 +924,18 @@ skip_prologue (pc, fdata)
       if (op == 0x4def7b82)
        {                       /* cror 0xf, 0xf, 0xf (nop) */
 
-         /* check and see if we are in main. If so, skip over this initializer
-            function as well. */
+         /* Check and see if we are in main.  If so, skip over this
+            initializer function as well.  */
 
          tmp = find_pc_misc_function (pc);
-         if (tmp >= 0 && STREQ (misc_function_vector[tmp].name, "main"))
+         if (tmp >= 0 && STREQ (misc_function_vector[tmp].name, main_name ()))
            return pc + 8;
        }
     }
 #endif /* 0 */
 
   fdata->offset = -fdata->offset;
-  return pc;
+  return last_prologue_pc;
 }
 
 
@@ -573,242 +944,60 @@ skip_prologue (pc, fdata)
   frames, etc. 
 *************************************************************************/
 
-/* The total size of dummy frame is 436, which is;
-
-   32 gpr's           - 128 bytes
-   32 fpr's           - 256 bytes
-   7  the rest        -  28 bytes
-   callee's link area -  24 bytes
-   padding            -  12 bytes
-
-   Note that the last 24 bytes for the link area might not be necessary,
-   since it will be taken care of by push_arguments(). */
-
-#define DUMMY_FRAME_SIZE 448
-
-#define        DUMMY_FRAME_ADDR_SIZE 10
-
-/* Make sure you initialize these in somewhere, in case gdb gives up what it
-   was debugging and starts debugging something else. FIXMEibm */
-
-static int dummy_frame_count = 0;
-static int dummy_frame_size = 0;
-static CORE_ADDR *dummy_frame_addr = 0;
-
-extern int stop_stack_dummy;
-
-/* push a dummy frame into stack, save all register. Currently we are saving
-   only gpr's and fpr's, which is not good enough! FIXMEmgo */
-
-void
-push_dummy_frame ()
-{
-  /* stack pointer.  */
-  CORE_ADDR sp;
-  /* Same thing, target byte order.  */
-  char sp_targ[4];
-
-  /* link register.  */
-  CORE_ADDR pc;
-  /* Same thing, target byte order.  */
-  char pc_targ[4];
-
-  /* Needed to figure out where to save the dummy link area.
-     FIXME: There should be an easier way to do this, no?  tiemann 9/9/95.  */
-  struct rs6000_framedata fdata;
-
-  int ii;
-
-  target_fetch_registers (-1);
-
-  if (dummy_frame_count >= dummy_frame_size)
-    {
-      dummy_frame_size += DUMMY_FRAME_ADDR_SIZE;
-      if (dummy_frame_addr)
-       dummy_frame_addr = (CORE_ADDR *) xrealloc
-         (dummy_frame_addr, sizeof (CORE_ADDR) * (dummy_frame_size));
-      else
-       dummy_frame_addr = (CORE_ADDR *)
-         xmalloc (sizeof (CORE_ADDR) * (dummy_frame_size));
-    }
-
-  sp = read_register (SP_REGNUM);
-  pc = read_register (PC_REGNUM);
-  store_address (pc_targ, 4, pc);
-
-  skip_prologue (get_pc_function_start (pc), &fdata);
-
-  dummy_frame_addr[dummy_frame_count++] = sp;
-
-  /* Be careful! If the stack pointer is not decremented first, then kernel 
-     thinks he is free to use the space underneath it. And kernel actually 
-     uses that area for IPC purposes when executing ptrace(2) calls. So 
-     before writing register values into the new frame, decrement and update
-     %sp first in order to secure your frame. */
-
-  /* FIXME: We don't check if the stack really has this much space.
-     This is a problem on the ppc simulator (which only grants one page
-     (4096 bytes) by default.  */
-
-  write_register (SP_REGNUM, sp - DUMMY_FRAME_SIZE);
-
-  /* gdb relies on the state of current_frame. We'd better update it,
-     otherwise things like do_registers_info() wouldn't work properly! */
-
-  flush_cached_frames ();
-
-  /* save program counter in link register's space. */
-  write_memory (sp + (fdata.lr_offset ? fdata.lr_offset : DEFAULT_LR_SAVE),
-               pc_targ, 4);
-
-  /* save all floating point and general purpose registers here. */
-
-  /* fpr's, f0..f31 */
-  for (ii = 0; ii < 32; ++ii)
-    write_memory (sp - 8 - (ii * 8), &registers[REGISTER_BYTE (31 - ii + FP0_REGNUM)], 8);
-
-  /* gpr's r0..r31 */
-  for (ii = 1; ii <= 32; ++ii)
-    write_memory (sp - 256 - (ii * 4), &registers[REGISTER_BYTE (32 - ii)], 4);
 
-  /* so far, 32*2 + 32 words = 384 bytes have been written. 
-     7 extra registers in our register set: pc, ps, cnd, lr, cnt, xer, mq */
-
-  for (ii = 1; ii <= (LAST_UISA_SP_REGNUM - FIRST_UISA_SP_REGNUM + 1); ++ii)
-    {
-      write_memory (sp - 384 - (ii * 4),
-                   &registers[REGISTER_BYTE (FPLAST_REGNUM + ii)], 4);
-    }
-
-  /* Save sp or so called back chain right here. */
-  store_address (sp_targ, 4, sp);
-  write_memory (sp - DUMMY_FRAME_SIZE, sp_targ, 4);
-  sp -= DUMMY_FRAME_SIZE;
-
-  /* And finally, this is the back chain. */
-  write_memory (sp + 8, pc_targ, 4);
-}
-
-
-/* Pop a dummy frame.
-
-   In rs6000 when we push a dummy frame, we save all of the registers. This
-   is usually done before user calls a function explicitly.
-
-   After a dummy frame is pushed, some instructions are copied into stack,
-   and stack pointer is decremented even more.  Since we don't have a frame
-   pointer to get back to the parent frame of the dummy, we start having
-   trouble poping it.  Therefore, we keep a dummy frame stack, keeping
-   addresses of dummy frames as such.  When poping happens and when we
-   detect that was a dummy frame, we pop it back to its parent by using
-   dummy frame stack (`dummy_frame_addr' array). 
-
-   FIXME:  This whole concept is broken.  You should be able to detect
-   a dummy stack frame *on the user's stack itself*.  When you do,
-   then you know the format of that stack frame -- including its
-   saved SP register!  There should *not* be a separate stack in the
-   GDB process that keeps track of these dummy frames!  -- gnu@cygnus.com Aug92
- */
+/* Pop the innermost frame, go back to the caller.  */
 
 static void
-pop_dummy_frame ()
-{
-  CORE_ADDR sp, pc;
-  int ii;
-  sp = dummy_frame_addr[--dummy_frame_count];
-
-  /* restore all fpr's. */
-  for (ii = 1; ii <= 32; ++ii)
-    read_memory (sp - (ii * 8), &registers[REGISTER_BYTE (32 - ii + FP0_REGNUM)], 8);
-
-  /* restore all gpr's */
-  for (ii = 1; ii <= 32; ++ii)
-    {
-      read_memory (sp - 256 - (ii * 4), &registers[REGISTER_BYTE (32 - ii)], 4);
-    }
-
-  /* restore the rest of the registers. */
-  for (ii = 1; ii <= (LAST_UISA_SP_REGNUM - FIRST_UISA_SP_REGNUM + 1); ++ii)
-    read_memory (sp - 384 - (ii * 4),
-                &registers[REGISTER_BYTE (FPLAST_REGNUM + ii)], 4);
-
-  read_memory (sp - (DUMMY_FRAME_SIZE - 8),
-              &registers[REGISTER_BYTE (PC_REGNUM)], 4);
-
-  /* when a dummy frame was being pushed, we had to decrement %sp first, in 
-     order to secure astack space. Thus, saved %sp (or %r1) value, is not the
-     one we should restore. Change it with the one we need. */
-
-  memcpy (&registers[REGISTER_BYTE (FP_REGNUM)], (char *) &sp, sizeof (int));
-
-  /* Now we can restore all registers. */
-
-  target_store_registers (-1);
-  pc = read_pc ();
-  flush_cached_frames ();
-}
-
-
-/* pop the innermost frame, go back to the caller. */
-
-void
-pop_frame ()
+rs6000_pop_frame (void)
 {
-  CORE_ADDR pc, lr, sp, prev_sp;       /* %pc, %lr, %sp */
+  CORE_ADDR pc, lr, sp, prev_sp, addr; /* %pc, %lr, %sp */
   struct rs6000_framedata fdata;
   struct frame_info *frame = get_current_frame ();
-  int addr, ii;
+  int ii, wordsize;
 
   pc = read_pc ();
   sp = FRAME_FP (frame);
 
-  if (stop_stack_dummy)
+  if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
     {
-      if (USE_GENERIC_DUMMY_FRAMES)
-       {
-         generic_pop_dummy_frame ();
-         flush_cached_frames ();
-         return;
-       }
-      else
-       {
-         if (dummy_frame_count)
-           pop_dummy_frame ();
-         return;
-       }
+      generic_pop_dummy_frame ();
+      flush_cached_frames ();
+      return;
     }
 
   /* Make sure that all registers are valid.  */
-  read_register_bytes (0, NULL, REGISTER_BYTES);
+  deprecated_read_register_bytes (0, NULL, REGISTER_BYTES);
 
-  /* figure out previous %pc value. If the function is frameless, it is 
+  /* Figure out previous %pc value.  If the function is frameless, it is 
      still in the link register, otherwise walk the frames and retrieve the
-     saved %pc value in the previous frame. */
+     saved %pc value in the previous frame.  */
 
   addr = get_pc_function_start (frame->pc);
-  (void) skip_prologue (addr, &fdata);
+  (void) skip_prologue (addr, frame->pc, &fdata);
 
+  wordsize = gdbarch_tdep (current_gdbarch)->wordsize;
   if (fdata.frameless)
     prev_sp = sp;
   else
-    prev_sp = read_memory_integer (sp, 4);
+    prev_sp = read_memory_addr (sp, wordsize);
   if (fdata.lr_offset == 0)
-    lr = read_register (LR_REGNUM);
+     lr = read_register (gdbarch_tdep (current_gdbarch)->ppc_lr_regnum);
   else
-    lr = read_memory_integer (prev_sp + fdata.lr_offset, 4);
+    lr = read_memory_addr (prev_sp + fdata.lr_offset, wordsize);
 
   /* reset %pc value. */
   write_register (PC_REGNUM, lr);
 
-  /* reset register values if any was saved earlier. */
+  /* reset register values if any was saved earlier.  */
 
   if (fdata.saved_gpr != -1)
     {
       addr = prev_sp + fdata.gpr_offset;
       for (ii = fdata.saved_gpr; ii <= 31; ++ii)
        {
-         read_memory (addr, &registers[REGISTER_BYTE (ii)], 4);
-         addr += 4;
+         read_memory (addr, &deprecated_registers[REGISTER_BYTE (ii)],
+                      wordsize);
+         addr += wordsize;
        }
     }
 
@@ -817,7 +1006,7 @@ pop_frame ()
       addr = prev_sp + fdata.fpr_offset;
       for (ii = fdata.saved_fpr; ii <= 31; ++ii)
        {
-         read_memory (addr, &registers[REGISTER_BYTE (ii + FP0_REGNUM)], 8);
+         read_memory (addr, &deprecated_registers[REGISTER_BYTE (ii + FP0_REGNUM)], 8);
          addr += 8;
        }
     }
@@ -827,80 +1016,51 @@ pop_frame ()
   flush_cached_frames ();
 }
 
-/* fixup the call sequence of a dummy function, with the real function address.
-   its argumets will be passed by gdb. */
-
-void
-rs6000_fix_call_dummy (dummyname, pc, fun, nargs, args, type, gcc_p)
-     char *dummyname;
-     CORE_ADDR pc;
-     CORE_ADDR fun;
-     int nargs;
-     value_ptr *args;
-     struct type *type;
-     int gcc_p;
-{
-#define        TOC_ADDR_OFFSET         20
-#define        TARGET_ADDR_OFFSET      28
+/* Fixup the call sequence of a dummy function, with the real function
+   address.  Its arguments will be passed by gdb.  */
 
+static void
+rs6000_fix_call_dummy (char *dummyname, CORE_ADDR pc, CORE_ADDR fun,
+                      int nargs, struct value **args, struct type *type,
+                      int gcc_p)
+{
   int ii;
   CORE_ADDR target_addr;
 
-  if (USE_GENERIC_DUMMY_FRAMES)
+  if (rs6000_find_toc_address_hook != NULL)
     {
-      if (find_toc_address_hook != NULL)
-       {
-         CORE_ADDR tocvalue = (*find_toc_address_hook) (fun);
-         write_register (TOC_REGNUM, tocvalue);
-       }
+      CORE_ADDR tocvalue = (*rs6000_find_toc_address_hook) (fun);
+      write_register (gdbarch_tdep (current_gdbarch)->ppc_toc_regnum,
+                     tocvalue);
     }
-  else
-    {
-      if (find_toc_address_hook != NULL)
-       {
-         CORE_ADDR tocvalue;
-
-         tocvalue = (*find_toc_address_hook) (fun);
-         ii = *(int *) ((char *) dummyname + TOC_ADDR_OFFSET);
-         ii = (ii & 0xffff0000) | (tocvalue >> 16);
-         *(int *) ((char *) dummyname + TOC_ADDR_OFFSET) = ii;
-
-         ii = *(int *) ((char *) dummyname + TOC_ADDR_OFFSET + 4);
-         ii = (ii & 0xffff0000) | (tocvalue & 0x0000ffff);
-         *(int *) ((char *) dummyname + TOC_ADDR_OFFSET + 4) = ii;
-       }
-
-      target_addr = fun;
-      ii = *(int *) ((char *) dummyname + TARGET_ADDR_OFFSET);
-      ii = (ii & 0xffff0000) | (target_addr >> 16);
-      *(int *) ((char *) dummyname + TARGET_ADDR_OFFSET) = ii;
+}
 
-      ii = *(int *) ((char *) dummyname + TARGET_ADDR_OFFSET + 4);
-      ii = (ii & 0xffff0000) | (target_addr & 0x0000ffff);
-      *(int *) ((char *) dummyname + TARGET_ADDR_OFFSET + 4) = ii;
-    }
+/* All the ABI's require 16 byte alignment.  */
+static CORE_ADDR
+rs6000_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  return (addr & -16);
 }
 
-/* Pass the arguments in either registers, or in the stack. In RS6000,
+/* Pass the arguments in either registers, or in the stack. In RS/6000,
    the first eight words of the argument list (that might be less than
    eight parameters if some parameters occupy more than one word) are
-   passed in r3..r11 registers.  float and double parameters are
-   passed in fpr's, in addition to that. Rest of the parameters if any
-   are passed in user stack. There might be cases in which half of the
+   passed in r3..r10 registers.  float and double parameters are
+   passed in fpr's, in addition to that.  Rest of the parameters if any
+   are passed in user stack.  There might be cases in which half of the
    parameter is copied into registers, the other half is pushed into
    stack.
 
+   Stack must be aligned on 64-bit boundaries when synthesizing
+   function calls.
+
    If the function is returning a structure, then the return address is passed
    in r3, then the first 7 words of the parameters can be passed in registers,
-   starting from r4. */
+   starting from r4.  */
 
-CORE_ADDR
-rs6000_push_arguments (nargs, args, sp, struct_return, struct_addr)
-     int nargs;
-     value_ptr *args;
-     CORE_ADDR sp;
-     int struct_return;
-     CORE_ADDR struct_addr;
+static CORE_ADDR
+rs6000_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
+                      int struct_return, CORE_ADDR struct_addr)
 {
   int ii;
   int len = 0;
@@ -908,25 +1068,20 @@ rs6000_push_arguments (nargs, args, sp, struct_return, struct_addr)
   int argbytes;                        /* current argument byte */
   char tmp_buffer[50];
   int f_argno = 0;             /* current floating point argno */
+  int wordsize = gdbarch_tdep (current_gdbarch)->wordsize;
 
-  value_ptr arg = 0;
+  struct value *arg = 0;
   struct type *type;
 
   CORE_ADDR saved_sp;
 
-  if (!USE_GENERIC_DUMMY_FRAMES)
-    {
-      if (dummy_frame_count <= 0)
-       printf_unfiltered ("FATAL ERROR -push_arguments()! frame not found!!\n");
-    }
-
-  /* The first eight words of ther arguments are passed in registers. Copy
-     them appropriately.
+  /* The first eight words of ther arguments are passed in registers.
+     Copy them appropriately.
 
      If the function is returning a `struct', then the first word (which 
-     will be passed in r3) is used for struct return address. In that
+     will be passed in r3) is used for struct return address.  In that
      case we should advance one word and start from r4 register to copy 
-     parameters. */
+     parameters.  */
 
   ii = struct_return ? 1 : 0;
 
@@ -960,15 +1115,15 @@ rs6000_push_arguments (nargs, args, sp, struct_return, struct_addr)
       if (TYPE_CODE (type) == TYPE_CODE_FLT)
        {
 
-         /* floating point arguments are passed in fpr's, as well as gpr's.
+         /* Floating point arguments are passed in fpr's, as well as gpr's.
             There are 13 fpr's reserved for passing parameters. At this point
-            there is no way we would run out of them. */
+            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);
 
-         memcpy (&registers[REGISTER_BYTE (FP0_REGNUM + 1 + f_argno)],
+         memcpy (&deprecated_registers[REGISTER_BYTE (FP0_REGNUM + 1 + f_argno)],
                  VALUE_CONTENTS (arg),
                  len);
          ++f_argno;
@@ -977,11 +1132,12 @@ rs6000_push_arguments (nargs, args, sp, struct_return, struct_addr)
       if (len > reg_size)
        {
 
-         /* Argument takes more than one register. */
+         /* Argument takes more than one register.  */
          while (argbytes < len)
            {
-             memset (&registers[REGISTER_BYTE (ii + 3)], 0, reg_size);
-             memcpy (&registers[REGISTER_BYTE (ii + 3)],
+             memset (&deprecated_registers[REGISTER_BYTE (ii + 3)], 0,
+                     reg_size);
+             memcpy (&deprecated_registers[REGISTER_BYTE (ii + 3)],
                      ((char *) VALUE_CONTENTS (arg)) + argbytes,
                      (len - argbytes) > reg_size
                        ? reg_size : len - argbytes);
@@ -994,10 +1150,11 @@ rs6000_push_arguments (nargs, args, sp, struct_return, struct_addr)
          --ii;
        }
       else
-       {                       /* Argument can fit in one register. No problem. */
-         int adj = TARGET_BYTE_ORDER == BIG_ENDIAN ? reg_size - len : 0;
-         memset (&registers[REGISTER_BYTE (ii + 3)], 0, reg_size);
-         memcpy ((char *)&registers[REGISTER_BYTE (ii + 3)] + adj, 
+       {
+         /* Argument can fit in one register.  No problem.  */
+         int adj = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? reg_size - len : 0;
+         memset (&deprecated_registers[REGISTER_BYTE (ii + 3)], 0, reg_size);
+         memcpy ((char *)&deprecated_registers[REGISTER_BYTE (ii + 3)] + adj, 
                  VALUE_CONTENTS (arg), len);
        }
       ++argno;
@@ -1005,34 +1162,19 @@ rs6000_push_arguments (nargs, args, sp, struct_return, struct_addr)
 
 ran_out_of_registers_for_arguments:
 
-  if (USE_GENERIC_DUMMY_FRAMES)
-    {
-      saved_sp = read_sp ();
-#ifndef ELF_OBJECT_FORMAT
-      /* location for 8 parameters are always reserved. */
-      sp -= 4 * 8;
-
-      /* another six words for back chain, TOC register, link register, etc. */
-      sp -= 24;
+  saved_sp = read_sp ();
 
-      /* stack pointer must be quadword aligned */
-      sp &= -16;
-#endif
-    }
-  else
-    {
-      /* location for 8 parameters are always reserved. */
-      sp -= 4 * 8;
+  /* Location for 8 parameters are always reserved.  */
+  sp -= wordsize * 8;
 
-      /* another six words for back chain, TOC register, link register, etc. */
-      sp -= 24;
+  /* Another six words for back chain, TOC register, link register, etc.  */
+  sp -= wordsize * 6;
 
-      /* stack pointer must be quadword aligned */
-      sp &= -16;
-    }
+  /* Stack pointer must be quadword aligned.  */
+  sp &= -16;
 
-  /* if there are more arguments, allocate space for them in 
-     the stack, then push them starting from the ninth one. */
+  /* If there are more arguments, allocate space for them in 
+     the stack, then push them starting from the ninth one.  */
 
   if ((argno < nargs) || argbytes)
     {
@@ -1048,23 +1190,24 @@ ran_out_of_registers_for_arguments:
 
       for (; jj < nargs; ++jj)
        {
-         value_ptr val = args[jj];
+         struct value *val = args[jj];
          space += ((TYPE_LENGTH (VALUE_TYPE (val))) + 3) & -4;
        }
 
-      /* add location required for the rest of the parameters */
+      /* Add location required for the rest of the parameters.  */
       space = (space + 15) & -16;
       sp -= space;
 
-      /* This is another instance we need to be concerned about securing our
-         stack space. If we write anything underneath %sp (r1), we might conflict
-         with the kernel who thinks he is free to use this area. So, update %sp
-         first before doing anything else. */
+      /* This is another instance we need to be concerned about
+         securing our stack space. If we write anything underneath %sp
+         (r1), we might conflict with the kernel who thinks he is free
+         to use this area. So, update %sp first before doing anything
+         else.  */
 
       write_register (SP_REGNUM, sp);
 
-      /* if the last argument copied into the registers didn't fit there 
-         completely, push the rest of it into stack. */
+      /* If the last argument copied into the registers didn't fit there 
+         completely, push the rest of it into stack.  */
 
       if (argbytes)
        {
@@ -1075,7 +1218,7 @@ ran_out_of_registers_for_arguments:
          ii += ((len - argbytes + 3) & -4) / 4;
        }
 
-      /* push the rest of the arguments into stack. */
+      /* Push the rest of the arguments into stack.  */
       for (; argno < nargs; ++argno)
        {
 
@@ -1084,7 +1227,8 @@ ran_out_of_registers_for_arguments:
          len = TYPE_LENGTH (type);
 
 
-         /* float types should be passed in fpr's, as well as in the stack. */
+         /* Float types should be passed in fpr's, as well as in the
+             stack.  */
          if (TYPE_CODE (type) == TYPE_CODE_FLT && f_argno < 13)
            {
 
@@ -1092,7 +1236,7 @@ ran_out_of_registers_for_arguments:
                printf_unfiltered (
                                    "Fatal Error: a floating point parameter #%d with a size > 8 is found!\n", argno);
 
-             memcpy (&registers[REGISTER_BYTE (FP0_REGNUM + 1 + f_argno)],
+             memcpy (&deprecated_registers[REGISTER_BYTE (FP0_REGNUM + 1 + f_argno)],
                      VALUE_CONTENTS (arg),
                      len);
              ++f_argno;
@@ -1103,19 +1247,9 @@ ran_out_of_registers_for_arguments:
        }
     }
   else
-    /* Secure stack areas first, before doing anything else. */
+    /* Secure stack areas first, before doing anything else.  */
     write_register (SP_REGNUM, sp);
 
-  if (!USE_GENERIC_DUMMY_FRAMES)
-    {
-      /* we want to copy 24 bytes of target's frame to dummy's frame,
-         then set back chain to point to new frame. */
-
-      saved_sp = dummy_frame_addr[dummy_frame_count - 1];
-      read_memory (saved_sp, tmp_buffer, 24);
-      write_memory (sp, tmp_buffer, 24);
-    }
-
   /* set back chain properly */
   store_address (tmp_buffer, 4, saved_sp);
   write_memory (sp, tmp_buffer, 4);
@@ -1123,32 +1257,82 @@ ran_out_of_registers_for_arguments:
   target_store_registers (-1);
   return sp;
 }
-/* #ifdef ELF_OBJECT_FORMAT */
 
 /* Function: ppc_push_return_address (pc, sp)
-   Set up the return address for the inferior function call. */
+   Set up the return address for the inferior function call.  */
 
-CORE_ADDR
-ppc_push_return_address (pc, sp)
-     CORE_ADDR pc;
-     CORE_ADDR sp;
+static CORE_ADDR
+ppc_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
 {
-  write_register (LR_REGNUM, CALL_DUMMY_ADDRESS ());
+  write_register (gdbarch_tdep (current_gdbarch)->ppc_lr_regnum,
+                 CALL_DUMMY_ADDRESS ());
   return sp;
 }
 
-/* #endif */
+/* Extract a function return value of type TYPE from raw register array
+   REGBUF, and copy that return value into VALBUF in virtual format.  */
+static void
+e500_extract_return_value (struct type *valtype, struct regcache *regbuf, void *valbuf)
+{
+  int offset = 0;
+  int vallen = TYPE_LENGTH (valtype);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
 
-/* a given return value in `regbuf' with a type `valtype', extract and copy its
-   value into `valbuf' */
+  if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
+      && vallen == 8
+      && TYPE_VECTOR (valtype))
+    {
+      regcache_raw_read (regbuf, tdep->ppc_ev0_regnum + 3, valbuf);
+    }
+  else
+    {
+      /* Return value is copied starting from r3.  Note that r3 for us
+         is a pseudo register.  */
+      int offset = 0;
+      int return_regnum = tdep->ppc_gp0_regnum + 3;
+      int reg_size = REGISTER_RAW_SIZE (return_regnum);
+      int reg_part_size;
+      char *val_buffer;
+      int copied = 0;
+      int i = 0;
+
+      /* Compute where we will start storing the value from.  */ 
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+        {
+         if (vallen <= reg_size)
+           offset = reg_size - vallen;
+         else
+           offset = reg_size + (reg_size - vallen);
+        }
+
+      /* How big does the local buffer need to be?  */
+      if (vallen <= reg_size)
+       val_buffer = alloca (reg_size);
+      else
+       val_buffer = alloca (vallen);
+
+      /* Read all we need into our private buffer.  We copy it in
+         chunks that are as long as one register, never shorter, even
+         if the value is smaller than the register.  */
+      while (copied < vallen)
+        {
+          reg_part_size = REGISTER_RAW_SIZE (return_regnum + i);
+         /* It is a pseudo/cooked register.  */
+          regcache_cooked_read (regbuf, return_regnum + i,
+                               val_buffer + copied);
+          copied += reg_part_size;
+          i++;
+        }
+      /* Put the stuff in the return buffer.  */
+      memcpy (valbuf, val_buffer + offset, vallen);
+    }
+}
 
-void
-extract_return_value (valtype, regbuf, valbuf)
-     struct type *valtype;
-     char regbuf[REGISTER_BYTES];
-     char *valbuf;
+static void
+rs6000_extract_return_value (struct type *valtype, char *regbuf, char *valbuf)
 {
   int offset = 0;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
 
   if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
     {
@@ -1157,7 +1341,7 @@ extract_return_value (valtype, regbuf, valbuf)
       float ff;
       /* floats and doubles are returned in fpr1. fpr's have a size of 8 bytes.
          We need to truncate the return value into float size (4 byte) if
-         necessary. */
+         necessary.  */
 
       if (TYPE_LENGTH (valtype) > 4)   /* this is a double */
        memcpy (valbuf,
@@ -1170,10 +1354,17 @@ extract_return_value (valtype, regbuf, valbuf)
          memcpy (valbuf, &ff, sizeof (float));
        }
     }
+  else if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
+           && TYPE_LENGTH (valtype) == 16
+           && TYPE_VECTOR (valtype))
+    {
+      memcpy (valbuf, regbuf + REGISTER_BYTE (tdep->ppc_vr0_regnum + 2),
+             TYPE_LENGTH (valtype));
+    }
   else
     {
       /* return value is copied starting from r3. */
-      if (TARGET_BYTE_ORDER == BIG_ENDIAN
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
          && TYPE_LENGTH (valtype) < REGISTER_RAW_SIZE (3))
        offset = REGISTER_RAW_SIZE (3) - TYPE_LENGTH (valtype);
 
@@ -1183,29 +1374,55 @@ extract_return_value (valtype, regbuf, valbuf)
     }
 }
 
+/* Return whether handle_inferior_event() should proceed through code
+   starting at PC in function NAME when stepping.
+
+   The AIX -bbigtoc linker option generates functions @FIX0, @FIX1, etc. to
+   handle memory references that are too distant to fit in instructions
+   generated by the compiler.  For example, if 'foo' in the following
+   instruction:
+
+     lwz r9,foo(r2)
+
+   is greater than 32767, the linker might replace the lwz with a branch to
+   somewhere in @FIX1 that does the load in 2 instructions and then branches
+   back to where execution should continue.
 
-/* keep structure return address in this variable.
-   FIXME:  This is a horrid kludge which should not be allowed to continue
-   living.  This only allows a single nested call to a structure-returning
-   function.  Come on, guys!  -- gnu@cygnus.com, Aug 92  */
+   GDB should silently step over @FIX code, just like AIX dbx does.
+   Unfortunately, the linker uses the "b" instruction for the branches,
+   meaning that the link register doesn't get set.  Therefore, GDB's usual
+   step_over_function() mechanism won't work.
+
+   Instead, use the IN_SOLIB_RETURN_TRAMPOLINE and SKIP_TRAMPOLINE_CODE hooks
+   in handle_inferior_event() to skip past @FIX code.  */
+
+int
+rs6000_in_solib_return_trampoline (CORE_ADDR pc, char *name)
+{
+  return name && !strncmp (name, "@FIX", 4);
+}
 
-CORE_ADDR rs6000_struct_return_address;
+/* Skip code that the user doesn't want to see when stepping:
 
+   1. Indirect function calls use a piece of trampoline code to do context
+   switching, i.e. to set the new TOC table.  Skip such code if we are on
+   its first instruction (as when we have single-stepped to here).
 
-/* Indirect function calls use a piece of trampoline code to do context
-   switching, i.e. to set the new TOC table. Skip such code if we are on
-   its first instruction (as when we have single-stepped to here). 
-   Also skip shared library trampoline code (which is different from
+   2. Skip shared library trampoline code (which is different from
    indirect function call trampolines).
+
+   3. Skip bigtoc fixup code.
+
    Result is desired PC to step until, or NULL if we are not in
-   trampoline code.  */
+   code that should be skipped.  */
 
 CORE_ADDR
-skip_trampoline_code (pc)
-     CORE_ADDR pc;
+rs6000_skip_trampoline_code (CORE_ADDR pc)
 {
   register unsigned int ii, op;
+  int rel;
   CORE_ADDR solib_target_pc;
+  struct minimal_symbol *msymbol;
 
   static unsigned trampoline_code[] =
   {
@@ -1219,6 +1436,21 @@ skip_trampoline_code (pc)
     0
   };
 
+  /* Check for bigtoc fixup code.  */
+  msymbol = lookup_minimal_symbol_by_pc (pc);
+  if (msymbol && rs6000_in_solib_return_trampoline (pc, SYMBOL_NAME (msymbol)))
+    {
+      /* Double-check that the third instruction from PC is relative "b".  */
+      op = read_memory_integer (pc + 8, 4);
+      if ((op & 0xfc000003) == 0x48000000)
+       {
+         /* Extract bits 6-29 as a signed 24-bit relative word address and
+            add it to the containing PC.  */
+         rel = ((int)(op << 6) >> 6);
+         return pc + 8 + rel;
+       }
+    }
+
   /* If pc is in a shared library trampoline, return its target.  */
   solib_target_pc = find_solib_trampoline_target (pc);
   if (solib_target_pc)
@@ -1231,7 +1463,7 @@ skip_trampoline_code (pc)
        return 0;
     }
   ii = read_register (11);     /* r11 holds destination addr   */
-  pc = read_memory_integer (ii, 4);    /* (r11) value                  */
+  pc = read_memory_addr (ii, gdbarch_tdep (current_gdbarch)->wordsize); /* (r11) value */
   return pc;
 }
 
@@ -1245,19 +1477,19 @@ rs6000_frameless_function_invocation (struct frame_info *fi)
 
   /* Don't even think about framelessness except on the innermost frame
      or if the function was interrupted by a signal.  */
-  if (fi->next != NULL && !fi->next->signal_handler_caller)
+  if (fi->next != NULL && !(get_frame_type (fi->next) == SIGTRAMP_FRAME))
     return 0;
 
   func_start = get_pc_function_start (fi->pc);
 
   /* If we failed to find the start of the function, it is a mistake
-     to inspect the instructions. */
+     to inspect the instructions.  */
 
   if (!func_start)
     {
       /* A frame with a zero PC is usually created by dereferencing a NULL
          function pointer, normally causing an immediate core dump of the
-         inferior. Mark function as frameless, as the inferior has no chance
+         inferior.  Mark function as frameless, as the inferior has no chance
          of setting up a stack frame.  */
       if (fi->pc == 0)
        return 1;
@@ -1265,48 +1497,59 @@ rs6000_frameless_function_invocation (struct frame_info *fi)
        return 0;
     }
 
-  (void) skip_prologue (func_start, &fdata);
+  (void) skip_prologue (func_start, fi->pc, &fdata);
   return fdata.frameless;
 }
 
-/* Return the PC saved in a frame */
+/* Return the PC saved in a frame */
 
-unsigned long
+CORE_ADDR
 rs6000_frame_saved_pc (struct frame_info *fi)
 {
   CORE_ADDR func_start;
   struct rs6000_framedata fdata;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  int wordsize = tdep->wordsize;
 
-  if (fi->signal_handler_caller)
-    return read_memory_integer (fi->frame + SIG_FRAME_PC_OFFSET, 4);
+  if ((get_frame_type (fi) == SIGTRAMP_FRAME))
+    return read_memory_addr (fi->frame + SIG_FRAME_PC_OFFSET, wordsize);
 
-  if (USE_GENERIC_DUMMY_FRAMES)
-    {
-      if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
-       return generic_read_register_dummy (fi->pc, fi->frame, PC_REGNUM);
-    }
+  if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+    return deprecated_read_register_dummy (fi->pc, fi->frame, PC_REGNUM);
 
   func_start = get_pc_function_start (fi->pc);
 
   /* If we failed to find the start of the function, it is a mistake
-     to inspect the instructions. */
+     to inspect the instructions.  */
   if (!func_start)
     return 0;
 
-  (void) skip_prologue (func_start, &fdata);
+  (void) skip_prologue (func_start, fi->pc, &fdata);
 
   if (fdata.lr_offset == 0 && fi->next != NULL)
     {
-      if (fi->next->signal_handler_caller)
-       return read_memory_integer (fi->next->frame + SIG_FRAME_LR_OFFSET, 4);
+      if ((get_frame_type (fi->next) == SIGTRAMP_FRAME))
+       return read_memory_addr (fi->next->frame + SIG_FRAME_LR_OFFSET,
+                                wordsize);
+      else if (PC_IN_CALL_DUMMY (get_next_frame (fi)->pc, 0, 0))
+       /* The link register wasn't saved by this frame and the next
+           (inner, newer) frame is a dummy.  Get the link register
+           value by unwinding it from that [dummy] frame.  */
+       {
+         ULONGEST lr;
+         frame_unwind_unsigned_register (get_next_frame (fi),
+                                         tdep->ppc_lr_regnum, &lr);
+         return lr;
+       }
       else
-       return read_memory_integer (FRAME_CHAIN (fi) + DEFAULT_LR_SAVE, 4);
+       return read_memory_addr (FRAME_CHAIN (fi) + tdep->lr_frame_offset,
+                                wordsize);
     }
 
   if (fdata.lr_offset == 0)
-    return read_register (LR_REGNUM);
+    return read_register (gdbarch_tdep (current_gdbarch)->ppc_lr_regnum);
 
-  return read_memory_integer (FRAME_CHAIN (fi) + fdata.lr_offset, 4);
+  return read_memory_addr (FRAME_CHAIN (fi) + fdata.lr_offset, wordsize);
 }
 
 /* If saved registers of frame FI are not known yet, read and cache them.
@@ -1314,12 +1557,12 @@ rs6000_frame_saved_pc (struct frame_info *fi)
    in which case the framedata are read.  */
 
 static void
-frame_get_saved_regs (fi, fdatap)
-     struct frame_info *fi;
-     struct rs6000_framedata *fdatap;
+frame_get_saved_regs (struct frame_info *fi, struct rs6000_framedata *fdatap)
 {
   CORE_ADDR frame_addr;
   struct rs6000_framedata work_fdata;
+  struct gdbarch_tdep * tdep = gdbarch_tdep (current_gdbarch);
+  int wordsize = tdep->wordsize;
 
   if (fi->saved_regs)
     return;
@@ -1327,23 +1570,32 @@ frame_get_saved_regs (fi, fdatap)
   if (fdatap == NULL)
     {
       fdatap = &work_fdata;
-      (void) skip_prologue (get_pc_function_start (fi->pc), fdatap);
+      (void) skip_prologue (get_pc_function_start (fi->pc), fi->pc, fdatap);
     }
 
   frame_saved_regs_zalloc (fi);
 
   /* If there were any saved registers, figure out parent's stack
-     pointer. */
+     pointer.  */
   /* The following is true only if the frame doesn't have a call to
-     alloca(), FIXME. */
-
-  if (fdatap->saved_fpr == 0 && fdatap->saved_gpr == 0
-      && fdatap->lr_offset == 0 && fdatap->cr_offset == 0)
+     alloca(), FIXME.  */
+
+  if (fdatap->saved_fpr == 0
+      && fdatap->saved_gpr == 0
+      && fdatap->saved_vr == 0
+      && fdatap->saved_ev == 0
+      && fdatap->lr_offset == 0
+      && fdatap->cr_offset == 0
+      && fdatap->vr_offset == 0
+      && fdatap->ev_offset == 0)
     frame_addr = 0;
-  else if (fi->prev && fi->prev->frame)
-    frame_addr = fi->prev->frame;
   else
-    frame_addr = read_memory_integer (fi->frame, 4);
+    /* NOTE: cagney/2002-04-14: The ->frame points to the inner-most
+       address of the current frame.  Things might be easier if the
+       ->frame pointed to the outer-most address of the frame.  In the
+       mean time, the address of the prev frame is used as the base
+       address of this frame.  */
+    frame_addr = FRAME_CHAIN (fi);
 
   /* if != -1, fdatap->saved_fpr is the smallest number of saved_fpr.
      All fpr's from saved_fpr to fp31 are saved.  */
@@ -1351,11 +1603,11 @@ frame_get_saved_regs (fi, fdatap)
   if (fdatap->saved_fpr >= 0)
     {
       int i;
-      int fpr_offset = frame_addr + fdatap->fpr_offset;
+      CORE_ADDR fpr_addr = frame_addr + fdatap->fpr_offset;
       for (i = fdatap->saved_fpr; i < 32; i++)
        {
-         fi->saved_regs[FP0_REGNUM + i] = fpr_offset;
-         fpr_offset += 8;
+         fi->saved_regs[FP0_REGNUM + i] = fpr_addr;
+         fpr_addr += 8;
        }
     }
 
@@ -1365,54 +1617,92 @@ frame_get_saved_regs (fi, fdatap)
   if (fdatap->saved_gpr >= 0)
     {
       int i;
-      int gpr_offset = frame_addr + fdatap->gpr_offset;
+      CORE_ADDR gpr_addr = frame_addr + fdatap->gpr_offset;
       for (i = fdatap->saved_gpr; i < 32; i++)
        {
-         fi->saved_regs[i] = gpr_offset;
-         gpr_offset += 4;
+         fi->saved_regs[i] = gpr_addr;
+         gpr_addr += wordsize;
+       }
+    }
+
+  /* if != -1, fdatap->saved_vr is the smallest number of saved_vr.
+     All vr's from saved_vr to vr31 are saved.  */
+  if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
+    {
+      if (fdatap->saved_vr >= 0)
+       {
+         int i;
+         CORE_ADDR vr_addr = frame_addr + fdatap->vr_offset;
+         for (i = fdatap->saved_vr; i < 32; i++)
+           {
+             fi->saved_regs[tdep->ppc_vr0_regnum + i] = vr_addr;
+             vr_addr += REGISTER_RAW_SIZE (tdep->ppc_vr0_regnum);
+           }
+       }
+    }
+
+  /* if != -1, fdatap->saved_ev is the smallest number of saved_ev.
+       All vr's from saved_ev to ev31 are saved. ????? */
+  if (tdep->ppc_ev0_regnum != -1 && tdep->ppc_ev31_regnum != -1)
+    {
+      if (fdatap->saved_ev >= 0)
+       {
+         int i;
+         CORE_ADDR ev_addr = frame_addr + fdatap->ev_offset;
+         for (i = fdatap->saved_ev; i < 32; i++)
+           {
+             fi->saved_regs[tdep->ppc_ev0_regnum + i] = ev_addr;
+              fi->saved_regs[tdep->ppc_gp0_regnum + i] = ev_addr + 4;
+             ev_addr += REGISTER_RAW_SIZE (tdep->ppc_ev0_regnum);
+            }
        }
     }
 
   /* If != 0, fdatap->cr_offset is the offset from the frame that holds
      the CR.  */
   if (fdatap->cr_offset != 0)
-    fi->saved_regs[CR_REGNUM] = frame_addr + fdatap->cr_offset;
+    fi->saved_regs[tdep->ppc_cr_regnum] = frame_addr + fdatap->cr_offset;
 
   /* If != 0, fdatap->lr_offset is the offset from the frame that holds
      the LR.  */
   if (fdatap->lr_offset != 0)
-    fi->saved_regs[LR_REGNUM] = frame_addr + fdatap->lr_offset;
+    fi->saved_regs[tdep->ppc_lr_regnum] = frame_addr + fdatap->lr_offset;
+
+  /* If != 0, fdatap->vrsave_offset is the offset from the frame that holds
+     the VRSAVE.  */
+  if (fdatap->vrsave_offset != 0)
+    fi->saved_regs[tdep->ppc_vrsave_regnum] = frame_addr + fdatap->vrsave_offset;
 }
 
 /* Return the address of a frame. This is the inital %sp value when the frame
-   was first allocated. For functions calling alloca(), it might be saved in
-   an alloca register. */
+   was first allocated.  For functions calling alloca(), it might be saved in
+   an alloca register.  */
 
 static CORE_ADDR
-frame_initial_stack_address (fi)
-     struct frame_info *fi;
+frame_initial_stack_address (struct frame_info *fi)
 {
   CORE_ADDR tmpaddr;
   struct rs6000_framedata fdata;
   struct frame_info *callee_fi;
 
-  /* if the initial stack pointer (frame address) of this frame is known,
-     just return it. */
+  /* If the initial stack pointer (frame address) of this frame is known,
+     just return it.  */
 
   if (fi->extra_info->initial_sp)
     return fi->extra_info->initial_sp;
 
-  /* find out if this function is using an alloca register.. */
+  /* Find out if this function is using an alloca register.  */
 
-  (void) skip_prologue (get_pc_function_start (fi->pc), &fdata);
+  (void) skip_prologue (get_pc_function_start (fi->pc), fi->pc, &fdata);
 
-  /* if saved registers of this frame are not known yet, read and cache them. */
+  /* If saved registers of this frame are not known yet, read and
+     cache them.  */
 
   if (!fi->saved_regs)
     frame_get_saved_regs (fi, &fdata);
 
   /* If no alloca register used, then fi->frame is the value of the %sp for
-     this frame, and it is good enough. */
+     this frame, and it is good enough.  */
 
   if (fdata.alloca_reg < 0)
     {
@@ -1420,119 +1710,422 @@ frame_initial_stack_address (fi)
       return fi->extra_info->initial_sp;
     }
 
-  /* This function has an alloca register. If this is the top-most frame
-     (with the lowest address), the value in alloca register is good. */
+  /* There is an alloca register, use its value, in the current frame,
+     as the initial stack pointer.  */
+  {
+    char *tmpbuf = alloca (MAX_REGISTER_RAW_SIZE);
+    if (frame_register_read (fi, fdata.alloca_reg, tmpbuf))
+      {
+       fi->extra_info->initial_sp
+         = extract_unsigned_integer (tmpbuf,
+                                     REGISTER_RAW_SIZE (fdata.alloca_reg));
+      }
+    else
+      /* NOTE: cagney/2002-04-17: At present the only time
+         frame_register_read will fail is when the register isn't
+         available.  If that does happen, use the frame.  */
+      fi->extra_info->initial_sp = fi->frame;
+  }
+  return fi->extra_info->initial_sp;
+}
+
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
 
-  if (!fi->next)
-    return fi->extra_info->initial_sp = read_register (fdata.alloca_reg);
+/* FRAME_CHAIN takes a frame's nominal address
+   and produces the frame's chain-pointer.  */
 
-  /* Otherwise, this is a caller frame. Callee has usually already saved
-     registers, but there are exceptions (such as when the callee
-     has no parameters). Find the address in which caller's alloca
-     register is saved. */
+/* In the case of the RS/6000, the frame's nominal address
+   is the address of a 4-byte word containing the calling frame's address.  */
 
-  for (callee_fi = fi->next; callee_fi; callee_fi = callee_fi->next)
-    {
+CORE_ADDR
+rs6000_frame_chain (struct frame_info *thisframe)
+{
+  CORE_ADDR fp, fpp, lr;
+  int wordsize = gdbarch_tdep (current_gdbarch)->wordsize;
+
+  if (PC_IN_CALL_DUMMY (thisframe->pc, thisframe->frame, thisframe->frame))
+    /* A dummy frame always correctly chains back to the previous
+       frame.  */
+    return read_memory_addr ((thisframe)->frame, wordsize);
+
+  if (inside_entry_file (thisframe->pc) ||
+      thisframe->pc == entry_point_address ())
+    return 0;
+
+  if ((get_frame_type (thisframe) == SIGTRAMP_FRAME))
+    fp = read_memory_addr (thisframe->frame + SIG_FRAME_FP_OFFSET,
+                             wordsize);
+  else if (thisframe->next != NULL
+          && (get_frame_type (thisframe->next) == SIGTRAMP_FRAME)
+          && FRAMELESS_FUNCTION_INVOCATION (thisframe))
+    /* A frameless function interrupted by a signal did not change the
+       frame pointer.  */
+    fp = FRAME_FP (thisframe);
+  else
+    fp = read_memory_addr ((thisframe)->frame, wordsize);
+  return fp;
+}
+
+/* Return the size of register REG when words are WORDSIZE bytes long.  If REG
+   isn't available with that word size, return 0.  */
+
+static int
+regsize (const struct reg *reg, int wordsize)
+{
+  return wordsize == 8 ? reg->sz64 : reg->sz32;
+}
+
+/* Return the name of register number N, or null if no such register exists
+   in the current architecture.  */
+
+static const char *
+rs6000_register_name (int n)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  const struct reg *reg = tdep->regs + n;
+
+  if (!regsize (reg, tdep->wordsize))
+    return NULL;
+  return reg->name;
+}
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
 
-      if (!callee_fi->saved_regs)
-       frame_get_saved_regs (callee_fi, NULL);
+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);
+}
 
-      /* this is the address in which alloca register is saved. */
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
 
-      tmpaddr = callee_fi->saved_regs[fdata.alloca_reg];
-      if (tmpaddr)
+static struct type *
+rs6000_register_virtual_type (int n)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  const struct reg *reg = tdep->regs + n;
+
+  if (reg->fpr)
+    return builtin_type_double;
+  else
+    {
+      int size = regsize (reg, tdep->wordsize);
+      switch (size)
        {
-         fi->extra_info->initial_sp = read_memory_integer (tmpaddr, 4);
-         return fi->extra_info->initial_sp;
+       case 8:
+         if (tdep->ppc_ev0_regnum <= n && n <= tdep->ppc_ev31_regnum)
+           return builtin_type_vec64;
+         else
+           return builtin_type_int64;
+         break;
+       case 16:
+         return builtin_type_vec128;
+         break;
+       default:
+         return builtin_type_int32;
+         break;
        }
-
-      /* Go look into deeper levels of the frame chain to see if any one of
-         the callees has saved alloca register. */
     }
+}
 
-  /* If alloca register was not saved, by the callee (or any of its callees)
-     then the value in the register is still good. */
+/* For the PowerPC, it appears that the debug info marks float parameters as
+   floats regardless of whether the function is prototyped, but the actual
+   values are always passed in as doubles.  Tell gdb to always assume that
+   floats are passed as doubles and then converted in the callee.  */
 
-  fi->extra_info->initial_sp = read_register (fdata.alloca_reg);
-  return fi->extra_info->initial_sp;
+static int
+rs6000_coerce_float_to_double (struct type *formal, struct type *actual)
+{
+  return 1;
 }
 
-CORE_ADDR
-rs6000_frame_chain (thisframe)
-     struct frame_info *thisframe;
+/* 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
+   double, we need a conversion if the memory format is float.  */
+
+static int
+rs6000_register_convertible (int n)
 {
-  CORE_ADDR fp;
+  const struct reg *reg = gdbarch_tdep (current_gdbarch)->regs + n;
+  return reg->fpr;
+}
+
+/* Convert data from raw format for register N in buffer FROM
+   to virtual format with type TYPE in buffer TO.  */
 
-  if (USE_GENERIC_DUMMY_FRAMES)
+static void
+rs6000_register_convert_to_virtual (int n, struct type *type,
+                                   char *from, char *to)
+{
+  if (TYPE_LENGTH (type) != REGISTER_RAW_SIZE (n))
     {
-      if (PC_IN_CALL_DUMMY (thisframe->pc, thisframe->frame, thisframe->frame))
-       return thisframe->frame;        /* dummy frame same as caller's frame */
+      double val = extract_floating (from, REGISTER_RAW_SIZE (n));
+      store_floating (to, TYPE_LENGTH (type), val);
     }
+  else
+    memcpy (to, from, REGISTER_RAW_SIZE (n));
+}
 
-  if (inside_entry_file (thisframe->pc) ||
-      thisframe->pc == entry_point_address ())
-    return 0;
+/* Convert data from virtual format with type TYPE in buffer FROM
+   to raw format for register N in buffer TO.  */
 
-  if (thisframe->signal_handler_caller)
-    fp = read_memory_integer (thisframe->frame + SIG_FRAME_FP_OFFSET, 4);
-  else if (thisframe->next != NULL
-          && thisframe->next->signal_handler_caller
-          && FRAMELESS_FUNCTION_INVOCATION (thisframe))
-    /* A frameless function interrupted by a signal did not change the
-       frame pointer.  */
-    fp = FRAME_FP (thisframe);
+static void
+rs6000_register_convert_to_raw (struct type *type, int n,
+                               char *from, char *to)
+{
+  if (TYPE_LENGTH (type) != REGISTER_RAW_SIZE (n))
+    {
+      double val = extract_floating (from, TYPE_LENGTH (type));
+      store_floating (to, REGISTER_RAW_SIZE (n), val);
+    }
   else
-    fp = read_memory_integer ((thisframe)->frame, 4);
+    memcpy (to, from, REGISTER_RAW_SIZE (n));
+}
+
+static void
+e500_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+                          int reg_nr, void *buffer)
+{
+  int base_regnum;
+  int offset = 0;
+  char *temp_buffer = (char*) alloca (MAX_REGISTER_RAW_SIZE);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 
 
-  if (USE_GENERIC_DUMMY_FRAMES)
+  if (reg_nr >= tdep->ppc_gp0_regnum 
+      && reg_nr <= tdep->ppc_gplast_regnum)
     {
-      CORE_ADDR fpp, lr;
+      base_regnum = reg_nr - tdep->ppc_gp0_regnum + tdep->ppc_ev0_regnum;
+
+      /* Build the value in the provided buffer.  */ 
+      /* Read the raw register of which this one is the lower portion.  */
+      regcache_raw_read (regcache, base_regnum, temp_buffer);
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+       offset = 4;
+      memcpy ((char *) buffer, temp_buffer + offset, 4);
+    }
+}
+
+static void
+e500_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+                           int reg_nr, const void *buffer)
+{
+  int base_regnum;
+  int offset = 0;
+  char *temp_buffer = (char*) alloca (MAX_REGISTER_RAW_SIZE);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 
 
-      lr = read_register (LR_REGNUM);
-      if (lr == entry_point_address ())
-       if (fp != 0 && (fpp = read_memory_integer (fp, 4)) != 0)
-         if (PC_IN_CALL_DUMMY (lr, fpp, fpp))
-           return fpp;
+  if (reg_nr >= tdep->ppc_gp0_regnum 
+      && reg_nr <= tdep->ppc_gplast_regnum)
+    {
+      base_regnum = reg_nr - tdep->ppc_gp0_regnum + tdep->ppc_ev0_regnum;
+      /* reg_nr is 32 bit here, and base_regnum is 64 bits.  */
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+       offset = 4;
+
+      /* Let's read the value of the base register into a temporary
+        buffer, so that overwriting the last four bytes with the new
+        value of the pseudo will leave the upper 4 bytes unchanged.  */
+      regcache_raw_read (regcache, base_regnum, temp_buffer);
+
+      /* Write as an 8 byte quantity.  */
+      memcpy (temp_buffer + offset, (char *) buffer, 4);
+      regcache_raw_write (regcache, base_regnum, temp_buffer);
     }
+}
 
-  return fp;
+/* Convert a dwarf2 register number to a gdb REGNUM.  */
+static int
+e500_dwarf2_reg_to_regnum (int num)
+{
+  int regnum;
+  if (0 <= num && num <= 31)
+    return num + gdbarch_tdep (current_gdbarch)->ppc_gp0_regnum;
+  else 
+    return num;
+}
+
+/* Convert a dbx stab register number (from `r' declaration) to a gdb
+   REGNUM.  */
+static int
+rs6000_stab_reg_to_regnum (int num)
+{
+  int regnum;
+  switch (num)
+    {
+    case 64: 
+      regnum = gdbarch_tdep (current_gdbarch)->ppc_mq_regnum;
+      break;
+    case 65: 
+      regnum = gdbarch_tdep (current_gdbarch)->ppc_lr_regnum;
+      break;
+    case 66: 
+      regnum = gdbarch_tdep (current_gdbarch)->ppc_ctr_regnum;
+      break;
+    case 76: 
+      regnum = gdbarch_tdep (current_gdbarch)->ppc_xer_regnum;
+      break;
+    default: 
+      regnum = num;
+      break;
+    }
+  return regnum;
+}
+
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  */
+
+static void
+rs6000_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  write_register (tdep->ppc_gp0_regnum + 3, addr);
+}
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  */
+static void
+e500_store_return_value (struct type *type, char *valbuf)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+  /* Everything is returned in GPR3 and up.  */
+  int copied = 0;
+  int i = 0;
+  int len = TYPE_LENGTH (type);
+  while (copied < len)
+    {
+      int regnum = gdbarch_tdep (current_gdbarch)->ppc_gp0_regnum + 3 + i;
+      int reg_size = REGISTER_RAW_SIZE (regnum);
+      char *reg_val_buf = alloca (reg_size);
+
+      memcpy (reg_val_buf, valbuf + copied, reg_size);
+      copied += reg_size;
+      deprecated_write_register_gen (regnum, reg_val_buf);
+      i++;
+    }
+}
+
+static void
+rs6000_store_return_value (struct type *type, char *valbuf)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_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 (REGISTER_BYTE (FP0_REGNUM + 1), valbuf,
+                                    TYPE_LENGTH (type));
+  else if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
+    {
+      if (TYPE_LENGTH (type) == 16
+          && TYPE_VECTOR (type))
+       deprecated_write_register_bytes (REGISTER_BYTE (tdep->ppc_vr0_regnum + 2),
+                                        valbuf, TYPE_LENGTH (type));
+    }
+  else
+    /* Everything else is returned in GPR3 and up.  */
+    deprecated_write_register_bytes (REGISTER_BYTE (gdbarch_tdep (current_gdbarch)->ppc_gp0_regnum + 3),
+                                    valbuf, TYPE_LENGTH (type));
+}
+
+/* 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).  */
+
+static CORE_ADDR
+rs6000_extract_struct_value_address (struct regcache *regcache)
+{
+  /* FIXME: cagney/2002-09-26: PR gdb/724: When making an inferior
+     function call GDB knows the address of the struct return value
+     and hence, should not need to call this function.  Unfortunately,
+     the current hand_function_call() code only saves the most recent
+     struct address leading to occasional calls.  The code should
+     instead maintain a stack of such addresses (in the dummy frame
+     object).  */
+  /* NOTE: cagney/2002-09-26: Return 0 which indicates that we've
+     really got no idea where the return value is being stored.  While
+     r3, on function entry, contained the address it will have since
+     been reused (scratch) and hence wouldn't be valid */
+  return 0;
+}
+
+/* Return whether PC is in a dummy function call.
+
+   FIXME: This just checks for the end of the stack, which is broken
+   for things like stepping through gcc nested function stubs.  */
+
+static int
+rs6000_pc_in_call_dummy (CORE_ADDR pc, CORE_ADDR sp, CORE_ADDR fp)
+{
+  return sp < pc && pc < fp;
+}
+
+/* Hook called when a new child process is started.  */
+
+void
+rs6000_create_inferior (int pid)
+{
+  if (rs6000_set_host_arch_hook)
+    rs6000_set_host_arch_hook (pid);
 }
 \f
-/* Return nonzero if ADDR (a function pointer) is in the data space and
-   is therefore a special function pointer.  */
+/* Support for CONVERT_FROM_FUNC_PTR_ADDR(ADDR).
+
+   Usually a function pointer's representation is simply the address
+   of the function. On the RS/6000 however, a function pointer is
+   represented by a pointer to a TOC entry. This TOC entry contains
+   three words, the first word is the address of the function, the
+   second word is the TOC pointer (r2), and the third word is the
+   static chain value.  Throughout GDB it is currently assumed that a
+   function pointer contains the address of the function, which is not
+   easy to fix.  In addition, the conversion of a function address to
+   a function pointer would require allocation of a TOC entry in the
+   inferior's memory space, with all its drawbacks.  To be able to
+   call C++ virtual methods in the inferior (which are called via
+   function pointers), find_function_addr uses this function to get the
+   function address from a function pointer.  */
+
+/* Return real function address if ADDR (a function pointer) is in the data
+   space and is therefore a special function pointer.  */
 
-int
-is_magic_function_pointer (addr)
-     CORE_ADDR addr;
+CORE_ADDR
+rs6000_convert_from_func_ptr_addr (CORE_ADDR addr)
 {
   struct obj_section *s;
 
   s = find_pc_section (addr);
   if (s && s->the_bfd_section->flags & SEC_CODE)
-    return 0;
-  else
-    return 1;
-}
+    return addr;
 
-#ifdef GDB_TARGET_POWERPC
-int
-gdb_print_insn_powerpc (memaddr, info)
-     bfd_vma memaddr;
-     disassemble_info *info;
-{
-  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
-    return print_insn_big_powerpc (memaddr, info);
-  else
-    return print_insn_little_powerpc (memaddr, info);
+  /* ADDR is in the data space, so it's a special function pointer. */
+  return read_memory_addr (addr, gdbarch_tdep (current_gdbarch)->wordsize);
 }
-#endif
 \f
 
-/* Handling the various PowerPC/RS6000 variants.  */
+/* Handling the various POWER/PowerPC variants.  */
 
 
-/* The arrays here called register_names_MUMBLE hold names that 
-   the rs6000_register_name function returns.
+/* The arrays here called registers_MUMBLE hold information about available
+   registers.
 
    For each family of PPC variants, I've tried to isolate out the
    common registers and put them up front, so that as long as you get
@@ -1549,161 +2142,317 @@ gdb_print_insn_powerpc (memaddr, info)
 
    Most of these register groups aren't anything formal.  I arrived at
    them by looking at the registers that occurred in more than one
-   processor.  */
-
-/* UISA register names common across all architectures, including POWER.  */
-
-#define COMMON_UISA_REG_NAMES \
-  /*  0 */ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",  \
-  /*  8 */ "r8", "r9", "r10","r11","r12","r13","r14","r15", \
-  /* 16 */ "r16","r17","r18","r19","r20","r21","r22","r23", \
-  /* 24 */ "r24","r25","r26","r27","r28","r29","r30","r31", \
-  /* 32 */ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",  \
-  /* 40 */ "f8", "f9", "f10","f11","f12","f13","f14","f15", \
-  /* 48 */ "f16","f17","f18","f19","f20","f21","f22","f23", \
-  /* 56 */ "f24","f25","f26","f27","f28","f29","f30","f31", \
-  /* 64 */ "pc", "ps"
-
-/* UISA-level SPR names for PowerPC.  */
-#define PPC_UISA_SPR_NAMES \
-  /* 66 */ "cr",  "lr", "ctr", "xer", ""
-
-/* Segment register names, for PowerPC.  */
-#define PPC_SEGMENT_REG_NAMES \
-  /* 71 */ "sr0", "sr1", "sr2",  "sr3",  "sr4",  "sr5",  "sr6",  "sr7", \
-  /* 79 */ "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15"
-
-/* OEA SPR names for 32-bit PowerPC implementations.
-   The blank space is for "asr", which is only present on 64-bit
-   implementations.  */
-#define PPC_32_OEA_SPR_NAMES \
-  /*  87 */ "pvr", \
-  /*  88 */ "ibat0u", "ibat0l", "ibat1u", "ibat1l", \
-  /*  92 */ "ibat2u", "ibat2l", "ibat3u", "ibat3l", \
-  /*  96 */ "dbat0u", "dbat0l", "dbat1u", "dbat1l", \
-  /* 100 */ "dbat2u", "dbat2l", "dbat3u", "dbat3l", \
-  /* 104 */ "sdr1", "", "dar", "dsisr", "sprg0", "sprg1", "sprg2", "sprg3",\
-  /* 112 */ "srr0", "srr1", "tbl", "tbu", "dec", "dabr", "ear"
-
-/* For the RS6000, we only cover user-level SPR's.  */
-char *register_names_rs6000[] =
-{
-  COMMON_UISA_REG_NAMES,
-  /* 66 */ "cnd", "lr", "cnt", "xer", "mq"
+   processor.
+   
+   Note: kevinb/2002-04-30: Support for the fpscr register was added
+   during April, 2002.  Slot 70 is being used for PowerPC and slot 71
+   for Power.  For PowerPC, slot 70 was unused and was already in the
+   PPC_UISA_SPRS which is ideally where fpscr should go.  For Power,
+   slot 70 was being used for "mq", so the next available slot (71)
+   was chosen.  It would have been nice to be able to make the
+   register numbers the same across processor cores, but this wasn't
+   possible without either 1) renumbering some registers for some
+   processors or 2) assigning fpscr to a really high slot that's
+   larger than any current register number.  Doing (1) is bad because
+   existing stubs would break.  Doing (2) is undesirable because it
+   would introduce a really large gap between fpscr and the rest of
+   the registers for most processors.  */
+
+/* Convenience macros for populating register arrays.  */
+
+/* Within another macro, convert S to a string.  */
+
+#define STR(s) #s
+
+/* Return a struct reg defining register NAME that's 32 bits on 32-bit systems
+   and 64 bits on 64-bit systems.  */
+#define R(name)                { STR(name), 4, 8, 0, 0 }
+
+/* Return a struct reg defining register NAME that's 32 bits on all
+   systems.  */
+#define R4(name)       { STR(name), 4, 4, 0, 0 }
+
+/* Return a struct reg defining register NAME that's 64 bits on all
+   systems.  */
+#define R8(name)       { STR(name), 8, 8, 0, 0 }
+
+/* Return a struct reg defining register NAME that's 128 bits on all
+   systems.  */
+#define R16(name)       { STR(name), 16, 16, 0, 0 }
+
+/* Return a struct reg defining floating-point register NAME.  */
+#define F(name)                { STR(name), 8, 8, 1, 0 }
+
+/* Return a struct reg defining a pseudo register NAME.  */
+#define P(name)                { STR(name), 4, 8, 0, 1}
+
+/* Return a struct reg defining register NAME that's 32 bits on 32-bit
+   systems and that doesn't exist on 64-bit systems.  */
+#define R32(name)      { STR(name), 4, 0, 0, 0 }
+
+/* Return a struct reg defining register NAME that's 64 bits on 64-bit
+   systems and that doesn't exist on 32-bit systems.  */
+#define R64(name)      { STR(name), 0, 8, 0, 0 }
+
+/* Return a struct reg placeholder for a register that doesn't exist.  */
+#define R0             { 0, 0, 0, 0, 0 }
+
+/* UISA registers common across all architectures, including POWER.  */
+
+#define COMMON_UISA_REGS \
+  /*  0 */ R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7),  \
+  /*  8 */ R(r8), R(r9), R(r10),R(r11),R(r12),R(r13),R(r14),R(r15), \
+  /* 16 */ R(r16),R(r17),R(r18),R(r19),R(r20),R(r21),R(r22),R(r23), \
+  /* 24 */ R(r24),R(r25),R(r26),R(r27),R(r28),R(r29),R(r30),R(r31), \
+  /* 32 */ F(f0), F(f1), F(f2), F(f3), F(f4), F(f5), F(f6), F(f7),  \
+  /* 40 */ F(f8), F(f9), F(f10),F(f11),F(f12),F(f13),F(f14),F(f15), \
+  /* 48 */ F(f16),F(f17),F(f18),F(f19),F(f20),F(f21),F(f22),F(f23), \
+  /* 56 */ F(f24),F(f25),F(f26),F(f27),F(f28),F(f29),F(f30),F(f31), \
+  /* 64 */ R(pc), R(ps)
+
+#define COMMON_UISA_NOFP_REGS \
+  /*  0 */ R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7),  \
+  /*  8 */ R(r8), R(r9), R(r10),R(r11),R(r12),R(r13),R(r14),R(r15), \
+  /* 16 */ R(r16),R(r17),R(r18),R(r19),R(r20),R(r21),R(r22),R(r23), \
+  /* 24 */ R(r24),R(r25),R(r26),R(r27),R(r28),R(r29),R(r30),R(r31), \
+  /* 32 */ R0,    R0,    R0,    R0,    R0,    R0,    R0,    R0,     \
+  /* 40 */ R0,    R0,    R0,    R0,    R0,    R0,    R0,    R0,     \
+  /* 48 */ R0,    R0,    R0,    R0,    R0,    R0,    R0,    R0,     \
+  /* 56 */ R0,    R0,    R0,    R0,    R0,    R0,    R0,    R0,     \
+  /* 64 */ R(pc), R(ps)
+
+/* UISA-level SPRs for PowerPC.  */
+#define PPC_UISA_SPRS \
+  /* 66 */ R4(cr),  R(lr), R(ctr), R4(xer), R4(fpscr)
+
+/* UISA-level SPRs for PowerPC without floating point support.  */
+#define PPC_UISA_NOFP_SPRS \
+  /* 66 */ R4(cr),  R(lr), R(ctr), R4(xer), R0
+
+/* Segment registers, for PowerPC.  */
+#define PPC_SEGMENT_REGS \
+  /* 71 */ R32(sr0),  R32(sr1),  R32(sr2),  R32(sr3),  \
+  /* 75 */ R32(sr4),  R32(sr5),  R32(sr6),  R32(sr7),  \
+  /* 79 */ R32(sr8),  R32(sr9),  R32(sr10), R32(sr11), \
+  /* 83 */ R32(sr12), R32(sr13), R32(sr14), R32(sr15)
+
+/* OEA SPRs for PowerPC.  */
+#define PPC_OEA_SPRS \
+  /*  87 */ R4(pvr), \
+  /*  88 */ R(ibat0u), R(ibat0l), R(ibat1u), R(ibat1l), \
+  /*  92 */ R(ibat2u), R(ibat2l), R(ibat3u), R(ibat3l), \
+  /*  96 */ R(dbat0u), R(dbat0l), R(dbat1u), R(dbat1l), \
+  /* 100 */ R(dbat2u), R(dbat2l), R(dbat3u), R(dbat3l), \
+  /* 104 */ R(sdr1),   R64(asr),  R(dar),    R4(dsisr), \
+  /* 108 */ R(sprg0),  R(sprg1),  R(sprg2),  R(sprg3),  \
+  /* 112 */ R(srr0),   R(srr1),   R(tbl),    R(tbu),    \
+  /* 116 */ R4(dec),   R(dabr),   R4(ear)
+
+/* AltiVec registers.  */
+#define PPC_ALTIVEC_REGS \
+  /*119*/R16(vr0), R16(vr1), R16(vr2), R16(vr3), R16(vr4), R16(vr5), R16(vr6), R16(vr7),  \
+  /*127*/R16(vr8), R16(vr9), R16(vr10),R16(vr11),R16(vr12),R16(vr13),R16(vr14),R16(vr15), \
+  /*135*/R16(vr16),R16(vr17),R16(vr18),R16(vr19),R16(vr20),R16(vr21),R16(vr22),R16(vr23), \
+  /*143*/R16(vr24),R16(vr25),R16(vr26),R16(vr27),R16(vr28),R16(vr29),R16(vr30),R16(vr31), \
+  /*151*/R4(vscr), R4(vrsave)
+
+/* Vectors of hi-lo general purpose registers.  */
+#define PPC_EV_REGS \
+  /* 0*/R8(ev0), R8(ev1), R8(ev2), R8(ev3), R8(ev4), R8(ev5), R8(ev6), R8(ev7),  \
+  /* 8*/R8(ev8), R8(ev9), R8(ev10),R8(ev11),R8(ev12),R8(ev13),R8(ev14),R8(ev15), \
+  /*16*/R8(ev16),R8(ev17),R8(ev18),R8(ev19),R8(ev20),R8(ev21),R8(ev22),R8(ev23), \
+  /*24*/R8(ev24),R8(ev25),R8(ev26),R8(ev27),R8(ev28),R8(ev29),R8(ev30),R8(ev31)
+
+/* Lower half of the EV registers.  */
+#define PPC_GPRS_PSEUDO_REGS \
+  /*  0 */ P(r0), P(r1), P(r2), P(r3), P(r4), P(r5), P(r6), P(r7),  \
+  /*  8 */ P(r8), P(r9), P(r10),P(r11),P(r12),P(r13),P(r14),P(r15), \
+  /* 16 */ P(r16),P(r17),P(r18),P(r19),P(r20),P(r21),P(r22),P(r23), \
+  /* 24 */ P(r24),P(r25),P(r26),P(r27),P(r28),P(r29),P(r30),P(r31), \
+
+/* IBM POWER (pre-PowerPC) architecture, user-level view.  We only cover
+   user-level SPR's.  */
+static const struct reg registers_power[] =
+{
+  COMMON_UISA_REGS,
+  /* 66 */ R4(cnd), R(lr), R(cnt), R4(xer), R4(mq),
+  /* 71 */ R4(fpscr)
+};
+
+/* PowerPC UISA - a PPC processor as viewed by user-level code.  A UISA-only
+   view of the PowerPC.  */
+static const struct reg registers_powerpc[] =
+{
+  COMMON_UISA_REGS,
+  PPC_UISA_SPRS,
+  PPC_ALTIVEC_REGS
 };
 
-/* a UISA-only view of the PowerPC.  */
-char *register_names_uisa[] =
+/* PowerPC UISA - a PPC processor as viewed by user-level
+   code, but without floating point registers.  */
+static const struct reg registers_powerpc_nofp[] =
 {
-  COMMON_UISA_REG_NAMES,
-  PPC_UISA_SPR_NAMES
+  COMMON_UISA_NOFP_REGS,
+  PPC_UISA_SPRS
 };
 
-char *register_names_403[] =
+/* IBM PowerPC 403.  */
+static const struct reg registers_403[] =
 {
-  COMMON_UISA_REG_NAMES,
-  PPC_UISA_SPR_NAMES,
-  PPC_SEGMENT_REG_NAMES,
-  PPC_32_OEA_SPR_NAMES,
-  /* 119 */ "icdbdr", "esr", "dear", "evpr", "cdbcr", "tsr", "tcr", "pit",
-  /* 127 */ "tbhi", "tblo", "srr2", "srr3", "dbsr", "dbcr", "iac1", "iac2",
-  /* 135 */ "dac1", "dac2", "dccr", "iccr", "pbl1", "pbu1", "pbl2", "pbu2"
+  COMMON_UISA_REGS,
+  PPC_UISA_SPRS,
+  PPC_SEGMENT_REGS,
+  PPC_OEA_SPRS,
+  /* 119 */ R(icdbdr), R(esr),  R(dear), R(evpr),
+  /* 123 */ R(cdbcr),  R(tsr),  R(tcr),  R(pit),
+  /* 127 */ R(tbhi),   R(tblo), R(srr2), R(srr3),
+  /* 131 */ R(dbsr),   R(dbcr), R(iac1), R(iac2),
+  /* 135 */ R(dac1),   R(dac2), R(dccr), R(iccr),
+  /* 139 */ R(pbl1),   R(pbu1), R(pbl2), R(pbu2)
 };
 
-char *register_names_403GC[] =
+/* IBM PowerPC 403GC.  */
+static const struct reg registers_403GC[] =
 {
-  COMMON_UISA_REG_NAMES,
-  PPC_UISA_SPR_NAMES,
-  PPC_SEGMENT_REG_NAMES,
-  PPC_32_OEA_SPR_NAMES,
-  /* 119 */ "icdbdr", "esr", "dear", "evpr", "cdbcr", "tsr", "tcr", "pit",
-  /* 127 */ "tbhi", "tblo", "srr2", "srr3", "dbsr", "dbcr", "iac1", "iac2",
-  /* 135 */ "dac1", "dac2", "dccr", "iccr", "pbl1", "pbu1", "pbl2", "pbu2",
-  /* 143 */ "zpr", "pid", "sgr", "dcwr", "tbhu", "tblu"
+  COMMON_UISA_REGS,
+  PPC_UISA_SPRS,
+  PPC_SEGMENT_REGS,
+  PPC_OEA_SPRS,
+  /* 119 */ R(icdbdr), R(esr),  R(dear), R(evpr),
+  /* 123 */ R(cdbcr),  R(tsr),  R(tcr),  R(pit),
+  /* 127 */ R(tbhi),   R(tblo), R(srr2), R(srr3),
+  /* 131 */ R(dbsr),   R(dbcr), R(iac1), R(iac2),
+  /* 135 */ R(dac1),   R(dac2), R(dccr), R(iccr),
+  /* 139 */ R(pbl1),   R(pbu1), R(pbl2), R(pbu2),
+  /* 143 */ R(zpr),    R(pid),  R(sgr),  R(dcwr),
+  /* 147 */ R(tbhu),   R(tblu)
 };
 
-char *register_names_505[] =
+/* Motorola PowerPC 505.  */
+static const struct reg registers_505[] =
 {
-  COMMON_UISA_REG_NAMES,
-  PPC_UISA_SPR_NAMES,
-  PPC_SEGMENT_REG_NAMES,
-  PPC_32_OEA_SPR_NAMES,
-  /* 119 */ "eie", "eid", "nri"
+  COMMON_UISA_REGS,
+  PPC_UISA_SPRS,
+  PPC_SEGMENT_REGS,
+  PPC_OEA_SPRS,
+  /* 119 */ R(eie), R(eid), R(nri)
 };
 
-char *register_names_860[] =
-{
-  COMMON_UISA_REG_NAMES,
-  PPC_UISA_SPR_NAMES,
-  PPC_SEGMENT_REG_NAMES,
-  PPC_32_OEA_SPR_NAMES,
-  /* 119 */ "eie", "eid", "nri", "cmpa", "cmpb", "cmpc", "cmpd", "icr",
-  /* 127 */ "der", "counta", "countb", "cmpe", "cmpf", "cmpg", "cmph",
-  /* 134 */ "lctrl1", "lctrl2", "ictrl", "bar", "ic_cst", "ic_adr", "ic_dat",
-  /* 141 */ "dc_cst", "dc_adr", "dc_dat", "dpdr", "dpir", "immr", "mi_ctr",
-  /* 148 */ "mi_ap", "mi_epn", "mi_twc", "mi_rpn", "md_ctr", "m_casid",
-  /* 154 */ "md_ap", "md_epn", "md_twb", "md_twc", "md_rpn", "m_tw",
-  /* 160 */ "mi_dbcam", "mi_dbram0", "mi_dbram1", "md_dbcam", "md_dbram0",
-  /* 165 */ "md_dbram1"
+/* Motorola PowerPC 860 or 850.  */
+static const struct reg registers_860[] =
+{
+  COMMON_UISA_REGS,
+  PPC_UISA_SPRS,
+  PPC_SEGMENT_REGS,
+  PPC_OEA_SPRS,
+  /* 119 */ R(eie), R(eid), R(nri), R(cmpa),
+  /* 123 */ R(cmpb), R(cmpc), R(cmpd), R(icr),
+  /* 127 */ R(der), R(counta), R(countb), R(cmpe),
+  /* 131 */ R(cmpf), R(cmpg), R(cmph), R(lctrl1),
+  /* 135 */ R(lctrl2), R(ictrl), R(bar), R(ic_cst),
+  /* 139 */ R(ic_adr), R(ic_dat), R(dc_cst), R(dc_adr),
+  /* 143 */ R(dc_dat), R(dpdr), R(dpir), R(immr),
+  /* 147 */ R(mi_ctr), R(mi_ap), R(mi_epn), R(mi_twc),
+  /* 151 */ R(mi_rpn), R(md_ctr), R(m_casid), R(md_ap),
+  /* 155 */ R(md_epn), R(md_twb), R(md_twc), R(md_rpn),
+  /* 159 */ R(m_tw), R(mi_dbcam), R(mi_dbram0), R(mi_dbram1),
+  /* 163 */ R(md_dbcam), R(md_dbram0), R(md_dbram1)
 };
 
-/* Note that the 601 has different register numbers for reading and
-   writing RTCU and RTCL.  However, how one reads and writes a
+/* Motorola PowerPC 601.  Note that the 601 has different register numbers
+   for reading and writing RTCU and RTCL.  However, how one reads and writes a
    register is the stub's problem.  */
-char *register_names_601[] =
-{
-  COMMON_UISA_REG_NAMES,
-  PPC_UISA_SPR_NAMES,
-  PPC_SEGMENT_REG_NAMES,
-  PPC_32_OEA_SPR_NAMES,
-  /* 119 */ "hid0", "hid1", "iabr", "dabr", "pir", "mq", "rtcu",
-  /* 126 */ "rtcl"
+static const struct reg registers_601[] =
+{
+  COMMON_UISA_REGS,
+  PPC_UISA_SPRS,
+  PPC_SEGMENT_REGS,
+  PPC_OEA_SPRS,
+  /* 119 */ R(hid0), R(hid1), R(iabr), R(dabr),
+  /* 123 */ R(pir), R(mq), R(rtcu), R(rtcl)
 };
 
-char *register_names_602[] =
+/* Motorola PowerPC 602.  */
+static const struct reg registers_602[] =
 {
-  COMMON_UISA_REG_NAMES,
-  PPC_UISA_SPR_NAMES,
-  PPC_SEGMENT_REG_NAMES,
-  PPC_32_OEA_SPR_NAMES,
-  /* 119 */ "hid0", "hid1", "iabr", "", "", "tcr", "ibr", "esassr", "sebr",
-  /* 128 */ "ser", "sp", "lt"
+  COMMON_UISA_REGS,
+  PPC_UISA_SPRS,
+  PPC_SEGMENT_REGS,
+  PPC_OEA_SPRS,
+  /* 119 */ R(hid0), R(hid1), R(iabr), R0,
+  /* 123 */ R0, R(tcr), R(ibr), R(esassr),
+  /* 127 */ R(sebr), R(ser), R(sp), R(lt)
 };
 
-char *register_names_603[] =
+/* Motorola/IBM PowerPC 603 or 603e.  */
+static const struct reg registers_603[] =
 {
-  COMMON_UISA_REG_NAMES,
-  PPC_UISA_SPR_NAMES,
-  PPC_SEGMENT_REG_NAMES,
-  PPC_32_OEA_SPR_NAMES,
-  /* 119 */ "hid0", "hid1", "iabr", "", "", "dmiss", "dcmp", "hash1",
-  /* 127 */ "hash2", "imiss", "icmp", "rpa"
+  COMMON_UISA_REGS,
+  PPC_UISA_SPRS,
+  PPC_SEGMENT_REGS,
+  PPC_OEA_SPRS,
+  /* 119 */ R(hid0), R(hid1), R(iabr), R0,
+  /* 123 */ R0, R(dmiss), R(dcmp), R(hash1),
+  /* 127 */ R(hash2), R(imiss), R(icmp), R(rpa)
 };
 
-char *register_names_604[] =
+/* Motorola PowerPC 604 or 604e.  */
+static const struct reg registers_604[] =
 {
-  COMMON_UISA_REG_NAMES,
-  PPC_UISA_SPR_NAMES,
-  PPC_SEGMENT_REG_NAMES,
-  PPC_32_OEA_SPR_NAMES,
-  /* 119 */ "hid0", "hid1", "iabr", "dabr", "pir", "mmcr0", "pmc1", "pmc2",
-  /* 127 */ "sia", "sda"
+  COMMON_UISA_REGS,
+  PPC_UISA_SPRS,
+  PPC_SEGMENT_REGS,
+  PPC_OEA_SPRS,
+  /* 119 */ R(hid0), R(hid1), R(iabr), R(dabr),
+  /* 123 */ R(pir), R(mmcr0), R(pmc1), R(pmc2),
+  /* 127 */ R(sia), R(sda)
 };
 
-char *register_names_750[] =
+/* Motorola/IBM PowerPC 750 or 740.  */
+static const struct reg registers_750[] =
+{
+  COMMON_UISA_REGS,
+  PPC_UISA_SPRS,
+  PPC_SEGMENT_REGS,
+  PPC_OEA_SPRS,
+  /* 119 */ R(hid0), R(hid1), R(iabr), R(dabr),
+  /* 123 */ R0, R(ummcr0), R(upmc1), R(upmc2),
+  /* 127 */ R(usia), R(ummcr1), R(upmc3), R(upmc4),
+  /* 131 */ R(mmcr0), R(pmc1), R(pmc2), R(sia),
+  /* 135 */ R(mmcr1), R(pmc3), R(pmc4), R(l2cr),
+  /* 139 */ R(ictc), R(thrm1), R(thrm2), R(thrm3)
+};
+
+
+/* Motorola PowerPC 7400.  */
+static const struct reg registers_7400[] =
 {
-  COMMON_UISA_REG_NAMES,
-  PPC_UISA_SPR_NAMES,
-  PPC_SEGMENT_REG_NAMES,
-  PPC_32_OEA_SPR_NAMES,
-  /* 119 */ "hid0", "hid1", "iabr", "dabr", "", "ummcr0", "upmc1", "upmc2",
-  /* 127 */ "usia", "ummcr1", "upmc3", "upmc4", "mmcr0", "pmc1", "pmc2",
-  /* 134 */ "sia", "mmcr1", "pmc3", "pmc4", "l2cr", "ictc", "thrm1", "thrm2",
-  /* 142 */ "thrm3"
+  /* gpr0-gpr31, fpr0-fpr31 */
+  COMMON_UISA_REGS,
+  /* ctr, xre, lr, cr */
+  PPC_UISA_SPRS,
+  /* sr0-sr15 */
+  PPC_SEGMENT_REGS,
+  PPC_OEA_SPRS,
+  /* vr0-vr31, vrsave, vscr */
+  PPC_ALTIVEC_REGS
+  /* FIXME? Add more registers? */
 };
 
+/* Motorola e500.  */
+static const struct reg registers_e500[] =
+{
+  R(pc), R(ps),
+  /* cr, lr, ctr, xer, "" */
+  PPC_UISA_NOFP_SPRS,
+  /* 7...38 */
+  PPC_EV_REGS,
+  /* 39...70 */
+  PPC_GPRS_PSEUDO_REGS
+};
 
 /* Information about a particular processor variant.  */
+
 struct variant
   {
     /* Name of this variant.  */
@@ -1712,14 +2461,53 @@ struct variant
     /* English description of the variant.  */
     char *description;
 
+    /* bfd_arch_info.arch corresponding to variant.  */
+    enum bfd_architecture arch;
+
+    /* bfd_arch_info.mach corresponding to variant.  */
+    unsigned long mach;
+
+    /* Number of real registers.  */
+    int nregs;
+
+    /* Number of pseudo registers.  */
+    int npregs;
+
+    /* Number of total registers (the sum of nregs and npregs).  */
+    int num_tot_regs;
+
     /* Table of register names; registers[R] is the name of the register
        number R.  */
-    int num_registers;
-    char **registers;
+    const struct reg *regs;
   };
 
-#define num_registers(list) (sizeof (list) / sizeof((list)[0]))
+#define tot_num_registers(list) (sizeof (list) / sizeof((list)[0]))
+
+static int
+num_registers (const struct reg *reg_list, int num_tot_regs)
+{
+  int i;
+  int nregs = 0;
+
+  for (i = 0; i < num_tot_regs; i++)
+    if (!reg_list[i].pseudo)
+      nregs++;
+       
+  return nregs;
+}
+
+static int
+num_pseudo_registers (const struct reg *reg_list, int num_tot_regs)
+{
+  int i;
+  int npregs = 0;
+
+  for (i = 0; i < num_tot_regs; i++)
+    if (reg_list[i].pseudo)
+      npregs ++; 
 
+  return npregs;
+}
 
 /* Information in this table comes from the following web sites:
    IBM:       http://www.chips.ibm.com:80/products/embedded/
@@ -1731,186 +2519,482 @@ struct variant
    If you add entries to this table, please be sure to allow the new
    value as an argument to the --with-cpu flag, in configure.in.  */
 
-static struct variant
-  variants[] =
-{
-  {"ppc-uisa", "PowerPC UISA - a PPC processor as viewed by user-level code",
-   num_registers (register_names_uisa), register_names_uisa},
-  {"rs6000", "IBM RS6000 (\"POWER\") architecture, user-level view",
-   num_registers (register_names_rs6000), register_names_rs6000},
-  {"403", "IBM PowerPC 403",
-   num_registers (register_names_403), register_names_403},
-  {"403GC", "IBM PowerPC 403GC",
-   num_registers (register_names_403GC), register_names_403GC},
-  {"505", "Motorola PowerPC 505",
-   num_registers (register_names_505), register_names_505},
-  {"860", "Motorola PowerPC 860 or 850",
-   num_registers (register_names_860), register_names_860},
-  {"601", "Motorola PowerPC 601",
-   num_registers (register_names_601), register_names_601},
-  {"602", "Motorola PowerPC 602",
-   num_registers (register_names_602), register_names_602},
-  {"603", "Motorola/IBM PowerPC 603 or 603e",
-   num_registers (register_names_603), register_names_603},
-  {"604", "Motorola PowerPC 604 or 604e",
-   num_registers (register_names_604), register_names_604},
-  {"750", "Motorola/IBM PowerPC 750 or 740",
-   num_registers (register_names_750), register_names_750},
-  {0, 0, 0, 0}
-};
-
-
-static struct variant *current_variant;
-
-char *
-rs6000_register_name (int i)
+static struct variant variants[] =
 {
-  if (i < 0 || i >= NUM_REGS)
-    error ("GDB bug: rs6000-tdep.c (rs6000_register_name): strange register number");
 
-  return ((i < current_variant->num_registers)
-         ? current_variant->registers[i]
-         : "");
-}
+  {"powerpc", "PowerPC user-level", bfd_arch_powerpc,
+   bfd_mach_ppc, -1, -1, tot_num_registers (registers_powerpc),
+   registers_powerpc},
+  {"power", "POWER user-level", bfd_arch_rs6000,
+   bfd_mach_rs6k, -1, -1, tot_num_registers (registers_power),
+   registers_power},
+  {"403", "IBM PowerPC 403", bfd_arch_powerpc,
+   bfd_mach_ppc_403, -1, -1, tot_num_registers (registers_403),
+   registers_403},
+  {"601", "Motorola PowerPC 601", bfd_arch_powerpc,
+   bfd_mach_ppc_601, -1, -1, tot_num_registers (registers_601),
+   registers_601},
+  {"602", "Motorola PowerPC 602", bfd_arch_powerpc,
+   bfd_mach_ppc_602, -1, -1, tot_num_registers (registers_602),
+   registers_602},
+  {"603", "Motorola/IBM PowerPC 603 or 603e", bfd_arch_powerpc,
+   bfd_mach_ppc_603, -1, -1, tot_num_registers (registers_603),
+   registers_603},
+  {"604", "Motorola PowerPC 604 or 604e", bfd_arch_powerpc,
+   604, -1, -1, tot_num_registers (registers_604),
+   registers_604},
+  {"403GC", "IBM PowerPC 403GC", bfd_arch_powerpc,
+   bfd_mach_ppc_403gc, -1, -1, tot_num_registers (registers_403GC),
+   registers_403GC},
+  {"505", "Motorola PowerPC 505", bfd_arch_powerpc,
+   bfd_mach_ppc_505, -1, -1, tot_num_registers (registers_505),
+   registers_505},
+  {"860", "Motorola PowerPC 860 or 850", bfd_arch_powerpc,
+   bfd_mach_ppc_860, -1, -1, tot_num_registers (registers_860),
+   registers_860},
+  {"750", "Motorola/IBM PowerPC 750 or 740", bfd_arch_powerpc,
+   bfd_mach_ppc_750, -1, -1, tot_num_registers (registers_750),
+   registers_750},
+  {"7400", "Motorola/IBM PowerPC 7400 (G4)", bfd_arch_powerpc,
+   bfd_mach_ppc_7400, -1, -1, tot_num_registers (registers_7400),
+   registers_7400},
+  {"e500", "Motorola PowerPC e500", bfd_arch_powerpc,
+   bfd_mach_ppc_e500, -1, -1, tot_num_registers (registers_e500),
+   registers_e500},
+
+  /* 64-bit */
+  {"powerpc64", "PowerPC 64-bit user-level", bfd_arch_powerpc,
+   bfd_mach_ppc64, -1, -1, tot_num_registers (registers_powerpc),
+   registers_powerpc},
+  {"620", "Motorola PowerPC 620", bfd_arch_powerpc,
+   bfd_mach_ppc_620, -1, -1, tot_num_registers (registers_powerpc),
+   registers_powerpc},
+  {"630", "Motorola PowerPC 630", bfd_arch_powerpc,
+   bfd_mach_ppc_630, -1, -1, tot_num_registers (registers_powerpc),
+   registers_powerpc},
+  {"a35", "PowerPC A35", bfd_arch_powerpc,
+   bfd_mach_ppc_a35, -1, -1, tot_num_registers (registers_powerpc),
+   registers_powerpc},
+  {"rs64ii", "PowerPC rs64ii", bfd_arch_powerpc,
+   bfd_mach_ppc_rs64ii, -1, -1, tot_num_registers (registers_powerpc),
+   registers_powerpc},
+  {"rs64iii", "PowerPC rs64iii", bfd_arch_powerpc,
+   bfd_mach_ppc_rs64iii, -1, -1, tot_num_registers (registers_powerpc),
+   registers_powerpc},
+
+  /* FIXME: I haven't checked the register sets of the following.  */
+  {"rs1", "IBM POWER RS1", bfd_arch_rs6000,
+   bfd_mach_rs6k_rs1, -1, -1, tot_num_registers (registers_power),
+   registers_power},
+  {"rsc", "IBM POWER RSC", bfd_arch_rs6000,
+   bfd_mach_rs6k_rsc, -1, -1, tot_num_registers (registers_power),
+   registers_power},
+  {"rs2", "IBM POWER RS2", bfd_arch_rs6000,
+   bfd_mach_rs6k_rs2, -1, -1, tot_num_registers (registers_power),
+   registers_power},
+
+  {0, 0, 0, 0, 0, 0, 0, 0}
+};
 
+/* Initialize the number of registers and pseudo registers in each variant.  */
 
 static void
-install_variant (struct variant *v)
+init_variants (void)
 {
-  current_variant = v;
+  struct variant *v;
+
+  for (v = variants; v->name; v++)
+    {
+      if (v->nregs == -1)
+        v->nregs = num_registers (v->regs, v->num_tot_regs);
+      if (v->npregs == -1)
+        v->npregs = num_pseudo_registers (v->regs, v->num_tot_regs);
+    }  
 }
 
+/* Return the variant corresponding to architecture ARCH and machine number
+   MACH.  If no such variant exists, return null.  */
 
-/* Look up the variant named NAME in the `variants' table.  Return a
-   pointer to the struct variant, or null if we couldn't find it.  */
-static struct variant *
-find_variant_by_name (char *name)
+static const struct variant *
+find_variant_by_arch (enum bfd_architecture arch, unsigned long mach)
 {
-  int i;
+  const struct variant *v;
 
-  for (i = 0; variants[i].name; i++)
-    if (!strcmp (name, variants[i].name))
-      return &variants[i];
+  for (v = variants; v->name; v++)
+    if (arch == v->arch && mach == v->mach)
+      return v;
 
-  return 0;
+  return NULL;
 }
 
+static int
+gdb_print_insn_powerpc (bfd_vma memaddr, disassemble_info *info)
+{
+  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+    return print_insn_big_powerpc (memaddr, info);
+  else
+    return print_insn_little_powerpc (memaddr, info);
+}
+\f
+/* Initialize the current architecture based on INFO.  If possible, re-use an
+   architecture from ARCHES, which is a list of architectures already created
+   during this debugging session.
 
-/* Install the PPC/RS6000 variant named NAME in the `variants' table.
-   Return zero if we installed it successfully, or a non-zero value if
-   we couldn't do it.
+   Called e.g. at program startup, when reading a core file, and when reading
+   a binary file.  */
 
-   This might be useful to code outside this file, which doesn't want
-   to depend on the exact indices of the entries in the `variants'
-   table.  Just make it non-static if you want that.  */
-static int
-install_variant_by_name (char *name)
+static struct gdbarch *
+rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
-  struct variant *v = find_variant_by_name (name);
+  struct gdbarch *gdbarch;
+  struct gdbarch_tdep *tdep;
+  int wordsize, from_xcoff_exec, from_elf_exec, power, i, off;
+  struct reg *regs;
+  const struct variant *v;
+  enum bfd_architecture arch;
+  unsigned long mach;
+  bfd abfd;
+  int sysv_abi;
+  enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
+  asection *sect;
+
+  from_xcoff_exec = info.abfd && info.abfd->format == bfd_object &&
+    bfd_get_flavour (info.abfd) == bfd_target_xcoff_flavour;
+
+  from_elf_exec = info.abfd && info.abfd->format == bfd_object &&
+    bfd_get_flavour (info.abfd) == bfd_target_elf_flavour;
+
+  sysv_abi = info.abfd && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour;
+
+  if (info.abfd)
+    osabi = gdbarch_lookup_osabi (info.abfd);
+
+  /* Check word size.  If INFO is from a binary file, infer it from
+     that, else choose a likely default.  */
+  if (from_xcoff_exec)
+    {
+      if (bfd_xcoff_is_xcoff64 (info.abfd))
+       wordsize = 8;
+      else
+       wordsize = 4;
+    }
+  else if (from_elf_exec)
+    {
+      if (elf_elfheader (info.abfd)->e_ident[EI_CLASS] == ELFCLASS64)
+       wordsize = 8;
+      else
+       wordsize = 4;
+    }
+  else
+    {
+      if (info.bfd_arch_info != NULL && info.bfd_arch_info->bits_per_word != 0)
+       wordsize = info.bfd_arch_info->bits_per_word /
+         info.bfd_arch_info->bits_per_byte;
+      else
+       wordsize = 4;
+    }
 
-  if (v)
+  /* Find a candidate among extant architectures.  */
+  for (arches = gdbarch_list_lookup_by_info (arches, &info);
+       arches != NULL;
+       arches = gdbarch_list_lookup_by_info (arches->next, &info))
     {
-      install_variant (v);
-      return 0;
+      /* Word size in the various PowerPC bfd_arch_info structs isn't
+         meaningful, because 64-bit CPUs can run in 32-bit mode.  So, perform
+         separate word size check.  */
+      tdep = gdbarch_tdep (arches->gdbarch);
+      if (tdep && tdep->wordsize == wordsize && tdep->osabi == osabi)
+       return arches->gdbarch;
+    }
+
+  /* None found, create a new architecture from INFO, whose bfd_arch_info
+     validity depends on the source:
+       - executable            useless
+       - rs6000_host_arch()    good
+       - core file             good
+       - "set arch"            trust blindly
+       - GDB startup           useless but harmless */
+
+  if (!from_xcoff_exec)
+    {
+      arch = info.bfd_arch_info->arch;
+      mach = info.bfd_arch_info->mach;
     }
   else
-    return 1;
-}
+    {
+      arch = bfd_arch_powerpc;
+      mach = 0;
+      bfd_default_set_arch_mach (&abfd, arch, mach);
+      info.bfd_arch_info = bfd_get_arch_info (&abfd);
+    }
+  tdep = xmalloc (sizeof (struct gdbarch_tdep));
+  tdep->wordsize = wordsize;
+  tdep->osabi = osabi;
+
+  /* For e500 executables, the apuinfo section is of help here.  Such
+     section contains the identifier and revision number of each
+     Application-specific Processing Unit that is present on the
+     chip.  The content of the section is determined by the assembler
+     which looks at each instruction and determines which unit (and
+     which version of it) can execute it. In our case we just look for
+     the existance of the section.  */
+
+  if (info.abfd)
+    {
+      sect = bfd_get_section_by_name (info.abfd, ".PPC.EMB.apuinfo");
+      if (sect)
+       {
+         arch = info.bfd_arch_info->arch;
+         mach = bfd_mach_ppc_e500;
+         bfd_default_set_arch_mach (&abfd, arch, mach);
+         info.bfd_arch_info = bfd_get_arch_info (&abfd);
+       }
+    }
 
+  gdbarch = gdbarch_alloc (&info, tdep);
+  power = arch == bfd_arch_rs6000;
+
+  /* Initialize the number of real and pseudo registers in each variant.  */
+  init_variants ();
+
+  /* Choose variant.  */
+  v = find_variant_by_arch (arch, mach);
+  if (!v)
+    return NULL;
+
+  tdep->regs = v->regs;
+
+  tdep->ppc_gp0_regnum = 0;
+  tdep->ppc_gplast_regnum = 31;
+  tdep->ppc_toc_regnum = 2;
+  tdep->ppc_ps_regnum = 65;
+  tdep->ppc_cr_regnum = 66;
+  tdep->ppc_lr_regnum = 67;
+  tdep->ppc_ctr_regnum = 68;
+  tdep->ppc_xer_regnum = 69;
+  if (v->mach == bfd_mach_ppc_601)
+    tdep->ppc_mq_regnum = 124;
+  else if (power)
+    tdep->ppc_mq_regnum = 70;
+  else
+    tdep->ppc_mq_regnum = -1;
+  tdep->ppc_fpscr_regnum = power ? 71 : 70;
+
+  set_gdbarch_pc_regnum (gdbarch, 64);
+  set_gdbarch_sp_regnum (gdbarch, 1);
+  set_gdbarch_fp_regnum (gdbarch, 1);
+  set_gdbarch_deprecated_extract_return_value (gdbarch,
+                                              rs6000_extract_return_value);
+  set_gdbarch_deprecated_store_return_value (gdbarch, rs6000_store_return_value);
+
+  if (v->arch == bfd_arch_powerpc)
+    switch (v->mach)
+      {
+      case bfd_mach_ppc: 
+       tdep->ppc_vr0_regnum = 71;
+       tdep->ppc_vrsave_regnum = 104;
+       tdep->ppc_ev0_regnum = -1;
+       tdep->ppc_ev31_regnum = -1;
+       break;
+      case bfd_mach_ppc_7400:
+       tdep->ppc_vr0_regnum = 119;
+       tdep->ppc_vrsave_regnum = 152;
+       tdep->ppc_ev0_regnum = -1;
+       tdep->ppc_ev31_regnum = -1;
+       break;
+      case bfd_mach_ppc_e500:
+        tdep->ppc_gp0_regnum = 39;
+        tdep->ppc_gplast_regnum = 70;
+        tdep->ppc_toc_regnum = -1;
+        tdep->ppc_ps_regnum = 1;
+        tdep->ppc_cr_regnum = 2;
+        tdep->ppc_lr_regnum = 3;
+        tdep->ppc_ctr_regnum = 4;
+        tdep->ppc_xer_regnum = 5;
+       tdep->ppc_ev0_regnum = 7;
+       tdep->ppc_ev31_regnum = 38;
+        set_gdbarch_pc_regnum (gdbarch, 0);
+        set_gdbarch_sp_regnum (gdbarch, 40);
+        set_gdbarch_fp_regnum (gdbarch, 40);
+        set_gdbarch_dwarf2_reg_to_regnum (gdbarch, e500_dwarf2_reg_to_regnum);
+        set_gdbarch_pseudo_register_read (gdbarch, e500_pseudo_register_read);
+        set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write);
+        set_gdbarch_extract_return_value (gdbarch, e500_extract_return_value);
+        set_gdbarch_deprecated_store_return_value (gdbarch, e500_store_return_value);
+       break;
+      default:
+       tdep->ppc_vr0_regnum = -1;
+       tdep->ppc_vrsave_regnum = -1;
+       tdep->ppc_ev0_regnum = -1;
+       tdep->ppc_ev31_regnum = -1;
+       break;
+      }   
+
+  /* Set lr_frame_offset.  */
+  if (wordsize == 8)
+    tdep->lr_frame_offset = 16;
+  else if (sysv_abi)
+    tdep->lr_frame_offset = 4;
+  else
+    tdep->lr_frame_offset = 8;
 
-static void
-list_variants ()
-{
-  int i;
+  /* 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);
+    }
 
-  printf_filtered ("GDB knows about the following PowerPC and RS6000 variants:\n");
+  /* Select instruction printer.  */
+  if (arch == power)
+    set_gdbarch_print_insn (gdbarch, print_insn_rs6000);
+  else
+    set_gdbarch_print_insn (gdbarch, gdb_print_insn_powerpc);
+
+  set_gdbarch_read_pc (gdbarch, generic_target_read_pc);
+  set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
+  set_gdbarch_read_fp (gdbarch, generic_target_read_fp);
+  set_gdbarch_read_sp (gdbarch, generic_target_read_sp);
+  set_gdbarch_write_sp (gdbarch, generic_target_write_sp);
+
+  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_register_size (gdbarch, wordsize);
+  set_gdbarch_register_bytes (gdbarch, off);
+  set_gdbarch_register_byte (gdbarch, rs6000_register_byte);
+  set_gdbarch_register_raw_size (gdbarch, rs6000_register_raw_size);
+  set_gdbarch_max_register_raw_size (gdbarch, 16);
+  set_gdbarch_register_virtual_size (gdbarch, generic_register_size);
+  set_gdbarch_max_register_virtual_size (gdbarch, 16);
+  set_gdbarch_register_virtual_type (gdbarch, rs6000_register_virtual_type);
+
+  set_gdbarch_ptr_bit (gdbarch, wordsize * TARGET_CHAR_BIT);
+  set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
+  set_gdbarch_int_bit (gdbarch, 4 * TARGET_CHAR_BIT);
+  set_gdbarch_long_bit (gdbarch, wordsize * TARGET_CHAR_BIT);
+  set_gdbarch_long_long_bit (gdbarch, 8 * TARGET_CHAR_BIT);
+  set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT);
+  set_gdbarch_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
+  set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
+  set_gdbarch_char_signed (gdbarch, 0);
+
+  set_gdbarch_use_generic_dummy_frames (gdbarch, 1);
+  set_gdbarch_call_dummy_length (gdbarch, 0);
+  set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
+  set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
+  set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
+  set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
+  set_gdbarch_call_dummy_start_offset (gdbarch, 0);
+  set_gdbarch_pc_in_call_dummy (gdbarch, generic_pc_in_call_dummy);
+  set_gdbarch_call_dummy_p (gdbarch, 1);
+  set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
+  set_gdbarch_fix_call_dummy (gdbarch, rs6000_fix_call_dummy);
+  set_gdbarch_frame_align (gdbarch, rs6000_frame_align);
+  set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
+  set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
+  set_gdbarch_push_return_address (gdbarch, ppc_push_return_address);
+  set_gdbarch_believe_pcc_promotion (gdbarch, 1);
+  set_gdbarch_coerce_float_to_double (gdbarch, rs6000_coerce_float_to_double);
+
+  set_gdbarch_register_convertible (gdbarch, rs6000_register_convertible);
+  set_gdbarch_register_convert_to_virtual (gdbarch, rs6000_register_convert_to_virtual);
+  set_gdbarch_register_convert_to_raw (gdbarch, rs6000_register_convert_to_raw);
+  set_gdbarch_stab_reg_to_regnum (gdbarch, rs6000_stab_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
+     worse results since it only works for 32-bit code.  So, for the moment,
+     we're better off calling rs6000_push_arguments() since it works for
+     64-bit code.  At some point in the future, this matter needs to be
+     revisited.  */
+  if (sysv_abi && wordsize == 4)
+    set_gdbarch_push_arguments (gdbarch, ppc_sysv_abi_push_arguments);
+  else
+    set_gdbarch_push_arguments (gdbarch, rs6000_push_arguments);
 
-  for (i = 0; variants[i].name; i++)
-    printf_filtered ("  %-8s  %s\n",
-                    variants[i].name, variants[i].description);
-}
+  set_gdbarch_store_struct_return (gdbarch, rs6000_store_struct_return);
+  set_gdbarch_extract_struct_value_address (gdbarch, rs6000_extract_struct_value_address);
+  set_gdbarch_pop_frame (gdbarch, rs6000_pop_frame);
 
+  set_gdbarch_skip_prologue (gdbarch, rs6000_skip_prologue);
+  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+  set_gdbarch_decr_pc_after_break (gdbarch, 0);
+  set_gdbarch_function_start_offset (gdbarch, 0);
+  set_gdbarch_breakpoint_from_pc (gdbarch, rs6000_breakpoint_from_pc);
 
-static void
-show_current_variant ()
-{
-  printf_filtered ("PowerPC / RS6000 processor variant is set to `%s'.\n",
-                  current_variant->name);
-}
+  /* Not sure on this. FIXMEmgo */
+  set_gdbarch_frame_args_skip (gdbarch, 8);
 
+  if (sysv_abi)
+    set_gdbarch_use_struct_convention (gdbarch,
+                                      ppc_sysv_abi_use_struct_convention);
+  else
+    set_gdbarch_use_struct_convention (gdbarch,
+                                      generic_use_struct_convention);
 
-static void
-set_processor (char *arg, int from_tty)
-{
-  if (!arg || arg[0] == '\0')
-    {
-      list_variants ();
-      return;
-    }
+  set_gdbarch_frame_chain_valid (gdbarch, file_frame_chain_valid);
+
+  set_gdbarch_frameless_function_invocation (gdbarch,
+                                         rs6000_frameless_function_invocation);
+  set_gdbarch_frame_chain (gdbarch, rs6000_frame_chain);
+  set_gdbarch_frame_saved_pc (gdbarch, rs6000_frame_saved_pc);
 
-  if (install_variant_by_name (arg))
+  set_gdbarch_frame_init_saved_regs (gdbarch, rs6000_frame_init_saved_regs);
+  set_gdbarch_init_extra_frame_info (gdbarch, rs6000_init_extra_frame_info);
+
+  if (!sysv_abi)
     {
-      error_begin ();
-      fprintf_filtered (gdb_stderr,
-       "`%s' is not a recognized PowerPC / RS6000 variant name.\n\n", arg);
-      list_variants ();
-      return_to_top_level (RETURN_ERROR);
+      /* Handle RS/6000 function pointers (which are really function
+         descriptors).  */
+      set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+       rs6000_convert_from_func_ptr_addr);
     }
+  set_gdbarch_frame_args_address (gdbarch, rs6000_frame_args_address);
+  set_gdbarch_frame_locals_address (gdbarch, rs6000_frame_args_address);
+  set_gdbarch_saved_pc_after_call (gdbarch, rs6000_saved_pc_after_call);
+
+  /* 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);
 
-  show_current_variant ();
+  /* Hook in ABI-specific overrides, if they have been registered.  */
+  gdbarch_init_osabi (info, gdbarch, osabi);
+
+  return gdbarch;
 }
 
 static void
-show_processor (char *arg, int from_tty)
+rs6000_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
 {
-  show_current_variant ();
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+  if (tdep == NULL)
+    return;
+
+  fprintf_unfiltered (file, "rs6000_dump_tdep: OS ABI = %s\n",
+                     gdbarch_osabi_name (tdep->osabi));
 }
 
+static struct cmd_list_element *info_powerpc_cmdlist = NULL;
 
-\f
+static void
+rs6000_info_powerpc_command (char *args, int from_tty)
+{
+  help_list (info_powerpc_cmdlist, "info powerpc ", class_info, gdb_stdout);
+}
 
 /* Initialization code.  */
 
 void
-_initialize_rs6000_tdep ()
-{
-  /* FIXME, this should not be decided via ifdef. */
-#ifdef GDB_TARGET_POWERPC
-  tm_print_insn = gdb_print_insn_powerpc;
-#else
-  tm_print_insn = print_insn_rs6000;
-#endif
-
-  /* I don't think we should use the set/show command arrangement
-     here, because the way that's implemented makes it hard to do the
-     error checking we want in a reasonable way.  So we just add them
-     as two separate commands.  */
-  add_cmd ("processor", class_support, set_processor,
-          "`set processor NAME' sets the PowerPC/RS6000 variant to NAME.\n\
-If you set this, GDB will know about the special-purpose registers that are\n\
-available on the given variant.\n\
-Type `set processor' alone for a list of recognized variant names.",
-          &setlist);
-  add_cmd ("processor", class_support, show_processor,
-          "Show the variant of the PowerPC or RS6000 processor in use.\n\
-Use `set processor' to change this.",
-          &showlist);
-
-  /* Set the current PPC processor variant.  */
-  {
-    int status = 1;
-
-#ifdef TARGET_CPU_DEFAULT
-    status = install_variant_by_name (TARGET_CPU_DEFAULT);
-#endif
+_initialize_rs6000_tdep (void)
+{
+  gdbarch_register (bfd_arch_rs6000, rs6000_gdbarch_init, rs6000_dump_tdep);
+  gdbarch_register (bfd_arch_powerpc, rs6000_gdbarch_init, rs6000_dump_tdep);
 
-    if (status)
-      {
-#ifdef GDB_TARGET_POWERPC
-       install_variant_by_name ("ppc-uisa");
-#else
-       install_variant_by_name ("rs6000");
-#endif
-      }
-  }
+  /* Add root prefix command for "info powerpc" commands */
+  add_prefix_cmd ("powerpc", class_info, rs6000_info_powerpc_command,
+                 "Various POWERPC info specific commands.",
+                 &info_powerpc_cmdlist, "info powerpc ", 0, &infolist);
 }
This page took 0.064169 seconds and 4 git commands to generate.