daily update
[deliverable/binutils-gdb.git] / gdb / rs6000-tdep.c
index 4b43bcf16f91e8664ccc2e0e4498d7e93df31d95..1f4a6d0de2b8aa33d016ddaaccd45d01510acd6a 100644 (file)
@@ -49,6 +49,7 @@
 #include "libxcoff.h"
 
 #include "elf-bfd.h"
+#include "elf/ppc.h"
 
 #include "solib-svr4.h"
 #include "ppc-tdep.h"
 #include "features/rs6000/powerpc-e500.c"
 #include "features/rs6000/rs6000.c"
 
+/* The list of available "set powerpc ..." and "show powerpc ..."
+   commands.  */
+static struct cmd_list_element *setpowerpccmdlist = NULL;
+static struct cmd_list_element *showpowerpccmdlist = NULL;
+
+static enum auto_boolean powerpc_soft_float_global = AUTO_BOOLEAN_AUTO;
+
+/* The vector ABI to use.  Keep this in sync with powerpc_vector_abi.  */
+static const char *powerpc_vector_strings[] =
+{
+  "auto",
+  "generic",
+  "altivec",
+  "spe",
+  NULL
+};
+
+/* A variable that can be configured by the user.  */
+static enum powerpc_vector_abi powerpc_vector_abi_global = POWERPC_VEC_AUTO;
+static const char *powerpc_vector_abi_string = "auto";
+
 /* 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
@@ -194,6 +216,16 @@ ppc_floating_point_unit_p (struct gdbarch *gdbarch)
           && tdep->ppc_fpscr_regnum >= 0);
 }
 
+/* Return non-zero if the architecture described by GDBARCH has
+   Altivec registers (vr0 --- vr31, vrsave and vscr).  */
+int
+ppc_altivec_support_p (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  return (tdep->ppc_vr0_regnum >= 0
+          && tdep->ppc_vrsave_regnum >= 0);
+}
 
 /* Check that TABLE[GDB_REGNO] is not already initialized, and then
    set it to SIM_REGNO.
@@ -310,17 +342,17 @@ init_sim_regno_table (struct gdbarch *arch)
 /* Given a GDB register number REG, return the corresponding SIM
    register number.  */
 static int
-rs6000_register_sim_regno (int reg)
+rs6000_register_sim_regno (struct gdbarch *gdbarch, int reg)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int sim_regno;
 
   if (tdep->sim_regno == NULL)
-    init_sim_regno_table (current_gdbarch);
+    init_sim_regno_table (gdbarch);
 
   gdb_assert (0 <= reg 
-             && reg <= gdbarch_num_regs (current_gdbarch)
-                       + gdbarch_num_pseudo_regs (current_gdbarch));
+             && reg <= gdbarch_num_regs (gdbarch)
+                       + gdbarch_num_pseudo_regs (gdbarch));
   sim_regno = tdep->sim_regno[reg];
 
   if (sim_regno >= 0)
@@ -436,6 +468,24 @@ ppc_fpreg_offset (struct gdbarch_tdep *tdep,
   return -1;
 }
 
+static int
+ppc_vrreg_offset (struct gdbarch_tdep *tdep,
+                 const struct ppc_reg_offsets *offsets,
+                 int regnum)
+{
+  if (regnum >= tdep->ppc_vr0_regnum
+      && regnum < tdep->ppc_vr0_regnum + ppc_num_vrs)
+    return offsets->vr0_offset + (regnum - tdep->ppc_vr0_regnum) * 16;
+
+  if (regnum == tdep->ppc_vrsave_regnum - 1)
+    return offsets->vscr_offset;
+
+  if (regnum == tdep->ppc_vrsave_regnum)
+    return offsets->vrsave_offset;
+
+  return -1;
+}
+
 /* Supply register REGNUM in the general-purpose register set REGSET
    from the buffer specified by GREGS and LEN to register cache
    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
@@ -518,6 +568,50 @@ ppc_supply_fpregset (const struct regset *regset, struct regcache *regcache,
                  regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
 }
 
+/* Supply register REGNUM in the Altivec register set REGSET
+   from the buffer specified by VRREGS and LEN to register cache
+   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
+
+void
+ppc_supply_vrregset (const struct regset *regset, struct regcache *regcache,
+                    int regnum, const void *vrregs, size_t len)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep;
+  const struct ppc_reg_offsets *offsets;
+  size_t offset;
+
+  if (!ppc_altivec_support_p (gdbarch))
+    return;
+
+  tdep = gdbarch_tdep (gdbarch);
+  offsets = regset->descr;
+  if (regnum == -1)
+    {
+      int i;
+
+      for (i = tdep->ppc_vr0_regnum, offset = offsets->vr0_offset;
+          i < tdep->ppc_vr0_regnum + ppc_num_vrs;
+          i++, offset += 16)
+        ppc_supply_reg (regcache, i, vrregs, offset, 16);
+
+      ppc_supply_reg (regcache, (tdep->ppc_vrsave_regnum - 1),
+                     vrregs, offsets->vscr_offset, 4);
+
+      ppc_supply_reg (regcache, tdep->ppc_vrsave_regnum,
+                     vrregs, offsets->vrsave_offset, 4);
+      return;
+    }
+
+  offset = ppc_vrreg_offset (tdep, offsets, regnum);
+  if (regnum != tdep->ppc_vrsave_regnum
+      && regnum != tdep->ppc_vrsave_regnum - 1)
+    ppc_supply_reg (regcache, regnum, vrregs, offset, 16);
+  else
+    ppc_supply_reg (regcache, regnum,
+                   vrregs, offset, 4);
+}
+
 /* Collect register REGNUM in the general-purpose register set
    REGSET from register cache REGCACHE into the buffer specified by
    GREGS and LEN.  If REGNUM is -1, do this for all registers in
@@ -603,6 +697,52 @@ ppc_collect_fpregset (const struct regset *regset,
   ppc_collect_reg (regcache, regnum, fpregs, offset,
                   regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
 }
+
+/* Collect register REGNUM in the Altivec register set
+   REGSET from register cache REGCACHE into the buffer specified by
+   VRREGS and LEN.  If REGNUM is -1, do this for all registers in
+   REGSET.  */
+
+void
+ppc_collect_vrregset (const struct regset *regset,
+                     const struct regcache *regcache,
+                     int regnum, void *vrregs, size_t len)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep;
+  const struct ppc_reg_offsets *offsets;
+  size_t offset;
+
+  if (!ppc_altivec_support_p (gdbarch))
+    return;
+
+  tdep = gdbarch_tdep (gdbarch);
+  offsets = regset->descr;
+  if (regnum == -1)
+    {
+      int i;
+
+      for (i = tdep->ppc_vr0_regnum, offset = offsets->vr0_offset;
+          i < tdep->ppc_vr0_regnum + ppc_num_vrs;
+          i++, offset += 16)
+       ppc_collect_reg (regcache, i, vrregs, offset, 16);
+
+      ppc_collect_reg (regcache, (tdep->ppc_vrsave_regnum - 1),
+                      vrregs, offsets->vscr_offset, 4);
+
+      ppc_collect_reg (regcache, tdep->ppc_vrsave_regnum,
+                      vrregs, offsets->vrsave_offset, 4);
+      return;
+    }
+
+  offset = ppc_vrreg_offset (tdep, offsets, regnum);
+  if (regnum != tdep->ppc_vrsave_regnum
+      && regnum != tdep->ppc_vrsave_regnum - 1)
+    ppc_collect_reg (regcache, regnum, vrregs, offset, 16);
+  else
+    ppc_collect_reg (regcache, regnum,
+                   vrregs, offset, 4);
+}
 \f
 
 /* Read a LEN-byte address from debugged memory address MEMADDR. */
