GDBserver
/home/stan/gdb/src/gdb/gdbserver/linux-ppc-low.c
Go to the documentation of this file.
00001 /* GNU/Linux/PowerPC specific low level interface, for the remote server for
00002    GDB.
00003    Copyright (C) 1995-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "server.h"
00021 #include "linux-low.h"
00022 
00023 #include <elf.h>
00024 #include <asm/ptrace.h>
00025 
00026 /* These are in <asm/cputable.h> in current kernels.  */
00027 #define PPC_FEATURE_HAS_VSX             0x00000080
00028 #define PPC_FEATURE_HAS_ALTIVEC         0x10000000
00029 #define PPC_FEATURE_HAS_SPE             0x00800000
00030 #define PPC_FEATURE_CELL                0x00010000
00031 #define PPC_FEATURE_HAS_DFP             0x00000400
00032 
00033 static unsigned long ppc_hwcap;
00034 
00035 
00036 /* Defined in auto-generated file powerpc-32l.c.  */
00037 void init_registers_powerpc_32l (void);
00038 extern const struct target_desc *tdesc_powerpc_32l;
00039 
00040 /* Defined in auto-generated file powerpc-altivec32l.c.  */
00041 void init_registers_powerpc_altivec32l (void);
00042 extern const struct target_desc *tdesc_powerpc_altivec32l;
00043 
00044 /* Defined in auto-generated file powerpc-cell32l.c.  */
00045 void init_registers_powerpc_cell32l (void);
00046 extern const struct target_desc *tdesc_powerpc_cell32l;
00047 
00048 /* Defined in auto-generated file powerpc-vsx32l.c.  */
00049 void init_registers_powerpc_vsx32l (void);
00050 extern const struct target_desc *tdesc_powerpc_vsx32l;
00051 
00052 /* Defined in auto-generated file powerpc-isa205-32l.c.  */
00053 void init_registers_powerpc_isa205_32l (void);
00054 extern const struct target_desc *tdesc_powerpc_isa205_32l;
00055 
00056 /* Defined in auto-generated file powerpc-isa205-altivec32l.c.  */
00057 void init_registers_powerpc_isa205_altivec32l (void);
00058 extern const struct target_desc *tdesc_powerpc_isa205_altivec32l;
00059 
00060 /* Defined in auto-generated file powerpc-isa205-vsx32l.c.  */
00061 void init_registers_powerpc_isa205_vsx32l (void);
00062 extern const struct target_desc *tdesc_powerpc_isa205_vsx32l;
00063 
00064 /* Defined in auto-generated file powerpc-e500l.c.  */
00065 void init_registers_powerpc_e500l (void);
00066 extern const struct target_desc *tdesc_powerpc_e500l;
00067 
00068 /* Defined in auto-generated file powerpc-64l.c.  */
00069 void init_registers_powerpc_64l (void);
00070 extern const struct target_desc *tdesc_powerpc_64l;
00071 
00072 /* Defined in auto-generated file powerpc-altivec64l.c.  */
00073 void init_registers_powerpc_altivec64l (void);
00074 extern const struct target_desc *tdesc_powerpc_altivec64l;
00075 
00076 /* Defined in auto-generated file powerpc-cell64l.c.  */
00077 void init_registers_powerpc_cell64l (void);
00078 extern const struct target_desc *tdesc_powerpc_cell64l;
00079 
00080 /* Defined in auto-generated file powerpc-vsx64l.c.  */
00081 void init_registers_powerpc_vsx64l (void);
00082 extern const struct target_desc *tdesc_powerpc_vsx64l;
00083 
00084 /* Defined in auto-generated file powerpc-isa205-64l.c.  */
00085 void init_registers_powerpc_isa205_64l (void);
00086 extern const struct target_desc *tdesc_powerpc_isa205_64l;
00087 
00088 /* Defined in auto-generated file powerpc-isa205-altivec64l.c.  */
00089 void init_registers_powerpc_isa205_altivec64l (void);
00090 extern const struct target_desc *tdesc_powerpc_isa205_altivec64l;
00091 
00092 /* Defined in auto-generated file powerpc-isa205-vsx64l.c.  */
00093 void init_registers_powerpc_isa205_vsx64l (void);
00094 extern const struct target_desc *tdesc_powerpc_isa205_vsx64l;
00095 
00096 #define ppc_num_regs 73
00097 
00098 /* This sometimes isn't defined.  */
00099 #ifndef PT_ORIG_R3
00100 #define PT_ORIG_R3 34
00101 #endif
00102 #ifndef PT_TRAP
00103 #define PT_TRAP 40
00104 #endif
00105 
00106 #ifdef __powerpc64__
00107 /* We use a constant for FPSCR instead of PT_FPSCR, because
00108    many shipped PPC64 kernels had the wrong value in ptrace.h.  */
00109 static int ppc_regmap[] =
00110  {PT_R0 * 8,     PT_R1 * 8,     PT_R2 * 8,     PT_R3 * 8,
00111   PT_R4 * 8,     PT_R5 * 8,     PT_R6 * 8,     PT_R7 * 8,
00112   PT_R8 * 8,     PT_R9 * 8,     PT_R10 * 8,    PT_R11 * 8,
00113   PT_R12 * 8,    PT_R13 * 8,    PT_R14 * 8,    PT_R15 * 8,
00114   PT_R16 * 8,    PT_R17 * 8,    PT_R18 * 8,    PT_R19 * 8,
00115   PT_R20 * 8,    PT_R21 * 8,    PT_R22 * 8,    PT_R23 * 8,
00116   PT_R24 * 8,    PT_R25 * 8,    PT_R26 * 8,    PT_R27 * 8,
00117   PT_R28 * 8,    PT_R29 * 8,    PT_R30 * 8,    PT_R31 * 8,
00118   PT_FPR0*8,     PT_FPR0*8 + 8, PT_FPR0*8+16,  PT_FPR0*8+24,
00119   PT_FPR0*8+32,  PT_FPR0*8+40,  PT_FPR0*8+48,  PT_FPR0*8+56,
00120   PT_FPR0*8+64,  PT_FPR0*8+72,  PT_FPR0*8+80,  PT_FPR0*8+88,
00121   PT_FPR0*8+96,  PT_FPR0*8+104,  PT_FPR0*8+112,  PT_FPR0*8+120,
00122   PT_FPR0*8+128, PT_FPR0*8+136,  PT_FPR0*8+144,  PT_FPR0*8+152,
00123   PT_FPR0*8+160,  PT_FPR0*8+168,  PT_FPR0*8+176,  PT_FPR0*8+184,
00124   PT_FPR0*8+192,  PT_FPR0*8+200,  PT_FPR0*8+208,  PT_FPR0*8+216,
00125   PT_FPR0*8+224,  PT_FPR0*8+232,  PT_FPR0*8+240,  PT_FPR0*8+248,
00126   PT_NIP * 8,    PT_MSR * 8,    PT_CCR * 8,    PT_LNK * 8,
00127   PT_CTR * 8,    PT_XER * 8,    PT_FPR0*8 + 256,
00128   PT_ORIG_R3 * 8, PT_TRAP * 8 };
00129 #else
00130 /* Currently, don't check/send MQ.  */
00131 static int ppc_regmap[] =
00132  {PT_R0 * 4,     PT_R1 * 4,     PT_R2 * 4,     PT_R3 * 4,
00133   PT_R4 * 4,     PT_R5 * 4,     PT_R6 * 4,     PT_R7 * 4,
00134   PT_R8 * 4,     PT_R9 * 4,     PT_R10 * 4,    PT_R11 * 4,
00135   PT_R12 * 4,    PT_R13 * 4,    PT_R14 * 4,    PT_R15 * 4,
00136   PT_R16 * 4,    PT_R17 * 4,    PT_R18 * 4,    PT_R19 * 4,
00137   PT_R20 * 4,    PT_R21 * 4,    PT_R22 * 4,    PT_R23 * 4,
00138   PT_R24 * 4,    PT_R25 * 4,    PT_R26 * 4,    PT_R27 * 4,
00139   PT_R28 * 4,    PT_R29 * 4,    PT_R30 * 4,    PT_R31 * 4,
00140   PT_FPR0*4,     PT_FPR0*4 + 8, PT_FPR0*4+16,  PT_FPR0*4+24,
00141   PT_FPR0*4+32,  PT_FPR0*4+40,  PT_FPR0*4+48,  PT_FPR0*4+56,
00142   PT_FPR0*4+64,  PT_FPR0*4+72,  PT_FPR0*4+80,  PT_FPR0*4+88,
00143   PT_FPR0*4+96,  PT_FPR0*4+104,  PT_FPR0*4+112,  PT_FPR0*4+120,
00144   PT_FPR0*4+128, PT_FPR0*4+136,  PT_FPR0*4+144,  PT_FPR0*4+152,
00145   PT_FPR0*4+160,  PT_FPR0*4+168,  PT_FPR0*4+176,  PT_FPR0*4+184,
00146   PT_FPR0*4+192,  PT_FPR0*4+200,  PT_FPR0*4+208,  PT_FPR0*4+216,
00147   PT_FPR0*4+224,  PT_FPR0*4+232,  PT_FPR0*4+240,  PT_FPR0*4+248,
00148   PT_NIP * 4,    PT_MSR * 4,    PT_CCR * 4,    PT_LNK * 4,
00149   PT_CTR * 4,    PT_XER * 4,    PT_FPSCR * 4,
00150   PT_ORIG_R3 * 4, PT_TRAP * 4
00151  };
00152 
00153 static int ppc_regmap_e500[] =
00154  {PT_R0 * 4,     PT_R1 * 4,     PT_R2 * 4,     PT_R3 * 4,
00155   PT_R4 * 4,     PT_R5 * 4,     PT_R6 * 4,     PT_R7 * 4,
00156   PT_R8 * 4,     PT_R9 * 4,     PT_R10 * 4,    PT_R11 * 4,
00157   PT_R12 * 4,    PT_R13 * 4,    PT_R14 * 4,    PT_R15 * 4,
00158   PT_R16 * 4,    PT_R17 * 4,    PT_R18 * 4,    PT_R19 * 4,
00159   PT_R20 * 4,    PT_R21 * 4,    PT_R22 * 4,    PT_R23 * 4,
00160   PT_R24 * 4,    PT_R25 * 4,    PT_R26 * 4,    PT_R27 * 4,
00161   PT_R28 * 4,    PT_R29 * 4,    PT_R30 * 4,    PT_R31 * 4,
00162   -1,            -1,            -1,            -1,
00163   -1,            -1,            -1,            -1,
00164   -1,            -1,            -1,            -1,
00165   -1,            -1,            -1,            -1,
00166   -1,            -1,            -1,            -1,
00167   -1,            -1,            -1,            -1,
00168   -1,            -1,            -1,            -1,
00169   -1,            -1,            -1,            -1,
00170   PT_NIP * 4,    PT_MSR * 4,    PT_CCR * 4,    PT_LNK * 4,
00171   PT_CTR * 4,    PT_XER * 4,    -1,
00172   PT_ORIG_R3 * 4, PT_TRAP * 4
00173  };
00174 #endif
00175 
00176 static int
00177 ppc_cannot_store_register (int regno)
00178 {
00179   const struct target_desc *tdesc = current_process ()->tdesc;
00180 
00181 #ifndef __powerpc64__
00182   /* Some kernels do not allow us to store fpscr.  */
00183   if (!(ppc_hwcap & PPC_FEATURE_HAS_SPE)
00184       && regno == find_regno (tdesc, "fpscr"))
00185     return 2;
00186 #endif
00187 
00188   /* Some kernels do not allow us to store orig_r3 or trap.  */
00189   if (regno == find_regno (tdesc, "orig_r3")
00190       || regno == find_regno (tdesc, "trap"))
00191     return 2;
00192 
00193   return 0;
00194 }
00195 
00196 static int
00197 ppc_cannot_fetch_register (int regno)
00198 {
00199   return 0;
00200 }
00201 
00202 static void
00203 ppc_collect_ptrace_register (struct regcache *regcache, int regno, char *buf)
00204 {
00205   int size = register_size (regcache->tdesc, regno);
00206 
00207   memset (buf, 0, sizeof (long));
00208 
00209   if (size < sizeof (long))
00210     collect_register (regcache, regno, buf + sizeof (long) - size);
00211   else
00212     collect_register (regcache, regno, buf);
00213 }
00214 
00215 static void
00216 ppc_supply_ptrace_register (struct regcache *regcache,
00217                             int regno, const char *buf)
00218 {
00219   int size = register_size (regcache->tdesc, regno);
00220   if (size < sizeof (long))
00221     supply_register (regcache, regno, buf + sizeof (long) - size);
00222   else
00223     supply_register (regcache, regno, buf);
00224 }
00225 
00226 
00227 #define INSTR_SC        0x44000002
00228 #define NR_spu_run      0x0116
00229 
00230 /* If the PPU thread is currently stopped on a spu_run system call,
00231    return to FD and ADDR the file handle and NPC parameter address
00232    used with the system call.  Return non-zero if successful.  */
00233 static int
00234 parse_spufs_run (struct regcache *regcache, int *fd, CORE_ADDR *addr)
00235 {
00236   CORE_ADDR curr_pc;
00237   int curr_insn;
00238   int curr_r0;
00239 
00240   if (register_size (regcache->tdesc, 0) == 4)
00241     {
00242       unsigned int pc, r0, r3, r4;
00243       collect_register_by_name (regcache, "pc", &pc);
00244       collect_register_by_name (regcache, "r0", &r0);
00245       collect_register_by_name (regcache, "orig_r3", &r3);
00246       collect_register_by_name (regcache, "r4", &r4);
00247       curr_pc = (CORE_ADDR) pc;
00248       curr_r0 = (int) r0;
00249       *fd = (int) r3;
00250       *addr = (CORE_ADDR) r4;
00251     }
00252   else
00253     {
00254       unsigned long pc, r0, r3, r4;
00255       collect_register_by_name (regcache, "pc", &pc);
00256       collect_register_by_name (regcache, "r0", &r0);
00257       collect_register_by_name (regcache, "orig_r3", &r3);
00258       collect_register_by_name (regcache, "r4", &r4);
00259       curr_pc = (CORE_ADDR) pc;
00260       curr_r0 = (int) r0;
00261       *fd = (int) r3;
00262       *addr = (CORE_ADDR) r4;
00263     }
00264 
00265   /* Fetch instruction preceding current NIP.  */
00266   if ((*the_target->read_memory) (curr_pc - 4,
00267                                   (unsigned char *) &curr_insn, 4) != 0)
00268     return 0;
00269   /* It should be a "sc" instruction.  */
00270   if (curr_insn != INSTR_SC)
00271     return 0;
00272   /* System call number should be NR_spu_run.  */
00273   if (curr_r0 != NR_spu_run)
00274     return 0;
00275 
00276   return 1;
00277 }
00278 
00279 static CORE_ADDR
00280 ppc_get_pc (struct regcache *regcache)
00281 {
00282   CORE_ADDR addr;
00283   int fd;
00284 
00285   if (parse_spufs_run (regcache, &fd, &addr))
00286     {
00287       unsigned int pc;
00288       (*the_target->read_memory) (addr, (unsigned char *) &pc, 4);
00289       return ((CORE_ADDR)1 << 63)
00290         | ((CORE_ADDR)fd << 32) | (CORE_ADDR) (pc - 4);
00291     }
00292   else if (register_size (regcache->tdesc, 0) == 4)
00293     {
00294       unsigned int pc;
00295       collect_register_by_name (regcache, "pc", &pc);
00296       return (CORE_ADDR) pc;
00297     }
00298   else
00299     {
00300       unsigned long pc;
00301       collect_register_by_name (regcache, "pc", &pc);
00302       return (CORE_ADDR) pc;
00303     }
00304 }
00305 
00306 static void
00307 ppc_set_pc (struct regcache *regcache, CORE_ADDR pc)
00308 {
00309   CORE_ADDR addr;
00310   int fd;
00311 
00312   if (parse_spufs_run (regcache, &fd, &addr))
00313     {
00314       unsigned int newpc = pc;
00315       (*the_target->write_memory) (addr, (unsigned char *) &newpc, 4);
00316     }
00317   else if (register_size (regcache->tdesc, 0) == 4)
00318     {
00319       unsigned int newpc = pc;
00320       supply_register_by_name (regcache, "pc", &newpc);
00321     }
00322   else
00323     {
00324       unsigned long newpc = pc;
00325       supply_register_by_name (regcache, "pc", &newpc);
00326     }
00327 }
00328 
00329 
00330 static int
00331 ppc_get_hwcap (unsigned long *valp)
00332 {
00333   const struct target_desc *tdesc = current_process ()->tdesc;
00334   int wordsize = register_size (tdesc, 0);
00335   unsigned char *data = alloca (2 * wordsize);
00336   int offset = 0;
00337 
00338   while ((*the_target->read_auxv) (offset, data, 2 * wordsize) == 2 * wordsize)
00339     {
00340       if (wordsize == 4)
00341         {
00342           unsigned int *data_p = (unsigned int *)data;
00343           if (data_p[0] == AT_HWCAP)
00344             {
00345               *valp = data_p[1];
00346               return 1;
00347             }
00348         }
00349       else
00350         {
00351           unsigned long *data_p = (unsigned long *)data;
00352           if (data_p[0] == AT_HWCAP)
00353             {
00354               *valp = data_p[1];
00355               return 1;
00356             }
00357         }
00358 
00359       offset += 2 * wordsize;
00360     }
00361 
00362   *valp = 0;
00363   return 0;
00364 }
00365 
00366 /* Forward declaration.  */
00367 static struct usrregs_info ppc_usrregs_info;
00368 #ifndef __powerpc64__
00369 static int ppc_regmap_adjusted;
00370 #endif
00371 
00372 static void
00373 ppc_arch_setup (void)
00374 {
00375   const struct target_desc *tdesc;
00376 #ifdef __powerpc64__
00377   long msr;
00378   struct regcache *regcache;
00379 
00380   /* On a 64-bit host, assume 64-bit inferior process with no
00381      AltiVec registers.  Reset ppc_hwcap to ensure that the
00382      collect_register call below does not fail.  */
00383   tdesc = tdesc_powerpc_64l;
00384   current_process ()->tdesc = tdesc;
00385   ppc_hwcap = 0;
00386 
00387   /* Only if the high bit of the MSR is set, we actually have
00388      a 64-bit inferior.  */
00389   regcache = new_register_cache (tdesc);
00390   fetch_inferior_registers (regcache, find_regno (tdesc, "msr"));
00391   collect_register_by_name (regcache, "msr", &msr);
00392   free_register_cache (regcache);
00393   if (msr < 0)
00394     {
00395       ppc_get_hwcap (&ppc_hwcap);
00396       if (ppc_hwcap & PPC_FEATURE_CELL)
00397         tdesc = tdesc_powerpc_cell64l;
00398       else if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
00399         {
00400           /* Power ISA 2.05 (implemented by Power 6 and newer processors)
00401              increases the FPSCR from 32 bits to 64 bits. Even though Power 7
00402              supports this ISA version, it doesn't have PPC_FEATURE_ARCH_2_05
00403              set, only PPC_FEATURE_ARCH_2_06.  Since for now the only bits
00404              used in the higher half of the register are for Decimal Floating
00405              Point, we check if that feature is available to decide the size
00406              of the FPSCR.  */
00407           if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
00408             tdesc = tdesc_powerpc_isa205_vsx64l;
00409           else
00410             tdesc = tdesc_powerpc_vsx64l;
00411         }
00412       else if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
00413         {
00414           if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
00415             tdesc = tdesc_powerpc_isa205_altivec64l;
00416           else
00417             tdesc = tdesc_powerpc_altivec64l;
00418         }
00419 
00420       current_process ()->tdesc = tdesc;
00421       return;
00422     }
00423 #endif
00424 
00425   /* OK, we have a 32-bit inferior.  */
00426   tdesc = tdesc_powerpc_32l;
00427   current_process ()->tdesc = tdesc;
00428 
00429   ppc_get_hwcap (&ppc_hwcap);
00430   if (ppc_hwcap & PPC_FEATURE_CELL)
00431     tdesc = tdesc_powerpc_cell32l;
00432   else if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
00433     {
00434       if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
00435         tdesc = tdesc_powerpc_isa205_vsx32l;
00436       else
00437         tdesc = tdesc_powerpc_vsx32l;
00438     }
00439   else if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
00440     {
00441       if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
00442         tdesc = tdesc_powerpc_isa205_altivec32l;
00443       else
00444         tdesc = tdesc_powerpc_altivec32l;
00445     }
00446 
00447   /* On 32-bit machines, check for SPE registers.
00448      Set the low target's regmap field as appropriately.  */
00449 #ifndef __powerpc64__
00450   if (ppc_hwcap & PPC_FEATURE_HAS_SPE)
00451     tdesc = tdesc_powerpc_e500l;
00452 
00453   if (!ppc_regmap_adjusted)
00454     {
00455       if (ppc_hwcap & PPC_FEATURE_HAS_SPE)
00456         ppc_usrregs_info.regmap = ppc_regmap_e500;
00457 
00458       /* If the FPSCR is 64-bit wide, we need to fetch the whole
00459          64-bit slot and not just its second word.  The PT_FPSCR
00460          supplied in a 32-bit GDB compilation doesn't reflect
00461          this.  */
00462       if (register_size (tdesc, 70) == 8)
00463         ppc_regmap[70] = (48 + 2*32) * sizeof (long);
00464 
00465       ppc_regmap_adjusted = 1;
00466    }
00467 #endif
00468   current_process ()->tdesc = tdesc;
00469 }
00470 
00471 /* Correct in either endianness.
00472    This instruction is "twge r2, r2", which GDB uses as a software
00473    breakpoint.  */
00474 static const unsigned int ppc_breakpoint = 0x7d821008;
00475 #define ppc_breakpoint_len 4
00476 
00477 static int
00478 ppc_breakpoint_at (CORE_ADDR where)
00479 {
00480   unsigned int insn;
00481 
00482   if (where & ((CORE_ADDR)1 << 63))
00483     {
00484       char mem_annex[32];
00485       sprintf (mem_annex, "%d/mem", (int)((where >> 32) & 0x7fffffff));
00486       (*the_target->qxfer_spu) (mem_annex, (unsigned char *) &insn,
00487                                 NULL, where & 0xffffffff, 4);
00488       if (insn == 0x3fff)
00489         return 1;
00490     }
00491   else
00492     {
00493       (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
00494       if (insn == ppc_breakpoint)
00495         return 1;
00496       /* If necessary, recognize more trap instructions here.  GDB only uses
00497          the one.  */
00498     }
00499 
00500   return 0;
00501 }
00502 
00503 /* Provide only a fill function for the general register set.  ps_lgetregs
00504    will use this for NPTL support.  */
00505 
00506 static void ppc_fill_gregset (struct regcache *regcache, void *buf)
00507 {
00508   int i;
00509 
00510   for (i = 0; i < 32; i++)
00511     ppc_collect_ptrace_register (regcache, i, (char *) buf + ppc_regmap[i]);
00512 
00513   for (i = 64; i < 70; i++)
00514     ppc_collect_ptrace_register (regcache, i, (char *) buf + ppc_regmap[i]);
00515 
00516   for (i = 71; i < 73; i++)
00517     ppc_collect_ptrace_register (regcache, i, (char *) buf + ppc_regmap[i]);
00518 }
00519 
00520 #ifndef PTRACE_GETVSXREGS
00521 #define PTRACE_GETVSXREGS 27
00522 #define PTRACE_SETVSXREGS 28
00523 #endif
00524 
00525 #define SIZEOF_VSXREGS 32*8
00526 
00527 static void
00528 ppc_fill_vsxregset (struct regcache *regcache, void *buf)
00529 {
00530   int i, base;
00531   char *regset = buf;
00532 
00533   if (!(ppc_hwcap & PPC_FEATURE_HAS_VSX))
00534     return;
00535 
00536   base = find_regno (regcache->tdesc, "vs0h");
00537   for (i = 0; i < 32; i++)
00538     collect_register (regcache, base + i, &regset[i * 8]);
00539 }
00540 
00541 static void
00542 ppc_store_vsxregset (struct regcache *regcache, const void *buf)
00543 {
00544   int i, base;
00545   const char *regset = buf;
00546 
00547   if (!(ppc_hwcap & PPC_FEATURE_HAS_VSX))
00548     return;
00549 
00550   base = find_regno (regcache->tdesc, "vs0h");
00551   for (i = 0; i < 32; i++)
00552     supply_register (regcache, base + i, &regset[i * 8]);
00553 }
00554 
00555 #ifndef PTRACE_GETVRREGS
00556 #define PTRACE_GETVRREGS 18
00557 #define PTRACE_SETVRREGS 19
00558 #endif
00559 
00560 #define SIZEOF_VRREGS 33*16+4
00561 
00562 static void
00563 ppc_fill_vrregset (struct regcache *regcache, void *buf)
00564 {
00565   int i, base;
00566   char *regset = buf;
00567 
00568   if (!(ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC))
00569     return;
00570 
00571   base = find_regno (regcache->tdesc, "vr0");
00572   for (i = 0; i < 32; i++)
00573     collect_register (regcache, base + i, &regset[i * 16]);
00574 
00575   collect_register_by_name (regcache, "vscr", &regset[32 * 16 + 12]);
00576   collect_register_by_name (regcache, "vrsave", &regset[33 * 16]);
00577 }
00578 
00579 static void
00580 ppc_store_vrregset (struct regcache *regcache, const void *buf)
00581 {
00582   int i, base;
00583   const char *regset = buf;
00584 
00585   if (!(ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC))
00586     return;
00587 
00588   base = find_regno (regcache->tdesc, "vr0");
00589   for (i = 0; i < 32; i++)
00590     supply_register (regcache, base + i, &regset[i * 16]);
00591 
00592   supply_register_by_name (regcache, "vscr", &regset[32 * 16 + 12]);
00593   supply_register_by_name (regcache, "vrsave", &regset[33 * 16]);
00594 }
00595 
00596 #ifndef PTRACE_GETEVRREGS
00597 #define PTRACE_GETEVRREGS       20
00598 #define PTRACE_SETEVRREGS       21
00599 #endif
00600 
00601 struct gdb_evrregset_t
00602 {
00603   unsigned long evr[32];
00604   unsigned long long acc;
00605   unsigned long spefscr;
00606 };
00607 
00608 static void
00609 ppc_fill_evrregset (struct regcache *regcache, void *buf)
00610 {
00611   int i, ev0;
00612   struct gdb_evrregset_t *regset = buf;
00613 
00614   if (!(ppc_hwcap & PPC_FEATURE_HAS_SPE))
00615     return;
00616 
00617   ev0 = find_regno (regcache->tdesc, "ev0h");
00618   for (i = 0; i < 32; i++)
00619     collect_register (regcache, ev0 + i, &regset->evr[i]);
00620 
00621   collect_register_by_name (regcache, "acc", &regset->acc);
00622   collect_register_by_name (regcache, "spefscr", &regset->spefscr);
00623 }
00624 
00625 static void
00626 ppc_store_evrregset (struct regcache *regcache, const void *buf)
00627 {
00628   int i, ev0;
00629   const struct gdb_evrregset_t *regset = buf;
00630 
00631   if (!(ppc_hwcap & PPC_FEATURE_HAS_SPE))
00632     return;
00633 
00634   ev0 = find_regno (regcache->tdesc, "ev0h");
00635   for (i = 0; i < 32; i++)
00636     supply_register (regcache, ev0 + i, &regset->evr[i]);
00637 
00638   supply_register_by_name (regcache, "acc", &regset->acc);
00639   supply_register_by_name (regcache, "spefscr", &regset->spefscr);
00640 }
00641 
00642 static struct regset_info ppc_regsets[] = {
00643   /* List the extra register sets before GENERAL_REGS.  That way we will
00644      fetch them every time, but still fall back to PTRACE_PEEKUSER for the
00645      general registers.  Some kernels support these, but not the newer
00646      PPC_PTRACE_GETREGS.  */
00647   { PTRACE_GETVSXREGS, PTRACE_SETVSXREGS, 0, SIZEOF_VSXREGS, EXTENDED_REGS,
00648   ppc_fill_vsxregset, ppc_store_vsxregset },
00649   { PTRACE_GETVRREGS, PTRACE_SETVRREGS, 0, SIZEOF_VRREGS, EXTENDED_REGS,
00650     ppc_fill_vrregset, ppc_store_vrregset },
00651   { PTRACE_GETEVRREGS, PTRACE_SETEVRREGS, 0, 32 * 4 + 8 + 4, EXTENDED_REGS,
00652     ppc_fill_evrregset, ppc_store_evrregset },
00653   { 0, 0, 0, 0, GENERAL_REGS, ppc_fill_gregset, NULL },
00654   { 0, 0, 0, -1, -1, NULL, NULL }
00655 };
00656 
00657 static struct usrregs_info ppc_usrregs_info =
00658   {
00659     ppc_num_regs,
00660     ppc_regmap,
00661   };
00662 
00663 static struct regsets_info ppc_regsets_info =
00664   {
00665     ppc_regsets, /* regsets */
00666     0, /* num_regsets */
00667     NULL, /* disabled_regsets */
00668   };
00669 
00670 static struct regs_info regs_info =
00671   {
00672     NULL, /* regset_bitmap */
00673     &ppc_usrregs_info,
00674     &ppc_regsets_info
00675   };
00676 
00677 static const struct regs_info *
00678 ppc_regs_info (void)
00679 {
00680   return &regs_info;
00681 }
00682 
00683 struct linux_target_ops the_low_target = {
00684   ppc_arch_setup,
00685   ppc_regs_info,
00686   ppc_cannot_fetch_register,
00687   ppc_cannot_store_register,
00688   NULL, /* fetch_register */
00689   ppc_get_pc,
00690   ppc_set_pc,
00691   (const unsigned char *) &ppc_breakpoint,
00692   ppc_breakpoint_len,
00693   NULL,
00694   0,
00695   ppc_breakpoint_at,
00696   NULL,
00697   NULL,
00698   NULL,
00699   NULL,
00700   ppc_collect_ptrace_register,
00701   ppc_supply_ptrace_register,
00702 };
00703 
00704 void
00705 initialize_low_arch (void)
00706 {
00707   /* Initialize the Linux target descriptions.  */
00708 
00709   init_registers_powerpc_32l ();
00710   init_registers_powerpc_altivec32l ();
00711   init_registers_powerpc_cell32l ();
00712   init_registers_powerpc_vsx32l ();
00713   init_registers_powerpc_isa205_32l ();
00714   init_registers_powerpc_isa205_altivec32l ();
00715   init_registers_powerpc_isa205_vsx32l ();
00716   init_registers_powerpc_e500l ();
00717   init_registers_powerpc_64l ();
00718   init_registers_powerpc_altivec64l ();
00719   init_registers_powerpc_cell64l ();
00720   init_registers_powerpc_vsx64l ();
00721   init_registers_powerpc_isa205_64l ();
00722   init_registers_powerpc_isa205_altivec64l ();
00723   init_registers_powerpc_isa205_vsx64l ();
00724 
00725   initialize_regsets_info (&ppc_regsets_info);
00726 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines