diff options
Diffstat (limited to 'ANDROID_3.4.5/arch/powerpc/lib/sstep.c')
-rw-r--r-- | ANDROID_3.4.5/arch/powerpc/lib/sstep.c | 1629 |
1 files changed, 0 insertions, 1629 deletions
diff --git a/ANDROID_3.4.5/arch/powerpc/lib/sstep.c b/ANDROID_3.4.5/arch/powerpc/lib/sstep.c deleted file mode 100644 index 9a523498..00000000 --- a/ANDROID_3.4.5/arch/powerpc/lib/sstep.c +++ /dev/null @@ -1,1629 +0,0 @@ -/* - * Single-step support. - * - * Copyright (C) 2004 Paul Mackerras <paulus@au.ibm.com>, IBM - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#include <linux/kernel.h> -#include <linux/kprobes.h> -#include <linux/ptrace.h> -#include <linux/prefetch.h> -#include <asm/sstep.h> -#include <asm/processor.h> -#include <asm/uaccess.h> -#include <asm/cputable.h> - -extern char system_call_common[]; - -#ifdef CONFIG_PPC64 -/* Bits in SRR1 that are copied from MSR */ -#define MSR_MASK 0xffffffff87c0ffffUL -#else -#define MSR_MASK 0x87c0ffff -#endif - -/* Bits in XER */ -#define XER_SO 0x80000000U -#define XER_OV 0x40000000U -#define XER_CA 0x20000000U - -#ifdef CONFIG_PPC_FPU -/* - * Functions in ldstfp.S - */ -extern int do_lfs(int rn, unsigned long ea); -extern int do_lfd(int rn, unsigned long ea); -extern int do_stfs(int rn, unsigned long ea); -extern int do_stfd(int rn, unsigned long ea); -extern int do_lvx(int rn, unsigned long ea); -extern int do_stvx(int rn, unsigned long ea); -extern int do_lxvd2x(int rn, unsigned long ea); -extern int do_stxvd2x(int rn, unsigned long ea); -#endif - -/* - * Emulate the truncation of 64 bit values in 32-bit mode. - */ -static unsigned long truncate_if_32bit(unsigned long msr, unsigned long val) -{ -#ifdef __powerpc64__ - if ((msr & MSR_64BIT) == 0) - val &= 0xffffffffUL; -#endif - return val; -} - -/* - * Determine whether a conditional branch instruction would branch. - */ -static int __kprobes branch_taken(unsigned int instr, struct pt_regs *regs) -{ - unsigned int bo = (instr >> 21) & 0x1f; - unsigned int bi; - - if ((bo & 4) == 0) { - /* decrement counter */ - --regs->ctr; - if (((bo >> 1) & 1) ^ (regs->ctr == 0)) - return 0; - } - if ((bo & 0x10) == 0) { - /* check bit from CR */ - bi = (instr >> 16) & 0x1f; - if (((regs->ccr >> (31 - bi)) & 1) != ((bo >> 3) & 1)) - return 0; - } - return 1; -} - - -static long __kprobes address_ok(struct pt_regs *regs, unsigned long ea, int nb) -{ - if (!user_mode(regs)) - return 1; - return __access_ok(ea, nb, USER_DS); -} - -/* - * Calculate effective address for a D-form instruction - */ -static unsigned long __kprobes dform_ea(unsigned int instr, struct pt_regs *regs) -{ - int ra; - unsigned long ea; - - ra = (instr >> 16) & 0x1f; - ea = (signed short) instr; /* sign-extend */ - if (ra) { - ea += regs->gpr[ra]; - if (instr & 0x04000000) /* update forms */ - regs->gpr[ra] = ea; - } - - return truncate_if_32bit(regs->msr, ea); -} - -#ifdef __powerpc64__ -/* - * Calculate effective address for a DS-form instruction - */ -static unsigned long __kprobes dsform_ea(unsigned int instr, struct pt_regs *regs) -{ - int ra; - unsigned long ea; - - ra = (instr >> 16) & 0x1f; - ea = (signed short) (instr & ~3); /* sign-extend */ - if (ra) { - ea += regs->gpr[ra]; - if ((instr & 3) == 1) /* update forms */ - regs->gpr[ra] = ea; - } - - return truncate_if_32bit(regs->msr, ea); -} -#endif /* __powerpc64 */ - -/* - * Calculate effective address for an X-form instruction - */ -static unsigned long __kprobes xform_ea(unsigned int instr, struct pt_regs *regs, - int do_update) -{ - int ra, rb; - unsigned long ea; - - ra = (instr >> 16) & 0x1f; - rb = (instr >> 11) & 0x1f; - ea = regs->gpr[rb]; - if (ra) { - ea += regs->gpr[ra]; - if (do_update) /* update forms */ - regs->gpr[ra] = ea; - } - - return truncate_if_32bit(regs->msr, ea); -} - -/* - * Return the largest power of 2, not greater than sizeof(unsigned long), - * such that x is a multiple of it. - */ -static inline unsigned long max_align(unsigned long x) -{ - x |= sizeof(unsigned long); - return x & -x; /* isolates rightmost bit */ -} - - -static inline unsigned long byterev_2(unsigned long x) -{ - return ((x >> 8) & 0xff) | ((x & 0xff) << 8); -} - -static inline unsigned long byterev_4(unsigned long x) -{ - return ((x >> 24) & 0xff) | ((x >> 8) & 0xff00) | - ((x & 0xff00) << 8) | ((x & 0xff) << 24); -} - -#ifdef __powerpc64__ -static inline unsigned long byterev_8(unsigned long x) -{ - return (byterev_4(x) << 32) | byterev_4(x >> 32); -} -#endif - -static int __kprobes read_mem_aligned(unsigned long *dest, unsigned long ea, - int nb) -{ - int err = 0; - unsigned long x = 0; - - switch (nb) { - case 1: - err = __get_user(x, (unsigned char __user *) ea); - break; - case 2: - err = __get_user(x, (unsigned short __user *) ea); - break; - case 4: - err = __get_user(x, (unsigned int __user *) ea); - break; -#ifdef __powerpc64__ - case 8: - err = __get_user(x, (unsigned long __user *) ea); - break; -#endif - } - if (!err) - *dest = x; - return err; -} - -static int __kprobes read_mem_unaligned(unsigned long *dest, unsigned long ea, - int nb, struct pt_regs *regs) -{ - int err; - unsigned long x, b, c; - - /* unaligned, do this in pieces */ - x = 0; - for (; nb > 0; nb -= c) { - c = max_align(ea); - if (c > nb) - c = max_align(nb); - err = read_mem_aligned(&b, ea, c); - if (err) - return err; - x = (x << (8 * c)) + b; - ea += c; - } - *dest = x; - return 0; -} - -/* - * Read memory at address ea for nb bytes, return 0 for success - * or -EFAULT if an error occurred. - */ -static int __kprobes read_mem(unsigned long *dest, unsigned long ea, int nb, - struct pt_regs *regs) -{ - if (!address_ok(regs, ea, nb)) - return -EFAULT; - if ((ea & (nb - 1)) == 0) - return read_mem_aligned(dest, ea, nb); - return read_mem_unaligned(dest, ea, nb, regs); -} - -static int __kprobes write_mem_aligned(unsigned long val, unsigned long ea, - int nb) -{ - int err = 0; - - switch (nb) { - case 1: - err = __put_user(val, (unsigned char __user *) ea); - break; - case 2: - err = __put_user(val, (unsigned short __user *) ea); - break; - case 4: - err = __put_user(val, (unsigned int __user *) ea); - break; -#ifdef __powerpc64__ - case 8: - err = __put_user(val, (unsigned long __user *) ea); - break; -#endif - } - return err; -} - -static int __kprobes write_mem_unaligned(unsigned long val, unsigned long ea, - int nb, struct pt_regs *regs) -{ - int err; - unsigned long c; - - /* unaligned or little-endian, do this in pieces */ - for (; nb > 0; nb -= c) { - c = max_align(ea); - if (c > nb) - c = max_align(nb); - err = write_mem_aligned(val >> (nb - c) * 8, ea, c); - if (err) - return err; - ++ea; - } - return 0; -} - -/* - * Write memory at address ea for nb bytes, return 0 for success - * or -EFAULT if an error occurred. - */ -static int __kprobes write_mem(unsigned long val, unsigned long ea, int nb, - struct pt_regs *regs) -{ - if (!address_ok(regs, ea, nb)) - return -EFAULT; - if ((ea & (nb - 1)) == 0) - return write_mem_aligned(val, ea, nb); - return write_mem_unaligned(val, ea, nb, regs); -} - -#ifdef CONFIG_PPC_FPU -/* - * Check the address and alignment, and call func to do the actual - * load or store. - */ -static int __kprobes do_fp_load(int rn, int (*func)(int, unsigned long), - unsigned long ea, int nb, - struct pt_regs *regs) -{ - int err; - unsigned long val[sizeof(double) / sizeof(long)]; - unsigned long ptr; - - if (!address_ok(regs, ea, nb)) - return -EFAULT; - if ((ea & 3) == 0) - return (*func)(rn, ea); - ptr = (unsigned long) &val[0]; - if (sizeof(unsigned long) == 8 || nb == 4) { - err = read_mem_unaligned(&val[0], ea, nb, regs); - ptr += sizeof(unsigned long) - nb; - } else { - /* reading a double on 32-bit */ - err = read_mem_unaligned(&val[0], ea, 4, regs); - if (!err) - err = read_mem_unaligned(&val[1], ea + 4, 4, regs); - } - if (err) - return err; - return (*func)(rn, ptr); -} - -static int __kprobes do_fp_store(int rn, int (*func)(int, unsigned long), - unsigned long ea, int nb, - struct pt_regs *regs) -{ - int err; - unsigned long val[sizeof(double) / sizeof(long)]; - unsigned long ptr; - - if (!address_ok(regs, ea, nb)) - return -EFAULT; - if ((ea & 3) == 0) - return (*func)(rn, ea); - ptr = (unsigned long) &val[0]; - if (sizeof(unsigned long) == 8 || nb == 4) { - ptr += sizeof(unsigned long) - nb; - err = (*func)(rn, ptr); - if (err) - return err; - err = write_mem_unaligned(val[0], ea, nb, regs); - } else { - /* writing a double on 32-bit */ - err = (*func)(rn, ptr); - if (err) - return err; - err = write_mem_unaligned(val[0], ea, 4, regs); - if (!err) - err = write_mem_unaligned(val[1], ea + 4, 4, regs); - } - return err; -} -#endif - -#ifdef CONFIG_ALTIVEC -/* For Altivec/VMX, no need to worry about alignment */ -static int __kprobes do_vec_load(int rn, int (*func)(int, unsigned long), - unsigned long ea, struct pt_regs *regs) -{ - if (!address_ok(regs, ea & ~0xfUL, 16)) - return -EFAULT; - return (*func)(rn, ea); -} - -static int __kprobes do_vec_store(int rn, int (*func)(int, unsigned long), - unsigned long ea, struct pt_regs *regs) -{ - if (!address_ok(regs, ea & ~0xfUL, 16)) - return -EFAULT; - return (*func)(rn, ea); -} -#endif /* CONFIG_ALTIVEC */ - -#ifdef CONFIG_VSX -static int __kprobes do_vsx_load(int rn, int (*func)(int, unsigned long), - unsigned long ea, struct pt_regs *regs) -{ - int err; - unsigned long val[2]; - - if (!address_ok(regs, ea, 16)) - return -EFAULT; - if ((ea & 3) == 0) - return (*func)(rn, ea); - err = read_mem_unaligned(&val[0], ea, 8, regs); - if (!err) - err = read_mem_unaligned(&val[1], ea + 8, 8, regs); - if (!err) - err = (*func)(rn, (unsigned long) &val[0]); - return err; -} - -static int __kprobes do_vsx_store(int rn, int (*func)(int, unsigned long), - unsigned long ea, struct pt_regs *regs) -{ - int err; - unsigned long val[2]; - - if (!address_ok(regs, ea, 16)) - return -EFAULT; - if ((ea & 3) == 0) - return (*func)(rn, ea); - err = (*func)(rn, (unsigned long) &val[0]); - if (err) - return err; - err = write_mem_unaligned(val[0], ea, 8, regs); - if (!err) - err = write_mem_unaligned(val[1], ea + 8, 8, regs); - return err; -} -#endif /* CONFIG_VSX */ - -#define __put_user_asmx(x, addr, err, op, cr) \ - __asm__ __volatile__( \ - "1: " op " %2,0,%3\n" \ - " mfcr %1\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: li %0,%4\n" \ - " b 2b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - PPC_LONG_ALIGN "\n" \ - PPC_LONG "1b,3b\n" \ - ".previous" \ - : "=r" (err), "=r" (cr) \ - : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err)) - -#define __get_user_asmx(x, addr, err, op) \ - __asm__ __volatile__( \ - "1: "op" %1,0,%2\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: li %0,%3\n" \ - " b 2b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - PPC_LONG_ALIGN "\n" \ - PPC_LONG "1b,3b\n" \ - ".previous" \ - : "=r" (err), "=r" (x) \ - : "r" (addr), "i" (-EFAULT), "0" (err)) - -#define __cacheop_user_asmx(addr, err, op) \ - __asm__ __volatile__( \ - "1: "op" 0,%1\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: li %0,%3\n" \ - " b 2b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - PPC_LONG_ALIGN "\n" \ - PPC_LONG "1b,3b\n" \ - ".previous" \ - : "=r" (err) \ - : "r" (addr), "i" (-EFAULT), "0" (err)) - -static void __kprobes set_cr0(struct pt_regs *regs, int rd) -{ - long val = regs->gpr[rd]; - - regs->ccr = (regs->ccr & 0x0fffffff) | ((regs->xer >> 3) & 0x10000000); -#ifdef __powerpc64__ - if (!(regs->msr & MSR_64BIT)) - val = (int) val; -#endif - if (val < 0) - regs->ccr |= 0x80000000; - else if (val > 0) - regs->ccr |= 0x40000000; - else - regs->ccr |= 0x20000000; -} - -static void __kprobes add_with_carry(struct pt_regs *regs, int rd, - unsigned long val1, unsigned long val2, - unsigned long carry_in) -{ - unsigned long val = val1 + val2; - - if (carry_in) - ++val; - regs->gpr[rd] = val; -#ifdef __powerpc64__ - if (!(regs->msr & MSR_64BIT)) { - val = (unsigned int) val; - val1 = (unsigned int) val1; - } -#endif - if (val < val1 || (carry_in && val == val1)) - regs->xer |= XER_CA; - else - regs->xer &= ~XER_CA; -} - -static void __kprobes do_cmp_signed(struct pt_regs *regs, long v1, long v2, - int crfld) -{ - unsigned int crval, shift; - - crval = (regs->xer >> 31) & 1; /* get SO bit */ - if (v1 < v2) - crval |= 8; - else if (v1 > v2) - crval |= 4; - else - crval |= 2; - shift = (7 - crfld) * 4; - regs->ccr = (regs->ccr & ~(0xf << shift)) | (crval << shift); -} - -static void __kprobes do_cmp_unsigned(struct pt_regs *regs, unsigned long v1, - unsigned long v2, int crfld) -{ - unsigned int crval, shift; - - crval = (regs->xer >> 31) & 1; /* get SO bit */ - if (v1 < v2) - crval |= 8; - else if (v1 > v2) - crval |= 4; - else - crval |= 2; - shift = (7 - crfld) * 4; - regs->ccr = (regs->ccr & ~(0xf << shift)) | (crval << shift); -} - -/* - * Elements of 32-bit rotate and mask instructions. - */ -#define MASK32(mb, me) ((0xffffffffUL >> (mb)) + \ - ((signed long)-0x80000000L >> (me)) + ((me) >= (mb))) -#ifdef __powerpc64__ -#define MASK64_L(mb) (~0UL >> (mb)) -#define MASK64_R(me) ((signed long)-0x8000000000000000L >> (me)) -#define MASK64(mb, me) (MASK64_L(mb) + MASK64_R(me) + ((me) >= (mb))) -#define DATA32(x) (((x) & 0xffffffffUL) | (((x) & 0xffffffffUL) << 32)) -#else -#define DATA32(x) (x) -#endif -#define ROTATE(x, n) ((n) ? (((x) << (n)) | ((x) >> (8 * sizeof(long) - (n)))) : (x)) - -/* - * Emulate instructions that cause a transfer of control, - * loads and stores, and a few other instructions. - * Returns 1 if the step was emulated, 0 if not, - * or -1 if the instruction is one that should not be stepped, - * such as an rfid, or a mtmsrd that would clear MSR_RI. - */ -int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) -{ - unsigned int opcode, ra, rb, rd, spr, u; - unsigned long int imm; - unsigned long int val, val2; - unsigned long int ea; - unsigned int cr, mb, me, sh; - int err; - unsigned long old_ra; - long ival; - - opcode = instr >> 26; - switch (opcode) { - case 16: /* bc */ - imm = (signed short)(instr & 0xfffc); - if ((instr & 2) == 0) - imm += regs->nip; - regs->nip += 4; - regs->nip = truncate_if_32bit(regs->msr, regs->nip); - if (instr & 1) - regs->link = regs->nip; - if (branch_taken(instr, regs)) - regs->nip = imm; - return 1; -#ifdef CONFIG_PPC64 - case 17: /* sc */ - /* - * N.B. this uses knowledge about how the syscall - * entry code works. If that is changed, this will - * need to be changed also. - */ - if (regs->gpr[0] == 0x1ebe && - cpu_has_feature(CPU_FTR_REAL_LE)) { - regs->msr ^= MSR_LE; - goto instr_done; - } - regs->gpr[9] = regs->gpr[13]; - regs->gpr[10] = MSR_KERNEL; - regs->gpr[11] = regs->nip + 4; - regs->gpr[12] = regs->msr & MSR_MASK; - regs->gpr[13] = (unsigned long) get_paca(); - regs->nip = (unsigned long) &system_call_common; - regs->msr = MSR_KERNEL; - return 1; -#endif - case 18: /* b */ - imm = instr & 0x03fffffc; - if (imm & 0x02000000) - imm -= 0x04000000; - if ((instr & 2) == 0) - imm += regs->nip; - if (instr & 1) - regs->link = truncate_if_32bit(regs->msr, regs->nip + 4); - imm = truncate_if_32bit(regs->msr, imm); - regs->nip = imm; - return 1; - case 19: - switch ((instr >> 1) & 0x3ff) { - case 16: /* bclr */ - case 528: /* bcctr */ - imm = (instr & 0x400)? regs->ctr: regs->link; - regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4); - imm = truncate_if_32bit(regs->msr, imm); - if (instr & 1) - regs->link = regs->nip; - if (branch_taken(instr, regs)) - regs->nip = imm; - return 1; - - case 18: /* rfid, scary */ - return -1; - - case 150: /* isync */ - isync(); - goto instr_done; - - case 33: /* crnor */ - case 129: /* crandc */ - case 193: /* crxor */ - case 225: /* crnand */ - case 257: /* crand */ - case 289: /* creqv */ - case 417: /* crorc */ - case 449: /* cror */ - ra = (instr >> 16) & 0x1f; - rb = (instr >> 11) & 0x1f; - rd = (instr >> 21) & 0x1f; - ra = (regs->ccr >> (31 - ra)) & 1; - rb = (regs->ccr >> (31 - rb)) & 1; - val = (instr >> (6 + ra * 2 + rb)) & 1; - regs->ccr = (regs->ccr & ~(1UL << (31 - rd))) | - (val << (31 - rd)); - goto instr_done; - } - break; - case 31: - switch ((instr >> 1) & 0x3ff) { - case 598: /* sync */ -#ifdef __powerpc64__ - switch ((instr >> 21) & 3) { - case 1: /* lwsync */ - asm volatile("lwsync" : : : "memory"); - goto instr_done; - case 2: /* ptesync */ - asm volatile("ptesync" : : : "memory"); - goto instr_done; - } -#endif - mb(); - goto instr_done; - - case 854: /* eieio */ - eieio(); - goto instr_done; - } - break; - } - - /* Following cases refer to regs->gpr[], so we need all regs */ - if (!FULL_REGS(regs)) - return 0; - - rd = (instr >> 21) & 0x1f; - ra = (instr >> 16) & 0x1f; - rb = (instr >> 11) & 0x1f; - - switch (opcode) { - case 7: /* mulli */ - regs->gpr[rd] = regs->gpr[ra] * (short) instr; - goto instr_done; - - case 8: /* subfic */ - imm = (short) instr; - add_with_carry(regs, rd, ~regs->gpr[ra], imm, 1); - goto instr_done; - - case 10: /* cmpli */ - imm = (unsigned short) instr; - val = regs->gpr[ra]; -#ifdef __powerpc64__ - if ((rd & 1) == 0) - val = (unsigned int) val; -#endif - do_cmp_unsigned(regs, val, imm, rd >> 2); - goto instr_done; - - case 11: /* cmpi */ - imm = (short) instr; - val = regs->gpr[ra]; -#ifdef __powerpc64__ - if ((rd & 1) == 0) - val = (int) val; -#endif - do_cmp_signed(regs, val, imm, rd >> 2); - goto instr_done; - - case 12: /* addic */ - imm = (short) instr; - add_with_carry(regs, rd, regs->gpr[ra], imm, 0); - goto instr_done; - - case 13: /* addic. */ - imm = (short) instr; - add_with_carry(regs, rd, regs->gpr[ra], imm, 0); - set_cr0(regs, rd); - goto instr_done; - - case 14: /* addi */ - imm = (short) instr; - if (ra) - imm += regs->gpr[ra]; - regs->gpr[rd] = imm; - goto instr_done; - - case 15: /* addis */ - imm = ((short) instr) << 16; - if (ra) - imm += regs->gpr[ra]; - regs->gpr[rd] = imm; - goto instr_done; - - case 20: /* rlwimi */ - mb = (instr >> 6) & 0x1f; - me = (instr >> 1) & 0x1f; - val = DATA32(regs->gpr[rd]); - imm = MASK32(mb, me); - regs->gpr[ra] = (regs->gpr[ra] & ~imm) | (ROTATE(val, rb) & imm); - goto logical_done; - - case 21: /* rlwinm */ - mb = (instr >> 6) & 0x1f; - me = (instr >> 1) & 0x1f; - val = DATA32(regs->gpr[rd]); - regs->gpr[ra] = ROTATE(val, rb) & MASK32(mb, me); - goto logical_done; - - case 23: /* rlwnm */ - mb = (instr >> 6) & 0x1f; - me = (instr >> 1) & 0x1f; - rb = regs->gpr[rb] & 0x1f; - val = DATA32(regs->gpr[rd]); - regs->gpr[ra] = ROTATE(val, rb) & MASK32(mb, me); - goto logical_done; - - case 24: /* ori */ - imm = (unsigned short) instr; - regs->gpr[ra] = regs->gpr[rd] | imm; - goto instr_done; - - case 25: /* oris */ - imm = (unsigned short) instr; - regs->gpr[ra] = regs->gpr[rd] | (imm << 16); - goto instr_done; - - case 26: /* xori */ - imm = (unsigned short) instr; - regs->gpr[ra] = regs->gpr[rd] ^ imm; - goto instr_done; - - case 27: /* xoris */ - imm = (unsigned short) instr; - regs->gpr[ra] = regs->gpr[rd] ^ (imm << 16); - goto instr_done; - - case 28: /* andi. */ - imm = (unsigned short) instr; - regs->gpr[ra] = regs->gpr[rd] & imm; - set_cr0(regs, ra); - goto instr_done; - - case 29: /* andis. */ - imm = (unsigned short) instr; - regs->gpr[ra] = regs->gpr[rd] & (imm << 16); - set_cr0(regs, ra); - goto instr_done; - -#ifdef __powerpc64__ - case 30: /* rld* */ - mb = ((instr >> 6) & 0x1f) | (instr & 0x20); - val = regs->gpr[rd]; - if ((instr & 0x10) == 0) { - sh = rb | ((instr & 2) << 4); - val = ROTATE(val, sh); - switch ((instr >> 2) & 3) { - case 0: /* rldicl */ - regs->gpr[ra] = val & MASK64_L(mb); - goto logical_done; - case 1: /* rldicr */ - regs->gpr[ra] = val & MASK64_R(mb); - goto logical_done; - case 2: /* rldic */ - regs->gpr[ra] = val & MASK64(mb, 63 - sh); - goto logical_done; - case 3: /* rldimi */ - imm = MASK64(mb, 63 - sh); - regs->gpr[ra] = (regs->gpr[ra] & ~imm) | - (val & imm); - goto logical_done; - } - } else { - sh = regs->gpr[rb] & 0x3f; - val = ROTATE(val, sh); - switch ((instr >> 1) & 7) { - case 0: /* rldcl */ - regs->gpr[ra] = val & MASK64_L(mb); - goto logical_done; - case 1: /* rldcr */ - regs->gpr[ra] = val & MASK64_R(mb); - goto logical_done; - } - } -#endif - - case 31: - switch ((instr >> 1) & 0x3ff) { - case 83: /* mfmsr */ - if (regs->msr & MSR_PR) - break; - regs->gpr[rd] = regs->msr & MSR_MASK; - goto instr_done; - case 146: /* mtmsr */ - if (regs->msr & MSR_PR) - break; - imm = regs->gpr[rd]; - if ((imm & MSR_RI) == 0) - /* can't step mtmsr that would clear MSR_RI */ - return -1; - regs->msr = imm; - goto instr_done; -#ifdef CONFIG_PPC64 - case 178: /* mtmsrd */ - /* only MSR_EE and MSR_RI get changed if bit 15 set */ - /* mtmsrd doesn't change MSR_HV and MSR_ME */ - if (regs->msr & MSR_PR) - break; - imm = (instr & 0x10000)? 0x8002: 0xefffffffffffefffUL; - imm = (regs->msr & MSR_MASK & ~imm) - | (regs->gpr[rd] & imm); - if ((imm & MSR_RI) == 0) - /* can't step mtmsrd that would clear MSR_RI */ - return -1; - regs->msr = imm; - goto instr_done; -#endif - case 19: /* mfcr */ - regs->gpr[rd] = regs->ccr; - regs->gpr[rd] &= 0xffffffffUL; - goto instr_done; - - case 144: /* mtcrf */ - imm = 0xf0000000UL; - val = regs->gpr[rd]; - for (sh = 0; sh < 8; ++sh) { - if (instr & (0x80000 >> sh)) - regs->ccr = (regs->ccr & ~imm) | - (val & imm); - imm >>= 4; - } - goto instr_done; - - case 339: /* mfspr */ - spr = (instr >> 11) & 0x3ff; - switch (spr) { - case 0x20: /* mfxer */ - regs->gpr[rd] = regs->xer; - regs->gpr[rd] &= 0xffffffffUL; - goto instr_done; - case 0x100: /* mflr */ - regs->gpr[rd] = regs->link; - goto instr_done; - case 0x120: /* mfctr */ - regs->gpr[rd] = regs->ctr; - goto instr_done; - } - break; - - case 467: /* mtspr */ - spr = (instr >> 11) & 0x3ff; - switch (spr) { - case 0x20: /* mtxer */ - regs->xer = (regs->gpr[rd] & 0xffffffffUL); - goto instr_done; - case 0x100: /* mtlr */ - regs->link = regs->gpr[rd]; - goto instr_done; - case 0x120: /* mtctr */ - regs->ctr = regs->gpr[rd]; - goto instr_done; - } - break; - -/* - * Compare instructions - */ - case 0: /* cmp */ - val = regs->gpr[ra]; - val2 = regs->gpr[rb]; -#ifdef __powerpc64__ - if ((rd & 1) == 0) { - /* word (32-bit) compare */ - val = (int) val; - val2 = (int) val2; - } -#endif - do_cmp_signed(regs, val, val2, rd >> 2); - goto instr_done; - - case 32: /* cmpl */ - val = regs->gpr[ra]; - val2 = regs->gpr[rb]; -#ifdef __powerpc64__ - if ((rd & 1) == 0) { - /* word (32-bit) compare */ - val = (unsigned int) val; - val2 = (unsigned int) val2; - } -#endif - do_cmp_unsigned(regs, val, val2, rd >> 2); - goto instr_done; - -/* - * Arithmetic instructions - */ - case 8: /* subfc */ - add_with_carry(regs, rd, ~regs->gpr[ra], - regs->gpr[rb], 1); - goto arith_done; -#ifdef __powerpc64__ - case 9: /* mulhdu */ - asm("mulhdu %0,%1,%2" : "=r" (regs->gpr[rd]) : - "r" (regs->gpr[ra]), "r" (regs->gpr[rb])); - goto arith_done; -#endif - case 10: /* addc */ - add_with_carry(regs, rd, regs->gpr[ra], - regs->gpr[rb], 0); - goto arith_done; - - case 11: /* mulhwu */ - asm("mulhwu %0,%1,%2" : "=r" (regs->gpr[rd]) : - "r" (regs->gpr[ra]), "r" (regs->gpr[rb])); - goto arith_done; - - case 40: /* subf */ - regs->gpr[rd] = regs->gpr[rb] - regs->gpr[ra]; - goto arith_done; -#ifdef __powerpc64__ - case 73: /* mulhd */ - asm("mulhd %0,%1,%2" : "=r" (regs->gpr[rd]) : - "r" (regs->gpr[ra]), "r" (regs->gpr[rb])); - goto arith_done; -#endif - case 75: /* mulhw */ - asm("mulhw %0,%1,%2" : "=r" (regs->gpr[rd]) : - "r" (regs->gpr[ra]), "r" (regs->gpr[rb])); - goto arith_done; - - case 104: /* neg */ - regs->gpr[rd] = -regs->gpr[ra]; - goto arith_done; - - case 136: /* subfe */ - add_with_carry(regs, rd, ~regs->gpr[ra], regs->gpr[rb], - regs->xer & XER_CA); - goto arith_done; - - case 138: /* adde */ - add_with_carry(regs, rd, regs->gpr[ra], regs->gpr[rb], - regs->xer & XER_CA); - goto arith_done; - - case 200: /* subfze */ - add_with_carry(regs, rd, ~regs->gpr[ra], 0L, - regs->xer & XER_CA); - goto arith_done; - - case 202: /* addze */ - add_with_carry(regs, rd, regs->gpr[ra], 0L, - regs->xer & XER_CA); - goto arith_done; - - case 232: /* subfme */ - add_with_carry(regs, rd, ~regs->gpr[ra], -1L, - regs->xer & XER_CA); - goto arith_done; -#ifdef __powerpc64__ - case 233: /* mulld */ - regs->gpr[rd] = regs->gpr[ra] * regs->gpr[rb]; - goto arith_done; -#endif - case 234: /* addme */ - add_with_carry(regs, rd, regs->gpr[ra], -1L, - regs->xer & XER_CA); - goto arith_done; - - case 235: /* mullw */ - regs->gpr[rd] = (unsigned int) regs->gpr[ra] * - (unsigned int) regs->gpr[rb]; - goto arith_done; - - case 266: /* add */ - regs->gpr[rd] = regs->gpr[ra] + regs->gpr[rb]; - goto arith_done; -#ifdef __powerpc64__ - case 457: /* divdu */ - regs->gpr[rd] = regs->gpr[ra] / regs->gpr[rb]; - goto arith_done; -#endif - case 459: /* divwu */ - regs->gpr[rd] = (unsigned int) regs->gpr[ra] / - (unsigned int) regs->gpr[rb]; - goto arith_done; -#ifdef __powerpc64__ - case 489: /* divd */ - regs->gpr[rd] = (long int) regs->gpr[ra] / - (long int) regs->gpr[rb]; - goto arith_done; -#endif - case 491: /* divw */ - regs->gpr[rd] = (int) regs->gpr[ra] / - (int) regs->gpr[rb]; - goto arith_done; - - -/* - * Logical instructions - */ - case 26: /* cntlzw */ - asm("cntlzw %0,%1" : "=r" (regs->gpr[ra]) : - "r" (regs->gpr[rd])); - goto logical_done; -#ifdef __powerpc64__ - case 58: /* cntlzd */ - asm("cntlzd %0,%1" : "=r" (regs->gpr[ra]) : - "r" (regs->gpr[rd])); - goto logical_done; -#endif - case 28: /* and */ - regs->gpr[ra] = regs->gpr[rd] & regs->gpr[rb]; - goto logical_done; - - case 60: /* andc */ - regs->gpr[ra] = regs->gpr[rd] & ~regs->gpr[rb]; - goto logical_done; - - case 124: /* nor */ - regs->gpr[ra] = ~(regs->gpr[rd] | regs->gpr[rb]); - goto logical_done; - - case 284: /* xor */ - regs->gpr[ra] = ~(regs->gpr[rd] ^ regs->gpr[rb]); - goto logical_done; - - case 316: /* xor */ - regs->gpr[ra] = regs->gpr[rd] ^ regs->gpr[rb]; - goto logical_done; - - case 412: /* orc */ - regs->gpr[ra] = regs->gpr[rd] | ~regs->gpr[rb]; - goto logical_done; - - case 444: /* or */ - regs->gpr[ra] = regs->gpr[rd] | regs->gpr[rb]; - goto logical_done; - - case 476: /* nand */ - regs->gpr[ra] = ~(regs->gpr[rd] & regs->gpr[rb]); - goto logical_done; - - case 922: /* extsh */ - regs->gpr[ra] = (signed short) regs->gpr[rd]; - goto logical_done; - - case 954: /* extsb */ - regs->gpr[ra] = (signed char) regs->gpr[rd]; - goto logical_done; -#ifdef __powerpc64__ - case 986: /* extsw */ - regs->gpr[ra] = (signed int) regs->gpr[rd]; - goto logical_done; -#endif - -/* - * Shift instructions - */ - case 24: /* slw */ - sh = regs->gpr[rb] & 0x3f; - if (sh < 32) - regs->gpr[ra] = (regs->gpr[rd] << sh) & 0xffffffffUL; - else - regs->gpr[ra] = 0; - goto logical_done; - - case 536: /* srw */ - sh = regs->gpr[rb] & 0x3f; - if (sh < 32) - regs->gpr[ra] = (regs->gpr[rd] & 0xffffffffUL) >> sh; - else - regs->gpr[ra] = 0; - goto logical_done; - - case 792: /* sraw */ - sh = regs->gpr[rb] & 0x3f; - ival = (signed int) regs->gpr[rd]; - regs->gpr[ra] = ival >> (sh < 32 ? sh : 31); - if (ival < 0 && (sh >= 32 || (ival & ((1 << sh) - 1)) != 0)) - regs->xer |= XER_CA; - else - regs->xer &= ~XER_CA; - goto logical_done; - - case 824: /* srawi */ - sh = rb; - ival = (signed int) regs->gpr[rd]; - regs->gpr[ra] = ival >> sh; - if (ival < 0 && (ival & ((1 << sh) - 1)) != 0) - regs->xer |= XER_CA; - else - regs->xer &= ~XER_CA; - goto logical_done; - -#ifdef __powerpc64__ - case 27: /* sld */ - sh = regs->gpr[rd] & 0x7f; - if (sh < 64) - regs->gpr[ra] = regs->gpr[rd] << sh; - else - regs->gpr[ra] = 0; - goto logical_done; - - case 539: /* srd */ - sh = regs->gpr[rb] & 0x7f; - if (sh < 64) - regs->gpr[ra] = regs->gpr[rd] >> sh; - else - regs->gpr[ra] = 0; - goto logical_done; - - case 794: /* srad */ - sh = regs->gpr[rb] & 0x7f; - ival = (signed long int) regs->gpr[rd]; - regs->gpr[ra] = ival >> (sh < 64 ? sh : 63); - if (ival < 0 && (sh >= 64 || (ival & ((1 << sh) - 1)) != 0)) - regs->xer |= XER_CA; - else - regs->xer &= ~XER_CA; - goto logical_done; - - case 826: /* sradi with sh_5 = 0 */ - case 827: /* sradi with sh_5 = 1 */ - sh = rb | ((instr & 2) << 4); - ival = (signed long int) regs->gpr[rd]; - regs->gpr[ra] = ival >> sh; - if (ival < 0 && (ival & ((1 << sh) - 1)) != 0) - regs->xer |= XER_CA; - else - regs->xer &= ~XER_CA; - goto logical_done; -#endif /* __powerpc64__ */ - -/* - * Cache instructions - */ - case 54: /* dcbst */ - ea = xform_ea(instr, regs, 0); - if (!address_ok(regs, ea, 8)) - return 0; - err = 0; - __cacheop_user_asmx(ea, err, "dcbst"); - if (err) - return 0; - goto instr_done; - - case 86: /* dcbf */ - ea = xform_ea(instr, regs, 0); - if (!address_ok(regs, ea, 8)) - return 0; - err = 0; - __cacheop_user_asmx(ea, err, "dcbf"); - if (err) - return 0; - goto instr_done; - - case 246: /* dcbtst */ - if (rd == 0) { - ea = xform_ea(instr, regs, 0); - prefetchw((void *) ea); - } - goto instr_done; - - case 278: /* dcbt */ - if (rd == 0) { - ea = xform_ea(instr, regs, 0); - prefetch((void *) ea); - } - goto instr_done; - - } - break; - } - - /* - * Following cases are for loads and stores, so bail out - * if we're in little-endian mode. - */ - if (regs->msr & MSR_LE) - return 0; - - /* - * Save register RA in case it's an update form load or store - * and the access faults. - */ - old_ra = regs->gpr[ra]; - - switch (opcode) { - case 31: - u = instr & 0x40; - switch ((instr >> 1) & 0x3ff) { - case 20: /* lwarx */ - ea = xform_ea(instr, regs, 0); - if (ea & 3) - break; /* can't handle misaligned */ - err = -EFAULT; - if (!address_ok(regs, ea, 4)) - goto ldst_done; - err = 0; - __get_user_asmx(val, ea, err, "lwarx"); - if (!err) - regs->gpr[rd] = val; - goto ldst_done; - - case 150: /* stwcx. */ - ea = xform_ea(instr, regs, 0); - if (ea & 3) - break; /* can't handle misaligned */ - err = -EFAULT; - if (!address_ok(regs, ea, 4)) - goto ldst_done; - err = 0; - __put_user_asmx(regs->gpr[rd], ea, err, "stwcx.", cr); - if (!err) - regs->ccr = (regs->ccr & 0x0fffffff) | - (cr & 0xe0000000) | - ((regs->xer >> 3) & 0x10000000); - goto ldst_done; - -#ifdef __powerpc64__ - case 84: /* ldarx */ - ea = xform_ea(instr, regs, 0); - if (ea & 7) - break; /* can't handle misaligned */ - err = -EFAULT; - if (!address_ok(regs, ea, 8)) - goto ldst_done; - err = 0; - __get_user_asmx(val, ea, err, "ldarx"); - if (!err) - regs->gpr[rd] = val; - goto ldst_done; - - case 214: /* stdcx. */ - ea = xform_ea(instr, regs, 0); - if (ea & 7) - break; /* can't handle misaligned */ - err = -EFAULT; - if (!address_ok(regs, ea, 8)) - goto ldst_done; - err = 0; - __put_user_asmx(regs->gpr[rd], ea, err, "stdcx.", cr); - if (!err) - regs->ccr = (regs->ccr & 0x0fffffff) | - (cr & 0xe0000000) | - ((regs->xer >> 3) & 0x10000000); - goto ldst_done; - - case 21: /* ldx */ - case 53: /* ldux */ - err = read_mem(®s->gpr[rd], xform_ea(instr, regs, u), - 8, regs); - goto ldst_done; -#endif - - case 23: /* lwzx */ - case 55: /* lwzux */ - err = read_mem(®s->gpr[rd], xform_ea(instr, regs, u), - 4, regs); - goto ldst_done; - - case 87: /* lbzx */ - case 119: /* lbzux */ - err = read_mem(®s->gpr[rd], xform_ea(instr, regs, u), - 1, regs); - goto ldst_done; - -#ifdef CONFIG_ALTIVEC - case 103: /* lvx */ - case 359: /* lvxl */ - if (!(regs->msr & MSR_VEC)) - break; - ea = xform_ea(instr, regs, 0); - err = do_vec_load(rd, do_lvx, ea, regs); - goto ldst_done; - - case 231: /* stvx */ - case 487: /* stvxl */ - if (!(regs->msr & MSR_VEC)) - break; - ea = xform_ea(instr, regs, 0); - err = do_vec_store(rd, do_stvx, ea, regs); - goto ldst_done; -#endif /* CONFIG_ALTIVEC */ - -#ifdef __powerpc64__ - case 149: /* stdx */ - case 181: /* stdux */ - val = regs->gpr[rd]; - err = write_mem(val, xform_ea(instr, regs, u), 8, regs); - goto ldst_done; -#endif - - case 151: /* stwx */ - case 183: /* stwux */ - val = regs->gpr[rd]; - err = write_mem(val, xform_ea(instr, regs, u), 4, regs); - goto ldst_done; - - case 215: /* stbx */ - case 247: /* stbux */ - val = regs->gpr[rd]; - err = write_mem(val, xform_ea(instr, regs, u), 1, regs); - goto ldst_done; - - case 279: /* lhzx */ - case 311: /* lhzux */ - err = read_mem(®s->gpr[rd], xform_ea(instr, regs, u), - 2, regs); - goto ldst_done; - -#ifdef __powerpc64__ - case 341: /* lwax */ - case 373: /* lwaux */ - err = read_mem(®s->gpr[rd], xform_ea(instr, regs, u), - 4, regs); - if (!err) - regs->gpr[rd] = (signed int) regs->gpr[rd]; - goto ldst_done; -#endif - - case 343: /* lhax */ - case 375: /* lhaux */ - err = read_mem(®s->gpr[rd], xform_ea(instr, regs, u), - 2, regs); - if (!err) - regs->gpr[rd] = (signed short) regs->gpr[rd]; - goto ldst_done; - - case 407: /* sthx */ - case 439: /* sthux */ - val = regs->gpr[rd]; - err = write_mem(val, xform_ea(instr, regs, u), 2, regs); - goto ldst_done; - -#ifdef __powerpc64__ - case 532: /* ldbrx */ - err = read_mem(&val, xform_ea(instr, regs, 0), 8, regs); - if (!err) - regs->gpr[rd] = byterev_8(val); - goto ldst_done; - -#endif - - case 534: /* lwbrx */ - err = read_mem(&val, xform_ea(instr, regs, 0), 4, regs); - if (!err) - regs->gpr[rd] = byterev_4(val); - goto ldst_done; - -#ifdef CONFIG_PPC_CPU - case 535: /* lfsx */ - case 567: /* lfsux */ - if (!(regs->msr & MSR_FP)) - break; - ea = xform_ea(instr, regs, u); - err = do_fp_load(rd, do_lfs, ea, 4, regs); - goto ldst_done; - - case 599: /* lfdx */ - case 631: /* lfdux */ - if (!(regs->msr & MSR_FP)) - break; - ea = xform_ea(instr, regs, u); - err = do_fp_load(rd, do_lfd, ea, 8, regs); - goto ldst_done; - - case 663: /* stfsx */ - case 695: /* stfsux */ - if (!(regs->msr & MSR_FP)) - break; - ea = xform_ea(instr, regs, u); - err = do_fp_store(rd, do_stfs, ea, 4, regs); - goto ldst_done; - - case 727: /* stfdx */ - case 759: /* stfdux */ - if (!(regs->msr & MSR_FP)) - break; - ea = xform_ea(instr, regs, u); - err = do_fp_store(rd, do_stfd, ea, 8, regs); - goto ldst_done; -#endif - -#ifdef __powerpc64__ - case 660: /* stdbrx */ - val = byterev_8(regs->gpr[rd]); - err = write_mem(val, xform_ea(instr, regs, 0), 8, regs); - goto ldst_done; - -#endif - case 662: /* stwbrx */ - val = byterev_4(regs->gpr[rd]); - err = write_mem(val, xform_ea(instr, regs, 0), 4, regs); - goto ldst_done; - - case 790: /* lhbrx */ - err = read_mem(&val, xform_ea(instr, regs, 0), 2, regs); - if (!err) - regs->gpr[rd] = byterev_2(val); - goto ldst_done; - - case 918: /* sthbrx */ - val = byterev_2(regs->gpr[rd]); - err = write_mem(val, xform_ea(instr, regs, 0), 2, regs); - goto ldst_done; - -#ifdef CONFIG_VSX - case 844: /* lxvd2x */ - case 876: /* lxvd2ux */ - if (!(regs->msr & MSR_VSX)) - break; - rd |= (instr & 1) << 5; - ea = xform_ea(instr, regs, u); - err = do_vsx_load(rd, do_lxvd2x, ea, regs); - goto ldst_done; - - case 972: /* stxvd2x */ - case 1004: /* stxvd2ux */ - if (!(regs->msr & MSR_VSX)) - break; - rd |= (instr & 1) << 5; - ea = xform_ea(instr, regs, u); - err = do_vsx_store(rd, do_stxvd2x, ea, regs); - goto ldst_done; - -#endif /* CONFIG_VSX */ - } - break; - - case 32: /* lwz */ - case 33: /* lwzu */ - err = read_mem(®s->gpr[rd], dform_ea(instr, regs), 4, regs); - goto ldst_done; - - case 34: /* lbz */ - case 35: /* lbzu */ - err = read_mem(®s->gpr[rd], dform_ea(instr, regs), 1, regs); - goto ldst_done; - - case 36: /* stw */ - case 37: /* stwu */ - val = regs->gpr[rd]; - err = write_mem(val, dform_ea(instr, regs), 4, regs); - goto ldst_done; - - case 38: /* stb */ - case 39: /* stbu */ - val = regs->gpr[rd]; - err = write_mem(val, dform_ea(instr, regs), 1, regs); - goto ldst_done; - - case 40: /* lhz */ - case 41: /* lhzu */ - err = read_mem(®s->gpr[rd], dform_ea(instr, regs), 2, regs); - goto ldst_done; - - case 42: /* lha */ - case 43: /* lhau */ - err = read_mem(®s->gpr[rd], dform_ea(instr, regs), 2, regs); - if (!err) - regs->gpr[rd] = (signed short) regs->gpr[rd]; - goto ldst_done; - - case 44: /* sth */ - case 45: /* sthu */ - val = regs->gpr[rd]; - err = write_mem(val, dform_ea(instr, regs), 2, regs); - goto ldst_done; - - case 46: /* lmw */ - ra = (instr >> 16) & 0x1f; - if (ra >= rd) - break; /* invalid form, ra in range to load */ - ea = dform_ea(instr, regs); - do { - err = read_mem(®s->gpr[rd], ea, 4, regs); - if (err) - return 0; - ea += 4; - } while (++rd < 32); - goto instr_done; - - case 47: /* stmw */ - ea = dform_ea(instr, regs); - do { - err = write_mem(regs->gpr[rd], ea, 4, regs); - if (err) - return 0; - ea += 4; - } while (++rd < 32); - goto instr_done; - -#ifdef CONFIG_PPC_FPU - case 48: /* lfs */ - case 49: /* lfsu */ - if (!(regs->msr & MSR_FP)) - break; - ea = dform_ea(instr, regs); - err = do_fp_load(rd, do_lfs, ea, 4, regs); - goto ldst_done; - - case 50: /* lfd */ - case 51: /* lfdu */ - if (!(regs->msr & MSR_FP)) - break; - ea = dform_ea(instr, regs); - err = do_fp_load(rd, do_lfd, ea, 8, regs); - goto ldst_done; - - case 52: /* stfs */ - case 53: /* stfsu */ - if (!(regs->msr & MSR_FP)) - break; - ea = dform_ea(instr, regs); - err = do_fp_store(rd, do_stfs, ea, 4, regs); - goto ldst_done; - - case 54: /* stfd */ - case 55: /* stfdu */ - if (!(regs->msr & MSR_FP)) - break; - ea = dform_ea(instr, regs); - err = do_fp_store(rd, do_stfd, ea, 8, regs); - goto ldst_done; -#endif - -#ifdef __powerpc64__ - case 58: /* ld[u], lwa */ - switch (instr & 3) { - case 0: /* ld */ - err = read_mem(®s->gpr[rd], dsform_ea(instr, regs), - 8, regs); - goto ldst_done; - case 1: /* ldu */ - err = read_mem(®s->gpr[rd], dsform_ea(instr, regs), - 8, regs); - goto ldst_done; - case 2: /* lwa */ - err = read_mem(®s->gpr[rd], dsform_ea(instr, regs), - 4, regs); - if (!err) - regs->gpr[rd] = (signed int) regs->gpr[rd]; - goto ldst_done; - } - break; - - case 62: /* std[u] */ - val = regs->gpr[rd]; - switch (instr & 3) { - case 0: /* std */ - err = write_mem(val, dsform_ea(instr, regs), 8, regs); - goto ldst_done; - case 1: /* stdu */ - err = write_mem(val, dsform_ea(instr, regs), 8, regs); - goto ldst_done; - } - break; -#endif /* __powerpc64__ */ - - } - err = -EINVAL; - - ldst_done: - if (err) { - regs->gpr[ra] = old_ra; - return 0; /* invoke DSI if -EFAULT? */ - } - instr_done: - regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4); - return 1; - - logical_done: - if (instr & 1) - set_cr0(regs, ra); - goto instr_done; - - arith_done: - if (instr & 1) - set_cr0(regs, rd); - goto instr_done; -} |