diff options
author | Ananth N Mavinakayanahalli <ananth@in.ibm.com> | 2007-04-18 01:56:38 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-04-24 07:31:57 -0400 |
commit | 6888199f7fe5ea496f48bb6de67b9b7f05b8071b (patch) | |
tree | 9d276fa0ac794226110b1c4676666f8b0df8650c /arch | |
parent | 5cc5133a29fab993f0b40c03e975bc5458ece507 (diff) |
[POWERPC] Emulate more instructions in software
Emulate a few more instructions in software - especially useful during
singlestepping (xmon/kprobes).
Instructions emulated with this patch are mfcr/mtcr rX, mfxer/mtxer rX,
mflr/mtlr rX, mfctr/mtctr rX and mr rA,rB.
Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/lib/sstep.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 7e8ded051b5b..4aae0c387645 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c | |||
@@ -54,7 +54,7 @@ static int __kprobes branch_taken(unsigned int instr, struct pt_regs *regs) | |||
54 | */ | 54 | */ |
55 | int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | 55 | int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) |
56 | { | 56 | { |
57 | unsigned int opcode, rd; | 57 | unsigned int opcode, rs, rb, rd, spr; |
58 | unsigned long int imm; | 58 | unsigned long int imm; |
59 | 59 | ||
60 | opcode = instr >> 26; | 60 | opcode = instr >> 26; |
@@ -152,6 +152,49 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | |||
152 | regs->nip &= 0xffffffffUL; | 152 | regs->nip &= 0xffffffffUL; |
153 | return 1; | 153 | return 1; |
154 | #endif | 154 | #endif |
155 | case 0x26: /* mfcr */ | ||
156 | regs->gpr[rd] = regs->ccr; | ||
157 | regs->gpr[rd] &= 0xffffffffUL; | ||
158 | goto mtspr_out; | ||
159 | case 0x2a6: /* mfspr */ | ||
160 | spr = (instr >> 11) & 0x3ff; | ||
161 | switch (spr) { | ||
162 | case 0x20: /* mfxer */ | ||
163 | regs->gpr[rd] = regs->xer; | ||
164 | regs->gpr[rd] &= 0xffffffffUL; | ||
165 | goto mtspr_out; | ||
166 | case 0x100: /* mflr */ | ||
167 | regs->gpr[rd] = regs->link; | ||
168 | goto mtspr_out; | ||
169 | case 0x120: /* mfctr */ | ||
170 | regs->gpr[rd] = regs->ctr; | ||
171 | goto mtspr_out; | ||
172 | } | ||
173 | break; | ||
174 | case 0x378: /* orx */ | ||
175 | rs = (instr >> 21) & 0x1f; | ||
176 | rb = (instr >> 11) & 0x1f; | ||
177 | if (rs == rb) { /* mr */ | ||
178 | rd = (instr >> 16) & 0x1f; | ||
179 | regs->gpr[rd] = regs->gpr[rs]; | ||
180 | goto mtspr_out; | ||
181 | } | ||
182 | break; | ||
183 | case 0x3a6: /* mtspr */ | ||
184 | spr = (instr >> 11) & 0x3ff; | ||
185 | switch (spr) { | ||
186 | case 0x20: /* mtxer */ | ||
187 | regs->xer = (regs->gpr[rd] & 0xffffffffUL); | ||
188 | goto mtspr_out; | ||
189 | case 0x100: /* mtlr */ | ||
190 | regs->link = regs->gpr[rd]; | ||
191 | goto mtspr_out; | ||
192 | case 0x120: /* mtctr */ | ||
193 | regs->ctr = regs->gpr[rd]; | ||
194 | mtspr_out: | ||
195 | regs->nip += 4; | ||
196 | return 1; | ||
197 | } | ||
155 | } | 198 | } |
156 | } | 199 | } |
157 | return 0; | 200 | return 0; |