@@ -825,12 +965,13 @@ branch_dest (struct frame_info *frame, int opcode, int instr,
 /* Sequence of bytes for breakpoint instruction.  */
 
 const static unsigned char *
-rs6000_breakpoint_from_pc (CORE_ADDR *bp_addr, int *bp_size)
+rs6000_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
+                          int *bp_size)
 {
   static unsigned char big_breakpoint[] = { 0x7d, 0x82, 0x10, 0x08 };
   static unsigned char little_breakpoint[] = { 0x08, 0x10, 0x82, 0x7d };
   *bp_size = 4;
-  if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
+  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
     return big_breakpoint;
   else
     return little_breakpoint;
@@ -939,7 +1080,8 @@ rs6000_software_single_step (struct frame_info *frame)
 {
   CORE_ADDR dummy;
   int breakp_sz;
-  const gdb_byte *breakp = rs6000_breakpoint_from_pc (&dummy, &breakp_sz);
+  const gdb_byte *breakp
+    = rs6000_breakpoint_from_pc (get_frame_arch (frame), &dummy, &breakp_sz);
   int ii, insn;
   CORE_ADDR loc;
   CORE_ADDR breaks[2];
@@ -974,29 +1116,6 @@ rs6000_software_single_step (struct frame_info *frame)
 }
 
 
-/* return pc value after skipping a function prologue and also return
-   information about a function frame.
-
-   in struct rs6000_framedata fdata:
-   - frameless is TRUE, if function does not have a frame.
-   - nosavedpc is TRUE, if function does not save %pc value in its frame.
-   - offset is the initial size of this stack frame --- the amount by
-   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)                                                \
   ((sizeof (short) == 2)                                               \
    ? ((int)(short)(x))                                                 \
@@ -1108,6 +1227,29 @@ bl_to_blrl_insn_p (CORE_ADDR pc, int insn)
   return 0;
 }
 
+/* return pc value after skipping a function prologue and also return
+   information about a function frame.
+
+   in struct rs6000_framedata fdata:
+   - frameless is TRUE, if function does not have a frame.
+   - nosavedpc is TRUE, if function does not save %pc value in its frame.
+   - offset is the initial size of this stack frame --- the amount by
+   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
+ */
+
 static CORE_ADDR
 skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
 {
@@ -2215,9 +2357,9 @@ regsize (const struct reg *reg, int wordsize)
    is an anonymous register.  */
 
 static const char *
-rs6000_register_name (int regno)
+rs6000_register_name (struct gdbarch *gdbarch, int regno)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   /* The upper half "registers" have names in the XML description,
      but we present only the low GPRs and the full 64-bit registers
@@ -2241,7 +2383,7 @@ rs6000_register_name (int regno)
       return spe_regnames[regno - tdep->ppc_ev0_regnum];
     }
 
-  return tdesc_register_name (regno);
+  return tdesc_register_name (gdbarch, regno);
 }
 
 /* Return the GDB type object for the "standard" data type of data in
@@ -2282,9 +2424,10 @@ rs6000_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
    double, we need a conversion if the memory format is float.  */
 
 static int
-rs6000_convert_register_p (int regnum, struct type *type)
+rs6000_convert_register_p (struct gdbarch *gdbarch, int regnum,
+                          struct type *type)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   return (tdep->ppc_fp0_regnum >= 0
          && regnum >= tdep->ppc_fp0_regnum
@@ -2414,9 +2557,9 @@ e500_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
 
 /* Convert a DBX STABS register number to a GDB register number.  */
 static int
-rs6000_stab_reg_to_regnum (int num)
+rs6000_stab_reg_to_regnum (struct gdbarch *gdbarch, int num)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   if (0 <= num && num <= 31)
     return tdep->ppc_gp0_regnum + num;
@@ -2456,9 +2599,9 @@ rs6000_stab_reg_to_regnum (int num)
 
 /* Convert a Dwarf 2 register number to a GDB register number.  */
 static int
-rs6000_dwarf2_reg_to_regnum (int num)
+rs6000_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int num)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   if (0 <= num && num <= 31)
     return tdep->ppc_gp0_regnum + num;
@@ -2947,6 +3090,68 @@ rs6000_frame_base_sniffer (struct frame_info *next_frame)
   return &rs6000_frame_base;
 }
 
+/* DWARF-2 frame support.  Used to handle the detection of
+  clobbered registers during function calls.  */
+
+static void
+ppc_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
+                           struct dwarf2_frame_state_reg *reg,
+                           struct frame_info *next_frame)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* PPC32 and PPC64 ABI's are the same regarding volatile and
+     non-volatile registers.  We will use the same code for both.  */
+
+  /* Call-saved GP registers.  */
+  if ((regnum >= tdep->ppc_gp0_regnum + 14
+      && regnum <= tdep->ppc_gp0_regnum + 31)
+      || (regnum == tdep->ppc_gp0_regnum + 1))
+    reg->how = DWARF2_FRAME_REG_SAME_VALUE;
+
+  /* Call-clobbered GP registers.  */
+  if ((regnum >= tdep->ppc_gp0_regnum + 3
+      && regnum <= tdep->ppc_gp0_regnum + 12)
+      || (regnum == tdep->ppc_gp0_regnum))
+    reg->how = DWARF2_FRAME_REG_UNDEFINED;
+
+  /* Deal with FP registers, if supported.  */
+  if (tdep->ppc_fp0_regnum >= 0)
+    {
+      /* Call-saved FP registers.  */
+      if ((regnum >= tdep->ppc_fp0_regnum + 14
+         && regnum <= tdep->ppc_fp0_regnum + 31))
+       reg->how = DWARF2_FRAME_REG_SAME_VALUE;
+
+      /* Call-clobbered FP registers.  */
+      if ((regnum >= tdep->ppc_fp0_regnum
+         && regnum <= tdep->ppc_fp0_regnum + 13))
+       reg->how = DWARF2_FRAME_REG_UNDEFINED;
+    }
+
+  /* Deal with ALTIVEC registers, if supported.  */
+  if (tdep->ppc_vr0_regnum > 0 && tdep->ppc_vrsave_regnum > 0)
+    {
+      /* Call-saved Altivec registers.  */
+      if ((regnum >= tdep->ppc_vr0_regnum + 20
+         && regnum <= tdep->ppc_vr0_regnum + 31)
+         || regnum == tdep->ppc_vrsave_regnum)
+       reg->how = DWARF2_FRAME_REG_SAME_VALUE;
+
+      /* Call-clobbered Altivec registers.  */
+      if ((regnum >= tdep->ppc_vr0_regnum
+         && regnum <= tdep->ppc_vr0_regnum + 19))
+       reg->how = DWARF2_FRAME_REG_UNDEFINED;
+    }
+
+  /* Handle PC register and Stack Pointer correctly.  */
+  if (regnum == gdbarch_pc_regnum (gdbarch))
+    reg->how = DWARF2_FRAME_REG_RA;
+  else if (regnum == gdbarch_sp_regnum (gdbarch))
+    reg->how = DWARF2_FRAME_REG_CFA;
+}
+
+
 /* 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.
@@ -2965,6 +3170,9 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   bfd abfd;
   int sysv_abi;
   asection *sect;
+  enum auto_boolean soft_float_flag = powerpc_soft_float_global;
+  int soft_float;
+  enum powerpc_vector_abi vector_abi = powerpc_vector_abi_global;
   int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0;
   int tdesc_wordsize = -1;
   const struct target_desc *tdesc = info.target_desc;
@@ -3237,6 +3445,76 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       return NULL;
     }
 
+#ifdef HAVE_ELF
+  if (soft_float_flag == AUTO_BOOLEAN_AUTO && from_elf_exec)
+    {
+      switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU,
+                                       Tag_GNU_Power_ABI_FP))
+       {
+       case 1:
+         soft_float_flag = AUTO_BOOLEAN_FALSE;
+         break;
+       case 2:
+         soft_float_flag = AUTO_BOOLEAN_TRUE;
+         break;
+       default:
+         break;
+       }
+    }
+
+  if (vector_abi == POWERPC_VEC_AUTO && from_elf_exec)
+    {
+      switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU,
+                                       Tag_GNU_Power_ABI_Vector))
+       {
+       case 1:
+         vector_abi = POWERPC_VEC_GENERIC;
+         break;
+       case 2:
+         vector_abi = POWERPC_VEC_ALTIVEC;
+         break;
+       case 3:
+         vector_abi = POWERPC_VEC_SPE;
+         break;
+       default:
+         break;
+       }
+    }
+#endif
+
+  if (soft_float_flag == AUTO_BOOLEAN_TRUE)
+    soft_float = 1;
+  else if (soft_float_flag == AUTO_BOOLEAN_FALSE)
+    soft_float = 0;
+  else
+    soft_float = !have_fpu;
+
+  /* If we have a hard float binary or setting but no floating point
+     registers, downgrade to soft float anyway.  We're still somewhat
+     useful in this scenario.  */
+  if (!soft_float && !have_fpu)
+    soft_float = 1;
+
+  /* Similarly for vector registers.  */
+  if (vector_abi == POWERPC_VEC_ALTIVEC && !have_altivec)
+    vector_abi = POWERPC_VEC_GENERIC;
+
+  if (vector_abi == POWERPC_VEC_SPE && !have_spe)
+    vector_abi = POWERPC_VEC_GENERIC;
+
+  if (vector_abi == POWERPC_VEC_AUTO)
+    {
+      if (have_altivec)
+       vector_abi = POWERPC_VEC_ALTIVEC;
+      else if (have_spe)
+       vector_abi = POWERPC_VEC_SPE;
+      else
+       vector_abi = POWERPC_VEC_GENERIC;
+    }
+
+  /* Do not limit the vector ABI based on available hardware, since we
+     do not yet know what hardware we'll decide we have.  Yuck!  FIXME!  */
+
   /* Find a candidate among extant architectures.  */
   for (arches = gdbarch_list_lookup_by_info (arches, &info);
        arches != NULL;
@@ -3246,6 +3524,10 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
          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->soft_float != soft_float)
