^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * arch/sh/math-emu/math.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2006 Takashi YOSHII <takasi-y@ops.dti.ne.jp>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * License. See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/perf_event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "sfp-util.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <math-emu/soft-fp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <math-emu/single.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <math-emu/double.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define FPUL (fregs->fpul)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define FPSCR (fregs->fpscr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define FPSCR_RM (FPSCR&3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define FPSCR_DN ((FPSCR>>18)&1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define FPSCR_PR ((FPSCR>>19)&1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define FPSCR_SZ ((FPSCR>>20)&1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define FPSCR_FR ((FPSCR>>21)&1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define FPSCR_MASK 0x003fffffUL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define BANK(n) (n^(FPSCR_FR?16:0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define FR ((unsigned long*)(fregs->fp_regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define FR0 (FR[BANK(0)])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define FRn (FR[BANK(n)])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define FRm (FR[BANK(m)])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define DR ((unsigned long long*)(fregs->fp_regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define DRn (DR[BANK(n)/2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define DRm (DR[BANK(m)/2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define XREG(n) (n^16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define XFn (FR[BANK(XREG(n))])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define XFm (FR[BANK(XREG(m))])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define XDn (DR[BANK(XREG(n))/2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define XDm (DR[BANK(XREG(m))/2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define R0 (regs->regs[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define Rn (regs->regs[n])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define Rm (regs->regs[m])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define WRITE(d,a) ({if(put_user(d, (typeof (d)*)a)) return -EFAULT;})
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define READ(d,a) ({if(get_user(d, (typeof (d)*)a)) return -EFAULT;})
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define PACK_S(r,f) FP_PACK_SP(&r,f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define UNPACK_S(f,r) FP_UNPACK_SP(f,&r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define PACK_D(r,f) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {u32 t[2]; FP_PACK_DP(t,f); ((u32*)&r)[0]=t[1]; ((u32*)&r)[1]=t[0];}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define UNPACK_D(f,r) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {u32 t[2]; t[0]=((u32*)&r)[1]; t[1]=((u32*)&r)[0]; FP_UNPACK_DP(f,t);}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) // 2 args instructions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define BOTH_PRmn(op,x) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) FP_DECL_EX; if(FPSCR_PR) op(D,x,DRm,DRn); else op(S,x,FRm,FRn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define CMP_X(SZ,R,M,N) do{ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) FP_DECL_##SZ(Fm); FP_DECL_##SZ(Fn); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) UNPACK_##SZ(Fm, M); UNPACK_##SZ(Fn, N); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) FP_CMP_##SZ(R, Fn, Fm, 2); }while(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define EQ_X(SZ,R,M,N) do{ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) FP_DECL_##SZ(Fm); FP_DECL_##SZ(Fn); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) UNPACK_##SZ(Fm, M); UNPACK_##SZ(Fn, N); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) FP_CMP_EQ_##SZ(R, Fn, Fm); }while(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define CMP(OP) ({ int r; BOTH_PRmn(OP##_X,r); r; })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) fcmp_gt(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (CMP(CMP) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) regs->sr |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) regs->sr &= ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) fcmp_eq(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (CMP(CMP /*EQ*/) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) regs->sr |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) regs->sr &= ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define ARITH_X(SZ,OP,M,N) do{ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) FP_DECL_##SZ(Fm); FP_DECL_##SZ(Fn); FP_DECL_##SZ(Fr); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) UNPACK_##SZ(Fm, M); UNPACK_##SZ(Fn, N); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) FP_##OP##_##SZ(Fr, Fn, Fm); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) PACK_##SZ(N, Fr); }while(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) fadd(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) BOTH_PRmn(ARITH_X, ADD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) fsub(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) BOTH_PRmn(ARITH_X, SUB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) fmul(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) BOTH_PRmn(ARITH_X, MUL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) fdiv(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) BOTH_PRmn(ARITH_X, DIV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) fmac(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) FP_DECL_EX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) FP_DECL_S(Fr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) FP_DECL_S(Ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) FP_DECL_S(F0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) FP_DECL_S(Fm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) FP_DECL_S(Fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) UNPACK_S(F0, FR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) UNPACK_S(Fm, FRm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) UNPACK_S(Fn, FRn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) FP_MUL_S(Ft, Fm, F0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) FP_ADD_S(Fr, Fn, Ft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) PACK_S(FRn, Fr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return 0;
^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) // to process fmov's extension (odd n for DR access XD).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define FMOV_EXT(x) if(x&1) x+=16-1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) fmov_idx_reg(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (FPSCR_SZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) FMOV_EXT(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) READ(FRn, Rm + R0 + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) READ(FRn, Rm + R0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) READ(FRn, Rm + R0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) fmov_mem_reg(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (FPSCR_SZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) FMOV_EXT(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) READ(FRn, Rm + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) READ(FRn, Rm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) READ(FRn, Rm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) fmov_inc_reg(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (FPSCR_SZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) FMOV_EXT(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) READ(FRn, Rm + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) READ(FRn, Rm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) Rm += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) READ(FRn, Rm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) Rm += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return 0;
^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 int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) fmov_reg_idx(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (FPSCR_SZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) FMOV_EXT(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) WRITE(FRm, Rn + R0 + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) m++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) WRITE(FRm, Rn + R0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) WRITE(FRm, Rn + R0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return 0;
^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 int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) fmov_reg_mem(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (FPSCR_SZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) FMOV_EXT(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) WRITE(FRm, Rn + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) m++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) WRITE(FRm, Rn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) WRITE(FRm, Rn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) fmov_reg_dec(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (FPSCR_SZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) FMOV_EXT(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) Rn -= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) WRITE(FRm, Rn + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) m++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) WRITE(FRm, Rn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) Rn -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) WRITE(FRm, Rn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) fmov_reg_reg(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (FPSCR_SZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) FMOV_EXT(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) FMOV_EXT(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) DRn = DRm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) FRn = FRm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) fnop_mn(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) // 1 arg instructions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) #define NOTYETn(i) static int i(struct sh_fpu_soft_struct *fregs, int n) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) { printk( #i " not yet done.\n"); return 0; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) NOTYETn(ftrv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) NOTYETn(fsqrt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) NOTYETn(fipr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) NOTYETn(fsca)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) NOTYETn(fsrra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) #define EMU_FLOAT_X(SZ,N) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) FP_DECL_##SZ(Fn); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) FP_FROM_INT_##SZ(Fn, FPUL, 32, int); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) PACK_##SZ(N, Fn); }while(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static int ffloat(struct sh_fpu_soft_struct *fregs, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) FP_DECL_EX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (FPSCR_PR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) EMU_FLOAT_X(D, DRn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) EMU_FLOAT_X(S, FRn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) #define EMU_FTRC_X(SZ,N) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) FP_DECL_##SZ(Fn); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) UNPACK_##SZ(Fn, N); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) FP_TO_INT_##SZ(FPUL, Fn, 32, 1); }while(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static int ftrc(struct sh_fpu_soft_struct *fregs, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) FP_DECL_EX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (FPSCR_PR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) EMU_FTRC_X(D, DRn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) EMU_FTRC_X(S, FRn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static int fcnvsd(struct sh_fpu_soft_struct *fregs, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) FP_DECL_EX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) FP_DECL_S(Fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) FP_DECL_D(Fr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) UNPACK_S(Fn, FPUL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) FP_CONV(D, S, 2, 1, Fr, Fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) PACK_D(DRn, Fr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) static int fcnvds(struct sh_fpu_soft_struct *fregs, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) FP_DECL_EX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) FP_DECL_D(Fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) FP_DECL_S(Fr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) UNPACK_D(Fn, DRn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) FP_CONV(S, D, 1, 2, Fr, Fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) PACK_S(FPUL, Fr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static int fxchg(struct sh_fpu_soft_struct *fregs, int flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) FPSCR ^= flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return 0;
^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) static int fsts(struct sh_fpu_soft_struct *fregs, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) FRn = FPUL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static int flds(struct sh_fpu_soft_struct *fregs, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) FPUL = FRn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static int fneg(struct sh_fpu_soft_struct *fregs, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) FRn ^= (1 << (_FP_W_TYPE_SIZE - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static int fabs(struct sh_fpu_soft_struct *fregs, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) FRn &= ~(1 << (_FP_W_TYPE_SIZE - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static int fld0(struct sh_fpu_soft_struct *fregs, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) FRn = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static int fld1(struct sh_fpu_soft_struct *fregs, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) FRn = (_FP_EXPBIAS_S << (_FP_FRACBITS_S - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static int fnop_n(struct sh_fpu_soft_struct *fregs, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /// Instruction decoders.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static int id_fxfd(struct sh_fpu_soft_struct *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static int id_fnxd(struct sh_fpu_soft_struct *, struct pt_regs *, int, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static int (*fnxd[])(struct sh_fpu_soft_struct *, int) = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) fsts, flds, ffloat, ftrc, fneg, fabs, fsqrt, fsrra,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) fld0, fld1, fcnvsd, fcnvds, fnop_n, fnop_n, fipr, id_fxfd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static int (*fnmx[])(struct sh_fpu_soft_struct *, struct pt_regs *, int, int) = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) fadd, fsub, fmul, fdiv, fcmp_eq, fcmp_gt, fmov_idx_reg, fmov_reg_idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) fmov_mem_reg, fmov_inc_reg, fmov_reg_mem, fmov_reg_dec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) fmov_reg_reg, id_fnxd, fmac, fnop_mn};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static int id_fxfd(struct sh_fpu_soft_struct *fregs, int x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) const int flag[] = { FPSCR_SZ, FPSCR_PR, FPSCR_FR, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) switch (x & 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) fxchg(fregs, flag[x >> 2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) ftrv(fregs, x - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) fsca(fregs, x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) id_fnxd(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int x, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return (fnxd[x])(fregs, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) id_fnmx(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, u16 code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) int n = (code >> 8) & 0xf, m = (code >> 4) & 0xf, x = code & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return (fnmx[x])(fregs, regs, m, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) id_sys(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, u16 code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) int n = ((code >> 8) & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) unsigned long *reg = (code & 0x0010) ? &FPUL : &FPSCR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) switch (code & 0xf0ff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) case 0x005a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) case 0x006a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) Rn = *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) case 0x405a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) case 0x406a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) *reg = Rn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) case 0x4052:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) case 0x4062:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) Rn -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) WRITE(*reg, Rn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) case 0x4056:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) case 0x4066:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) READ(*reg, Rn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) Rn += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) static int fpu_emulate(u16 code, struct sh_fpu_soft_struct *fregs, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if ((code & 0xf000) == 0xf000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return id_fnmx(fregs, regs, code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return id_sys(fregs, regs, code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * fpu_init - Initialize FPU registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * @fpu: Pointer to software emulated FPU registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) static void fpu_init(struct sh_fpu_soft_struct *fpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) fpu->fpscr = FPSCR_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) fpu->fpul = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) for (i = 0; i < 16; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) fpu->fp_regs[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) fpu->xfp_regs[i]= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) * do_fpu_inst - Handle reserved instructions for FPU emulation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * @inst: instruction code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * @regs: registers on stack.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) int do_fpu_inst(unsigned short inst, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) struct task_struct *tsk = current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) struct sh_fpu_soft_struct *fpu = &(tsk->thread.xstate->softfpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (!(task_thread_info(tsk)->status & TS_USEDFPU)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) /* initialize once. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) fpu_init(fpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) task_thread_info(tsk)->status |= TS_USEDFPU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return fpu_emulate(inst, fpu, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }