^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* visemul.c: Emulation of VIS instructions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2006 David S. Miller (davem@davemloft.net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/thread_info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/perf_event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/pstate.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/fpumacro.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /* OPF field of various VIS instructions. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* 000111011 - four 16-bit packs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define FPACK16_OPF 0x03b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* 000111010 - two 32-bit packs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define FPACK32_OPF 0x03a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* 000111101 - four 16-bit packs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define FPACKFIX_OPF 0x03d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* 001001101 - four 16-bit expands */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define FEXPAND_OPF 0x04d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* 001001011 - two 32-bit merges */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define FPMERGE_OPF 0x04b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* 000110001 - 8-by-16-bit partitioned product */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define FMUL8x16_OPF 0x031
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* 000110011 - 8-by-16-bit upper alpha partitioned product */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define FMUL8x16AU_OPF 0x033
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* 000110101 - 8-by-16-bit lower alpha partitioned product */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define FMUL8x16AL_OPF 0x035
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /* 000110110 - upper 8-by-16-bit partitioned product */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define FMUL8SUx16_OPF 0x036
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* 000110111 - lower 8-by-16-bit partitioned product */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define FMUL8ULx16_OPF 0x037
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* 000111000 - upper 8-by-16-bit partitioned product */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define FMULD8SUx16_OPF 0x038
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /* 000111001 - lower unsigned 8-by-16-bit partitioned product */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define FMULD8ULx16_OPF 0x039
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* 000101000 - four 16-bit compare; set rd if src1 > src2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define FCMPGT16_OPF 0x028
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* 000101100 - two 32-bit compare; set rd if src1 > src2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define FCMPGT32_OPF 0x02c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* 000100000 - four 16-bit compare; set rd if src1 <= src2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define FCMPLE16_OPF 0x020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* 000100100 - two 32-bit compare; set rd if src1 <= src2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define FCMPLE32_OPF 0x024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* 000100010 - four 16-bit compare; set rd if src1 != src2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define FCMPNE16_OPF 0x022
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* 000100110 - two 32-bit compare; set rd if src1 != src2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define FCMPNE32_OPF 0x026
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* 000101010 - four 16-bit compare; set rd if src1 == src2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define FCMPEQ16_OPF 0x02a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* 000101110 - two 32-bit compare; set rd if src1 == src2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define FCMPEQ32_OPF 0x02e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* 000000000 - Eight 8-bit edge boundary processing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define EDGE8_OPF 0x000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* 000000001 - Eight 8-bit edge boundary processing, no CC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define EDGE8N_OPF 0x001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* 000000010 - Eight 8-bit edge boundary processing, little-endian */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define EDGE8L_OPF 0x002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* 000000011 - Eight 8-bit edge boundary processing, little-endian, no CC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define EDGE8LN_OPF 0x003
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /* 000000100 - Four 16-bit edge boundary processing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define EDGE16_OPF 0x004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* 000000101 - Four 16-bit edge boundary processing, no CC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define EDGE16N_OPF 0x005
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* 000000110 - Four 16-bit edge boundary processing, little-endian */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define EDGE16L_OPF 0x006
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* 000000111 - Four 16-bit edge boundary processing, little-endian, no CC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define EDGE16LN_OPF 0x007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* 000001000 - Two 32-bit edge boundary processing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define EDGE32_OPF 0x008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* 000001001 - Two 32-bit edge boundary processing, no CC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define EDGE32N_OPF 0x009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* 000001010 - Two 32-bit edge boundary processing, little-endian */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define EDGE32L_OPF 0x00a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* 000001011 - Two 32-bit edge boundary processing, little-endian, no CC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define EDGE32LN_OPF 0x00b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /* 000111110 - distance between 8 8-bit components */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define PDIST_OPF 0x03e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* 000010000 - convert 8-bit 3-D address to blocked byte address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define ARRAY8_OPF 0x010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* 000010010 - convert 16-bit 3-D address to blocked byte address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define ARRAY16_OPF 0x012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* 000010100 - convert 32-bit 3-D address to blocked byte address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define ARRAY32_OPF 0x014
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /* 000011001 - Set the GSR.MASK field in preparation for a BSHUFFLE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define BMASK_OPF 0x019
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* 001001100 - Permute bytes as specified by GSR.MASK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define BSHUFFLE_OPF 0x04c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define VIS_OPF_SHIFT 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define VIS_OPF_MASK (0x1ff << VIS_OPF_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define RS1(INSN) (((INSN) >> 14) & 0x1f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define RS2(INSN) (((INSN) >> 0) & 0x1f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define RD(INSN) (((INSN) >> 25) & 0x1f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) unsigned int rd, int from_kernel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (rs2 >= 16 || rs1 >= 16 || rd >= 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (from_kernel != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) __asm__ __volatile__("flushw");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) flushw_user();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) unsigned long value, fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (reg < 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return (!reg ? 0 : regs->u_regs[reg]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) fp = regs->u_regs[UREG_FP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (regs->tstate & TSTATE_PRIV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct reg_window *win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) win = (struct reg_window *)(fp + STACK_BIAS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) value = win->locals[reg - 16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) } else if (!test_thread_64bit_stack(fp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct reg_window32 __user *win32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) get_user(value, &win32->locals[reg - 16]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct reg_window __user *win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) win = (struct reg_window __user *)(fp + STACK_BIAS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) get_user(value, &win->locals[reg - 16]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static inline unsigned long __user *__fetch_reg_addr_user(unsigned int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) unsigned long fp = regs->u_regs[UREG_FP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) BUG_ON(reg < 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) BUG_ON(regs->tstate & TSTATE_PRIV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (!test_thread_64bit_stack(fp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct reg_window32 __user *win32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return (unsigned long __user *)&win32->locals[reg - 16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct reg_window __user *win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) win = (struct reg_window __user *)(fp + STACK_BIAS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return &win->locals[reg - 16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static inline unsigned long *__fetch_reg_addr_kern(unsigned int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) BUG_ON(reg >= 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) BUG_ON(regs->tstate & TSTATE_PRIV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return ®s->u_regs[reg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static void store_reg(struct pt_regs *regs, unsigned long val, unsigned long rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (rd < 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) unsigned long *rd_kern = __fetch_reg_addr_kern(rd, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) *rd_kern = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) unsigned long __user *rd_user = __fetch_reg_addr_user(rd, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (!test_thread_64bit_stack(regs->u_regs[UREG_FP]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) __put_user((u32)val, (u32 __user *)rd_user);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) __put_user(val, rd_user);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static inline unsigned long fpd_regval(struct fpustate *f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) unsigned int insn_regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) insn_regnum = (((insn_regnum & 1) << 5) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) (insn_regnum & 0x1e));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return *(unsigned long *) &f->regs[insn_regnum];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static inline unsigned long *fpd_regaddr(struct fpustate *f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) unsigned int insn_regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) insn_regnum = (((insn_regnum & 1) << 5) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) (insn_regnum & 0x1e));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return (unsigned long *) &f->regs[insn_regnum];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static inline unsigned int fps_regval(struct fpustate *f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) unsigned int insn_regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return f->regs[insn_regnum];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static inline unsigned int *fps_regaddr(struct fpustate *f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) unsigned int insn_regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return &f->regs[insn_regnum];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct edge_tab {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) u16 left, right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static struct edge_tab edge8_tab[8] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) { 0xff, 0x80 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) { 0x7f, 0xc0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) { 0x3f, 0xe0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) { 0x1f, 0xf0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) { 0x0f, 0xf8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) { 0x07, 0xfc },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) { 0x03, 0xfe },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) { 0x01, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static struct edge_tab edge8_tab_l[8] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) { 0xff, 0x01 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) { 0xfe, 0x03 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) { 0xfc, 0x07 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) { 0xf8, 0x0f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) { 0xf0, 0x1f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) { 0xe0, 0x3f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) { 0xc0, 0x7f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) { 0x80, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static struct edge_tab edge16_tab[4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) { 0xf, 0x8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) { 0x7, 0xc },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) { 0x3, 0xe },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) { 0x1, 0xf },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static struct edge_tab edge16_tab_l[4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) { 0xf, 0x1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) { 0xe, 0x3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) { 0xc, 0x7 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) { 0x8, 0xf },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static struct edge_tab edge32_tab[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) { 0x3, 0x2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) { 0x1, 0x3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static struct edge_tab edge32_tab_l[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) { 0x3, 0x1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) { 0x2, 0x3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static void edge(struct pt_regs *regs, unsigned int insn, unsigned int opf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) unsigned long orig_rs1, rs1, orig_rs2, rs2, rd_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) u16 left, right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) maybe_flush_windows(RS1(insn), RS2(insn), RD(insn), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) orig_rs1 = rs1 = fetch_reg(RS1(insn), regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) orig_rs2 = rs2 = fetch_reg(RS2(insn), regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (test_thread_flag(TIF_32BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) rs1 = rs1 & 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) rs2 = rs2 & 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) switch (opf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) case EDGE8_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) case EDGE8N_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) left = edge8_tab[rs1 & 0x7].left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) right = edge8_tab[rs2 & 0x7].right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) case EDGE8L_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) case EDGE8LN_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) left = edge8_tab_l[rs1 & 0x7].left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) right = edge8_tab_l[rs2 & 0x7].right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) case EDGE16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) case EDGE16N_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) left = edge16_tab[(rs1 >> 1) & 0x3].left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) right = edge16_tab[(rs2 >> 1) & 0x3].right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) case EDGE16L_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) case EDGE16LN_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) left = edge16_tab_l[(rs1 >> 1) & 0x3].left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) right = edge16_tab_l[(rs2 >> 1) & 0x3].right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) case EDGE32_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) case EDGE32N_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) left = edge32_tab[(rs1 >> 2) & 0x1].left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) right = edge32_tab[(rs2 >> 2) & 0x1].right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) case EDGE32L_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) case EDGE32LN_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) left = edge32_tab_l[(rs1 >> 2) & 0x1].left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) right = edge32_tab_l[(rs2 >> 2) & 0x1].right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if ((rs1 & ~0x7UL) == (rs2 & ~0x7UL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) rd_val = right & left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) rd_val = left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) store_reg(regs, rd_val, RD(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) switch (opf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) case EDGE8_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) case EDGE8L_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) case EDGE16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) case EDGE16L_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) case EDGE32_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) case EDGE32L_OPF: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) unsigned long ccr, tstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) __asm__ __volatile__("subcc %1, %2, %%g0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) "rd %%ccr, %0"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) : "=r" (ccr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) : "r" (orig_rs1), "r" (orig_rs2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) : "cc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) tstate = regs->tstate & ~(TSTATE_XCC | TSTATE_ICC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) regs->tstate = tstate | (ccr << 32UL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static void array(struct pt_regs *regs, unsigned int insn, unsigned int opf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) unsigned long rs1, rs2, rd_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) unsigned int bits, bits_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) maybe_flush_windows(RS1(insn), RS2(insn), RD(insn), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) rs1 = fetch_reg(RS1(insn), regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) rs2 = fetch_reg(RS2(insn), regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) bits = (rs2 > 5 ? 5 : rs2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) bits_mask = (1UL << bits) - 1UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) rd_val = ((((rs1 >> 11) & 0x3) << 0) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) (((rs1 >> 33) & 0x3) << 2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) (((rs1 >> 55) & 0x1) << 4) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) (((rs1 >> 13) & 0xf) << 5) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) (((rs1 >> 35) & 0xf) << 9) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) (((rs1 >> 56) & 0xf) << 13) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) (((rs1 >> 17) & bits_mask) << 17) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) (((rs1 >> 39) & bits_mask) << (17 + bits)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) (((rs1 >> 60) & 0xf) << (17 + (2*bits))));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) switch (opf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) case ARRAY16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) rd_val <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) case ARRAY32_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) rd_val <<= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) store_reg(regs, rd_val, RD(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) static void bmask(struct pt_regs *regs, unsigned int insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) unsigned long rs1, rs2, rd_val, gsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) maybe_flush_windows(RS1(insn), RS2(insn), RD(insn), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) rs1 = fetch_reg(RS1(insn), regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) rs2 = fetch_reg(RS2(insn), regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) rd_val = rs1 + rs2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) store_reg(regs, rd_val, RD(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) gsr = current_thread_info()->gsr[0] & 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) gsr |= rd_val << 32UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) current_thread_info()->gsr[0] = gsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) static void bshuffle(struct pt_regs *regs, unsigned int insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct fpustate *f = FPUSTATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) unsigned long rs1, rs2, rd_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) unsigned long bmask, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) bmask = current_thread_info()->gsr[0] >> 32UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) rs1 = fpd_regval(f, RS1(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) rs2 = fpd_regval(f, RS2(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) rd_val = 0UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) unsigned long which = (bmask >> (i * 4)) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) unsigned long byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (which < 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) byte = (rs1 >> (which * 8)) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) byte = (rs2 >> ((which-8)*8)) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) rd_val |= (byte << (i * 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) *fpd_regaddr(f, RD(insn)) = rd_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static void pdist(struct pt_regs *regs, unsigned int insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) struct fpustate *f = FPUSTATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) unsigned long rs1, rs2, *rd, rd_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) unsigned long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) rs1 = fpd_regval(f, RS1(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) rs2 = fpd_regval(f, RS2(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) rd = fpd_regaddr(f, RD(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) rd_val = *rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) s16 s1, s2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) s1 = (rs1 >> (56 - (i * 8))) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) s2 = (rs2 >> (56 - (i * 8))) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /* Absolute value of difference. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) s1 -= s2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (s1 < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) s1 = ~s1 + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) rd_val += s1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) *rd = rd_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) static void pformat(struct pt_regs *regs, unsigned int insn, unsigned int opf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) struct fpustate *f = FPUSTATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) unsigned long rs1, rs2, gsr, scale, rd_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) gsr = current_thread_info()->gsr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) scale = (gsr >> 3) & (opf == FPACK16_OPF ? 0xf : 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) switch (opf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) case FPACK16_OPF: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) unsigned long byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) rs2 = fpd_regval(f, RS2(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) rd_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) for (byte = 0; byte < 4; byte++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) s16 src = (rs2 >> (byte * 16UL)) & 0xffffUL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) int scaled = src << scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) int from_fixed = scaled >> 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) val = ((from_fixed < 0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) (from_fixed > 255) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 255 : from_fixed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) rd_val |= (val << (8 * byte));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) *fps_regaddr(f, RD(insn)) = rd_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) case FPACK32_OPF: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) unsigned long word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) rs1 = fpd_regval(f, RS1(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) rs2 = fpd_regval(f, RS2(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) rd_val = (rs1 << 8) & ~(0x000000ff000000ffUL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) for (word = 0; word < 2; word++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) s32 src = (rs2 >> (word * 32UL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) s64 scaled = src << scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) s64 from_fixed = scaled >> 23;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) val = ((from_fixed < 0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) (from_fixed > 255) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 255 : from_fixed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) rd_val |= (val << (32 * word));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) *fpd_regaddr(f, RD(insn)) = rd_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) case FPACKFIX_OPF: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) unsigned long word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) rs2 = fpd_regval(f, RS2(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) rd_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) for (word = 0; word < 2; word++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) s32 src = (rs2 >> (word * 32UL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) s64 scaled = src << scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) s64 from_fixed = scaled >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) val = ((from_fixed < -32768) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) -32768 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) (from_fixed > 32767) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 32767 : from_fixed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) rd_val |= ((val & 0xffff) << (word * 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) *fps_regaddr(f, RD(insn)) = rd_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) case FEXPAND_OPF: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) unsigned long byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) rs2 = fps_regval(f, RS2(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) rd_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) for (byte = 0; byte < 4; byte++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) u8 src = (rs2 >> (byte * 8)) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) val = src << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) rd_val |= (val << (byte * 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) *fpd_regaddr(f, RD(insn)) = rd_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) case FPMERGE_OPF: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) rs1 = fps_regval(f, RS1(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) rs2 = fps_regval(f, RS2(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) rd_val = (((rs2 & 0x000000ff) << 0) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) ((rs1 & 0x000000ff) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) ((rs2 & 0x0000ff00) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) ((rs1 & 0x0000ff00) << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) ((rs2 & 0x00ff0000) << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) ((rs1 & 0x00ff0000) << 24) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) ((rs2 & 0xff000000) << 24) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) ((rs1 & 0xff000000) << 32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) *fpd_regaddr(f, RD(insn)) = rd_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) static void pmul(struct pt_regs *regs, unsigned int insn, unsigned int opf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) struct fpustate *f = FPUSTATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) unsigned long rs1, rs2, rd_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) switch (opf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) case FMUL8x16_OPF: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) unsigned long byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) rs1 = fps_regval(f, RS1(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) rs2 = fpd_regval(f, RS2(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) rd_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) for (byte = 0; byte < 4; byte++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) u16 src1 = (rs1 >> (byte * 8)) & 0x00ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) s16 src2 = (rs2 >> (byte * 16)) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) u32 prod = src1 * src2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) u16 scaled = ((prod & 0x00ffff00) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) /* Round up. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (prod & 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) scaled++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) rd_val |= ((scaled & 0xffffUL) << (byte * 16UL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) *fpd_regaddr(f, RD(insn)) = rd_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) case FMUL8x16AU_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) case FMUL8x16AL_OPF: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) unsigned long byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) s16 src2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) rs1 = fps_regval(f, RS1(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) rs2 = fps_regval(f, RS2(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) rd_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) src2 = rs2 >> (opf == FMUL8x16AU_OPF ? 16 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) for (byte = 0; byte < 4; byte++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) u16 src1 = (rs1 >> (byte * 8)) & 0x00ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) u32 prod = src1 * src2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) u16 scaled = ((prod & 0x00ffff00) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) /* Round up. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (prod & 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) scaled++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) rd_val |= ((scaled & 0xffffUL) << (byte * 16UL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) *fpd_regaddr(f, RD(insn)) = rd_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) case FMUL8SUx16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) case FMUL8ULx16_OPF: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) unsigned long byte, ushift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) rs1 = fpd_regval(f, RS1(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) rs2 = fpd_regval(f, RS2(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) rd_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) ushift = (opf == FMUL8SUx16_OPF) ? 8 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) for (byte = 0; byte < 4; byte++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) u16 src1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) s16 src2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) u32 prod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) u16 scaled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) src1 = ((rs1 >> ((16 * byte) + ushift)) & 0x00ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) src2 = ((rs2 >> (16 * byte)) & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) prod = src1 * src2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) scaled = ((prod & 0x00ffff00) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) /* Round up. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (prod & 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) scaled++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) rd_val |= ((scaled & 0xffffUL) << (byte * 16UL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) *fpd_regaddr(f, RD(insn)) = rd_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) case FMULD8SUx16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) case FMULD8ULx16_OPF: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) unsigned long byte, ushift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) rs1 = fps_regval(f, RS1(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) rs2 = fps_regval(f, RS2(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) rd_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) ushift = (opf == FMULD8SUx16_OPF) ? 8 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) for (byte = 0; byte < 2; byte++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) u16 src1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) s16 src2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) u32 prod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) u16 scaled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) src1 = ((rs1 >> ((16 * byte) + ushift)) & 0x00ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) src2 = ((rs2 >> (16 * byte)) & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) prod = src1 * src2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) scaled = ((prod & 0x00ffff00) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) /* Round up. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (prod & 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) scaled++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) rd_val |= ((scaled & 0xffffUL) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) ((byte * 32UL) + 7UL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) *fpd_regaddr(f, RD(insn)) = rd_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) struct fpustate *f = FPUSTATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) unsigned long rs1, rs2, rd_val, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) rs1 = fpd_regval(f, RS1(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) rs2 = fpd_regval(f, RS2(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) rd_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) switch (opf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) case FCMPGT16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) s16 a = (rs1 >> (i * 16)) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) s16 b = (rs2 >> (i * 16)) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (a > b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) rd_val |= 8 >> i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) case FCMPGT32_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) s32 a = (rs1 >> (i * 32)) & 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) s32 b = (rs2 >> (i * 32)) & 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (a > b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) rd_val |= 2 >> i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) case FCMPLE16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) s16 a = (rs1 >> (i * 16)) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) s16 b = (rs2 >> (i * 16)) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (a <= b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) rd_val |= 8 >> i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) case FCMPLE32_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) s32 a = (rs1 >> (i * 32)) & 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) s32 b = (rs2 >> (i * 32)) & 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (a <= b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) rd_val |= 2 >> i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) case FCMPNE16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) s16 a = (rs1 >> (i * 16)) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) s16 b = (rs2 >> (i * 16)) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (a != b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) rd_val |= 8 >> i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) case FCMPNE32_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) s32 a = (rs1 >> (i * 32)) & 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) s32 b = (rs2 >> (i * 32)) & 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (a != b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) rd_val |= 2 >> i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) case FCMPEQ16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) s16 a = (rs1 >> (i * 16)) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) s16 b = (rs2 >> (i * 16)) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (a == b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) rd_val |= 8 >> i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) case FCMPEQ32_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) s32 a = (rs1 >> (i * 32)) & 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) s32 b = (rs2 >> (i * 32)) & 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (a == b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) rd_val |= 2 >> i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) maybe_flush_windows(0, 0, RD(insn), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) store_reg(regs, rd_val, RD(insn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) /* Emulate the VIS instructions which are not implemented in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) * hardware on Niagara.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) int vis_emul(struct pt_regs *regs, unsigned int insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) unsigned long pc = regs->tpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) unsigned int opf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) BUG_ON(regs->tstate & TSTATE_PRIV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (test_thread_flag(TIF_32BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) pc = (u32)pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) if (get_user(insn, (u32 __user *) pc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) save_and_clear_fpu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) opf = (insn & VIS_OPF_MASK) >> VIS_OPF_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) switch (opf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) /* Pixel Formatting Instructions. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) case FPACK16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) case FPACK32_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) case FPACKFIX_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) case FEXPAND_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) case FPMERGE_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) pformat(regs, insn, opf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) /* Partitioned Multiply Instructions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) case FMUL8x16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) case FMUL8x16AU_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) case FMUL8x16AL_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) case FMUL8SUx16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) case FMUL8ULx16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) case FMULD8SUx16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) case FMULD8ULx16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) pmul(regs, insn, opf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) /* Pixel Compare Instructions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) case FCMPGT16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) case FCMPGT32_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) case FCMPLE16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) case FCMPLE32_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) case FCMPNE16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) case FCMPNE32_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) case FCMPEQ16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) case FCMPEQ32_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) pcmp(regs, insn, opf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) /* Edge Handling Instructions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) case EDGE8_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) case EDGE8N_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) case EDGE8L_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) case EDGE8LN_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) case EDGE16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) case EDGE16N_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) case EDGE16L_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) case EDGE16LN_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) case EDGE32_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) case EDGE32N_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) case EDGE32L_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) case EDGE32LN_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) edge(regs, insn, opf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) /* Pixel Component Distance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) case PDIST_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) pdist(regs, insn);
^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) /* Three-Dimensional Array Addressing Instructions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) case ARRAY8_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) case ARRAY16_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) case ARRAY32_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) array(regs, insn, opf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /* Byte Mask and Shuffle Instructions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) case BMASK_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) bmask(regs, insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) case BSHUFFLE_OPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) bshuffle(regs, insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) regs->tpc = regs->tnpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) regs->tnpc += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }