Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:15

0001 /*
0002  * Copyright (c) 2024 Contemporary Software
0003  * All rights reserved.
0004  *
0005  * Redistribution and use in source and binary forms, with or without
0006  * modification, are permitted provided that the following conditions
0007  * are met:
0008  * 1. Redistributions of source code must retain the above copyright
0009  *    notice, this list of conditions and the following disclaimer.
0010  * 2. Redistributions in binary form must reproduce the above copyright
0011  *    notice, this list of conditions and the following disclaimer in the
0012  *    documentation and/or other materials provided with the distribution.
0013  *
0014  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
0015  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0016  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0017  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
0018  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0019  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0020  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0021  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0022  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0023  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0024  * SUCH DAMAGE.
0025  */
0026 
0027 #define TARGET_DEBUG 0
0028 
0029 #ifdef HAVE_CONFIG_H
0030 #include "config.h"
0031 #endif
0032 
0033 #include <errno.h>
0034 #include <inttypes.h>
0035 #include <stdlib.h>
0036 
0037 #include <rtems.h>
0038 #include <rtems/score/threadimpl.h>
0039 
0040 #include "rtems-debugger-target.h"
0041 #include "rtems-debugger-threads.h"
0042 
0043 #include <rtems/powerpc/registers.h>
0044 
0045 /*
0046  * Hardware breakpoints. Limited by hardware
0047  */
0048 #define RTEMS_DEBUGGER_HWBREAK_NUM 4
0049 
0050 /*
0051  * Number of registers.
0052  */
0053 #define RTEMS_DEBUGGER_NUMREGS 72
0054 
0055 /*
0056  * Debugger registers layout.
0057  */
0058 #define REG_R0            0
0059 #define REG_R1            1
0060 #define REG_R2            2
0061 #define REG_R3            3
0062 #define REG_R4            4
0063 #define REG_R5            5
0064 #define REG_R6            6
0065 #define REG_R7            7
0066 #define REG_R8            8
0067 #define REG_R9            9
0068 #define REG_R10          10
0069 #define REG_R11          11
0070 #define REG_R12          12
0071 #define REG_R13          13
0072 #define REG_R14          14
0073 #define REG_R15          15
0074 #define REG_R16          16
0075 #define REG_R17          17
0076 #define REG_R18          18
0077 #define REG_R19          19
0078 #define REG_R20          20
0079 #define REG_R21          21
0080 #define REG_R22          22
0081 #define REG_R23          23
0082 #define REG_R24          24
0083 #define REG_R25          25
0084 #define REG_R26          26
0085 #define REG_R27          27
0086 #define REG_R28          28
0087 #define REG_R29          29
0088 #define REG_R30          30
0089 #define REG_R31          31
0090 #define REG_F0           32
0091 #define REG_F1           33
0092 #define REG_F2           34
0093 #define REG_F3           35
0094 #define REG_F4           36
0095 #define REG_F5           37
0096 #define REG_F6           38
0097 #define REG_F7           39
0098 #define REG_F8           40
0099 #define REG_F9           41
0100 #define REG_F10          42
0101 #define REG_F11          43
0102 #define REG_F12          44
0103 #define REG_F13          45
0104 #define REG_F14          46
0105 #define REG_F15          47
0106 #define REG_F16          48
0107 #define REG_F17          49
0108 #define REG_F18          50
0109 #define REG_F19          51
0110 #define REG_F20          52
0111 #define REG_F21          53
0112 #define REG_F22          54
0113 #define REG_F23          55
0114 #define REG_F24          56
0115 #define REG_F25          57
0116 #define REG_F26          58
0117 #define REG_F27          59
0118 #define REG_F28          60
0119 #define REG_F29          61
0120 #define REG_F30          62
0121 #define REG_F31          63
0122 #define REG_PC           64
0123 #define REG_MSR          65
0124 #define REG_CND          66
0125 #define REG_LR           67
0126 #define REG_CNT          68
0127 #define REG_XER          69
0128 #define REG_ACC          70
0129 #define REG_SPEFSCR      71
0130 
0131 /**
0132  * Register offset table with the total as the last entry.
0133  *
0134  * Check this table in gdb with the command:
0135  *
0136  *   maint print remote-registers
0137  *
0138  * The important column is the Rmt Nr and g/G offset
0139  */
0140 
0141 /*
0142  * MPC604/MPC750
0143  *
0144  * From the MVME2700 executable (main print architecture):
0145  *
0146  *  gdbarch_dump: bfd_arch_info = powerpc:common
0147  *
0148  */
0149 static const size_t ppc_common_reg_offsets[RTEMS_DEBUGGER_NUMREGS + 1] =
0150 {
0151   0,     /* REG_R0      4 uint32_t */
0152   4,     /* REG_R1      4 uint32_t */
0153   8,     /* REG_R2      4 uint32_t */
0154   12,    /* REG_R3      4 uint32_t */
0155   16,    /* REG_R4      4 uint32_t */
0156   20,    /* REG_R5      4 uint32_t */
0157   24,    /* REG_R6      4 uint32_t */
0158   28,    /* REG_R7      4 uint32_t */
0159   32,    /* REG_R8      4 uint32_t */
0160   36,    /* REG_R9      4 uint32_t */
0161   40,    /* REG_R10     4 uint32_t */
0162   44,    /* REG_R11     4 uint32_t */
0163   48,    /* REG_R12     4 uint32_t */
0164   52,    /* REG_R13     4 uint32_t */
0165   56,    /* REG_R14     4 uint32_t */
0166   60,    /* REG_R15     4 uint32_t */
0167   64,    /* REG_R16     4 uint32_t */
0168   68,    /* REG_R17     4 uint32_t */
0169   72,    /* REG_R18     4 uint32_t */
0170   76,    /* REG_R19     4 uint32_t */
0171   80,    /* REG_R20     4 uint32_t */
0172   84,    /* REG_R21     4 uint32_t */
0173   88,    /* REG_R22     4 uint32_t */
0174   92,    /* REG_R23     4 uint32_t */
0175   96,    /* REG_R24     4 uint32_t */
0176   100,   /* REG_R25     4 uint32_t */
0177   104,   /* REG_R26     4 uint32_t */
0178   108,   /* REG_R27     4 uint32_t */
0179   112,   /* REG_R28     4 uint32_t */
0180   116,   /* REG_R29     4 uint32_t */
0181   120,   /* REG_R30     4 uint32_t */
0182   124,   /* REG_R31     4 uint32_t */
0183   128,   /* REG_F0      8 long */
0184   136,   /* REG_F1      8 long */
0185   144,   /* REG_F2      8 long */
0186   152,   /* REG_F3      8 long */
0187   160,   /* REG_F4      8 long */
0188   168,   /* REG_F5      8 long */
0189   176,   /* REG_F6      8 long */
0190   184,   /* REG_F7      8 long */
0191   192,   /* REG_F8      8 long */
0192   200,   /* REG_F9      8 long */
0193   208,   /* REG_F10     8 long */
0194   216,   /* REG_F11     8 long */
0195   224,   /* REG_F12     8 long */
0196   232,   /* REG_F13     8 long */
0197   240,   /* REG_F14     8 long */
0198   248,   /* REG_F15     8 long */
0199   256,   /* REG_F16     8 long */
0200   264,   /* REG_F17     8 long */
0201   272,   /* REG_F18     8 long */
0202   280,   /* REG_F19     8 long */
0203   288,   /* REG_F20     8 long */
0204   296,   /* REG_F21     8 long */
0205   304,   /* REG_F22     8 long */
0206   312,   /* REG_F23     8 long */
0207   320,   /* REG_F24     8 long */
0208   328,   /* REG_F25     8 long */
0209   336,   /* REG_F26     8 long */
0210   344,   /* REG_F27     8 long */
0211   352,   /* REG_F28     8 long */
0212   360,   /* REG_F29     8 long */
0213   368,   /* REG_F30     8 long */
0214   376,   /* REG_F31     8 long */
0215   384,   /* REG_PC      4 *1 */
0216   388,   /* REG_MSR     4 uint32_t */
0217   392,   /* REG_CND     4 uint32_t */
0218   396,   /* REG_LR      4 *1 */
0219   400,   /* REG_CNT     4 uint32_t */
0220   404,   /* REG_XER     4 uint32_t */
0221   408,   /* REG_ACC     no present */
0222   408,   /* REG_SPEFSCR 4 long */
0223   412    /* total size */
0224 };
0225 
0226 /*
0227  * MPC604/MPC750
0228  *
0229  * From the MVME2700 executable:
0230  *
0231  * gdbarch_dump: bfd_arch_info = powerpc:e500
0232  *
0233  * Note:
0234  *  No REG_F?? registers defined. The EV?? registers are defined
0235  *  and can be viewed in GDB with `info all-registers` however
0236  *  there is no remote protocol mapping I can see and the data being
0237  *  display in the EV?? rergisters is an alias of the normal register
0238  *  data.
0239  */
0240 static const size_t ppc_e500_reg_offsets[RTEMS_DEBUGGER_NUMREGS + 1] =
0241 {
0242   0,     /* REG_R0      4 uint32_t */
0243   4,     /* REG_R1      4 uint32_t */
0244   8,     /* REG_R2      4 uint32_t */
0245   12,    /* REG_R3      4 uint32_t */
0246   16,    /* REG_R4      4 uint32_t */
0247   20,    /* REG_R5      4 uint32_t */
0248   24,    /* REG_R6      4 uint32_t */
0249   28,    /* REG_R7      4 uint32_t */
0250   32,    /* REG_R8      4 uint32_t */
0251   36,    /* REG_R9      4 uint32_t */
0252   40,    /* REG_R10     4 uint32_t */
0253   44,    /* REG_R11     4 uint32_t */
0254   48,    /* REG_R12     4 uint32_t */
0255   52,    /* REG_R13     4 uint32_t */
0256   56,    /* REG_R14     4 uint32_t */
0257   60,    /* REG_R15     4 uint32_t */
0258   64,    /* REG_R16     4 uint32_t */
0259   68,    /* REG_R17     4 uint32_t */
0260   72,    /* REG_R18     4 uint32_t */
0261   76,    /* REG_R19     4 uint32_t */
0262   80,    /* REG_R20     4 uint32_t */
0263   84,    /* REG_R21     4 uint32_t */
0264   88,    /* REG_R22     4 uint32_t */
0265   92,    /* REG_R23     4 uint32_t */
0266   96,    /* REG_R24     4 uint32_t */
0267   100,   /* REG_R25     4 uint32_t */
0268   104,   /* REG_R26     4 uint32_t */
0269   108,   /* REG_R27     4 uint32_t */
0270   112,   /* REG_R28     4 uint32_t */
0271   116,   /* REG_R29     4 uint32_t */
0272   120,   /* REG_R30     4 uint32_t */
0273   124,   /* REG_R31     4 uint32_t */
0274   128,   /* REG_F0      4 long */
0275   132,   /* REG_F1      4 long */
0276   136,   /* REG_F2      4 long */
0277   140,   /* REG_F3      4 long */
0278   144,   /* REG_F4      4 long */
0279   148,   /* REG_F5      4 long */
0280   152,   /* REG_F6      4 long */
0281   156,   /* REG_F7      4 long */
0282   160,   /* REG_F8      4 long */
0283   164,   /* REG_F9      4 long */
0284   168,   /* REG_F10     4 long */
0285   172,   /* REG_F11     4 long */
0286   176,   /* REG_F12     4 long */
0287   180,   /* REG_F13     4 long */
0288   184,   /* REG_F14     4 long */
0289   188,   /* REG_F15     4 long */
0290   192,   /* REG_F16     4 long */
0291   196,   /* REG_F17     4 long */
0292   200,   /* REG_F18     4 long */
0293   204,   /* REG_F19     4 long */
0294   208,   /* REG_F20     4 long */
0295   212,   /* REG_F21     4 long */
0296   216,   /* REG_F22     4 long */
0297   220,   /* REG_F23     4 long */
0298   224,   /* REG_F24     4 long */
0299   228,   /* REG_F25     4 long */
0300   232,   /* REG_F26     4 long */
0301   236,   /* REG_F27     4 long */
0302   240,   /* REG_F28     4 long */
0303   244,   /* REG_F29     4 long */
0304   248,   /* REG_F30     4 long */
0305   252,   /* REG_F31     4 long */
0306   256,   /* REG_PC      4 *1 */
0307   260,   /* REG_MSR     4 uint32_t */
0308   264,   /* REG_CND     4 uint32_t */
0309   268,   /* REG_LR      4 *1 */
0310   272,   /* REG_CNT     4 uint32_t */
0311   276,   /* REG_XER     4 uint32_t */
0312   280,   /* REG_ACC     8 long long */
0313   288,   /* REG_SPEFSCR 4 long */
0314   292    /* total size */
0315 };
0316 
0317 static const size_t* ppc_reg_offsets;
0318 
0319 /*
0320  * Number of bytes of registers.
0321  */
0322 #define RTEMS_DEBUGGER_NUMREGBYTES ppc_reg_offsets[RTEMS_DEBUGGER_NUMREGS]
0323 
0324 /*
0325  * Exception handler to hook.
0326  */
0327 typedef CPU_Exception_frame BSP_Exception_frame;
0328 typedef void (*exception_handler_t)(BSP_Exception_frame*);
0329 extern exception_handler_t globalExceptHdl;
0330 
0331 /**
0332  * The `sc` instruction
0333  */
0334 #define TARGET_BKPT 0x0ce00000
0335 static const uint8_t breakpoint[4] = { 0x0c, 0xe0, 0x00, 0x00 };
0336 
0337 /**
0338  * Target lock.
0339  */
0340 RTEMS_INTERRUPT_LOCK_DEFINE(static, target_lock, "target_lock")
0341 
0342 /**
0343  * The orginal exception handler.
0344  */
0345 static void (*orig_currentExcHandler)(CPU_Exception_frame* frame);
0346 
0347 #if TARGET_DEBUG
0348 #include <rtems/bspIo.h>
0349 static void target_printk(const char* format, ...) RTEMS_PRINTFLIKE(1, 2);
0350 static void
0351 target_printk(const char* format, ...)
0352 {
0353   va_list ap;
0354   va_start(ap, format);
0355   vprintk(format, ap);
0356   va_end(ap);
0357 }
0358 #else
0359 #define target_printk(_fmt, ...)
0360 #endif
0361 
0362 /*
0363  * The CPU Ident code is taken from libcpu/cpuIndent.h because
0364  * this cpukit code cannot reach over into the BSP headers.
0365  * Adding the code here is not optimal but it solves the need.
0366  */
0367 #define ASM_RESET_VECTOR                     0x01
0368 #define ASM_MACH_VECTOR                      0x02
0369 #define ASM_PROT_VECTOR                      0x03
0370 #define ASM_ISI_VECTOR                       0x04
0371 #define ASM_EXT_VECTOR                       0x05
0372 #define ASM_ALIGN_VECTOR                     0x06
0373 #define ASM_PROG_VECTOR                      0x07
0374 #define ASM_FLOAT_VECTOR                     0x08
0375 #define ASM_DEC_VECTOR                       0x09
0376 #define ASM_SYS_VECTOR                       0x0C
0377 #define ASM_TRACE_VECTOR                     0x0D
0378 
0379 #define ASM_60X_VEC_VECTOR                   0x0A
0380 #define ASM_60X_PERFMON_VECTOR               0x0F
0381 #define ASM_60X_IMISS_VECTOR                 0x10
0382 #define ASM_60X_DLMISS_VECTOR                0x11
0383 #define ASM_60X_DSMISS_VECTOR                0x12
0384 #define ASM_60X_ADDR_VECTOR                  0x13
0385 #define ASM_60X_SYSMGMT_VECTOR               0x14
0386 #define ASM_60X_VEC_ASSIST_VECTOR            0x16
0387 #define ASM_60X_ITM_VECTOR                   0x17
0388 
0389 #define LAST_VALID_EXC                       0x1F
0390 
0391 typedef enum
0392 {
0393   PPC_601 = 0x1,
0394   PPC_5XX = 0x2,
0395   PPC_603 = 0x3,
0396   PPC_604 = 0x4,
0397   PPC_603e = 0x6,
0398   PPC_603ev = 0x7,
0399   PPC_750 = 0x8,
0400   PPC_750_IBM = 0x7000,
0401   PPC_604e = 0x9,
0402   PPC_604r = 0xA,
0403   PPC_7400 = 0xC,
0404   PPC_405  = 0x2001,  /* Xilinx Virtex-II Pro or -4 */
0405   PPC_405EX = 0x1291,   /* + 405EXr */
0406   PPC_405GP = 0x4011,   /* + 405CR */
0407   PPC_405GPr = 0x5091,
0408   PPC_405EZ = 0x4151,
0409   PPC_405EP = 0x5121,
0410   PPC_440 = 0x7ff2,  /* Xilinx Virtex-5*/
0411   PPC_7455 = 0x8001, /* Kate Feng */
0412   PPC_7457 = 0x8002,
0413   PPC_620 = 0x16,
0414   PPC_860 = 0x50,
0415   PPC_821 = PPC_860,
0416   PPC_823 = PPC_860,
0417   PPC_8260 = 0x81,
0418   PPC_8240 = PPC_8260,
0419   PPC_8245 = 0x8081,
0420   PPC_8540 = 0x8020,
0421   PPC_e500v2 = 0x8021,
0422   PPC_e6500 = 0x8040,
0423   PPC_603le = 0x8082, /* 603le core, in MGT5100 and MPC5200 */
0424   PPC_e300c1  = 0x8083, /* e300c1  core, in MPC83xx*/
0425   PPC_e300c2  = 0x8084, /* e300c2  core */
0426   PPC_e300c3  = 0x8085, /* e300c3  core */
0427   PPC_e200z0  = 0x8170,
0428   PPC_e200z1  = 0x8140,
0429   PPC_e200z4  = 0x8150,
0430   PPC_e200z6  = 0x8110,
0431   PPC_e200z7  = 0x8160,
0432   PPC_PSIM    = 0xfffe,  /* GDB PowerPC simulator -- fake version */
0433   PPC_UNKNOWN = 0xffff
0434 } ppc_cpu_id;
0435 
0436 #define PPC_BOOKE_405   1 /* almost like booke but with some significant differences */
0437 #define PPC_BOOKE_STD   2
0438 #define PPC_BOOKE_E500  3 /* bookE with extensions */
0439 
0440 typedef struct {
0441   volatile bool type_1_complete;
0442   volatile uint32_t msr;
0443 } powerpc_stepping;
0444 
0445 static ppc_cpu_id ppc_cpu;
0446 static int is_bookE;
0447 static powerpc_stepping stepping_instr;
0448 
0449 #define xppc_read_spr(reg, val) \
0450         __asm__ __volatile__("mfspr %0,"#reg : "=r" (val))
0451 #define xppc_write_spr(reg, val) \
0452         __asm__ __volatile__("mtspr "#reg",%0" : : "r" (val))
0453 #define ppc_read_spr(reg, val) xppc_read_spr(reg, val)
0454 #define ppc_write_spr(reg, val) xppc_write_spr(reg, val)
0455 
0456 static const char *ppc_get_cpu_type_name(ppc_cpu_id cpu)
0457 {
0458   switch (cpu) {
0459     case PPC_405:     return "PPC405";
0460     case PPC_405GP:   return "PPC405GP";
0461     case PPC_405EX:   return "PPC405EX";
0462     case PPC_440:     return "PPC440";
0463     case PPC_601:     return "MPC601";
0464     case PPC_5XX:     return "MPC5XX";
0465     case PPC_603:     return "MPC603";
0466     case PPC_603ev:   return "MPC603ev";
0467     case PPC_604:     return "MPC604";
0468     case PPC_750:     return "MPC750";
0469     case PPC_750_IBM: return "IBM PPC750";
0470     case PPC_7400:    return "MPC7400";
0471     case PPC_7455:    return "MPC7455";
0472     case PPC_7457:    return "MPC7457";
0473     case PPC_603le:   return "MPC603le";
0474     case PPC_604e:    return "MPC604e";
0475     case PPC_604r:    return "MPC604r";
0476     case PPC_620:     return "MPC620";
0477     case PPC_860:     return "MPC860";
0478     case PPC_8260:    return "MPC8260";
0479     case PPC_8245:    return "MPC8245";
0480     case PPC_8540:    return "MPC8540";
0481     case PPC_PSIM:    return "PSIM";
0482     case PPC_e200z0:  return "e200z0";
0483     case PPC_e200z1:  return "e200z1";
0484     case PPC_e200z4:  return "e200z4";
0485     case PPC_e200z6:  return "e200z6";
0486     case PPC_e200z7:  return "e200z7";
0487     case PPC_e500v2:  return "e500v2";
0488     case PPC_e6500:   return "e6500";
0489     default:
0490       break;
0491   }
0492   return "unknown";
0493 }
0494 
0495 static bool ppc_is_bookE(void)
0496 {
0497   return is_bookE != 0;
0498 }
0499 
0500 static bool ppc_is_bookE_405(void)
0501 {
0502   return is_bookE == PPC_BOOKE_405;
0503 }
0504 
0505 static int ppc_probe_cpu_type(void)
0506 {
0507   /*
0508    * cpu types listed here have the lowermost nibble as a version identifier
0509    * we will tweak them to the standard version
0510    */
0511   const uint32_t ppc_cpu_id_version_nibble[] = {
0512     PPC_e200z0,
0513     PPC_e200z1,
0514     PPC_e200z4,
0515     PPC_e200z6,
0516     PPC_e200z7
0517   };
0518   #define NUM_CPU_ID_VERSION \
0519     (sizeof(ppc_cpu_id_version_nibble) / sizeof(ppc_cpu_id_version_nibble[0]))
0520 
0521   uint32_t pvr;
0522   int i;
0523 
0524   ppc_read_spr(PPC_PVR, pvr);
0525   pvr >>= 16;
0526 
0527   /*
0528    * apply tweaks to ignore version
0529    */
0530   for (i = 0; i < NUM_CPU_ID_VERSION; ++i) {
0531     if ((pvr & 0xfff0) == (ppc_cpu_id_version_nibble[i] & 0xfff0)) {
0532       pvr = ppc_cpu_id_version_nibble[i];
0533       break;
0534     }
0535   }
0536 
0537   ppc_cpu = (ppc_cpu_id) pvr;
0538 
0539   switch (pvr) {
0540     case PPC_405:
0541     case PPC_405GP:
0542     case PPC_405EX:
0543     case PPC_440:
0544     case PPC_601:
0545     case PPC_5XX:
0546     case PPC_603:
0547     case PPC_603ev:
0548     case PPC_603le:
0549     case PPC_604:
0550     case PPC_604r:
0551     case PPC_750:
0552     case PPC_750_IBM:
0553     case PPC_7400:
0554     case PPC_7455:
0555     case PPC_7457:
0556     case PPC_604e:
0557     case PPC_620:
0558     case PPC_860:
0559     case PPC_8260:
0560     case PPC_8245:
0561     case PPC_PSIM:
0562     case PPC_8540:
0563     case PPC_e200z0:
0564     case PPC_e200z1:
0565     case PPC_e200z4:
0566     case PPC_e200z6:
0567     case PPC_e200z7:
0568     case PPC_e300c1:
0569     case PPC_e300c2:
0570     case PPC_e300c3:
0571     case PPC_e500v2:
0572     case PPC_e6500:
0573       break;
0574     default:
0575       rtems_debugger_printf("rtems-db: powerpc: unknown CPU\n");
0576       return -1;
0577   }
0578 
0579   switch (ppc_cpu) {
0580     case PPC_405:
0581     case PPC_405GP:
0582     case PPC_405EX:
0583       is_bookE = PPC_BOOKE_405;
0584       break;
0585     case PPC_440:
0586       is_bookE = PPC_BOOKE_STD;
0587       break;
0588     case PPC_8540:
0589     case PPC_e200z0:
0590     case PPC_e200z1:
0591     case PPC_e200z4:
0592     case PPC_e200z6:
0593     case PPC_e200z7:
0594     case PPC_e500v2:
0595     case PPC_e6500:
0596       is_bookE = PPC_BOOKE_E500;
0597       break;
0598     default:
0599       break;
0600   }
0601 
0602   rtems_debugger_printf("rtems-db: powerpc: %s %s\n",
0603                         ppc_get_cpu_type_name(ppc_cpu),
0604                         ppc_is_bookE() ? "(book E)" : "");
0605 
0606   return 0;
0607 }
0608 
0609 static void ppc_set_dbsr(uint32_t dbsr)
0610 {
0611   if (ppc_is_bookE()) {
0612     if (ppc_is_bookE_405()) {
0613       ppc_write_spr(0x3f0, dbsr);
0614     } else {
0615       ppc_write_spr(BOOKE_DBSR, dbsr);
0616     }
0617   }
0618 }
0619 
0620 static void ppc_set_dbcr0(uint32_t dbcr)
0621 {
0622   if (ppc_is_bookE()) {
0623     if (ppc_is_bookE_405()) {
0624       ppc_write_spr(0x3f2, dbcr);
0625     } else {
0626       ppc_write_spr(BOOKE_DBCR0, dbcr);
0627     }
0628   }
0629 }
0630 
0631 static int ppc_debug_probe(rtems_debugger_target* target)
0632 {
0633   if (ppc_probe_cpu_type() != 0) {
0634     return -1;
0635   }
0636   ppc_set_dbsr(0xffffffffUL);
0637   ppc_set_dbcr0(0);
0638   return 0;
0639 }
0640 
0641 static int ppc_code_writer(void* address, const void* data, size_t size) {
0642   uint32_t current_level;
0643   uint32_t addr;
0644   uint32_t val;
0645   addr = (uint32_t) (intptr_t) address;
0646   val = *((uint32_t*) data);
0647   target_printk("[] powerpc: code_ writer: %08x -> %p size=%zu\n", val, address, size);
0648   if (size != 4) {
0649     rtems_debugger_printf("rtems-db: powerpc: invalid code write size: size=%zu\n", size);
0650     return -1;
0651   }
0652   /*
0653    * Disable interrupts and MMU to work around write-protection.
0654    *
0655    * This hack is due to the lack of a proper MMU API for the older
0656    * PPC hardware. Normally libdebugger makes the code section
0657    * read/write so breakpoint insertion and removal is fast. The lack
0658    * of a MMU API and the way some of the BSPs MMU is set up means it
0659    * not easy to update the BSPs.
0660    *
0661    * The following is based on Till's `do_patch` implementation.
0662    */
0663   current_level = ppc_interrupt_disable();
0664   asm volatile(
0665     "   mfmsr 0         \n"
0666     "   andc  7,0,%0    \n"
0667     "   mtmsr 7         \n" /* msr is exec. synchronizing; rval access complete */
0668     "   isync           \n" /* context sync.; DR off after this                 */
0669     "   stw   %2,0(%1)  \n"
0670     "   dcbst 0,%1      \n" /* write out data cache line (addr)                 */
0671     "   icbi  0,%1      \n" /* invalidate instr. cache line (addr)              */
0672     "   mtmsr 0         \n" /* msr is exec. synchr.; mem access completed       */
0673     "   sync            \n" /* probably not necessary                           */
0674     "   isync           \n" /* context sync.; MMU on after this                 */
0675     /* add 'key' to input operands to make sure this asm is not
0676      * moved around
0677      */
0678     ::"r"(ppc_is_bookE() ? 0 : MSR_DR), "b"(addr), "r"(val), "r"(current_level)
0679     :"r0","r7");
0680   ppc_interrupt_enable(current_level);
0681   return 0;
0682 }
0683 
0684 int
0685 rtems_debugger_target_configure(rtems_debugger_target* target)
0686 {
0687   if (is_bookE) {
0688     ppc_reg_offsets = ppc_e500_reg_offsets;
0689   } else {
0690     ppc_reg_offsets = ppc_common_reg_offsets;
0691   }
0692   target->capabilities = (RTEMS_DEBUGGER_TARGET_CAP_SWBREAK);
0693   target->reg_num = RTEMS_DEBUGGER_NUMREGS;
0694   target->reg_offset = ppc_reg_offsets;
0695   target->breakpoint = &breakpoint[0];
0696   target->breakpoint_size = sizeof(breakpoint);
0697   target->code_writer = ppc_code_writer;
0698   return ppc_debug_probe(target);
0699 }
0700 
0701 static void powerpc_print_exception_frame(CPU_Exception_frame* frame) {
0702   uintptr_t* gpr;
0703   int r;
0704   target_printk("[} frame = %08" PRIx32 " sig=%d (0x%" PRIx32 ")\n",
0705                 (uint32_t) frame,
0706                 rtems_debugger_target_exception_to_signal(frame),
0707                 frame->_EXC_number);
0708 #ifndef __SPE__
0709   target_printk("[} SRR0 = %08" PRIx32 " SRR1 = %08" PRIx32 "\n",
0710                 frame->EXC_SRR0, frame->EXC_SRR1);
0711 #else
0712   target_printk("[} SRR0 = %08" PRIx32 " SRR1 = %08" PRIx32 \
0713                 " SPEFSCR = %08" PRIx32 " ACC = %08" PRIx32 "\n",
0714                 frame->EXC_SRR0, frame->EXC_SRR1,
0715                 frame->EXC_SPEFSCR, frame->EXC_ACC);
0716 #endif
0717   target_printk("[} LR = %08" PRIx32 " CR = %08" PRIx32 \
0718                 " XER = %08" PRIx32 " CTR = %08" PRIx32 "\n",
0719                 frame->EXC_LR, frame->EXC_CR, frame->EXC_XER, frame->EXC_CTR);
0720   gpr = &frame->GPR0;
0721   for (r= 0; r < 32; r += 4, gpr += 4) {
0722     target_printk("[} R%-2d = %08" PRIx32 " R%-2d = %08" PRIx32 \
0723                   " R%-2d = %08" PRIx32 " R%-2d = %08" PRIx32 "\n",
0724                   r, *gpr, r + 1, *(gpr + 1), r + 2,
0725                   *(gpr + 2), r + 3, *(gpr + 3));
0726   }
0727 }
0728 
0729 /*
0730  * NXP BOOK_EUM.PDF Programmeing Note, Chapter 9 Debug Facilities
0731  *
0732  * There are two classes of debug exception types:
0733  *
0734  *   Type 1: exception before instruction
0735  *      Type 2: exception after instruction
0736  *
0737  * Almost all debug exceptions fall into the first category. That is,
0738  * they all take the interrupt upon encountering an instruction having
0739  * the exception without updating any architectural state (other than
0740  * DBSR, CSRR0, CSRR1, MSR) for that instruction.
0741  *
0742  * The CSRR0 for this type of exception points to the instruction that
0743  * encountered the exception. This includes IAC, DAC, branch taken,
0744  * etc.
0745  *
0746  * The only exception which fall into the second category is the
0747  * instruction complete debug exception. This exception is taken upon
0748  * completing and updating one instruction and then pointing CSRR0 to
0749  * the next instruction to execute.
0750  */
0751 static bool
0752 powerpc_stepping_exception(CPU_Exception_frame* frame)
0753 {
0754   bool r = false;
0755   frame->EXC_SRR1 &= ~MSR_SE;
0756   switch (frame->_EXC_number) {
0757   default:
0758     stepping_instr.type_1_complete = false;
0759     break;
0760   case ASM_TRACE_VECTOR:
0761     if (stepping_instr.type_1_complete) {
0762       /*
0763        * Type 2 exception after instruction
0764        */
0765       stepping_instr.type_1_complete = false;
0766       frame->EXC_SRR1 |= stepping_instr.msr;
0767     } else {
0768       stepping_instr.type_1_complete = true;
0769       frame->EXC_SRR1 &= ~ppc_interrupt_get_disable_mask();
0770       frame->EXC_SRR1 |= MSR_SE;
0771       r = true;
0772     }
0773     break;
0774   case ASM_PROG_VECTOR:
0775     /*
0776      * Breakpoint.
0777      */
0778     break;
0779   }
0780   return r;
0781 }
0782 
0783 static void
0784 powerpc_stepping_frame(CPU_Exception_frame* frame)
0785 {
0786   if (ppc_is_bookE()) {
0787     stepping_instr.type_1_complete = false;
0788   } else {
0789     stepping_instr.type_1_complete = true;
0790   }
0791   stepping_instr.msr =
0792     frame->EXC_SRR1 & ppc_interrupt_get_disable_mask();;
0793   frame->EXC_SRR1 &= ~ppc_interrupt_get_disable_mask();
0794   frame->EXC_SRR1 |= MSR_SE;
0795 }
0796 
0797 static void
0798 target_exception(BSP_Exception_frame* bsp_frame)
0799 {
0800   CPU_Exception_frame* frame = bsp_frame;
0801 
0802   target_printk("[} powerpc target exc: entry\n");
0803   powerpc_print_exception_frame(frame);
0804 
0805   if (!powerpc_stepping_exception(bsp_frame)) {
0806     switch (rtems_debugger_target_exception(frame)) {
0807     case rtems_debugger_target_exc_consumed:
0808     default:
0809       break;
0810     case rtems_debugger_target_exc_step:
0811       powerpc_stepping_frame(frame);
0812       break;
0813     case rtems_debugger_target_exc_cascade:
0814       if (orig_currentExcHandler != NULL) {
0815         orig_currentExcHandler(bsp_frame);
0816       }
0817       break;
0818     }
0819   }
0820 }
0821 
0822 static bool
0823 rtems_debugger_is_int_reg(size_t reg)
0824 {
0825   const size_t size = ppc_reg_offsets[reg + 1] - ppc_reg_offsets[reg];
0826   return size == RTEMS_DEBUGGER_NUMREGBYTES;
0827 }
0828 
0829 static void
0830 rtems_debugger_set_int_reg(rtems_debugger_thread* thread,
0831                            const uintptr_t        reg,
0832                            const uint32_t         value)
0833 {
0834   const size_t offset = ppc_reg_offsets[reg];
0835   /*
0836    * Use memcpy to avoid alignment issues.
0837    */
0838   memcpy(&thread->registers[offset], &value, sizeof(uintptr_t));
0839 }
0840 
0841 static const uintptr_t
0842 rtems_debugger_get_int_reg(rtems_debugger_thread* thread, const size_t reg)
0843 {
0844   const size_t offset = ppc_reg_offsets[reg];
0845   uintptr_t value;
0846   memcpy(&value, &thread->registers[offset], sizeof(uintptr_t));
0847   return value;
0848 }
0849 
0850 static void rtems_debugger_acquire_exc(void) {
0851   if (orig_currentExcHandler == NULL) {
0852     orig_currentExcHandler = globalExceptHdl;
0853     globalExceptHdl = target_exception;
0854   }
0855 }
0856 
0857 static void rtems_debugger_release_exc(void) {
0858   if (orig_currentExcHandler != NULL) {
0859     globalExceptHdl = orig_currentExcHandler;
0860   }
0861 }
0862 
0863 int
0864 rtems_debugger_target_enable(void)
0865 {
0866   target_printk("]] rtems-db: powerpc: %s\n", __func__);
0867   rtems_interrupt_lock_context lock_context;
0868   rtems_interrupt_lock_acquire(&target_lock, &lock_context);
0869   rtems_debugger_acquire_exc();
0870   rtems_interrupt_lock_release(&target_lock, &lock_context);
0871   return 0;
0872 }
0873 
0874 int
0875 rtems_debugger_target_disable(void)
0876 {
0877   target_printk("]] rtems-db: powerpc: %s\n", __func__);
0878   rtems_interrupt_lock_context lock_context;
0879   rtems_interrupt_lock_acquire(&target_lock, &lock_context);
0880   ppc_set_dbsr(0xffffffffUL);
0881   ppc_set_dbcr0(0);
0882   rtems_debugger_release_exc();
0883   rtems_interrupt_lock_release(&target_lock, &lock_context);
0884   return 0;
0885 }
0886 
0887 int
0888 rtems_debugger_target_read_regs(rtems_debugger_thread* thread)
0889 {
0890   target_printk("]] rtems-db: powerpc: %s\n", __func__);
0891   if (!rtems_debugger_thread_flag(thread,
0892                                   RTEMS_DEBUGGER_THREAD_FLAG_REG_VALID)) {
0893     static const uintptr_t good_address = (uintptr_t) &good_address;
0894     size_t i;
0895 
0896     for (i = 0; i < rtems_debugger_target_reg_num(); ++i) {
0897       if (rtems_debugger_is_int_reg(i)) {
0898         rtems_debugger_set_int_reg(thread, i, (uintptr_t) &good_address);
0899       }
0900     }
0901 
0902     if (thread->frame) {
0903       CPU_Exception_frame* frame = thread->frame;
0904       rtems_debugger_set_int_reg(thread, REG_R0, frame->GPR0);
0905       rtems_debugger_set_int_reg(thread, REG_R1, frame->GPR1);
0906       rtems_debugger_set_int_reg(thread, REG_R2, frame->GPR2);
0907       rtems_debugger_set_int_reg(thread, REG_R3, frame->GPR3);
0908       rtems_debugger_set_int_reg(thread, REG_R4, frame->GPR4);
0909       rtems_debugger_set_int_reg(thread, REG_R5, frame->GPR5);
0910       rtems_debugger_set_int_reg(thread, REG_R6, frame->GPR6);
0911       rtems_debugger_set_int_reg(thread, REG_R7, frame->GPR7);
0912       rtems_debugger_set_int_reg(thread, REG_R8, frame->GPR8);
0913       rtems_debugger_set_int_reg(thread, REG_R9, frame->GPR9);
0914       rtems_debugger_set_int_reg(thread, REG_R10, frame->GPR10);
0915       rtems_debugger_set_int_reg(thread, REG_R11, frame->GPR11);
0916       rtems_debugger_set_int_reg(thread, REG_R12, frame->GPR12);
0917       rtems_debugger_set_int_reg(thread, REG_R13, frame->GPR13);
0918       rtems_debugger_set_int_reg(thread, REG_R14, frame->GPR14);
0919       rtems_debugger_set_int_reg(thread, REG_R15, frame->GPR15);
0920       rtems_debugger_set_int_reg(thread, REG_R16, frame->GPR16);
0921       rtems_debugger_set_int_reg(thread, REG_R17, frame->GPR17);
0922       rtems_debugger_set_int_reg(thread, REG_R18, frame->GPR18);
0923       rtems_debugger_set_int_reg(thread, REG_R19, frame->GPR19);
0924       rtems_debugger_set_int_reg(thread, REG_R20, frame->GPR20);
0925       rtems_debugger_set_int_reg(thread, REG_R21, frame->GPR21);
0926       rtems_debugger_set_int_reg(thread, REG_R22, frame->GPR22);
0927       rtems_debugger_set_int_reg(thread, REG_R23, frame->GPR23);
0928       rtems_debugger_set_int_reg(thread, REG_R24, frame->GPR24);
0929       rtems_debugger_set_int_reg(thread, REG_R25, frame->GPR25);
0930       rtems_debugger_set_int_reg(thread, REG_R26, frame->GPR26);
0931       rtems_debugger_set_int_reg(thread, REG_R27, frame->GPR27);
0932       rtems_debugger_set_int_reg(thread, REG_R28, frame->GPR28);
0933       rtems_debugger_set_int_reg(thread, REG_R29, frame->GPR29);
0934       rtems_debugger_set_int_reg(thread, REG_R30, frame->GPR30);
0935       rtems_debugger_set_int_reg(thread, REG_R31, frame->GPR31);
0936 
0937       rtems_debugger_set_int_reg(thread, REG_PC, frame->EXC_SRR0);
0938       rtems_debugger_set_int_reg(thread, REG_MSR, frame->EXC_SRR1);
0939       rtems_debugger_set_int_reg(thread, REG_CND, frame->EXC_CR);
0940       rtems_debugger_set_int_reg(thread, REG_LR, frame->EXC_LR);
0941       rtems_debugger_set_int_reg(thread, REG_CNT, frame->EXC_CTR);
0942       rtems_debugger_set_int_reg(thread, REG_XER, frame->EXC_XER);
0943 
0944       /*
0945        * Get the signal from the frame.
0946        */
0947       thread->signal = rtems_debugger_target_exception_to_signal(frame);
0948     }
0949     else {
0950       ppc_context* thread_ctx = ppc_get_context(&thread->tcb->Registers);
0951       rtems_debugger_set_int_reg(thread, REG_R1,  thread_ctx->gpr1);
0952       rtems_debugger_set_int_reg(thread, REG_R14, thread_ctx->gpr14);
0953       rtems_debugger_set_int_reg(thread, REG_R15, thread_ctx->gpr15);
0954       rtems_debugger_set_int_reg(thread, REG_R16, thread_ctx->gpr16);
0955       rtems_debugger_set_int_reg(thread, REG_R17, thread_ctx->gpr17);
0956       rtems_debugger_set_int_reg(thread, REG_R18, thread_ctx->gpr18);
0957       rtems_debugger_set_int_reg(thread, REG_R19, thread_ctx->gpr19);
0958       rtems_debugger_set_int_reg(thread, REG_R20, thread_ctx->gpr20);
0959       rtems_debugger_set_int_reg(thread, REG_R21, thread_ctx->gpr21);
0960       rtems_debugger_set_int_reg(thread, REG_R22, thread_ctx->gpr22);
0961       rtems_debugger_set_int_reg(thread, REG_R23, thread_ctx->gpr23);
0962       rtems_debugger_set_int_reg(thread, REG_R24, thread_ctx->gpr24);
0963       rtems_debugger_set_int_reg(thread, REG_R25, thread_ctx->gpr25);
0964       rtems_debugger_set_int_reg(thread, REG_R26, thread_ctx->gpr26);
0965       rtems_debugger_set_int_reg(thread, REG_R27, thread_ctx->gpr27);
0966       rtems_debugger_set_int_reg(thread, REG_R28, thread_ctx->gpr28);
0967       rtems_debugger_set_int_reg(thread, REG_R29, thread_ctx->gpr29);
0968       rtems_debugger_set_int_reg(thread, REG_R30, thread_ctx->gpr30);
0969       rtems_debugger_set_int_reg(thread, REG_R31, thread_ctx->gpr31);
0970 
0971       rtems_debugger_set_int_reg(thread, REG_PC, thread_ctx->lr);
0972       rtems_debugger_set_int_reg(thread, REG_MSR, thread_ctx->msr);
0973       rtems_debugger_set_int_reg(thread, REG_CND, thread_ctx->cr);
0974       rtems_debugger_set_int_reg(thread, REG_LR, thread_ctx->lr);
0975       rtems_debugger_set_int_reg(thread, REG_CNT, 0);
0976       rtems_debugger_set_int_reg(thread, REG_XER, 0);
0977       rtems_debugger_set_int_reg(thread, REG_SPEFSCR, 0);
0978 
0979       /*
0980        * Blocked threads have no signal.
0981        */
0982       thread->signal = 0;
0983     }
0984 
0985     thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_REG_VALID;
0986     thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
0987   }
0988 
0989   return 0;
0990 }
0991 
0992 int
0993 rtems_debugger_target_write_regs(rtems_debugger_thread* thread)
0994 {
0995   target_printk("]] rtems-db: powerpc: %s\n", __func__);
0996   if (rtems_debugger_thread_flag(thread,
0997                                  RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY)) {
0998     /*
0999      * Only write to debugger controlled threads. Do not touch the registers
1000      * for threads blocked in the context switcher.
1001      */
1002     if (rtems_debugger_thread_flag(thread,
1003                                    RTEMS_DEBUGGER_THREAD_FLAG_EXCEPTION)) {
1004       CPU_Exception_frame* frame = thread->frame;
1005       frame->GPR0 = rtems_debugger_get_int_reg(thread, REG_R0);
1006       frame->GPR1 = rtems_debugger_get_int_reg(thread, REG_R1);
1007       frame->GPR2 = rtems_debugger_get_int_reg(thread, REG_R2);
1008       frame->GPR3 = rtems_debugger_get_int_reg(thread, REG_R3);
1009       frame->GPR4 = rtems_debugger_get_int_reg(thread, REG_R4);
1010       frame->GPR5 = rtems_debugger_get_int_reg(thread, REG_R5);
1011       frame->GPR6 = rtems_debugger_get_int_reg(thread, REG_R6);
1012       frame->GPR7 = rtems_debugger_get_int_reg(thread, REG_R7);
1013       frame->GPR8 = rtems_debugger_get_int_reg(thread, REG_R8);
1014       frame->GPR9 = rtems_debugger_get_int_reg(thread, REG_R9);
1015       frame->GPR10 = rtems_debugger_get_int_reg(thread, REG_R10);
1016       frame->GPR11 = rtems_debugger_get_int_reg(thread, REG_R11);
1017       frame->GPR12 = rtems_debugger_get_int_reg(thread, REG_R12);
1018       frame->GPR13 = rtems_debugger_get_int_reg(thread, REG_R13);
1019       frame->GPR14 = rtems_debugger_get_int_reg(thread, REG_R14);
1020       frame->GPR15 = rtems_debugger_get_int_reg(thread, REG_R15);
1021       frame->GPR16 = rtems_debugger_get_int_reg(thread, REG_R16);
1022       frame->GPR17 = rtems_debugger_get_int_reg(thread, REG_R17);
1023       frame->GPR18 = rtems_debugger_get_int_reg(thread, REG_R18);
1024       frame->GPR19 = rtems_debugger_get_int_reg(thread, REG_R19);
1025       frame->GPR20 = rtems_debugger_get_int_reg(thread, REG_R20);
1026       frame->GPR21 = rtems_debugger_get_int_reg(thread, REG_R21);
1027       frame->GPR22 = rtems_debugger_get_int_reg(thread, REG_R22);
1028       frame->GPR23 = rtems_debugger_get_int_reg(thread, REG_R23);
1029       frame->GPR24 = rtems_debugger_get_int_reg(thread, REG_R24);
1030       frame->GPR25 = rtems_debugger_get_int_reg(thread, REG_R25);
1031       frame->GPR26 = rtems_debugger_get_int_reg(thread, REG_R26);
1032       frame->GPR27 = rtems_debugger_get_int_reg(thread, REG_R27);
1033       frame->GPR28 = rtems_debugger_get_int_reg(thread, REG_R28);
1034       frame->GPR29 = rtems_debugger_get_int_reg(thread, REG_R29);
1035       frame->GPR30 = rtems_debugger_get_int_reg(thread, REG_R30);
1036       frame->GPR31 = rtems_debugger_get_int_reg(thread, REG_R31);
1037 
1038       frame->EXC_SRR0 = rtems_debugger_get_int_reg(thread, REG_PC);
1039       frame->EXC_SRR1 = rtems_debugger_get_int_reg(thread, REG_MSR);
1040       frame->EXC_CR = rtems_debugger_get_int_reg(thread, REG_CND);
1041       frame->EXC_LR = rtems_debugger_get_int_reg(thread, REG_LR);
1042       frame->EXC_CTR = rtems_debugger_get_int_reg(thread, REG_CNT);
1043       frame->EXC_XER = rtems_debugger_get_int_reg(thread, REG_XER);
1044     }
1045     thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
1046   }
1047   return 0;
1048 }
1049 
1050 uintptr_t
1051 rtems_debugger_target_reg_pc(rtems_debugger_thread* thread)
1052 {
1053   int r;
1054   r = rtems_debugger_target_read_regs(thread);
1055   if (r >= 0) {
1056     return rtems_debugger_get_int_reg(thread, REG_PC);
1057   }
1058   return 0;
1059 }
1060 
1061 uintptr_t
1062 rtems_debugger_target_frame_pc(CPU_Exception_frame* frame)
1063 {
1064   return (uintptr_t) frame->EXC_SRR0;
1065 }
1066 
1067 uintptr_t
1068 rtems_debugger_target_reg_sp(rtems_debugger_thread* thread)
1069 {
1070   int r;
1071   r = rtems_debugger_target_read_regs(thread);
1072   if (r >= 0) {
1073     return rtems_debugger_get_int_reg(thread, REG_R1);
1074   }
1075   return 0;
1076 }
1077 
1078 uintptr_t
1079 rtems_debugger_target_tcb_sp(rtems_debugger_thread* thread)
1080 {
1081   ppc_context* thread_ctx = ppc_get_context(&thread->tcb->Registers);
1082   return (DB_UINT) thread_ctx->gpr1;
1083 }
1084 
1085 int
1086 rtems_debugger_target_thread_stepping(rtems_debugger_thread* thread)
1087 {
1088   target_printk("]] rtems-db: powerpc: %s\n", __func__);
1089   if (rtems_debugger_thread_flag(thread,
1090                                  RTEMS_DEBUGGER_THREAD_FLAG_STEP_INSTR)) {
1091     CPU_Exception_frame* frame = thread->frame;
1092     /*
1093      * There maybe no frame, ie connect and then enter `si`
1094      */
1095     if (frame != NULL) {
1096       /*
1097        * Single step instructions with interrupts masked to avoid
1098        * stepping into an interrupt handler.
1099        */
1100       if ((frame->EXC_SRR1 & MSR_EE) == 0) {
1101         thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_INTS_DISABLED;
1102       }
1103       powerpc_stepping_frame(frame);
1104     }
1105   }
1106   return 0;
1107 }
1108 
1109 int
1110 rtems_debugger_target_exception_to_signal(CPU_Exception_frame* frame)
1111 {
1112   int sig = RTEMS_DEBUGGER_SIGNAL_HUP;
1113   switch (frame->_EXC_number) {
1114   case ASM_MACH_VECTOR:
1115     sig = RTEMS_DEBUGGER_SIGNAL_BUS;
1116     break;
1117   case ASM_PROT_VECTOR:
1118   case ASM_ISI_VECTOR:
1119   case ASM_ALIGN_VECTOR:
1120   case ASM_60X_IMISS_VECTOR:
1121   case ASM_60X_DLMISS_VECTOR:
1122   case ASM_60X_DSMISS_VECTOR:
1123     sig = RTEMS_DEBUGGER_SIGNAL_SEGV;
1124     break;
1125   case ASM_PROG_VECTOR:
1126     sig = RTEMS_DEBUGGER_SIGNAL_TRAP;
1127     break;
1128   case ASM_FLOAT_VECTOR:
1129     sig = RTEMS_DEBUGGER_SIGNAL_FPE;
1130     break;
1131   case ASM_DEC_VECTOR:
1132     sig = RTEMS_DEBUGGER_SIGNAL_ALRM;
1133     break;
1134   case ASM_SYS_VECTOR:
1135   case ASM_TRACE_VECTOR:
1136     sig = RTEMS_DEBUGGER_SIGNAL_TRAP;
1137     break;
1138   default:
1139     break;
1140   }
1141   return sig;
1142 }
1143 
1144 void
1145 rtems_debugger_target_exception_print(CPU_Exception_frame* frame)
1146 {
1147   uintptr_t* gpr = &frame->GPR0;
1148   int r = 0;
1149 #ifndef __SPE__
1150   rtems_debugger_printf("SRR0 = %08" PRIx32 " SRR1 = %08" PRIx32 "\n",
1151                         frame->EXC_SRR0, frame->EXC_SRR1);
1152 #else
1153   rtems_debugger_printf("SRR0 = %08" PRIx32 " SRR1 = %08" PRIx32 \
1154                         " SPEFSCR = %08" PRIx32 " ACC = %08" PRIx32 "\n",
1155                         frame->EXC_SRR0, frame->EXC_SRR1,
1156                         frame->EXC_SPEFSCR, frame->EXC_ACC);
1157 #endif
1158   rtems_debugger_printf("LR = %08" PRIx32 " CR = %08" PRIx32 \
1159                         " XER = %08" PRIx32 " CTR = %08" PRIx32 "\n",
1160                         frame->EXC_LR, frame->EXC_CR,
1161                         frame->EXC_XER, frame->EXC_CTR);
1162   gpr = &frame->GPR0;
1163   for (r= 0; r < 32; r += 4, gpr += 4) {
1164     rtems_debugger_printf("R%-2d = %08" PRIx32 " R%-2d = %08" PRIx32     \
1165                   " R%-2d = %08" PRIx32 " R%-2d = %08" PRIx32 "\n",
1166                   r, *gpr, r + 1, *(gpr + 1), r + 2,
1167                   *(gpr + 2), r + 3, *(gpr + 3));
1168   }
1169 }
1170 
1171 int
1172 rtems_debugger_target_hwbreak_insert(void)
1173 {
1174   target_printk("]] rtems-db: powerpc: %s\n", __func__);
1175   /*
1176    * Do nothing, load on exit of the exception handler.
1177    */
1178   return 0;
1179 }
1180 
1181 int
1182 rtems_debugger_target_hwbreak_remove(void)
1183 {
1184   target_printk("]] rtems-db: powerpc: %s\n", __func__);
1185   return 0;
1186 }
1187 
1188 int
1189 rtems_debugger_target_hwbreak_control(rtems_debugger_target_watchpoint wp,
1190                                       bool                             insert,
1191                                       uintptr_t                        addr,
1192                                       DB_UINT                          kind)
1193 {
1194   target_printk("]] rtems-db: powerpc: %s\n", __func__);
1195   /*
1196    * To do.
1197    */
1198   return 0;
1199 }
1200 
1201 int
1202 rtems_debugger_target_cache_sync(rtems_debugger_target_swbreak* swbreak)
1203 {
1204   /*
1205    * Flush the data cache and invalidate the instruction cache.
1206    */
1207   rtems_cache_flush_multiple_data_lines(
1208     swbreak->address,
1209     sizeof( breakpoint )
1210   );
1211   rtems_cache_instruction_sync_after_code_change(
1212     swbreak->address,
1213     sizeof( breakpoint )
1214   );
1215   return 0;
1216 }