^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * License. See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (c) 2014 Imagination Technologies Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Author: Markos Chandras <markos.chandras@imgtec.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * MIPS R2 user space instruction emulator for MIPS R6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/bug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/asm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/branch.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/break.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/fpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <asm/fpu_emulator.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <asm/inst.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <asm/mips-r2-to-r6-emul.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <asm/local.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <asm/mipsregs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define ADDIU "daddiu "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define INS "dins "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define EXT "dext "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define ADDIU "addiu "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define INS "ins "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define EXT "ext "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #endif /* CONFIG_64BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define SB "sb "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define LB "lb "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define LL "ll "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define SC "sc "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static DEFINE_PER_CPU(struct mips_r2_emulator_stats, mipsr2emustats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static DEFINE_PER_CPU(struct mips_r2_emulator_stats, mipsr2bdemustats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static DEFINE_PER_CPU(struct mips_r2br_emulator_stats, mipsr2bremustats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) extern const unsigned int fpucondbit[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define MIPS_R2_EMUL_TOTAL_PASS 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) int mipsr2_emulation = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static int __init mipsr2emu_enable(char *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) mipsr2_emulation = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) pr_info("MIPS R2-to-R6 Emulator Enabled!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) __setup("mipsr2emu", mipsr2emu_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * mipsr6_emul - Emulate some frequent R2/R5/R6 instructions in delay slot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * for performance instead of the traditional way of using a stack trampoline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * which is rather slow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static inline int mipsr6_emul(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) switch (MIPSInst_OPCODE(ir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) case addiu_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (MIPSInst_RT(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) regs->regs[MIPSInst_RT(ir)] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) (s32)regs->regs[MIPSInst_RS(ir)] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) (s32)MIPSInst_SIMM(ir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) case daddiu_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (IS_ENABLED(CONFIG_32BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (MIPSInst_RT(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) regs->regs[MIPSInst_RT(ir)] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) (s64)regs->regs[MIPSInst_RS(ir)] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) (s64)MIPSInst_SIMM(ir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) case lwc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) case swc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) case cop1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) case cop1x_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* FPU instructions in delay slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return -SIGFPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) case spec_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) switch (MIPSInst_FUNC(ir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) case or_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) regs->regs[MIPSInst_RD(ir)] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) regs->regs[MIPSInst_RS(ir)] |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) regs->regs[MIPSInst_RT(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) case sll_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (MIPSInst_RS(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) regs->regs[MIPSInst_RD(ir)] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) (s32)(((u32)regs->regs[MIPSInst_RT(ir)]) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) MIPSInst_FD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) case srl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (MIPSInst_RS(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) regs->regs[MIPSInst_RD(ir)] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) (s32)(((u32)regs->regs[MIPSInst_RT(ir)]) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) MIPSInst_FD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) case addu_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (MIPSInst_FD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) regs->regs[MIPSInst_RD(ir)] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) (s32)((u32)regs->regs[MIPSInst_RS(ir)] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) (u32)regs->regs[MIPSInst_RT(ir)]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) case subu_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (MIPSInst_FD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) regs->regs[MIPSInst_RD(ir)] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) (s32)((u32)regs->regs[MIPSInst_RS(ir)] -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) (u32)regs->regs[MIPSInst_RT(ir)]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) case dsll_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (IS_ENABLED(CONFIG_32BIT) || MIPSInst_RS(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) regs->regs[MIPSInst_RD(ir)] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) (s64)(((u64)regs->regs[MIPSInst_RT(ir)]) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) MIPSInst_FD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) case dsrl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (IS_ENABLED(CONFIG_32BIT) || MIPSInst_RS(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) regs->regs[MIPSInst_RD(ir)] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) (s64)(((u64)regs->regs[MIPSInst_RT(ir)]) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) MIPSInst_FD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) case daddu_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (IS_ENABLED(CONFIG_32BIT) || MIPSInst_FD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) regs->regs[MIPSInst_RD(ir)] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) (u64)regs->regs[MIPSInst_RS(ir)] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) (u64)regs->regs[MIPSInst_RT(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) case dsubu_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (IS_ENABLED(CONFIG_32BIT) || MIPSInst_FD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) regs->regs[MIPSInst_RD(ir)] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) (s64)((u64)regs->regs[MIPSInst_RS(ir)] -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) (u64)regs->regs[MIPSInst_RT(ir)]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) pr_debug("No fastpath BD emulation for instruction 0x%08x (op: %02x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) ir, MIPSInst_OPCODE(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * movf_func - Emulate a MOVF instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static int movf_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) u32 csr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) u32 cond;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) csr = current->thread.fpu.fcr31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) cond = fpucondbit[MIPSInst_RT(ir) >> 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (((csr & cond) == 0) && MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) regs->regs[MIPSInst_RD(ir)] = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) MIPS_R2_STATS(movs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * movt_func - Emulate a MOVT instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static int movt_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) u32 csr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) u32 cond;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) csr = current->thread.fpu.fcr31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) cond = fpucondbit[MIPSInst_RT(ir) >> 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (((csr & cond) != 0) && MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) regs->regs[MIPSInst_RD(ir)] = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) MIPS_R2_STATS(movs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * jr_func - Emulate a JR instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * @pt_regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * Returns SIGILL if JR was in delay slot, SIGEMT if we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * can't compute the EPC, SIGSEGV if we can't access the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * userland instruction or 0 on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static int jr_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) unsigned long cepc, epc, nepc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) u32 nir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (delay_slot(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* EPC after the RI/JR instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) nepc = regs->cp0_epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /* Roll back to the reserved R2 JR instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) regs->cp0_epc -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) epc = regs->cp0_epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) err = __compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return SIGEMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /* Computed EPC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) cepc = regs->cp0_epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* Get DS instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) err = __get_user(nir, (u32 __user *)nepc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) MIPS_R2BR_STATS(jrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /* If nir == 0(NOP), then nothing else to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (nir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * Negative err means FPU instruction in BD-slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * Zero err means 'BD-slot emulation done'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * For anything else we go back to trampoline emulation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) err = mipsr6_emul(regs, nir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (err > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) regs->cp0_epc = nepc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) err = mips_dsemul(regs, nir, epc, cepc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (err == SIGILL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) err = SIGEMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) MIPS_R2_STATS(dsemul);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * movz_func - Emulate a MOVZ instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static int movz_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (((regs->regs[MIPSInst_RT(ir)]) == 0) && MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) regs->regs[MIPSInst_RD(ir)] = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) MIPS_R2_STATS(movs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * movn_func - Emulate a MOVZ instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static int movn_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (((regs->regs[MIPSInst_RT(ir)]) != 0) && MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) regs->regs[MIPSInst_RD(ir)] = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) MIPS_R2_STATS(movs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * mfhi_func - Emulate a MFHI instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) static int mfhi_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) regs->regs[MIPSInst_RD(ir)] = regs->hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) MIPS_R2_STATS(hilo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * mthi_func - Emulate a MTHI instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static int mthi_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) regs->hi = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) MIPS_R2_STATS(hilo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * mflo_func - Emulate a MFLO instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static int mflo_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) regs->regs[MIPSInst_RD(ir)] = regs->lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) MIPS_R2_STATS(hilo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * mtlo_func - Emulate a MTLO instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) static int mtlo_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) regs->lo = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) MIPS_R2_STATS(hilo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * mult_func - Emulate a MULT instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) static int mult_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) s64 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) s32 rt, rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) rt = regs->regs[MIPSInst_RT(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) rs = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) res = (s64)rt * (s64)rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) rs = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) regs->lo = (s64)rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) rt = res >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) res = (s64)rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) regs->hi = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) MIPS_R2_STATS(muls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * multu_func - Emulate a MULTU instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) static int multu_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) u64 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) u32 rt, rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) rt = regs->regs[MIPSInst_RT(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) rs = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) res = (u64)rt * (u64)rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) rt = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) regs->lo = (s64)(s32)rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) regs->hi = (s64)(s32)(res >> 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) MIPS_R2_STATS(muls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * div_func - Emulate a DIV instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) static int div_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) s32 rt, rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) rt = regs->regs[MIPSInst_RT(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) rs = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) regs->lo = (s64)(rs / rt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) regs->hi = (s64)(rs % rt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) MIPS_R2_STATS(divs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * divu_func - Emulate a DIVU instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static int divu_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) u32 rt, rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) rt = regs->regs[MIPSInst_RT(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) rs = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) regs->lo = (s64)(rs / rt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) regs->hi = (s64)(rs % rt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) MIPS_R2_STATS(divs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * dmult_func - Emulate a DMULT instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) * Returns 0 on success or SIGILL for 32-bit kernels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) static int dmult_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) s64 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) s64 rt, rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (IS_ENABLED(CONFIG_32BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) rt = regs->regs[MIPSInst_RT(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) rs = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) res = rt * rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) regs->lo = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) "dmuh %0, %1, %2\t\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) : "=r"(res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) : "r"(rt), "r"(rs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) regs->hi = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) MIPS_R2_STATS(muls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * dmultu_func - Emulate a DMULTU instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) * Returns 0 on success or SIGILL for 32-bit kernels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) static int dmultu_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) u64 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) u64 rt, rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (IS_ENABLED(CONFIG_32BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) rt = regs->regs[MIPSInst_RT(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) rs = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) res = rt * rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) regs->lo = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) "dmuhu %0, %1, %2\t\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) : "=r"(res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) : "r"(rt), "r"(rs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) regs->hi = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) MIPS_R2_STATS(muls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * ddiv_func - Emulate a DDIV instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * Returns 0 on success or SIGILL for 32-bit kernels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) static int ddiv_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) s64 rt, rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (IS_ENABLED(CONFIG_32BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) rt = regs->regs[MIPSInst_RT(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) rs = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) regs->lo = rs / rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) regs->hi = rs % rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) MIPS_R2_STATS(divs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * ddivu_func - Emulate a DDIVU instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * Returns 0 on success or SIGILL for 32-bit kernels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) static int ddivu_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) u64 rt, rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (IS_ENABLED(CONFIG_32BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) rt = regs->regs[MIPSInst_RT(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) rs = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) regs->lo = rs / rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) regs->hi = rs % rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) MIPS_R2_STATS(divs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) /* R6 removed instructions for the SPECIAL opcode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) static const struct r2_decoder_table spec_op_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) { 0xfc1ff83f, 0x00000008, jr_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) { 0xfc00ffff, 0x00000018, mult_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) { 0xfc00ffff, 0x00000019, multu_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) { 0xfc00ffff, 0x0000001c, dmult_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) { 0xfc00ffff, 0x0000001d, dmultu_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) { 0xffff07ff, 0x00000010, mfhi_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) { 0xfc1fffff, 0x00000011, mthi_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) { 0xffff07ff, 0x00000012, mflo_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) { 0xfc1fffff, 0x00000013, mtlo_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) { 0xfc0307ff, 0x00000001, movf_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) { 0xfc0307ff, 0x00010001, movt_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) { 0xfc0007ff, 0x0000000a, movz_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) { 0xfc0007ff, 0x0000000b, movn_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) { 0xfc00ffff, 0x0000001a, div_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) { 0xfc00ffff, 0x0000001b, divu_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) { 0xfc00ffff, 0x0000001e, ddiv_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) { 0xfc00ffff, 0x0000001f, ddivu_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) * madd_func - Emulate a MADD instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) static int madd_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) s64 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) s32 rt, rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) rt = regs->regs[MIPSInst_RT(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) rs = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) res = (s64)rt * (s64)rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) rt = regs->hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) rs = regs->lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) res += ((((s64)rt) << 32) | (u32)rs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) rt = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) regs->lo = (s64)rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) rs = res >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) regs->hi = (s64)rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) MIPS_R2_STATS(dsps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) * maddu_func - Emulate a MADDU instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) static int maddu_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) u64 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) u32 rt, rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) rt = regs->regs[MIPSInst_RT(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) rs = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) res = (u64)rt * (u64)rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) rt = regs->hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) rs = regs->lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) res += ((((s64)rt) << 32) | (u32)rs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) rt = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) regs->lo = (s64)(s32)rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) rs = res >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) regs->hi = (s64)(s32)rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) MIPS_R2_STATS(dsps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * msub_func - Emulate a MSUB instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) static int msub_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) s64 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) s32 rt, rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) rt = regs->regs[MIPSInst_RT(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) rs = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) res = (s64)rt * (s64)rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) rt = regs->hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) rs = regs->lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) res = ((((s64)rt) << 32) | (u32)rs) - res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) rt = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) regs->lo = (s64)rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) rs = res >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) regs->hi = (s64)rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) MIPS_R2_STATS(dsps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) * msubu_func - Emulate a MSUBU instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) static int msubu_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) u64 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) u32 rt, rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) rt = regs->regs[MIPSInst_RT(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) rs = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) res = (u64)rt * (u64)rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) rt = regs->hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) rs = regs->lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) res = ((((s64)rt) << 32) | (u32)rs) - res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) rt = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) regs->lo = (s64)(s32)rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) rs = res >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) regs->hi = (s64)(s32)rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) MIPS_R2_STATS(dsps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) * mul_func - Emulate a MUL instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) static int mul_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) s64 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) s32 rt, rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (!MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) rt = regs->regs[MIPSInst_RT(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) rs = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) res = (s64)rt * (s64)rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) rs = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) regs->regs[MIPSInst_RD(ir)] = (s64)rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) MIPS_R2_STATS(muls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * clz_func - Emulate a CLZ instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) static int clz_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) u32 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) u32 rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (!MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) rs = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) __asm__ __volatile__("clz %0, %1" : "=r"(res) : "r"(rs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) regs->regs[MIPSInst_RD(ir)] = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) MIPS_R2_STATS(bops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) * clo_func - Emulate a CLO instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) static int clo_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) u32 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) u32 rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (!MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) rs = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) __asm__ __volatile__("clo %0, %1" : "=r"(res) : "r"(rs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) regs->regs[MIPSInst_RD(ir)] = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) MIPS_R2_STATS(bops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) * dclz_func - Emulate a DCLZ instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) static int dclz_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) u64 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) u64 rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (IS_ENABLED(CONFIG_32BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (!MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) rs = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) __asm__ __volatile__("dclz %0, %1" : "=r"(res) : "r"(rs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) regs->regs[MIPSInst_RD(ir)] = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) MIPS_R2_STATS(bops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) * dclo_func - Emulate a DCLO instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * @ir: Instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * Returns 0 since it always succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) static int dclo_func(struct pt_regs *regs, u32 ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) u64 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) u64 rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (IS_ENABLED(CONFIG_32BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (!MIPSInst_RD(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) rs = regs->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) __asm__ __volatile__("dclo %0, %1" : "=r"(res) : "r"(rs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) regs->regs[MIPSInst_RD(ir)] = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) MIPS_R2_STATS(bops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) /* R6 removed instructions for the SPECIAL2 opcode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) static const struct r2_decoder_table spec2_op_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) { 0xfc00ffff, 0x70000000, madd_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) { 0xfc00ffff, 0x70000001, maddu_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) { 0xfc0007ff, 0x70000002, mul_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) { 0xfc00ffff, 0x70000004, msub_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) { 0xfc00ffff, 0x70000005, msubu_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) { 0xfc0007ff, 0x70000020, clz_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) { 0xfc0007ff, 0x70000021, clo_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) { 0xfc0007ff, 0x70000024, dclz_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) { 0xfc0007ff, 0x70000025, dclo_func },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) static inline int mipsr2_find_op_func(struct pt_regs *regs, u32 inst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) const struct r2_decoder_table *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) const struct r2_decoder_table *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) for (p = table; p->func; p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if ((inst & p->mask) == p->code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) err = (p->func)(regs, inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) * mipsr2_decoder: Decode and emulate a MIPS R2 instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * @regs: Process register set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) * @inst: Instruction to decode and emulate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) * @fcr31: Floating Point Control and Status Register Cause bits returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) unsigned long vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) u32 nir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) unsigned long cpc, epc, nepc, r31, res, rs, rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) void __user *fault_addr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) int pass = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) repeat:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) r31 = regs->regs[31];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) epc = regs->cp0_epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) err = compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) return SIGEMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) pr_debug("Emulating the 0x%08x R2 instruction @ 0x%08lx (pass=%d))\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) inst, epc, pass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) switch (MIPSInst_OPCODE(inst)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) case spec_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) err = mipsr2_find_op_func(regs, inst, spec_op_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) /* FPU instruction under JR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) regs->cp0_cause |= CAUSEF_BD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) goto fpu_emul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) case spec2_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) err = mipsr2_find_op_func(regs, inst, spec2_op_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) case bcond_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) rt = MIPSInst_RT(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) rs = MIPSInst_RS(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) switch (rt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) case tgei_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) if ((long)regs->regs[rs] >= MIPSInst_SIMM(inst))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) do_trap_or_bp(regs, 0, 0, "TGEI");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) MIPS_R2_STATS(traps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) case tgeiu_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (regs->regs[rs] >= MIPSInst_UIMM(inst))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) do_trap_or_bp(regs, 0, 0, "TGEIU");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) MIPS_R2_STATS(traps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) case tlti_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) if ((long)regs->regs[rs] < MIPSInst_SIMM(inst))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) do_trap_or_bp(regs, 0, 0, "TLTI");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) MIPS_R2_STATS(traps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) case tltiu_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (regs->regs[rs] < MIPSInst_UIMM(inst))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) do_trap_or_bp(regs, 0, 0, "TLTIU");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) MIPS_R2_STATS(traps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) case teqi_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) if (regs->regs[rs] == MIPSInst_SIMM(inst))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) do_trap_or_bp(regs, 0, 0, "TEQI");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) MIPS_R2_STATS(traps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) case tnei_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if (regs->regs[rs] != MIPSInst_SIMM(inst))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) do_trap_or_bp(regs, 0, 0, "TNEI");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) MIPS_R2_STATS(traps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) case bltzl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) case bgezl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) case bltzall_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) case bgezall_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if (delay_slot(regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) err = SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) regs->regs[31] = r31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) regs->cp0_epc = epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) err = __compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) return SIGEMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (err != BRANCH_LIKELY_TAKEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) cpc = regs->cp0_epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) nepc = epc + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) err = __get_user(nir, (u32 __user *)nepc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) err = SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) * This will probably be optimized away when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) * CONFIG_DEBUG_FS is not enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) switch (rt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) case bltzl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) MIPS_R2BR_STATS(bltzl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) case bgezl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) MIPS_R2BR_STATS(bgezl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) case bltzall_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) MIPS_R2BR_STATS(bltzall);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) case bgezall_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) MIPS_R2BR_STATS(bgezall);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) switch (MIPSInst_OPCODE(nir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) case cop1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) case cop1x_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) case lwc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) case swc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) regs->cp0_cause |= CAUSEF_BD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) goto fpu_emul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (nir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) err = mipsr6_emul(regs, nir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (err > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) err = mips_dsemul(regs, nir, epc, cpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (err == SIGILL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) err = SIGEMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) MIPS_R2_STATS(dsemul);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) case bltzal_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) case bgezal_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) if (delay_slot(regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) err = SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) regs->regs[31] = r31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) regs->cp0_epc = epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) err = __compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) return SIGEMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) cpc = regs->cp0_epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) nepc = epc + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) err = __get_user(nir, (u32 __user *)nepc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) err = SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) * This will probably be optimized away when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) * CONFIG_DEBUG_FS is not enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) switch (rt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) case bltzal_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) MIPS_R2BR_STATS(bltzal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) case bgezal_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) MIPS_R2BR_STATS(bgezal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) switch (MIPSInst_OPCODE(nir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) case cop1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) case cop1x_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) case lwc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) case swc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) regs->cp0_cause |= CAUSEF_BD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) goto fpu_emul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) if (nir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) err = mipsr6_emul(regs, nir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) if (err > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) err = mips_dsemul(regs, nir, epc, cpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (err == SIGILL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) err = SIGEMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) MIPS_R2_STATS(dsemul);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) regs->regs[31] = r31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) regs->cp0_epc = epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) err = SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) case blezl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) case bgtzl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) * For BLEZL and BGTZL, rt field must be set to 0. If this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) * is not the case, this may be an encoding of a MIPS R6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) * instruction, so return to CPU execution if this occurs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) if (MIPSInst_RT(inst)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) err = SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) case beql_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) case bnel_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (delay_slot(regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) err = SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) regs->regs[31] = r31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) regs->cp0_epc = epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) err = __compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) return SIGEMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (err != BRANCH_LIKELY_TAKEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) cpc = regs->cp0_epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) nepc = epc + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) err = __get_user(nir, (u32 __user *)nepc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) err = SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) * This will probably be optimized away when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) * CONFIG_DEBUG_FS is not enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) switch (MIPSInst_OPCODE(inst)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) case beql_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) MIPS_R2BR_STATS(beql);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) case bnel_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) MIPS_R2BR_STATS(bnel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) case blezl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) MIPS_R2BR_STATS(blezl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) case bgtzl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) MIPS_R2BR_STATS(bgtzl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) switch (MIPSInst_OPCODE(nir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) case cop1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) case cop1x_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) case lwc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) case swc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) regs->cp0_cause |= CAUSEF_BD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) goto fpu_emul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) if (nir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) err = mipsr6_emul(regs, nir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (err > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) err = mips_dsemul(regs, nir, epc, cpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) if (err == SIGILL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) err = SIGEMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) MIPS_R2_STATS(dsemul);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) case lwc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) case swc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) case cop1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) case cop1x_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) fpu_emul:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) regs->regs[31] = r31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) regs->cp0_epc = epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) err = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) &fault_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) * We can't allow the emulated instruction to leave any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) * enabled Cause bits set in $fcr31.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) *fcr31 = res = mask_fcr31_x(current->thread.fpu.fcr31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) current->thread.fpu.fcr31 &= ~res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) * this is a tricky issue - lose_fpu() uses LL/SC atomics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) * if FPU is owned and effectively cancels user level LL/SC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) * So, it could be logical to don't restore FPU ownership here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) * But the sequence of multiple FPU instructions is much much
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) * more often than LL-FPU-SC and I prefer loop here until
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) * next scheduler cycle cancels FPU ownership
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) own_fpu(1); /* Restore FPU state. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) current->thread.cp0_baduaddr = (unsigned long)fault_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) MIPS_R2_STATS(fpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) case lwl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) rt = regs->regs[MIPSInst_RT(inst)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) if (!access_ok((void __user *)vaddr, 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) current->thread.cp0_baduaddr = vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) err = SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) " .set push\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) " .set reorder\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) #ifdef CONFIG_CPU_LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) "1:" LB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) INS "%0, %1, 24, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) ADDIU "%2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) "2:" LB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) INS "%0, %1, 16, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) ADDIU "%2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) "3:" LB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) INS "%0, %1, 8, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) ADDIU "%2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) "4:" LB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) INS "%0, %1, 0, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) #else /* !CONFIG_CPU_LITTLE_ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) "1:" LB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) INS "%0, %1, 24, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) ADDIU "%2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) "2:" LB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) INS "%0, %1, 16, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) ADDIU "%2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) "3:" LB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) INS "%0, %1, 8, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) ADDIU "%2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) "4:" LB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) INS "%0, %1, 0, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) #endif /* CONFIG_CPU_LITTLE_ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) "9: sll %0, %0, 0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) "10:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) " .insn\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) " .section .fixup,\"ax\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) "8: li %3,%4\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) " j 10b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) " .previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) " .section __ex_table,\"a\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) STR(PTR) " 1b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) STR(PTR) " 2b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) STR(PTR) " 3b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) STR(PTR) " 4b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) " .previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) " .set pop\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) : "+&r"(rt), "=&r"(rs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) "+&r"(vaddr), "+&r"(err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) : "i"(SIGSEGV));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if (MIPSInst_RT(inst) && !err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) regs->regs[MIPSInst_RT(inst)] = rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) MIPS_R2_STATS(loads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) case lwr_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) rt = regs->regs[MIPSInst_RT(inst)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) if (!access_ok((void __user *)vaddr, 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) current->thread.cp0_baduaddr = vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) err = SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) " .set push\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) " .set reorder\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) #ifdef CONFIG_CPU_LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) "1:" LB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) INS "%0, %1, 0, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) ADDIU "%2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) "2:" LB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) INS "%0, %1, 8, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) ADDIU "%2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) "3:" LB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) INS "%0, %1, 16, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) ADDIU "%2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) "4:" LB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) INS "%0, %1, 24, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) " sll %0, %0, 0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) #else /* !CONFIG_CPU_LITTLE_ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) "1:" LB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) INS "%0, %1, 0, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) ADDIU "%2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) "2:" LB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) INS "%0, %1, 8, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) ADDIU "%2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) "3:" LB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) INS "%0, %1, 16, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) ADDIU "%2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) "4:" LB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) INS "%0, %1, 24, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) " sll %0, %0, 0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) #endif /* CONFIG_CPU_LITTLE_ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) "9:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) "10:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) " .insn\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) " .section .fixup,\"ax\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) "8: li %3,%4\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) " j 10b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) " .previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) " .section __ex_table,\"a\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) STR(PTR) " 1b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) STR(PTR) " 2b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) STR(PTR) " 3b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) STR(PTR) " 4b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) " .previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) " .set pop\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) : "+&r"(rt), "=&r"(rs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) "+&r"(vaddr), "+&r"(err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) : "i"(SIGSEGV));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) if (MIPSInst_RT(inst) && !err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) regs->regs[MIPSInst_RT(inst)] = rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) MIPS_R2_STATS(loads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) case swl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) rt = regs->regs[MIPSInst_RT(inst)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) if (!access_ok((void __user *)vaddr, 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) current->thread.cp0_baduaddr = vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) err = SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) " .set push\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) " .set reorder\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) #ifdef CONFIG_CPU_LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) EXT "%1, %0, 24, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) "1:" SB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) ADDIU "%2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) EXT "%1, %0, 16, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) "2:" SB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) ADDIU "%2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) EXT "%1, %0, 8, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) "3:" SB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) ADDIU "%2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) EXT "%1, %0, 0, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) "4:" SB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) #else /* !CONFIG_CPU_LITTLE_ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) EXT "%1, %0, 24, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) "1:" SB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) ADDIU "%2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) EXT "%1, %0, 16, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) "2:" SB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) ADDIU "%2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) EXT "%1, %0, 8, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) "3:" SB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) ADDIU "%2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) EXT "%1, %0, 0, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) "4:" SB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) #endif /* CONFIG_CPU_LITTLE_ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) "9:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) " .insn\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) " .section .fixup,\"ax\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) "8: li %3,%4\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) " j 9b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) " .previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) " .section __ex_table,\"a\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) STR(PTR) " 1b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) STR(PTR) " 2b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) STR(PTR) " 3b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) STR(PTR) " 4b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) " .previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) " .set pop\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) : "+&r"(rt), "=&r"(rs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) "+&r"(vaddr), "+&r"(err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) : "i"(SIGSEGV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) MIPS_R2_STATS(stores);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) case swr_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) rt = regs->regs[MIPSInst_RT(inst)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) if (!access_ok((void __user *)vaddr, 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) current->thread.cp0_baduaddr = vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) err = SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) " .set push\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) " .set reorder\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) #ifdef CONFIG_CPU_LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) EXT "%1, %0, 0, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) "1:" SB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) ADDIU "%2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) EXT "%1, %0, 8, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) "2:" SB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) ADDIU "%2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) EXT "%1, %0, 16, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) "3:" SB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) ADDIU "%2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) EXT "%1, %0, 24, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) "4:" SB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) #else /* !CONFIG_CPU_LITTLE_ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) EXT "%1, %0, 0, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) "1:" SB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) ADDIU "%2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) EXT "%1, %0, 8, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) "2:" SB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) ADDIU "%2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) EXT "%1, %0, 16, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) "3:" SB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) " andi %1, %2, 0x3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) ADDIU "%2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) EXT "%1, %0, 24, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) "4:" SB "%1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) #endif /* CONFIG_CPU_LITTLE_ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) "9:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) " .insn\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) " .section .fixup,\"ax\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) "8: li %3,%4\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) " j 9b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) " .previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) " .section __ex_table,\"a\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) STR(PTR) " 1b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) STR(PTR) " 2b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) STR(PTR) " 3b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) STR(PTR) " 4b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) " .previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) " .set pop\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) : "+&r"(rt), "=&r"(rs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) "+&r"(vaddr), "+&r"(err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) : "i"(SIGSEGV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) MIPS_R2_STATS(stores);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) case ldl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) if (IS_ENABLED(CONFIG_32BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) err = SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) rt = regs->regs[MIPSInst_RT(inst)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) if (!access_ok((void __user *)vaddr, 8)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) current->thread.cp0_baduaddr = vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) err = SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) " .set push\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) " .set reorder\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) #ifdef CONFIG_CPU_LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) "1: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) " dinsu %0, %1, 56, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) "2: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) " dinsu %0, %1, 48, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) "3: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) " dinsu %0, %1, 40, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) "4: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) " dinsu %0, %1, 32, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) "5: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) " dins %0, %1, 24, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) "6: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) " dins %0, %1, 16, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) "7: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) " dins %0, %1, 8, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) "0: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) " dins %0, %1, 0, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) #else /* !CONFIG_CPU_LITTLE_ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) "1: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) " dinsu %0, %1, 56, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) "2: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) " dinsu %0, %1, 48, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) "3: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) " dinsu %0, %1, 40, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) "4: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) " dinsu %0, %1, 32, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) "5: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) " dins %0, %1, 24, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) "6: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) " dins %0, %1, 16, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) "7: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) " dins %0, %1, 8, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) "0: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) " dins %0, %1, 0, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) #endif /* CONFIG_CPU_LITTLE_ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) "9:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) " .insn\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) " .section .fixup,\"ax\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) "8: li %3,%4\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) " j 9b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) " .previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) " .section __ex_table,\"a\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) STR(PTR) " 1b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) STR(PTR) " 2b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) STR(PTR) " 3b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) STR(PTR) " 4b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) STR(PTR) " 5b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) STR(PTR) " 6b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) STR(PTR) " 7b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) STR(PTR) " 0b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) " .previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) " .set pop\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) : "+&r"(rt), "=&r"(rs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) "+&r"(vaddr), "+&r"(err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) : "i"(SIGSEGV));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) if (MIPSInst_RT(inst) && !err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) regs->regs[MIPSInst_RT(inst)] = rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) MIPS_R2_STATS(loads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) case ldr_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) if (IS_ENABLED(CONFIG_32BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) err = SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) rt = regs->regs[MIPSInst_RT(inst)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) if (!access_ok((void __user *)vaddr, 8)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) current->thread.cp0_baduaddr = vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) err = SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) " .set push\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) " .set reorder\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) #ifdef CONFIG_CPU_LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) "1: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) " dins %0, %1, 0, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) "2: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) " dins %0, %1, 8, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) "3: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) " dins %0, %1, 16, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) "4: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) " dins %0, %1, 24, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) "5: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) " dinsu %0, %1, 32, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) "6: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) " dinsu %0, %1, 40, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) "7: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) " dinsu %0, %1, 48, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) "0: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) " dinsu %0, %1, 56, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) #else /* !CONFIG_CPU_LITTLE_ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) "1: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) " dins %0, %1, 0, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) "2: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) " dins %0, %1, 8, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) "3: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) " dins %0, %1, 16, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) "4: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) " dins %0, %1, 24, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) "5: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) " dinsu %0, %1, 32, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) "6: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) " dinsu %0, %1, 40, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) "7: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) " dinsu %0, %1, 48, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) "0: lb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) " dinsu %0, %1, 56, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) #endif /* CONFIG_CPU_LITTLE_ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) "9:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) " .insn\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) " .section .fixup,\"ax\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) "8: li %3,%4\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) " j 9b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) " .previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) " .section __ex_table,\"a\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) STR(PTR) " 1b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) STR(PTR) " 2b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) STR(PTR) " 3b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) STR(PTR) " 4b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) STR(PTR) " 5b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) STR(PTR) " 6b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) STR(PTR) " 7b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) STR(PTR) " 0b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) " .previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) " .set pop\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) : "+&r"(rt), "=&r"(rs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) "+&r"(vaddr), "+&r"(err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) : "i"(SIGSEGV));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) if (MIPSInst_RT(inst) && !err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) regs->regs[MIPSInst_RT(inst)] = rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) MIPS_R2_STATS(loads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) case sdl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) if (IS_ENABLED(CONFIG_32BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) err = SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) rt = regs->regs[MIPSInst_RT(inst)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) if (!access_ok((void __user *)vaddr, 8)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) current->thread.cp0_baduaddr = vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) err = SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) " .set push\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) " .set reorder\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) #ifdef CONFIG_CPU_LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) " dextu %1, %0, 56, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) "1: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) " dextu %1, %0, 48, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) "2: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) " dextu %1, %0, 40, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) "3: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) " dextu %1, %0, 32, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) "4: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) " dext %1, %0, 24, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) "5: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) " dext %1, %0, 16, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) "6: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) " dext %1, %0, 8, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) "7: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) " dext %1, %0, 0, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) "0: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) #else /* !CONFIG_CPU_LITTLE_ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) " dextu %1, %0, 56, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) "1: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) " dextu %1, %0, 48, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) "2: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) " dextu %1, %0, 40, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) "3: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) " dextu %1, %0, 32, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) "4: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) " dext %1, %0, 24, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) "5: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) " dext %1, %0, 16, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) "6: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) " dext %1, %0, 8, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) "7: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) " dext %1, %0, 0, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) "0: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) #endif /* CONFIG_CPU_LITTLE_ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) "9:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) " .insn\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) " .section .fixup,\"ax\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) "8: li %3,%4\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) " j 9b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) " .previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) " .section __ex_table,\"a\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) STR(PTR) " 1b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) STR(PTR) " 2b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) STR(PTR) " 3b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) STR(PTR) " 4b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) STR(PTR) " 5b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) STR(PTR) " 6b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) STR(PTR) " 7b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) STR(PTR) " 0b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) " .previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) " .set pop\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) : "+&r"(rt), "=&r"(rs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) "+&r"(vaddr), "+&r"(err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) : "i"(SIGSEGV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) MIPS_R2_STATS(stores);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) case sdr_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) if (IS_ENABLED(CONFIG_32BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) err = SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) rt = regs->regs[MIPSInst_RT(inst)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) if (!access_ok((void __user *)vaddr, 8)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) current->thread.cp0_baduaddr = vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) err = SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) " .set push\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) " .set reorder\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) #ifdef CONFIG_CPU_LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) " dext %1, %0, 0, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) "1: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) " dext %1, %0, 8, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) "2: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) " dext %1, %0, 16, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) "3: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) " dext %1, %0, 24, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) "4: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) " dextu %1, %0, 32, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) "5: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) " dextu %1, %0, 40, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) "6: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) " dextu %1, %0, 48, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) "7: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) " daddiu %2, %2, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) " dextu %1, %0, 56, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) "0: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) #else /* !CONFIG_CPU_LITTLE_ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) " dext %1, %0, 0, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) "1: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) " dext %1, %0, 8, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) "2: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) " dext %1, %0, 16, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) "3: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) " dext %1, %0, 24, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) "4: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) " dextu %1, %0, 32, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) "5: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) " dextu %1, %0, 40, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) "6: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) " dextu %1, %0, 48, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) "7: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) " andi %1, %2, 0x7\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) " beq $0, %1, 9f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) " daddiu %2, %2, -1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) " dextu %1, %0, 56, 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) "0: sb %1, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) #endif /* CONFIG_CPU_LITTLE_ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) "9:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) " .insn\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) " .section .fixup,\"ax\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) "8: li %3,%4\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) " j 9b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) " .previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) " .section __ex_table,\"a\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) STR(PTR) " 1b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) STR(PTR) " 2b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) STR(PTR) " 3b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) STR(PTR) " 4b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) STR(PTR) " 5b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) STR(PTR) " 6b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) STR(PTR) " 7b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) STR(PTR) " 0b,8b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) " .previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) " .set pop\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) : "+&r"(rt), "=&r"(rs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) "+&r"(vaddr), "+&r"(err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) : "i"(SIGSEGV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) MIPS_R2_STATS(stores);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) case ll_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) if (vaddr & 0x3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) current->thread.cp0_baduaddr = vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) err = SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) if (!access_ok((void __user *)vaddr, 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) current->thread.cp0_baduaddr = vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) err = SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) if (!cpu_has_rw_llb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) * An LL/SC block can't be safely emulated without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) * a Config5/LLB availability. So it's probably time to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) * kill our process before things get any worse. This is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) * because Config5/LLB allows us to use ERETNC so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) * the LLAddr/LLB bit is not cleared when we return from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) * an exception. MIPS R2 LL/SC instructions trap with an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) * RI exception so once we emulate them here, we return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) * back to userland with ERETNC. That preserves the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) * LLAddr/LLB so the subsequent SC instruction will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) * succeed preserving the atomic semantics of the LL/SC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) * block. Without that, there is no safe way to emulate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) * an LL/SC block in MIPSR2 userland.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) pr_err("Can't emulate MIPSR2 LL/SC without Config5/LLB\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) err = SIGKILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) "1:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) "ll %0, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) "2:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) ".insn\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) ".section .fixup,\"ax\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) "3:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) "li %1, %3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) "j 2b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) ".previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) ".section __ex_table,\"a\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) STR(PTR) " 1b,3b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) ".previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) : "=&r"(res), "+&r"(err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) : "r"(vaddr), "i"(SIGSEGV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) if (MIPSInst_RT(inst) && !err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) regs->regs[MIPSInst_RT(inst)] = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) MIPS_R2_STATS(llsc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) case sc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) if (vaddr & 0x3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) current->thread.cp0_baduaddr = vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) err = SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) if (!access_ok((void __user *)vaddr, 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) current->thread.cp0_baduaddr = vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) err = SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) if (!cpu_has_rw_llb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) * An LL/SC block can't be safely emulated without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) * a Config5/LLB availability. So it's probably time to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) * kill our process before things get any worse. This is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) * because Config5/LLB allows us to use ERETNC so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) * the LLAddr/LLB bit is not cleared when we return from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) * an exception. MIPS R2 LL/SC instructions trap with an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) * RI exception so once we emulate them here, we return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) * back to userland with ERETNC. That preserves the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) * LLAddr/LLB so the subsequent SC instruction will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) * succeed preserving the atomic semantics of the LL/SC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) * block. Without that, there is no safe way to emulate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) * an LL/SC block in MIPSR2 userland.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) pr_err("Can't emulate MIPSR2 LL/SC without Config5/LLB\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) err = SIGKILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) res = regs->regs[MIPSInst_RT(inst)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) "1:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) "sc %0, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) "2:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) ".insn\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) ".section .fixup,\"ax\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) "3:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) "li %1, %3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) "j 2b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) ".previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) ".section __ex_table,\"a\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) STR(PTR) " 1b,3b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) ".previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) : "+&r"(res), "+&r"(err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) : "r"(vaddr), "i"(SIGSEGV));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) if (MIPSInst_RT(inst) && !err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) regs->regs[MIPSInst_RT(inst)] = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) MIPS_R2_STATS(llsc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) case lld_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) if (IS_ENABLED(CONFIG_32BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) err = SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) if (vaddr & 0x7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) current->thread.cp0_baduaddr = vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) err = SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) if (!access_ok((void __user *)vaddr, 8)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) current->thread.cp0_baduaddr = vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) err = SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) if (!cpu_has_rw_llb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) * An LL/SC block can't be safely emulated without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) * a Config5/LLB availability. So it's probably time to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) * kill our process before things get any worse. This is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) * because Config5/LLB allows us to use ERETNC so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) * the LLAddr/LLB bit is not cleared when we return from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) * an exception. MIPS R2 LL/SC instructions trap with an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) * RI exception so once we emulate them here, we return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) * back to userland with ERETNC. That preserves the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) * LLAddr/LLB so the subsequent SC instruction will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) * succeed preserving the atomic semantics of the LL/SC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) * block. Without that, there is no safe way to emulate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) * an LL/SC block in MIPSR2 userland.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) pr_err("Can't emulate MIPSR2 LL/SC without Config5/LLB\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) err = SIGKILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) "1:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) "lld %0, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) "2:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) ".insn\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) ".section .fixup,\"ax\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) "3:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) "li %1, %3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) "j 2b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) ".previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) ".section __ex_table,\"a\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) STR(PTR) " 1b,3b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) ".previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) : "=&r"(res), "+&r"(err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) : "r"(vaddr), "i"(SIGSEGV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) if (MIPSInst_RT(inst) && !err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) regs->regs[MIPSInst_RT(inst)] = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) MIPS_R2_STATS(llsc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) case scd_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) if (IS_ENABLED(CONFIG_32BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) err = SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) if (vaddr & 0x7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) current->thread.cp0_baduaddr = vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) err = SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) if (!access_ok((void __user *)vaddr, 8)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) current->thread.cp0_baduaddr = vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) err = SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) if (!cpu_has_rw_llb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) * An LL/SC block can't be safely emulated without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) * a Config5/LLB availability. So it's probably time to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) * kill our process before things get any worse. This is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) * because Config5/LLB allows us to use ERETNC so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) * the LLAddr/LLB bit is not cleared when we return from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) * an exception. MIPS R2 LL/SC instructions trap with an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) * RI exception so once we emulate them here, we return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) * back to userland with ERETNC. That preserves the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) * LLAddr/LLB so the subsequent SC instruction will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) * succeed preserving the atomic semantics of the LL/SC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) * block. Without that, there is no safe way to emulate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) * an LL/SC block in MIPSR2 userland.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) pr_err("Can't emulate MIPSR2 LL/SC without Config5/LLB\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) err = SIGKILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) res = regs->regs[MIPSInst_RT(inst)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) "1:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) "scd %0, 0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) "2:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) ".insn\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) ".section .fixup,\"ax\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) "3:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) "li %1, %3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) "j 2b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) ".previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) ".section __ex_table,\"a\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) STR(PTR) " 1b,3b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) ".previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) : "+&r"(res), "+&r"(err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) : "r"(vaddr), "i"(SIGSEGV));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) if (MIPSInst_RT(inst) && !err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) regs->regs[MIPSInst_RT(inst)] = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) MIPS_R2_STATS(llsc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) case pref_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) /* skip it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) err = SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) * Let's not return to userland just yet. It's costly and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) * it's likely we have more R2 instructions to emulate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) if (!err && (pass++ < MIPS_R2_EMUL_TOTAL_PASS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) regs->cp0_cause &= ~CAUSEF_BD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) err = get_user(inst, (u32 __user *)regs->cp0_epc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) goto repeat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) err = SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) if (err && (err != SIGEMT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) regs->regs[31] = r31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) regs->cp0_epc = epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) /* Likely a MIPS R6 compatible instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) if (pass && (err == SIGILL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) static int mipsr2_emul_show(struct seq_file *s, void *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) seq_printf(s, "Instruction\tTotal\tBDslot\n------------------------------\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) seq_printf(s, "movs\t\t%ld\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) (unsigned long)__this_cpu_read(mipsr2emustats.movs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) (unsigned long)__this_cpu_read(mipsr2bdemustats.movs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) seq_printf(s, "hilo\t\t%ld\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) (unsigned long)__this_cpu_read(mipsr2emustats.hilo),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) (unsigned long)__this_cpu_read(mipsr2bdemustats.hilo));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) seq_printf(s, "muls\t\t%ld\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) (unsigned long)__this_cpu_read(mipsr2emustats.muls),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) (unsigned long)__this_cpu_read(mipsr2bdemustats.muls));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) seq_printf(s, "divs\t\t%ld\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) (unsigned long)__this_cpu_read(mipsr2emustats.divs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) (unsigned long)__this_cpu_read(mipsr2bdemustats.divs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) seq_printf(s, "dsps\t\t%ld\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) (unsigned long)__this_cpu_read(mipsr2emustats.dsps),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) (unsigned long)__this_cpu_read(mipsr2bdemustats.dsps));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) seq_printf(s, "bops\t\t%ld\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) (unsigned long)__this_cpu_read(mipsr2emustats.bops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) (unsigned long)__this_cpu_read(mipsr2bdemustats.bops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) seq_printf(s, "traps\t\t%ld\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) (unsigned long)__this_cpu_read(mipsr2emustats.traps),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) (unsigned long)__this_cpu_read(mipsr2bdemustats.traps));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) seq_printf(s, "fpus\t\t%ld\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) (unsigned long)__this_cpu_read(mipsr2emustats.fpus),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) (unsigned long)__this_cpu_read(mipsr2bdemustats.fpus));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) seq_printf(s, "loads\t\t%ld\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) (unsigned long)__this_cpu_read(mipsr2emustats.loads),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) (unsigned long)__this_cpu_read(mipsr2bdemustats.loads));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) seq_printf(s, "stores\t\t%ld\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) (unsigned long)__this_cpu_read(mipsr2emustats.stores),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) (unsigned long)__this_cpu_read(mipsr2bdemustats.stores));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) seq_printf(s, "llsc\t\t%ld\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) (unsigned long)__this_cpu_read(mipsr2emustats.llsc),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) (unsigned long)__this_cpu_read(mipsr2bdemustats.llsc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) seq_printf(s, "dsemul\t\t%ld\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) (unsigned long)__this_cpu_read(mipsr2emustats.dsemul),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) (unsigned long)__this_cpu_read(mipsr2bdemustats.dsemul));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) seq_printf(s, "jr\t\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) (unsigned long)__this_cpu_read(mipsr2bremustats.jrs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) seq_printf(s, "bltzl\t\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) (unsigned long)__this_cpu_read(mipsr2bremustats.bltzl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) seq_printf(s, "bgezl\t\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) (unsigned long)__this_cpu_read(mipsr2bremustats.bgezl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) seq_printf(s, "bltzll\t\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) (unsigned long)__this_cpu_read(mipsr2bremustats.bltzll));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) seq_printf(s, "bgezll\t\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) (unsigned long)__this_cpu_read(mipsr2bremustats.bgezll));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) seq_printf(s, "bltzal\t\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) (unsigned long)__this_cpu_read(mipsr2bremustats.bltzal));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) seq_printf(s, "bgezal\t\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) (unsigned long)__this_cpu_read(mipsr2bremustats.bgezal));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) seq_printf(s, "beql\t\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) (unsigned long)__this_cpu_read(mipsr2bremustats.beql));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) seq_printf(s, "bnel\t\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) (unsigned long)__this_cpu_read(mipsr2bremustats.bnel));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) seq_printf(s, "blezl\t\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) (unsigned long)__this_cpu_read(mipsr2bremustats.blezl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) seq_printf(s, "bgtzl\t\t%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) (unsigned long)__this_cpu_read(mipsr2bremustats.bgtzl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) static int mipsr2_clear_show(struct seq_file *s, void *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) mipsr2_emul_show(s, unused);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) __this_cpu_write((mipsr2emustats).movs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) __this_cpu_write((mipsr2bdemustats).movs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) __this_cpu_write((mipsr2emustats).hilo, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) __this_cpu_write((mipsr2bdemustats).hilo, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) __this_cpu_write((mipsr2emustats).muls, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) __this_cpu_write((mipsr2bdemustats).muls, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) __this_cpu_write((mipsr2emustats).divs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) __this_cpu_write((mipsr2bdemustats).divs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) __this_cpu_write((mipsr2emustats).dsps, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) __this_cpu_write((mipsr2bdemustats).dsps, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) __this_cpu_write((mipsr2emustats).bops, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) __this_cpu_write((mipsr2bdemustats).bops, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) __this_cpu_write((mipsr2emustats).traps, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) __this_cpu_write((mipsr2bdemustats).traps, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) __this_cpu_write((mipsr2emustats).fpus, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) __this_cpu_write((mipsr2bdemustats).fpus, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) __this_cpu_write((mipsr2emustats).loads, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) __this_cpu_write((mipsr2bdemustats).loads, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) __this_cpu_write((mipsr2emustats).stores, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) __this_cpu_write((mipsr2bdemustats).stores, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) __this_cpu_write((mipsr2emustats).llsc, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) __this_cpu_write((mipsr2bdemustats).llsc, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) __this_cpu_write((mipsr2emustats).dsemul, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) __this_cpu_write((mipsr2bdemustats).dsemul, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) __this_cpu_write((mipsr2bremustats).jrs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) __this_cpu_write((mipsr2bremustats).bltzl, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) __this_cpu_write((mipsr2bremustats).bgezl, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) __this_cpu_write((mipsr2bremustats).bltzll, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) __this_cpu_write((mipsr2bremustats).bgezll, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) __this_cpu_write((mipsr2bremustats).bltzall, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) __this_cpu_write((mipsr2bremustats).bgezall, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) __this_cpu_write((mipsr2bremustats).bltzal, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) __this_cpu_write((mipsr2bremustats).bgezal, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) __this_cpu_write((mipsr2bremustats).beql, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) __this_cpu_write((mipsr2bremustats).bnel, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) __this_cpu_write((mipsr2bremustats).blezl, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) __this_cpu_write((mipsr2bremustats).bgtzl, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) DEFINE_SHOW_ATTRIBUTE(mipsr2_emul);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) DEFINE_SHOW_ATTRIBUTE(mipsr2_clear);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) static int __init mipsr2_init_debugfs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) debugfs_create_file("r2_emul_stats", S_IRUGO, mips_debugfs_dir, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) &mipsr2_emul_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) debugfs_create_file("r2_emul_stats_clear", S_IRUGO, mips_debugfs_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) NULL, &mipsr2_clear_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) device_initcall(mipsr2_init_debugfs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) #endif /* CONFIG_DEBUG_FS */