20 #include <linux/kernel.h>
22 #include <asm/processor.h>
23 #include <asm/uaccess.h>
24 #include <asm/cache.h>
25 #include <asm/cputable.h>
27 #include <asm/switch_to.h>
34 #define IS_XFORM(inst) (((inst) >> 26) == 31)
35 #define IS_DSFORM(inst) (((inst) >> 26) >= 56)
37 #define INVALID { 0, 0 }
57 #define SWAP(a, b) (t = (a), (a) = (b), (b) = t)
199 static inline unsigned make_dsisr(
unsigned instr)
205 dsisr = (instr & 0x03ff0000) >> 16;
209 dsisr |= (instr & 0x00000006) << 14;
211 dsisr |= (instr & 0x00000040) << 8;
213 dsisr |= (instr & 0x00000780) << 3;
216 dsisr |= (instr & 0x04000000) >> 12;
218 dsisr |= (instr & 0x78000000) >> 17;
221 dsisr |= (instr & 0x00000003) << 18;
234 static int emulate_dcbz(
struct pt_regs *
regs,
unsigned char __user *
addr)
247 for (i = 0; i < size /
sizeof(
long); ++
i)
248 if (__put_user_inatomic(0, p+i))
260 #define REG_BYTE(rp, i) *((u8 *)((rp) + ((i) >> 2)) + ((i) & 3) + 4)
262 #define REG_BYTE(rp, i) *((u8 *)(rp) + (i))
265 #define SWIZ_PTR(p) ((unsigned char __user *)((p) ^ swiz))
267 static int emulate_multiple(
struct pt_regs *regs,
unsigned char __user *addr,
268 unsigned int reg,
unsigned int nb,
269 unsigned int flags,
unsigned int instr,
273 unsigned int nb0,
i, bswiz;
289 nb = regs->
xer & 127;
293 unsigned long pc = regs->
nip ^ (swiz & 4);
295 if (__get_user_inatomic(instr,
296 (
unsigned int __user *)pc))
298 if (swiz == 0 && (flags &
SW))
300 nb = (instr >> 11) & 0x1f;
304 if (nb + reg * 4 > 128) {
305 nb0 = nb + reg * 4 - 128;
317 p = (
unsigned long) addr;
318 bswiz = (flags &
SW)? 3: 0;
326 memset(rptr, 0, ((nb + 3) / 4) *
sizeof(
unsigned long));
329 ((nb0 + 3) / 4) *
sizeof(
unsigned long));
331 for (i = 0; i < nb; ++
i, ++
p)
332 if (__get_user_inatomic(
REG_BYTE(rptr, i ^ bswiz),
336 rptr = ®s->
gpr[0];
338 for (i = 0; i < nb0; ++
i, ++
p)
339 if (__get_user_inatomic(
REG_BYTE(rptr,
346 for (i = 0; i < nb; ++
i, ++
p)
347 if (__put_user_inatomic(
REG_BYTE(rptr, i ^ bswiz),
351 rptr = ®s->
gpr[0];
353 for (i = 0; i < nb0; ++
i, ++
p)
354 if (__put_user_inatomic(
REG_BYTE(rptr,
368 static int emulate_fp_pair(
unsigned char __user *addr,
unsigned int reg,
371 char *ptr0 = (
char *) &
current->thread.TS_FPR(reg);
372 char *ptr1 = (
char *) &
current->thread.TS_FPR(reg+1);
382 for (i = 0; i < 8; ++
i) {
398 static struct aligninfo spe_aligninfo[32] = {
437 #define EVLHHESPLAT 0x04
438 #define EVLHHOUSPLAT 0x06
439 #define EVLHHOSSPLAT 0x07
443 #define EVLWWSPLAT 0x0C
444 #define EVLWHSPLAT 0x0E
458 static int emulate_spe(
struct pt_regs *regs,
unsigned int reg,
469 unsigned long *evr = &
current->thread.evr[
reg];
470 unsigned int nb,
flags;
472 instr = (instr >> 1) & 0x1f;
475 addr = (
unsigned char __user *)regs->
dar;
477 nb = spe_aligninfo[instr].
len;
478 flags = spe_aligninfo[instr].
flags;
505 data.h[2] = *evr >> 16;
509 data.h[2] = *evr & 0xffff;
522 temp.ll =
data.ll = 0;
528 ret |= __get_user_inatomic(temp.v[0], p++);
529 ret |= __get_user_inatomic(temp.v[1], p++);
530 ret |= __get_user_inatomic(temp.v[2], p++);
531 ret |= __get_user_inatomic(temp.v[3], p++);
533 ret |= __get_user_inatomic(temp.v[4], p++);
534 ret |= __get_user_inatomic(temp.v[5], p++);
536 ret |= __get_user_inatomic(temp.v[6], p++);
537 ret |= __get_user_inatomic(temp.v[7], p++);
549 data.h[0] = temp.h[3];
550 data.h[2] = temp.h[3];
554 data.h[1] = temp.h[3];
555 data.h[3] = temp.h[3];
558 data.h[0] = temp.h[2];
559 data.h[2] = temp.h[3];
563 data.h[1] = temp.h[2];
564 data.h[3] = temp.h[3];
567 data.w[0] = temp.w[1];
568 data.w[1] = temp.w[1];
571 data.h[0] = temp.h[2];
572 data.h[1] = temp.h[2];
573 data.h[2] = temp.h[3];
574 data.h[3] = temp.h[3];
582 switch (flags & 0xf0) {
617 ret |= __put_user_inatomic(
data.v[0], p++);
618 ret |= __put_user_inatomic(
data.v[1], p++);
619 ret |= __put_user_inatomic(
data.v[2], p++);
620 ret |= __put_user_inatomic(
data.v[3], p++);
622 ret |= __put_user_inatomic(
data.v[4], p++);
623 ret |= __put_user_inatomic(
data.v[5], p++);
625 ret |= __put_user_inatomic(
data.v[6], p++);
626 ret |= __put_user_inatomic(
data.v[7], p++);
643 static int emulate_vsx(
unsigned char __user *addr,
unsigned int reg,
644 unsigned int areg,
struct pt_regs *regs,
645 unsigned int flags,
unsigned int length,
657 ptr = (
char *) &
current->thread.TS_FPR(reg);
659 ptr = (
char *) &
current->thread.vr[reg - 32];
661 lptr = (
unsigned long *)
ptr;
666 for (j = 0; j <
length; j += elsize) {
667 for (i = 0; i < elsize; ++
i) {
679 regs->
gpr[areg] = regs->
dar;
685 else if (!(flags & ST) && (8 == length))
705 unsigned int reg, areg;
708 unsigned long p, swiz;
719 unsigned char hi48[6];
736 unsigned long pc = regs->
nip;
740 if (
unlikely(__get_user_inatomic(instr,
741 (
unsigned int __user *)pc)))
745 dsisr = make_dsisr(instr);
750 reg = (dsisr >> 5) & 0x1f;
754 if ((instr >> 26) == 0x4) {
756 return emulate_spe(regs, reg, instr);
760 instr = (dsisr >> 10) & 0x7f;
761 instr |= (dsisr >> 13) & 0x60;
769 if (regs->
msr & MSR_LE) {
786 addr = (
unsigned char __user *)regs->
dar;
789 if ((instruction & 0xfc00003e) == 0x7c000018) {
793 reg |= (instruction & 0x1) << 5;
797 if (instruction & 0x200)
803 if (instruction & 0x80)
807 if (regs->
msr & MSR_LE)
809 if (instruction & 0x100)
811 if (instruction & 0x040)
814 if ((instruction & 0x400) == 0){
819 return emulate_vsx(addr, reg, areg, regs, flags, nb, elsize);
827 return emulate_dcbz(regs, addr);
837 return emulate_multiple(regs, addr, reg, nb,
858 return emulate_fp_pair(addr, reg, flags);
869 p = (
unsigned long) addr;
885 }
else if (flags & F) {
889 #ifdef CONFIG_PPC_FPU
892 cvt_df(&
data.dd, (
float *)&
data.v[4]);
922 switch (flags & ~(U|SW)) {
933 #ifdef CONFIG_PPC_FPU
936 cvt_fd((
float *)&
data.v[4], &
data.dd);
947 p = (
unsigned long) addr;
963 }
else if (flags & F)
970 regs->
gpr[areg] = regs->
dar;