diff options
author | Nicholas Piggin <npiggin@gmail.com> | 2018-09-09 16:18:58 +1000 |
---|---|---|
committer | Alistair Popple <alistair@popple.id.au> | 2018-09-20 11:40:28 +1000 |
commit | b3f67cfb3b05329d84f97abeae5749b03740369f (patch) | |
tree | 822c23ad743c809c84b0f74af909eabd19b7cc45 /libpdbg/chip.c | |
parent | e7225ecbe7fc0235ce00328c4e848012a1438f7f (diff) | |
download | pdbg-b3f67cfb3b05329d84f97abeae5749b03740369f.tar.gz pdbg-b3f67cfb3b05329d84f97abeae5749b03740369f.zip |
libpdbg/chip: implement putnia with a sequence compatible with P9
P9 MTNIA uses LR as the source register, so set LR as well as GPR0.
This will work on P8 and P9. This is a bit ugly, but it will work
until we have general getspr/putspr calls for target backends.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Tested-by: Rashmica Gupta <rashmica.g@gmail.com>
Diffstat (limited to 'libpdbg/chip.c')
-rw-r--r-- | libpdbg/chip.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/libpdbg/chip.c b/libpdbg/chip.c index 7a93ab6..93eb3f0 100644 --- a/libpdbg/chip.c +++ b/libpdbg/chip.c @@ -159,8 +159,8 @@ int ram_sreset_thread(struct pdbg_target *thread_target) * into *results. *results must point to an array the same size as * *opcodes. Each entry from *results is put into SCR0 prior to * executing an opcode so that it may also be used to pass in - * data. Note that only register r0 is saved and restored so opcodes - * must not touch other registers. + * data. Note that only registers r0 and r1 are saved and restored so + * opcode sequences must preserve other registers. */ int ram_instructions(struct pdbg_target *thread_target, uint64_t *opcodes, uint64_t *results, int len, unsigned int lpar) @@ -257,10 +257,21 @@ int ram_getnia(struct pdbg_target *thread, uint64_t *value) return 0; } +/* + * P9 must MTNIA from LR, P8 can MTNIA from R0. So we set both LR and R0 + * to value. LR must be saved and restored. + * + * This is a hack and should be made much cleaner once we have target + * specific putspr commands. + */ int ram_putnia(struct pdbg_target *thread, uint64_t value) { - uint64_t opcodes[] = {mfspr(0, 277), mtnia(0)}; - uint64_t results[] = {value, 0}; + uint64_t opcodes[] = { mfspr(1, 8), /* mflr r1 */ + mfspr(0, 277), /* value -> r0 */ + mtspr(8, 0), /* mtlr r0 */ + mtnia(0), + mtspr(8, 1), }; /* mtlr r1 */ + uint64_t results[] = {0, value, 0, 0, 0}; CHECK_ERR(ram_instructions(thread, opcodes, results, ARRAY_SIZE(opcodes), 0)); return 0; |