Skip to content

Commit 9322961

Browse files
Vincent ChenGreentime Hu
authored andcommitted
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: Vincent Chen <vincentc@andestech.com> Acked-by: Greentime Hu <greentime@andestech.com> Signed-off-by: Greentime Hu <greentime@andestech.com>
1 parent ed32949 commit 9322961

File tree

15 files changed

+393
-5
lines changed

15 files changed

+393
-5
lines changed

arch/nds32/include/asm/fpuemu.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ void fsubs(void *ft, void *fa, void *fb);
1313
void fmuls(void *ft, void *fa, void *fb);
1414
void fdivs(void *ft, void *fa, void *fb);
1515
void fs2d(void *ft, void *fa);
16+
void fs2si(void *ft, void *fa);
17+
void fs2si_z(void *ft, void *fa);
18+
void fs2ui(void *ft, void *fa);
19+
void fs2ui_z(void *ft, void *fa);
20+
void fsi2s(void *ft, void *fa);
21+
void fui2s(void *ft, void *fa);
1622
void fsqrts(void *ft, void *fa);
1723
void fnegs(void *ft, void *fa);
1824
int fcmps(void *ft, void *fa, void *fb, int cop);
@@ -26,6 +32,12 @@ void fmuld(void *ft, void *fa, void *fb);
2632
void fdivd(void *ft, void *fa, void *fb);
2733
void fsqrtd(void *ft, void *fa);
2834
void fd2s(void *ft, void *fa);
35+
void fd2si(void *ft, void *fa);
36+
void fd2si_z(void *ft, void *fa);
37+
void fd2ui(void *ft, void *fa);
38+
void fd2ui_z(void *ft, void *fa);
39+
void fsi2d(void *ft, void *fa);
40+
void fui2d(void *ft, void *fa);
2941
void fnegd(void *ft, void *fa);
3042
int fcmpd(void *ft, void *fa, void *fb, int cop);
3143

arch/nds32/math-emu/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@
44

55
obj-y := fpuemu.o \
66
fdivd.o fmuld.o fsubd.o faddd.o fs2d.o fsqrtd.o fcmpd.o fnegs.o \
7-
fdivs.o fmuls.o fsubs.o fadds.o fd2s.o fsqrts.o fcmps.o fnegd.o
7+
fd2si.o fd2ui.o fd2siz.o fd2uiz.o fsi2d.o fui2d.o \
8+
fdivs.o fmuls.o fsubs.o fadds.o fd2s.o fsqrts.o fcmps.o fnegd.o \
9+
fs2si.o fs2ui.o fs2siz.o fs2uiz.o fsi2s.o fui2s.o

arch/nds32/math-emu/fd2si.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (C) 2005-2019 Andes Technology Corporation
3+
#include <linux/uaccess.h>
4+
5+
#include <asm/sfp-machine.h>
6+
#include <math-emu/soft-fp.h>
7+
#include <math-emu/double.h>
8+
9+
void fd2si(void *ft, void *fa)
10+
{
11+
int r;
12+
13+
FP_DECL_D(A);
14+
FP_DECL_EX;
15+
16+
FP_UNPACK_DP(A, fa);
17+
18+
if (A_c == FP_CLS_INF) {
19+
*(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000;
20+
__FPU_FPCSR |= FP_EX_INVALID;
21+
} else if (A_c == FP_CLS_NAN) {
22+
*(int *)ft = 0xffffffff;
23+
__FPU_FPCSR |= FP_EX_INVALID;
24+
} else {
25+
FP_TO_INT_ROUND_D(r, A, 32, 1);
26+
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
27+
*(int *)ft = r;
28+
}
29+
30+
}

arch/nds32/math-emu/fd2siz.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (C) 2005-2019 Andes Technology Corporation
3+
#include <linux/uaccess.h>
4+
5+
#include <asm/sfp-machine.h>
6+
#include <math-emu/soft-fp.h>
7+
#include <math-emu/double.h>
8+
9+
void fd2si_z(void *ft, void *fa)
10+
{
11+
int r;
12+
13+
FP_DECL_D(A);
14+
FP_DECL_EX;
15+
16+
FP_UNPACK_DP(A, fa);
17+
18+
if (A_c == FP_CLS_INF) {
19+
*(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000;
20+
__FPU_FPCSR |= FP_EX_INVALID;
21+
} else if (A_c == FP_CLS_NAN) {
22+
*(int *)ft = 0xffffffff;
23+
__FPU_FPCSR |= FP_EX_INVALID;
24+
} else {
25+
FP_TO_INT_D(r, A, 32, 1);
26+
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
27+
*(int *)ft = r;
28+
}
29+
30+
}

arch/nds32/math-emu/fd2ui.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (C) 2005-2019 Andes Technology Corporation
3+
#include <linux/uaccess.h>
4+
5+
#include <asm/sfp-machine.h>
6+
#include <math-emu/soft-fp.h>
7+
#include <math-emu/double.h>
8+
9+
void fd2ui(void *ft, void *fa)
10+
{
11+
unsigned int r;
12+
13+
FP_DECL_D(A);
14+
FP_DECL_EX;
15+
16+
FP_UNPACK_DP(A, fa);
17+
18+
if (A_c == FP_CLS_INF) {
19+
*(unsigned int *)ft = (A_s == 0) ? 0xffffffff : 0x00000000;
20+
__FPU_FPCSR |= FP_EX_INVALID;
21+
} else if (A_c == FP_CLS_NAN) {
22+
*(unsigned int *)ft = 0xffffffff;
23+
__FPU_FPCSR |= FP_EX_INVALID;
24+
} else {
25+
FP_TO_INT_ROUND_D(r, A, 32, 0);
26+
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
27+
*(unsigned int *)ft = r;
28+
}
29+
30+
}

arch/nds32/math-emu/fd2uiz.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (C) 2005-2019 Andes Technology Corporation
3+
#include <linux/uaccess.h>
4+
5+
#include <asm/sfp-machine.h>
6+
#include <math-emu/soft-fp.h>
7+
#include <math-emu/double.h>
8+
9+
void fd2ui_z(void *ft, void *fa)
10+
{
11+
unsigned int r;
12+
13+
FP_DECL_D(A);
14+
FP_DECL_EX;
15+
16+
FP_UNPACK_DP(A, fa);
17+
18+
if (A_c == FP_CLS_INF) {
19+
*(unsigned int *)ft = (A_s == 0) ? 0xffffffff : 0x00000000;
20+
__FPU_FPCSR |= FP_EX_INVALID;
21+
} else if (A_c == FP_CLS_NAN) {
22+
*(unsigned int *)ft = 0xffffffff;
23+
__FPU_FPCSR |= FP_EX_INVALID;
24+
} else {
25+
FP_TO_INT_D(r, A, 32, 0);
26+
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
27+
*(unsigned int *)ft = r;
28+
}
29+
30+
}

arch/nds32/math-emu/fpuemu.c

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,30 @@ static int fpu_emu(struct fpu_struct *fpu_reg, unsigned long insn)
113113
func.b = fs2d;
114114
ftype = S1D;
115115
break;
116+
case fs2si_op:
117+
func.b = fs2si;
118+
ftype = S1S;
119+
break;
120+
case fs2si_z_op:
121+
func.b = fs2si_z;
122+
ftype = S1S;
123+
break;
124+
case fs2ui_op:
125+
func.b = fs2ui;
126+
ftype = S1S;
127+
break;
128+
case fs2ui_z_op:
129+
func.b = fs2ui_z;
130+
ftype = S1S;
131+
break;
132+
case fsi2s_op:
133+
func.b = fsi2s;
134+
ftype = S1S;
135+
break;
136+
case fui2s_op:
137+
func.b = fui2s;
138+
ftype = S1S;
139+
break;
116140
case fsqrts_op:
117141
func.b = fsqrts;
118142
ftype = S1S;
@@ -182,6 +206,30 @@ static int fpu_emu(struct fpu_struct *fpu_reg, unsigned long insn)
182206
func.b = fd2s;
183207
ftype = D1S;
184208
break;
209+
case fd2si_op:
210+
func.b = fd2si;
211+
ftype = D1S;
212+
break;
213+
case fd2si_z_op:
214+
func.b = fd2si_z;
215+
ftype = D1S;
216+
break;
217+
case fd2ui_op:
218+
func.b = fd2ui;
219+
ftype = D1S;
220+
break;
221+
case fd2ui_z_op:
222+
func.b = fd2ui_z;
223+
ftype = D1S;
224+
break;
225+
case fsi2d_op:
226+
func.b = fsi2d;
227+
ftype = D1S;
228+
break;
229+
case fui2d_op:
230+
func.b = fui2d;
231+
ftype = D1S;
232+
break;
185233
case fsqrtd_op:
186234
func.b = fsqrtd;
187235
ftype = D1D;
@@ -305,16 +353,16 @@ static int fpu_emu(struct fpu_struct *fpu_reg, unsigned long insn)
305353
* If an exception is required, generate a tidy SIGFPE exception.
306354
*/
307355
#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
308-
if (((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE_NO_UDFE) ||
309-
((fpu_reg->fpcsr & FPCSR_mskUDF) && (fpu_reg->UDF_trap)))
356+
if (((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE_NO_UDF_IEXE)
357+
|| ((fpu_reg->fpcsr << 5) & (fpu_reg->UDF_IEX_trap))) {
310358
#else
311-
if ((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE)
359+
if ((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE) {
312360
#endif
313361
return SIGFPE;
362+
}
314363
return 0;
315364
}
316365

317-
318366
int do_fpuemu(struct pt_regs *regs, struct fpu_struct *fpu)
319367
{
320368
unsigned long insn = 0, addr = regs->ipc;
@@ -336,6 +384,7 @@ int do_fpuemu(struct pt_regs *regs, struct fpu_struct *fpu)
336384

337385
if (NDS32Insn_OPCODE(insn) != cop0_op)
338386
return SIGILL;
387+
339388
switch (NDS32Insn_OPCODE_COP0(insn)) {
340389
case fs1_op:
341390
case fs2_op:

arch/nds32/math-emu/fs2si.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (C) 2005-2019 Andes Technology Corporation
3+
#include <linux/uaccess.h>
4+
5+
#include <asm/sfp-machine.h>
6+
#include <math-emu/soft-fp.h>
7+
#include <math-emu/single.h>
8+
9+
void fs2si(void *ft, void *fa)
10+
{
11+
int r;
12+
13+
FP_DECL_S(A);
14+
FP_DECL_EX;
15+
16+
FP_UNPACK_SP(A, fa);
17+
18+
if (A_c == FP_CLS_INF) {
19+
*(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000;
20+
__FPU_FPCSR |= FP_EX_INVALID;
21+
} else if (A_c == FP_CLS_NAN) {
22+
*(int *)ft = 0xffffffff;
23+
__FPU_FPCSR |= FP_EX_INVALID;
24+
} else {
25+
FP_TO_INT_ROUND_S(r, A, 32, 1);
26+
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
27+
*(int *)ft = r;
28+
}
29+
}

arch/nds32/math-emu/fs2siz.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (C) 2005-2019 Andes Technology Corporation
3+
#include <linux/uaccess.h>
4+
5+
#include <asm/sfp-machine.h>
6+
#include <math-emu/soft-fp.h>
7+
#include <math-emu/single.h>
8+
9+
void fs2si_z(void *ft, void *fa)
10+
{
11+
int r;
12+
13+
FP_DECL_S(A);
14+
FP_DECL_EX;
15+
16+
FP_UNPACK_SP(A, fa);
17+
18+
if (A_c == FP_CLS_INF) {
19+
*(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000;
20+
__FPU_FPCSR |= FP_EX_INVALID;
21+
} else if (A_c == FP_CLS_NAN) {
22+
*(int *)ft = 0xffffffff;
23+
__FPU_FPCSR |= FP_EX_INVALID;
24+
} else {
25+
FP_TO_INT_S(r, A, 32, 1);
26+
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
27+
*(int *)ft = r;
28+
}
29+
}

arch/nds32/math-emu/fs2ui.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (C) 2005-2019 Andes Technology Corporation
3+
#include <linux/uaccess.h>
4+
5+
#include <asm/sfp-machine.h>
6+
#include <math-emu/soft-fp.h>
7+
#include <math-emu/single.h>
8+
9+
void fs2ui(void *ft, void *fa)
10+
{
11+
unsigned int r;
12+
13+
FP_DECL_S(A);
14+
FP_DECL_EX;
15+
16+
FP_UNPACK_SP(A, fa);
17+
18+
if (A_c == FP_CLS_INF) {
19+
*(unsigned int *)ft = (A_s == 0) ? 0xffffffff : 0x00000000;
20+
__FPU_FPCSR |= FP_EX_INVALID;
21+
} else if (A_c == FP_CLS_NAN) {
22+
*(unsigned int *)ft = 0xffffffff;
23+
__FPU_FPCSR |= FP_EX_INVALID;
24+
} else {
25+
FP_TO_INT_ROUND_S(r, A, 32, 0);
26+
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
27+
*(unsigned int *)ft = r;
28+
}
29+
}

0 commit comments

Comments
 (0)