Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Ananth N Mavinakayanahalli and committed by
Paul Mackerras
6888199f 5cc5133a

+44 -1
+44 -1
arch/powerpc/lib/sstep.c
··· 54 54 */ 55 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 58 unsigned long int imm; 59 59 60 60 opcode = instr >> 26; ··· 152 152 regs->nip &= 0xffffffffUL; 153 153 return 1; 154 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 200 return 0;