Commit 93229612 authored by Vincent Chen's avatar Vincent Chen Committed by Greentime Hu

nds32: add new emulations for floating point instruction

The existing floating point emulations is only available for floating
instruction that possibly issue denormalized input and underflow
exceptions. These existing FPU emulations are not sufficient when IEx
Trap is enabled because some floating point instructions only issue inexact
exception. This patch adds the emulations of such floating point
instructions.
Signed-off-by: default avatarVincent Chen <vincentc@andestech.com>
Acked-by: default avatarGreentime Hu <greentime@andestech.com>
Signed-off-by: default avatarGreentime Hu <greentime@andestech.com>
parent ed32949e
......@@ -13,6 +13,12 @@ void fsubs(void *ft, void *fa, void *fb);
void fmuls(void *ft, void *fa, void *fb);
void fdivs(void *ft, void *fa, void *fb);
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 fnegs(void *ft, void *fa);
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 fsqrtd(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);
int fcmpd(void *ft, void *fa, void *fb, int cop);
......
......@@ -4,4 +4,6 @@
obj-y := fpuemu.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
// 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;
}
}
// 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;
}
}
// 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;
}
}
// 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;
ftype = S1D;
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:
func.b = fsqrts;
ftype = S1S;
......@@ -182,6 +206,30 @@ static int fpu_emu(struct fpu_struct *fpu_reg, unsigned long insn)
func.b = fd2s;
ftype = D1S;
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:
func.b = fsqrtd;
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 IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
if (((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE_NO_UDFE) ||
((fpu_reg->fpcsr & FPCSR_mskUDF) && (fpu_reg->UDF_trap)))
if (((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE_NO_UDF_IEXE)
|| ((fpu_reg->fpcsr << 5) & (fpu_reg->UDF_IEX_trap))) {
#else
if ((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE)
if ((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE) {
#endif
return SIGFPE;
}
return 0;
}
int do_fpuemu(struct pt_regs *regs, struct fpu_struct *fpu)
{
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)
return SIGILL;
switch (NDS32Insn_OPCODE_COP0(insn)) {
case fs1_op:
case fs2_op:
......
// 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;
}
}
// 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;
}
}
// 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;
}
}
// 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;
}
}
// 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;
}
// 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;
}
// 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;
}
// 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;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment