From b477e9102a10813fe629633a48c877c9af46cd32 Mon Sep 17 00:00:00 2001 From: Jiri Gaisler Date: Mon, 6 Apr 2020 23:10:03 +0200 Subject: Map RISC-V FPU CSR on host cpu using fenv.h --- Makefile.am | 2 +- Makefile.in | 16 +++++------- exec.c | 9 ++++++- float.c | 85 ------------------------------------------------------------- riscv.c | 66 ++++++++++++++++++++++++++++++++++++++++++----- sparc.c | 54 ++++++++++++++++++++++++++++++++++++--- 6 files changed, 125 insertions(+), 107 deletions(-) delete mode 100644 float.c 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 #include #include +#include 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 . */ - -/* 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 - -/* 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 #include #include +#include #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 #include #include +#include #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; -- cgit v1.2.3