nds32 patches for 5.2-rc3
Here is the nds32 patchset based on 5.2-rc1 Contained in here are 1. fix warning for math-emu 2. fix nds32 fpu exception handling 3. fix nds32 fpu emulation implementation -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.17 (GNU/Linux) iQIcBAABAgAGBQJc9SRzAAoJEHfB0l0b2JxETZwQAJFERZU5ziU/UU5g4W8P2fn8 KAS3bxqWk6mJ8qptSsvdggfXsJjCqxb+6Qhc9cAWQBiasfp6a6HR9zWFyAwOP7qo y0SydlRv/tMwhImpkF63Pp9omDfFVH0xpWSGIIF/PM7Uy2GrV9pmeTFX9R7Om4qV qdxGVPu2fe/aNP4W3/Typ2YttmWMAN5MJjTaig8hnsWQQGfVNuPZJNTAyt/iCmS/ /XwxCRWpE4WIlYkcBV1LqhYRQ7xPN/IdnkD4EY4zPsDOq1+bgQQmGh8ekoiaITgB zSj1btl6FBcyeItFv/idaGxPjxmlN87Misix1P069pXOKVfbwB/HncZZJ3/msYFk tHbVMoVIsJ09kFiHUgXb9sjttf4o1xl8FM3uH32HEEJBOS4OPxbEhTbXRUECEDww xvrV6M0rKCp/Mbxvp3PmAJp75hY6/wE7Ygu7Enf9+OQBx1H6yAph25z9T2J7AoDl 5rCGwaHw0SUHyz8GeE6vvcQ0JPRRGv59tVJEYKZmttoNlS6JebYDQJ7WPm1Rkp+V BmLv6SYeAJGdO1nhS7tMPUUWVD7cerRvz8VTmiMOSgbd/lwAR+4KIIMdi3cvaD9m TTyHcyxUNXwa7ox2OFvFXlvIEzqBiilzNgP89DKCAI7osvUuOviqRlgBNOvN0KxR ip/vG/xwDKXg1XVCaKdC =kAV3 -----END PGP SIGNATURE----- Merge tag 'nds32-for-linux-5.2-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/greentime/linux Pull nds32 fixes from Greentime Hu: - fix warning for math-emu - fix nds32 fpu exception handling - fix nds32 fpu emulation implementation * tag 'nds32-for-linux-5.2-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/greentime/linux: nds32: add new emulations for floating point instruction nds32: Avoid IEX status being incorrectly modified math-emu: Use statement expressions to fix Wshift-count-overflow warning
This commit is contained in:
commit
30d1d92a88
|
@ -937,7 +937,7 @@
|
||||||
#define FPCSR_mskDNIT ( 0x1 << FPCSR_offDNIT )
|
#define FPCSR_mskDNIT ( 0x1 << FPCSR_offDNIT )
|
||||||
#define FPCSR_mskRIT ( 0x1 << FPCSR_offRIT )
|
#define FPCSR_mskRIT ( 0x1 << FPCSR_offRIT )
|
||||||
#define FPCSR_mskALL (FPCSR_mskIVO | FPCSR_mskDBZ | FPCSR_mskOVF | FPCSR_mskUDF | FPCSR_mskIEX)
|
#define FPCSR_mskALL (FPCSR_mskIVO | FPCSR_mskDBZ | FPCSR_mskOVF | FPCSR_mskUDF | FPCSR_mskIEX)
|
||||||
#define FPCSR_mskALLE_NO_UDFE (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE | FPCSR_mskIEXE)
|
#define FPCSR_mskALLE_NO_UDF_IEXE (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE)
|
||||||
#define FPCSR_mskALLE (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE | FPCSR_mskUDFE | FPCSR_mskIEXE)
|
#define FPCSR_mskALLE (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE | FPCSR_mskUDFE | FPCSR_mskIEXE)
|
||||||
#define FPCSR_mskALLT (FPCSR_mskIVOT | FPCSR_mskDBZT | FPCSR_mskOVFT | FPCSR_mskUDFT | FPCSR_mskIEXT |FPCSR_mskDNIT | FPCSR_mskRIT)
|
#define FPCSR_mskALLT (FPCSR_mskIVOT | FPCSR_mskDBZT | FPCSR_mskOVFT | FPCSR_mskUDFT | FPCSR_mskIEXT |FPCSR_mskDNIT | FPCSR_mskRIT)
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ extern int do_fpuemu(struct pt_regs *regs, struct fpu_struct *fpu);
|
||||||
* enabled by default and kerenl will re-execute it by fpu emulator
|
* enabled by default and kerenl will re-execute it by fpu emulator
|
||||||
* when getting underflow exception.
|
* when getting underflow exception.
|
||||||
*/
|
*/
|
||||||
#define FPCSR_INIT FPCSR_mskUDFE
|
#define FPCSR_INIT (FPCSR_mskUDFE | FPCSR_mskIEXE)
|
||||||
#else
|
#else
|
||||||
#define FPCSR_INIT 0x0UL
|
#define FPCSR_INIT 0x0UL
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,6 +13,12 @@ void fsubs(void *ft, void *fa, void *fb);
|
||||||
void fmuls(void *ft, void *fa, void *fb);
|
void fmuls(void *ft, void *fa, void *fb);
|
||||||
void fdivs(void *ft, void *fa, void *fb);
|
void fdivs(void *ft, void *fa, void *fb);
|
||||||
void fs2d(void *ft, void *fa);
|
void fs2d(void *ft, void *fa);
|
||||||
|
void fs2si(void *ft, void *fa);
|
||||||
|
void fs2si_z(void *ft, void *fa);
|
||||||
|
void fs2ui(void *ft, void *fa);
|
||||||
|
void fs2ui_z(void *ft, void *fa);
|
||||||
|
void fsi2s(void *ft, void *fa);
|
||||||
|
void fui2s(void *ft, void *fa);
|
||||||
void fsqrts(void *ft, void *fa);
|
void fsqrts(void *ft, void *fa);
|
||||||
void fnegs(void *ft, void *fa);
|
void fnegs(void *ft, void *fa);
|
||||||
int fcmps(void *ft, void *fa, void *fb, int cop);
|
int fcmps(void *ft, void *fa, void *fb, int cop);
|
||||||
|
@ -26,6 +32,12 @@ void fmuld(void *ft, void *fa, void *fb);
|
||||||
void fdivd(void *ft, void *fa, void *fb);
|
void fdivd(void *ft, void *fa, void *fb);
|
||||||
void fsqrtd(void *ft, void *fa);
|
void fsqrtd(void *ft, void *fa);
|
||||||
void fd2s(void *ft, void *fa);
|
void fd2s(void *ft, void *fa);
|
||||||
|
void fd2si(void *ft, void *fa);
|
||||||
|
void fd2si_z(void *ft, void *fa);
|
||||||
|
void fd2ui(void *ft, void *fa);
|
||||||
|
void fd2ui_z(void *ft, void *fa);
|
||||||
|
void fsi2d(void *ft, void *fa);
|
||||||
|
void fui2d(void *ft, void *fa);
|
||||||
void fnegd(void *ft, void *fa);
|
void fnegd(void *ft, void *fa);
|
||||||
int fcmpd(void *ft, void *fa, void *fb, int cop);
|
int fcmpd(void *ft, void *fa, void *fb, int cop);
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
asmlinkage long sys_cacheflush(unsigned long addr, unsigned long len, unsigned int op);
|
asmlinkage long sys_cacheflush(unsigned long addr, unsigned long len, unsigned int op);
|
||||||
asmlinkage long sys_fadvise64_64_wrapper(int fd, int advice, loff_t offset, loff_t len);
|
asmlinkage long sys_fadvise64_64_wrapper(int fd, int advice, loff_t offset, loff_t len);
|
||||||
asmlinkage long sys_rt_sigreturn_wrapper(void);
|
asmlinkage long sys_rt_sigreturn_wrapper(void);
|
||||||
asmlinkage long sys_udftrap(int option);
|
asmlinkage long sys_fp_udfiex_crtl(int cmd, int act);
|
||||||
|
|
||||||
#include <asm-generic/syscalls.h>
|
#include <asm-generic/syscalls.h>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright (C) 2005-2019 Andes Technology Corporation */
|
||||||
|
#ifndef _FP_UDF_IEX_CRTL_H
|
||||||
|
#define _FP_UDF_IEX_CRTL_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The cmd list of sys_fp_udfiex_crtl()
|
||||||
|
*/
|
||||||
|
/* Disable UDF or IEX trap based on the content of parameter act */
|
||||||
|
#define DISABLE_UDF_IEX_TRAP 0
|
||||||
|
/* Enable UDF or IEX trap based on the content of parameter act */
|
||||||
|
#define ENABLE_UDF_IEX_TRAP 1
|
||||||
|
/* Get current status of UDF and IEX trap */
|
||||||
|
#define GET_UDF_IEX_TRAP 2
|
||||||
|
|
||||||
|
#endif /* _FP_UDF_IEX_CRTL_H */
|
|
@ -13,14 +13,24 @@ struct fpu_struct {
|
||||||
unsigned long long fd_regs[32];
|
unsigned long long fd_regs[32];
|
||||||
unsigned long fpcsr;
|
unsigned long fpcsr;
|
||||||
/*
|
/*
|
||||||
* UDF_trap is used to recognize whether underflow trap is enabled
|
* When CONFIG_SUPPORT_DENORMAL_ARITHMETIC is defined, kernel prevents
|
||||||
* or not. When UDF_trap == 1, this process will be traped and then
|
* hardware from treating the denormalized output as an underflow case
|
||||||
* get a SIGFPE signal when encountering an underflow exception.
|
* and rounding it to a normal number. Hence kernel enables the UDF and
|
||||||
* UDF_trap is only modified through setfputrap syscall. Therefore,
|
* IEX trap in the fpcsr register to step in the calculation.
|
||||||
* UDF_trap needn't be saved or loaded to context in each context
|
* However, the UDF and IEX trap enable bit in $fpcsr also lose
|
||||||
* switch.
|
* their use.
|
||||||
|
*
|
||||||
|
* UDF_IEX_trap replaces the feature of UDF and IEX trap enable bit in
|
||||||
|
* $fpcsr to control the trap of underflow and inexact. The bit filed
|
||||||
|
* of UDF_IEX_trap is the same as $fpcsr, 10th bit is used to enable UDF
|
||||||
|
* exception trapping and 11th bit is used to enable IEX exception
|
||||||
|
* trapping.
|
||||||
|
*
|
||||||
|
* UDF_IEX_trap is only modified through fp_udfiex_crtl syscall.
|
||||||
|
* Therefore, UDF_IEX_trap needn't be saved and restored in each
|
||||||
|
* context switch.
|
||||||
*/
|
*/
|
||||||
unsigned long UDF_trap;
|
unsigned long UDF_IEX_trap;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct zol_struct {
|
struct zol_struct {
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
|
||||||
/* Copyright (C) 2005-2018 Andes Technology Corporation */
|
|
||||||
#ifndef _ASM_SETFPUTRAP
|
|
||||||
#define _ASM_SETFPUTRAP
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Options for setfputrap system call
|
|
||||||
*/
|
|
||||||
#define DISABLE_UDFTRAP 0 /* disable underflow exception trap */
|
|
||||||
#define ENABLE_UDFTRAP 1 /* enable undeflos exception trap */
|
|
||||||
#define GET_UDFTRAP 2 /* only get undeflos exception trap status */
|
|
||||||
|
|
||||||
#endif /* _ASM_CACHECTL */
|
|
|
@ -11,6 +11,6 @@
|
||||||
|
|
||||||
/* Additional NDS32 specific syscalls. */
|
/* Additional NDS32 specific syscalls. */
|
||||||
#define __NR_cacheflush (__NR_arch_specific_syscall)
|
#define __NR_cacheflush (__NR_arch_specific_syscall)
|
||||||
#define __NR_udftrap (__NR_arch_specific_syscall + 1)
|
#define __NR_fp_udfiex_crtl (__NR_arch_specific_syscall + 1)
|
||||||
__SYSCALL(__NR_cacheflush, sys_cacheflush)
|
__SYSCALL(__NR_cacheflush, sys_cacheflush)
|
||||||
__SYSCALL(__NR_udftrap, sys_udftrap)
|
__SYSCALL(__NR_fp_udfiex_crtl, sys_fp_udfiex_crtl)
|
||||||
|
|
|
@ -14,7 +14,7 @@ const struct fpu_struct init_fpuregs = {
|
||||||
.fd_regs = {[0 ... 31] = sNAN64},
|
.fd_regs = {[0 ... 31] = sNAN64},
|
||||||
.fpcsr = FPCSR_INIT,
|
.fpcsr = FPCSR_INIT,
|
||||||
#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
|
#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
|
||||||
.UDF_trap = 0
|
.UDF_IEX_trap = 0
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ inline void do_fpu_context_switch(struct pt_regs *regs)
|
||||||
/* First time FPU user. */
|
/* First time FPU user. */
|
||||||
load_fpu(&init_fpuregs);
|
load_fpu(&init_fpuregs);
|
||||||
#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
|
#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
|
||||||
current->thread.fpu.UDF_trap = init_fpuregs.UDF_trap;
|
current->thread.fpu.UDF_IEX_trap = init_fpuregs.UDF_IEX_trap;
|
||||||
#endif
|
#endif
|
||||||
set_used_math();
|
set_used_math();
|
||||||
}
|
}
|
||||||
|
@ -206,7 +206,7 @@ inline void handle_fpu_exception(struct pt_regs *regs)
|
||||||
unsigned int fpcsr;
|
unsigned int fpcsr;
|
||||||
int si_code = 0, si_signo = SIGFPE;
|
int si_code = 0, si_signo = SIGFPE;
|
||||||
#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
|
#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
|
||||||
unsigned long redo_except = FPCSR_mskDNIT|FPCSR_mskUDFT;
|
unsigned long redo_except = FPCSR_mskDNIT|FPCSR_mskUDFT|FPCSR_mskIEXT;
|
||||||
#else
|
#else
|
||||||
unsigned long redo_except = FPCSR_mskDNIT;
|
unsigned long redo_except = FPCSR_mskDNIT;
|
||||||
#endif
|
#endif
|
||||||
|
@ -215,21 +215,18 @@ inline void handle_fpu_exception(struct pt_regs *regs)
|
||||||
fpcsr = current->thread.fpu.fpcsr;
|
fpcsr = current->thread.fpu.fpcsr;
|
||||||
|
|
||||||
if (fpcsr & redo_except) {
|
if (fpcsr & redo_except) {
|
||||||
#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
|
|
||||||
if (fpcsr & FPCSR_mskUDFT)
|
|
||||||
current->thread.fpu.fpcsr &= ~FPCSR_mskIEX;
|
|
||||||
#endif
|
|
||||||
si_signo = do_fpuemu(regs, ¤t->thread.fpu);
|
si_signo = do_fpuemu(regs, ¤t->thread.fpu);
|
||||||
fpcsr = current->thread.fpu.fpcsr;
|
fpcsr = current->thread.fpu.fpcsr;
|
||||||
if (!si_signo)
|
if (!si_signo) {
|
||||||
|
current->thread.fpu.fpcsr &= ~(redo_except);
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
} else if (fpcsr & FPCSR_mskRIT) {
|
} else if (fpcsr & FPCSR_mskRIT) {
|
||||||
if (!user_mode(regs))
|
if (!user_mode(regs))
|
||||||
do_exit(SIGILL);
|
do_exit(SIGILL);
|
||||||
si_signo = SIGILL;
|
si_signo = SIGILL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
switch (si_signo) {
|
switch (si_signo) {
|
||||||
case SIGFPE:
|
case SIGFPE:
|
||||||
fill_sigfpe_signo(fpcsr, &si_code);
|
fill_sigfpe_signo(fpcsr, &si_code);
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
|
|
||||||
#include <asm/cachectl.h>
|
#include <asm/cachectl.h>
|
||||||
#include <asm/proc-fns.h>
|
#include <asm/proc-fns.h>
|
||||||
#include <asm/udftrap.h>
|
|
||||||
#include <asm/fpu.h>
|
#include <asm/fpu.h>
|
||||||
|
#include <asm/fp_udfiex_crtl.h>
|
||||||
|
|
||||||
SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
|
SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
|
||||||
unsigned long, prot, unsigned long, flags,
|
unsigned long, prot, unsigned long, flags,
|
||||||
|
@ -51,31 +51,33 @@ SYSCALL_DEFINE3(cacheflush, unsigned int, start, unsigned int, end, int, cache)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE1(udftrap, int, option)
|
SYSCALL_DEFINE2(fp_udfiex_crtl, unsigned int, cmd, unsigned int, act)
|
||||||
{
|
{
|
||||||
#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
|
#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
|
||||||
int old_udftrap;
|
int old_udf_iex;
|
||||||
|
|
||||||
if (!used_math()) {
|
if (!used_math()) {
|
||||||
load_fpu(&init_fpuregs);
|
load_fpu(&init_fpuregs);
|
||||||
current->thread.fpu.UDF_trap = init_fpuregs.UDF_trap;
|
current->thread.fpu.UDF_IEX_trap = init_fpuregs.UDF_IEX_trap;
|
||||||
set_used_math();
|
set_used_math();
|
||||||
}
|
}
|
||||||
|
|
||||||
old_udftrap = current->thread.fpu.UDF_trap;
|
old_udf_iex = current->thread.fpu.UDF_IEX_trap;
|
||||||
switch (option) {
|
act &= (FPCSR_mskUDFE | FPCSR_mskIEXE);
|
||||||
case DISABLE_UDFTRAP:
|
|
||||||
current->thread.fpu.UDF_trap = 0;
|
switch (cmd) {
|
||||||
|
case DISABLE_UDF_IEX_TRAP:
|
||||||
|
current->thread.fpu.UDF_IEX_trap &= ~act;
|
||||||
break;
|
break;
|
||||||
case ENABLE_UDFTRAP:
|
case ENABLE_UDF_IEX_TRAP:
|
||||||
current->thread.fpu.UDF_trap = FPCSR_mskUDFE;
|
current->thread.fpu.UDF_IEX_trap |= act;
|
||||||
break;
|
break;
|
||||||
case GET_UDFTRAP:
|
case GET_UDF_IEX_TRAP:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
return old_udftrap;
|
return old_udf_iex;
|
||||||
#else
|
#else
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,4 +5,6 @@
|
||||||
|
|
||||||
obj-y := fpuemu.o \
|
obj-y := fpuemu.o \
|
||||||
fdivd.o fmuld.o fsubd.o faddd.o fs2d.o fsqrtd.o fcmpd.o fnegs.o \
|
fdivd.o fmuld.o fsubd.o faddd.o fs2d.o fsqrtd.o fcmpd.o fnegs.o \
|
||||||
fdivs.o fmuls.o fsubs.o fadds.o fd2s.o fsqrts.o fcmps.o fnegd.o
|
fd2si.o fd2ui.o fd2siz.o fd2uiz.o fsi2d.o fui2d.o \
|
||||||
|
fdivs.o fmuls.o fsubs.o fadds.o fd2s.o fsqrts.o fcmps.o fnegd.o \
|
||||||
|
fs2si.o fs2ui.o fs2siz.o fs2uiz.o fsi2s.o fui2s.o
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
// Copyright (C) 2005-2019 Andes Technology Corporation
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#include <asm/sfp-machine.h>
|
||||||
|
#include <math-emu/soft-fp.h>
|
||||||
|
#include <math-emu/double.h>
|
||||||
|
|
||||||
|
void fd2si(void *ft, void *fa)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
FP_DECL_D(A);
|
||||||
|
FP_DECL_EX;
|
||||||
|
|
||||||
|
FP_UNPACK_DP(A, fa);
|
||||||
|
|
||||||
|
if (A_c == FP_CLS_INF) {
|
||||||
|
*(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000;
|
||||||
|
__FPU_FPCSR |= FP_EX_INVALID;
|
||||||
|
} else if (A_c == FP_CLS_NAN) {
|
||||||
|
*(int *)ft = 0xffffffff;
|
||||||
|
__FPU_FPCSR |= FP_EX_INVALID;
|
||||||
|
} else {
|
||||||
|
FP_TO_INT_ROUND_D(r, A, 32, 1);
|
||||||
|
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
|
||||||
|
*(int *)ft = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
// Copyright (C) 2005-2019 Andes Technology Corporation
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#include <asm/sfp-machine.h>
|
||||||
|
#include <math-emu/soft-fp.h>
|
||||||
|
#include <math-emu/double.h>
|
||||||
|
|
||||||
|
void fd2si_z(void *ft, void *fa)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
FP_DECL_D(A);
|
||||||
|
FP_DECL_EX;
|
||||||
|
|
||||||
|
FP_UNPACK_DP(A, fa);
|
||||||
|
|
||||||
|
if (A_c == FP_CLS_INF) {
|
||||||
|
*(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000;
|
||||||
|
__FPU_FPCSR |= FP_EX_INVALID;
|
||||||
|
} else if (A_c == FP_CLS_NAN) {
|
||||||
|
*(int *)ft = 0xffffffff;
|
||||||
|
__FPU_FPCSR |= FP_EX_INVALID;
|
||||||
|
} else {
|
||||||
|
FP_TO_INT_D(r, A, 32, 1);
|
||||||
|
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
|
||||||
|
*(int *)ft = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
// Copyright (C) 2005-2019 Andes Technology Corporation
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#include <asm/sfp-machine.h>
|
||||||
|
#include <math-emu/soft-fp.h>
|
||||||
|
#include <math-emu/double.h>
|
||||||
|
|
||||||
|
void fd2ui(void *ft, void *fa)
|
||||||
|
{
|
||||||
|
unsigned int r;
|
||||||
|
|
||||||
|
FP_DECL_D(A);
|
||||||
|
FP_DECL_EX;
|
||||||
|
|
||||||
|
FP_UNPACK_DP(A, fa);
|
||||||
|
|
||||||
|
if (A_c == FP_CLS_INF) {
|
||||||
|
*(unsigned int *)ft = (A_s == 0) ? 0xffffffff : 0x00000000;
|
||||||
|
__FPU_FPCSR |= FP_EX_INVALID;
|
||||||
|
} else if (A_c == FP_CLS_NAN) {
|
||||||
|
*(unsigned int *)ft = 0xffffffff;
|
||||||
|
__FPU_FPCSR |= FP_EX_INVALID;
|
||||||
|
} else {
|
||||||
|
FP_TO_INT_ROUND_D(r, A, 32, 0);
|
||||||
|
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
|
||||||
|
*(unsigned int *)ft = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
// Copyright (C) 2005-2019 Andes Technology Corporation
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#include <asm/sfp-machine.h>
|
||||||
|
#include <math-emu/soft-fp.h>
|
||||||
|
#include <math-emu/double.h>
|
||||||
|
|
||||||
|
void fd2ui_z(void *ft, void *fa)
|
||||||
|
{
|
||||||
|
unsigned int r;
|
||||||
|
|
||||||
|
FP_DECL_D(A);
|
||||||
|
FP_DECL_EX;
|
||||||
|
|
||||||
|
FP_UNPACK_DP(A, fa);
|
||||||
|
|
||||||
|
if (A_c == FP_CLS_INF) {
|
||||||
|
*(unsigned int *)ft = (A_s == 0) ? 0xffffffff : 0x00000000;
|
||||||
|
__FPU_FPCSR |= FP_EX_INVALID;
|
||||||
|
} else if (A_c == FP_CLS_NAN) {
|
||||||
|
*(unsigned int *)ft = 0xffffffff;
|
||||||
|
__FPU_FPCSR |= FP_EX_INVALID;
|
||||||
|
} else {
|
||||||
|
FP_TO_INT_D(r, A, 32, 0);
|
||||||
|
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
|
||||||
|
*(unsigned int *)ft = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -113,6 +113,30 @@ static int fpu_emu(struct fpu_struct *fpu_reg, unsigned long insn)
|
||||||
func.b = fs2d;
|
func.b = fs2d;
|
||||||
ftype = S1D;
|
ftype = S1D;
|
||||||
break;
|
break;
|
||||||
|
case fs2si_op:
|
||||||
|
func.b = fs2si;
|
||||||
|
ftype = S1S;
|
||||||
|
break;
|
||||||
|
case fs2si_z_op:
|
||||||
|
func.b = fs2si_z;
|
||||||
|
ftype = S1S;
|
||||||
|
break;
|
||||||
|
case fs2ui_op:
|
||||||
|
func.b = fs2ui;
|
||||||
|
ftype = S1S;
|
||||||
|
break;
|
||||||
|
case fs2ui_z_op:
|
||||||
|
func.b = fs2ui_z;
|
||||||
|
ftype = S1S;
|
||||||
|
break;
|
||||||
|
case fsi2s_op:
|
||||||
|
func.b = fsi2s;
|
||||||
|
ftype = S1S;
|
||||||
|
break;
|
||||||
|
case fui2s_op:
|
||||||
|
func.b = fui2s;
|
||||||
|
ftype = S1S;
|
||||||
|
break;
|
||||||
case fsqrts_op:
|
case fsqrts_op:
|
||||||
func.b = fsqrts;
|
func.b = fsqrts;
|
||||||
ftype = S1S;
|
ftype = S1S;
|
||||||
|
@ -182,6 +206,30 @@ static int fpu_emu(struct fpu_struct *fpu_reg, unsigned long insn)
|
||||||
func.b = fd2s;
|
func.b = fd2s;
|
||||||
ftype = D1S;
|
ftype = D1S;
|
||||||
break;
|
break;
|
||||||
|
case fd2si_op:
|
||||||
|
func.b = fd2si;
|
||||||
|
ftype = D1S;
|
||||||
|
break;
|
||||||
|
case fd2si_z_op:
|
||||||
|
func.b = fd2si_z;
|
||||||
|
ftype = D1S;
|
||||||
|
break;
|
||||||
|
case fd2ui_op:
|
||||||
|
func.b = fd2ui;
|
||||||
|
ftype = D1S;
|
||||||
|
break;
|
||||||
|
case fd2ui_z_op:
|
||||||
|
func.b = fd2ui_z;
|
||||||
|
ftype = D1S;
|
||||||
|
break;
|
||||||
|
case fsi2d_op:
|
||||||
|
func.b = fsi2d;
|
||||||
|
ftype = D1S;
|
||||||
|
break;
|
||||||
|
case fui2d_op:
|
||||||
|
func.b = fui2d;
|
||||||
|
ftype = D1S;
|
||||||
|
break;
|
||||||
case fsqrtd_op:
|
case fsqrtd_op:
|
||||||
func.b = fsqrtd;
|
func.b = fsqrtd;
|
||||||
ftype = D1D;
|
ftype = D1D;
|
||||||
|
@ -305,16 +353,16 @@ static int fpu_emu(struct fpu_struct *fpu_reg, unsigned long insn)
|
||||||
* If an exception is required, generate a tidy SIGFPE exception.
|
* If an exception is required, generate a tidy SIGFPE exception.
|
||||||
*/
|
*/
|
||||||
#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
|
#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
|
||||||
if (((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE_NO_UDFE) ||
|
if (((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE_NO_UDF_IEXE)
|
||||||
((fpu_reg->fpcsr & FPCSR_mskUDF) && (fpu_reg->UDF_trap)))
|
|| ((fpu_reg->fpcsr << 5) & (fpu_reg->UDF_IEX_trap))) {
|
||||||
#else
|
#else
|
||||||
if ((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE)
|
if ((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE) {
|
||||||
#endif
|
#endif
|
||||||
return SIGFPE;
|
return SIGFPE;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int do_fpuemu(struct pt_regs *regs, struct fpu_struct *fpu)
|
int do_fpuemu(struct pt_regs *regs, struct fpu_struct *fpu)
|
||||||
{
|
{
|
||||||
unsigned long insn = 0, addr = regs->ipc;
|
unsigned long insn = 0, addr = regs->ipc;
|
||||||
|
@ -336,6 +384,7 @@ int do_fpuemu(struct pt_regs *regs, struct fpu_struct *fpu)
|
||||||
|
|
||||||
if (NDS32Insn_OPCODE(insn) != cop0_op)
|
if (NDS32Insn_OPCODE(insn) != cop0_op)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
switch (NDS32Insn_OPCODE_COP0(insn)) {
|
switch (NDS32Insn_OPCODE_COP0(insn)) {
|
||||||
case fs1_op:
|
case fs1_op:
|
||||||
case fs2_op:
|
case fs2_op:
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
// Copyright (C) 2005-2019 Andes Technology Corporation
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#include <asm/sfp-machine.h>
|
||||||
|
#include <math-emu/soft-fp.h>
|
||||||
|
#include <math-emu/single.h>
|
||||||
|
|
||||||
|
void fs2si(void *ft, void *fa)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
FP_DECL_S(A);
|
||||||
|
FP_DECL_EX;
|
||||||
|
|
||||||
|
FP_UNPACK_SP(A, fa);
|
||||||
|
|
||||||
|
if (A_c == FP_CLS_INF) {
|
||||||
|
*(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000;
|
||||||
|
__FPU_FPCSR |= FP_EX_INVALID;
|
||||||
|
} else if (A_c == FP_CLS_NAN) {
|
||||||
|
*(int *)ft = 0xffffffff;
|
||||||
|
__FPU_FPCSR |= FP_EX_INVALID;
|
||||||
|
} else {
|
||||||
|
FP_TO_INT_ROUND_S(r, A, 32, 1);
|
||||||
|
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
|
||||||
|
*(int *)ft = r;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
// Copyright (C) 2005-2019 Andes Technology Corporation
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#include <asm/sfp-machine.h>
|
||||||
|
#include <math-emu/soft-fp.h>
|
||||||
|
#include <math-emu/single.h>
|
||||||
|
|
||||||
|
void fs2si_z(void *ft, void *fa)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
FP_DECL_S(A);
|
||||||
|
FP_DECL_EX;
|
||||||
|
|
||||||
|
FP_UNPACK_SP(A, fa);
|
||||||
|
|
||||||
|
if (A_c == FP_CLS_INF) {
|
||||||
|
*(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000;
|
||||||
|
__FPU_FPCSR |= FP_EX_INVALID;
|
||||||
|
} else if (A_c == FP_CLS_NAN) {
|
||||||
|
*(int *)ft = 0xffffffff;
|
||||||
|
__FPU_FPCSR |= FP_EX_INVALID;
|
||||||
|
} else {
|
||||||
|
FP_TO_INT_S(r, A, 32, 1);
|
||||||
|
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
|
||||||
|
*(int *)ft = r;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
// Copyright (C) 2005-2019 Andes Technology Corporation
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#include <asm/sfp-machine.h>
|
||||||
|
#include <math-emu/soft-fp.h>
|
||||||
|
#include <math-emu/single.h>
|
||||||
|
|
||||||
|
void fs2ui(void *ft, void *fa)
|
||||||
|
{
|
||||||
|
unsigned int r;
|
||||||
|
|
||||||
|
FP_DECL_S(A);
|
||||||
|
FP_DECL_EX;
|
||||||
|
|
||||||
|
FP_UNPACK_SP(A, fa);
|
||||||
|
|
||||||
|
if (A_c == FP_CLS_INF) {
|
||||||
|
*(unsigned int *)ft = (A_s == 0) ? 0xffffffff : 0x00000000;
|
||||||
|
__FPU_FPCSR |= FP_EX_INVALID;
|
||||||
|
} else if (A_c == FP_CLS_NAN) {
|
||||||
|
*(unsigned int *)ft = 0xffffffff;
|
||||||
|
__FPU_FPCSR |= FP_EX_INVALID;
|
||||||
|
} else {
|
||||||
|
FP_TO_INT_ROUND_S(r, A, 32, 0);
|
||||||
|
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
|
||||||
|
*(unsigned int *)ft = r;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
// Copyright (C) 2005-2019 Andes Technology Corporation
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#include <asm/sfp-machine.h>
|
||||||
|
#include <math-emu/soft-fp.h>
|
||||||
|
#include <math-emu/single.h>
|
||||||
|
|
||||||
|
void fs2ui_z(void *ft, void *fa)
|
||||||
|
{
|
||||||
|
unsigned int r;
|
||||||
|
|
||||||
|
FP_DECL_S(A);
|
||||||
|
FP_DECL_EX;
|
||||||
|
|
||||||
|
FP_UNPACK_SP(A, fa);
|
||||||
|
|
||||||
|
if (A_c == FP_CLS_INF) {
|
||||||
|
*(unsigned int *)ft = (A_s == 0) ? 0xffffffff : 0x00000000;
|
||||||
|
__FPU_FPCSR |= FP_EX_INVALID;
|
||||||
|
} else if (A_c == FP_CLS_NAN) {
|
||||||
|
*(unsigned int *)ft = 0xffffffff;
|
||||||
|
__FPU_FPCSR |= FP_EX_INVALID;
|
||||||
|
} else {
|
||||||
|
FP_TO_INT_S(r, A, 32, 0);
|
||||||
|
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
|
||||||
|
*(unsigned int *)ft = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
// Copyright (C) 2005-2019 Andes Technology Corporation
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#include <asm/sfp-machine.h>
|
||||||
|
#include <math-emu/soft-fp.h>
|
||||||
|
#include <math-emu/double.h>
|
||||||
|
|
||||||
|
void fsi2d(void *ft, void *fa)
|
||||||
|
{
|
||||||
|
int a = *(int *)fa;
|
||||||
|
|
||||||
|
FP_DECL_D(R);
|
||||||
|
FP_DECL_EX;
|
||||||
|
|
||||||
|
FP_FROM_INT_D(R, a, 32, int);
|
||||||
|
|
||||||
|
FP_PACK_DP(ft, R);
|
||||||
|
|
||||||
|
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
// Copyright (C) 2005-2019 Andes Technology Corporation
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#include <asm/sfp-machine.h>
|
||||||
|
#include <math-emu/soft-fp.h>
|
||||||
|
#include <math-emu/single.h>
|
||||||
|
|
||||||
|
void fsi2s(void *ft, void *fa)
|
||||||
|
{
|
||||||
|
int a = *(int *)fa;
|
||||||
|
|
||||||
|
FP_DECL_S(R);
|
||||||
|
FP_DECL_EX;
|
||||||
|
|
||||||
|
FP_FROM_INT_S(R, a, 32, int);
|
||||||
|
|
||||||
|
FP_PACK_SP(ft, R);
|
||||||
|
|
||||||
|
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
// Copyright (C) 2005-2019 Andes Technology Corporation
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#include <asm/sfp-machine.h>
|
||||||
|
#include <math-emu/soft-fp.h>
|
||||||
|
#include <math-emu/double.h>
|
||||||
|
|
||||||
|
void fui2d(void *ft, void *fa)
|
||||||
|
{
|
||||||
|
unsigned int a = *(unsigned int *)fa;
|
||||||
|
|
||||||
|
FP_DECL_D(R);
|
||||||
|
FP_DECL_EX;
|
||||||
|
|
||||||
|
FP_FROM_INT_D(R, a, 32, int);
|
||||||
|
|
||||||
|
FP_PACK_DP(ft, R);
|
||||||
|
|
||||||
|
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
// Copyright (C) 2005-2019 Andes Technology Corporation
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#include <asm/sfp-machine.h>
|
||||||
|
#include <math-emu/soft-fp.h>
|
||||||
|
#include <math-emu/single.h>
|
||||||
|
|
||||||
|
void fui2s(void *ft, void *fa)
|
||||||
|
{
|
||||||
|
unsigned int a = *(unsigned int *)fa;
|
||||||
|
|
||||||
|
FP_DECL_S(R);
|
||||||
|
FP_DECL_EX;
|
||||||
|
|
||||||
|
FP_FROM_INT_S(R, a, 32, int);
|
||||||
|
|
||||||
|
FP_PACK_SP(ft, R);
|
||||||
|
|
||||||
|
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
|
||||||
|
|
||||||
|
}
|
|
@ -567,16 +567,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _FP_FRAC_ASSEMBLE_2(r, X, rsize) \
|
#define _FP_FRAC_ASSEMBLE_2(r, X, rsize) \
|
||||||
do { \
|
(void) (((rsize) <= _FP_W_TYPE_SIZE) \
|
||||||
if (rsize <= _FP_W_TYPE_SIZE) \
|
? ({ (r) = X##_f0; }) \
|
||||||
r = X##_f0; \
|
: ({ \
|
||||||
else \
|
(r) = X##_f1; \
|
||||||
{ \
|
(r) <<= _FP_W_TYPE_SIZE; \
|
||||||
r = X##_f1; \
|
(r) += X##_f0; \
|
||||||
r <<= _FP_W_TYPE_SIZE; \
|
}))
|
||||||
r += X##_f0; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define _FP_FRAC_DISASSEMBLE_2(X, r, rsize) \
|
#define _FP_FRAC_DISASSEMBLE_2(X, r, rsize) \
|
||||||
do { \
|
do { \
|
||||||
|
|
|
@ -795,11 +795,12 @@ do { \
|
||||||
ur_ = (unsigned rtype) -r; \
|
ur_ = (unsigned rtype) -r; \
|
||||||
else \
|
else \
|
||||||
ur_ = (unsigned rtype) r; \
|
ur_ = (unsigned rtype) r; \
|
||||||
if (rsize <= _FP_W_TYPE_SIZE) \
|
(void) (((rsize) <= _FP_W_TYPE_SIZE) \
|
||||||
__FP_CLZ(X##_e, ur_); \
|
? ({ __FP_CLZ(X##_e, ur_); }) \
|
||||||
else \
|
: ({ \
|
||||||
__FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \
|
__FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \
|
||||||
(_FP_W_TYPE)ur_); \
|
(_FP_W_TYPE)ur_); \
|
||||||
|
})); \
|
||||||
if (rsize < _FP_W_TYPE_SIZE) \
|
if (rsize < _FP_W_TYPE_SIZE) \
|
||||||
X##_e -= (_FP_W_TYPE_SIZE - rsize); \
|
X##_e -= (_FP_W_TYPE_SIZE - rsize); \
|
||||||
X##_e = rsize - X##_e - 1; \
|
X##_e = rsize - X##_e - 1; \
|
||||||
|
|
Loading…
Reference in New Issue