^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * cp1emu.c: a MIPS coprocessor 1 (FPU) instruction emulator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * MIPS floating point support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 1994-2000 Algorithmics Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2000 MIPS Technologies, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * A complete emulator for MIPS coprocessor 1 instructions. This is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * required for #float(switch) or #float(trap), where it catches all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * COP1 instructions via the "CoProcessor Unusable" exception.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * More surprisingly it is also required for #float(ieee), to help out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * the hardware FPU at the boundaries of the IEEE-754 representation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * (denormalised values, infinities, underflow, etc). It is made
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * quite nasty because emulation of some non-COP1 instructions is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * required, e.g. in branch delay slots.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Note if you know that you won't have an FPU, then you'll get much
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * better performance by compiling with -msoft-float!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/percpu-defs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/perf_event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <asm/branch.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <asm/inst.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 <asm/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <asm/cpu-info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <asm/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <asm/fpu_emulator.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <asm/fpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <asm/mips-r2-to-r6-emul.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include "ieee754.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /* Function which emulates a floating point instruction. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) mips_instruction);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static int fpux_emu(struct pt_regs *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct mips_fpu_struct *, mips_instruction, void __user **);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* Control registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define FPCREG_RID 0 /* $0 = revision id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define FPCREG_FCCR 25 /* $25 = fccr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define FPCREG_FEXR 26 /* $26 = fexr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define FPCREG_FENR 28 /* $28 = fenr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define FPCREG_CSR 31 /* $31 = csr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* convert condition code register number to csr bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) const unsigned int fpucondbit[8] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) FPU_CSR_COND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) FPU_CSR_COND1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) FPU_CSR_COND2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) FPU_CSR_COND3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) FPU_CSR_COND4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) FPU_CSR_COND5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) FPU_CSR_COND6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) FPU_CSR_COND7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* (microMIPS) Convert certain microMIPS instructions to MIPS32 format. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static const int sd_format[] = {16, 17, 0, 0, 0, 0, 0, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static const int sdps_format[] = {16, 17, 22, 0, 0, 0, 0, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static const int dwl_format[] = {17, 20, 21, 0, 0, 0, 0, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static const int swl_format[] = {16, 20, 21, 0, 0, 0, 0, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * This functions translates a 32-bit microMIPS instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * into a 32-bit MIPS32 instruction. Returns 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * and SIGILL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static int microMIPS32_to_MIPS32(union mips_instruction *insn_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) union mips_instruction insn = *insn_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) union mips_instruction mips32_insn = insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) int func, fmt, op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) switch (insn.mm_i_format.opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) case mm_ldc132_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) mips32_insn.mm_i_format.opcode = ldc1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) mips32_insn.mm_i_format.rt = insn.mm_i_format.rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) mips32_insn.mm_i_format.rs = insn.mm_i_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) case mm_lwc132_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) mips32_insn.mm_i_format.opcode = lwc1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) mips32_insn.mm_i_format.rt = insn.mm_i_format.rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) mips32_insn.mm_i_format.rs = insn.mm_i_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) case mm_sdc132_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) mips32_insn.mm_i_format.opcode = sdc1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) mips32_insn.mm_i_format.rt = insn.mm_i_format.rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) mips32_insn.mm_i_format.rs = insn.mm_i_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) case mm_swc132_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) mips32_insn.mm_i_format.opcode = swc1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) mips32_insn.mm_i_format.rt = insn.mm_i_format.rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) mips32_insn.mm_i_format.rs = insn.mm_i_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) case mm_pool32i_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* NOTE: offset is << by 1 if in microMIPS mode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if ((insn.mm_i_format.rt == mm_bc1f_op) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) (insn.mm_i_format.rt == mm_bc1t_op)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) mips32_insn.fb_format.opcode = cop1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) mips32_insn.fb_format.bc = bc_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) mips32_insn.fb_format.flag =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) (insn.mm_i_format.rt == mm_bc1t_op) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) case mm_pool32f_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) switch (insn.mm_fp0_format.func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) case mm_32f_01_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) case mm_32f_11_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) case mm_32f_02_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) case mm_32f_12_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) case mm_32f_41_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) case mm_32f_51_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) case mm_32f_42_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) case mm_32f_52_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) op = insn.mm_fp0_format.func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (op == mm_32f_01_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) func = madd_s_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) else if (op == mm_32f_11_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) func = madd_d_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) else if (op == mm_32f_02_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) func = nmadd_s_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) else if (op == mm_32f_12_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) func = nmadd_d_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) else if (op == mm_32f_41_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) func = msub_s_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) else if (op == mm_32f_51_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) func = msub_d_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) else if (op == mm_32f_42_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) func = nmsub_s_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) func = nmsub_d_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) mips32_insn.fp6_format.opcode = cop1x_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) mips32_insn.fp6_format.fr = insn.mm_fp6_format.fr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) mips32_insn.fp6_format.ft = insn.mm_fp6_format.ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) mips32_insn.fp6_format.fs = insn.mm_fp6_format.fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) mips32_insn.fp6_format.fd = insn.mm_fp6_format.fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) mips32_insn.fp6_format.func = func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) case mm_32f_10_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) func = -1; /* Invalid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) op = insn.mm_fp5_format.op & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (op == mm_ldxc1_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) func = ldxc1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) else if (op == mm_sdxc1_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) func = sdxc1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) else if (op == mm_lwxc1_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) func = lwxc1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) else if (op == mm_swxc1_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) func = swxc1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (func != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) mips32_insn.r_format.opcode = cop1x_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) mips32_insn.r_format.rs =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) insn.mm_fp5_format.base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) mips32_insn.r_format.rt =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) insn.mm_fp5_format.index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) mips32_insn.r_format.rd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) mips32_insn.r_format.re = insn.mm_fp5_format.fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) mips32_insn.r_format.func = func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) case mm_32f_40_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) op = -1; /* Invalid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (insn.mm_fp2_format.op == mm_fmovt_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) op = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) else if (insn.mm_fp2_format.op == mm_fmovf_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) op = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (op != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) mips32_insn.fp0_format.opcode = cop1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) mips32_insn.fp0_format.fmt =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) sdps_format[insn.mm_fp2_format.fmt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) mips32_insn.fp0_format.ft =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) (insn.mm_fp2_format.cc<<2) + op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) mips32_insn.fp0_format.fs =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) insn.mm_fp2_format.fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) mips32_insn.fp0_format.fd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) insn.mm_fp2_format.fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) mips32_insn.fp0_format.func = fmovc_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) case mm_32f_60_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) func = -1; /* Invalid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (insn.mm_fp0_format.op == mm_fadd_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) func = fadd_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) else if (insn.mm_fp0_format.op == mm_fsub_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) func = fsub_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) else if (insn.mm_fp0_format.op == mm_fmul_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) func = fmul_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) else if (insn.mm_fp0_format.op == mm_fdiv_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) func = fdiv_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (func != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) mips32_insn.fp0_format.opcode = cop1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) mips32_insn.fp0_format.fmt =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) sdps_format[insn.mm_fp0_format.fmt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) mips32_insn.fp0_format.ft =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) insn.mm_fp0_format.ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) mips32_insn.fp0_format.fs =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) insn.mm_fp0_format.fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) mips32_insn.fp0_format.fd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) insn.mm_fp0_format.fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) mips32_insn.fp0_format.func = func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) case mm_32f_70_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) func = -1; /* Invalid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (insn.mm_fp0_format.op == mm_fmovn_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) func = fmovn_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) else if (insn.mm_fp0_format.op == mm_fmovz_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) func = fmovz_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (func != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) mips32_insn.fp0_format.opcode = cop1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) mips32_insn.fp0_format.fmt =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) sdps_format[insn.mm_fp0_format.fmt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) mips32_insn.fp0_format.ft =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) insn.mm_fp0_format.ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) mips32_insn.fp0_format.fs =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) insn.mm_fp0_format.fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) mips32_insn.fp0_format.fd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) insn.mm_fp0_format.fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) mips32_insn.fp0_format.func = func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) case mm_32f_73_op: /* POOL32FXF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) switch (insn.mm_fp1_format.op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) case mm_movf0_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) case mm_movf1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) case mm_movt0_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) case mm_movt1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if ((insn.mm_fp1_format.op & 0x7f) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) mm_movf0_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) op = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) op = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) mips32_insn.r_format.opcode = spec_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) mips32_insn.r_format.rs = insn.mm_fp4_format.fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) mips32_insn.r_format.rt =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) (insn.mm_fp4_format.cc << 2) + op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) mips32_insn.r_format.rd = insn.mm_fp4_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) mips32_insn.r_format.re = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) mips32_insn.r_format.func = movc_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) case mm_fcvtd0_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) case mm_fcvtd1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) case mm_fcvts0_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) case mm_fcvts1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if ((insn.mm_fp1_format.op & 0x7f) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) mm_fcvtd0_op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) func = fcvtd_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) fmt = swl_format[insn.mm_fp3_format.fmt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) func = fcvts_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) fmt = dwl_format[insn.mm_fp3_format.fmt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) mips32_insn.fp0_format.opcode = cop1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) mips32_insn.fp0_format.fmt = fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) mips32_insn.fp0_format.ft = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) mips32_insn.fp0_format.fs =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) insn.mm_fp3_format.fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) mips32_insn.fp0_format.fd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) insn.mm_fp3_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) mips32_insn.fp0_format.func = func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) case mm_fmov0_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) case mm_fmov1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) case mm_fabs0_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) case mm_fabs1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) case mm_fneg0_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) case mm_fneg1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if ((insn.mm_fp1_format.op & 0x7f) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) mm_fmov0_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) func = fmov_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) else if ((insn.mm_fp1_format.op & 0x7f) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) mm_fabs0_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) func = fabs_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) func = fneg_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) mips32_insn.fp0_format.opcode = cop1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) mips32_insn.fp0_format.fmt =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) sdps_format[insn.mm_fp3_format.fmt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) mips32_insn.fp0_format.ft = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) mips32_insn.fp0_format.fs =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) insn.mm_fp3_format.fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) mips32_insn.fp0_format.fd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) insn.mm_fp3_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) mips32_insn.fp0_format.func = func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) case mm_ffloorl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) case mm_ffloorw_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) case mm_fceill_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) case mm_fceilw_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) case mm_ftruncl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) case mm_ftruncw_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) case mm_froundl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) case mm_froundw_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) case mm_fcvtl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) case mm_fcvtw_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (insn.mm_fp1_format.op == mm_ffloorl_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) func = ffloorl_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) else if (insn.mm_fp1_format.op == mm_ffloorw_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) func = ffloor_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) else if (insn.mm_fp1_format.op == mm_fceill_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) func = fceill_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) else if (insn.mm_fp1_format.op == mm_fceilw_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) func = fceil_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) else if (insn.mm_fp1_format.op == mm_ftruncl_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) func = ftruncl_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) else if (insn.mm_fp1_format.op == mm_ftruncw_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) func = ftrunc_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) else if (insn.mm_fp1_format.op == mm_froundl_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) func = froundl_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) else if (insn.mm_fp1_format.op == mm_froundw_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) func = fround_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) else if (insn.mm_fp1_format.op == mm_fcvtl_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) func = fcvtl_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) func = fcvtw_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) mips32_insn.fp0_format.opcode = cop1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) mips32_insn.fp0_format.fmt =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) sd_format[insn.mm_fp1_format.fmt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) mips32_insn.fp0_format.ft = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) mips32_insn.fp0_format.fs =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) insn.mm_fp1_format.fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) mips32_insn.fp0_format.fd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) insn.mm_fp1_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) mips32_insn.fp0_format.func = func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) case mm_frsqrt_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) case mm_fsqrt_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) case mm_frecip_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (insn.mm_fp1_format.op == mm_frsqrt_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) func = frsqrt_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) else if (insn.mm_fp1_format.op == mm_fsqrt_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) func = fsqrt_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) func = frecip_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) mips32_insn.fp0_format.opcode = cop1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) mips32_insn.fp0_format.fmt =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) sdps_format[insn.mm_fp1_format.fmt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) mips32_insn.fp0_format.ft = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) mips32_insn.fp0_format.fs =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) insn.mm_fp1_format.fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) mips32_insn.fp0_format.fd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) insn.mm_fp1_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) mips32_insn.fp0_format.func = func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) case mm_mfc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) case mm_mtc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) case mm_cfc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) case mm_ctc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) case mm_mfhc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) case mm_mthc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (insn.mm_fp1_format.op == mm_mfc1_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) op = mfc_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) else if (insn.mm_fp1_format.op == mm_mtc1_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) op = mtc_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) else if (insn.mm_fp1_format.op == mm_cfc1_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) op = cfc_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) else if (insn.mm_fp1_format.op == mm_ctc1_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) op = ctc_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) else if (insn.mm_fp1_format.op == mm_mfhc1_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) op = mfhc_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) op = mthc_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) mips32_insn.fp1_format.opcode = cop1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) mips32_insn.fp1_format.op = op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) mips32_insn.fp1_format.rt =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) insn.mm_fp1_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) mips32_insn.fp1_format.fs =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) insn.mm_fp1_format.fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) mips32_insn.fp1_format.fd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) mips32_insn.fp1_format.func = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) case mm_32f_74_op: /* c.cond.fmt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) mips32_insn.fp0_format.opcode = cop1_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) mips32_insn.fp0_format.fmt =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) sdps_format[insn.mm_fp4_format.fmt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) mips32_insn.fp0_format.ft = insn.mm_fp4_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) mips32_insn.fp0_format.fs = insn.mm_fp4_format.fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) mips32_insn.fp0_format.fd = insn.mm_fp4_format.cc << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) mips32_insn.fp0_format.func =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) insn.mm_fp4_format.cond | MM_MIPS32_COND_FC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) *insn_ptr = mips32_insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * Redundant with logic already in kernel/branch.c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * embedded in compute_return_epc. At some point,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * a single subroutine should be used across both
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * modules.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) unsigned long *contpc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) union mips_instruction insn = (union mips_instruction)dec_insn.insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) unsigned int fcr31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) unsigned int bit = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) unsigned int bit0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) union fpureg *fpr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) switch (insn.i_format.opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) case spec_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) switch (insn.r_format.func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) case jalr_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (insn.r_format.rd != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) regs->regs[insn.r_format.rd] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) regs->cp0_epc + dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) case jr_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /* For R6, JR already emulated in jalr_op */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (NO_R6EMU && insn.r_format.func == jr_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) *contpc = regs->regs[insn.r_format.rs];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) case bcond_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) switch (insn.i_format.rt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) case bltzal_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) case bltzall_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (NO_R6EMU && (insn.i_format.rs ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) insn.i_format.rt == bltzall_op))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) regs->regs[31] = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) case bltzl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (NO_R6EMU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) case bltz_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if ((long)regs->regs[insn.i_format.rs] < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) (insn.i_format.simmediate << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) case bgezal_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) case bgezall_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (NO_R6EMU && (insn.i_format.rs ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) insn.i_format.rt == bgezall_op))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) regs->regs[31] = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) case bgezl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (NO_R6EMU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) case bgez_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if ((long)regs->regs[insn.i_format.rs] >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) (insn.i_format.simmediate << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) case jalx_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) set_isa16_mode(bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) case jal_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) regs->regs[31] = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) case j_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) *contpc = regs->cp0_epc + dec_insn.pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) *contpc >>= 28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) *contpc <<= 28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) *contpc |= (insn.j_format.target << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) /* Set microMIPS mode bit: XOR for jalx. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) *contpc ^= bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) case beql_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (NO_R6EMU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) case beq_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (regs->regs[insn.i_format.rs] ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) regs->regs[insn.i_format.rt])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) (insn.i_format.simmediate << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) case bnel_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (NO_R6EMU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) case bne_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (regs->regs[insn.i_format.rs] !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) regs->regs[insn.i_format.rt])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) (insn.i_format.simmediate << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) case blezl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (!insn.i_format.rt && NO_R6EMU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) case blez_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) * Compact branches for R6 for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * blez and blezl opcodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) * BLEZ | rs = 0 | rt != 0 == BLEZALC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * BLEZ | rs = rt != 0 == BGEZALC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) * BLEZ | rs != 0 | rt != 0 == BGEUC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) * BLEZL | rs = 0 | rt != 0 == BLEZC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) * BLEZL | rs = rt != 0 == BGEZC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) * BLEZL | rs != 0 | rt != 0 == BGEC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) * For real BLEZ{,L}, rt is always 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (cpu_has_mips_r6 && insn.i_format.rt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if ((insn.i_format.opcode == blez_op) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) ((!insn.i_format.rs && insn.i_format.rt) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) (insn.i_format.rs == insn.i_format.rt)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) regs->regs[31] = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) dec_insn.pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) *contpc = regs->cp0_epc + dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if ((long)regs->regs[insn.i_format.rs] <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) (insn.i_format.simmediate << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) case bgtzl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (!insn.i_format.rt && NO_R6EMU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) case bgtz_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) * Compact branches for R6 for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) * bgtz and bgtzl opcodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) * BGTZ | rs = 0 | rt != 0 == BGTZALC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) * BGTZ | rs = rt != 0 == BLTZALC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) * BGTZ | rs != 0 | rt != 0 == BLTUC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) * BGTZL | rs = 0 | rt != 0 == BGTZC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * BGTZL | rs = rt != 0 == BLTZC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) * BGTZL | rs != 0 | rt != 0 == BLTC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * *ZALC varint for BGTZ &&& rt != 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) * For real GTZ{,L}, rt is always 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (cpu_has_mips_r6 && insn.i_format.rt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if ((insn.i_format.opcode == blez_op) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) ((!insn.i_format.rs && insn.i_format.rt) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) (insn.i_format.rs == insn.i_format.rt)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) regs->regs[31] = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) dec_insn.pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) *contpc = regs->cp0_epc + dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if ((long)regs->regs[insn.i_format.rs] > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) (insn.i_format.simmediate << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) case pop10_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) case pop30_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (insn.i_format.rt && !insn.i_format.rs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) regs->regs[31] = regs->cp0_epc + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) *contpc = regs->cp0_epc + dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) #ifdef CONFIG_CPU_CAVIUM_OCTEON
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) case lwc2_op: /* This is bbit0 on Octeon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) *contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) *contpc = regs->cp0_epc + 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) case ldc2_op: /* This is bbit032 on Octeon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if ((regs->regs[insn.i_format.rs] & (1ull<<(insn.i_format.rt + 32))) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) *contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) *contpc = regs->cp0_epc + 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) case swc2_op: /* This is bbit1 on Octeon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) *contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) *contpc = regs->cp0_epc + 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) case sdc2_op: /* This is bbit132 on Octeon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (regs->regs[insn.i_format.rs] & (1ull<<(insn.i_format.rt + 32)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) *contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) *contpc = regs->cp0_epc + 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) case bc6_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) * Only valid for MIPS R6 but we can still end up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) * here from a broken userland so just tell emulator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * this is not a branch and let it break later on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) *contpc = regs->cp0_epc + dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) case balc6_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) regs->regs[31] = regs->cp0_epc + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) *contpc = regs->cp0_epc + dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) case pop66_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) *contpc = regs->cp0_epc + dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) case pop76_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (!insn.i_format.rs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) regs->regs[31] = regs->cp0_epc + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) *contpc = regs->cp0_epc + dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) case cop0_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) case cop1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) /* Need to check for R6 bc1nez and bc1eqz branches */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (cpu_has_mips_r6 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) ((insn.i_format.rs == bc1eqz_op) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) (insn.i_format.rs == bc1nez_op))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) bit = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) fpr = ¤t->thread.fpu.fpr[insn.i_format.rt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) bit0 = get_fpr32(fpr, 0) & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) switch (insn.i_format.rs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) case bc1eqz_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) bit = bit0 == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) case bc1nez_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) bit = bit0 != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) (insn.i_format.simmediate << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) /* R2/R6 compatible cop1 instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) case cop2_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) case cop1x_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (insn.i_format.rs == bc_op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) preempt_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (is_fpu_owner())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) fcr31 = read_32bit_cp1_register(CP1_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) fcr31 = current->thread.fpu.fcr31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) preempt_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) bit = (insn.i_format.rt >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) bit += (bit != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) bit += 23;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) switch (insn.i_format.rt & 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) case 0: /* bc1f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) case 2: /* bc1fl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (~fcr31 & (1 << bit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) (insn.i_format.simmediate << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) case 1: /* bc1t */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) case 3: /* bc1tl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (fcr31 & (1 << bit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) (insn.i_format.simmediate << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) *contpc = regs->cp0_epc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) dec_insn.pc_inc +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) * In the Linux kernel, we support selection of FPR format on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) * basis of the Status.FR bit. If an FPU is not present, the FR bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) * is hardwired to zero, which would imply a 32-bit FPU even for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) * 64-bit CPUs so we rather look at TIF_32BIT_FPREGS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) * FPU emu is slow and bulky and optimizing this function offers fairly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) * sizeable benefits so we try to be clever and make this function return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) * a constant whenever possible, that is on 64-bit kernels without O32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) * compatibility enabled and on 32-bit without 64-bit FPU support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) static inline int cop1_64bit(struct pt_regs *xcp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (IS_ENABLED(CONFIG_64BIT) && !IS_ENABLED(CONFIG_MIPS32_O32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) else if (IS_ENABLED(CONFIG_32BIT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) !IS_ENABLED(CONFIG_MIPS_O32_FP64_SUPPORT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) return !test_thread_flag(TIF_32BIT_FPREGS);
^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) static inline bool hybrid_fprs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) return test_thread_flag(TIF_HYBRID_FPREGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) #define SIFROMREG(si, x) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (cop1_64bit(xcp) && !hybrid_fprs()) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) (si) = (int)get_fpr32(&ctx->fpr[x], 0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) else \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) (si) = (int)get_fpr32(&ctx->fpr[(x) & ~1], (x) & 1); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) #define SITOREG(si, x) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (cop1_64bit(xcp) && !hybrid_fprs()) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) unsigned int i; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) set_fpr32(&ctx->fpr[x], 0, si); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) for (i = 1; i < ARRAY_SIZE(ctx->fpr[x].val32); i++) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) set_fpr32(&ctx->fpr[x], i, 0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) } else { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) set_fpr32(&ctx->fpr[(x) & ~1], (x) & 1, si); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) #define SIFROMHREG(si, x) ((si) = (int)get_fpr32(&ctx->fpr[x], 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) #define SITOHREG(si, x) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) unsigned int i; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) set_fpr32(&ctx->fpr[x], 1, si); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) for (i = 2; i < ARRAY_SIZE(ctx->fpr[x].val32); i++) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) set_fpr32(&ctx->fpr[x], i, 0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) #define DIFROMREG(di, x) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) ((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) ^ 1)], 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) #define DITOREG(di, x) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) unsigned int fpr, i; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) fpr = (x) & ~(cop1_64bit(xcp) ^ 1); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) set_fpr64(&ctx->fpr[fpr], 0, di); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) for (i = 1; i < ARRAY_SIZE(ctx->fpr[x].val64); i++) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) set_fpr64(&ctx->fpr[fpr], i, 0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) #define SPFROMREG(sp, x) SIFROMREG((sp).bits, x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) #define SPTOREG(sp, x) SITOREG((sp).bits, x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) #define DPFROMREG(dp, x) DIFROMREG((dp).bits, x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) #define DPTOREG(dp, x) DITOREG((dp).bits, x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * Emulate a CFC1 instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) static inline void cop1_cfc(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) mips_instruction ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) u32 fcr31 = ctx->fcr31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) u32 value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) switch (MIPSInst_RD(ir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) case FPCREG_CSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) value = fcr31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) pr_debug("%p gpr[%d]<-csr=%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) case FPCREG_FENR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) if (!cpu_has_mips_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) value = (fcr31 >> (FPU_CSR_FS_S - MIPS_FENR_FS_S)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) MIPS_FENR_FS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) value |= fcr31 & (FPU_CSR_ALL_E | FPU_CSR_RM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) pr_debug("%p gpr[%d]<-enr=%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) case FPCREG_FEXR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (!cpu_has_mips_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) value = fcr31 & (FPU_CSR_ALL_X | FPU_CSR_ALL_S);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) pr_debug("%p gpr[%d]<-exr=%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) case FPCREG_FCCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if (!cpu_has_mips_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) value = (fcr31 >> (FPU_CSR_COND_S - MIPS_FCCR_COND0_S)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) MIPS_FCCR_COND0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) value |= (fcr31 >> (FPU_CSR_COND1_S - MIPS_FCCR_COND1_S)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) (MIPS_FCCR_CONDX & ~MIPS_FCCR_COND0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) pr_debug("%p gpr[%d]<-ccr=%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) case FPCREG_RID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) value = boot_cpu_data.fpu_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (MIPSInst_RT(ir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) xcp->regs[MIPSInst_RT(ir)] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) * Emulate a CTC1 instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) static inline void cop1_ctc(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) mips_instruction ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) u32 fcr31 = ctx->fcr31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (MIPSInst_RT(ir) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) value = xcp->regs[MIPSInst_RT(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) switch (MIPSInst_RD(ir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) case FPCREG_CSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) pr_debug("%p gpr[%d]->csr=%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) /* Preserve read-only bits. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) mask = boot_cpu_data.fpu_msk31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) fcr31 = (value & ~mask) | (fcr31 & mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) case FPCREG_FENR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (!cpu_has_mips_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) pr_debug("%p gpr[%d]->enr=%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) fcr31 &= ~(FPU_CSR_FS | FPU_CSR_ALL_E | FPU_CSR_RM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) fcr31 |= (value << (FPU_CSR_FS_S - MIPS_FENR_FS_S)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) FPU_CSR_FS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) fcr31 |= value & (FPU_CSR_ALL_E | FPU_CSR_RM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) case FPCREG_FEXR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) if (!cpu_has_mips_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) pr_debug("%p gpr[%d]->exr=%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) fcr31 &= ~(FPU_CSR_ALL_X | FPU_CSR_ALL_S);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) fcr31 |= value & (FPU_CSR_ALL_X | FPU_CSR_ALL_S);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) case FPCREG_FCCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (!cpu_has_mips_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) pr_debug("%p gpr[%d]->ccr=%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) fcr31 &= ~(FPU_CSR_CONDX | FPU_CSR_COND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) fcr31 |= (value << (FPU_CSR_COND_S - MIPS_FCCR_COND0_S)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) FPU_CSR_COND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) fcr31 |= (value << (FPU_CSR_COND1_S - MIPS_FCCR_COND1_S)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) FPU_CSR_CONDX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) ctx->fcr31 = fcr31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) * Emulate the single floating point instruction pointed at by EPC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) * Two instructions if the instruction is in a branch delay slot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) struct mm_decoded_insn dec_insn, void __user **fault_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) unsigned long contpc = xcp->cp0_epc + dec_insn.pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) unsigned int cond, cbit, bit0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) mips_instruction ir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) int likely, pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) union fpureg *fpr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) u32 __user *wva;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) u64 __user *dva;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) u32 wval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) u64 dval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) int sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) * These are giving gcc a gentle hint about what to expect in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) * dec_inst in order to do better optimization.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if (!cpu_has_mmips && dec_insn.micro_mips_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) unreachable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) /* XXX NEC Vr54xx bug workaround */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (delay_slot(xcp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) if (dec_insn.micro_mips_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (!mm_isBranchInstr(xcp, dec_insn, &contpc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) clear_delay_slot(xcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (!isBranchInstr(xcp, dec_insn, &contpc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) clear_delay_slot(xcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (delay_slot(xcp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) * The instruction to be emulated is in a branch delay slot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) * which means that we have to emulate the branch instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) * BEFORE we do the cop1 instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) * This branch could be a COP1 branch, but in that case we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) * would have had a trap for that instruction, and would not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) * come through this route.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) * Linux MIPS branch emulator operates on context, updating the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) * cp0_epc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) ir = dec_insn.next_insn; /* process delay slot instr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) pc_inc = dec_insn.next_pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) ir = dec_insn.insn; /* process current instr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) pc_inc = dec_insn.pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) * Since microMIPS FPU instructios are a subset of MIPS32 FPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) * instructions, we want to convert microMIPS FPU instructions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) * into MIPS32 instructions so that we could reuse all of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) * FPU emulation code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) * NOTE: We cannot do this for branch instructions since they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) * are not a subset. Example: Cannot emulate a 16-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) * aligned target address with a MIPS32 instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) if (dec_insn.micro_mips_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) * If next instruction is a 16-bit instruction, then it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) * it cannot be a FPU instruction. This could happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) * since we can be called for non-FPU instructions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if ((pc_inc == 2) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) (microMIPS32_to_MIPS32((union mips_instruction *)&ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) == SIGILL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) emul:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, xcp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) MIPS_FPU_EMU_INC_STATS(emulated);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) switch (MIPSInst_OPCODE(ir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) case ldc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) dva = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) MIPSInst_SIMM(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) MIPS_FPU_EMU_INC_STATS(loads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (!access_ok(dva, sizeof(u64))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) *fault_addr = dva;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) return SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (__get_user(dval, dva)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) *fault_addr = dva;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) return SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) DITOREG(dval, MIPSInst_RT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) case sdc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) dva = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) MIPSInst_SIMM(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) MIPS_FPU_EMU_INC_STATS(stores);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) DIFROMREG(dval, MIPSInst_RT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (!access_ok(dva, sizeof(u64))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) *fault_addr = dva;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) return SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) if (__put_user(dval, dva)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) *fault_addr = dva;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) return SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) case lwc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) wva = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) MIPSInst_SIMM(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) MIPS_FPU_EMU_INC_STATS(loads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (!access_ok(wva, sizeof(u32))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) *fault_addr = wva;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) return SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (__get_user(wval, wva)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) *fault_addr = wva;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) return SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) SITOREG(wval, MIPSInst_RT(ir));
^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 swc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) wva = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) MIPSInst_SIMM(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) MIPS_FPU_EMU_INC_STATS(stores);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) SIFROMREG(wval, MIPSInst_RT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) if (!access_ok(wva, sizeof(u32))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) *fault_addr = wva;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) return SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (__put_user(wval, wva)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) *fault_addr = wva;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) return SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) case cop1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) switch (MIPSInst_RS(ir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) case dmfc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) /* copregister fs -> gpr[rt] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (MIPSInst_RT(ir) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) DIFROMREG(xcp->regs[MIPSInst_RT(ir)],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) MIPSInst_RD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) case dmtc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) /* copregister fs <- rt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) case mfhc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (!cpu_has_mips_r2_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) /* copregister rd -> gpr[rt] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) if (MIPSInst_RT(ir) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) SIFROMHREG(xcp->regs[MIPSInst_RT(ir)],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) MIPSInst_RD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) case mthc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (!cpu_has_mips_r2_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) /* copregister rd <- gpr[rt] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) SITOHREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) case mfc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) /* copregister rd -> gpr[rt] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) if (MIPSInst_RT(ir) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) SIFROMREG(xcp->regs[MIPSInst_RT(ir)],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) MIPSInst_RD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) case mtc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) /* copregister rd <- rt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) SITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) case cfc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) /* cop control register rd -> gpr[rt] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) cop1_cfc(xcp, ctx, ir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) case ctc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) /* copregister rd <- rt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) cop1_ctc(xcp, ctx, ir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) return SIGFPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) case bc1eqz_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) case bc1nez_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) if (!cpu_has_mips_r6 || delay_slot(xcp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) likely = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) cond = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) fpr = ¤t->thread.fpu.fpr[MIPSInst_RT(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) bit0 = get_fpr32(fpr, 0) & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) switch (MIPSInst_RS(ir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) case bc1eqz_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) MIPS_FPU_EMU_INC_STATS(bc1eqz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) cond = bit0 == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) case bc1nez_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) MIPS_FPU_EMU_INC_STATS(bc1nez);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) cond = bit0 != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) goto branch_common;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) case bc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (delay_slot(xcp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) if (cpu_has_mips_4_5_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) cbit = fpucondbit[MIPSInst_RT(ir) >> 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) cbit = FPU_CSR_COND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) cond = ctx->fcr31 & cbit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) likely = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) switch (MIPSInst_RT(ir) & 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) case bcfl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) if (cpu_has_mips_2_3_4_5_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) likely = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) case bcf_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) cond = !cond;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) case bctl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) if (cpu_has_mips_2_3_4_5_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) likely = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) case bct_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) branch_common:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) MIPS_FPU_EMU_INC_STATS(branches);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) set_delay_slot(xcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) if (cond) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) * Branch taken: emulate dslot instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) unsigned long bcpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) * Remember EPC at the branch to point back
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) * at so that any delay-slot instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) * signal is not silently ignored.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) bcpc = xcp->cp0_epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) xcp->cp0_epc += dec_insn.pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) contpc = MIPSInst_SIMM(ir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) ir = dec_insn.next_insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) if (dec_insn.micro_mips_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) contpc = (xcp->cp0_epc + (contpc << 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) /* If 16-bit instruction, not FPU. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) if ((dec_insn.next_pc_inc == 2) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) (microMIPS32_to_MIPS32((union mips_instruction *)&ir) == SIGILL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) * Since this instruction will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) * be put on the stack with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) * 32-bit words, get around
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) * this problem by putting a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) * NOP16 as the second one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) if (dec_insn.next_pc_inc == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) ir = (ir & (~0xffff)) | MM_NOP16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) * Single step the non-CP1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) * instruction in the dslot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) sig = mips_dsemul(xcp, ir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) bcpc, contpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) if (sig < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) if (sig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) xcp->cp0_epc = bcpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) * SIGILL forces out of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) * the emulation loop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) return sig ? sig : SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) contpc = (xcp->cp0_epc + (contpc << 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) switch (MIPSInst_OPCODE(ir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) case lwc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) case swc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) goto emul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) case ldc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) case sdc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) if (cpu_has_mips_2_3_4_5_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) goto emul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) goto bc_sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) case cop1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) goto emul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) case cop1x_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if (cpu_has_mips_4_5_64_r2_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) /* its one of ours */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) goto emul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) goto bc_sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) case spec_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) switch (MIPSInst_FUNC(ir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) case movc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) if (cpu_has_mips_4_5_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) goto emul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) goto bc_sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) bc_sigill:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) xcp->cp0_epc = bcpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) * Single step the non-cp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) * instruction in the dslot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) sig = mips_dsemul(xcp, ir, bcpc, contpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) if (sig < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) if (sig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) xcp->cp0_epc = bcpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) /* SIGILL forces out of the emulation loop. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) return sig ? sig : SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) } else if (likely) { /* branch not taken */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) * branch likely nullifies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) * dslot if not taken
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) xcp->cp0_epc += dec_insn.pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) contpc += dec_insn.pc_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) * else continue & execute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) * dslot as normal insn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) if (!(MIPSInst_RS(ir) & 0x10))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) /* a real fpu computation instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) sig = fpu_emu(xcp, ctx, ir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if (sig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) return sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) case cop1x_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) if (!cpu_has_mips_4_5_64_r2_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) sig = fpux_emu(xcp, ctx, ir, fault_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) if (sig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) return sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) case spec_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) if (!cpu_has_mips_4_5_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) if (MIPSInst_FUNC(ir) != movc_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) cond = fpucondbit[MIPSInst_RT(ir) >> 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) if (((ctx->fcr31 & cond) != 0) == ((MIPSInst_RT(ir) & 1) != 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) xcp->regs[MIPSInst_RD(ir)] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) xcp->regs[MIPSInst_RS(ir)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) /* we did it !! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) xcp->cp0_epc = contpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) clear_delay_slot(xcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) * Conversion table from MIPS compare ops 48-63
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) * cond = ieee754dp_cmp(x,y,IEEE754_UN,sig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) static const unsigned char cmptab[8] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 0, /* cmp_0 (sig) cmp_sf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) IEEE754_CUN, /* cmp_un (sig) cmp_ngle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) IEEE754_CEQ, /* cmp_eq (sig) cmp_seq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) IEEE754_CEQ | IEEE754_CUN, /* cmp_ueq (sig) cmp_ngl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) IEEE754_CLT, /* cmp_olt (sig) cmp_lt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) IEEE754_CLT | IEEE754_CUN, /* cmp_ult (sig) cmp_nge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) IEEE754_CLT | IEEE754_CEQ, /* cmp_ole (sig) cmp_le */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) static const unsigned char negative_cmptab[8] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 0, /* Reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) IEEE754_CLT | IEEE754_CGT | IEEE754_CEQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) IEEE754_CLT | IEEE754_CGT | IEEE754_CUN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) IEEE754_CLT | IEEE754_CGT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) /* Reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) * Additional MIPS4 instructions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) #define DEF3OP(name, p, f1, f2, f3) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) static union ieee754##p fpemu_##p##_##name(union ieee754##p r, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) union ieee754##p s, union ieee754##p t) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) struct _ieee754_csr ieee754_csr_save; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) s = f1(s, t); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) ieee754_csr_save = ieee754_csr; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) s = f2(s, r); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) ieee754_csr_save.cx |= ieee754_csr.cx; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) ieee754_csr_save.sx |= ieee754_csr.sx; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) s = f3(s); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) ieee754_csr.cx |= ieee754_csr_save.cx; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) ieee754_csr.sx |= ieee754_csr_save.sx; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) return s; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) static union ieee754dp fpemu_dp_recip(union ieee754dp d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) return ieee754dp_div(ieee754dp_one(0), d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) static union ieee754dp fpemu_dp_rsqrt(union ieee754dp d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) static union ieee754sp fpemu_sp_recip(union ieee754sp s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) return ieee754sp_div(ieee754sp_one(0), s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) static union ieee754sp fpemu_sp_rsqrt(union ieee754sp s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) DEF3OP(madd, sp, ieee754sp_mul, ieee754sp_add, );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) DEF3OP(msub, sp, ieee754sp_mul, ieee754sp_sub, );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) DEF3OP(nmadd, sp, ieee754sp_mul, ieee754sp_add, ieee754sp_neg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) DEF3OP(nmsub, sp, ieee754sp_mul, ieee754sp_sub, ieee754sp_neg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) DEF3OP(madd, dp, ieee754dp_mul, ieee754dp_add, );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) DEF3OP(msub, dp, ieee754dp_mul, ieee754dp_sub, );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) mips_instruction ir, void __user **fault_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) unsigned int rcsr = 0; /* resulting csr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) MIPS_FPU_EMU_INC_STATS(cp1xops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) switch (MIPSInst_FMA_FFMT(ir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) case s_fmt:{ /* 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) union ieee754sp(*handler) (union ieee754sp, union ieee754sp, union ieee754sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) union ieee754sp fd, fr, fs, ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) u32 __user *va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) switch (MIPSInst_FUNC(ir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) case lwxc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) xcp->regs[MIPSInst_FT(ir)]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) MIPS_FPU_EMU_INC_STATS(loads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) if (!access_ok(va, sizeof(u32))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) *fault_addr = va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) return SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) if (__get_user(val, va)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) *fault_addr = va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) return SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) SITOREG(val, MIPSInst_FD(ir));
^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) case swxc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) xcp->regs[MIPSInst_FT(ir)]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) MIPS_FPU_EMU_INC_STATS(stores);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) SIFROMREG(val, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) if (!access_ok(va, sizeof(u32))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) *fault_addr = va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) return SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) if (put_user(val, va)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) *fault_addr = va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) return SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) case madd_s_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) if (cpu_has_mac2008_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) handler = ieee754sp_madd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) handler = fpemu_sp_madd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) goto scoptop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) case msub_s_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) if (cpu_has_mac2008_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) handler = ieee754sp_msub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) handler = fpemu_sp_msub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) goto scoptop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) case nmadd_s_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) if (cpu_has_mac2008_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) handler = ieee754sp_nmadd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) handler = fpemu_sp_nmadd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) goto scoptop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) case nmsub_s_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) if (cpu_has_mac2008_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) handler = ieee754sp_nmsub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) handler = fpemu_sp_nmsub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) goto scoptop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) scoptop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) SPFROMREG(fr, MIPSInst_FR(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) SPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) fd = (*handler) (fr, fs, ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) SPTOREG(fd, MIPSInst_FD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) copcsr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) if (ieee754_cxtest(IEEE754_INEXACT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) MIPS_FPU_EMU_INC_STATS(ieee754_inexact);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) if (ieee754_cxtest(IEEE754_UNDERFLOW)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) MIPS_FPU_EMU_INC_STATS(ieee754_underflow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) if (ieee754_cxtest(IEEE754_OVERFLOW)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) MIPS_FPU_EMU_INC_STATS(ieee754_overflow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) MIPS_FPU_EMU_INC_STATS(ieee754_invalidop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) /*printk ("SIGFPE: FPU csr = %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) ctx->fcr31); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) return SIGFPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) case d_fmt:{ /* 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) union ieee754dp(*handler) (union ieee754dp, union ieee754dp, union ieee754dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) union ieee754dp fd, fr, fs, ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) u64 __user *va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) switch (MIPSInst_FUNC(ir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) case ldxc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) xcp->regs[MIPSInst_FT(ir)]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) MIPS_FPU_EMU_INC_STATS(loads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) if (!access_ok(va, sizeof(u64))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) *fault_addr = va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) return SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) if (__get_user(val, va)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) *fault_addr = va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) return SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) DITOREG(val, MIPSInst_FD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) case sdxc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) xcp->regs[MIPSInst_FT(ir)]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) MIPS_FPU_EMU_INC_STATS(stores);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) DIFROMREG(val, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) if (!access_ok(va, sizeof(u64))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) *fault_addr = va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) return SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) if (__put_user(val, va)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) *fault_addr = va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) return SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) }
^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) case madd_d_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) if (cpu_has_mac2008_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) handler = ieee754dp_madd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) handler = fpemu_dp_madd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) goto dcoptop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) case msub_d_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) if (cpu_has_mac2008_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) handler = ieee754dp_msub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) handler = fpemu_dp_msub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) goto dcoptop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) case nmadd_d_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) if (cpu_has_mac2008_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) handler = ieee754dp_nmadd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) handler = fpemu_dp_nmadd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) goto dcoptop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) case nmsub_d_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) if (cpu_has_mac2008_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) handler = ieee754dp_nmsub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) handler = fpemu_dp_nmsub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) goto dcoptop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) dcoptop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) DPFROMREG(fr, MIPSInst_FR(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) DPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) fd = (*handler) (fr, fs, ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) DPTOREG(fd, MIPSInst_FD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) case 0x3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) if (MIPSInst_FUNC(ir) != pfetch_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) /* ignore prefx operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) * Emulate a single COP1 arithmetic instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) mips_instruction ir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) int rfmt; /* resulting format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) unsigned int rcsr = 0; /* resulting csr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) unsigned int oldrm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) unsigned int cbit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) unsigned int cond;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) union ieee754dp d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) union ieee754sp s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) int w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) s64 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) } rv; /* resulting value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) u64 bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) MIPS_FPU_EMU_INC_STATS(cp1ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) case s_fmt: { /* 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) union ieee754sp(*b) (union ieee754sp, union ieee754sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) union ieee754sp(*u) (union ieee754sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) } handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) union ieee754sp fd, fs, ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) switch (MIPSInst_FUNC(ir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) /* binary ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) case fadd_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) MIPS_FPU_EMU_INC_STATS(add_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) handler.b = ieee754sp_add;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) goto scopbop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) case fsub_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) MIPS_FPU_EMU_INC_STATS(sub_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) handler.b = ieee754sp_sub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) goto scopbop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) case fmul_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) MIPS_FPU_EMU_INC_STATS(mul_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) handler.b = ieee754sp_mul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) goto scopbop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) case fdiv_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) MIPS_FPU_EMU_INC_STATS(div_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) handler.b = ieee754sp_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) goto scopbop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) /* unary ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) case fsqrt_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) if (!cpu_has_mips_2_3_4_5_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) MIPS_FPU_EMU_INC_STATS(sqrt_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) handler.u = ieee754sp_sqrt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) goto scopuop;
^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) * Note that on some MIPS IV implementations such as the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) * R5000 and R8000 the FSQRT and FRECIP instructions do not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) * achieve full IEEE-754 accuracy - however this emulator does.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) case frsqrt_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) if (!cpu_has_mips_4_5_64_r2_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) MIPS_FPU_EMU_INC_STATS(rsqrt_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) handler.u = fpemu_sp_rsqrt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) goto scopuop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) case frecip_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) if (!cpu_has_mips_4_5_64_r2_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) MIPS_FPU_EMU_INC_STATS(recip_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) handler.u = fpemu_sp_recip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) goto scopuop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) case fmovc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) if (!cpu_has_mips_4_5_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) cond = fpucondbit[MIPSInst_FT(ir) >> 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) if (((ctx->fcr31 & cond) != 0) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) ((MIPSInst_FT(ir) & 1) != 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) SPFROMREG(rv.s, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) case fmovz_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) if (!cpu_has_mips_4_5_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) if (xcp->regs[MIPSInst_FT(ir)] != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) SPFROMREG(rv.s, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) case fmovn_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) if (!cpu_has_mips_4_5_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) if (xcp->regs[MIPSInst_FT(ir)] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) SPFROMREG(rv.s, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) case fseleqz_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) MIPS_FPU_EMU_INC_STATS(seleqz_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) SPFROMREG(rv.s, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) if (rv.w & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) rv.w = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) SPFROMREG(rv.s, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) case fselnez_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) MIPS_FPU_EMU_INC_STATS(selnez_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) SPFROMREG(rv.s, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) if (rv.w & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) SPFROMREG(rv.s, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) rv.w = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) case fmaddf_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) union ieee754sp ft, fs, fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) MIPS_FPU_EMU_INC_STATS(maddf_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) SPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) SPFROMREG(fd, MIPSInst_FD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) rv.s = ieee754sp_maddf(fd, fs, ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) case fmsubf_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) union ieee754sp ft, fs, fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) MIPS_FPU_EMU_INC_STATS(msubf_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) SPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) SPFROMREG(fd, MIPSInst_FD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) rv.s = ieee754sp_msubf(fd, fs, ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) case frint_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) union ieee754sp fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) MIPS_FPU_EMU_INC_STATS(rint_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) rv.s = ieee754sp_rint(fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) case fclass_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) union ieee754sp fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) MIPS_FPU_EMU_INC_STATS(class_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) rv.w = ieee754sp_2008class(fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) rfmt = w_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) case fmin_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) union ieee754sp fs, ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) MIPS_FPU_EMU_INC_STATS(min_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) SPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) rv.s = ieee754sp_fmin(fs, ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) case fmina_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) union ieee754sp fs, ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) MIPS_FPU_EMU_INC_STATS(mina_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) SPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) rv.s = ieee754sp_fmina(fs, ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) case fmax_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) union ieee754sp fs, ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) MIPS_FPU_EMU_INC_STATS(max_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) SPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) rv.s = ieee754sp_fmax(fs, ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) case fmaxa_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) union ieee754sp fs, ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) MIPS_FPU_EMU_INC_STATS(maxa_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) SPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) rv.s = ieee754sp_fmaxa(fs, ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) case fabs_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) MIPS_FPU_EMU_INC_STATS(abs_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) handler.u = ieee754sp_abs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) goto scopuop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) case fneg_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) MIPS_FPU_EMU_INC_STATS(neg_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) handler.u = ieee754sp_neg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) goto scopuop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) case fmov_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) /* an easy one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) MIPS_FPU_EMU_INC_STATS(mov_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) SPFROMREG(rv.s, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) /* binary op on handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) scopbop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) SPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) rv.s = (*handler.b) (fs, ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) scopuop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) rv.s = (*handler.u) (fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) copcsr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) if (ieee754_cxtest(IEEE754_INEXACT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) MIPS_FPU_EMU_INC_STATS(ieee754_inexact);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) if (ieee754_cxtest(IEEE754_UNDERFLOW)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) MIPS_FPU_EMU_INC_STATS(ieee754_underflow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) if (ieee754_cxtest(IEEE754_OVERFLOW)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) MIPS_FPU_EMU_INC_STATS(ieee754_overflow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) if (ieee754_cxtest(IEEE754_ZERO_DIVIDE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) MIPS_FPU_EMU_INC_STATS(ieee754_zerodiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) MIPS_FPU_EMU_INC_STATS(ieee754_invalidop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) /* unary conv ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) case fcvts_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) return SIGILL; /* not defined */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) case fcvtd_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) MIPS_FPU_EMU_INC_STATS(cvt_d_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) rv.d = ieee754dp_fsp(fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) rfmt = d_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) case fcvtw_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) MIPS_FPU_EMU_INC_STATS(cvt_w_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) rv.w = ieee754sp_tint(fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) rfmt = w_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) case fround_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) case ftrunc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) case fceil_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) case ffloor_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) if (!cpu_has_mips_2_3_4_5_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) if (MIPSInst_FUNC(ir) == fceil_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) MIPS_FPU_EMU_INC_STATS(ceil_w_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) if (MIPSInst_FUNC(ir) == ffloor_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) MIPS_FPU_EMU_INC_STATS(floor_w_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) if (MIPSInst_FUNC(ir) == fround_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) MIPS_FPU_EMU_INC_STATS(round_w_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) if (MIPSInst_FUNC(ir) == ftrunc_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) MIPS_FPU_EMU_INC_STATS(trunc_w_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) oldrm = ieee754_csr.rm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) ieee754_csr.rm = MIPSInst_FUNC(ir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) rv.w = ieee754sp_tint(fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) ieee754_csr.rm = oldrm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) rfmt = w_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) case fsel_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) MIPS_FPU_EMU_INC_STATS(sel_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) SPFROMREG(fd, MIPSInst_FD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) if (fd.bits & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) SPFROMREG(rv.s, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) SPFROMREG(rv.s, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) case fcvtl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) if (!cpu_has_mips_3_4_5_64_r2_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) MIPS_FPU_EMU_INC_STATS(cvt_l_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) rv.l = ieee754sp_tlong(fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) rfmt = l_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) case froundl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) case ftruncl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) case fceill_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) case ffloorl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) if (!cpu_has_mips_3_4_5_64_r2_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) if (MIPSInst_FUNC(ir) == fceill_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) MIPS_FPU_EMU_INC_STATS(ceil_l_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) if (MIPSInst_FUNC(ir) == ffloorl_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) MIPS_FPU_EMU_INC_STATS(floor_l_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) if (MIPSInst_FUNC(ir) == froundl_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) MIPS_FPU_EMU_INC_STATS(round_l_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) if (MIPSInst_FUNC(ir) == ftruncl_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) MIPS_FPU_EMU_INC_STATS(trunc_l_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) oldrm = ieee754_csr.rm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) ieee754_csr.rm = MIPSInst_FUNC(ir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) rv.l = ieee754sp_tlong(fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) ieee754_csr.rm = oldrm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) rfmt = l_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) if (!NO_R6EMU && MIPSInst_FUNC(ir) >= fcmp_op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) unsigned int cmpop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) union ieee754sp fs, ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) cmpop = MIPSInst_FUNC(ir) - fcmp_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) SPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) rv.w = ieee754sp_cmp(fs, ft,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) cmptab[cmpop & 0x7], cmpop & 0x8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) rfmt = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) if ((cmpop & 0x8) && ieee754_cxtest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) (IEEE754_INVALID_OPERATION))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) case d_fmt: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) union ieee754dp fd, fs, ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) union ieee754dp(*b) (union ieee754dp, union ieee754dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) union ieee754dp(*u) (union ieee754dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) } handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) switch (MIPSInst_FUNC(ir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) /* binary ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) case fadd_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) MIPS_FPU_EMU_INC_STATS(add_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) handler.b = ieee754dp_add;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) goto dcopbop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) case fsub_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) MIPS_FPU_EMU_INC_STATS(sub_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) handler.b = ieee754dp_sub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) goto dcopbop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) case fmul_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) MIPS_FPU_EMU_INC_STATS(mul_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) handler.b = ieee754dp_mul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) goto dcopbop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) case fdiv_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) MIPS_FPU_EMU_INC_STATS(div_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) handler.b = ieee754dp_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) goto dcopbop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) /* unary ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) case fsqrt_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) if (!cpu_has_mips_2_3_4_5_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) MIPS_FPU_EMU_INC_STATS(sqrt_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) handler.u = ieee754dp_sqrt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) goto dcopuop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) * Note that on some MIPS IV implementations such as the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) * R5000 and R8000 the FSQRT and FRECIP instructions do not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) * achieve full IEEE-754 accuracy - however this emulator does.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) case frsqrt_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) if (!cpu_has_mips_4_5_64_r2_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) MIPS_FPU_EMU_INC_STATS(rsqrt_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) handler.u = fpemu_dp_rsqrt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) goto dcopuop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) case frecip_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) if (!cpu_has_mips_4_5_64_r2_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) MIPS_FPU_EMU_INC_STATS(recip_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) handler.u = fpemu_dp_recip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) goto dcopuop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) case fmovc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) if (!cpu_has_mips_4_5_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) cond = fpucondbit[MIPSInst_FT(ir) >> 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) if (((ctx->fcr31 & cond) != 0) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) ((MIPSInst_FT(ir) & 1) != 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) DPFROMREG(rv.d, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) case fmovz_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) if (!cpu_has_mips_4_5_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) if (xcp->regs[MIPSInst_FT(ir)] != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) DPFROMREG(rv.d, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) case fmovn_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) if (!cpu_has_mips_4_5_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) if (xcp->regs[MIPSInst_FT(ir)] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) DPFROMREG(rv.d, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) case fseleqz_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) MIPS_FPU_EMU_INC_STATS(seleqz_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) DPFROMREG(rv.d, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) if (rv.l & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) rv.l = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) DPFROMREG(rv.d, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) case fselnez_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) MIPS_FPU_EMU_INC_STATS(selnez_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) DPFROMREG(rv.d, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) if (rv.l & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) DPFROMREG(rv.d, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) rv.l = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) case fmaddf_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) union ieee754dp ft, fs, fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) MIPS_FPU_EMU_INC_STATS(maddf_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) DPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) DPFROMREG(fd, MIPSInst_FD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) rv.d = ieee754dp_maddf(fd, fs, ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) case fmsubf_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) union ieee754dp ft, fs, fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) MIPS_FPU_EMU_INC_STATS(msubf_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) DPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) DPFROMREG(fd, MIPSInst_FD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) rv.d = ieee754dp_msubf(fd, fs, ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) case frint_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) union ieee754dp fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) MIPS_FPU_EMU_INC_STATS(rint_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) rv.d = ieee754dp_rint(fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) case fclass_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) union ieee754dp fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) MIPS_FPU_EMU_INC_STATS(class_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) rv.l = ieee754dp_2008class(fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) rfmt = l_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) case fmin_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) union ieee754dp fs, ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) MIPS_FPU_EMU_INC_STATS(min_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) DPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) rv.d = ieee754dp_fmin(fs, ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) case fmina_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) union ieee754dp fs, ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) MIPS_FPU_EMU_INC_STATS(mina_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) DPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) rv.d = ieee754dp_fmina(fs, ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) case fmax_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) union ieee754dp fs, ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) MIPS_FPU_EMU_INC_STATS(max_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) DPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) rv.d = ieee754dp_fmax(fs, ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) case fmaxa_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) union ieee754dp fs, ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) MIPS_FPU_EMU_INC_STATS(maxa_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) DPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) rv.d = ieee754dp_fmaxa(fs, ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) case fabs_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) MIPS_FPU_EMU_INC_STATS(abs_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) handler.u = ieee754dp_abs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) goto dcopuop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) case fneg_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) MIPS_FPU_EMU_INC_STATS(neg_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) handler.u = ieee754dp_neg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) goto dcopuop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) case fmov_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) /* an easy one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) MIPS_FPU_EMU_INC_STATS(mov_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) DPFROMREG(rv.d, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) /* binary op on handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) dcopbop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) DPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) rv.d = (*handler.b) (fs, ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) dcopuop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) rv.d = (*handler.u) (fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) * unary conv ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) case fcvts_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) MIPS_FPU_EMU_INC_STATS(cvt_s_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) rv.s = ieee754sp_fdp(fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) rfmt = s_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) case fcvtd_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) return SIGILL; /* not defined */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) case fcvtw_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) MIPS_FPU_EMU_INC_STATS(cvt_w_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) rv.w = ieee754dp_tint(fs); /* wrong */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) rfmt = w_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) case fround_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) case ftrunc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) case fceil_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) case ffloor_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) if (!cpu_has_mips_2_3_4_5_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) if (MIPSInst_FUNC(ir) == fceil_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) MIPS_FPU_EMU_INC_STATS(ceil_w_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) if (MIPSInst_FUNC(ir) == ffloor_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) MIPS_FPU_EMU_INC_STATS(floor_w_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) if (MIPSInst_FUNC(ir) == fround_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) MIPS_FPU_EMU_INC_STATS(round_w_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) if (MIPSInst_FUNC(ir) == ftrunc_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) MIPS_FPU_EMU_INC_STATS(trunc_w_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) oldrm = ieee754_csr.rm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) ieee754_csr.rm = MIPSInst_FUNC(ir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) rv.w = ieee754dp_tint(fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) ieee754_csr.rm = oldrm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) rfmt = w_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) case fsel_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) if (!cpu_has_mips_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) MIPS_FPU_EMU_INC_STATS(sel_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) DPFROMREG(fd, MIPSInst_FD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) if (fd.bits & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) DPFROMREG(rv.d, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) DPFROMREG(rv.d, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) case fcvtl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) if (!cpu_has_mips_3_4_5_64_r2_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) MIPS_FPU_EMU_INC_STATS(cvt_l_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) rv.l = ieee754dp_tlong(fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) rfmt = l_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) case froundl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) case ftruncl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) case fceill_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) case ffloorl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) if (!cpu_has_mips_3_4_5_64_r2_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) if (MIPSInst_FUNC(ir) == fceill_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) MIPS_FPU_EMU_INC_STATS(ceil_l_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) if (MIPSInst_FUNC(ir) == ffloorl_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) MIPS_FPU_EMU_INC_STATS(floor_l_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) if (MIPSInst_FUNC(ir) == froundl_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) MIPS_FPU_EMU_INC_STATS(round_l_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) if (MIPSInst_FUNC(ir) == ftruncl_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) MIPS_FPU_EMU_INC_STATS(trunc_l_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) oldrm = ieee754_csr.rm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) ieee754_csr.rm = MIPSInst_FUNC(ir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) rv.l = ieee754dp_tlong(fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) ieee754_csr.rm = oldrm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) rfmt = l_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) if (!NO_R6EMU && MIPSInst_FUNC(ir) >= fcmp_op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) unsigned int cmpop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) union ieee754dp fs, ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) cmpop = MIPSInst_FUNC(ir) - fcmp_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) DPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) rv.w = ieee754dp_cmp(fs, ft,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) cmptab[cmpop & 0x7], cmpop & 0x8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) rfmt = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) if ((cmpop & 0x8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) ieee754_cxtest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) (IEEE754_INVALID_OPERATION))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) case w_fmt: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) union ieee754dp fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) switch (MIPSInst_FUNC(ir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) case fcvts_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) /* convert word to single precision real */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) MIPS_FPU_EMU_INC_STATS(cvt_s_w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) rv.s = ieee754sp_fint(fs.bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) rfmt = s_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) case fcvtd_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) /* convert word to double precision real */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) MIPS_FPU_EMU_INC_STATS(cvt_d_w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) rv.d = ieee754dp_fint(fs.bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) rfmt = d_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) default: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) /* Emulating the new CMP.condn.fmt R6 instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) #define CMPOP_MASK 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) #define SIGN_BIT (0x1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) #define PREDICATE_BIT (0x1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) int cmpop = MIPSInst_FUNC(ir) & CMPOP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) int sig = MIPSInst_FUNC(ir) & SIGN_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) union ieee754sp fs, ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) /* This is an R6 only instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) if (!cpu_has_mips_r6 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) (MIPSInst_FUNC(ir) & 0x20))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) if (!sig) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) switch (cmpop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) MIPS_FPU_EMU_INC_STATS(cmp_af_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) MIPS_FPU_EMU_INC_STATS(cmp_un_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) MIPS_FPU_EMU_INC_STATS(cmp_eq_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) MIPS_FPU_EMU_INC_STATS(cmp_ueq_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) MIPS_FPU_EMU_INC_STATS(cmp_lt_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) MIPS_FPU_EMU_INC_STATS(cmp_ult_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) MIPS_FPU_EMU_INC_STATS(cmp_le_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) MIPS_FPU_EMU_INC_STATS(cmp_ule_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) switch (cmpop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) MIPS_FPU_EMU_INC_STATS(cmp_or_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) MIPS_FPU_EMU_INC_STATS(cmp_une_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) MIPS_FPU_EMU_INC_STATS(cmp_ne_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) switch (cmpop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) MIPS_FPU_EMU_INC_STATS(cmp_saf_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) MIPS_FPU_EMU_INC_STATS(cmp_sun_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) MIPS_FPU_EMU_INC_STATS(cmp_seq_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) MIPS_FPU_EMU_INC_STATS(cmp_sueq_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) MIPS_FPU_EMU_INC_STATS(cmp_slt_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) MIPS_FPU_EMU_INC_STATS(cmp_sult_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) MIPS_FPU_EMU_INC_STATS(cmp_sle_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) MIPS_FPU_EMU_INC_STATS(cmp_sule_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) switch (cmpop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) MIPS_FPU_EMU_INC_STATS(cmp_sor_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) MIPS_FPU_EMU_INC_STATS(cmp_sune_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) MIPS_FPU_EMU_INC_STATS(cmp_sne_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) /* fmt is w_fmt for single precision so fix it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) rfmt = s_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) /* default to false */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) rv.w = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) /* CMP.condn.S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) SPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) SPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) /* positive predicates */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) if (ieee754sp_cmp(fs, ft, cmptab[cmpop],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) sig))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) rv.w = -1; /* true, all 1s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) if ((sig) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) ieee754_cxtest(IEEE754_INVALID_OPERATION))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) /* negative predicates */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) switch (cmpop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) if (ieee754sp_cmp(fs, ft,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) negative_cmptab[cmpop],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) sig))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) rv.w = -1; /* true, all 1s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) if (sig &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) ieee754_cxtest(IEEE754_INVALID_OPERATION))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) /* Reserved R6 ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) case l_fmt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) if (!cpu_has_mips_3_4_5_64_r2_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) DIFROMREG(bits, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) switch (MIPSInst_FUNC(ir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) case fcvts_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) /* convert long to single precision real */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) MIPS_FPU_EMU_INC_STATS(cvt_s_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) rv.s = ieee754sp_flong(bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) rfmt = s_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) case fcvtd_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) /* convert long to double precision real */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) MIPS_FPU_EMU_INC_STATS(cvt_d_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) rv.d = ieee754dp_flong(bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) rfmt = d_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) default: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) /* Emulating the new CMP.condn.fmt R6 instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) int cmpop = MIPSInst_FUNC(ir) & CMPOP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) int sig = MIPSInst_FUNC(ir) & SIGN_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) union ieee754dp fs, ft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) if (!cpu_has_mips_r6 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) (MIPSInst_FUNC(ir) & 0x20))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) if (!sig) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) switch (cmpop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) MIPS_FPU_EMU_INC_STATS(cmp_af_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) MIPS_FPU_EMU_INC_STATS(cmp_un_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) MIPS_FPU_EMU_INC_STATS(cmp_eq_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) MIPS_FPU_EMU_INC_STATS(cmp_ueq_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) MIPS_FPU_EMU_INC_STATS(cmp_lt_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) MIPS_FPU_EMU_INC_STATS(cmp_ult_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) MIPS_FPU_EMU_INC_STATS(cmp_le_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) MIPS_FPU_EMU_INC_STATS(cmp_ule_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) switch (cmpop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) MIPS_FPU_EMU_INC_STATS(cmp_or_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) MIPS_FPU_EMU_INC_STATS(cmp_une_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) MIPS_FPU_EMU_INC_STATS(cmp_ne_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) switch (cmpop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) MIPS_FPU_EMU_INC_STATS(cmp_saf_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) MIPS_FPU_EMU_INC_STATS(cmp_sun_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) MIPS_FPU_EMU_INC_STATS(cmp_seq_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) MIPS_FPU_EMU_INC_STATS(cmp_sueq_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) MIPS_FPU_EMU_INC_STATS(cmp_slt_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) MIPS_FPU_EMU_INC_STATS(cmp_sult_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) MIPS_FPU_EMU_INC_STATS(cmp_sle_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) MIPS_FPU_EMU_INC_STATS(cmp_sule_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) switch (cmpop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) MIPS_FPU_EMU_INC_STATS(cmp_sor_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) MIPS_FPU_EMU_INC_STATS(cmp_sune_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) MIPS_FPU_EMU_INC_STATS(cmp_sne_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) /* fmt is l_fmt for double precision so fix it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) rfmt = d_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) /* default to false */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) rv.l = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) /* CMP.condn.D */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) DPFROMREG(fs, MIPSInst_FS(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) DPFROMREG(ft, MIPSInst_FT(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) /* positive predicates */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) if (ieee754dp_cmp(fs, ft,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) cmptab[cmpop], sig))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) rv.l = -1LL; /* true, all 1s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) if (sig &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) ieee754_cxtest(IEEE754_INVALID_OPERATION))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) /* negative predicates */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) switch (cmpop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) if (ieee754dp_cmp(fs, ft,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) negative_cmptab[cmpop],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) sig))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) rv.l = -1LL; /* true, all 1s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) if (sig &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) ieee754_cxtest(IEEE754_INVALID_OPERATION))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) goto copcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) /* Reserved R6 ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) * Update the fpu CSR register for this operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) * If an exception is required, generate a tidy SIGFPE exception,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) * without updating the result register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) * Note: cause exception bits do not accumulate, they are rewritten
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) * for each op; only the flag/sticky bits accumulate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) /*printk ("SIGFPE: FPU csr = %08x\n",ctx->fcr31); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) return SIGFPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) * Now we can safely write the result back to the register file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) switch (rfmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) case -1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) if (cpu_has_mips_4_5_r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) cbit = fpucondbit[MIPSInst_FD(ir) >> 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) cbit = FPU_CSR_COND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) if (rv.w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) ctx->fcr31 |= cbit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) ctx->fcr31 &= ~cbit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) case d_fmt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) DPTOREG(rv.d, MIPSInst_FD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) case s_fmt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) SPTOREG(rv.s, MIPSInst_FD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) case w_fmt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) SITOREG(rv.w, MIPSInst_FD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) case l_fmt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) if (!cpu_has_mips_3_4_5_64_r2_r6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) DITOREG(rv.l, MIPSInst_FD(ir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) return SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) * Emulate FPU instructions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) * If we use FPU hardware, then we have been typically called to handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) * an unimplemented operation, such as where an operand is a NaN or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) * denormalized. In that case exit the emulation loop after a single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) * iteration so as to let hardware execute any subsequent instructions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) * If we have no FPU hardware or it has been disabled, then continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) * emulating floating-point instructions until one of these conditions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) * has occurred:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) * - a non-FPU instruction has been encountered,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) * - an attempt to emulate has ended with a signal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) * - the ISA mode has been switched.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) * We need to terminate the emulation loop if we got switched to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) * MIPS16 mode, whether supported or not, so that we do not attempt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) * to emulate a MIPS16 instruction as a regular MIPS FPU instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) * Similarly if we got switched to the microMIPS mode and only the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) * regular MIPS mode is supported, so that we do not attempt to emulate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) * a microMIPS instruction as a regular MIPS FPU instruction. Or if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) * we got switched to the regular MIPS mode and only the microMIPS mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) * is supported, so that we do not attempt to emulate a regular MIPS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) * instruction that should cause an Address Error exception instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) * For simplicity we always terminate upon an ISA mode switch.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) int has_fpu, void __user **fault_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) unsigned long oldepc, prevepc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) struct mm_decoded_insn dec_insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) u16 instr[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) u16 *instr_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) int sig = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) * Initialize context if it hasn't been used already, otherwise ensure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) * it has been saved to struct thread_struct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) if (!init_fp_ctx(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) lose_fpu(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) oldepc = xcp->cp0_epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) prevepc = xcp->cp0_epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) if (get_isa16_mode(prevepc) && cpu_has_mmips) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) * Get next 2 microMIPS instructions and convert them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) * into 32-bit instructions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) if ((get_user(instr[0], (u16 __user *)msk_isa16_mode(xcp->cp0_epc))) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) (get_user(instr[1], (u16 __user *)msk_isa16_mode(xcp->cp0_epc + 2))) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) (get_user(instr[2], (u16 __user *)msk_isa16_mode(xcp->cp0_epc + 4))) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) (get_user(instr[3], (u16 __user *)msk_isa16_mode(xcp->cp0_epc + 6)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) return SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) instr_ptr = instr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) /* Get first instruction. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) if (mm_insn_16bit(*instr_ptr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) /* Duplicate the half-word. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) dec_insn.insn = (*instr_ptr << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) (*instr_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) /* 16-bit instruction. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) dec_insn.pc_inc = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) instr_ptr += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) dec_insn.insn = (*instr_ptr << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) *(instr_ptr+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) /* 32-bit instruction. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) dec_insn.pc_inc = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) instr_ptr += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) /* Get second instruction. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) if (mm_insn_16bit(*instr_ptr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) /* Duplicate the half-word. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) dec_insn.next_insn = (*instr_ptr << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) (*instr_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) /* 16-bit instruction. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) dec_insn.next_pc_inc = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) dec_insn.next_insn = (*instr_ptr << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) *(instr_ptr+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) /* 32-bit instruction. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) dec_insn.next_pc_inc = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) dec_insn.micro_mips_mode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) if ((get_user(dec_insn.insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) (mips_instruction __user *) xcp->cp0_epc)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) (get_user(dec_insn.next_insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) (mips_instruction __user *)(xcp->cp0_epc+4)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) MIPS_FPU_EMU_INC_STATS(errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) return SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) dec_insn.pc_inc = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) dec_insn.next_pc_inc = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) dec_insn.micro_mips_mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) if ((dec_insn.insn == 0) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) ((dec_insn.pc_inc == 2) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) ((dec_insn.insn & 0xffff) == MM_NOP16)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) xcp->cp0_epc += dec_insn.pc_inc; /* Skip NOPs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) * The 'ieee754_csr' is an alias of ctx->fcr31.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) * No need to copy ctx->fcr31 to ieee754_csr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) sig = cop1Emulate(xcp, ctx, dec_insn, fault_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) if (has_fpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) if (sig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) * We have to check for the ISA bit explicitly here,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) * because `get_isa16_mode' may return 0 if support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) * for code compression has been globally disabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) * or otherwise we may produce the wrong signal or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) * even proceed successfully where we must not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) if ((xcp->cp0_epc ^ prevepc) & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) } while (xcp->cp0_epc > prevepc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) /* SIGILL indicates a non-fpu instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) if (sig == SIGILL && xcp->cp0_epc != oldepc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) /* but if EPC has advanced, then ignore it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) sig = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) return sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) }