^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) // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <abi/reg_ops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #define MTCR_MASK 0xFC00FFE0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #define MFCR_MASK 0xFC00FFE0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #define MTCR_DIST 0xC0006420
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define MFCR_DIST 0xC0006020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * fpu_libc_helper() is to help libc to excute:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * - mfcr %a, cr<1, 2>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * - mfcr %a, cr<2, 2>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * - mtcr %a, cr<1, 2>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * - mtcr %a, cr<2, 2>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) int fpu_libc_helper(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) int fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) unsigned long instrptr, regx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) unsigned long index = 0, tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) unsigned long tinstr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) u16 instr_hi, instr_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) instrptr = instruction_pointer(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) if (instrptr & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) fault = __get_user(instr_low, (u16 *)instrptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (fault)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) fault = __get_user(instr_hi, (u16 *)(instrptr + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (fault)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) tinstr = instr_hi | ((unsigned long)instr_low << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (((tinstr >> 21) & 0x1F) != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if ((tinstr & MTCR_MASK) == MTCR_DIST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) index = (tinstr >> 16) & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (index > 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) tmp = tinstr & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (tmp > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) regx = *(®s->a0 + index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (tmp == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) mtcr("cr<1, 2>", regx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) else if (tmp == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) mtcr("cr<2, 2>", regx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) regs->pc += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if ((tinstr & MFCR_MASK) == MFCR_DIST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) index = tinstr & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (index > 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) tmp = ((tinstr >> 16) & 0x1F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (tmp > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (tmp == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) regx = mfcr("cr<1, 2>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) else if (tmp == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) regx = mfcr("cr<2, 2>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) *(®s->a0 + index) = regx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) regs->pc += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return 1;
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) void fpu_fpe(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int sig, code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned int fesr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) fesr = mfcr("cr<2, 2>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) sig = SIGFPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) code = FPE_FLTUNK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (fesr & FPE_ILLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) sig = SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) code = ILL_ILLOPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) } else if (fesr & FPE_IDC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) sig = SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) code = ILL_ILLOPN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) } else if (fesr & FPE_FEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) sig = SIGFPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (fesr & FPE_IOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) code = FPE_FLTINV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) else if (fesr & FPE_DZC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) code = FPE_FLTDIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) else if (fesr & FPE_UFC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) code = FPE_FLTUND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) else if (fesr & FPE_OFC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) code = FPE_FLTOVF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) else if (fesr & FPE_IXC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) code = FPE_FLTRES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) force_sig_fault(sig, code, (void __user *)regs->pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define FMFVR_FPU_REGS(vrx, vry) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) "fmfvrl %0, "#vrx"\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) "fmfvrh %1, "#vrx"\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) "fmfvrl %2, "#vry"\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) "fmfvrh %3, "#vry"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define FMTVR_FPU_REGS(vrx, vry) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) "fmtvrl "#vrx", %0\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) "fmtvrh "#vrx", %1\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) "fmtvrl "#vry", %2\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) "fmtvrh "#vry", %3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define STW_FPU_REGS(a, b, c, d) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) "stw %0, (%4, "#a")\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) "stw %1, (%4, "#b")\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) "stw %2, (%4, "#c")\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) "stw %3, (%4, "#d")\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define LDW_FPU_REGS(a, b, c, d) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) "ldw %0, (%4, "#a")\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) "ldw %1, (%4, "#b")\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) "ldw %2, (%4, "#c")\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) "ldw %3, (%4, "#d")\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) void save_to_user_fp(struct user_fp *user_fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) unsigned long flg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) unsigned long tmp1, tmp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) unsigned long *fpregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) local_irq_save(flg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) tmp1 = mfcr("cr<1, 2>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) tmp2 = mfcr("cr<2, 2>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) user_fp->fcr = tmp1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) user_fp->fesr = tmp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) fpregs = &user_fp->vr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #ifdef CONFIG_CPU_HAS_FPUV2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #ifdef CONFIG_CPU_HAS_VDSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) "vstmu.32 vr0-vr3, (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) "vstmu.32 vr4-vr7, (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) "vstmu.32 vr8-vr11, (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) "vstmu.32 vr12-vr15, (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) "fstmu.64 vr16-vr31, (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) : "+a"(fpregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) ::"memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) "fstmu.64 vr0-vr31, (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) : "+a"(fpregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) ::"memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) unsigned long tmp3, tmp4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) FMFVR_FPU_REGS(vr0, vr1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) STW_FPU_REGS(0, 4, 16, 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) FMFVR_FPU_REGS(vr2, vr3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) STW_FPU_REGS(32, 36, 48, 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) FMFVR_FPU_REGS(vr4, vr5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) STW_FPU_REGS(64, 68, 80, 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) FMFVR_FPU_REGS(vr6, vr7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) STW_FPU_REGS(96, 100, 112, 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) "addi %4, 128\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) FMFVR_FPU_REGS(vr8, vr9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) STW_FPU_REGS(0, 4, 16, 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) FMFVR_FPU_REGS(vr10, vr11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) STW_FPU_REGS(32, 36, 48, 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) FMFVR_FPU_REGS(vr12, vr13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) STW_FPU_REGS(64, 68, 80, 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) FMFVR_FPU_REGS(vr14, vr15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) STW_FPU_REGS(96, 100, 112, 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) : "=a"(tmp1), "=a"(tmp2), "=a"(tmp3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) "=a"(tmp4), "+a"(fpregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) ::"memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) local_irq_restore(flg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) void restore_from_user_fp(struct user_fp *user_fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) unsigned long flg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) unsigned long tmp1, tmp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) unsigned long *fpregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) local_irq_save(flg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) tmp1 = user_fp->fcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) tmp2 = user_fp->fesr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) mtcr("cr<1, 2>", tmp1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) mtcr("cr<2, 2>", tmp2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) fpregs = &user_fp->vr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) #ifdef CONFIG_CPU_HAS_FPUV2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) #ifdef CONFIG_CPU_HAS_VDSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) "vldmu.32 vr0-vr3, (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) "vldmu.32 vr4-vr7, (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) "vldmu.32 vr8-vr11, (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) "vldmu.32 vr12-vr15, (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) "fldmu.64 vr16-vr31, (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) : "+a"(fpregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) ::"memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) "fldmu.64 vr0-vr31, (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) : "+a"(fpregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ::"memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) unsigned long tmp3, tmp4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) LDW_FPU_REGS(0, 4, 16, 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) FMTVR_FPU_REGS(vr0, vr1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) LDW_FPU_REGS(32, 36, 48, 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) FMTVR_FPU_REGS(vr2, vr3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) LDW_FPU_REGS(64, 68, 80, 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) FMTVR_FPU_REGS(vr4, vr5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) LDW_FPU_REGS(96, 100, 112, 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) FMTVR_FPU_REGS(vr6, vr7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) "addi %4, 128\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) LDW_FPU_REGS(0, 4, 16, 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) FMTVR_FPU_REGS(vr8, vr9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) LDW_FPU_REGS(32, 36, 48, 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) FMTVR_FPU_REGS(vr10, vr11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) LDW_FPU_REGS(64, 68, 80, 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) FMTVR_FPU_REGS(vr12, vr13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) LDW_FPU_REGS(96, 100, 112, 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) FMTVR_FPU_REGS(vr14, vr15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) : "=a"(tmp1), "=a"(tmp2), "=a"(tmp3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) "=a"(tmp4), "+a"(fpregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) ::"memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) local_irq_restore(flg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }