summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiri Gaisler <jiri@gaisler.se>2020-04-06 23:10:03 +0200
committerJiri Gaisler <jiri@gaisler.se>2020-09-09 10:37:55 +0200
commitb477e9102a10813fe629633a48c877c9af46cd32 (patch)
tree4cbe638aedc330dcc1cb768511be16c392da81e1
parentd03731a245113bd4f9587dc9a64c1c06cd8c6a1a (diff)
Map RISC-V FPU CSR on host cpu using fenv.h
-rw-r--r--Makefile.am2
-rw-r--r--Makefile.in16
-rw-r--r--exec.c9
-rw-r--r--float.c85
-rw-r--r--riscv.c66
-rw-r--r--sparc.c54
6 files changed, 125 insertions, 107 deletions
diff --git a/Makefile.am b/Makefile.am
index 108dd0c..59d1b20 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,7 +5,7 @@ else
endif
bin_PROGRAMS = sis
-sis_SOURCES = erc32.c float.c grlib.c leon3.c exec.c func.c help.c \
+sis_SOURCES = erc32.c grlib.c leon3.c exec.c func.c help.c \
sparc.c riscv.c leon2.c sis.c interf.c remote.c elf.c \
$(LN_SRC)
diff --git a/Makefile.in b/Makefile.in
index 8b091a6..c6c5762 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -77,15 +77,14 @@ CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(infodir)"
PROGRAMS = $(bin_PROGRAMS)
-am__sis_SOURCES_DIST = erc32.c float.c grlib.c leon3.c exec.c func.c \
- help.c sparc.c riscv.c leon2.c sis.c interf.c remote.c elf.c \
+am__sis_SOURCES_DIST = erc32.c grlib.c leon3.c exec.c func.c help.c \
+ sparc.c riscv.c leon2.c sis.c interf.c remote.c elf.c \
linenoise.c
@LINENOISE_TRUE@am__objects_1 = linenoise.$(OBJEXT)
-am_sis_OBJECTS = erc32.$(OBJEXT) float.$(OBJEXT) grlib.$(OBJEXT) \
- leon3.$(OBJEXT) exec.$(OBJEXT) func.$(OBJEXT) help.$(OBJEXT) \
- sparc.$(OBJEXT) riscv.$(OBJEXT) leon2.$(OBJEXT) sis.$(OBJEXT) \
- interf.$(OBJEXT) remote.$(OBJEXT) elf.$(OBJEXT) \
- $(am__objects_1)
+am_sis_OBJECTS = erc32.$(OBJEXT) grlib.$(OBJEXT) leon3.$(OBJEXT) \
+ exec.$(OBJEXT) func.$(OBJEXT) help.$(OBJEXT) sparc.$(OBJEXT) \
+ riscv.$(OBJEXT) leon2.$(OBJEXT) sis.$(OBJEXT) interf.$(OBJEXT) \
+ remote.$(OBJEXT) elf.$(OBJEXT) $(am__objects_1)
sis_OBJECTS = $(am_sis_OBJECTS)
sis_DEPENDENCIES =
DEFAULT_INCLUDES = -I.@am__isrc@
@@ -264,7 +263,7 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
@LINENOISE_FALSE@LN_SRC =
@LINENOISE_TRUE@LN_SRC = linenoise.c
-sis_SOURCES = erc32.c float.c grlib.c leon3.c exec.c func.c help.c \
+sis_SOURCES = erc32.c grlib.c leon3.c exec.c func.c help.c \
sparc.c riscv.c leon2.c sis.c interf.c remote.c elf.c \
$(LN_SRC)
@@ -379,7 +378,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/erc32.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exec.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/float.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/func.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grlib.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/help.Po@am__quote@
diff --git a/exec.c b/exec.c
index 3c9548d..0805b38 100644
--- a/exec.c
+++ b/exec.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
+#include <fenv.h>
int ext_irl[NCPU];
@@ -114,6 +115,13 @@ div64 (uint32 n1_hi, uint32 n1_low, uint32 n2, uint32 * result, int msigned)
*result = (uint32) (n1 & 0xffffffff);
}
+/* How to clear the accrued FPU exceptions */
+void
+clear_accex ()
+{
+ feclearexcept (FE_ALL_EXCEPT);
+}
+
void
init_regs (sregs)
struct pstate *sregs;
@@ -147,7 +155,6 @@ init_regs (sregs)
sregs[i].fsi = (int32 *) sregs[i].fd;
sregs[i].fsr = 0;
sregs[i].fpu_pres = !nfp;
- set_fsr (sregs[i].fsr);
sregs[i].ildreg = 0;
sregs[i].ildtime = 0;
diff --git a/float.c b/float.c
deleted file mode 100644
index 58c307e..0000000
--- a/float.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/* This file is part of SIS (SPARC instruction simulator)
-
- Copyright (C) 1995-2017 Free Software Foundation, Inc.
- Contributed by Jiri Gaisler, European Space Agency
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-/* This file implements the interface between the host and the simulated
- FPU. IEEE trap handling is done as follows:
- 1. In the host, all IEEE traps are masked
- 2. After each simulated FPU instruction, check if any exception
- occured by reading the exception bits from the host FPU status
- register (get_accex()).
- 3. Propagate any exceptions to the simulated FSR.
- 4. Clear host exception bits.
- */
-
-#include "config.h"
-#include "sis.h"
-#include <fenv.h>
-
-/* This routine should return the accrued exceptions */
-int
-get_accex ()
-{
- int fexc, accx;
-
- fexc = fetestexcept (FE_ALL_EXCEPT);
- accx = 0;
- if (fexc & FE_INEXACT)
- accx |= 1;
- if (fexc & FE_DIVBYZERO)
- accx |= 2;
- if (fexc & FE_UNDERFLOW)
- accx |= 4;
- if (fexc & FE_OVERFLOW)
- accx |= 8;
- if (fexc & FE_INVALID)
- accx |= 0x10;
- return accx;
-}
-
-/* How to clear the accrued exceptions */
-void
-clear_accex ()
-{
- feclearexcept (FE_ALL_EXCEPT);
-}
-
-/* How to map SPARC FSR onto the host */
-void
-set_fsr (fsr)
- uint32 fsr;
-{
- int fround;
-
- fsr >>= 30;
- switch (fsr)
- {
- case 0:
- fround = FE_TONEAREST;
- break;
- case 1:
- fround = FE_TOWARDZERO;
- break;
- case 2:
- fround = FE_UPWARD;
- break;
- case 3:
- fround = FE_DOWNWARD;
- break;
- }
- fesetround (fround);
-}
diff --git a/riscv.c b/riscv.c
index d097fb2..100f7ad 100644
--- a/riscv.c
+++ b/riscv.c
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
+#include <fenv.h>
#ifdef WORDS_BIGENDIAN
#define BEH 1
@@ -30,6 +31,54 @@
#define BEH 0
#endif
+/* This routine should return the accrued FPU exceptions */
+static int
+riscv_get_accex ()
+{
+ int fexc, accx;
+
+ fexc = fetestexcept (FE_ALL_EXCEPT);
+ accx = 0;
+ if (fexc & FE_INEXACT)
+ accx |= 1;
+ if (fexc & FE_UNDERFLOW)
+ accx |= 2;
+ if (fexc & FE_OVERFLOW)
+ accx |= 4;
+ if (fexc & FE_DIVBYZERO)
+ accx |= 8;
+ if (fexc & FE_INVALID)
+ accx |= 0x10;
+ return accx;
+}
+
+/* How to map RISCV FSR onto the host */
+static void
+riscv_set_fsr (fsr)
+ uint32 fsr;
+{
+ int fround;
+
+ fsr >>= 5;
+ fsr &= 0x3;
+ switch (fsr)
+ {
+ case 0:
+ fround = FE_TONEAREST;
+ break;
+ case 1:
+ fround = FE_TOWARDZERO;
+ break;
+ case 2:
+ fround = FE_DOWNWARD;
+ break;
+ case 3:
+ fround = FE_UPWARD;
+ break;
+ }
+ fesetround (fround);
+}
+
static int
set_csr (address, sregs, value)
uint32 address;
@@ -61,12 +110,15 @@ set_csr (address, sregs, value)
break;
case CSR_FFLAGS:
sregs->fsr = (sregs->fsr & ~0x1f) | value;
+ riscv_set_fsr (sregs->fsr);
break;
case CSR_FRM:
- sregs->fsr = (sregs->fsr & ~0xc0) | (value << 5);
+ sregs->fsr = (sregs->fsr & ~0xe0) | (value << 5);
+ riscv_set_fsr (sregs->fsr);
break;
case CSR_FCSR:
sregs->fsr = value;
+ riscv_set_fsr (sregs->fsr);
break;
default:
return 1;
@@ -1824,7 +1876,7 @@ riscv_dispatch_instruction (sregs)
default:
sregs->trap = TRAP_ILLEG;
}
- sregs->fsr |= get_accex ();
+ sregs->fsr |= riscv_get_accex ();
clear_accex ();
break;
case OP_FMADD:
@@ -1849,7 +1901,7 @@ riscv_dispatch_instruction (sregs)
default:
sregs->trap = TRAP_ILLEG;
}
- sregs->fsr |= get_accex ();
+ sregs->fsr |= riscv_get_accex ();
clear_accex ();
break;
case OP_FMSUB:
@@ -1874,7 +1926,7 @@ riscv_dispatch_instruction (sregs)
default:
sregs->trap = TRAP_ILLEG;
}
- sregs->fsr |= get_accex ();
+ sregs->fsr |= riscv_get_accex ();
clear_accex ();
break;
case OP_FNMSUB:
@@ -1899,7 +1951,7 @@ riscv_dispatch_instruction (sregs)
default:
sregs->trap = TRAP_ILLEG;
}
- sregs->fsr |= get_accex ();
+ sregs->fsr |= riscv_get_accex ();
clear_accex ();
break;
case OP_FNMADD:
@@ -1924,7 +1976,7 @@ riscv_dispatch_instruction (sregs)
default:
sregs->trap = TRAP_ILLEG;
}
- sregs->fsr |= get_accex ();
+ sregs->fsr |= riscv_get_accex ();
clear_accex ();
break;
#endif
@@ -2143,7 +2195,7 @@ riscv_set_rega (struct pstate *sregs, char *reg, uint32 rval)
else if (strcmp (reg, "fsr") == 0)
{
sregs->fsr = rval;
- set_fsr (rval);
+ riscv_set_fsr (rval);
}
else if (strcmp (reg, "g0") == 0)
err = 2;
diff --git a/sparc.c b/sparc.c
index 03a78d8..dee95c1 100644
--- a/sparc.c
+++ b/sparc.c
@@ -4,6 +4,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
+#include <fenv.h>
#include "sparc.h"
static int fpexec (uint32 op3, uint32 rd, uint32 rs1, uint32 rs2,
@@ -132,6 +133,31 @@ extract_byte (uint32 data, uint32 address)
return ((data >> ((3 - (address & 3)) * 8)) & 0xff);
}
+/* How to map SPARC FSR onto the host */
+static void
+sparc_set_fsr (fsr)
+ uint32 fsr;
+{
+ int fround;
+
+ fsr >>= 30;
+ switch (fsr)
+ {
+ case 0:
+ fround = FE_TONEAREST;
+ break;
+ case 1:
+ fround = FE_TOWARDZERO;
+ break;
+ case 2:
+ fround = FE_UPWARD;
+ break;
+ case 3:
+ fround = FE_DOWNWARD;
+ break;
+ }
+ fesetround (fround);
+}
static int
sparc_dispatch_instruction (sregs)
@@ -1249,7 +1275,7 @@ sparc_dispatch_instruction (sregs)
else
{
sregs->fsr = (sregs->fsr & 0x7FF000) | (data & ~0x7FF000);
- set_fsr (sregs->fsr);
+ sparc_set_fsr (sregs->fsr);
}
break;
case STFSR:
@@ -1598,6 +1624,26 @@ sparc_dispatch_instruction (sregs)
#define FsTOi 0xD1
#define FsTOd 0xC9
+/* This routine should return the accrued exceptions */
+static int
+sparc_get_accex ()
+{
+ int fexc, accx;
+
+ fexc = fetestexcept (FE_ALL_EXCEPT);
+ accx = 0;
+ if (fexc & FE_INEXACT)
+ accx |= 1;
+ if (fexc & FE_DIVBYZERO)
+ accx |= 2;
+ if (fexc & FE_UNDERFLOW)
+ accx |= 4;
+ if (fexc & FE_OVERFLOW)
+ accx |= 8;
+ if (fexc & FE_INVALID)
+ accx |= 0x10;
+ return accx;
+}
static int
fpexec (op3, rd, rs1, rs2, sregs)
@@ -1844,7 +1890,7 @@ fpexec (op3, rd, rs1, rs2, sregs)
}
#endif
- accex = get_accex ();
+ accex = sparc_get_accex ();
if (sregs->fpstate == FP_EXC_PE)
{
@@ -2063,7 +2109,7 @@ sparc_set_regi (sregs, reg, rval)
break;
case 70:
sregs->fsr = rval;
- set_fsr (rval);
+ sparc_set_fsr (rval);
break;
default:
break;
@@ -2150,7 +2196,7 @@ sparc_set_rega (struct pstate *sregs, char *reg, uint32 rval)
else if (strcmp (reg, "fsr") == 0)
{
sregs->fsr = rval;
- set_fsr (rval);
+ sparc_set_fsr (rval);
}
else if (strcmp (reg, "g0") == 0)
err = 2;