+       continue;
+      if (tdep && tdep->vector_abi != vector_abi)
+       continue;
       if (tdep && tdep->wordsize == wordsize)
        {
          if (tdesc_data != NULL)
@@ -3264,6 +3546,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   tdep = XCALLOC (1, struct gdbarch_tdep);
   tdep->wordsize = wordsize;
+  tdep->soft_float = soft_float;
+  tdep->vector_abi = vector_abi;
 
   gdbarch = gdbarch_alloc (&info, tdep);
 
@@ -3371,6 +3655,10 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   set_gdbarch_breakpoint_from_pc (gdbarch, rs6000_breakpoint_from_pc);
 
+  /* The value of symbols of type N_SO and N_FUN maybe null when
+     it shouldn't be. */
+  set_gdbarch_sofun_address_maybe_missing (gdbarch, 1);
+
   /* Handles single stepping of atomic sequences.  */
   set_gdbarch_software_single_step (gdbarch, deal_with_atomic_sequence);
   
@@ -3406,6 +3694,9 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
   dwarf2_frame_set_adjust_regnum (gdbarch, rs6000_adjust_frame_regnum);
 
+  /* Frame handling.  */
+  dwarf2_frame_set_init_reg (gdbarch, ppc_dwarf2_frame_init_reg);
+
   /* Hook in ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
@@ -3456,6 +3747,61 @@ rs6000_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
   /* FIXME: Dump gdbarch_tdep.  */
 }
 
