7 #include <asm/ptrace.h>
8 #include <asm/uaccess.h>
15 val = *(
unsigned long *)(®s->
r0 + nr);
17 val = *(
unsigned long *)(®s->
r4 + (nr - 4));
19 val = *(
unsigned long *)(®s->
r7 + (nr - 7));
21 val = *(
unsigned long *)(®s->
fp + (nr - 13));
26 static void set_reg(
struct pt_regs *regs,
int nr,
int val)
29 *(
unsigned long *)(®s->
r0 + nr) =
val;
31 *(
unsigned long *)(®s->
r4 + (nr - 4)) = val;
33 *(
unsigned long *)(®s->
r7 + (nr - 7)) = val;
35 *(
unsigned long *)(®s->
fp + (nr - 13)) = val;
38 #define REG1(insn) (((insn) & 0x0f00) >> 8)
39 #define REG2(insn) ((insn) & 0x000f)
43 #define ISA_LD1 0x20c0
44 #define ISA_LD2 0x20e0
45 #define ISA_LDH 0x20a0
46 #define ISA_LDUH 0x20b0
47 #define ISA_ST1 0x2040
48 #define ISA_ST2 0x2060
49 #define ISA_ST3 0x2070
50 #define ISA_STH1 0x2020
51 #define ISA_STH2 0x2030
53 #ifdef CONFIG_ISA_DUAL_ISSUE
56 #define ISA_ADD 0x00a0
57 #define ISA_ADDI 0x4000
58 #define ISA_ADDX 0x0090
59 #define ISA_AND 0x00c0
60 #define ISA_CMP 0x0040
61 #define ISA_CMPEQ 0x0060
62 #define ISA_CMPU 0x0050
63 #define ISA_CMPZ 0x0070
64 #define ISA_LDI 0x6000
66 #define ISA_NEG 0x0030
67 #define ISA_NOP 0x7000
68 #define ISA_NOT 0x00b0
70 #define ISA_SUB 0x0020
71 #define ISA_SUBX 0x0010
72 #define ISA_XOR 0x00d0
75 #define ISA_MUL 0x1060
76 #define ISA_MULLO_A0 0x3010
77 #define ISA_MULLO_A1 0x3090
78 #define ISA_MVFACMI_A0 0x50f2
79 #define ISA_MVFACMI_A1 0x50f6
81 static int emu_addi(
unsigned short insn,
struct pt_regs *regs)
83 char imm = (
char)(insn & 0xff);
89 set_reg(regs, dest, val);
94 static int emu_ldi(
unsigned short insn,
struct pt_regs *regs)
96 char imm = (
char)(insn & 0xff);
98 set_reg(regs,
REG1(insn), (
int)imm);
103 static int emu_add(
unsigned short insn,
struct pt_regs *regs)
111 set_reg(regs, dest, val);
116 static int emu_addx(
unsigned short insn,
struct pt_regs *regs)
125 set_reg(regs, dest, val);
136 static int emu_and(
unsigned short insn,
struct pt_regs *regs)
138 int dest =
REG1(insn);
143 set_reg(regs, dest, val);
148 static int emu_cmp(
unsigned short insn,
struct pt_regs *regs)
158 static int emu_cmpeq(
unsigned short insn,
struct pt_regs *regs)
168 static int emu_cmpu(
unsigned short insn,
struct pt_regs *regs)
179 static int emu_cmpz(
unsigned short insn,
struct pt_regs *regs)
189 static int emu_mv(
unsigned short insn,
struct pt_regs *regs)
194 set_reg(regs,
REG1(insn), val);
199 static int emu_neg(
unsigned short insn,
struct pt_regs *regs)
204 set_reg(regs,
REG1(insn), 0 - val);
209 static int emu_not(
unsigned short insn,
struct pt_regs *regs)
214 set_reg(regs,
REG1(insn), ~val);
219 static int emu_or(
unsigned short insn,
struct pt_regs *regs)
221 int dest =
REG1(insn);
226 set_reg(regs, dest, val);
231 static int emu_sub(
unsigned short insn,
struct pt_regs *regs)
233 int dest =
REG1(insn);
238 set_reg(regs, dest, val);
243 static int emu_subx(
unsigned short insn,
struct pt_regs *regs)
245 int dest =
REG1(insn);
248 val = tmp =
get_reg(regs, dest);
251 set_reg(regs, dest, val);
262 static int emu_xor(
unsigned short insn,
struct pt_regs *regs)
264 int dest =
REG1(insn);
269 set_reg(regs, dest, val);
274 static int emu_mul(
unsigned short insn,
struct pt_regs *regs)
276 int dest =
REG1(insn);
284 :
"+r" (reg1) :
"r" (reg2)
287 set_reg(regs, dest, reg1);
292 static int emu_mullo_a0(
unsigned short insn,
struct pt_regs *regs)
300 "mullo %0, %1, a0; \n\t"
301 "mvfachi %0, a0; \n\t"
302 "mvfaclo %1, a0; \n\t"
303 :
"+r" (reg1),
"+r" (reg2)
312 static int emu_mullo_a1(
unsigned short insn,
struct pt_regs *regs)
320 "mullo %0, %1, a0; \n\t"
321 "mvfachi %0, a0; \n\t"
322 "mvfaclo %1, a0; \n\t"
323 :
"+r" (reg1),
"+r" (reg2)
332 static int emu_mvfacmi_a0(
unsigned short insn,
struct pt_regs *regs)
336 val = (regs->
acc0h << 16) | (regs->
acc0l >> 16);
337 set_reg(regs,
REG1(insn), (
int)val);
342 static int emu_mvfacmi_a1(
unsigned short insn,
struct pt_regs *regs)
346 val = (regs->
acc1h << 16) | (regs->
acc1l >> 16);
347 set_reg(regs,
REG1(insn), (
int)val);
352 static int emu_m32r2(
unsigned short insn,
struct pt_regs *regs)
356 if ((insn & 0x7fff) == ISA_NOP)
359 switch(insn & 0x7000) {
361 res = emu_addi(insn, regs);
364 res = emu_ldi(insn, regs);
373 switch(insn & 0x70f0) {
375 res = emu_add(insn, regs);
378 res = emu_addx(insn, regs);
381 res = emu_and(insn, regs);
384 res = emu_cmp(insn, regs);
387 res = emu_cmpeq(insn, regs);
390 res = emu_cmpu(insn, regs);
393 res = emu_cmpz(insn, regs);
396 res = emu_mv(insn, regs);
399 res = emu_neg(insn, regs);
402 res = emu_not(insn, regs);
405 res = emu_or(insn, regs);
408 res = emu_sub(insn, regs);
411 res = emu_subx(insn, regs);
414 res = emu_xor(insn, regs);
417 res = emu_mul(insn, regs);
420 res = emu_mullo_a0(insn, regs);
423 res = emu_mullo_a1(insn, regs);
432 switch(insn & 0x70ff) {
434 res = emu_mvfacmi_a0(insn, regs);
437 res = emu_mvfacmi_a1(insn, regs);
459 static int insn_check(
unsigned long insn,
struct pt_regs *regs,
469 if (insn & 0x80000000) {
470 *ucp += (
short)(insn & 0x0000ffff);
473 #ifdef CONFIG_ISA_DUAL_ISSUE
475 if (!(regs->
bpc & 0x2) && insn & 0x8000) {
476 res = emu_m32r2((
unsigned short)insn, regs);
486 static int emu_ld(
unsigned long insn32,
struct pt_regs *regs)
490 unsigned short insn16;
493 insn16 = insn32 >> 16;
495 ucp = (
unsigned char *)
get_reg(regs, src);
497 if (insn_check(insn32, regs, &ucp))
500 size = insn16 & 0x0040 ? 4 : 2;
508 if ((insn16 & 0x00f0) == 0x00a0 && (val & 0x8000))
511 set_reg(regs,
REG1(insn16), val);
514 if ((insn16 & 0xf0f0) ==
ISA_LD2)
515 set_reg(regs, src, (
unsigned long)(ucp + 4));
520 static int emu_st(
unsigned long insn32,
struct pt_regs *regs)
524 unsigned short insn16;
527 insn16 = insn32 >> 16;
530 ucp = (
unsigned char *)
get_reg(regs, src2);
532 if (insn_check(insn32, regs, &ucp))
535 size = insn16 & 0x0040 ? 4 : 2;
541 if ((insn16 & 0xf0e0) == 0x2060) {
547 set_reg(regs, src2, (
unsigned long)ucp);
554 if ((insn16 & 0xf0f0) ==
ISA_STH2) {
556 set_reg(regs, src2, (
unsigned long)ucp);
564 unsigned short insn16;
567 insn16 = insn32 >> 16;
570 if ((insn16 & 0x7000) != 0x2000)
574 if ((insn16 & 0x8000) && (regs->
bpc & 3))
578 res = emu_ld(insn32, regs);
580 res = emu_st(insn32, regs);