+/* PowerPC-specific commands.  */
+
+static void
+set_powerpc_command (char *args, int from_tty)
+{
+  printf_unfiltered (_("\
+\"set powerpc\" must be followed by an appropriate subcommand.\n"));
+  help_list (setpowerpccmdlist, "set powerpc ", all_commands, gdb_stdout);
+}
+
+static void
+show_powerpc_command (char *args, int from_tty)
+{
+  cmd_show_list (showpowerpccmdlist, from_tty, "");
+}
+
+static void
+powerpc_set_soft_float (char *args, int from_tty,
+                       struct cmd_list_element *c)
+{
+  struct gdbarch_info info;
+
+  /* Update the architecture.  */
+  gdbarch_info_init (&info);
+  if (!gdbarch_update_p (info))
+    internal_error (__FILE__, __LINE__, "could not update architecture");
+}
+
+static void
+powerpc_set_vector_abi (char *args, int from_tty,
+                       struct cmd_list_element *c)
+{
+  struct gdbarch_info info;
+  enum powerpc_vector_abi vector_abi;
+
+  for (vector_abi = POWERPC_VEC_AUTO;
+       vector_abi != POWERPC_VEC_LAST;
+       vector_abi++)
+    if (strcmp (powerpc_vector_abi_string,
+               powerpc_vector_strings[vector_abi]) == 0)
+      {
+       powerpc_vector_abi_global = vector_abi;
+       break;
+      }
+
+  if (vector_abi == POWERPC_VEC_LAST)
+    internal_error (__FILE__, __LINE__, _("Invalid vector ABI accepted: %s."),
+                   powerpc_vector_abi_string);
+
+  /* Update the architecture.  */
+  gdbarch_info_init (&info);
+  if (!gdbarch_update_p (info))
+    internal_error (__FILE__, __LINE__, "could not update architecture");
+}
+
 /* Initialization code.  */
 
 extern initialize_file_ftype _initialize_rs6000_tdep; /* -Wmissing-prototypes */
@@ -3481,4 +3827,30 @@ _initialize_rs6000_tdep (void)
   initialize_tdesc_powerpc_860 ();
   initialize_tdesc_powerpc_e500 ();
   initialize_tdesc_rs6000 ();
+
+  /* Add root prefix command for all "set powerpc"/"show powerpc"
+     commands.  */
+  add_prefix_cmd ("powerpc", no_class, set_powerpc_command,
+                 _("Various PowerPC-specific commands."),
+                 &setpowerpccmdlist, "set powerpc ", 0, &setlist);
+
+  add_prefix_cmd ("powerpc", no_class, show_powerpc_command,
+                 _("Various PowerPC-specific commands."),
+                 &showpowerpccmdlist, "show powerpc ", 0, &showlist);
+
+  /* Add a command to allow the user to force the ABI.  */
+  add_setshow_auto_boolean_cmd ("soft-float", class_support,
+                               &powerpc_soft_float_global,
+                               _("Set whether to use a soft-float ABI."),
+                               _("Show whether to use a soft-float ABI."),
+                               NULL,
+                               powerpc_set_soft_float, NULL,
+                               &setpowerpccmdlist, &showpowerpccmdlist);
+
+  add_setshow_enum_cmd ("vector-abi", class_support, powerpc_vector_strings,
+                       &powerpc_vector_abi_string,
+                       _("Set the vector ABI."),
+                       _("Show the vector ABI."),
+                       NULL, powerpc_set_vector_abi, NULL,
+                       &setpowerpccmdlist, &showpowerpccmdlist);
 }
This page took 0.037205 seconds and 4 git commands to generate.