aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/continuous-integration.yml2
-rw-r--r--.gitignore1
-rw-r--r--Makefile.in11
-rw-r--r--README.md21
-rw-r--r--ci-tests/atomics.c20
-rwxr-xr-xci-tests/build-spike4
-rwxr-xr-xci-tests/create-ci-binary-tarball17
-rw-r--r--ci-tests/custom-csr.cc82
-rw-r--r--ci-tests/customcsr.c12
-rw-r--r--ci-tests/test-customext.cc9
-rwxr-xr-xci-tests/test-spike10
-rw-r--r--ci-tests/testlib.cc (renamed from ci-tests/testlib.c)3
-rw-r--r--config.h.in22
-rwxr-xr-xconfigure1402
-rw-r--r--configure.ac28
-rw-r--r--customext/cflush.cc22
-rw-r--r--customext/dummy_rocc.cc8
-rwxr-xr-xdebug_rom/debug_rom.S58
-rw-r--r--debug_rom/debug_rom.h32
-rw-r--r--disasm/disasm.cc487
-rw-r--r--disasm/isa_parser.cc83
-rw-r--r--fdt/fdt.mk.in2
-rw-r--r--fdt/libfdt.h4
-rw-r--r--fesvr/byteorder.h22
-rw-r--r--fesvr/dtm.cc43
-rw-r--r--fesvr/dtm.h2
-rw-r--r--fesvr/elfloader.h1
-rw-r--r--fesvr/htif.cc98
-rw-r--r--fesvr/htif.h11
-rw-r--r--fesvr/htif_pthread.h2
-rw-r--r--fesvr/memif.cc28
-rw-r--r--fesvr/syscall.cc16
-rw-r--r--m4/ax_append_flag.m4 (renamed from ax_append_flag.m4)0
-rw-r--r--m4/ax_append_link_flags.m4 (renamed from ax_append_link_flags.m4)0
-rw-r--r--m4/ax_boost_asio.m4 (renamed from ax_boost_asio.m4)0
-rw-r--r--m4/ax_boost_base.m4 (renamed from ax_boost_base.m4)20
-rw-r--r--m4/ax_boost_regex.m4 (renamed from ax_boost_regex.m4)0
-rw-r--r--m4/ax_check_compile_flag.m4 (renamed from ax_check_compile_flag.m4)16
-rw-r--r--m4/ax_check_link_flag.m4 (renamed from ax_check_link_flag.m4)0
-rw-r--r--m4/ax_require_defined.m4 (renamed from ax_require_defined.m4)0
-rw-r--r--riscv/abstract_device.h1
-rw-r--r--riscv/arith.h6
-rw-r--r--riscv/cfg.cc8
-rw-r--r--riscv/cfg.h3
-rw-r--r--riscv/clint.cc10
-rw-r--r--riscv/csr_init.cc552
-rw-r--r--riscv/csrs.cc605
-rw-r--r--riscv/csrs.h149
-rw-r--r--riscv/debug_module.cc12
-rw-r--r--riscv/debug_module.h5
-rw-r--r--riscv/decode.h11
-rw-r--r--riscv/decode_macros.h29
-rw-r--r--riscv/devices.cc125
-rw-r--r--riscv/devices.h36
-rw-r--r--riscv/disasm.h4
-rw-r--r--riscv/dts.cc155
-rw-r--r--riscv/dts.h11
-rw-r--r--riscv/encoding.h314
-rw-r--r--riscv/entropy_source.h5
-rw-r--r--riscv/execute.cc68
-rw-r--r--riscv/extension.cc14
-rw-r--r--riscv/extension.h22
-rw-r--r--riscv/insn_template.cc47
-rw-r--r--riscv/insns/bclri.h1
-rw-r--r--riscv/insns/bexti.h1
-rw-r--r--riscv/insns/binvi.h1
-rw-r--r--riscv/insns/bseti.h1
-rw-r--r--riscv/insns/c_ld.h2
-rw-r--r--riscv/insns/c_ldsp.h2
-rw-r--r--riscv/insns/c_sd.h2
-rw-r--r--riscv/insns/c_sdsp.h2
-rw-r--r--riscv/insns/dret.h16
-rw-r--r--riscv/insns/fcvtmod_w_d.h3
-rw-r--r--riscv/insns/jal.h1
-rw-r--r--riscv/insns/jalr.h1
-rw-r--r--riscv/insns/mnret.h6
-rw-r--r--riscv/insns/mret.h7
-rw-r--r--riscv/insns/sret.h16
-rw-r--r--riscv/insns/ssrdp.h2
-rw-r--r--riscv/insns/vcompress_vm.h7
-rw-r--r--riscv/insns/vcpop_m.h12
-rw-r--r--riscv/insns/vfirst_m.h3
-rw-r--r--riscv/insns/vfrsqrt7_v.h2
-rw-r--r--riscv/insns/vghsh_vv.h4
-rw-r--r--riscv/insns/vgmul_vv.h4
-rw-r--r--riscv/insns/viota_m.h25
-rw-r--r--riscv/insns/vmandn_mm.h2
-rw-r--r--riscv/insns/vmnand_mm.h2
-rw-r--r--riscv/insns/vmnor_mm.h2
-rw-r--r--riscv/insns/vmorn_mm.h2
-rw-r--r--riscv/insns/vmsbf_m.h17
-rw-r--r--riscv/insns/vmsif_m.h18
-rw-r--r--riscv/insns/vmsof_m.h16
-rw-r--r--riscv/insns/vmulhu_vv.h2
-rw-r--r--riscv/insns/vmxnor_mm.h2
-rw-r--r--riscv/insns/vnclip_wi.h6
-rw-r--r--riscv/insns/vnclip_wv.h6
-rw-r--r--riscv/insns/vnclip_wx.h6
-rw-r--r--riscv/insns/vnclipu_wi.h6
-rw-r--r--riscv/insns/vnclipu_wv.h6
-rw-r--r--riscv/insns/vnclipu_wx.h6
-rw-r--r--riscv/insns/vnsra_wi.h2
-rw-r--r--riscv/insns/vqdot_common.h15
-rw-r--r--riscv/insns/vqdot_vv.h11
-rw-r--r--riscv/insns/vqdot_vx.h11
-rw-r--r--riscv/insns/vqdotsu_vv.h11
-rw-r--r--riscv/insns/vqdotsu_vx.h11
-rw-r--r--riscv/insns/vqdotu_vv.h11
-rw-r--r--riscv/insns/vqdotu_vx.h11
-rw-r--r--riscv/insns/vqdotus_vx.h11
-rw-r--r--riscv/insns/vredand_vs.h2
-rw-r--r--riscv/insns/vredmaxu_vs.h2
-rw-r--r--riscv/insns/vredmin_vs.h2
-rw-r--r--riscv/insns/vredminu_vs.h2
-rw-r--r--riscv/insns/vredor_vs.h2
-rw-r--r--riscv/insns/vredsum_vs.h2
-rw-r--r--riscv/insns/vredxor_vs.h2
-rw-r--r--riscv/insns/vsll_vi.h4
-rw-r--r--riscv/insns/vsll_vv.h2
-rw-r--r--riscv/insns/vsll_vx.h2
-rw-r--r--riscv/insns/vsm3c_vi.h1
-rw-r--r--riscv/insns/vsm3me_vv.h1
-rw-r--r--riscv/insns/vsm4k_vi.h1
-rw-r--r--riscv/insns/vsm4r_vs.h4
-rw-r--r--riscv/insns/vsm4r_vv.h2
-rw-r--r--riscv/insns/vsmul_vv.h8
-rw-r--r--riscv/insns/vsmul_vx.h8
-rw-r--r--riscv/insns/vsra_vi.h2
-rw-r--r--riscv/insns/vsrl_vi.h2
-rw-r--r--riscv/insns/vssra_vi.h6
-rw-r--r--riscv/insns/vssra_vv.h2
-rw-r--r--riscv/insns/vssra_vx.h2
-rw-r--r--riscv/insns/vssrl_vi.h6
-rw-r--r--riscv/insns/vssrl_vv.h2
-rw-r--r--riscv/insns/vssrl_vx.h2
-rw-r--r--riscv/insns/vwsll_vi.h1
-rw-r--r--riscv/insns/vwsll_vv.h1
-rw-r--r--riscv/insns/vwsll_vx.h1
-rw-r--r--riscv/interactive.cc83
-rw-r--r--riscv/isa_parser.h14
-rw-r--r--riscv/jtag_dtm.h4
-rw-r--r--riscv/log_file.h2
-rw-r--r--riscv/mmu.cc370
-rw-r--r--riscv/mmu.h197
-rw-r--r--riscv/ns16550.cc4
-rw-r--r--riscv/platform.h2
-rw-r--r--riscv/plic.cc12
-rw-r--r--riscv/processor.cc702
-rw-r--r--riscv/processor.h51
-rw-r--r--riscv/riscv.ac14
-rw-r--r--riscv/riscv.mk.in13
-rw-r--r--riscv/rocc.cc28
-rw-r--r--riscv/rocc.h12
-rw-r--r--riscv/sim.cc132
-rw-r--r--riscv/sim.h14
-rw-r--r--riscv/trap.h1
-rw-r--r--riscv/triggers.cc108
-rw-r--r--riscv/triggers.h6
-rw-r--r--riscv/v_ext_macros.h129
-rw-r--r--riscv/vector_unit.cc26
-rw-r--r--riscv/vector_unit.h11
-rw-r--r--riscv/zicfiss.h2
-rw-r--r--riscv/zvk_ext_macros.h26
-rw-r--r--riscv/zvkned_ext_macros.h16
-rw-r--r--riscv/zvknh_ext_macros.h1
-rw-r--r--riscv/zvksed_ext_macros.h3
-rw-r--r--riscv/zvksh_ext_macros.h3
-rwxr-xr-x[-rw-r--r--]scripts/config.guess1323
-rwxr-xr-x[-rw-r--r--]scripts/config.sub306
-rwxr-xr-xscripts/install-sh541
-rwxr-xr-xscripts/install.sh238
-rw-r--r--softfloat/bf16_classify.c36
-rw-r--r--softfloat/bf16_cmp.c65
-rw-r--r--softfloat/bf16_to_i32.c48
-rw-r--r--softfloat/bf16_to_i8.c57
-rw-r--r--softfloat/bf16_to_ui32.c48
-rw-r--r--softfloat/bf16_to_ui8.c54
-rw-r--r--[-rwxr-xr-x]softfloat/f128_classify.c0
-rw-r--r--[-rwxr-xr-x]softfloat/f16_classify.c0
-rw-r--r--[-rwxr-xr-x]softfloat/f32_classify.c0
-rw-r--r--[-rwxr-xr-x]softfloat/f64_classify.c0
-rw-r--r--softfloat/f64_to_bf16.c46
-rw-r--r--softfloat/fall_maxmin.c28
-rw-r--r--softfloat/fall_reciprocal.c80
-rw-r--r--softfloat/fall_sign.c63
-rw-r--r--softfloat/i32_to_bf16.c52
-rw-r--r--softfloat/internals.h15
-rw-r--r--softfloat/softfloat.h18
-rw-r--r--softfloat/softfloat.mk.in16
-rw-r--r--softfloat/specialize.h7
-rw-r--r--softfloat/ui32_to_bf16.c51
-rw-r--r--spike_dasm/spike-dasm.cc6
-rw-r--r--spike_main/spike-log-parser.cc5
-rw-r--r--spike_main/spike.cc85
194 files changed, 6560 insertions, 3793 deletions
diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index 88facc8..517c74e 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -38,7 +38,7 @@ jobs:
test-macos:
name: Test Spike build (MacOS)
- runs-on: macos-12
+ runs-on: macos-13
steps:
- uses: actions/checkout@v2
with:
diff --git a/.gitignore b/.gitignore
index 6bae0e1..eb0379b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ autom4te.cache/
.gdb_history
.#*
*~
+config.log
diff --git a/Makefile.in b/Makefile.in
index f90159e..66d087b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -93,7 +93,7 @@ VPATH := $(addprefix $(src_dir)/, $(sprojs_enabled))
# These all appear on the command line, from lowest precedence to
# highest.
-default-CFLAGS := -DPREFIX=\"$(prefix)\" -Wall -Wno-unused -Wno-nonportable-include-path -g -O2 -fPIC
+default-CFLAGS := -DPREFIX=\"$(prefix)\" -Wall -Wno-nonportable-include-path -g -O2 -fPIC
default-CXXFLAGS := $(default-CFLAGS) -std=c++2a
mcppbs-CPPFLAGS := @CPPFLAGS@
@@ -385,6 +385,15 @@ install-hdrs : $(install_hdrs)
$(INSTALL_HDR) $(src_dir)/$$file $(install_hdrs_dir)/`dirname $$file`; \
done
+install-hdrs-list.h: $(install_hdrs)
+ rm -f $@.tmp
+ for file in $(subst $(src_dir)/,,$^); \
+ do \
+ $(MKINSTALLDIRS) $(install_hdrs_dir)/`dirname $$file`; \
+ echo "#include <$(src_dir)/$$file>" >> $@.tmp; \
+ done
+ mv $@.tmp $@
+
install-libs : $(install_libs)
$(MKINSTALLDIRS) $(install_libs_dir)
for file in $^; \
diff --git a/README.md b/README.md
index 63f29eb..83d4503 100644
--- a/README.md
+++ b/README.md
@@ -13,8 +13,10 @@ Spike supports the following RISC-V ISA features:
- RV32E and RV64E base ISAs, v1.9
- Zifencei extension, v2.0
- Zicsr extension, v2.0
+ - Zicntr extension, v2.0
- M extension, v2.0
- A extension, v2.1
+ - B extension, v1.0
- F extension, v2.2
- D extension, v2.2
- Q extension, v2.2
@@ -28,6 +30,7 @@ Spike supports the following RISC-V ISA features:
- Zbc extension, v1.0
- Zbs extension, v1.0
- Zfh and Zfhmin half-precision floating-point extensions, v1.0
+ - Zfa extension, v1.0
- Zfinx extension, v1.0
- Zmmul integer multiplication extension, v1.0
- Zicbom, Zicbop, Zicboz cache-block maintenance extensions, v1.0
@@ -37,11 +40,23 @@ Spike supports the following RISC-V ISA features:
- Svnapot extension, v1.0
- Svpbmt extension, v1.0
- Svinval extension, v1.0
+ - Svadu extension, v1.0
+ - Svade extension, v1.0
- Sdext extension, v1.0-STABLE
- Sdtrig extension, v1.0-STABLE
- Smepmp extension v1.0
- Smstateen extension, v1.0
+ - Smdbltrp extension, v1.0
- Sscofpmf v0.5.2
+ - Ssdbltrp extension, v1.0
+ - Ssqosid extension, v1.0
+ - Zaamo extension, v1.0
+ - Zalrsc extension, v1.0
+ - Zabha extension, v1.0
+ - Zacas extension, v1.0
+ - Zawrs extension, v1.0
+ - Zicfiss extension, v1.0
+ - Zicfilp extension, v1.0
- Zca extension, v1.0
- Zcb extension, v1.0
- Zcf extension, v1.0
@@ -61,8 +76,10 @@ Spike supports the following RISC-V ISA features:
- Zvkt extension, v1.0
- Zvkn, Zvknc, Zvkng extension, v1.0
- Zvks, Zvksc, Zvksg extension, v1.0
- - Zilsd extension, v0.9.0
- - Zcmlsd extension, v0.9.0
+ - Zicond extension, v1.0
+ - Zilsd extension, v1.0
+ - Zclsd extension, v1.0
+ - Zimop extension, v1.0
Versioning and APIs
-------------------
diff --git a/ci-tests/atomics.c b/ci-tests/atomics.c
new file mode 100644
index 0000000..ece5a38
--- /dev/null
+++ b/ci-tests/atomics.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <stdatomic.h>
+
+atomic_int acnt = 0;
+atomic_int bcnt = 0;
+
+int foo() {
+ for(int n = 0; n < 1000; ++n) {
+ ++acnt;
+ if(acnt % 10 == 0)
+ ++bcnt;
+ }
+ return acnt;
+}
+
+int main(void) {
+ int acnt = foo();
+ printf("First atomic counter is %u, second is %u\n", acnt, bcnt);
+ return 0;
+}
diff --git a/ci-tests/build-spike b/ci-tests/build-spike
index 058defd..0a1b315 100755
--- a/ci-tests/build-spike
+++ b/ci-tests/build-spike
@@ -8,10 +8,10 @@ rm -rf build
mkdir build
cd build
mkdir install
-CXXFLAGS="-Wnon-virtual-dtor" CFLAGS="-Werror -Wignored-qualifiers -Wunused-function -Wunused-parameter -Wunused-variable" $DIR/../configure --prefix=`pwd`/install
+CXXFLAGS="-Wnon-virtual-dtor" CFLAGS="-Werror -Wall -Wextra -Wvla" $DIR/../configure --prefix=`pwd`/install
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
make check
-make install
+make install install-hdrs-list.h
# check that help message prints without error
install/bin/spike -h
diff --git a/ci-tests/create-ci-binary-tarball b/ci-tests/create-ci-binary-tarball
index abc9ee0..1080d0a 100755
--- a/ci-tests/create-ci-binary-tarball
+++ b/ci-tests/create-ci-binary-tarball
@@ -4,7 +4,7 @@ set -e
rm -rf build
mkdir -p build/pk && cd "$_"
-`git rev-parse --show-toplevel`/../riscv-pk/configure --host=riscv64-unknown-elf
+`git rev-parse --show-toplevel`/../riscv-pk/configure --host=riscv64-unknown-elf --with-arch=rv64gc_zifencei
make -j4
cd -
@@ -16,9 +16,20 @@ mkdir -p build/dummy-slliuw && cd "$_"
riscv64-unknown-elf-gcc -O2 -o dummy-slliuw `git rev-parse --show-toplevel`/ci-tests/dummy-slliuw.c
cd -
+mkdir -p build/dummycsr && cd "$_"
+riscv64-unknown-elf-gcc -O2 -o customcsr `git rev-parse --show-toplevel`/ci-tests/customcsr.c
+cd -
+
+mkdir -p build/atomics && cd "$_"
+riscv64-unknown-elf-gcc -O2 -o atomics `git rev-parse --show-toplevel`/ci-tests/atomics.c
+cd -
+
+
mv build/pk/pk .
mv build/hello/hello .
mv build/dummy-slliuw/dummy-slliuw .
-tar -cf spike-ci.tar pk hello dummy-slliuw
+mv build/dummycsr/customcsr .
+mv build/atomics/atomics .
+tar -cf spike-ci.tar pk hello dummy-slliuw customcsr atomics
-rm pk hello dummy-slliuw
+rm pk hello dummy-slliuw customcsr atomics
diff --git a/ci-tests/custom-csr.cc b/ci-tests/custom-csr.cc
new file mode 100644
index 0000000..857c9c3
--- /dev/null
+++ b/ci-tests/custom-csr.cc
@@ -0,0 +1,82 @@
+#include <riscv/extension.h>
+#include <riscv/sim.h>
+
+
+class dummycsr_t: public csr_t {
+ public:
+ dummycsr_t(processor_t *proc, const reg_t addr): csr_t(proc, addr) {}
+
+ reg_t read() const noexcept override {
+ return 42;
+ }
+
+ void verify_permissions(insn_t insn, bool write) const override {}
+
+ protected:
+ bool unlogged_write(const reg_t val) noexcept override {
+ return true;
+ }
+};
+
+// dummy extension with dummy CSRs. Nice.
+struct xdummycsr_t : public extension_t {
+ const char *name() const override { return "dummycsr"; }
+
+ xdummycsr_t() {}
+
+ std::vector<insn_desc_t> get_instructions(const processor_t &) override {
+ return {};
+ }
+
+ std::vector<disasm_insn_t *> get_disasms(const processor_t *) override {
+ return {};
+ }
+
+ std::vector<csr_t_p> get_csrs(processor_t &proc) const override {
+ return {std::make_shared<dummycsr_t>(&proc, /*Addr*/ 0xfff)};
+ }
+};
+
+REGISTER_EXTENSION(dummycsr, []() { return new xdummycsr_t; })
+
+// Copied from spike main.
+// TODO: This should really be provided in libriscv
+static std::vector<std::pair<reg_t, abstract_mem_t *>>
+make_mems(const std::vector<mem_cfg_t> &layout) {
+ std::vector<std::pair<reg_t, abstract_mem_t *>> mems;
+ mems.reserve(layout.size());
+ for (const auto &cfg : layout) {
+ mems.push_back(std::make_pair(cfg.get_base(), new mem_t(cfg.get_size())));
+ }
+ return mems;
+}
+
+int main(int argc, char **argv) {
+ cfg_t cfg;
+ cfg.isa = "RV64IMAFDCV_Zicsr_xdummycsr";
+ std::vector<device_factory_sargs_t> plugin_devices;
+ if (argc != 3) {
+ std::cerr << "Error: invalid arguments\n";
+ exit(1);
+ }
+ std::vector<std::string> htif_args{argv[1] /* pk */, argv[2] /* executable */};
+ debug_module_config_t dm_config = {.progbufsize = 2,
+ .max_sba_data_width = 0,
+ .require_authentication = false,
+ .abstract_rti = 0,
+ .support_hasel = true,
+ .support_abstract_csr_access = true,
+ .support_abstract_fpr_access = true,
+ .support_haltgroups = true,
+ .support_impebreak = true};
+ std::vector<std::pair<reg_t, abstract_mem_t *>> mems =
+ make_mems(cfg.mem_layout);
+ sim_t sim(&cfg, false, mems, plugin_devices, htif_args, dm_config,
+ nullptr, // log_path
+ true, // dtb_enabled
+ nullptr, // dtb_file
+ false, // socket_enabled
+ nullptr, // cmd_file
+ std::nullopt); // instruction_limit
+ sim.run();
+}
diff --git a/ci-tests/customcsr.c b/ci-tests/customcsr.c
new file mode 100644
index 0000000..7d02689
--- /dev/null
+++ b/ci-tests/customcsr.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+int main() {
+ int x = 1;
+ // dummycsr
+ asm("csrr %0, 0xfff" : "=r"(x));
+ if (x == 42)
+ printf("Executed successfully\n");
+ else
+ printf("FAIL. Got value: %d instead of 42\n", x);
+ return 0;
+}
diff --git a/ci-tests/test-customext.cc b/ci-tests/test-customext.cc
index e493811..77c739f 100644
--- a/ci-tests/test-customext.cc
+++ b/ci-tests/test-customext.cc
@@ -26,11 +26,11 @@ static reg_t do_nop4([[maybe_unused]] processor_t *p,
// dummy extension that uses the same prefix as standard zba extension
struct xslliuw_dummy_t : public extension_t {
- const char *name() { return "dummyslliuw"; }
+ const char *name() const { return "dummyslliuw"; }
xslliuw_dummy_t() {}
- std::vector<insn_desc_t> get_instructions() {
+ std::vector<insn_desc_t> get_instructions(const processor_t &) {
std::vector<insn_desc_t> insns;
insns.push_back(insn_desc_t{MATCH_SLLI_UW, MASK_SLLI_UW, do_nop4, do_nop4,
do_nop4, do_nop4, do_nop4, do_nop4, do_nop4,
@@ -38,7 +38,7 @@ struct xslliuw_dummy_t : public extension_t {
return insns;
}
- std::vector<disasm_insn_t *> get_disasms() {
+ std::vector<disasm_insn_t *> get_disasms(const processor_t *) {
std::vector<disasm_insn_t *> insns;
insns.push_back(new disasm_insn_t("dummy_slliuw", MATCH_SLLI_UW,
MASK_SLLI_UW, {&xrd, &xrs1, &shamt}));
@@ -85,6 +85,7 @@ int main(int argc, char **argv) {
true, // dtb_enabled
nullptr, // dtb_file
false, // socket_enabled
- nullptr); // cmd_file
+ nullptr, // cmd_file
+ std::nullopt); // instruction_limit
sim.run();
}
diff --git a/ci-tests/test-spike b/ci-tests/test-spike
index 0540739..6fe5bdb 100755
--- a/ci-tests/test-spike
+++ b/ci-tests/test-spike
@@ -11,10 +11,16 @@ cd run
wget https://github.com/riscv-software-src/riscv-isa-sim/releases/download/dummy-tag-for-ci-storage/spike-ci.tar
tar xf spike-ci.tar
time ../install/bin/spike --isa=rv64gc pk hello | grep "Hello, world! Pi is approximately 3.141588."
+../install/bin/spike --log-commits --isa=rv64gc pk atomics | grep "First atomic counter is 1000, second is 100"
# check that including sim.h in an external project works
-g++ -std=c++17 -I../install/include -L../install/lib $DIR/testlib.c -lriscv -o test-libriscv
-g++ -std=c++17 -I../install/include -L../install/lib $DIR/test-customext.cc -lriscv -o test-customext
+g++ -std=c++2a -I../install/include -L../install/lib $DIR/testlib.cc -lriscv -o test-libriscv
+g++ -std=c++2a -I../install/include -L../install/lib $DIR/test-customext.cc -lriscv -o test-customext
+g++ -std=c++2a -I../install/include -L../install/lib $DIR/custom-csr.cc -lriscv -o test-custom-csr
+
+# check that all installed headers are functional
+g++ -std=c++2a -I../install/include -L../install/lib $DIR/testlib.cc -lriscv -o /dev/null -include ../install-hdrs-list.h
LD_LIBRARY_PATH=../install/lib ./test-libriscv pk hello| grep "Hello, world! Pi is approximately 3.141588."
LD_LIBRARY_PATH=../install/lib ./test-customext pk dummy-slliuw | grep "Executed successfully"
+LD_LIBRARY_PATH=../install/lib ./test-custom-csr pk customcsr | grep "Executed successfully"
diff --git a/ci-tests/testlib.c b/ci-tests/testlib.cc
index 6bc0886..eb91d97 100644
--- a/ci-tests/testlib.c
+++ b/ci-tests/testlib.cc
@@ -34,6 +34,7 @@ int main(int argc, char **argv) {
true,
nullptr,
false,
- nullptr);
+ nullptr,
+ std::nullopt);
sim.run();
}
diff --git a/config.h.in b/config.h.in
index aef3596..e1f8734 100644
--- a/config.h.in
+++ b/config.h.in
@@ -6,12 +6,6 @@
/* Define if subproject MCPPBS_SPROJ_NORM is enabled */
#undef CUSTOMEXT_ENABLED
-/* Default value for --isa switch */
-#undef DEFAULT_ISA
-
-/* Default value for --priv switch */
-#undef DEFAULT_PRIV
-
/* Define if subproject MCPPBS_SPROJ_NORM is enabled */
#undef DISASM_ENABLED
@@ -42,18 +36,15 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
-/* Define to 1 if you have the `boost_regex' library (-lboost_regex). */
+/* Define to 1 if you have the 'boost_regex' library (-lboost_regex). */
#undef HAVE_LIBBOOST_REGEX
-/* Define to 1 if you have the `boost_system' library (-lboost_system). */
+/* Define to 1 if you have the 'boost_system' library (-lboost_system). */
#undef HAVE_LIBBOOST_SYSTEM
-/* Define to 1 if you have the `pthread' library (-lpthread). */
+/* Define to 1 if you have the 'pthread' library (-lpthread). */
#undef HAVE_LIBPTHREAD
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
/* Define to 1 if struct statx exists. */
#undef HAVE_STATX
@@ -63,6 +54,9 @@
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
@@ -114,7 +108,9 @@
/* Define if subproject MCPPBS_SPROJ_NORM is enabled */
#undef SPIKE_MAIN_ENABLED
-/* Define to 1 if you have the ANSI C header files. */
+/* Define to 1 if all of the C89 standard headers exist (not just the ones
+ required in a freestanding environment). This macro is provided for
+ backward compatibility; new code need not use it. */
#undef STDC_HEADERS
/* Default value for --target switch */
diff --git a/configure b/configure
index 4ad998a..7c10ebd 100755
--- a/configure
+++ b/configure
@@ -1,11 +1,11 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.71 for RISC-V ISA Simulator ?.
+# Generated by GNU Autoconf 2.72 for RISC-V ISA Simulator ?.
#
# Report bugs to <Andrew Waterman>.
#
#
-# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
+# Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation,
# Inc.
#
#
@@ -17,7 +17,6 @@
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-as_nop=:
if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
emulate sh
@@ -26,12 +25,13 @@ then :
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else $as_nop
- case `(set -o) 2>/dev/null` in #(
+else case e in #(
+ e) case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
*) :
;;
+esac ;;
esac
fi
@@ -103,7 +103,7 @@ IFS=$as_save_IFS
;;
esac
-# We did not find ourselves, most probably we were run as `sh COMMAND'
+# We did not find ourselves, most probably we were run as 'sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
as_myself=$0
@@ -133,15 +133,14 @@ case $- in # ((((
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
-# out after a failed `exec'.
+# out after a failed 'exec'.
printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
# We don't want this to propagate to other subprocesses.
{ _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
- as_bourne_compatible="as_nop=:
-if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+ as_bourne_compatible="if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
emulate sh
NULLCMD=:
@@ -149,12 +148,13 @@ then :
# is contrary to our usage. Disable this feature.
alias -g '\${1+\"\$@\"}'='\"\$@\"'
setopt NO_GLOB_SUBST
-else \$as_nop
- case \`(set -o) 2>/dev/null\` in #(
+else case e in #(
+ e) case \`(set -o) 2>/dev/null\` in #(
*posix*) :
set -o posix ;; #(
*) :
;;
+esac ;;
esac
fi
"
@@ -172,8 +172,9 @@ as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
if ( set x; as_fn_ret_success y && test x = \"\$1\" )
then :
-else \$as_nop
- exitcode=1; echo positional parameters were not saved.
+else case e in #(
+ e) exitcode=1; echo positional parameters were not saved. ;;
+esac
fi
test x\$exitcode = x0 || exit 1
blah=\$(echo \$(echo blah))
@@ -182,19 +183,19 @@ test -x / || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
- test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
-test \$(( 1 + 1 )) = 2 || exit 1"
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
if (eval "$as_required") 2>/dev/null
then :
as_have_required=yes
-else $as_nop
- as_have_required=no
+else case e in #(
+ e) as_have_required=no ;;
+esac
fi
if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
then :
-else $as_nop
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+else case e in #(
+ e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
@@ -227,12 +228,13 @@ IFS=$as_save_IFS
if $as_found
then :
-else $as_nop
- if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+else case e in #(
+ e) if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
then :
CONFIG_SHELL=$SHELL as_have_required=yes
-fi
+fi ;;
+esac
fi
@@ -254,7 +256,7 @@ case $- in # ((((
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
-# out after a failed `exec'.
+# out after a failed 'exec'.
printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
@@ -274,7 +276,8 @@ $0: manually run the script under such a shell if you do
$0: have one."
fi
exit 1
-fi
+fi ;;
+esac
fi
fi
SHELL=${CONFIG_SHELL-/bin/sh}
@@ -313,14 +316,6 @@ as_fn_exit ()
as_fn_set_status $1
exit $1
} # as_fn_exit
-# as_fn_nop
-# ---------
-# Do nothing but, unlike ":", preserve the value of $?.
-as_fn_nop ()
-{
- return $?
-}
-as_nop=as_fn_nop
# as_fn_mkdir_p
# -------------
@@ -389,11 +384,12 @@ then :
{
eval $1+=\$2
}'
-else $as_nop
- as_fn_append ()
+else case e in #(
+ e) as_fn_append ()
{
eval $1=\$$1\$2
- }
+ } ;;
+esac
fi # as_fn_append
# as_fn_arith ARG...
@@ -407,21 +403,14 @@ then :
{
as_val=$(( $* ))
}'
-else $as_nop
- as_fn_arith ()
+else case e in #(
+ e) as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
- }
+ } ;;
+esac
fi # as_fn_arith
-# as_fn_nop
-# ---------
-# Do nothing but, unlike ":", preserve the value of $?.
-as_fn_nop ()
-{
- return $?
-}
-as_nop=as_fn_nop
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
@@ -495,6 +484,8 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
/[$]LINENO/=
' <$as_myself |
sed '
+ t clear
+ :clear
s/[$]LINENO.*/&-/
t lineno
b
@@ -543,7 +534,6 @@ esac
as_echo='printf %s\n'
as_echo_n='printf %s'
-
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -555,9 +545,9 @@ if (echo >conf$$.file) 2>/dev/null; then
if ln -s conf$$.file conf$$ 2>/dev/null; then
as_ln_s='ln -s'
# ... but there are two gotchas:
- # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
- # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
- # In both cases, we have to default to `cp -pR'.
+ # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.
+ # In both cases, we have to default to 'cp -pR'.
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
as_ln_s='cp -pR'
elif ln conf$$.file conf$$ 2>/dev/null; then
@@ -582,10 +572,12 @@ as_test_x='test -x'
as_executable_p=as_fn_executable_p
# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated
# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+as_tr_sh="eval sed '$as_sed_sh'" # deprecated
test -n "$DJDIR" || exec 7<&0 </dev/null
@@ -660,8 +652,6 @@ BOOST_LDFLAGS
BOOST_CPPFLAGS
HAVE_CLANG_PCH
HAVE_INT128
-EGREP
-GREP
INSTALL_DATA
INSTALL_SCRIPT
INSTALL_PROGRAM
@@ -737,8 +727,6 @@ with_boost
with_boost_libdir
with_boost_asio
with_boost_regex
-with_isa
-with_priv
with_target
enable_dual_endian
'
@@ -863,7 +851,7 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: \`$ac_useropt'"
+ as_fn_error $? "invalid feature name: '$ac_useropt'"
ac_useropt_orig=$ac_useropt
ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
@@ -889,7 +877,7 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: \`$ac_useropt'"
+ as_fn_error $? "invalid feature name: '$ac_useropt'"
ac_useropt_orig=$ac_useropt
ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
@@ -1102,7 +1090,7 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: \`$ac_useropt'"
+ as_fn_error $? "invalid package name: '$ac_useropt'"
ac_useropt_orig=$ac_useropt
ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
@@ -1118,7 +1106,7 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: \`$ac_useropt'"
+ as_fn_error $? "invalid package name: '$ac_useropt'"
ac_useropt_orig=$ac_useropt
ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
@@ -1148,8 +1136,8 @@ do
| --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
x_libraries=$ac_optarg ;;
- -*) as_fn_error $? "unrecognized option: \`$ac_option'
-Try \`$0 --help' for more information"
+ -*) as_fn_error $? "unrecognized option: '$ac_option'
+Try '$0 --help' for more information"
;;
*=*)
@@ -1157,7 +1145,7 @@ Try \`$0 --help' for more information"
# Reject names that are not valid shell variable names.
case $ac_envvar in #(
'' | [0-9]* | *[!_$as_cr_alnum]* )
- as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ as_fn_error $? "invalid variable name: '$ac_envvar'" ;;
esac
eval $ac_envvar=\$ac_optarg
export $ac_envvar ;;
@@ -1207,7 +1195,7 @@ do
as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
done
-# There might be people who depend on the old broken behavior: `$host'
+# There might be people who depend on the old broken behavior: '$host'
# used to hold the argument of --host etc.
# FIXME: To remove some day.
build=$build_alias
@@ -1275,7 +1263,7 @@ if test ! -r "$srcdir/$ac_unique_file"; then
test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
fi
-ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_msg="sources are in $srcdir, but 'cd $srcdir' does not work"
ac_abs_confdir=`(
cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
pwd)`
@@ -1303,7 +1291,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures RISC-V ISA Simulator ? to adapt to many kinds of systems.
+'configure' configures RISC-V ISA Simulator ? to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1317,11 +1305,11 @@ Configuration:
--help=short display options specific to this package
--help=recursive display the short help of all the included packages
-V, --version display version information and exit
- -q, --quiet, --silent do not print \`checking ...' messages
+ -q, --quiet, --silent do not print 'checking ...' messages
--cache-file=FILE cache test results in FILE [disabled]
- -C, --config-cache alias for \`--cache-file=config.cache'
+ -C, --config-cache alias for '--cache-file=config.cache'
-n, --no-create do not create output files
- --srcdir=DIR find the sources in DIR [configure dir or \`..']
+ --srcdir=DIR find the sources in DIR [configure dir or '..']
Installation directories:
--prefix=PREFIX install architecture-independent files in PREFIX
@@ -1329,10 +1317,10 @@ Installation directories:
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
[PREFIX]
-By default, \`make install' will install all the files in
-\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
-an installation prefix other than \`$ac_default_prefix' using \`--prefix',
-for instance \`--prefix=\$HOME'.
+By default, 'make install' will install all the files in
+'$ac_default_prefix/bin', '$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than '$ac_default_prefix' using '--prefix',
+for instance '--prefix=\$HOME'.
For better control, use the options below.
@@ -1403,9 +1391,6 @@ Optional Packages:
use the Regex library from boost - it is possible to
specify a certain library for the linker e.g.
--with-boost-regex=boost_regex-gcc-mt-d-1_33_1
- --with-isa=RV64IMAFDC_zicntr_zihpm
- Sets the default RISC-V ISA
- --with-priv=MSU Sets the default RISC-V privilege modes supported
--with-target=riscv64-unknown-elf
Sets the default target config
@@ -1422,7 +1407,7 @@ Some influential environment variables:
STOW_ROOT Root for non-native stow-based installs
STOW_PREFIX Prefix for stow-based installs
-Use these variables to override the choices made by `configure' or to help
+Use these variables to override the choices made by 'configure' or to help
it to find libraries and programs with nonstandard names/locations.
Report bugs to <Andrew Waterman>.
@@ -1490,9 +1475,9 @@ test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
RISC-V ISA Simulator configure ?
-generated by GNU Autoconf 2.71
+generated by GNU Autoconf 2.72
-Copyright (C) 2021 Free Software Foundation, Inc.
+Copyright (C) 2023 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
@@ -1531,11 +1516,12 @@ printf "%s\n" "$ac_try_echo"; } >&5
} && test -s conftest.$ac_objext
then :
ac_retval=0
-else $as_nop
- printf "%s\n" "$as_me: failed program was:" >&5
+else case e in #(
+ e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
- ac_retval=1
+ ac_retval=1 ;;
+esac
fi
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
@@ -1570,17 +1556,66 @@ printf "%s\n" "$ac_try_echo"; } >&5
} && test -s conftest.$ac_objext
then :
ac_retval=0
-else $as_nop
- printf "%s\n" "$as_me: failed program was:" >&5
+else case e in #(
+ e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
- ac_retval=1
+ ac_retval=1 ;;
+esac
fi
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_cxx_try_compile
+# ac_fn_cxx_try_link LINENO
+# -------------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }
+then :
+ ac_retval=0
+else case e in #(
+ e) printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1 ;;
+esac
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_link
+
# ac_fn_cxx_try_run LINENO
# ------------------------
# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
@@ -1611,12 +1646,13 @@ printf "%s\n" "$ac_try_echo"; } >&5
test $ac_status = 0; }; }
then :
ac_retval=0
-else $as_nop
- printf "%s\n" "$as_me: program exited with status $ac_status" >&5
+else case e in #(
+ e) printf "%s\n" "$as_me: program exited with status $ac_status" >&5
printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
- ac_retval=$ac_status
+ ac_retval=$ac_status ;;
+esac
fi
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
@@ -1636,8 +1672,8 @@ printf %s "checking for $2... " >&6; }
if eval test \${$3+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
#include <$2>
@@ -1645,10 +1681,12 @@ _ACEOF
if ac_fn_cxx_try_compile "$LINENO"
then :
eval "$3=yes"
-else $as_nop
- eval "$3=no"
+else case e in #(
+ e) eval "$3=no" ;;
+esac
fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
fi
eval ac_res=\$$3
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
@@ -1669,8 +1707,8 @@ printf %s "checking for $2... " >&6; }
if eval test \${$3+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- eval "$3=no"
+else case e in #(
+ e) eval "$3=no"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
@@ -1700,12 +1738,14 @@ _ACEOF
if ac_fn_cxx_try_compile "$LINENO"
then :
-else $as_nop
- eval "$3=yes"
+else case e in #(
+ e) eval "$3=yes" ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
fi
eval ac_res=\$$3
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
@@ -1714,53 +1754,6 @@ printf "%s\n" "$ac_res" >&6; }
} # ac_fn_cxx_check_type
-# ac_fn_cxx_try_link LINENO
-# -------------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded.
-ac_fn_cxx_try_link ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
- if { { ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-printf "%s\n" "$ac_try_echo"; } >&5
- (eval "$ac_link") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- grep -v '^ *+' conftest.err >conftest.er1
- cat conftest.er1 >&5
- mv -f conftest.er1 conftest.err
- fi
- printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && {
- test -z "$ac_cxx_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- test -x conftest$ac_exeext
- }
-then :
- ac_retval=0
-else $as_nop
- printf "%s\n" "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=1
-fi
- # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
- # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
- # interfere with the next link command; also delete a directory that is
- # left behind by Apple's compiler. We do this before executing the actions.
- rm -rf conftest.dSYM conftest_ipa8_conftest.oo
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_cxx_try_link
-
# ac_fn_cxx_check_member LINENO AGGR MEMBER VAR INCLUDES
# ------------------------------------------------------
# Tries to find if the field MEMBER exists in type AGGR, after including
@@ -1773,8 +1766,8 @@ printf %s "checking for $2.$3... " >&6; }
if eval test \${$4+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$5
int
@@ -1790,8 +1783,8 @@ _ACEOF
if ac_fn_cxx_try_compile "$LINENO"
then :
eval "$4=yes"
-else $as_nop
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$5
int
@@ -1807,12 +1800,15 @@ _ACEOF
if ac_fn_cxx_try_compile "$LINENO"
then :
eval "$4=yes"
-else $as_nop
- eval "$4=no"
+else case e in #(
+ e) eval "$4=no" ;;
+esac
fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
fi
eval ac_res=\$$4
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
@@ -1845,7 +1841,7 @@ This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by RISC-V ISA Simulator $as_me ?, which was
-generated by GNU Autoconf 2.71. Invocation command line was
+generated by GNU Autoconf 2.72. Invocation command line was
$ $0$ac_configure_args_raw
@@ -2091,10 +2087,10 @@ esac
printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file" \
- || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
-See \`config.log' for more details" "$LINENO" 5; }
+See 'config.log' for more details" "$LINENO" 5; }
fi
done
@@ -2130,9 +2126,7 @@ struct stat;
/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */
struct buf { int x; };
struct buf * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
+static char *e (char **p, int i)
{
return p[i];
}
@@ -2146,6 +2140,21 @@ static char *f (char * (*g) (char **, int), char **p, ...)
return s;
}
+/* C89 style stringification. */
+#define noexpand_stringify(a) #a
+const char *stringified = noexpand_stringify(arbitrary+token=sequence);
+
+/* C89 style token pasting. Exercises some of the corner cases that
+ e.g. old MSVC gets wrong, but not very hard. */
+#define noexpand_concat(a,b) a##b
+#define expand_concat(a,b) noexpand_concat(a,b)
+extern int vA;
+extern int vbee;
+#define aye A
+#define bee B
+int *pvA = &expand_concat(v,aye);
+int *pvbee = &noexpand_concat(v,bee);
+
/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
function prototypes and stuff, but not \xHH hex character constants.
These do not provoke an error unfortunately, instead are silently treated
@@ -2173,16 +2182,19 @@ ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
# Test code for whether the C compiler supports C99 (global declarations)
ac_c_conftest_c99_globals='
-// Does the compiler advertise C99 conformance?
+/* Does the compiler advertise C99 conformance? */
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
# error "Compiler does not advertise C99 conformance"
#endif
+// See if C++-style comments work.
+
#include <stdbool.h>
extern int puts (const char *);
extern int printf (const char *, ...);
extern int dprintf (int, const char *, ...);
extern void *malloc (size_t);
+extern void free (void *);
// Check varargs macros. These examples are taken from C99 6.10.3.5.
// dprintf is used instead of fprintf to avoid needing to declare
@@ -2232,7 +2244,6 @@ typedef const char *ccp;
static inline int
test_restrict (ccp restrict text)
{
- // See if C++-style comments work.
// Iterate through items via the restricted pointer.
// Also check for declarations in for loops.
for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
@@ -2298,6 +2309,8 @@ ac_c_conftest_c99_main='
ia->datasize = 10;
for (int i = 0; i < ia->datasize; ++i)
ia->data[i] = i * 1.234;
+ // Work around memory leak warnings.
+ free (ia);
// Check named initializers.
struct named_init ni = {
@@ -2319,7 +2332,7 @@ ac_c_conftest_c99_main='
# Test code for whether the C compiler supports C11 (global declarations)
ac_c_conftest_c11_globals='
-// Does the compiler advertise C11 conformance?
+/* Does the compiler advertise C11 conformance? */
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
# error "Compiler does not advertise C11 conformance"
#endif
@@ -2727,8 +2740,9 @@ IFS=$as_save_IFS
if $as_found
then :
-else $as_nop
- as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
+else case e in #(
+ e) as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 ;;
+esac
fi
@@ -2756,12 +2770,12 @@ for ac_var in $ac_precious_vars; do
eval ac_new_val=\$ac_env_${ac_var}_value
case $ac_old_set,$ac_new_set in
set,)
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&5
+printf "%s\n" "$as_me: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&2;}
ac_cache_corrupted=: ;;
,set)
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
-printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was not set in the previous run" >&5
+printf "%s\n" "$as_me: error: '$ac_var' was not set in the previous run" >&2;}
ac_cache_corrupted=: ;;
,);;
*)
@@ -2770,18 +2784,18 @@ printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_old_val_w=`echo x $ac_old_val`
ac_new_val_w=`echo x $ac_new_val`
if test "$ac_old_val_w" != "$ac_new_val_w"; then
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
-printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' has changed since the previous run:" >&5
+printf "%s\n" "$as_me: error: '$ac_var' has changed since the previous run:" >&2;}
ac_cache_corrupted=:
else
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
-printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&5
+printf "%s\n" "$as_me: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&2;}
eval $ac_var=\$ac_old_val
fi
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
-printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;}
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
-printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: '$ac_old_val'" >&5
+printf "%s\n" "$as_me: former value: '$ac_old_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: '$ac_new_val'" >&5
+printf "%s\n" "$as_me: current value: '$ac_new_val'" >&2;}
fi;;
esac
# Pass precious variables to config.status.
@@ -2797,11 +2811,11 @@ printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;}
fi
done
if $ac_cache_corrupted; then
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
- as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
+ as_fn_error $? "run '${MAKE-make} distclean' and/or 'rm $cache_file'
and start over" "$LINENO" 5
fi
## -------------------- ##
@@ -2835,15 +2849,16 @@ printf %s "checking build system type... " >&6; }
if test ${ac_cv_build+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_build_alias=$build_alias
+else case e in #(
+ e) ac_build_alias=$build_alias
test "x$ac_build_alias" = x &&
ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
test "x$ac_build_alias" = x &&
as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
-
+ ;;
+esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
printf "%s\n" "$ac_cv_build" >&6; }
@@ -2870,14 +2885,15 @@ printf %s "checking host system type... " >&6; }
if test ${ac_cv_host+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- if test "x$host_alias" = x; then
+else case e in #(
+ e) if test "x$host_alias" = x; then
ac_cv_host=$ac_cv_build
else
ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
fi
-
+ ;;
+esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
printf "%s\n" "$ac_cv_host" >&6; }
@@ -3004,7 +3020,7 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
# and this notice are preserved. This file is offered as-is, without any
# warranty.
-#serial 6
+#serial 11
# ===========================================================================
@@ -3096,10 +3112,10 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
#
# Test for the Boost C++ libraries of a particular version (or newer)
#
-# If no path to the installed boost library is given the macro searchs
-# under /usr, /usr/local, /opt and /opt/local and evaluates the
-# $BOOST_ROOT environment variable. Further documentation is available at
-# <http://randspringer.de/boost/index.html>.
+# If no path to the installed boost library is given the macro searches
+# under /usr, /usr/local, /opt, /opt/local and /opt/homebrew and evaluates
+# the $BOOST_ROOT environment variable. Further documentation is available
+# at <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
@@ -3119,7 +3135,7 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
# and this notice are preserved. This file is offered as-is, without any
# warranty.
-#serial 49
+#serial 55
# example boost program (need to pass version)
@@ -3231,8 +3247,8 @@ printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- if test -n "$CC"; then
+else case e in #(
+ e) if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -3254,7 +3270,8 @@ done
done
IFS=$as_save_IFS
-fi
+fi ;;
+esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
@@ -3276,8 +3293,8 @@ printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- if test -n "$ac_ct_CC"; then
+else case e in #(
+ e) if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -3299,7 +3316,8 @@ done
done
IFS=$as_save_IFS
-fi
+fi ;;
+esac
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
@@ -3334,8 +3352,8 @@ printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- if test -n "$CC"; then
+else case e in #(
+ e) if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -3357,7 +3375,8 @@ done
done
IFS=$as_save_IFS
-fi
+fi ;;
+esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
@@ -3379,8 +3398,8 @@ printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- if test -n "$CC"; then
+else case e in #(
+ e) if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
ac_prog_rejected=no
@@ -3419,7 +3438,8 @@ if test $ac_prog_rejected = yes; then
ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
fi
fi
-fi
+fi ;;
+esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
@@ -3443,8 +3463,8 @@ printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- if test -n "$CC"; then
+else case e in #(
+ e) if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -3466,7 +3486,8 @@ done
done
IFS=$as_save_IFS
-fi
+fi ;;
+esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
@@ -3492,8 +3513,8 @@ printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- if test -n "$ac_ct_CC"; then
+else case e in #(
+ e) if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -3515,7 +3536,8 @@ done
done
IFS=$as_save_IFS
-fi
+fi ;;
+esac
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
@@ -3553,8 +3575,8 @@ printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- if test -n "$CC"; then
+else case e in #(
+ e) if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -3576,7 +3598,8 @@ done
done
IFS=$as_save_IFS
-fi
+fi ;;
+esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
@@ -3598,8 +3621,8 @@ printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- if test -n "$ac_ct_CC"; then
+else case e in #(
+ e) if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -3621,7 +3644,8 @@ done
done
IFS=$as_save_IFS
-fi
+fi ;;
+esac
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
@@ -3650,10 +3674,10 @@ fi
fi
-test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
-See \`config.log' for more details" "$LINENO" 5; }
+See 'config.log' for more details" "$LINENO" 5; }
# Provide some information about the compiler.
printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
@@ -3725,8 +3749,8 @@ printf "%s\n" "$ac_try_echo"; } >&5
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
then :
- # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
-# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+ # Autoconf-2.13 could set the ac_cv_exeext variable to 'no'.
+# So ignore a value of 'no', otherwise this would lead to 'EXEEXT = no'
# in a Makefile. We should not override ac_cv_exeext if it was cached,
# so that the user can short-circuit this test for compilers unknown to
# Autoconf.
@@ -3746,7 +3770,7 @@ do
ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
fi
# We set ac_cv_exeext here because the later test for it is not
- # safe: cross compilers may not add the suffix if given an `-o'
+ # safe: cross compilers may not add the suffix if given an '-o'
# argument, so we may need to know it at that point already.
# Even if this section looks crufty: it has the advantage of
# actually working.
@@ -3757,8 +3781,9 @@ do
done
test "$ac_cv_exeext" = no && ac_cv_exeext=
-else $as_nop
- ac_file=''
+else case e in #(
+ e) ac_file='' ;;
+esac
fi
if test -z "$ac_file"
then :
@@ -3767,13 +3792,14 @@ printf "%s\n" "no" >&6; }
printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error 77 "C compiler cannot create executables
-See \`config.log' for more details" "$LINENO" 5; }
-else $as_nop
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-printf "%s\n" "yes" >&6; }
+See 'config.log' for more details" "$LINENO" 5; }
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; } ;;
+esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
printf %s "checking for C compiler default output file name... " >&6; }
@@ -3797,10 +3823,10 @@ printf "%s\n" "$ac_try_echo"; } >&5
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
then :
- # If both `conftest.exe' and `conftest' are `present' (well, observable)
-# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
-# work properly (i.e., refer to `conftest.exe'), while it won't with
-# `rm'.
+ # If both 'conftest.exe' and 'conftest' are 'present' (well, observable)
+# catch 'conftest.exe'. For instance with Cygwin, 'ls conftest' will
+# work properly (i.e., refer to 'conftest.exe'), while it won't with
+# 'rm'.
for ac_file in conftest.exe conftest conftest.*; do
test -f "$ac_file" || continue
case $ac_file in
@@ -3810,11 +3836,12 @@ for ac_file in conftest.exe conftest conftest.*; do
* ) break;;
esac
done
-else $as_nop
- { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+else case e in #(
+ e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details" "$LINENO" 5; }
+See 'config.log' for more details" "$LINENO" 5; } ;;
+esac
fi
rm -f conftest conftest$ac_cv_exeext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
@@ -3830,6 +3857,8 @@ int
main (void)
{
FILE *f = fopen ("conftest.out", "w");
+ if (!f)
+ return 1;
return ferror (f) || fclose (f) != 0;
;
@@ -3869,26 +3898,27 @@ printf "%s\n" "$ac_try_echo"; } >&5
if test "$cross_compiling" = maybe; then
cross_compiling=yes
else
- { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error 77 "cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details" "$LINENO" 5; }
+If you meant to cross compile, use '--host'.
+See 'config.log' for more details" "$LINENO" 5; }
fi
fi
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
printf "%s\n" "$cross_compiling" >&6; }
-rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+rm -f conftest.$ac_ext conftest$ac_cv_exeext \
+ conftest.o conftest.obj conftest.out
ac_clean_files=$ac_clean_files_save
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
printf %s "checking for suffix of object files... " >&6; }
if test ${ac_cv_objext+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -3920,16 +3950,18 @@ then :
break;;
esac
done
-else $as_nop
- printf "%s\n" "$as_me: failed program was:" >&5
+else case e in #(
+ e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
-See \`config.log' for more details" "$LINENO" 5; }
+See 'config.log' for more details" "$LINENO" 5; } ;;
+esac
fi
-rm -f conftest.$ac_cv_objext conftest.$ac_ext
+rm -f conftest.$ac_cv_objext conftest.$ac_ext ;;
+esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
printf "%s\n" "$ac_cv_objext" >&6; }
@@ -3940,8 +3972,8 @@ printf %s "checking whether the compiler supports GNU C... " >&6; }
if test ${ac_cv_c_compiler_gnu+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -3958,12 +3990,14 @@ _ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_compiler_gnu=yes
-else $as_nop
- ac_compiler_gnu=no
+else case e in #(
+ e) ac_compiler_gnu=no ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
-
+ ;;
+esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
@@ -3981,8 +4015,8 @@ printf %s "checking whether $CC accepts -g... " >&6; }
if test ${ac_cv_prog_cc_g+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_save_c_werror_flag=$ac_c_werror_flag
+else case e in #(
+ e) ac_save_c_werror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
ac_cv_prog_cc_g=no
CFLAGS="-g"
@@ -4000,8 +4034,8 @@ _ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_prog_cc_g=yes
-else $as_nop
- CFLAGS=""
+else case e in #(
+ e) CFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -4016,8 +4050,8 @@ _ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
-else $as_nop
- ac_c_werror_flag=$ac_save_c_werror_flag
+else case e in #(
+ e) ac_c_werror_flag=$ac_save_c_werror_flag
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -4034,12 +4068,15 @@ if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_prog_cc_g=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
- ac_c_werror_flag=$ac_save_c_werror_flag
+ ac_c_werror_flag=$ac_save_c_werror_flag ;;
+esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
@@ -4066,8 +4103,8 @@ printf %s "checking for $CC option to enable C11 features... " >&6; }
if test ${ac_cv_prog_cc_c11+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_cv_prog_cc_c11=no
+else case e in #(
+ e) ac_cv_prog_cc_c11=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -4084,25 +4121,28 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c11" != "xno" && break
done
rm -f conftest.$ac_ext
-CC=$ac_save_CC
+CC=$ac_save_CC ;;
+esac
fi
if test "x$ac_cv_prog_cc_c11" = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
-else $as_nop
- if test "x$ac_cv_prog_cc_c11" = x
+else case e in #(
+ e) if test "x$ac_cv_prog_cc_c11" = x
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
-else $as_nop
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
- CC="$CC $ac_cv_prog_cc_c11"
+ CC="$CC $ac_cv_prog_cc_c11" ;;
+esac
fi
ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
- ac_prog_cc_stdc=c11
+ ac_prog_cc_stdc=c11 ;;
+esac
fi
fi
if test x$ac_prog_cc_stdc = xno
@@ -4112,8 +4152,8 @@ printf %s "checking for $CC option to enable C99 features... " >&6; }
if test ${ac_cv_prog_cc_c99+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_cv_prog_cc_c99=no
+else case e in #(
+ e) ac_cv_prog_cc_c99=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -4130,25 +4170,28 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c99" != "xno" && break
done
rm -f conftest.$ac_ext
-CC=$ac_save_CC
+CC=$ac_save_CC ;;
+esac
fi
if test "x$ac_cv_prog_cc_c99" = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
-else $as_nop
- if test "x$ac_cv_prog_cc_c99" = x
+else case e in #(
+ e) if test "x$ac_cv_prog_cc_c99" = x
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
-else $as_nop
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
- CC="$CC $ac_cv_prog_cc_c99"
+ CC="$CC $ac_cv_prog_cc_c99" ;;
+esac
fi
ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
- ac_prog_cc_stdc=c99
+ ac_prog_cc_stdc=c99 ;;
+esac
fi
fi
if test x$ac_prog_cc_stdc = xno
@@ -4158,8 +4201,8 @@ printf %s "checking for $CC option to enable C89 features... " >&6; }
if test ${ac_cv_prog_cc_c89+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_cv_prog_cc_c89=no
+else case e in #(
+ e) ac_cv_prog_cc_c89=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -4176,25 +4219,28 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
-CC=$ac_save_CC
+CC=$ac_save_CC ;;
+esac
fi
if test "x$ac_cv_prog_cc_c89" = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
-else $as_nop
- if test "x$ac_cv_prog_cc_c89" = x
+else case e in #(
+ e) if test "x$ac_cv_prog_cc_c89" = x
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
-else $as_nop
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
- CC="$CC $ac_cv_prog_cc_c89"
+ CC="$CC $ac_cv_prog_cc_c89" ;;
+esac
fi
ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
- ac_prog_cc_stdc=c89
+ ac_prog_cc_stdc=c89 ;;
+esac
fi
fi
@@ -4229,8 +4275,8 @@ printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CXX+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- if test -n "$CXX"; then
+else case e in #(
+ e) if test -n "$CXX"; then
ac_cv_prog_CXX="$CXX" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -4252,7 +4298,8 @@ done
done
IFS=$as_save_IFS
-fi
+fi ;;
+esac
fi
CXX=$ac_cv_prog_CXX
if test -n "$CXX"; then
@@ -4278,8 +4325,8 @@ printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CXX+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- if test -n "$ac_ct_CXX"; then
+else case e in #(
+ e) if test -n "$ac_ct_CXX"; then
ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -4301,7 +4348,8 @@ done
done
IFS=$as_save_IFS
-fi
+fi ;;
+esac
fi
ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
if test -n "$ac_ct_CXX"; then
@@ -4361,8 +4409,8 @@ printf %s "checking whether the compiler supports GNU C++... " >&6; }
if test ${ac_cv_cxx_compiler_gnu+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -4379,12 +4427,14 @@ _ACEOF
if ac_fn_cxx_try_compile "$LINENO"
then :
ac_compiler_gnu=yes
-else $as_nop
- ac_compiler_gnu=no
+else case e in #(
+ e) ac_compiler_gnu=no ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
-
+ ;;
+esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; }
@@ -4402,8 +4452,8 @@ printf %s "checking whether $CXX accepts -g... " >&6; }
if test ${ac_cv_prog_cxx_g+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+else case e in #(
+ e) ac_save_cxx_werror_flag=$ac_cxx_werror_flag
ac_cxx_werror_flag=yes
ac_cv_prog_cxx_g=no
CXXFLAGS="-g"
@@ -4421,8 +4471,8 @@ _ACEOF
if ac_fn_cxx_try_compile "$LINENO"
then :
ac_cv_prog_cxx_g=yes
-else $as_nop
- CXXFLAGS=""
+else case e in #(
+ e) CXXFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -4437,8 +4487,8 @@ _ACEOF
if ac_fn_cxx_try_compile "$LINENO"
then :
-else $as_nop
- ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+else case e in #(
+ e) ac_cxx_werror_flag=$ac_save_cxx_werror_flag
CXXFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -4455,12 +4505,15 @@ if ac_fn_cxx_try_compile "$LINENO"
then :
ac_cv_prog_cxx_g=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
- ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag ;;
+esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
printf "%s\n" "$ac_cv_prog_cxx_g" >&6; }
@@ -4484,11 +4537,11 @@ if test x$ac_prog_cxx_stdcxx = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5
printf %s "checking for $CXX option to enable C++11 features... " >&6; }
-if test ${ac_cv_prog_cxx_11+y}
+if test ${ac_cv_prog_cxx_cxx11+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_cv_prog_cxx_11=no
+else case e in #(
+ e) ac_cv_prog_cxx_cxx11=no
ac_save_CXX=$CXX
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -4505,36 +4558,39 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cxx_cxx11" != "xno" && break
done
rm -f conftest.$ac_ext
-CXX=$ac_save_CXX
+CXX=$ac_save_CXX ;;
+esac
fi
if test "x$ac_cv_prog_cxx_cxx11" = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
-else $as_nop
- if test "x$ac_cv_prog_cxx_cxx11" = x
+else case e in #(
+ e) if test "x$ac_cv_prog_cxx_cxx11" = x
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
-else $as_nop
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5
printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; }
- CXX="$CXX $ac_cv_prog_cxx_cxx11"
+ CXX="$CXX $ac_cv_prog_cxx_cxx11" ;;
+esac
fi
ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11
- ac_prog_cxx_stdcxx=cxx11
+ ac_prog_cxx_stdcxx=cxx11 ;;
+esac
fi
fi
if test x$ac_prog_cxx_stdcxx = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5
printf %s "checking for $CXX option to enable C++98 features... " >&6; }
-if test ${ac_cv_prog_cxx_98+y}
+if test ${ac_cv_prog_cxx_cxx98+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_cv_prog_cxx_98=no
+else case e in #(
+ e) ac_cv_prog_cxx_cxx98=no
ac_save_CXX=$CXX
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -4551,25 +4607,28 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cxx_cxx98" != "xno" && break
done
rm -f conftest.$ac_ext
-CXX=$ac_save_CXX
+CXX=$ac_save_CXX ;;
+esac
fi
if test "x$ac_cv_prog_cxx_cxx98" = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
-else $as_nop
- if test "x$ac_cv_prog_cxx_cxx98" = x
+else case e in #(
+ e) if test "x$ac_cv_prog_cxx_cxx98" = x
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
-else $as_nop
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5
printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; }
- CXX="$CXX $ac_cv_prog_cxx_cxx98"
+ CXX="$CXX $ac_cv_prog_cxx_cxx98" ;;
+esac
fi
ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98
- ac_prog_cxx_stdcxx=cxx98
+ ac_prog_cxx_stdcxx=cxx98 ;;
+esac
fi
fi
@@ -4587,8 +4646,8 @@ printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_AR+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- if test -n "$AR"; then
+else case e in #(
+ e) if test -n "$AR"; then
ac_cv_prog_AR="$AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -4610,7 +4669,8 @@ done
done
IFS=$as_save_IFS
-fi
+fi ;;
+esac
fi
AR=$ac_cv_prog_AR
if test -n "$AR"; then
@@ -4632,8 +4692,8 @@ printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_AR+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- if test -n "$ac_ct_AR"; then
+else case e in #(
+ e) if test -n "$ac_ct_AR"; then
ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -4655,7 +4715,8 @@ done
done
IFS=$as_save_IFS
-fi
+fi ;;
+esac
fi
ac_ct_AR=$ac_cv_prog_ac_ct_AR
if test -n "$ac_ct_AR"; then
@@ -4689,8 +4750,8 @@ printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_RANLIB+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- if test -n "$RANLIB"; then
+else case e in #(
+ e) if test -n "$RANLIB"; then
ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -4712,7 +4773,8 @@ done
done
IFS=$as_save_IFS
-fi
+fi ;;
+esac
fi
RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
@@ -4734,8 +4796,8 @@ printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_RANLIB+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- if test -n "$ac_ct_RANLIB"; then
+else case e in #(
+ e) if test -n "$ac_ct_RANLIB"; then
ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -4757,7 +4819,8 @@ done
done
IFS=$as_save_IFS
-fi
+fi ;;
+esac
fi
ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
if test -n "$ac_ct_RANLIB"; then
@@ -4790,8 +4853,8 @@ printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_path_DTC+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- case $DTC in
+else case e in #(
+ e) case $DTC in
[\\/]* | ?:[\\/]*)
ac_cv_path_DTC="$DTC" # Let the user override the test with a path.
;;
@@ -4817,6 +4880,7 @@ IFS=$as_save_IFS
test -z "$ac_cv_path_DTC" && ac_cv_path_DTC="no"
;;
+esac ;;
esac
fi
DTC=$ac_cv_path_DTC
@@ -4872,8 +4936,8 @@ printf %s "checking whether byte ordering is bigendian... " >&6; }
if test ${ac_cv_c_bigendian+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_cv_c_bigendian=unknown
+else case e in #(
+ e) ac_cv_c_bigendian=unknown
# See if we're dealing with a universal compiler.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -4919,8 +4983,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
int
main (void)
{
-#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
- && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \\
+ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \\
&& LITTLE_ENDIAN)
bogus endian macros
#endif
@@ -4951,8 +5015,9 @@ _ACEOF
if ac_fn_cxx_try_compile "$LINENO"
then :
ac_cv_c_bigendian=yes
-else $as_nop
- ac_cv_c_bigendian=no
+else case e in #(
+ e) ac_cv_c_bigendian=no ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
@@ -4996,8 +5061,9 @@ _ACEOF
if ac_fn_cxx_try_compile "$LINENO"
then :
ac_cv_c_bigendian=yes
-else $as_nop
- ac_cv_c_bigendian=no
+else case e in #(
+ e) ac_cv_c_bigendian=no ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
@@ -5024,22 +5090,23 @@ unsigned short int ascii_mm[] =
int use_ebcdic (int i) {
return ebcdic_mm[i] + ebcdic_ii[i];
}
- extern int foo;
-
-int
-main (void)
-{
-return use_ascii (foo) == use_ebcdic (foo);
- ;
- return 0;
-}
+ int
+ main (int argc, char **argv)
+ {
+ /* Intimidate the compiler so that it does not
+ optimize the arrays away. */
+ char *p = argv[0];
+ ascii_mm[1] = *p++; ebcdic_mm[1] = *p++;
+ ascii_ii[1] = *p++; ebcdic_ii[1] = *p++;
+ return use_ascii (argc) == use_ebcdic (*p);
+ }
_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"
+if ac_fn_cxx_try_link "$LINENO"
then :
- if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+ if grep BIGenDianSyS conftest$ac_exeext >/dev/null; then
ac_cv_c_bigendian=yes
fi
- if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if grep LiTTleEnDian conftest$ac_exeext >/dev/null ; then
if test "$ac_cv_c_bigendian" = unknown; then
ac_cv_c_bigendian=no
else
@@ -5048,9 +5115,10 @@ then :
fi
fi
fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-else $as_nop
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_includes_default
int
@@ -5073,14 +5141,17 @@ _ACEOF
if ac_fn_cxx_try_run "$LINENO"
then :
ac_cv_c_bigendian=no
-else $as_nop
- ac_cv_c_bigendian=yes
+else case e in #(
+ e) ac_cv_c_bigendian=yes ;;
+esac
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
+ conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
fi
- fi
+ fi ;;
+esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
printf "%s\n" "$ac_cv_c_bigendian" >&6; }
@@ -5129,8 +5200,8 @@ if test -z "$INSTALL"; then
if test ${ac_cv_path_install+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+else case e in #(
+ e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
@@ -5184,7 +5255,8 @@ esac
IFS=$as_save_IFS
rm -rf conftest.one conftest.two conftest.dir
-
+ ;;
+esac
fi
if test ${ac_cv_path_install+y}; then
INSTALL=$ac_cv_path_install
@@ -5215,8 +5287,9 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
if test ${enable_stow+y}
then :
enableval=$enable_stow; enable_stow="yes"
-else $as_nop
- enable_stow="no"
+else case e in #(
+ e) enable_stow="no" ;;
+esac
fi
@@ -5233,157 +5306,6 @@ fi
#-------------------------------------------------------------------------
-# Checks for header files
-#-------------------------------------------------------------------------
-
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
-printf %s "checking for grep that handles long lines and -e... " >&6; }
-if test ${ac_cv_path_GREP+y}
-then :
- printf %s "(cached) " >&6
-else $as_nop
- if test -z "$GREP"; then
- ac_path_GREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- case $as_dir in #(((
- '') as_dir=./ ;;
- */) ;;
- *) as_dir=$as_dir/ ;;
- esac
- for ac_prog in grep ggrep
- do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_GREP="$as_dir$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_GREP" || continue
-# Check for GNU ac_path_GREP and select it if it is found.
- # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
- ac_count=0
- printf %s 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- printf "%s\n" 'GREP' >> "conftest.nl"
- "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_GREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_GREP="$ac_path_GREP"
- ac_path_GREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_GREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_GREP"; then
- as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_GREP=$GREP
-fi
-
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
-printf "%s\n" "$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-# Autoupdate added the next two lines to ensure that your configure
-# script's behavior did not change. They are probably safe to remove.
-
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
-printf %s "checking for egrep... " >&6; }
-if test ${ac_cv_path_EGREP+y}
-then :
- printf %s "(cached) " >&6
-else $as_nop
- if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
- then ac_cv_path_EGREP="$GREP -E"
- else
- if test -z "$EGREP"; then
- ac_path_EGREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- case $as_dir in #(((
- '') as_dir=./ ;;
- */) ;;
- *) as_dir=$as_dir/ ;;
- esac
- for ac_prog in egrep
- do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_EGREP" || continue
-# Check for GNU ac_path_EGREP and select it if it is found.
- # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
- ac_count=0
- printf %s 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- printf "%s\n" 'EGREP' >> "conftest.nl"
- "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_EGREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_EGREP="$ac_path_EGREP"
- ac_path_EGREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_EGREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_EGREP"; then
- as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_EGREP=$EGREP
-fi
-
- fi
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
-printf "%s\n" "$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
-
-
-#-------------------------------------------------------------------------
# Checks for type
#-------------------------------------------------------------------------
@@ -5407,14 +5329,14 @@ fi
for flag in -Wl,--export-dynamic; do
- as_CACHEVAR=`printf "%s\n" "ax_cv_check_ldflags__$flag" | $as_tr_sh`
+ as_CACHEVAR=`printf "%s\n" "ax_cv_check_ldflags__$flag" | sed "$as_sed_sh"`
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts $flag" >&5
printf %s "checking whether the linker accepts $flag... " >&6; }
if eval test \${$as_CACHEVAR+y}
then :
printf %s "(cached) " >&6
-else $as_nop
-
+else case e in #(
+ e)
ax_check_save_flags=$LDFLAGS
LDFLAGS="$LDFLAGS $flag"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -5431,12 +5353,14 @@ _ACEOF
if ac_fn_cxx_try_link "$LINENO"
then :
eval "$as_CACHEVAR=yes"
-else $as_nop
- eval "$as_CACHEVAR=no"
+else case e in #(
+ e) eval "$as_CACHEVAR=no" ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
- LDFLAGS=$ax_check_save_flags
+ LDFLAGS=$ax_check_save_flags ;;
+esac
fi
eval ac_res=\$$as_CACHEVAR
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
@@ -5465,33 +5389,38 @@ then :
;;
esac
-else $as_nop
-
+else case e in #(
+ e)
LDFLAGS=$flag
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS\""; } >&5
(: LDFLAGS="$LDFLAGS") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
-
+ ;;
+esac
fi
-else $as_nop
- :
+else case e in #(
+ e) : ;;
+esac
fi
done
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -relocatable-pch" >&5
-printf %s "checking whether C++ compiler accepts -relocatable-pch... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler accepts -relocatable-pch" >&5
+printf %s "checking whether the C++ compiler accepts -relocatable-pch... " >&6; }
if test ${ax_cv_check_cxxflags___relocatable_pch+y}
then :
printf %s "(cached) " >&6
-else $as_nop
-
+else case e in #(
+ e)
ax_check_save_flags=$CXXFLAGS
- CXXFLAGS="$CXXFLAGS -relocatable-pch"
+ if test x"$GXX" = xyes ; then
+ add_gnu_werror="-Werror"
+ fi
+ CXXFLAGS="$CXXFLAGS -relocatable-pch $add_gnu_werror"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -5506,11 +5435,13 @@ _ACEOF
if ac_fn_cxx_try_compile "$LINENO"
then :
ax_cv_check_cxxflags___relocatable_pch=yes
-else $as_nop
- ax_cv_check_cxxflags___relocatable_pch=no
+else case e in #(
+ e) ax_cv_check_cxxflags___relocatable_pch=no ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
- CXXFLAGS=$ax_check_save_flags
+ CXXFLAGS=$ax_check_save_flags ;;
+esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cxxflags___relocatable_pch" >&5
printf "%s\n" "$ax_cv_check_cxxflags___relocatable_pch" >&6; }
@@ -5518,8 +5449,9 @@ if test "x$ax_cv_check_cxxflags___relocatable_pch" = xyes
then :
HAVE_CLANG_PCH=yes
-else $as_nop
- :
+else case e in #(
+ e) : ;;
+esac
fi
@@ -5590,8 +5522,8 @@ printf %s "checking for pthread_create in -lpthread... " >&6; }
if test ${ac_cv_lib_pthread_pthread_create+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_check_lib_save_LIBS=$LIBS
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lpthread $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -5610,12 +5542,14 @@ _ACEOF
if ac_fn_cxx_try_link "$LINENO"
then :
ac_cv_lib_pthread_pthread_create=yes
-else $as_nop
- ac_cv_lib_pthread_pthread_create=no
+else case e in #(
+ e) ac_cv_lib_pthread_pthread_create=no ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
printf "%s\n" "$ac_cv_lib_pthread_pthread_create" >&6; }
@@ -5625,8 +5559,9 @@ then :
LIBS="-lpthread $LIBS"
-else $as_nop
- as_fn_error $? "libpthread is required" "$LINENO" 5
+else case e in #(
+ e) as_fn_error $? "libpthread is required" "$LINENO" 5 ;;
+esac
fi
@@ -5714,8 +5649,9 @@ then :
want_boost="yes";_AX_BOOST_BASE_boost_path="$withval" ;;
esac
-else $as_nop
- want_boost="yes"
+else case e in #(
+ e) want_boost="yes" ;;
+esac
fi
@@ -5728,12 +5664,14 @@ then :
if test -d "$withval"
then :
_AX_BOOST_BASE_boost_lib_path="$withval"
-else $as_nop
- as_fn_error $? "--with-boost-libdir expected directory name" "$LINENO" 5
+else case e in #(
+ e) as_fn_error $? "--with-boost-libdir expected directory name" "$LINENO" 5 ;;
+esac
fi
-else $as_nop
- _AX_BOOST_BASE_boost_lib_path=""
+else case e in #(
+ e) _AX_BOOST_BASE_boost_lib_path="" ;;
+esac
fi
@@ -5746,8 +5684,9 @@ then :
if test "x1.53" = "x"
then :
_AX_BOOST_BASE_TONUMERICVERSION_req="1.20.0"
-else $as_nop
- _AX_BOOST_BASE_TONUMERICVERSION_req="1.53"
+else case e in #(
+ e) _AX_BOOST_BASE_TONUMERICVERSION_req="1.53" ;;
+esac
fi
_AX_BOOST_BASE_TONUMERICVERSION_req_shorten=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\([0-9]*\.[0-9]*\)'`
_AX_BOOST_BASE_TONUMERICVERSION_req_major=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\([0-9]*\)'`
@@ -5777,7 +5716,7 @@ fi
libsubdirs="lib64 libx32 lib lib64" ;; #(
mips*64*) :
libsubdirs="lib64 lib32 lib lib64" ;; #(
- ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64|e2k) :
+ ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64|e2k|loongarch64) :
libsubdirs="lib64 lib lib64" ;; #(
*) :
libsubdirs="lib"
@@ -5816,25 +5755,27 @@ printf "%s\n" "yes" >&6; }
BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp";
break;
-else $as_nop
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
-printf "%s\n" "no" >&6; }
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; } ;;
+esac
fi
done
-else $as_nop
-
+else case e in #(
+ e)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
-printf "%s\n" "no" >&6; }
+printf "%s\n" "no" >&6; } ;;
+esac
fi
-else $as_nop
-
+else case e in #(
+ e)
if test X"$cross_compiling" = Xyes; then
search_libsubdirs=$multiarch_libsubdir
else
search_libsubdirs="$multiarch_libsubdir $libsubdirs"
fi
- for _AX_BOOST_BASE_boost_path_tmp in /usr /usr/local /opt /opt/local ; do
+ for _AX_BOOST_BASE_boost_path_tmp in /usr /usr/local /opt /opt/local /opt/homebrew ; do
if test -d "$_AX_BOOST_BASE_boost_path_tmp/include/boost" && test -r "$_AX_BOOST_BASE_boost_path_tmp/include/boost" ; then
for libsubdir in $search_libsubdirs ; do
if ls "$_AX_BOOST_BASE_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
@@ -5844,7 +5785,8 @@ else $as_nop
break;
fi
done
-
+ ;;
+esac
fi
if test "x$_AX_BOOST_BASE_boost_lib_path" != "x"
@@ -5936,7 +5878,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
fi
else
if test "x$cross_compiling" != "xyes" ; then
- for _AX_BOOST_BASE_boost_path in /usr /usr/local /opt /opt/local ; do
+ for _AX_BOOST_BASE_boost_path in /usr /usr/local /opt /opt/local /opt/homebrew ; do
if test -d "$_AX_BOOST_BASE_boost_path" && test -r "$_AX_BOOST_BASE_boost_path" ; then
for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do
_version_tmp=`echo $i | sed "s#$_AX_BOOST_BASE_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
@@ -6030,6 +5972,8 @@ printf "%s\n" "$as_me: We could not detect the boost libraries (version 1.53 or
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: Your boost libraries seems to old (version $_version)." >&5
printf "%s\n" "$as_me: Your boost libraries seems to old (version $_version)." >&6;}
fi
+ BOOST_LDFLAGS=""
+ BOOST_CPPFLAGS=""
# execute ACTION-IF-NOT-FOUND (if present):
:
else
@@ -6064,9 +6008,10 @@ then :
ax_boost_user_asio_lib="$withval"
fi
-else $as_nop
- want_boost="yes"
-
+else case e in #(
+ e) want_boost="yes"
+ ;;
+esac
fi
@@ -6085,8 +6030,8 @@ printf %s "checking whether the Boost::ASIO library is available... " >&6; }
if test ${ax_cv_boost_asio+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_ext=cpp
+else case e in #(
+ e) ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
@@ -6115,8 +6060,9 @@ _ACEOF
if ac_fn_cxx_try_compile "$LINENO"
then :
ax_cv_boost_asio=yes
-else $as_nop
- ax_cv_boost_asio=no
+else case e in #(
+ e) ax_cv_boost_asio=no ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_ext=cpp
@@ -6125,7 +6071,8 @@ ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
+ ;;
+esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_boost_asio" >&5
printf "%s\n" "$ax_cv_boost_asio" >&6; }
@@ -6137,14 +6084,14 @@ printf "%s\n" "#define HAVE_BOOST_ASIO /**/" >>confdefs.h
BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/[^\/]*//'`
if test "x$ax_boost_user_asio_lib" = "x"; then
for ax_lib in `ls $BOOSTLIBDIR/libboost_system*.so* $BOOSTLIBDIR/libboost_system*.dylib* $BOOSTLIBDIR/libboost_system*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_system.*\)\.so.*$;\1;' -e 's;^lib\(boost_system.*\)\.dylib.*$;\1;' -e 's;^lib\(boost_system.*\)\.a.*$;\1;' ` ; do
- as_ac_Lib=`printf "%s\n" "ac_cv_lib_$ax_lib""_main" | $as_tr_sh`
+ as_ac_Lib=`printf "%s\n" "ac_cv_lib_$ax_lib""_main" | sed "$as_sed_sh"`
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -l$ax_lib" >&5
printf %s "checking for main in -l$ax_lib... " >&6; }
if eval test \${$as_ac_Lib+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_check_lib_save_LIBS=$LIBS
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
LIBS="-l$ax_lib $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -6163,12 +6110,14 @@ _ACEOF
if ac_fn_cxx_try_link "$LINENO"
then :
eval "$as_ac_Lib=yes"
-else $as_nop
- eval "$as_ac_Lib=no"
+else case e in #(
+ e) eval "$as_ac_Lib=no" ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
fi
eval ac_res=\$$as_ac_Lib
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
@@ -6176,21 +6125,22 @@ printf "%s\n" "$ac_res" >&6; }
if eval test \"x\$"$as_ac_Lib"\" = x"yes"
then :
BOOST_ASIO_LIB="-l$ax_lib" link_thread="yes" break
-else $as_nop
- link_thread="no"
+else case e in #(
+ e) link_thread="no" ;;
+esac
fi
done
else
for ax_lib in $ax_boost_user_asio_lib $BN-$ax_boost_user_asio_lib; do
- as_ac_Lib=`printf "%s\n" "ac_cv_lib_$ax_lib""_main" | $as_tr_sh`
+ as_ac_Lib=`printf "%s\n" "ac_cv_lib_$ax_lib""_main" | sed "$as_sed_sh"`
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -l$ax_lib" >&5
printf %s "checking for main in -l$ax_lib... " >&6; }
if eval test \${$as_ac_Lib+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_check_lib_save_LIBS=$LIBS
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
LIBS="-l$ax_lib $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -6209,12 +6159,14 @@ _ACEOF
if ac_fn_cxx_try_link "$LINENO"
then :
eval "$as_ac_Lib=yes"
-else $as_nop
- eval "$as_ac_Lib=no"
+else case e in #(
+ e) eval "$as_ac_Lib=no" ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
fi
eval ac_res=\$$as_ac_Lib
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
@@ -6222,8 +6174,9 @@ printf "%s\n" "$ac_res" >&6; }
if eval test \"x\$"$as_ac_Lib"\" = x"yes"
then :
BOOST_ASIO_LIB="-l$ax_lib" link_asio="yes" break
-else $as_nop
- link_asio="no"
+else case e in #(
+ e) link_asio="no" ;;
+esac
fi
done
@@ -6257,9 +6210,10 @@ then :
ax_boost_user_regex_lib="$withval"
fi
-else $as_nop
- want_boost="yes"
-
+else case e in #(
+ e) want_boost="yes"
+ ;;
+esac
fi
@@ -6278,8 +6232,8 @@ printf %s "checking whether the Boost::Regex library is available... " >&6; }
if test ${ax_cv_boost_regex+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_ext=cpp
+else case e in #(
+ e) ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
@@ -6300,8 +6254,9 @@ _ACEOF
if ac_fn_cxx_try_compile "$LINENO"
then :
ax_cv_boost_regex=yes
-else $as_nop
- ax_cv_boost_regex=no
+else case e in #(
+ e) ax_cv_boost_regex=no ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_ext=cpp
@@ -6310,7 +6265,8 @@ ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
+ ;;
+esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_boost_regex" >&5
printf "%s\n" "$ax_cv_boost_regex" >&6; }
@@ -6322,14 +6278,14 @@ printf "%s\n" "#define HAVE_BOOST_REGEX /**/" >>confdefs.h
if test "x$ax_boost_user_regex_lib" = "x"; then
for libextension in `ls $BOOSTLIBDIR/libboost_regex*.so* $BOOSTLIBDIR/libboost_regex*.dylib* $BOOSTLIBDIR/libboost_regex*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_regex.*\)\.so.*$;\1;' -e 's;^lib\(boost_regex.*\)\.dylib.*;\1;' -e 's;^lib\(boost_regex.*\)\.a.*$;\1;'` ; do
ax_lib=${libextension}
- as_ac_Lib=`printf "%s\n" "ac_cv_lib_$ax_lib""_exit" | $as_tr_sh`
+ as_ac_Lib=`printf "%s\n" "ac_cv_lib_$ax_lib""_exit" | sed "$as_sed_sh"`
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5
printf %s "checking for exit in -l$ax_lib... " >&6; }
if eval test \${$as_ac_Lib+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_check_lib_save_LIBS=$LIBS
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
LIBS="-l$ax_lib $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -6348,12 +6304,14 @@ _ACEOF
if ac_fn_cxx_try_link "$LINENO"
then :
eval "$as_ac_Lib=yes"
-else $as_nop
- eval "$as_ac_Lib=no"
+else case e in #(
+ e) eval "$as_ac_Lib=no" ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
fi
eval ac_res=\$$as_ac_Lib
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
@@ -6361,22 +6319,23 @@ printf "%s\n" "$ac_res" >&6; }
if eval test \"x\$"$as_ac_Lib"\" = x"yes"
then :
BOOST_REGEX_LIB="-l$ax_lib"; link_regex="yes"; break
-else $as_nop
- link_regex="no"
+else case e in #(
+ e) link_regex="no" ;;
+esac
fi
done
if test "x$link_regex" != "xyes"; then
for libextension in `ls $BOOSTLIBDIR/boost_regex*.dll* $BOOSTLIBDIR/boost_regex*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_regex.*\)\.dll.*$;\1;' -e 's;^\(boost_regex.*\)\.a.*$;\1;'` ; do
ax_lib=${libextension}
- as_ac_Lib=`printf "%s\n" "ac_cv_lib_$ax_lib""_exit" | $as_tr_sh`
+ as_ac_Lib=`printf "%s\n" "ac_cv_lib_$ax_lib""_exit" | sed "$as_sed_sh"`
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5
printf %s "checking for exit in -l$ax_lib... " >&6; }
if eval test \${$as_ac_Lib+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_check_lib_save_LIBS=$LIBS
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
LIBS="-l$ax_lib $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -6395,12 +6354,14 @@ _ACEOF
if ac_fn_cxx_try_link "$LINENO"
then :
eval "$as_ac_Lib=yes"
-else $as_nop
- eval "$as_ac_Lib=no"
+else case e in #(
+ e) eval "$as_ac_Lib=no" ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
fi
eval ac_res=\$$as_ac_Lib
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
@@ -6408,8 +6369,9 @@ printf "%s\n" "$ac_res" >&6; }
if eval test \"x\$"$as_ac_Lib"\" = x"yes"
then :
BOOST_REGEX_LIB="-l$ax_lib"; link_regex="yes"; break
-else $as_nop
- link_regex="no"
+else case e in #(
+ e) link_regex="no" ;;
+esac
fi
done
@@ -6417,14 +6379,14 @@ fi
else
for ax_lib in $ax_boost_user_regex_lib boost_regex-$ax_boost_user_regex_lib; do
- as_ac_Lib=`printf "%s\n" "ac_cv_lib_$ax_lib""_main" | $as_tr_sh`
+ as_ac_Lib=`printf "%s\n" "ac_cv_lib_$ax_lib""_main" | sed "$as_sed_sh"`
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -l$ax_lib" >&5
printf %s "checking for main in -l$ax_lib... " >&6; }
if eval test \${$as_ac_Lib+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_check_lib_save_LIBS=$LIBS
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
LIBS="-l$ax_lib $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -6443,12 +6405,14 @@ _ACEOF
if ac_fn_cxx_try_link "$LINENO"
then :
eval "$as_ac_Lib=yes"
-else $as_nop
- eval "$as_ac_Lib=no"
+else case e in #(
+ e) eval "$as_ac_Lib=no" ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
fi
eval ac_res=\$$as_ac_Lib
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
@@ -6456,8 +6420,9 @@ printf "%s\n" "$ac_res" >&6; }
if eval test \"x\$"$as_ac_Lib"\" = x"yes"
then :
BOOST_REGEX_LIB="-l$ax_lib"; link_regex="yes"; break
-else $as_nop
- link_regex="no"
+else case e in #(
+ e) link_regex="no" ;;
+esac
fi
done
@@ -6480,8 +6445,8 @@ printf %s "checking for main in -lboost_system... " >&6; }
if test ${ac_cv_lib_boost_system_main+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_check_lib_save_LIBS=$LIBS
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lboost_system $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -6500,12 +6465,14 @@ _ACEOF
if ac_fn_cxx_try_link "$LINENO"
then :
ac_cv_lib_boost_system_main=yes
-else $as_nop
- ac_cv_lib_boost_system_main=no
+else case e in #(
+ e) ac_cv_lib_boost_system_main=no ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_boost_system_main" >&5
printf "%s\n" "$ac_cv_lib_boost_system_main" >&6; }
@@ -6523,8 +6490,8 @@ printf %s "checking for main in -lboost_regex... " >&6; }
if test ${ac_cv_lib_boost_regex_main+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_check_lib_save_LIBS=$LIBS
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lboost_regex $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -6543,12 +6510,14 @@ _ACEOF
if ac_fn_cxx_try_link "$LINENO"
then :
ac_cv_lib_boost_regex_main=yes
-else $as_nop
- ac_cv_lib_boost_regex_main=no
+else case e in #(
+ e) ac_cv_lib_boost_regex_main=no ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_boost_regex_main" >&5
printf "%s\n" "$ac_cv_lib_boost_regex_main" >&6; }
@@ -6562,44 +6531,17 @@ fi
-# Check whether --with-isa was given.
-if test ${with_isa+y}
-then :
- withval=$with_isa;
-printf "%s\n" "#define DEFAULT_ISA \"$withval\"" >>confdefs.h
-
-else $as_nop
-
-printf "%s\n" "#define DEFAULT_ISA \"RV64IMAFDC_zicntr_zihpm\"" >>confdefs.h
-
-fi
-
-
-
-# Check whether --with-priv was given.
-if test ${with_priv+y}
-then :
- withval=$with_priv;
-printf "%s\n" "#define DEFAULT_PRIV \"$withval\"" >>confdefs.h
-
-else $as_nop
-
-printf "%s\n" "#define DEFAULT_PRIV \"MSU\"" >>confdefs.h
-
-fi
-
-
-
# Check whether --with-target was given.
if test ${with_target+y}
then :
withval=$with_target;
printf "%s\n" "#define TARGET_ARCH \"$withval\"" >>confdefs.h
-else $as_nop
-
+else case e in #(
+ e)
printf "%s\n" "#define TARGET_ARCH \"riscv64-unknown-elf\"" >>confdefs.h
-
+ ;;
+esac
fi
@@ -6608,8 +6550,8 @@ printf %s "checking for library containing dlopen... " >&6; }
if test ${ac_cv_search_dlopen+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_func_search_save_LIBS=$LIBS
+else case e in #(
+ e) ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -6646,11 +6588,13 @@ done
if test ${ac_cv_search_dlopen+y}
then :
-else $as_nop
- ac_cv_search_dlopen=no
+else case e in #(
+ e) ac_cv_search_dlopen=no ;;
+esac
fi
rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
+LIBS=$ac_func_search_save_LIBS ;;
+esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
printf "%s\n" "$ac_cv_search_dlopen" >&6; }
@@ -6673,8 +6617,8 @@ printf %s "checking for pthread_create in -lpthread... " >&6; }
if test ${ac_cv_lib_pthread_pthread_create+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- ac_check_lib_save_LIBS=$LIBS
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lpthread $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -6693,12 +6637,14 @@ _ACEOF
if ac_fn_cxx_try_link "$LINENO"
then :
ac_cv_lib_pthread_pthread_create=yes
-else $as_nop
- ac_cv_lib_pthread_pthread_create=no
+else case e in #(
+ e) ac_cv_lib_pthread_pthread_create=no ;;
+esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
printf "%s\n" "$ac_cv_lib_pthread_pthread_create" >&6; }
@@ -6708,8 +6654,9 @@ then :
LIBS="-lpthread $LIBS"
-else $as_nop
- as_fn_error $? "libpthread is required" "$LINENO" 5
+else case e in #(
+ e) as_fn_error $? "libpthread is required" "$LINENO" 5 ;;
+esac
fi
@@ -7044,8 +6991,8 @@ cat >confcache <<\_ACEOF
# config.status only pays attention to the cache file if you give it
# the --recheck option to rerun configure.
#
-# `ac_cv_env_foo' variables (set or unset) will be overridden when
-# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# 'ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* 'ac_cv_foo' will be assigned the
# following values.
_ACEOF
@@ -7075,14 +7022,14 @@ printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;}
(set) 2>&1 |
case $as_nl`(ac_space=' '; set) 2>&1` in #(
*${as_nl}ac_space=\ *)
- # `set' does not quote correctly, so add quotes: double-quote
+ # 'set' does not quote correctly, so add quotes: double-quote
# substitution turns \\\\ into \\, and sed turns \\ into \.
sed -n \
"s/'/'\\\\''/g;
s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
;; #(
*)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
+ # 'set' quotes correctly as required by POSIX, so do not add quotes.
sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
;;
esac |
@@ -7173,7 +7120,6 @@ cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-as_nop=:
if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
emulate sh
@@ -7182,12 +7128,13 @@ then :
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else $as_nop
- case `(set -o) 2>/dev/null` in #(
+else case e in #(
+ e) case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
*) :
;;
+esac ;;
esac
fi
@@ -7259,7 +7206,7 @@ IFS=$as_save_IFS
;;
esac
-# We did not find ourselves, most probably we were run as `sh COMMAND'
+# We did not find ourselves, most probably we were run as 'sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
as_myself=$0
@@ -7288,7 +7235,6 @@ as_fn_error ()
} # as_fn_error
-
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -7328,11 +7274,12 @@ then :
{
eval $1+=\$2
}'
-else $as_nop
- as_fn_append ()
+else case e in #(
+ e) as_fn_append ()
{
eval $1=\$$1\$2
- }
+ } ;;
+esac
fi # as_fn_append
# as_fn_arith ARG...
@@ -7346,11 +7293,12 @@ then :
{
as_val=$(( $* ))
}'
-else $as_nop
- as_fn_arith ()
+else case e in #(
+ e) as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
- }
+ } ;;
+esac
fi # as_fn_arith
@@ -7433,9 +7381,9 @@ if (echo >conf$$.file) 2>/dev/null; then
if ln -s conf$$.file conf$$ 2>/dev/null; then
as_ln_s='ln -s'
# ... but there are two gotchas:
- # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
- # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
- # In both cases, we have to default to `cp -pR'.
+ # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.
+ # In both cases, we have to default to 'cp -pR'.
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
as_ln_s='cp -pR'
elif ln conf$$.file conf$$ 2>/dev/null; then
@@ -7516,10 +7464,12 @@ as_test_x='test -x'
as_executable_p=as_fn_executable_p
# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated
# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+as_tr_sh="eval sed '$as_sed_sh'" # deprecated
exec 6>&1
@@ -7535,7 +7485,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# values after options handling.
ac_log="
This file was extended by RISC-V ISA Simulator $as_me ?, which was
-generated by GNU Autoconf 2.71. Invocation command line was
+generated by GNU Autoconf 2.72. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -7566,7 +7516,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
ac_cs_usage="\
-\`$as_me' instantiates files and other configuration actions
+'$as_me' instantiates files and other configuration actions
from templates according to the current configuration. Unless the files
and actions are specified as TAGs, all are instantiated by default.
@@ -7599,10 +7549,10 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
RISC-V ISA Simulator config.status ?
-configured by $0, generated by GNU Autoconf 2.71,
+configured by $0, generated by GNU Autoconf 2.72,
with options \\"\$ac_cs_config\\"
-Copyright (C) 2021 Free Software Foundation, Inc.
+Copyright (C) 2023 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -7662,8 +7612,8 @@ do
ac_need_defaults=false;;
--he | --h)
# Conflict between --help and --header
- as_fn_error $? "ambiguous option: \`$1'
-Try \`$0 --help' for more information.";;
+ as_fn_error $? "ambiguous option: '$1'
+Try '$0 --help' for more information.";;
--help | --hel | -h )
printf "%s\n" "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
@@ -7671,8 +7621,8 @@ Try \`$0 --help' for more information.";;
ac_cs_silent=: ;;
# This is an error.
- -*) as_fn_error $? "unrecognized option: \`$1'
-Try \`$0 --help' for more information." ;;
+ -*) as_fn_error $? "unrecognized option: '$1'
+Try '$0 --help' for more information." ;;
*) as_fn_append ac_config_targets " $1"
ac_need_defaults=false ;;
@@ -7734,7 +7684,7 @@ do
"riscv-disasm.pc") CONFIG_FILES="$CONFIG_FILES riscv-disasm.pc" ;;
"riscv-riscv.pc") CONFIG_FILES="$CONFIG_FILES riscv-riscv.pc" ;;
- *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ *) as_fn_error $? "invalid argument: '$ac_config_target'" "$LINENO" 5;;
esac
done
@@ -7753,7 +7703,7 @@ fi
# creating and moving files from /tmp can sometimes cause problems.
# Hook for its removal unless debugging.
# Note that there is a small window in which the directory will not be cleaned:
-# after its creation but before its name has been assigned to `$tmp'.
+# after its creation but before its name has been assigned to '$tmp'.
$debug ||
{
tmp= ac_tmp=
@@ -7777,7 +7727,7 @@ ac_tmp=$tmp
# Set up the scripts for CONFIG_FILES section.
# No need to generate them if there are no CONFIG_FILES.
-# This happens for instance with `./config.status config.h'.
+# This happens for instance with './config.status config.h'.
if test -n "$CONFIG_FILES"; then
@@ -7935,13 +7885,13 @@ fi # test -n "$CONFIG_FILES"
# Set up the scripts for CONFIG_HEADERS section.
# No need to generate them if there are no CONFIG_HEADERS.
-# This happens for instance with `./config.status Makefile'.
+# This happens for instance with './config.status Makefile'.
if test -n "$CONFIG_HEADERS"; then
cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
BEGIN {
_ACEOF
-# Transform confdefs.h into an awk script `defines.awk', embedded as
+# Transform confdefs.h into an awk script 'defines.awk', embedded as
# here-document in config.status, that substitutes the proper values into
# config.h.in to produce config.h.
@@ -8051,7 +8001,7 @@ do
esac
case $ac_mode$ac_tag in
:[FHL]*:*);;
- :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :L* | :C*:*) as_fn_error $? "invalid tag '$ac_tag'" "$LINENO" 5;;
:[FH]-) ac_tag=-:-;;
:[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
esac
@@ -8073,19 +8023,19 @@ do
-) ac_f="$ac_tmp/stdin";;
*) # Look for the file first in the build tree, then in the source tree
# (if the path is not absolute). The absolute path cannot be DOS-style,
- # because $ac_f cannot contain `:'.
+ # because $ac_f cannot contain ':'.
test -f "$ac_f" ||
case $ac_f in
[\\/$]*) false;;
*) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
esac ||
- as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ as_fn_error 1 "cannot find input file: '$ac_f'" "$LINENO" 5;;
esac
case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
done
- # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # Let's still pretend it is 'configure' which instantiates (i.e., don't
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
configure_input='Generated from '`
@@ -8213,7 +8163,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
esac
_ACEOF
-# Neutralize VPATH when `$srcdir' = `.'.
+# Neutralize VPATH when '$srcdir' = '.'.
# Shell code in configure.ac might set extrasub.
# FIXME: do we really want to maintain this feature?
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
@@ -8243,9 +8193,9 @@ test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
"$ac_tmp/out"`; test -z "$ac_out"; } &&
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable 'datarootdir'
which seems to be undefined. Please make sure it is defined" >&5
-printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable 'datarootdir'
which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$ac_tmp/stdin"
diff --git a/configure.ac b/configure.ac
index 701bd99..e007335 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
#=========================================================================
# Toplevel configure.ac for the Modular C++ Build System
#=========================================================================
-# Please read the documenation in 'mcppbs-doc.txt' for more details on
+# Please read the documentation in 'mcppbs-doc.txt' for more details on
# how the Modular C++ Build System works. For most new projects, a
# developer will only need to make the following changes:
#
@@ -36,21 +36,21 @@ m4_define( proj_version, [?])
# Setup
#-------------------------------------------------------------------------
-AC_INIT(proj_name,proj_version,proj_maintainer,proj_abbreviation)
-AC_LANG_CPLUSPLUS
+AC_INIT([proj_name],[proj_version],[proj_maintainer],[proj_abbreviation])
+AC_LANG([C++])
AC_CONFIG_SRCDIR([riscv/common.h])
AC_CONFIG_AUX_DIR([scripts])
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
-m4_include(ax_require_defined.m4)
-m4_include(ax_append_flag.m4)
-m4_include(ax_check_compile_flag.m4)
-m4_include(ax_check_link_flag.m4)
-m4_include(ax_append_link_flags.m4)
-m4_include(ax_boost_base.m4)
-m4_include(ax_boost_asio.m4)
-m4_include(ax_boost_regex.m4)
+m4_include(m4/ax_require_defined.m4)
+m4_include(m4/ax_append_flag.m4)
+m4_include(m4/ax_check_compile_flag.m4)
+m4_include(m4/ax_check_link_flag.m4)
+m4_include(m4/ax_append_link_flags.m4)
+m4_include(m4/ax_boost_base.m4)
+m4_include(m4/ax_boost_asio.m4)
+m4_include(m4/ax_boost_regex.m4)
#-------------------------------------------------------------------------
# Checks for programs
@@ -76,12 +76,6 @@ AC_C_BIGENDIAN
MCPPBS_PROG_INSTALL
#-------------------------------------------------------------------------
-# Checks for header files
-#-------------------------------------------------------------------------
-
-AC_HEADER_STDC
-
-#-------------------------------------------------------------------------
# Checks for type
#-------------------------------------------------------------------------
diff --git a/customext/cflush.cc b/customext/cflush.cc
index 485716a..c090e88 100644
--- a/customext/cflush.cc
+++ b/customext/cflush.cc
@@ -19,23 +19,23 @@ static reg_t custom_cflush(processor_t* p, insn_t insn, reg_t pc)
class cflush_t : public extension_t
{
public:
- const char* name() { return "cflush"; }
+ const char* name() const override { return "cflush"; }
cflush_t() {}
- std::vector<insn_desc_t> get_instructions() {
- std::vector<insn_desc_t> insns;
- insns.push_back((insn_desc_t){0xFC000073, 0xFFF07FFF, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush});
- insns.push_back((insn_desc_t){0xFC200073, 0xFFF07FFF, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush});
- insns.push_back((insn_desc_t){0xFC100073, 0xFFF07FFF, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush});
+ std::vector<insn_desc_t> get_instructions(const processor_t &) override {
+ std::vector<insn_desc_t> insns = {
+ {0xFC000073, 0xFFF07FFF, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush},
+ {0xFC200073, 0xFFF07FFF, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush},
+ {0xFC100073, 0xFFF07FFF, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush}};
return insns;
}
- std::vector<disasm_insn_t*> get_disasms() {
- std::vector<disasm_insn_t*> insns;
- insns.push_back(new disasm_insn_t("cflush.d.l1", 0xFC000073, 0xFFF07FFF, {&xrs1}));
- insns.push_back(new disasm_insn_t("cdiscard.d.l1", 0xFC200073, 0xFFF07FFF, {&xrs1}));
- insns.push_back(new disasm_insn_t("cflush.i.l1", 0xFC100073, 0xFFF07FFF, {&xrs1}));
+ std::vector<disasm_insn_t *> get_disasms(const processor_t *) override {
+ std::vector<disasm_insn_t*> insns = {
+ new disasm_insn_t("cflush.d.l1", 0xFC000073, 0xFFF07FFF, {&xrs1}),
+ new disasm_insn_t("cdiscard.d.l1", 0xFC200073, 0xFFF07FFF, {&xrs1}),
+ new disasm_insn_t("cflush.i.l1", 0xFC100073, 0xFFF07FFF, {&xrs1})};
return insns;
}
};
diff --git a/customext/dummy_rocc.cc b/customext/dummy_rocc.cc
index 8c051fa..6669887 100644
--- a/customext/dummy_rocc.cc
+++ b/customext/dummy_rocc.cc
@@ -5,14 +5,14 @@
class dummy_rocc_t : public rocc_t
{
public:
- const char* name() { return "dummy_rocc"; }
+ const char* name() const { return "dummy_rocc"; }
- reg_t custom0(rocc_insn_t insn, reg_t xs1, reg_t UNUSED xs2)
+ reg_t custom0(processor_t *p, rocc_insn_t insn, reg_t xs1, reg_t UNUSED xs2)
{
reg_t prev_acc = acc[insn.rs2];
if (insn.rs2 >= num_acc)
- illegal_instruction();
+ illegal_instruction(*p);
switch (insn.funct)
{
@@ -28,7 +28,7 @@ class dummy_rocc_t : public rocc_t
acc[insn.rs2] += xs1;
break;
default:
- illegal_instruction();
+ illegal_instruction(*p);
}
return prev_acc; // in all cases, xd <- previous value of acc[rs2]
diff --git a/debug_rom/debug_rom.S b/debug_rom/debug_rom.S
index 2d36139..378c568 100755
--- a/debug_rom/debug_rom.S
+++ b/debug_rom/debug_rom.S
@@ -7,6 +7,19 @@
.global entry
.global exception
+// This macro handles mem access with proper management of the MPRVEN
+// Usage: MEMORY_ACCESS_WITH_MPRV(<your code>)
+#define MEMORY_ACCESS_WITH_MPRV(...) \
+ csrrci s0, CSR_DCSR, DCSR_MPRVEN; \
+ andi s0, s0, DCSR_MPRVEN; \
+ bnez s0, 1f; \
+ __VA_ARGS__; \
+ j 2f; \
+1: \
+ __VA_ARGS__; \
+ csrrsi zero, CSR_DCSR, DCSR_MPRVEN; \
+2:
+
// Entry location on ebreak, Halt, or Breakpoint
// It is the same for all harts. They branch when
// their GO or RESUME bit is set.
@@ -30,13 +43,22 @@ _entry:
// We keep checking both whether there is something the debugger wants
// us to do, or whether we should resume.
entry_loop:
- csrr s0, CSR_MHARTID
- sw s0, DEBUG_ROM_HALTED(zero)
- lbu s0, DEBUG_ROM_FLAGS(s0) // 1 byte flag per hart. Only one hart advances here.
+ // 1 byte flag per hart. Only one hart advances here.
+ MEMORY_ACCESS_WITH_MPRV(
+ csrr s0, CSR_MHARTID;
+ sw s0, DEBUG_ROM_HALTED(zero);
+ lbu s0, DEBUG_ROM_FLAGS(s0);
+ )
+
andi s0, s0, (1 << DEBUG_ROM_FLAG_GO)
bnez s0, going
- csrr s0, CSR_MHARTID
- lbu s0, DEBUG_ROM_FLAGS(s0) // multiple harts can resume here
+
+ // multiple harts can resume here
+ MEMORY_ACCESS_WITH_MPRV(
+ csrr s0, CSR_MHARTID;
+ lbu s0, DEBUG_ROM_FLAGS(s0);
+ )
+
andi s0, s0, (1 << DEBUG_ROM_FLAG_RESUME)
bnez s0, _resume
wfi
@@ -46,13 +68,23 @@ _exception:
// Restore S0, which we always save to dscratch.
// We need this in case the user tried an abstract write to a
// non-existent CSR.
- csrr s0, CSR_DSCRATCH0
- sw zero, DEBUG_ROM_EXCEPTION(zero) // Let debug module know you got an exception.
+
+
+ // Let debug module know you got an exception.
+ MEMORY_ACCESS_WITH_MPRV(
+ csrr s0, CSR_DSCRATCH0;
+ sw zero, DEBUG_ROM_EXCEPTION(zero);
+ )
+
ebreak
going:
- csrr s0, CSR_MHARTID
- sw s0, DEBUG_ROM_GOING(zero) // When debug module sees this write, the GO flag is reset.
+ // When debug module sees this write, the GO flag is reset.
+ MEMORY_ACCESS_WITH_MPRV(
+ csrr s0, CSR_MHARTID;
+ sw s0, DEBUG_ROM_GOING(zero);
+ )
+
csrr s0, CSR_DSCRATCH0 // Restore s0 here
fence
fence.i
@@ -61,8 +93,12 @@ going:
// because jalr is special there)
_resume:
- csrr s0, CSR_MHARTID
- sw s0, DEBUG_ROM_RESUMING(zero) // When Debug Module sees this write, the RESUME flag is reset.
+ // When Debug Module sees this write, the RESUME flag is reset.
+ MEMORY_ACCESS_WITH_MPRV(
+ csrr s0, CSR_MHARTID;
+ sw s0, DEBUG_ROM_RESUMING(zero);
+ )
+
csrr s0, CSR_DSCRATCH0 // Restore s0
dret
diff --git a/debug_rom/debug_rom.h b/debug_rom/debug_rom.h
index 7edd5f6..d3d89a2 100644
--- a/debug_rom/debug_rom.h
+++ b/debug_rom/debug_rom.h
@@ -1,13 +1,25 @@
static const unsigned char debug_rom_raw[] = {
- 0x6f, 0x00, 0xc0, 0x00, 0x6f, 0x00, 0x00, 0x06, 0x6f, 0x00, 0x80, 0x03,
- 0x0f, 0x00, 0xf0, 0x0f, 0x73, 0x10, 0x24, 0x7b, 0x73, 0x24, 0x40, 0xf1,
- 0x23, 0x20, 0x80, 0x10, 0x03, 0x44, 0x04, 0x40, 0x13, 0x74, 0x14, 0x00,
- 0x63, 0x14, 0x04, 0x02, 0x73, 0x24, 0x40, 0xf1, 0x03, 0x44, 0x04, 0x40,
- 0x13, 0x74, 0x24, 0x00, 0x63, 0x18, 0x04, 0x02, 0x73, 0x00, 0x50, 0x10,
- 0x6f, 0xf0, 0x9f, 0xfd, 0x73, 0x24, 0x20, 0x7b, 0x23, 0x26, 0x00, 0x10,
- 0x73, 0x00, 0x10, 0x00, 0x73, 0x24, 0x40, 0xf1, 0x23, 0x22, 0x80, 0x10,
- 0x73, 0x24, 0x20, 0x7b, 0x0f, 0x00, 0xf0, 0x0f, 0x0f, 0x10, 0x00, 0x00,
- 0x67, 0x00, 0x00, 0x30, 0x73, 0x24, 0x40, 0xf1, 0x23, 0x24, 0x80, 0x10,
+ 0x6f, 0x00, 0xc0, 0x00, 0x6f, 0x00, 0x40, 0x0d, 0x6f, 0x00, 0x40, 0x07,
+ 0x0f, 0x00, 0xf0, 0x0f, 0x73, 0x10, 0x24, 0x7b, 0x73, 0x74, 0x08, 0x7b,
+ 0x13, 0x74, 0x04, 0x01, 0x63, 0x1a, 0x04, 0x00, 0x73, 0x24, 0x40, 0xf1,
+ 0x23, 0x20, 0x80, 0x10, 0x03, 0x44, 0x04, 0x40, 0x6f, 0x00, 0x40, 0x01,
+ 0x73, 0x24, 0x40, 0xf1, 0x23, 0x20, 0x80, 0x10, 0x03, 0x44, 0x04, 0x40,
+ 0x73, 0x60, 0x08, 0x7b, 0x13, 0x74, 0x14, 0x00, 0x63, 0x10, 0x04, 0x06,
+ 0x73, 0x74, 0x08, 0x7b, 0x13, 0x74, 0x04, 0x01, 0x63, 0x18, 0x04, 0x00,
+ 0x73, 0x24, 0x40, 0xf1, 0x03, 0x44, 0x04, 0x40, 0x6f, 0x00, 0x00, 0x01,
+ 0x73, 0x24, 0x40, 0xf1, 0x03, 0x44, 0x04, 0x40, 0x73, 0x60, 0x08, 0x7b,
+ 0x13, 0x74, 0x24, 0x00, 0x63, 0x14, 0x04, 0x06, 0x73, 0x00, 0x50, 0x10,
+ 0x6f, 0xf0, 0xdf, 0xf9, 0x73, 0x74, 0x08, 0x7b, 0x13, 0x74, 0x04, 0x01,
+ 0x63, 0x18, 0x04, 0x00, 0x73, 0x24, 0x20, 0x7b, 0x23, 0x26, 0x00, 0x10,
+ 0x6f, 0x00, 0x00, 0x01, 0x73, 0x24, 0x20, 0x7b, 0x23, 0x26, 0x00, 0x10,
+ 0x73, 0x60, 0x08, 0x7b, 0x73, 0x00, 0x10, 0x00, 0x73, 0x74, 0x08, 0x7b,
+ 0x13, 0x74, 0x04, 0x01, 0x63, 0x18, 0x04, 0x00, 0x73, 0x24, 0x40, 0xf1,
+ 0x23, 0x22, 0x80, 0x10, 0x6f, 0x00, 0x00, 0x01, 0x73, 0x24, 0x40, 0xf1,
+ 0x23, 0x22, 0x80, 0x10, 0x73, 0x60, 0x08, 0x7b, 0x73, 0x24, 0x20, 0x7b,
+ 0x0f, 0x00, 0xf0, 0x0f, 0x0f, 0x10, 0x00, 0x00, 0x67, 0x00, 0x00, 0x30,
+ 0x73, 0x74, 0x08, 0x7b, 0x13, 0x74, 0x04, 0x01, 0x63, 0x18, 0x04, 0x00,
+ 0x73, 0x24, 0x40, 0xf1, 0x23, 0x24, 0x80, 0x10, 0x6f, 0x00, 0x00, 0x01,
+ 0x73, 0x24, 0x40, 0xf1, 0x23, 0x24, 0x80, 0x10, 0x73, 0x60, 0x08, 0x7b,
0x73, 0x24, 0x20, 0x7b, 0x73, 0x00, 0x20, 0x7b
};
-static const unsigned int debug_rom_raw_len = 116;
+static const unsigned int debug_rom_raw_len = 260;
diff --git a/disasm/disasm.cc b/disasm/disasm.cc
index c3ba62a..49f2794 100644
--- a/disasm/disasm.cc
+++ b/disasm/disasm.cc
@@ -2,6 +2,7 @@
#include "disasm.h"
#include "decode_macros.h"
+#include "platform.h"
#include <cassert>
#include <string>
#include <vector>
@@ -705,44 +706,39 @@ static void NOINLINE add_sfence_insn(disassembler_t* d, const char* name, uint32
d->add_insn(new disasm_insn_t(name, match, mask, {&xrs1, &xrs2}));
}
-static void NOINLINE add_pitype3_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask)
+static void NOINLINE add_vector_v_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask)
{
- d->add_insn(new disasm_insn_t(name, match, mask, {&xrd, &xrs1, &p_imm3}));
+ d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &vs2, opt, &vm}));
}
-static void NOINLINE add_pitype4_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask)
+static void NOINLINE add_vector_vv_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask)
{
- d->add_insn(new disasm_insn_t(name, match, mask, {&xrd, &xrs1, &p_imm4}));
+ d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &vs2, &vs1, opt, &vm}));
}
-static void NOINLINE add_pitype5_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask)
+static void NOINLINE add_vector_multiplyadd_vv_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask)
{
- d->add_insn(new disasm_insn_t(name, match, mask, {&xrd, &xrs1, &p_imm5}));
+ d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &vs1, &vs2, opt, &vm}));
}
-static void NOINLINE add_pitype6_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask)
+static void NOINLINE add_vector_vx_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask)
{
- d->add_insn(new disasm_insn_t(name, match, mask, {&xrd, &xrs1, &p_imm6}));
+ d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &vs2, &xrs1, opt, &vm}));
}
-static void NOINLINE add_vector_v_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask)
+static void NOINLINE add_vector_multiplyadd_vx_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask)
{
- d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &vs2, opt, &vm}));
+ d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &xrs1, &vs2, opt, &vm}));
}
-static void NOINLINE add_vector_vv_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask)
+static void NOINLINE add_vector_vf_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask)
{
- d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &vs2, &vs1, opt, &vm}));
+ d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &vs2, &frs1, opt, &vm}));
}
-static void NOINLINE add_vector_vx_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask)
+static void NOINLINE add_vector_multiplyadd_vf_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask)
{
- d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &vs2, &xrs1, opt, &vm}));
-}
-
-static void NOINLINE add_vector_vf_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask)
-{
- d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &vs2, &frs1, opt, &vm}));
+ d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &frs1, &vs2, opt, &vm}));
}
static void NOINLINE add_vector_vi_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask)
@@ -793,7 +789,12 @@ static void NOINLINE add_unknown_insns(disassembler_t* d)
#undef DECLARE_INSN
}
-void disassembler_t::add_instructions(const isa_parser_t* isa)
+#define ext_enabled_strict(x) (isa->extension_enabled(x))
+#define ext_enabled(x) (ext_enabled_strict(x) || !strict)
+#define xlen_eq(x) (xlen_eq_strict(x) || !strict)
+#define xlen_eq_strict(x) (isa->get_max_xlen() == (x))
+
+void disassembler_t::add_instructions(const isa_parser_t* isa, bool strict)
{
const uint32_t mask_rd = 0x1fUL << 7;
const uint32_t match_rd_ra = 1UL << 7;
@@ -866,16 +867,19 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_XLOAD(lh)
DEFINE_XLOAD(lhu)
DEFINE_XLOAD(lw)
- DEFINE_XLOAD(lwu)
- DEFINE_XLOAD(ld)
DEFINE_XSTORE(sb)
DEFINE_XSTORE(sh)
DEFINE_XSTORE(sw)
- DEFINE_XSTORE(sd)
- if (isa->extension_enabled('A') ||
- isa->extension_enabled(EXT_ZAAMO)) {
+ if (xlen_eq(64)) {
+ DEFINE_XLOAD(lwu)
+ DEFINE_XLOAD(ld)
+
+ DEFINE_XSTORE(sd)
+ }
+
+ if (ext_enabled(EXT_ZAAMO)) {
DEFINE_XAMO(amoadd_w)
DEFINE_XAMO(amoswap_w)
DEFINE_XAMO(amoand_w)
@@ -885,32 +889,39 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_XAMO(amomax_w)
DEFINE_XAMO(amominu_w)
DEFINE_XAMO(amomaxu_w)
- DEFINE_XAMO(amoadd_d)
- DEFINE_XAMO(amoswap_d)
- DEFINE_XAMO(amoand_d)
- DEFINE_XAMO(amoor_d)
- DEFINE_XAMO(amoxor_d)
- DEFINE_XAMO(amomin_d)
- DEFINE_XAMO(amomax_d)
- DEFINE_XAMO(amominu_d)
- DEFINE_XAMO(amomaxu_d)
- }
-
- if (isa->extension_enabled('A') ||
- isa->extension_enabled(EXT_ZALRSC)) {
+
+ if (xlen_eq(64)) {
+ DEFINE_XAMO(amoadd_d)
+ DEFINE_XAMO(amoswap_d)
+ DEFINE_XAMO(amoand_d)
+ DEFINE_XAMO(amoor_d)
+ DEFINE_XAMO(amoxor_d)
+ DEFINE_XAMO(amomin_d)
+ DEFINE_XAMO(amomax_d)
+ DEFINE_XAMO(amominu_d)
+ DEFINE_XAMO(amomaxu_d)
+ }
+ }
+
+ if (ext_enabled(EXT_ZALRSC)) {
DEFINE_XLOAD_BASE(lr_w)
DEFINE_XAMO(sc_w)
- DEFINE_XLOAD_BASE(lr_d)
- DEFINE_XAMO(sc_d)
+
+ if (xlen_eq(64)) {
+ DEFINE_XLOAD_BASE(lr_d)
+ DEFINE_XAMO(sc_d)
+ }
}
- if (isa->extension_enabled(EXT_ZACAS)) {
+ if (ext_enabled(EXT_ZACAS)) {
DEFINE_XAMO(amocas_w)
DEFINE_XAMO(amocas_d)
- DEFINE_XAMO(amocas_q)
+
+ if (xlen_eq(64))
+ DEFINE_XAMO(amocas_q)
}
- if (isa->extension_enabled(EXT_ZABHA)) {
+ if (ext_enabled(EXT_ZABHA)) {
DEFINE_XAMO(amoadd_b)
DEFINE_XAMO(amoswap_b)
DEFINE_XAMO(amoand_b)
@@ -933,12 +944,12 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_XAMO(amocas_h)
}
- if (isa->extension_enabled(EXT_ZAWRS)) {
+ if (ext_enabled(EXT_ZAWRS)) {
DEFINE_NOARG(wrs_sto);
DEFINE_NOARG(wrs_nto);
}
- if (isa->extension_enabled(EXT_ZICFILP)) {
+ if (ext_enabled(EXT_ZICFILP)) {
// lpad encodes as `auipc x0, label`, so it needs to be added before auipc
// for higher disassembling priority
DISASM_INSN("lpad", lpad, 0, {&bigimm});
@@ -983,12 +994,21 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_ITYPE(ori);
DEFINE_ITYPE(andi);
- DEFINE_I1TYPE("sext.w", addiw);
- DEFINE_ITYPE(addiw);
- DEFINE_ITYPE_SHIFT(slliw);
- DEFINE_ITYPE_SHIFT(srliw);
- DEFINE_ITYPE_SHIFT(sraiw);
+ if (xlen_eq(64)) {
+ DEFINE_I1TYPE("sext.w", addiw);
+ DEFINE_ITYPE(addiw);
+
+ DEFINE_ITYPE_SHIFT(slliw);
+ DEFINE_ITYPE_SHIFT(srliw);
+ DEFINE_ITYPE_SHIFT(sraiw);
+
+ DEFINE_RTYPE(addw);
+ DEFINE_RTYPE(subw);
+ DEFINE_RTYPE(sllw);
+ DEFINE_RTYPE(srlw);
+ DEFINE_RTYPE(sraw);
+ }
DEFINE_RTYPE(add);
DEFINE_RTYPE(sub);
@@ -1001,11 +1021,6 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_RTYPE(sra);
DEFINE_RTYPE(or);
DEFINE_RTYPE(and);
- DEFINE_RTYPE(addw);
- DEFINE_RTYPE(subw);
- DEFINE_RTYPE(sllw);
- DEFINE_RTYPE(srlw);
- DEFINE_RTYPE(sraw);
DEFINE_NOARG(ecall);
DEFINE_NOARG(ebreak);
@@ -1029,32 +1044,35 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
add_insn(new disasm_insn_t("csrrsi", match_csrrsi, mask_csrrsi, {&xrd, &csr, &zimm5}));
add_insn(new disasm_insn_t("csrrci", match_csrrci, mask_csrrci, {&xrd, &csr, &zimm5}));
- if (isa->extension_enabled('S')) {
+ if (ext_enabled('S')) {
DEFINE_NOARG(sret);
DEFINE_SFENCE_TYPE(sfence_vma);
}
- if (isa->extension_enabled('M')) {
+ if (ext_enabled('M')) {
DEFINE_RTYPE(mul);
DEFINE_RTYPE(mulh);
DEFINE_RTYPE(mulhu);
DEFINE_RTYPE(mulhsu);
- DEFINE_RTYPE(mulw);
DEFINE_RTYPE(div);
DEFINE_RTYPE(divu);
DEFINE_RTYPE(rem);
DEFINE_RTYPE(remu);
- DEFINE_RTYPE(divw);
- DEFINE_RTYPE(divuw);
- DEFINE_RTYPE(remw);
- DEFINE_RTYPE(remuw);
+
+ if (xlen_eq(64)) {
+ DEFINE_RTYPE(mulw);
+ DEFINE_RTYPE(divw);
+ DEFINE_RTYPE(divuw);
+ DEFINE_RTYPE(remw);
+ DEFINE_RTYPE(remuw);
+ }
}
- if (isa->extension_enabled(EXT_ZBA)) {
+ if (ext_enabled(EXT_ZBA)) {
DEFINE_RTYPE(sh1add);
DEFINE_RTYPE(sh2add);
DEFINE_RTYPE(sh3add);
- if (isa->get_max_xlen() == 64) {
+ if (xlen_eq(64)) {
DEFINE_ITYPE_SHIFT(slli_uw);
add_insn(new disasm_insn_t("zext.w", match_add_uw, mask_add_uw | mask_rs2, {&xrd, &xrs1}));
DEFINE_RTYPE(add_uw);
@@ -1064,7 +1082,7 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
}
}
- if (isa->extension_enabled(EXT_ZBB)) {
+ if (ext_enabled(EXT_ZBB)) {
DEFINE_RTYPE(ror);
DEFINE_RTYPE(rol);
DEFINE_ITYPE_SHIFT(rori);
@@ -1083,7 +1101,7 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
add_insn(new disasm_insn_t("rev8", match_grevi | ((isa->get_max_xlen() - 8) << imm_shift), mask_grevi | mask_imm, {&xrd, &xrs1}));
add_insn(new disasm_insn_t("orc.b", match_gorci | (0x7 << imm_shift), mask_grevi | mask_imm, {&xrd, &xrs1}));
add_insn(new disasm_insn_t("zext.h", (isa->get_max_xlen() == 32 ? match_pack : match_packw), mask_pack | mask_rs2, {&xrd, &xrs1}));
- if (isa->get_max_xlen() == 64) {
+ if (xlen_eq(64)) {
DEFINE_RTYPE(rorw);
DEFINE_RTYPE(rolw);
DEFINE_ITYPE_SHIFT(roriw);
@@ -1093,13 +1111,13 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
}
}
- if (isa->extension_enabled(EXT_ZBC)) {
+ if (ext_enabled(EXT_ZBC)) {
DEFINE_RTYPE(clmul);
DEFINE_RTYPE(clmulh);
DEFINE_RTYPE(clmulr);
}
- if (isa->extension_enabled(EXT_ZBS)) {
+ if (ext_enabled(EXT_ZBS)) {
DEFINE_RTYPE(bclr);
DEFINE_RTYPE(binv);
DEFINE_RTYPE(bset);
@@ -1110,17 +1128,17 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_ITYPE_SHIFT(bexti);
}
- if (isa->extension_enabled(EXT_ZBKB)) {
+ if (ext_enabled(EXT_ZBKB)) {
add_insn(new disasm_insn_t("brev8", match_grevi | (0x7 << imm_shift), mask_grevi | mask_imm, {&xrd, &xrs1})); // brev8
add_insn(new disasm_insn_t("rev8", match_grevi | ((isa->get_max_xlen() - 8) << imm_shift), mask_grevi | mask_imm, {&xrd, &xrs1}));
DEFINE_RTYPE(pack);
DEFINE_RTYPE(packh);
- if (isa->get_max_xlen() == 64) {
+ if (xlen_eq(64)) {
DEFINE_RTYPE(packw);
}
}
- if (isa->extension_enabled(EXT_SVINVAL)) {
+ if (ext_enabled(EXT_SVINVAL)) {
DEFINE_NOARG(sfence_w_inval);
DEFINE_NOARG(sfence_inval_ir);
DEFINE_SFENCE_TYPE(sinval_vma);
@@ -1128,9 +1146,14 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_SFENCE_TYPE(hinval_gvma);
}
- if (isa->extension_enabled('F')) {
+ if (ext_enabled('F')) {
DEFINE_FLOAD(flw)
DEFINE_FSTORE(fsw)
+ DEFINE_XFTYPE(fmv_w_x);
+ DEFINE_FXTYPE(fmv_x_w);
+ }
+
+ if (ext_enabled('F') || ext_enabled(EXT_ZFINX)) {
DEFINE_FRTYPE(fadd_s);
DEFINE_FRTYPE(fsub_s);
DEFINE_FRTYPE(fmul_s);
@@ -1147,58 +1170,35 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_FRTYPE(fsgnjx_s);
DEFINE_FR1TYPE(fcvt_s_d);
DEFINE_FR1TYPE(fcvt_s_q);
- DEFINE_XFTYPE(fcvt_s_l);
- DEFINE_XFTYPE(fcvt_s_lu);
DEFINE_XFTYPE(fcvt_s_w);
DEFINE_XFTYPE(fcvt_s_wu);
DEFINE_XFTYPE(fcvt_s_wu);
- DEFINE_XFTYPE(fmv_w_x);
- DEFINE_FXTYPE(fcvt_l_s);
- DEFINE_FXTYPE(fcvt_lu_s);
DEFINE_FXTYPE(fcvt_w_s);
DEFINE_FXTYPE(fcvt_wu_s);
DEFINE_FXTYPE(fclass_s);
- DEFINE_FXTYPE(fmv_x_w);
DEFINE_FX2TYPE(feq_s);
DEFINE_FX2TYPE(flt_s);
DEFINE_FX2TYPE(fle_s);
+
+ if (xlen_eq(64)) {
+ DEFINE_XFTYPE(fcvt_s_l);
+ DEFINE_XFTYPE(fcvt_s_lu);
+ DEFINE_FXTYPE(fcvt_l_s);
+ DEFINE_FXTYPE(fcvt_lu_s);
+ }
}
- if (isa->extension_enabled(EXT_ZFINX)) {
- DEFINE_RTYPE(fadd_s);
- DEFINE_RTYPE(fsub_s);
- DEFINE_RTYPE(fmul_s);
- DEFINE_RTYPE(fdiv_s);
- DEFINE_R1TYPE(fsqrt_s);
- DEFINE_RTYPE(fmin_s);
- DEFINE_RTYPE(fmax_s);
- DEFINE_R3TYPE(fmadd_s);
- DEFINE_R3TYPE(fmsub_s);
- DEFINE_R3TYPE(fnmadd_s);
- DEFINE_R3TYPE(fnmsub_s);
- DEFINE_RTYPE(fsgnj_s);
- DEFINE_RTYPE(fsgnjn_s);
- DEFINE_RTYPE(fsgnjx_s);
- DEFINE_R1TYPE(fcvt_s_d);
- //DEFINE_R1TYPE(fcvt_s_q);
- DEFINE_R1TYPE(fcvt_s_l);
- DEFINE_R1TYPE(fcvt_s_lu);
- DEFINE_R1TYPE(fcvt_s_w);
- DEFINE_R1TYPE(fcvt_s_wu);
- DEFINE_R1TYPE(fcvt_s_wu);
- DEFINE_R1TYPE(fcvt_l_s);
- DEFINE_R1TYPE(fcvt_lu_s);
- DEFINE_R1TYPE(fcvt_w_s);
- DEFINE_R1TYPE(fcvt_wu_s);
- DEFINE_R1TYPE(fclass_s);
- DEFINE_RTYPE(feq_s);
- DEFINE_RTYPE(flt_s);
- DEFINE_RTYPE(fle_s);
- }
-
- if (isa->extension_enabled('D')) {
+ if (ext_enabled('D')) {
DEFINE_FLOAD(fld)
DEFINE_FSTORE(fsd)
+
+ if (xlen_eq(64)) {
+ DEFINE_XFTYPE(fmv_d_x);
+ DEFINE_FXTYPE(fmv_x_d);
+ }
+ }
+
+ if (ext_enabled('D') || ext_enabled(EXT_ZDINX)) {
DEFINE_FRTYPE(fadd_d);
DEFINE_FRTYPE(fsub_d);
DEFINE_FRTYPE(fmul_d);
@@ -1215,24 +1215,25 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_FRTYPE(fsgnjx_d);
DEFINE_FR1TYPE(fcvt_d_s);
DEFINE_FR1TYPE(fcvt_d_q);
- DEFINE_XFTYPE(fcvt_d_l);
- DEFINE_XFTYPE(fcvt_d_lu);
DEFINE_XFTYPE(fcvt_d_w);
DEFINE_XFTYPE(fcvt_d_wu);
DEFINE_XFTYPE(fcvt_d_wu);
- DEFINE_XFTYPE(fmv_d_x);
- DEFINE_FXTYPE(fcvt_l_d);
- DEFINE_FXTYPE(fcvt_lu_d);
DEFINE_FXTYPE(fcvt_w_d);
DEFINE_FXTYPE(fcvt_wu_d);
DEFINE_FXTYPE(fclass_d);
- DEFINE_FXTYPE(fmv_x_d);
DEFINE_FX2TYPE(feq_d);
DEFINE_FX2TYPE(flt_d);
DEFINE_FX2TYPE(fle_d);
+
+ if (xlen_eq(64)) {
+ DEFINE_XFTYPE(fcvt_d_l);
+ DEFINE_XFTYPE(fcvt_d_lu);
+ DEFINE_FXTYPE(fcvt_l_d);
+ DEFINE_FXTYPE(fcvt_lu_d);
+ }
}
- if (isa->extension_enabled(EXT_ZFA)) {
+ if (ext_enabled(EXT_ZFA)) {
DEFINE_FLITYPE(fli_s);
DEFINE_FRTYPE(fminm_s);
DEFINE_FRTYPE(fmaxm_s);
@@ -1241,7 +1242,7 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_FX2TYPE(fleq_s);
DEFINE_FX2TYPE(fltq_s);
- if (isa->extension_enabled(EXT_ZFH) || isa->extension_enabled(EXT_ZVFH)) {
+ if (ext_enabled(EXT_ZFH) || ext_enabled(EXT_ZVFH)) {
DEFINE_FLITYPE(fli_h);
DEFINE_FRTYPE(fminm_h);
DEFINE_FRTYPE(fmaxm_h);
@@ -1251,7 +1252,7 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_FX2TYPE(fltq_h);
}
- if (isa->extension_enabled('D')) {
+ if (ext_enabled('D')) {
DEFINE_FLITYPE(fli_d);
DEFINE_FRTYPE(fminm_d);
DEFINE_FRTYPE(fmaxm_d);
@@ -1260,13 +1261,13 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_FX2TYPE(fleq_d);
DEFINE_FX2TYPE(fltq_d);
- if (isa->get_max_xlen() == 32) {
+ if (xlen_eq(32)) {
DEFINE_XF2TYPE(fmvp_d_x);
DEFINE_FXTYPE(fmvh_x_d);
}
}
- if (isa->extension_enabled('Q')) {
+ if (ext_enabled('Q')) {
DEFINE_FLITYPE(fli_q);
DEFINE_FRTYPE(fminm_q);
DEFINE_FRTYPE(fmaxm_q);
@@ -1275,46 +1276,14 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_FX2TYPE(fleq_q);
DEFINE_FX2TYPE(fltq_q);
- if (isa->get_max_xlen() == 64) {
+ if (xlen_eq(64)) {
DEFINE_XF2TYPE(fmvp_q_x);
DEFINE_FXTYPE(fmvh_x_q);
}
}
}
- if (isa->extension_enabled(EXT_ZDINX)) {
- DEFINE_RTYPE(fadd_d);
- DEFINE_RTYPE(fsub_d);
- DEFINE_RTYPE(fmul_d);
- DEFINE_RTYPE(fdiv_d);
- DEFINE_R1TYPE(fsqrt_d);
- DEFINE_RTYPE(fmin_d);
- DEFINE_RTYPE(fmax_d);
- DEFINE_R3TYPE(fmadd_d);
- DEFINE_R3TYPE(fmsub_d);
- DEFINE_R3TYPE(fnmadd_d);
- DEFINE_R3TYPE(fnmsub_d);
- DEFINE_RTYPE(fsgnj_d);
- DEFINE_RTYPE(fsgnjn_d);
- DEFINE_RTYPE(fsgnjx_d);
- DEFINE_R1TYPE(fcvt_d_s);
- //DEFINE_R1TYPE(fcvt_d_q);
- DEFINE_R1TYPE(fcvt_d_l);
- DEFINE_R1TYPE(fcvt_d_lu);
- DEFINE_R1TYPE(fcvt_d_w);
- DEFINE_R1TYPE(fcvt_d_wu);
- DEFINE_R1TYPE(fcvt_d_wu);
- DEFINE_R1TYPE(fcvt_l_d);
- DEFINE_R1TYPE(fcvt_lu_d);
- DEFINE_R1TYPE(fcvt_w_d);
- DEFINE_R1TYPE(fcvt_wu_d);
- DEFINE_R1TYPE(fclass_d);
- DEFINE_RTYPE(feq_d);
- DEFINE_RTYPE(flt_d);
- DEFINE_RTYPE(fle_d);
- }
-
- if (isa->extension_enabled(EXT_ZFH)) {
+ if (ext_enabled(EXT_ZFH)) {
DEFINE_FRTYPE(fadd_h);
DEFINE_FRTYPE(fsub_h);
DEFINE_FRTYPE(fmul_h);
@@ -1344,7 +1313,7 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_FX2TYPE(fle_h);
}
- if (isa->extension_enabled(EXT_ZHINX)) {
+ if (ext_enabled(EXT_ZHINX)) {
DEFINE_RTYPE(fadd_h);
DEFINE_RTYPE(fsub_h);
DEFINE_RTYPE(fmul_h);
@@ -1374,7 +1343,7 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_RTYPE(fle_h);
}
- if (isa->extension_enabled(EXT_ZFHMIN)) {
+ if (ext_enabled(EXT_ZFHMIN)) {
DEFINE_FR1TYPE(fcvt_h_s);
DEFINE_FR1TYPE(fcvt_h_d);
DEFINE_FR1TYPE(fcvt_h_q);
@@ -1383,14 +1352,14 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_FR1TYPE(fcvt_q_h);
}
- if (isa->extension_enabled(EXT_INTERNAL_ZFH_MOVE)) {
+ if (ext_enabled(EXT_INTERNAL_ZFH_MOVE)) {
DEFINE_FLOAD(flh)
DEFINE_FSTORE(fsh)
DEFINE_XFTYPE(fmv_h_x);
DEFINE_FXTYPE(fmv_x_h);
}
- if (isa->extension_enabled(EXT_ZHINXMIN)) {
+ if (ext_enabled(EXT_ZHINXMIN)) {
DEFINE_R1TYPE(fcvt_h_s);
DEFINE_R1TYPE(fcvt_h_d);
//DEFINE_R1TYPE(fcvt_h_q);
@@ -1399,7 +1368,7 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
//DEFINE_R1TYPE(fcvt_q_h);
}
- if (isa->extension_enabled('Q')) {
+ if (ext_enabled('Q')) {
DEFINE_FLOAD(flq)
DEFINE_FSTORE(fsq)
DEFINE_FRTYPE(fadd_q);
@@ -1433,13 +1402,13 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_FX2TYPE(fle_q);
}
- if (isa->extension_enabled(EXT_ZFBFMIN)) {
+ if (ext_enabled(EXT_ZFBFMIN)) {
DEFINE_FR1TYPE(fcvt_bf16_s);
DEFINE_FR1TYPE(fcvt_s_bf16);
}
// ext-h
- if (isa->extension_enabled('H')) {
+ if (ext_enabled('H')) {
DEFINE_XLOAD_BASE(hlv_b)
DEFINE_XLOAD_BASE(hlv_bu)
DEFINE_XLOAD_BASE(hlv_h)
@@ -1461,7 +1430,7 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
}
// ext-c
- if (isa->extension_enabled(EXT_ZCA)) {
+ if (ext_enabled(EXT_ZCA)) {
DISASM_INSN("c.ebreak", c_add, mask_rd | mask_rvc_rs2, {});
add_insn(new disasm_insn_t("ret", match_c_jr | match_rd_ra, mask_c_jr | mask_rd | mask_rvc_imm, {}));
DISASM_INSN("c.jr", c_jr, mask_rvc_imm, {&rvc_rs1});
@@ -1478,9 +1447,7 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DISASM_INSN("c.andi", c_andi, 0, {&rvc_rs1s, &rvc_imm});
DISASM_INSN("c.mv", c_mv, 0, {&xrd, &rvc_rs2});
DISASM_INSN("c.add", c_add, 0, {&xrd, &rvc_rs2});
- DISASM_INSN("c.addw", c_addw, 0, {&rvc_rs1s, &rvc_rs2s});
DISASM_INSN("c.sub", c_sub, 0, {&rvc_rs1s, &rvc_rs2s});
- DISASM_INSN("c.subw", c_subw, 0, {&rvc_rs1s, &rvc_rs2s});
DISASM_INSN("c.and", c_and, 0, {&rvc_rs1s, &rvc_rs2s});
DISASM_INSN("c.or", c_or, 0, {&rvc_rs1s, &rvc_rs2s});
DISASM_INSN("c.xor", c_xor, 0, {&rvc_rs1s, &rvc_rs2s});
@@ -1491,13 +1458,18 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DISASM_INSN("c.beqz", c_beqz, 0, {&rvc_rs1s, &rvc_branch_target});
DISASM_INSN("c.bnez", c_bnez, 0, {&rvc_rs1s, &rvc_branch_target});
DISASM_INSN("c.j", c_j, 0, {&rvc_jump_target});
- if (isa->get_max_xlen() == 32) {
+ if (xlen_eq_strict(32)) {
DISASM_INSN("c.jal", c_jal, 0, {&rvc_jump_target});
} else {
DISASM_INSN("c.addiw", c_addiw, 0, {&xrd, &rvc_imm});
}
- if (isa->get_max_xlen() == 64 || isa->extension_enabled(EXT_ZCMLSD)) {
+ if (xlen_eq(64)) {
+ DISASM_INSN("c.addw", c_addw, 0, {&rvc_rs1s, &rvc_rs2s});
+ DISASM_INSN("c.subw", c_subw, 0, {&rvc_rs1s, &rvc_rs2s});
+ }
+
+ if (xlen_eq_strict(64) || ext_enabled_strict(EXT_ZCLSD)) {
DISASM_INSN("c.ld", c_ld, 0, {&rvc_rs2s, &rvc_ld_address});
DISASM_INSN("c.ldsp", c_ldsp, 0, {&xrd, &rvc_ldsp_address});
DISASM_INSN("c.sd", c_sd, 0, {&rvc_rs2s, &rvc_ld_address});
@@ -1505,26 +1477,26 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
}
}
- if (isa->extension_enabled(EXT_ZCD) && isa->extension_enabled('D')) {
+ if (ext_enabled(EXT_ZCD)) {
DISASM_INSN("c.fld", c_fld, 0, {&rvc_fp_rs2s, &rvc_ld_address});
DISASM_INSN("c.fldsp", c_fldsp, 0, {&frd, &rvc_ldsp_address});
DISASM_INSN("c.fsd", c_fsd, 0, {&rvc_fp_rs2s, &rvc_ld_address});
DISASM_INSN("c.fsdsp", c_fsdsp, 0, {&rvc_fp_rs2, &rvc_sdsp_address});
}
- if (isa->extension_enabled(EXT_ZCF) && isa->extension_enabled('F')) {
+ if (ext_enabled(EXT_ZCF)) {
DISASM_INSN("c.flw", c_flw, 0, {&rvc_fp_rs2s, &rvc_lw_address});
DISASM_INSN("c.flwsp", c_flwsp, 0, {&frd, &rvc_lwsp_address});
DISASM_INSN("c.fsw", c_fsw, 0, {&rvc_fp_rs2s, &rvc_lw_address});
DISASM_INSN("c.fswsp", c_fswsp, 0, {&rvc_fp_rs2, &rvc_swsp_address});
}
- if (isa->extension_enabled(EXT_ZCB)) {
+ if (ext_enabled(EXT_ZCB)) {
DISASM_INSN("c.zext.b", c_zext_b, 0, {&rvc_rs1s});
DISASM_INSN("c.sext.b", c_sext_b, 0, {&rvc_rs1s});
DISASM_INSN("c.zext.h", c_zext_h, 0, {&rvc_rs1s});
DISASM_INSN("c.sext.h", c_sext_h, 0, {&rvc_rs1s});
- if (isa->get_max_xlen() == 64) {
+ if (xlen_eq(64)) {
DISASM_INSN("c.zext.w", c_zext_w, 0, {&rvc_rs1s});
}
DISASM_INSN("c.not", c_not, 0, {&rvc_rs1s});
@@ -1536,8 +1508,8 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DISASM_INSN("c.sh", c_sh, 0, {&rvc_rs2s, &rvb_h_address});
}
- if (isa->extension_enabled(EXT_ZCMP)) {
- if (isa->get_max_xlen() == 32) {
+ if (ext_enabled(EXT_ZCMP)) {
+ if (xlen_eq_strict(32)) {
DISASM_INSN("cm.push", cm_push, 0, {&rvcm_pushpop_rlist, &rvcm_push_stack_adj_32});
DISASM_INSN("cm.pop", cm_pop, 0, {&rvcm_pushpop_rlist, &rvcm_pop_stack_adj_32});
DISASM_INSN("cm.popret", cm_popret, 0, {&rvcm_pushpop_rlist, &rvcm_pop_stack_adj_32});
@@ -1553,12 +1525,12 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DISASM_INSN("cm.mvsa01", cm_mvsa01, 0, {&rvc_r1s, &rvc_r2s});
}
- if (isa->extension_enabled(EXT_ZCMT)) {
+ if (ext_enabled(EXT_ZCMT)) {
DISASM_INSN("cm.jt", cm_jalt, 0x380, {&rvcm_jt_index});
DISASM_INSN("cm.jalt", cm_jalt, 0, {&rvcm_jt_index});
}
- if (isa->has_any_vector()) {
+ if (isa->has_any_vector() || !strict) {
DISASM_INSN("vsetivli", vsetivli, 0, {&xrd, &zimm5, &v_vtype});
DISASM_INSN("vsetvli", vsetvli, 0, {&xrd, &xrs1, &v_vtype});
DEFINE_RTYPE(vsetvl);
@@ -1642,8 +1614,11 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
#define DEFINE_VECTOR_V(code) add_vector_v_insn(this, #code, match_##code, mask_##code)
#define DEFINE_VECTOR_VV(code) add_vector_vv_insn(this, #code, match_##code, mask_##code)
+ #define DEFINE_VECTOR_MULTIPLYADD_VV(code) add_vector_multiplyadd_vv_insn(this, #code, match_##code, mask_##code)
#define DEFINE_VECTOR_VX(code) add_vector_vx_insn(this, #code, match_##code, mask_##code)
+ #define DEFINE_VECTOR_MULTIPLYADD_VX(code) add_vector_multiplyadd_vx_insn(this, #code, match_##code, mask_##code)
#define DEFINE_VECTOR_VF(code) add_vector_vf_insn(this, #code, match_##code, mask_##code)
+ #define DEFINE_VECTOR_MULTIPLYADD_VF(code) add_vector_multiplyadd_vf_insn(this, #code, match_##code, mask_##code)
#define DEFINE_VECTOR_VI(code) add_vector_vi_insn(this, #code, match_##code, mask_##code)
#define DEFINE_VECTOR_VIU(code) add_vector_viu_insn(this, #code, match_##code, mask_##code)
@@ -1659,6 +1634,10 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_VECTOR_VV(name##_vv); \
DEFINE_VECTOR_VX(name##_vx)
+ #define DISASM_OPIV_MULTIPLYADD_VX__INSN(name, sign) \
+ DEFINE_VECTOR_MULTIPLYADD_VV(name##_vv); \
+ DEFINE_VECTOR_MULTIPLYADD_VX(name##_vx)
+
#define DISASM_OPIV__XI_INSN(name, sign) \
DEFINE_VECTOR_VX(name##_vx); \
if (sign) \
@@ -1678,6 +1657,8 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
#define DISASM_OPIV__X__INSN(name, sign) DEFINE_VECTOR_VX(name##_vx)
+ #define DISASM_OPIV_MULTIPLYADD__X__INSN(name, sign) DEFINE_VECTOR_MULTIPLYADD_VX(name##_vx)
+
#define DEFINE_VECTOR_VVM(name) \
add_vector_vvm_insn(this, #name, match_##name, mask_##name | mask_vm)
@@ -1821,10 +1802,10 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DISASM_OPIV_VX__INSN(vmul, 1);
DISASM_OPIV_VX__INSN(vmulhsu, 0);
DISASM_OPIV_VX__INSN(vmulh, 1);
- DISASM_OPIV_VX__INSN(vmadd, 1);
- DISASM_OPIV_VX__INSN(vnmsub, 1);
- DISASM_OPIV_VX__INSN(vmacc, 1);
- DISASM_OPIV_VX__INSN(vnmsac, 1);
+ DISASM_OPIV_MULTIPLYADD_VX__INSN(vmadd, 1);
+ DISASM_OPIV_MULTIPLYADD_VX__INSN(vnmsub, 1);
+ DISASM_OPIV_MULTIPLYADD_VX__INSN(vmacc, 1);
+ DISASM_OPIV_MULTIPLYADD_VX__INSN(vnmsac, 1);
//0b11_0000
DISASM_OPIV_VX__INSN(vwaddu, 0);
@@ -1838,10 +1819,17 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DISASM_OPIV_VX__INSN(vwmulu, 0);
DISASM_OPIV_VX__INSN(vwmulsu, 0);
DISASM_OPIV_VX__INSN(vwmul, 1);
- DISASM_OPIV_VX__INSN(vwmaccu, 0);
- DISASM_OPIV_VX__INSN(vwmacc, 1);
- DISASM_OPIV__X__INSN(vwmaccus, 1);
- DISASM_OPIV_VX__INSN(vwmaccsu, 0);
+ DISASM_OPIV_MULTIPLYADD_VX__INSN(vwmaccu, 0);
+ DISASM_OPIV_MULTIPLYADD_VX__INSN(vwmacc, 1);
+ DISASM_OPIV_MULTIPLYADD__X__INSN(vwmaccus, 1);
+ DISASM_OPIV_MULTIPLYADD_VX__INSN(vwmaccsu, 0);
+
+ if (ext_enabled(EXT_ZVQDOTQ)) {
+ DISASM_OPIV_VX__INSN(vqdot, 0);
+ DISASM_OPIV_VX__INSN(vqdotu, 0);
+ DISASM_OPIV_VX__INSN(vqdotsu, 0);
+ DISASM_OPIV__X__INSN(vqdotus, 0);
+ }
#undef DISASM_OPIV_VXI_INSN
#undef DISASM_OPIV_VX__INSN
@@ -1858,6 +1846,10 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_VECTOR_VV(name##_vv); \
DEFINE_VECTOR_VF(name##_vf)
+ #define DISASM_OPIV_MULTIPLYADD_VF_INSN(name) \
+ DEFINE_VECTOR_MULTIPLYADD_VV(name##_vv); \
+ DEFINE_VECTOR_MULTIPLYADD_VF(name##_vf)
+
#define DISASM_OPIV_WF_INSN(name) \
DEFINE_VECTOR_VV(name##_wv); \
DEFINE_VECTOR_VF(name##_wf)
@@ -1925,14 +1917,14 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DISASM_OPIV_VF_INSN(vfmul);
DISASM_OPIV__F_INSN(vfrsub);
- DISASM_OPIV_VF_INSN(vfmadd);
- DISASM_OPIV_VF_INSN(vfnmadd);
- DISASM_OPIV_VF_INSN(vfmsub);
- DISASM_OPIV_VF_INSN(vfnmsub);
- DISASM_OPIV_VF_INSN(vfmacc);
- DISASM_OPIV_VF_INSN(vfnmacc);
- DISASM_OPIV_VF_INSN(vfmsac);
- DISASM_OPIV_VF_INSN(vfnmsac);
+ DISASM_OPIV_MULTIPLYADD_VF_INSN(vfmadd);
+ DISASM_OPIV_MULTIPLYADD_VF_INSN(vfnmadd);
+ DISASM_OPIV_MULTIPLYADD_VF_INSN(vfmsub);
+ DISASM_OPIV_MULTIPLYADD_VF_INSN(vfnmsub);
+ DISASM_OPIV_MULTIPLYADD_VF_INSN(vfmacc);
+ DISASM_OPIV_MULTIPLYADD_VF_INSN(vfnmacc);
+ DISASM_OPIV_MULTIPLYADD_VF_INSN(vfmsac);
+ DISASM_OPIV_MULTIPLYADD_VF_INSN(vfnmsac);
//0b11_0000
DISASM_OPIV_VF_INSN(vfwadd);
@@ -1942,10 +1934,10 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DISASM_OPIV_WF_INSN(vfwadd);
DISASM_OPIV_WF_INSN(vfwsub);
DISASM_OPIV_VF_INSN(vfwmul);
- DISASM_OPIV_VF_INSN(vfwmacc);
- DISASM_OPIV_VF_INSN(vfwnmacc);
- DISASM_OPIV_VF_INSN(vfwmsac);
- DISASM_OPIV_VF_INSN(vfwnmsac);
+ DISASM_OPIV_MULTIPLYADD_VF_INSN(vfwmacc);
+ DISASM_OPIV_MULTIPLYADD_VF_INSN(vfwnmacc);
+ DISASM_OPIV_MULTIPLYADD_VF_INSN(vfwmsac);
+ DISASM_OPIV_MULTIPLYADD_VF_INSN(vfwnmsac);
#undef DISASM_OPIV_VF_INSN
#undef DISASM_OPIV__F_INSN
@@ -1954,40 +1946,42 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
#undef DISASM_VFUNARY0_INSN
}
- if (isa->extension_enabled(EXT_ZVFBFMIN)) {
+ if (ext_enabled(EXT_ZVFBFMIN)) {
DEFINE_VECTOR_V(vfncvtbf16_f_f_w);
DEFINE_VECTOR_V(vfwcvtbf16_f_f_v);
}
- if (isa->extension_enabled(EXT_ZVFBFWMA)) {
+ if (ext_enabled(EXT_ZVFBFWMA)) {
DEFINE_VECTOR_VV(vfwmaccbf16_vv);
DEFINE_VECTOR_VF(vfwmaccbf16_vf);
}
-
- if (isa->extension_enabled(EXT_ZMMUL)) {
+
+ if (ext_enabled(EXT_ZMMUL)) {
DEFINE_RTYPE(mul);
DEFINE_RTYPE(mulh);
DEFINE_RTYPE(mulhu);
DEFINE_RTYPE(mulhsu);
- DEFINE_RTYPE(mulw);
+
+ if (xlen_eq(64))
+ DEFINE_RTYPE(mulw);
}
- if (isa->extension_enabled(EXT_ZICBOM)) {
+ if (ext_enabled(EXT_ZICBOM)) {
DISASM_INSN("cbo.clean", cbo_clean, 0, {&base_only_address});
DISASM_INSN("cbo.flush", cbo_flush, 0, {&base_only_address});
DISASM_INSN("cbo.inval", cbo_inval, 0, {&base_only_address});
}
- if (isa->extension_enabled(EXT_ZICBOZ)) {
+ if (ext_enabled(EXT_ZICBOZ)) {
DISASM_INSN("cbo.zero", cbo_zero, 0, {&base_only_address});
}
- if (isa->extension_enabled(EXT_ZICOND)) {
+ if (ext_enabled(EXT_ZICOND)) {
DEFINE_RTYPE(czero_eqz);
DEFINE_RTYPE(czero_nez);
}
- if (isa->extension_enabled(EXT_ZIMOP)) {
+ if (ext_enabled(EXT_ZIMOP)) {
#define DISASM_MOP_R(name, rs1, rd) \
add_insn(new disasm_insn_t(#name, match_##name | (rs1 << 15) | (rd << 7), \
0xFFFFFFFF, {&xrd, &xrs1}));
@@ -2023,7 +2017,7 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_R1TYPE(mop_r_25);
DEFINE_R1TYPE(mop_r_26);
DEFINE_R1TYPE(mop_r_27);
- if (!isa->extension_enabled(EXT_ZICFISS)) {
+ if (!ext_enabled_strict(EXT_ZICFISS)) {
DEFINE_R1TYPE(mop_r_28);
} else {
// Add code points of mop_r_28 not used by Zicfiss
@@ -2043,7 +2037,7 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_RTYPE(mop_rr_5);
DEFINE_RTYPE(mop_rr_6);
DEFINE_RTYPE(mop_rr_7);
- if (!isa->extension_enabled(EXT_ZICFISS)) {
+ if (!ext_enabled_strict(EXT_ZICFISS)) {
DEFINE_RTYPE(mop_rr_7);
} else {
// Add code points of mop_rr_7 not used by Zicfiss
@@ -2055,11 +2049,11 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
}
}
- if (isa->extension_enabled(EXT_ZCMOP)) {
- if (!isa->extension_enabled(EXT_ZICFISS))
+ if (ext_enabled(EXT_ZCMOP)) {
+ if (!ext_enabled_strict(EXT_ZICFISS))
DISASM_INSN("c.mop.1", c_mop_1, 0, {});
DISASM_INSN("c.mop.3", c_mop_3, 0, {});
- if (!isa->extension_enabled(EXT_ZICFISS))
+ if (!ext_enabled_strict(EXT_ZICFISS))
DISASM_INSN("c.mop.5", c_mop_5, 0, {});
DISASM_INSN("c.mop.7", c_mop_7, 0, {});
DISASM_INSN("c.mop.9", c_mop_9, 0, {});
@@ -2068,44 +2062,50 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DISASM_INSN("c.mop.15", c_mop_15, 0, {});
}
- if (isa->extension_enabled(EXT_ZKND) ||
- isa->extension_enabled(EXT_ZKNE)) {
+ if (ext_enabled(EXT_ZKND) || ext_enabled(EXT_ZKNE)) {
DISASM_INSN("aes64ks1i", aes64ks1i, 0, {&xrd, &xrs1, &rcon});
DEFINE_RTYPE(aes64ks2);
}
- if (isa->extension_enabled(EXT_ZKND)) {
- if(isa->get_max_xlen() == 64) {
+ if (ext_enabled(EXT_ZKND)) {
+ if (xlen_eq(64)) {
DEFINE_RTYPE(aes64ds);
DEFINE_RTYPE(aes64dsm);
DEFINE_R1TYPE(aes64im);
- } else if (isa->get_max_xlen() == 32) {
+ }
+
+ if (xlen_eq(32)) {
DISASM_INSN("aes32dsi", aes32dsi, 0, {&xrd, &xrs1, &xrs2, &bs});
DISASM_INSN("aes32dsmi", aes32dsmi, 0, {&xrd, &xrs1, &xrs2, &bs});
}
}
- if (isa->extension_enabled(EXT_ZKNE)) {
- if(isa->get_max_xlen() == 64) {
+ if (ext_enabled(EXT_ZKNE)) {
+ if (xlen_eq(64)) {
DEFINE_RTYPE(aes64es);
DEFINE_RTYPE(aes64esm);
- } else if (isa->get_max_xlen() == 32) {
+ }
+
+ if (xlen_eq(32)) {
DISASM_INSN("aes32esi", aes32esi, 0, {&xrd, &xrs1, &xrs2, &bs});
DISASM_INSN("aes32esmi", aes32esmi, 0, {&xrd, &xrs1, &xrs2, &bs});
}
}
- if (isa->extension_enabled(EXT_ZKNH)) {
+ if (ext_enabled(EXT_ZKNH)) {
DEFINE_R1TYPE(sha256sig0);
DEFINE_R1TYPE(sha256sig1);
DEFINE_R1TYPE(sha256sum0);
DEFINE_R1TYPE(sha256sum1);
- if(isa->get_max_xlen() == 64) {
+
+ if (xlen_eq(64)) {
DEFINE_R1TYPE(sha512sig0);
DEFINE_R1TYPE(sha512sig1);
DEFINE_R1TYPE(sha512sum0);
DEFINE_R1TYPE(sha512sum1);
- } else if (isa->get_max_xlen() == 32) {
+ }
+
+ if (xlen_eq(32)) {
DEFINE_RTYPE(sha512sig0h);
DEFINE_RTYPE(sha512sig0l);
DEFINE_RTYPE(sha512sig1h);
@@ -2115,17 +2115,17 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
}
}
- if (isa->extension_enabled(EXT_ZKSED)) {
+ if (ext_enabled(EXT_ZKSED)) {
DISASM_INSN("sm4ed", sm4ed, 0, {&xrd, &xrs1, &xrs2, &bs});
DISASM_INSN("sm4ks", sm4ks, 0, {&xrd, &xrs1, &xrs2, &bs});
}
- if (isa->extension_enabled(EXT_ZKSH)) {
+ if (ext_enabled(EXT_ZKSH)) {
DEFINE_R1TYPE(sm3p0);
DEFINE_R1TYPE(sm3p1);
}
- if (isa->extension_enabled(EXT_ZVBB)) {
+ if (ext_enabled(EXT_ZVBB)) {
#define DEFINE_VECTOR_VIU_ZIMM6(code) \
add_vector_viu_z6_insn(this, #code, match_##code, mask_##code)
#define DISASM_VECTOR_VV_VX(name) \
@@ -2157,7 +2157,7 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
#undef DISASM_VECTOR_VV_VX_VIU_ZIMM6
}
- if (isa->extension_enabled(EXT_ZVBC)) {
+ if (ext_enabled(EXT_ZVBC)) {
#define DISASM_VECTOR_VV_VX(name) \
DEFINE_VECTOR_VV(name##_vv); \
DEFINE_VECTOR_VX(name##_vx)
@@ -2168,14 +2168,14 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
#undef DISASM_VECTOR_VV_VX
}
- if (isa->extension_enabled(EXT_ZVKG)) {
+ if (ext_enabled(EXT_ZVKG)) {
// Despite its suffix, the vgmul.vv instruction
// is really ".v", with the form "vgmul.vv vd, vs2".
DEFINE_VECTOR_V(vgmul_vv);
DEFINE_VECTOR_VV(vghsh_vv);
}
- if (isa->extension_enabled(EXT_ZVKNED)) {
+ if (ext_enabled(EXT_ZVKNED)) {
// Despite their suffixes, the vaes*.{vv,vs} instructions
// are really ".v", with the form "<op>.{vv,vs} vd, vs2".
#define DISASM_VECTOR_VV_VS(name) \
@@ -2193,14 +2193,13 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
#undef DISASM_VECTOR_VV_VS
}
- if (isa->extension_enabled(EXT_ZVKNHA) ||
- isa->extension_enabled(EXT_ZVKNHB)) {
+ if (ext_enabled(EXT_ZVKNHA) || ext_enabled(EXT_ZVKNHB)) {
DEFINE_VECTOR_VV(vsha2ms_vv);
DEFINE_VECTOR_VV(vsha2ch_vv);
DEFINE_VECTOR_VV(vsha2cl_vv);
}
- if (isa->extension_enabled(EXT_ZVKSED)) {
+ if (ext_enabled(EXT_ZVKSED)) {
DEFINE_VECTOR_VIU(vsm4k_vi);
// Despite their suffixes, the vsm4r.{vv,vs} instructions
// are really ".v", with the form "vsm4r.{vv,vs} vd, vs2".
@@ -2208,12 +2207,12 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_VECTOR_V(vsm4r_vs);
}
- if (isa->extension_enabled(EXT_ZVKSH)) {
+ if (ext_enabled(EXT_ZVKSH)) {
DEFINE_VECTOR_VIU(vsm3c_vi);
DEFINE_VECTOR_VV(vsm3me_vv);
}
- if (isa->extension_enabled(EXT_ZALASR)) {
+ if (ext_enabled(EXT_ZALASR)) {
DEFINE_XLOAD_BASE(lb_aq);
DEFINE_XLOAD_BASE(lh_aq);
DEFINE_XLOAD_BASE(lw_aq);
@@ -2224,7 +2223,7 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_XSTORE_BASE(sd_rl);
}
- if(isa->extension_enabled(EXT_ZICFISS)) {
+ if (ext_enabled(EXT_ZICFISS)) {
DISASM_INSN("sspush", sspush_x1, 0, {&xrs2});
DISASM_INSN("sspush", sspush_x5, 0, {&xrs2});
DISASM_INSN("sspopchk", sspopchk_x1, 0, {&xrs1});
@@ -2232,30 +2231,28 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DISASM_INSN("ssrdp", ssrdp, 0, {&xrd});
DEFINE_XAMO(ssamoswap_w);
- if(isa->get_max_xlen() == 64)
+ if (xlen_eq(64))
DEFINE_XAMO(ssamoswap_d)
- if (isa->extension_enabled(EXT_ZCA)) {
+ if (ext_enabled(EXT_ZCA)) {
DISASM_INSN("c.sspush", c_sspush_x1, 0, {&rvc_ra});
DISASM_INSN("c.sspopchk", c_sspopchk_x5, 0, {&rvc_t0});
}
}
}
-disassembler_t::disassembler_t(const isa_parser_t *isa)
+disassembler_t::disassembler_t(const isa_parser_t *isa, bool strict)
{
// highest priority: instructions explicitly enabled
- add_instructions(isa);
+ add_instructions(isa, true);
- // next-highest priority: other instructions in same base ISA
- std::string fallback_isa_string = std::string("rv") + std::to_string(isa->get_max_xlen()) +
- "gqcvh_zfh_zfa_zba_zbb_zbc_zbs_zcb_zicbom_zicboz_zicond_zk_zks_svinval_"
- "zcmop_zimop_zawrs_zicfiss_zicfilp_zvknc_zvkg_zvfbfmin_zvfbfwma_zfbfmin";
- isa_parser_t fallback_isa(fallback_isa_string.c_str(), DEFAULT_PRIV);
- add_instructions(&fallback_isa);
+ if (!strict) {
+ // next-highest priority: other instructions in same base ISA
+ add_instructions(isa, false);
- // finally: instructions with known opcodes but unknown arguments
- add_unknown_insns(this);
+ // finally: instructions with known opcodes but unknown arguments
+ add_unknown_insns(this);
+ }
// Now, reverse the lists, because we search them back-to-front (so that
// custom instructions later added with add_insn have highest priority).
diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc
index e37b72f..24eb5f2 100644
--- a/disasm/isa_parser.cc
+++ b/disasm/isa_parser.cc
@@ -1,14 +1,35 @@
#include "isa_parser.h"
+#include <cstring>
#include <stdexcept>
static std::string strtolower(const char* str)
{
- std::string res;
- for (const char *r = str; *r; r++)
- res += std::tolower(*r);
+ std::string res(str);
+ for (char &c : res)
+ c = std::tolower(c);
return res;
}
+static unsigned long safe_stoul(const std::string& s)
+{
+ int old_errno = errno;
+ errno = 0;
+
+ char* endp;
+ unsigned long ret = strtoul(s.c_str(), &endp, 10);
+
+ int new_errno = errno;
+ errno = old_errno;
+
+ if (endp == s.c_str() || *endp)
+ throw std::invalid_argument("stoul");
+
+ if (new_errno)
+ throw std::out_of_range("stoul");
+
+ return ret;
+}
+
static void bad_option_string(const char *option, const char *value,
const char *msg)
{
@@ -30,7 +51,7 @@ static void bad_priv_string(const char* priv)
isa_parser_t::isa_parser_t(const char* str, const char *priv)
{
isa_string = strtolower(str);
- const char* all_subsets = "mafdqcpvhb";
+ const char* all_subsets = "mafdqcbpvh";
if (isa_string.compare(0, 4, "rv32") == 0)
max_xlen = 32;
@@ -49,7 +70,7 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
// G = IMAFD_Zicsr_Zifencei, but Spike includes the latter two
// unconditionally, so they need not be explicitly added here.
isa_string = isa_string.substr(0, 4) + "imafd" + isa_string.substr(5);
- // Fall through
+ [[fallthrough]];
case 'i':
extension_table['I'] = true;
break;
@@ -77,9 +98,9 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
switch (*p) {
case 'v': vlen = 128; elen = 64; zvf = true; zvd = true;
- // even rv32iv implies double float
+ [[fallthrough]];
case 'q': extension_table['D'] = true;
- // Fall through
+ [[fallthrough]];
case 'd': extension_table['F'] = true;
}
extension_table[toupper(*p)] = true;
@@ -119,6 +140,10 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
// HINTs encoded in base-ISA instructions are always present.
} else if (ext_str == "zihintntl") {
// HINTs encoded in base-ISA instructions are always present.
+ } else if (ext_str == "ziccid") {
+ extension_table[EXT_ZICCID] = true;
+ } else if (ext_str == "ziccif") {
+ // aligned instruction fetch is always atomic in Spike
} else if (ext_str == "zaamo") {
extension_table[EXT_ZAAMO] = true;
} else if (ext_str == "zalrsc") {
@@ -224,6 +249,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
extension_table[EXT_SSCOFPMF] = true;
} else if (ext_str == "svadu") {
extension_table[EXT_SVADU] = true;
+ } else if (ext_str == "svade") {
+ extension_table[EXT_SVADE] = true;
} else if (ext_str == "svnapot") {
extension_table[EXT_SVNAPOT] = true;
} else if (ext_str == "svpbmt") {
@@ -247,8 +274,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
if (max_xlen != 32)
bad_isa_string(str, "'Zilsd' requires RV32");
extension_table[EXT_ZILSD] = true;
- } else if (ext_str == "zcmlsd") {
- extension_table[EXT_ZCMLSD] = true;
+ } else if (ext_str == "zclsd") {
+ extension_table[EXT_ZCLSD] = true;
} else if (ext_str == "zvbb") {
extension_table[EXT_ZVBB] = true;
} else if (ext_str == "zvbc") {
@@ -297,6 +324,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
extension_table[EXT_ZVKSED] = true;
} else if (ext_str == "zvksh") {
extension_table[EXT_ZVKSH] = true;
+ } else if (ext_str == "zvqdotq") {
+ extension_table[EXT_ZVQDOTQ] = true;
} else if (ext_str == "zvkt") {
} else if (ext_str == "sstc") {
extension_table[EXT_SSTC] = true;
@@ -306,6 +335,10 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
extension_table[EXT_SSCSRIND] = true;
} else if (ext_str == "smcntrpmf") {
extension_table[EXT_SMCNTRPMF] = true;
+ } else if (ext_str == "smcdeleg") {
+ extension_table[EXT_SMCDELEG] = true;
+ } else if (ext_str == "ssccfg") {
+ extension_table[EXT_SSCCFG] = true;
} else if (ext_str == "zimop") {
extension_table[EXT_ZIMOP] = true;
} else if (ext_str == "zcmop") {
@@ -318,20 +351,26 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
extension_table[EXT_ZICFILP] = true;
} else if (ext_str == "zicfiss") {
extension_table[EXT_ZICFISS] = true;
+ } else if (ext_str == "smmpm") {
+ extension_table[EXT_SMMPM] = true;
+ } else if (ext_str == "smnpm") {
+ extension_table[EXT_SMNPM] = true;
+ } else if (ext_str == "ssnpm") {
+ extension_table[EXT_SSNPM] = true;
} else if (ext_str.substr(0, 3) == "zvl") {
reg_t new_vlen;
try {
- new_vlen = std::stol(ext_str.substr(3, ext_str.size() - 4));
+ new_vlen = safe_stoul(ext_str.substr(3, ext_str.size() - 4));
} catch (std::logic_error& e) {
new_vlen = 0;
}
- if ((new_vlen & (new_vlen - 1)) != 0 || new_vlen < 32)
+ if ((new_vlen & (new_vlen - 1)) != 0 || new_vlen < 32 || ext_str.back() != 'b')
bad_isa_string(str, ("Invalid Zvl string: " + ext_str).c_str());
vlen = std::max(vlen, new_vlen);
} else if (ext_str.substr(0, 3) == "zve") {
reg_t new_elen;
try {
- new_elen = std::stol(ext_str.substr(3, ext_str.size() - 4));
+ new_elen = safe_stoul(ext_str.substr(3, ext_str.size() - 4));
} catch (std::logic_error& e) {
new_elen = 0;
}
@@ -347,6 +386,18 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
if (new_elen != 32 && new_elen != 64)
bad_isa_string(str, ("Invalid Zve string: " + ext_str).c_str());
elen = std::max(elen, new_elen);
+ } else if (ext_str == "ssdbltrp") {
+ extension_table[EXT_SSDBLTRP] = true;
+ } else if (ext_str == "smdbltrp") {
+ extension_table[EXT_SMDBLTRP] = true;
+ } else if (ext_str == "smaia") {
+ extension_table[EXT_SMAIA] = true;
+ extension_table[EXT_SSAIA] = true;
+ extension_table[EXT_SMCSRIND] = true;
+ extension_table[EXT_SSCSRIND] = true;
+ } else if (ext_str == "ssaia") {
+ extension_table[EXT_SSAIA] = true;
+ extension_table[EXT_SSCSRIND] = true;
} else if (ext_str[0] == 'x') {
extension_table['X'] = true;
if (ext_str.size() == 1) {
@@ -386,12 +437,12 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
extension_table[EXT_ZCD] = true;
}
- if (extension_table[EXT_ZCMLSD] && extension_table[EXT_ZCF]) {
- bad_isa_string(str, "'Zcmlsd' extension conflicts with 'Zcf' extensions");
+ if (extension_table[EXT_ZCLSD] && extension_table[EXT_ZCF]) {
+ bad_isa_string(str, "'Zclsd' extension conflicts with 'Zcf' extensions");
}
- if (extension_table[EXT_ZCMLSD] && (!extension_table[EXT_ZCA] || !extension_table[EXT_ZILSD])) {
- bad_isa_string(str, "'Zcmlsd' extension requires 'Zca' and 'Zilsd' extensions");
+ if (extension_table[EXT_ZCLSD] && (!extension_table[EXT_ZCA] || !extension_table[EXT_ZILSD])) {
+ bad_isa_string(str, "'Zclsd' extension requires 'Zca' and 'Zilsd' extensions");
}
if (extension_table[EXT_ZFBFMIN] && !extension_table['F']) {
diff --git a/fdt/fdt.mk.in b/fdt/fdt.mk.in
index 64d06ac..accc080 100644
--- a/fdt/fdt.mk.in
+++ b/fdt/fdt.mk.in
@@ -16,4 +16,4 @@ fdt_c_srcs = \
fdt_addresses.c \
fdt_overlay.c \
-fdt_CFLAGS = -I$(src_dir)/fdt
+fdt_CFLAGS = -I$(src_dir)/fdt -Wno-sign-compare
diff --git a/fdt/libfdt.h b/fdt/libfdt.h
index d2356cc..8fb42fb 100644
--- a/fdt/libfdt.h
+++ b/fdt/libfdt.h
@@ -6,8 +6,8 @@
* Copyright (C) 2006 David Gibson, IBM Corporation.
*/
-#include <libfdt_env.h>
-#include <fdt.h>
+#include "libfdt_env.h"
+#include "fdt.h"
#define FDT_FIRST_SUPPORTED_VERSION 0x02
#define FDT_LAST_SUPPORTED_VERSION 0x11
diff --git a/fesvr/byteorder.h b/fesvr/byteorder.h
index d9e503a..2147f96 100644
--- a/fesvr/byteorder.h
+++ b/fesvr/byteorder.h
@@ -3,8 +3,8 @@
#ifndef _RISCV_BYTEORDER_H
#define _RISCV_BYTEORDER_H
-#include "config.h"
#include <stdint.h>
+#include <arpa/inet.h>
static inline uint8_t swap(uint8_t n) { return n; }
static inline uint16_t swap(uint16_t n) { return (n >> 8) | (n << 8); }
@@ -16,23 +16,17 @@ static inline int32_t swap(int32_t n) { return int32_t(swap(uint32_t(n))); }
static inline int64_t swap(int64_t n) { return int64_t(swap(uint64_t(n))); }
#ifdef HAVE_INT128
-typedef __int128 int128_t;
-typedef unsigned __int128 uint128_t;
+__extension__ typedef __int128 int128_t;
+__extension__ typedef unsigned __int128 uint128_t;
static inline uint128_t swap(uint128_t n) { return (uint128_t(swap(uint64_t(n))) << 64) | swap(uint64_t(n >> 64)); }
static inline int128_t swap(int128_t n) { return int128_t(swap(uint128_t(n))); }
#endif
-#ifdef WORDS_BIGENDIAN
-template<typename T> static inline T from_be(T n) { return n; }
-template<typename T> static inline T to_be(T n) { return n; }
-template<typename T> static inline T from_le(T n) { return swap(n); }
-template<typename T> static inline T to_le(T n) { return swap(n); }
-#else
-template<typename T> static inline T from_le(T n) { return n; }
-template<typename T> static inline T to_le(T n) { return n; }
-template<typename T> static inline T from_be(T n) { return swap(n); }
-template<typename T> static inline T to_be(T n) { return swap(n); }
-#endif
+static inline bool is_be() { return htonl(1) == 1; }
+template<typename T> static inline T from_be(T n) { return is_be() ? n : swap(n); }
+template<typename T> static inline T to_be(T n) { return from_be(n); }
+template<typename T> static inline T from_le(T n) { return is_be() ? swap(n) : n; }
+template<typename T> static inline T to_le(T n) { return from_le(n); }
// Wrapper to mark a value as target endian, to guide conversion code
diff --git a/fesvr/dtm.cc b/fesvr/dtm.cc
index 0f810e7..a0c3254 100644
--- a/fesvr/dtm.cc
+++ b/fesvr/dtm.cc
@@ -51,6 +51,9 @@
} \
}
+#define MAX_DATA_WORDS (1 << DM_ABSTRACTCS_DATACOUNT_LENGTH)
+#define MAX_PROG_WORDS (1 << DM_ABSTRACTCS_PROGBUFSIZE_LENGTH)
+
uint32_t dtm_t::do_command(dtm_t::req r)
{
req_buf = r;
@@ -61,17 +64,20 @@ uint32_t dtm_t::do_command(dtm_t::req r)
uint32_t dtm_t::read(uint32_t addr)
{
- return do_command((req){addr, 1, 0});
+ req r = {addr, 1, 0};
+ return do_command(r);
}
uint32_t dtm_t::write(uint32_t addr, uint32_t data)
{
- return do_command((req){addr, 2, data});
+ req r = {addr, 2, data};
+ return do_command(r);
}
void dtm_t::nop()
{
- do_command((req){0, 0, 0});
+ req r = {0, 0, 0};
+ do_command(r);
}
void dtm_t::select_hart(int hartsel) {
@@ -104,7 +110,7 @@ void dtm_t::halt(int hartsel)
read(DM_DMSTATUS);
}
- int dmcontrol = DM_DMCONTROL_HALTREQ | DM_DMCONTROL_DMACTIVE;
+ reg_t dmcontrol = DM_DMCONTROL_HALTREQ | DM_DMCONTROL_DMACTIVE;
dmcontrol = set_field(dmcontrol, DM_DMCONTROL_HASEL, hartsel);
write(DM_DMCONTROL, dmcontrol);
int dmstatus;
@@ -142,7 +148,7 @@ void dtm_t::resume(int hartsel)
uint64_t dtm_t::save_reg(unsigned regno)
{
- uint32_t data[xlen/(8*4)];
+ uint32_t data[MAX_DATA_WORDS];
uint32_t command = AC_ACCESS_REGISTER_TRANSFER | AC_AR_SIZE(xlen) | AC_AR_REGNO(regno);
RUN_AC_OR_DIE(command, 0, 0, data, xlen / (8*4));
@@ -155,7 +161,7 @@ uint64_t dtm_t::save_reg(unsigned regno)
void dtm_t::restore_reg(unsigned regno, uint64_t val)
{
- uint32_t data[xlen/(8*4)];
+ uint32_t data[MAX_DATA_WORDS];
data[0] = (uint32_t) val;
if (xlen > 32) {
data[1] = (uint32_t) (val >> 32);
@@ -174,8 +180,8 @@ uint32_t dtm_t::run_abstract_command(uint32_t command,
const uint32_t program[], size_t program_n,
uint32_t data[], size_t data_n)
{
- assert(program_n <= ram_words);
- assert(data_n <= data_words);
+ assert(program_n <= MAX_PROG_WORDS);
+ assert(data_n <= MAX_DATA_WORDS);
for (size_t i = 0; i < program_n; i++) {
write(DM_PROGBUF0 + i, program[i]);
@@ -214,8 +220,8 @@ size_t dtm_t::chunk_align()
void dtm_t::read_chunk(uint64_t taddr, size_t len, void* dst)
{
- uint32_t prog[ram_words];
- uint32_t data[data_words];
+ uint32_t prog[MAX_PROG_WORDS];
+ uint32_t data[MAX_DATA_WORDS];
uint8_t * curr = (uint8_t*) dst;
@@ -267,8 +273,8 @@ void dtm_t::read_chunk(uint64_t taddr, size_t len, void* dst)
void dtm_t::write_chunk(uint64_t taddr, size_t len, const void* src)
{
- uint32_t prog[ram_words];
- uint32_t data[data_words];
+ uint32_t prog[MAX_PROG_WORDS];
+ uint32_t data[MAX_DATA_WORDS];
const uint8_t * curr = (const uint8_t*) src;
@@ -362,8 +368,8 @@ void dtm_t::die(uint32_t cmderr)
void dtm_t::clear_chunk(uint64_t taddr, size_t len)
{
- uint32_t prog[ram_words];
- uint32_t data[data_words];
+ uint32_t prog[MAX_PROG_WORDS];
+ uint32_t data[MAX_DATA_WORDS];
halt(current_hart);
uint64_t s0 = save_reg(S0);
@@ -477,8 +483,8 @@ uint32_t dtm_t::get_xlen()
uint32_t command = AC_ACCESS_REGISTER_TRANSFER | AC_AR_REGNO(S0);
uint32_t cmderr;
- const uint32_t prog[] = {};
- uint32_t data[] = {};
+ const uint32_t prog[1] = {};
+ uint32_t data[1] = {};
cmderr = run_abstract_command(command | AC_AR_SIZE(128), prog, 0, data, 0);
if (cmderr == 0){
@@ -560,11 +566,6 @@ void dtm_t::producer_thread()
// Poll until the debugger agrees it's enabled.
while ((read(DM_DMCONTROL) & DM_DMCONTROL_DMACTIVE) == 0) ;
- // These are checked every time we run an abstract command.
- uint32_t abstractcs = read(DM_ABSTRACTCS);
- ram_words = get_field(abstractcs, DM_ABSTRACTCS_PROGBUFSIZE);
- data_words = get_field(abstractcs, DM_ABSTRACTCS_DATACOUNT);
-
// These things are only needed for the 'modify_csr' function.
// That could be re-written to not use these at some performance
// overhead.
diff --git a/fesvr/dtm.h b/fesvr/dtm.h
index f47b648..03c2f79 100644
--- a/fesvr/dtm.h
+++ b/fesvr/dtm.h
@@ -109,8 +109,6 @@ class dtm_t : public htif_t
static const int max_idle_cycles = 10000;
- size_t ram_words;
- size_t data_words;
int num_harts;
int current_hart;
diff --git a/fesvr/elfloader.h b/fesvr/elfloader.h
index 0a250cd..6cbdda3 100644
--- a/fesvr/elfloader.h
+++ b/fesvr/elfloader.h
@@ -4,6 +4,7 @@
#define _ELFLOADER_H
#include "elf.h"
+#include "memif.h"
#include <map>
#include <string>
diff --git a/fesvr/htif.cc b/fesvr/htif.cc
index 46f15d3..15f79bf 100644
--- a/fesvr/htif.cc
+++ b/fesvr/htif.cc
@@ -46,7 +46,7 @@ static void handle_signal(int sig)
htif_t::htif_t()
: mem(this), entry(DRAM_BASE), sig_addr(0), sig_len(0),
- tohost_addr(0), fromhost_addr(0), exitcode(0), stopped(false),
+ tohost_addr(0), fromhost_addr(0), stopped(false),
syscall_proxy(this)
{
signal(SIGINT, &handle_signal);
@@ -65,14 +65,14 @@ htif_t::htif_t(int argc, char** argv) : htif_t()
htif_t::htif_t(const std::vector<std::string>& args) : htif_t()
{
int argc = args.size() + 1;
- char * argv[argc];
+ std::vector<char*>argv(argc);
argv[0] = (char *) "htif";
for (unsigned int i = 0; i < args.size(); i++) {
argv[i+1] = (char *) args[i].c_str();
}
//Set line size as 16 by default.
line_size = 16;
- parse_arguments(argc, argv);
+ parse_arguments(argc, &argv[0]);
register_devices();
}
@@ -84,16 +84,20 @@ htif_t::~htif_t()
void htif_t::start()
{
- if (!targs.empty() && targs[0] != "none") {
- try {
- load_program();
- } catch (const incompat_xlen & err) {
- fprintf(stderr, "Error: cannot execute %d-bit program on RV%d hart\n", err.actual_xlen, err.expected_xlen);
- exit(1);
+ if (!targs.empty()) {
+ if (targs[0] != "none") {
+ try {
+ load_program();
+ } catch (const incompat_xlen & err) {
+ fprintf(stderr, "Error: cannot execute %d-bit program on RV%d hart\n", err.actual_xlen, err.expected_xlen);
+ exit(1);
+ }
+ reset();
+ } else {
+ auto empty_symbols = std::map<std::string, uint64_t>();
+ load_symbols(empty_symbols);
}
}
-
- reset();
}
static void bad_address(const std::string& situation, reg_t addr)
@@ -116,7 +120,7 @@ std::map<std::string, uint64_t> htif_t::load_payload(const std::string& payload,
else
throw std::runtime_error(
"could not open " + payload + "; searched paths:\n" +
- "\t. (current directory)\n" +
+ "\t. (current directory)\n" +
"\t" + PREFIX TARGET_DIR + " (based on configured --prefix and --with-target)"
);
}
@@ -150,35 +154,13 @@ std::map<std::string, uint64_t> htif_t::load_payload(const std::string& payload,
}
}
-void htif_t::load_program()
+void htif_t::load_symbols(std::map<std::string, uint64_t>& symbols)
{
- std::map<std::string, uint64_t> symbols = load_payload(targs[0], &entry, load_offset);
-
- if (symbols.count("tohost") && symbols.count("fromhost")) {
- tohost_addr = symbols["tohost"];
- fromhost_addr = symbols["fromhost"];
- } else {
- fprintf(stderr, "warning: tohost and fromhost symbols not in ELF; can't communicate with target\n");
- }
-
- // detect torture tests so we can print the memory signature at the end
- if (symbols.count("begin_signature") && symbols.count("end_signature")) {
- sig_addr = symbols["begin_signature"];
- sig_len = symbols["end_signature"] - sig_addr;
- }
-
- for (auto payload : payloads) {
- reg_t dummy_entry;
- load_payload(payload, &dummy_entry, 0);
- }
-
class nop_memif_t : public memif_t {
public:
- nop_memif_t(htif_t* htif) : memif_t(htif), htif(htif) {}
+ nop_memif_t(htif_t* htif) : memif_t(htif) {}
void read(addr_t UNUSED addr, size_t UNUSED len, void UNUSED *bytes) override {}
void write(addr_t UNUSED taddr, size_t UNUSED len, const void UNUSED *src) override {}
- private:
- htif_t* htif;
} nop_memif(this);
reg_t nop_entry;
@@ -188,11 +170,36 @@ void htif_t::load_program()
symbols.merge(other_symbols);
}
+ // detect torture tests so we can print the memory signature at the end
+ if (symbols.count("begin_signature") && symbols.count("end_signature")) {
+ sig_addr = symbols["begin_signature"];
+ sig_len = symbols["end_signature"] - sig_addr;
+ }
+
+ if (symbols.count("tohost") && symbols.count("fromhost")) {
+ tohost_addr = symbols["tohost"];
+ fromhost_addr = symbols["fromhost"];
+ } else {
+ fprintf(stderr, "warning: tohost and fromhost symbols not in ELF; can't communicate with target\n");
+ }
+
for (auto i : symbols) {
auto it = addr2symbol.find(i.second);
if ( it == addr2symbol.end())
addr2symbol[i.second] = i.first;
}
+}
+
+void htif_t::load_program()
+{
+ std::map<std::string, uint64_t> symbols = load_payload(targs[0], &entry, load_offset);
+
+ load_symbols(symbols);
+
+ for (auto payload : payloads) {
+ reg_t dummy_entry;
+ load_payload(payload, &dummy_entry, 0);
+ }
return;
}
@@ -207,6 +214,14 @@ const char* htif_t::get_symbol(uint64_t addr)
return it->second.c_str();
}
+bool htif_t::should_exit() const {
+ return signal_exit || exitcode.has_value();
+}
+
+void htif_t::htif_exit(int exit_code) {
+ exitcode = exit_code;
+}
+
void htif_t::stop()
{
if (!sig_file.empty() && sig_len) // print final torture test signature
@@ -236,11 +251,10 @@ void htif_t::stop()
void htif_t::clear_chunk(addr_t taddr, size_t len)
{
- char zeros[chunk_max_size()];
- memset(zeros, 0, chunk_max_size());
+ std::vector<uint8_t> zeros(chunk_max_size(), 0);
for (size_t pos = 0; pos < len; pos += chunk_max_size())
- write_chunk(taddr + pos, std::min(len - pos, chunk_max_size()), zeros);
+ write_chunk(taddr + pos, std::min(len - pos, chunk_max_size()), &zeros[0]);
}
int htif_t::run()
@@ -253,11 +267,11 @@ int htif_t::run()
std::bind(enq_func, &fromhost_queue, std::placeholders::_1);
if (tohost_addr == 0) {
- while (!signal_exit)
+ while (!should_exit())
idle();
}
- while (!signal_exit && exitcode == 0)
+ while (!should_exit())
{
uint64_t tohost;
@@ -305,7 +319,7 @@ bool htif_t::done()
int htif_t::exit_code()
{
- return exitcode >> 1;
+ return exitcode.value_or(0) >> 1;
}
void htif_t::parse_arguments(int argc, char ** argv)
diff --git a/fesvr/htif.h b/fesvr/htif.h
index 74511f5..380e24a 100644
--- a/fesvr/htif.h
+++ b/fesvr/htif.h
@@ -24,6 +24,9 @@ class htif_t : public chunked_memif_t
virtual void start();
virtual void stop();
+ // Cause the simulation to exit with the given exit code.
+ void htif_exit(int exit_code);
+
int run();
bool done();
int exit_code();
@@ -62,6 +65,7 @@ class htif_t : public chunked_memif_t
virtual std::map<std::string, uint64_t> load_payload(const std::string& payload, reg_t* entry,
reg_t load_addr);
virtual void load_program();
+ virtual void load_symbols(std::map<std::string, uint64_t>&);
virtual void idle() {}
const std::vector<std::string>& host_args() { return hargs; }
@@ -76,6 +80,10 @@ class htif_t : public chunked_memif_t
// Given an address, return symbol from addr2symbol map
const char* get_symbol(uint64_t addr);
+ // Return true if the simulation should exit due to a signal,
+ // or end-of-test from HTIF, or an instruction limit.
+ bool should_exit() const;
+
private:
void parse_arguments(int argc, char ** argv);
void register_devices();
@@ -93,7 +101,8 @@ class htif_t : public chunked_memif_t
addr_t sig_len; // torture
addr_t tohost_addr;
addr_t fromhost_addr;
- int exitcode;
+ // Set to a value by htif_exit() when the simulation should exit.
+ std::optional<int> exitcode;
bool stopped;
device_list_t device_list;
diff --git a/fesvr/htif_pthread.h b/fesvr/htif_pthread.h
index c00c382..ab56007 100644
--- a/fesvr/htif_pthread.h
+++ b/fesvr/htif_pthread.h
@@ -13,7 +13,7 @@ class htif_pthread_t : public htif_t
htif_pthread_t(int argc, char** argv);
virtual ~htif_pthread_t();
- // target inteface
+ // target interface
void send(const void* buf, size_t size);
void recv(void* buf, size_t size);
bool recv_nonblocking(void* buf, size_t size);
diff --git a/fesvr/memif.cc b/fesvr/memif.cc
index e56bd94..59938b9 100644
--- a/fesvr/memif.cc
+++ b/fesvr/memif.cc
@@ -12,10 +12,10 @@ void memif_t::read(addr_t addr, size_t len, void* bytes)
if (len && (addr & (align-1)))
{
size_t this_len = std::min(len, align - size_t(addr & (align-1)));
- uint8_t chunk[align];
+ std::vector<uint8_t> chunk(align);
- cmemif->read_chunk(addr & ~(align-1), align, chunk);
- memcpy(bytes, chunk + (addr & (align-1)), this_len);
+ cmemif->read_chunk(addr & ~(align-1), align, &chunk[0]);
+ memcpy(bytes, &chunk[addr & (align-1)], this_len);
bytes = (char*)bytes + this_len;
addr += this_len;
@@ -26,10 +26,10 @@ void memif_t::read(addr_t addr, size_t len, void* bytes)
{
size_t this_len = len & (align-1);
size_t start = len - this_len;
- uint8_t chunk[align];
+ std::vector<uint8_t> chunk(align);
- cmemif->read_chunk(addr + start, align, chunk);
- memcpy((char*)bytes + start, chunk, this_len);
+ cmemif->read_chunk(addr + start, align, &chunk[0]);
+ memcpy((char*)bytes + start, &chunk[0], this_len);
len -= this_len;
}
@@ -45,11 +45,11 @@ void memif_t::write(addr_t addr, size_t len, const void* bytes)
if (len && (addr & (align-1)))
{
size_t this_len = std::min(len, align - size_t(addr & (align-1)));
- uint8_t chunk[align];
+ std::vector<uint8_t> chunk(align);
- cmemif->read_chunk(addr & ~(align-1), align, chunk);
- memcpy(chunk + (addr & (align-1)), bytes, this_len);
- cmemif->write_chunk(addr & ~(align-1), align, chunk);
+ cmemif->read_chunk(addr & ~(align-1), align, &chunk[0]);
+ memcpy(&chunk[addr & (align-1)], bytes, this_len);
+ cmemif->write_chunk(addr & ~(align-1), align, &chunk[0]);
bytes = (char*)bytes + this_len;
addr += this_len;
@@ -60,11 +60,11 @@ void memif_t::write(addr_t addr, size_t len, const void* bytes)
{
size_t this_len = len & (align-1);
size_t start = len - this_len;
- uint8_t chunk[align];
+ std::vector<uint8_t> chunk(align);
- cmemif->read_chunk(addr + start, align, chunk);
- memcpy(chunk, (char*)bytes + start, this_len);
- cmemif->write_chunk(addr + start, align, chunk);
+ cmemif->read_chunk(addr + start, align, &chunk[0]);
+ memcpy(&chunk[0], (char*)bytes + start, this_len);
+ cmemif->write_chunk(addr + start, align, &chunk[0]);
len -= this_len;
}
diff --git a/fesvr/syscall.cc b/fesvr/syscall.cc
index 162cbfc..014a468 100644
--- a/fesvr/syscall.cc
+++ b/fesvr/syscall.cc
@@ -114,19 +114,23 @@ struct riscv_statx
attributes_mask(htif->to_target<uint64_t>(s.stx_attributes_mask)),
atime {
htif->to_target<int64_t>(s.stx_atime.tv_sec),
- htif->to_target<uint32_t>(s.stx_atime.tv_nsec)
+ htif->to_target<uint32_t>(s.stx_atime.tv_nsec),
+ htif->to_target<int32_t>(0)
},
btime {
htif->to_target<int64_t>(s.stx_btime.tv_sec),
- htif->to_target<uint32_t>(s.stx_btime.tv_nsec)
+ htif->to_target<uint32_t>(s.stx_btime.tv_nsec),
+ htif->to_target<int32_t>(0)
},
ctime {
htif->to_target<int64_t>(s.stx_ctime.tv_sec),
- htif->to_target<uint32_t>(s.stx_ctime.tv_nsec)
+ htif->to_target<uint32_t>(s.stx_ctime.tv_nsec),
+ htif->to_target<int32_t>(0)
},
mtime {
htif->to_target<int64_t>(s.stx_mtime.tv_sec),
- htif->to_target<uint32_t>(s.stx_mtime.tv_nsec)
+ htif->to_target<uint32_t>(s.stx_mtime.tv_nsec),
+ htif->to_target<int32_t>(0)
},
rdev_major(htif->to_target<uint32_t>(s.stx_rdev_major)),
rdev_minor(htif->to_target<uint32_t>(s.stx_rdev_minor)),
@@ -137,7 +141,7 @@ struct riscv_statx
__spare2(), __spare3()
#else
__spare2()
-#endif
+#endif
{}
};
#endif
@@ -221,7 +225,7 @@ void syscall_t::handle_syscall(command_t cmd)
reg_t syscall_t::sys_exit(reg_t code, reg_t a1, reg_t a2, reg_t a3, reg_t a4, reg_t a5, reg_t a6)
{
- htif->exitcode = code << 1 | 1;
+ htif->htif_exit(code << 1 | 1);
return 0;
}
diff --git a/ax_append_flag.m4 b/m4/ax_append_flag.m4
index dd6d8b6..dd6d8b6 100644
--- a/ax_append_flag.m4
+++ b/m4/ax_append_flag.m4
diff --git a/ax_append_link_flags.m4 b/m4/ax_append_link_flags.m4
index 99b9fa5..99b9fa5 100644
--- a/ax_append_link_flags.m4
+++ b/m4/ax_append_link_flags.m4
diff --git a/ax_boost_asio.m4 b/m4/ax_boost_asio.m4
index 4247b33..4247b33 100644
--- a/ax_boost_asio.m4
+++ b/m4/ax_boost_asio.m4
diff --git a/ax_boost_base.m4 b/m4/ax_boost_base.m4
index 519f1c9..9d5a08c 100644
--- a/ax_boost_base.m4
+++ b/m4/ax_boost_base.m4
@@ -10,10 +10,10 @@
#
# Test for the Boost C++ libraries of a particular version (or newer)
#
-# If no path to the installed boost library is given the macro searchs
-# under /usr, /usr/local, /opt and /opt/local and evaluates the
-# $BOOST_ROOT environment variable. Further documentation is available at
-# <http://randspringer.de/boost/index.html>.
+# If no path to the installed boost library is given the macro searches
+# under /usr, /usr/local, /opt, /opt/local and /opt/homebrew and evaluates
+# the $BOOST_ROOT environment variable. Further documentation is available
+# at <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
@@ -33,7 +33,7 @@
# and this notice are preserved. This file is offered as-is, without any
# warranty.
-#serial 49
+#serial 55
# example boost program (need to pass version)
m4_define([_AX_BOOST_BASE_PROGRAM],
@@ -114,7 +114,7 @@ AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[
AS_CASE([${host_cpu}],
[x86_64],[libsubdirs="lib64 libx32 lib lib64"],
[mips*64*],[libsubdirs="lib64 lib32 lib lib64"],
- [ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64|e2k],[libsubdirs="lib64 lib lib64"],
+ [ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64|e2k|loongarch64],[libsubdirs="lib64 lib lib64"],
[libsubdirs="lib"]
)
@@ -128,7 +128,7 @@ AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[
)
dnl first we check the system location for boost libraries
- dnl this location ist chosen if boost libraries are installed with the --layout=system option
+ dnl this location is chosen if boost libraries are installed with the --layout=system option
dnl or if you install boost with RPM
AS_IF([test "x$_AX_BOOST_BASE_boost_path" != "x"],[
AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) includes in "$_AX_BOOST_BASE_boost_path/include"])
@@ -151,7 +151,7 @@ AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[
else
search_libsubdirs="$multiarch_libsubdir $libsubdirs"
fi
- for _AX_BOOST_BASE_boost_path_tmp in /usr /usr/local /opt /opt/local ; do
+ for _AX_BOOST_BASE_boost_path_tmp in /usr /usr/local /opt /opt/local /opt/homebrew ; do
if test -d "$_AX_BOOST_BASE_boost_path_tmp/include/boost" && test -r "$_AX_BOOST_BASE_boost_path_tmp/include/boost" ; then
for libsubdir in $search_libsubdirs ; do
if ls "$_AX_BOOST_BASE_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
@@ -227,7 +227,7 @@ AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[
fi
else
if test "x$cross_compiling" != "xyes" ; then
- for _AX_BOOST_BASE_boost_path in /usr /usr/local /opt /opt/local ; do
+ for _AX_BOOST_BASE_boost_path in /usr /usr/local /opt /opt/local /opt/homebrew ; do
if test -d "$_AX_BOOST_BASE_boost_path" && test -r "$_AX_BOOST_BASE_boost_path" ; then
for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do
_version_tmp=`echo $i | sed "s#$_AX_BOOST_BASE_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
@@ -289,6 +289,8 @@ AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[
else
AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).])
fi
+ BOOST_LDFLAGS=""
+ BOOST_CPPFLAGS=""
# execute ACTION-IF-NOT-FOUND (if present):
ifelse([$3], , :, [$3])
else
diff --git a/ax_boost_regex.m4 b/m4/ax_boost_regex.m4
index e2413c2..e2413c2 100644
--- a/ax_boost_regex.m4
+++ b/m4/ax_boost_regex.m4
diff --git a/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4
index bd753b3..54191c5 100644
--- a/ax_check_compile_flag.m4
+++ b/m4/ax_check_compile_flag.m4
@@ -34,14 +34,24 @@
# and this notice are preserved. This file is offered as-is, without any
# warranty.
-#serial 6
+#serial 11
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
-AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
+AC_CACHE_CHECK([whether the _AC_LANG compiler accepts $1], CACHEVAR, [
ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
- _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
+ if test x"m4_case(_AC_LANG,
+ [C], [$GCC],
+ [C++], [$GXX],
+ [Fortran], [$GFC],
+ [Fortran 77], [$G77],
+ [Objective C], [$GOBJC],
+ [Objective C++], [$GOBJCXX],
+ [no])" = xyes ; then
+ add_gnu_werror="-Werror"
+ fi
+ _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1 $add_gnu_werror"
AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
[AS_VAR_SET(CACHEVAR,[yes])],
[AS_VAR_SET(CACHEVAR,[no])])
diff --git a/ax_check_link_flag.m4 b/m4/ax_check_link_flag.m4
index 03a30ce..03a30ce 100644
--- a/ax_check_link_flag.m4
+++ b/m4/ax_check_link_flag.m4
diff --git a/ax_require_defined.m4 b/m4/ax_require_defined.m4
index 17c3eab..17c3eab 100644
--- a/ax_require_defined.m4
+++ b/m4/ax_require_defined.m4
diff --git a/riscv/abstract_device.h b/riscv/abstract_device.h
index 0726cd7..d8ddbab 100644
--- a/riscv/abstract_device.h
+++ b/riscv/abstract_device.h
@@ -16,6 +16,7 @@ class abstract_device_t {
public:
virtual bool load(reg_t addr, size_t len, uint8_t* bytes) = 0;
virtual bool store(reg_t addr, size_t len, const uint8_t* bytes) = 0;
+ virtual reg_t size() = 0;
virtual ~abstract_device_t() {}
virtual void tick(reg_t UNUSED rtc_ticks) {}
};
diff --git a/riscv/arith.h b/riscv/arith.h
index c60fcbe..b61b28c 100644
--- a/riscv/arith.h
+++ b/riscv/arith.h
@@ -32,15 +32,15 @@ inline uint64_t mulhu(uint64_t a, uint64_t b)
inline int64_t mulh(int64_t a, int64_t b)
{
int negate = (a < 0) != (b < 0);
- uint64_t res = mulhu(a < 0 ? -a : a, b < 0 ? -b : b);
+ uint64_t res = mulhu(a < 0 ? -(uint64_t)a : a, b < 0 ? -(uint64_t)b : b);
return negate ? ~res + ((uint64_t)a * (uint64_t)b == 0) : res;
}
inline int64_t mulhsu(int64_t a, uint64_t b)
{
int negate = a < 0;
- uint64_t res = mulhu(a < 0 ? -a : a, b);
- return negate ? ~res + (a * b == 0) : res;
+ uint64_t res = mulhu(a < 0 ? -(uint64_t)a : a, b);
+ return negate ? ~res + ((uint64_t)a * b == 0) : res;
}
//ref: https://locklessinc.com/articles/sat_arithmetic/
diff --git a/riscv/cfg.cc b/riscv/cfg.cc
index 67dfdb4..cc39a54 100644
--- a/riscv/cfg.cc
+++ b/riscv/cfg.cc
@@ -1,5 +1,6 @@
// See LICENSE for license details.
+#include "config.h"
#include "cfg.h"
#include "mmu.h"
#include "decode.h"
@@ -17,13 +18,15 @@ bool mem_cfg_t::check_if_supported(reg_t base, reg_t size)
// the regions in the first place, but we have them here to make sure that
// we can't end up describing memory regions that don't make sense. They
// ask that the page size is a multiple of the minimum page size, that the
- // page is aligned to the minimum page size, that the page is non-empty and
- // that the top address is still representable in a reg_t.
+ // page is aligned to the minimum page size, that the page is non-empty,
+ // that the size doesn't overflow size_t, and that the top address is still
+ // representable in a reg_t.
//
// Note: (base + size == 0) part of the assertion is to handle cases like
// { base = 0xffff_ffff_ffff_f000, size: 0x1000 }
return (size % PGSIZE == 0) &&
(base % PGSIZE == 0) &&
+ (size_t(size) == size) &&
(size > 0) &&
((base + size > base) || (base + size == 0));
}
@@ -44,4 +47,5 @@ cfg_t::cfg_t()
explicit_hartids = false;
real_time_clint = false;
trigger_count = 4;
+ cache_blocksz = 64;
}
diff --git a/riscv/cfg.h b/riscv/cfg.h
index c972f03..8032856 100644
--- a/riscv/cfg.h
+++ b/riscv/cfg.h
@@ -6,6 +6,7 @@
#include <vector>
#include "decode.h"
#include <cassert>
+class abstract_sim_if_t;
typedef enum {
endianness_little,
@@ -77,6 +78,8 @@ public:
bool explicit_hartids;
bool real_time_clint;
reg_t trigger_count;
+ reg_t cache_blocksz;
+ std::optional<abstract_sim_if_t*> external_simulator;
size_t nprocs() const { return hartids.size(); }
size_t max_hartid() const { return hartids.back(); }
diff --git a/riscv/clint.cc b/riscv/clint.cc
index 208ea0e..3d5c984 100644
--- a/riscv/clint.cc
+++ b/riscv/clint.cc
@@ -39,7 +39,8 @@ bool clint_t::load(reg_t addr, size_t len, uint8_t* bytes)
tick(0);
- if (addr >= MSIP_BASE && addr < MTIMECMP_BASE) {
+ static_assert(MSIP_BASE == 0);
+ if (/* addr >= MSIP_BASE && */ addr < MTIMECMP_BASE) {
if (len == 8) {
// Implement double-word loads as a pair of word loads
return load(addr, 4, bytes) && load(addr + 4, 4, bytes + 4);
@@ -68,7 +69,8 @@ bool clint_t::store(reg_t addr, size_t len, const uint8_t* bytes)
if (len > 8)
return false;
- if (addr >= MSIP_BASE && addr < MTIMECMP_BASE) {
+ static_assert(MSIP_BASE == 0);
+ if (/* addr >= MSIP_BASE && */ addr < MTIMECMP_BASE) {
if (len == 8) {
// Implement double-word stores as a pair of word stores
return store(addr, 4, bytes) && store(addr + 4, 4, bytes + 4);
@@ -117,7 +119,7 @@ void clint_t::tick(reg_t rtc_ticks)
}
clint_t* clint_parse_from_fdt(const void* fdt, const sim_t* sim, reg_t* base,
- const std::vector<std::string>& UNUSED sargs) {
+ const std::vector<std::string>& sargs UNUSED) {
if (fdt_parse_clint(fdt, base, "riscv,clint0") == 0 || fdt_parse_clint(fdt, base, "sifive,clint0") == 0)
return new clint_t(sim,
sim->CPU_HZ / sim->INSNS_PER_RTC_TICK,
@@ -126,7 +128,7 @@ clint_t* clint_parse_from_fdt(const void* fdt, const sim_t* sim, reg_t* base,
return nullptr;
}
-std::string clint_generate_dts(const sim_t* sim, const std::vector<std::string>& UNUSED sargs) {
+std::string clint_generate_dts(const sim_t* sim, const std::vector<std::string>& sargs UNUSED) {
std::stringstream s;
s << std::hex
<< " clint@" << CLINT_BASE << " {\n"
diff --git a/riscv/csr_init.cc b/riscv/csr_init.cc
new file mode 100644
index 0000000..0acd1c7
--- /dev/null
+++ b/riscv/csr_init.cc
@@ -0,0 +1,552 @@
+#include "processor.h"
+#include "debug_defines.h"
+
+void state_t::add_csr(reg_t addr, const csr_t_p& csr)
+{
+ csrmap[addr] = csr;
+}
+
+#define add_const_ext_csr(ext, addr, csr) do { auto csr__ = (csr); if (proc->extension_enabled_const(ext)) { add_csr(addr, csr__); } } while (0)
+#define add_ext_csr(ext, addr, csr) do { auto csr__ = (csr); if (proc->extension_enabled(ext)) { add_csr(addr, csr__); } } while (0)
+#define add_user_csr(addr, csr) add_const_ext_csr('U', addr, csr)
+#define add_supervisor_csr(addr, csr) add_const_ext_csr('S', addr, csr)
+#define add_hypervisor_csr(addr, csr) add_ext_csr('H', addr, csr)
+
+void state_t::add_ireg_proxy(processor_t* const proc, sscsrind_reg_csr_t::sscsrind_reg_csr_t_p ireg)
+{
+ // This assumes xlen is always max_xlen, which is true today (see
+ // mstatus_csr_t::unlogged_write()):
+ auto xlen = proc->get_isa().get_max_xlen();
+
+ const reg_t iprio0_addr = 0x30;
+ for (int i=0; i<16; i+=2) {
+ csr_t_p iprio = std::make_shared<aia_csr_t>(proc, iprio0_addr + i, 0, 0);
+ if (xlen == 32) {
+ ireg->add_ireg_proxy(iprio0_addr + i, std::make_shared<rv32_low_csr_t>(proc, iprio0_addr + i, iprio));
+ ireg->add_ireg_proxy(iprio0_addr + i + 1, std::make_shared<rv32_high_csr_t>(proc, iprio0_addr + i + 1, iprio));
+ } else {
+ ireg->add_ireg_proxy(iprio0_addr + i, iprio);
+ }
+ }
+}
+
+void state_t::csr_init(processor_t* const proc, reg_t max_isa)
+{
+ // This assumes xlen is always max_xlen, which is true today (see
+ // mstatus_csr_t::unlogged_write()):
+ auto xlen = proc->get_isa().get_max_xlen();
+
+ add_csr(CSR_MISA, misa = std::make_shared<misa_csr_t>(proc, CSR_MISA, max_isa));
+ mstatus = std::make_shared<mstatus_csr_t>(proc, CSR_MSTATUS);
+
+ if (xlen == 32) {
+ add_csr(CSR_MSTATUS, std::make_shared<rv32_low_csr_t>(proc, CSR_MSTATUS, mstatus));
+ add_csr(CSR_MSTATUSH, mstatush = std::make_shared<rv32_high_csr_t>(proc, CSR_MSTATUSH, mstatus));
+ } else {
+ add_csr(CSR_MSTATUS, mstatus);
+ }
+ add_csr(CSR_MEPC, mepc = std::make_shared<epc_csr_t>(proc, CSR_MEPC));
+ add_csr(CSR_MTVAL, mtval = std::make_shared<basic_csr_t>(proc, CSR_MTVAL, 0));
+ add_csr(CSR_MSCRATCH, std::make_shared<basic_csr_t>(proc, CSR_MSCRATCH, 0));
+ add_csr(CSR_MTVEC, mtvec = std::make_shared<tvec_csr_t>(proc, CSR_MTVEC));
+ add_csr(CSR_MCAUSE, mcause = std::make_shared<cause_csr_t>(proc, CSR_MCAUSE));
+
+ const reg_t minstretcfg_mask = !proc->extension_enabled_const(EXT_SMCNTRPMF) ? 0 :
+ MHPMEVENT_MINH | MHPMEVENT_SINH | MHPMEVENT_UINH | MHPMEVENT_VSINH | MHPMEVENT_VUINH;
+ auto minstretcfg = std::make_shared<smcntrpmf_csr_t>(proc, CSR_MINSTRETCFG, minstretcfg_mask, 0);
+ auto mcyclecfg = std::make_shared<smcntrpmf_csr_t>(proc, CSR_MCYCLECFG, minstretcfg_mask, 0);
+
+ minstret = std::make_shared<wide_counter_csr_t>(proc, CSR_MINSTRET, minstretcfg);
+ mcycle = std::make_shared<wide_counter_csr_t>(proc, CSR_MCYCLE, mcyclecfg);
+ time = std::make_shared<time_counter_csr_t>(proc, CSR_TIME);
+ if (proc->extension_enabled_const(EXT_ZICNTR)) {
+ add_csr(CSR_INSTRET, std::make_shared<counter_proxy_csr_t>(proc, CSR_INSTRET, minstret));
+ add_csr(CSR_CYCLE, std::make_shared<counter_proxy_csr_t>(proc, CSR_CYCLE, mcycle));
+ add_csr(CSR_TIME, time_proxy = std::make_shared<counter_proxy_csr_t>(proc, CSR_TIME, time));
+ }
+ if (xlen == 32) {
+ csr_t_p minstreth, mcycleh;
+ add_csr(CSR_MINSTRET, std::make_shared<rv32_low_csr_t>(proc, CSR_MINSTRET, minstret));
+ add_csr(CSR_MINSTRETH, minstreth = std::make_shared<rv32_high_csr_t>(proc, CSR_MINSTRETH, minstret));
+ add_csr(CSR_MCYCLE, std::make_shared<rv32_low_csr_t>(proc, CSR_MCYCLE, mcycle));
+ add_csr(CSR_MCYCLEH, mcycleh = std::make_shared<rv32_high_csr_t>(proc, CSR_MCYCLEH, mcycle));
+ if (proc->extension_enabled_const(EXT_ZICNTR)) {
+ auto timeh = std::make_shared<rv32_high_csr_t>(proc, CSR_TIMEH, time);
+ add_csr(CSR_INSTRETH, std::make_shared<counter_proxy_csr_t>(proc, CSR_INSTRETH, minstreth));
+ add_csr(CSR_CYCLEH, std::make_shared<counter_proxy_csr_t>(proc, CSR_CYCLEH, mcycleh));
+ add_csr(CSR_TIMEH, std::make_shared<counter_proxy_csr_t>(proc, CSR_TIMEH, timeh));
+ }
+ } else {
+ add_csr(CSR_MINSTRET, minstret);
+ add_csr(CSR_MCYCLE, mcycle);
+ }
+ for (reg_t i = 0; i < N_HPMCOUNTERS; ++i) {
+ const reg_t which_mevent = CSR_MHPMEVENT3 + i;
+ const reg_t which_meventh = CSR_MHPMEVENT3H + i;
+ const reg_t which_mcounter = CSR_MHPMCOUNTER3 + i;
+ const reg_t which_mcounterh = CSR_MHPMCOUNTER3H + i;
+ const reg_t which_counter = CSR_HPMCOUNTER3 + i;
+ const reg_t which_counterh = CSR_HPMCOUNTER3H + i;
+ mevent[i] = std::make_shared<mevent_csr_t>(proc, which_mevent);
+ auto mcounter = std::make_shared<const_csr_t>(proc, which_mcounter, 0);
+ add_csr(which_mcounter, mcounter);
+
+ auto counter = std::make_shared<counter_proxy_csr_t>(proc, which_counter, mcounter);
+ add_const_ext_csr(EXT_ZIHPM, which_counter, counter);
+
+ if (xlen == 32) {
+ add_csr(which_mevent, std::make_shared<rv32_low_csr_t>(proc, which_mevent, mevent[i]));
+ auto mcounterh = std::make_shared<const_csr_t>(proc, which_mcounterh, 0);
+ add_csr(which_mcounterh, mcounterh);
+ add_const_ext_csr(EXT_ZIHPM, which_counterh, std::make_shared<counter_proxy_csr_t>(proc, which_counterh, mcounterh));
+ add_const_ext_csr(EXT_SSCOFPMF, which_meventh, std::make_shared<rv32_high_csr_t>(proc, which_meventh, mevent[i]));
+ } else {
+ add_csr(which_mevent, mevent[i]);
+ }
+ }
+ add_const_ext_csr(EXT_SSCOFPMF, CSR_SCOUNTOVF, std::make_shared<scountovf_csr_t>(proc, CSR_SCOUNTOVF));
+ mie = std::make_shared<mie_csr_t>(proc, CSR_MIE);
+ mip = std::make_shared<mip_csr_t>(proc, CSR_MIP);
+ if (xlen == 32 && proc->extension_enabled_const(EXT_SMAIA)) {
+ add_csr(CSR_MIE, std::make_shared<rv32_low_csr_t>(proc, CSR_MIE, mie));
+ add_csr(CSR_MIEH, std::make_shared<rv32_high_csr_t>(proc, CSR_MIEH, mie));
+ add_csr(CSR_MIP, std::make_shared<rv32_low_csr_t>(proc, CSR_MIP, mip));
+ add_csr(CSR_MIPH, std::make_shared<rv32_high_csr_t>(proc, CSR_MIPH, mip));
+ } else {
+ add_csr(CSR_MIE, mie);
+ add_csr(CSR_MIP, mip);
+ }
+ auto sip_sie_accr = std::make_shared<generic_int_accessor_t>(
+ this,
+ ~MIP_HS_MASK, // read_mask
+ MIP_SSIP | MIP_LCOFIP, // ip_write_mask
+ ~MIP_HS_MASK, // ie_write_mask
+ generic_int_accessor_t::mask_mode_t::MIDELEG,
+ 0 // shiftamt
+ );
+
+ auto hip_hie_accr = std::make_shared<generic_int_accessor_t>(
+ this,
+ MIP_HS_MASK, // read_mask
+ MIP_VSSIP, // ip_write_mask
+ MIP_HS_MASK, // ie_write_mask
+ generic_int_accessor_t::mask_mode_t::MIDELEG,
+ 0 // shiftamt
+ );
+
+ auto vsip_vsie_accr = std::make_shared<generic_int_accessor_t>(
+ this,
+ MIP_VS_MASK, // read_mask
+ MIP_VSSIP, // ip_write_mask
+ MIP_VS_MASK, // ie_write_mask
+ generic_int_accessor_t::mask_mode_t::HIDELEG,
+ 1 // shiftamt
+ );
+
+ nonvirtual_sip = std::make_shared<sip_csr_t>(proc, CSR_SIP, sip_sie_accr);
+ auto vsip = std::make_shared<mip_proxy_csr_t>(proc, CSR_VSIP, vsip_vsie_accr);
+ auto sip = std::make_shared<virtualized_csr_t>(proc, nonvirtual_sip, vsip);
+ if (xlen == 32 && proc->extension_enabled_const(EXT_SSAIA)) {
+ add_hypervisor_csr(CSR_VSIP, std::make_shared<rv32_low_csr_t>(proc, CSR_VSIP, vsip));
+ add_hypervisor_csr(CSR_VSIPH, std::make_shared<aia_rv32_high_csr_t>(proc, CSR_VSIPH, vsip));
+ add_supervisor_csr(CSR_SIP, std::make_shared<rv32_low_csr_t>(proc, CSR_SIP, sip));
+ add_supervisor_csr(CSR_SIPH, std::make_shared<aia_rv32_high_csr_t>(proc, CSR_SIPH, sip));
+ } else {
+ add_hypervisor_csr(CSR_VSIP, vsip);
+ add_supervisor_csr(CSR_SIP, sip);
+ }
+ add_hypervisor_csr(CSR_HIP, std::make_shared<mip_proxy_csr_t>(proc, CSR_HIP, hip_hie_accr));
+ hvip = std::make_shared<hvip_csr_t>(proc, CSR_HVIP, 0);
+ if (xlen == 32 && proc->extension_enabled_const(EXT_SSAIA)) {
+ add_hypervisor_csr(CSR_HVIP, std::make_shared<rv32_low_csr_t>(proc, CSR_HVIP, hvip));
+ add_hypervisor_csr(CSR_HVIPH, std::make_shared<aia_rv32_high_csr_t>(proc, CSR_HVIPH, hvip));
+ } else {
+ add_hypervisor_csr(CSR_HVIP, hvip);
+ }
+
+ nonvirtual_sie = std::make_shared<sie_csr_t>(proc, CSR_SIE, sip_sie_accr);
+ auto vsie = std::make_shared<mie_proxy_csr_t>(proc, CSR_VSIE, vsip_vsie_accr);
+ auto sie = std::make_shared<virtualized_csr_t>(proc, nonvirtual_sie, vsie);
+ if (xlen == 32 && proc->extension_enabled_const(EXT_SSAIA)) {
+ add_hypervisor_csr(CSR_VSIE, std::make_shared<rv32_low_csr_t>(proc, CSR_VSIE, vsie));
+ add_hypervisor_csr(CSR_VSIEH, std::make_shared<aia_rv32_high_csr_t>(proc, CSR_VSIEH, vsie));
+ add_supervisor_csr(CSR_SIE, std::make_shared<rv32_low_csr_t>(proc, CSR_SIE, sie));
+ add_supervisor_csr(CSR_SIEH, std::make_shared<aia_rv32_high_csr_t>(proc, CSR_SIEH, sie));
+ } else {
+ add_hypervisor_csr(CSR_VSIE, vsie);
+ add_supervisor_csr(CSR_SIE, sie);
+ }
+ add_hypervisor_csr(CSR_HIE, std::make_shared<mie_proxy_csr_t>(proc, CSR_HIE, hip_hie_accr));
+
+ add_supervisor_csr(CSR_MEDELEG, medeleg = std::make_shared<medeleg_csr_t>(proc, CSR_MEDELEG));
+ mideleg = std::make_shared<mideleg_csr_t>(proc, CSR_MIDELEG);
+ if (xlen == 32 && proc->extension_enabled_const(EXT_SMAIA)) {
+ add_supervisor_csr(CSR_MIDELEG, std::make_shared<rv32_low_csr_t>(proc, CSR_MIDELEG, mideleg));
+ add_supervisor_csr(CSR_MIDELEGH, std::make_shared<aia_rv32_high_csr_t>(proc, CSR_MIDELEGH, mideleg));
+ } else {
+ add_supervisor_csr(CSR_MIDELEG, mideleg);
+ }
+ const reg_t counteren_mask = (proc->extension_enabled_const(EXT_ZICNTR) ? 0x7UL : 0x0) | (proc->extension_enabled_const(EXT_ZIHPM) ? 0xfffffff8ULL : 0x0);
+ add_user_csr(CSR_MCOUNTEREN, mcounteren = std::make_shared<masked_csr_t>(proc, CSR_MCOUNTEREN, counteren_mask, 0));
+ add_csr(CSR_MCOUNTINHIBIT, mcountinhibit = std::make_shared<masked_csr_t>(proc, CSR_MCOUNTINHIBIT, counteren_mask & (~MCOUNTEREN_TIME), 0));
+ add_supervisor_csr(CSR_SCOUNTEREN, scounteren = std::make_shared<masked_csr_t>(proc, CSR_SCOUNTEREN, counteren_mask, 0));
+ nonvirtual_sepc = std::make_shared<epc_csr_t>(proc, CSR_SEPC);
+ add_hypervisor_csr(CSR_VSEPC, vsepc = std::make_shared<epc_csr_t>(proc, CSR_VSEPC));
+ add_supervisor_csr(CSR_SEPC, sepc = std::make_shared<virtualized_csr_t>(proc, nonvirtual_sepc, vsepc));
+ nonvirtual_stval = std::make_shared<basic_csr_t>(proc, CSR_STVAL, 0);
+ add_hypervisor_csr(CSR_VSTVAL, vstval = std::make_shared<basic_csr_t>(proc, CSR_VSTVAL, 0));
+ add_supervisor_csr(CSR_STVAL, stval = std::make_shared<virtualized_csr_t>(proc, nonvirtual_stval, vstval));
+ auto sscratch = std::make_shared<basic_csr_t>(proc, CSR_SSCRATCH, 0);
+ auto vsscratch = std::make_shared<basic_csr_t>(proc, CSR_VSSCRATCH, 0);
+ // Note: if max_isa does not include H, we don't really need this virtualized_csr_t at all (though it doesn't hurt):
+ add_supervisor_csr(CSR_SSCRATCH, std::make_shared<virtualized_csr_t>(proc, sscratch, vsscratch));
+ add_hypervisor_csr(CSR_VSSCRATCH, vsscratch);
+ nonvirtual_stvec = std::make_shared<tvec_csr_t>(proc, CSR_STVEC);
+ add_hypervisor_csr(CSR_VSTVEC, vstvec = std::make_shared<tvec_csr_t>(proc, CSR_VSTVEC));
+ add_supervisor_csr(CSR_STVEC, stvec = std::make_shared<virtualized_csr_t>(proc, nonvirtual_stvec, vstvec));
+ auto nonvirtual_satp = std::make_shared<satp_csr_t>(proc, CSR_SATP);
+ add_hypervisor_csr(CSR_VSATP, vsatp = std::make_shared<base_atp_csr_t>(proc, CSR_VSATP));
+ add_supervisor_csr(CSR_SATP, satp = std::make_shared<virtualized_satp_csr_t>(proc, nonvirtual_satp, vsatp));
+ nonvirtual_scause = std::make_shared<cause_csr_t>(proc, CSR_SCAUSE);
+ add_hypervisor_csr(CSR_VSCAUSE, vscause = std::make_shared<cause_csr_t>(proc, CSR_VSCAUSE));
+ add_supervisor_csr(CSR_SCAUSE, scause = std::make_shared<virtualized_csr_t>(proc, nonvirtual_scause, vscause));
+ mtval2 = std::make_shared<mtval2_csr_t>(proc, CSR_MTVAL2);
+ if (proc->extension_enabled('H') || proc->extension_enabled(EXT_SSDBLTRP))
+ add_csr(CSR_MTVAL2, mtval2);
+ add_hypervisor_csr(CSR_MTINST, mtinst = std::make_shared<hypervisor_csr_t>(proc, CSR_MTINST));
+ add_hypervisor_csr(CSR_HSTATUS, hstatus = std::make_shared<hstatus_csr_t>(proc, CSR_HSTATUS));
+ add_hypervisor_csr(CSR_HGEIE, std::make_shared<const_csr_t>(proc, CSR_HGEIE, 0));
+ add_hypervisor_csr(CSR_HGEIP, std::make_shared<const_csr_t>(proc, CSR_HGEIP, 0));
+ hideleg = std::make_shared<hideleg_csr_t>(proc, CSR_HIDELEG, mideleg);
+ if (xlen == 32 && proc->extension_enabled_const(EXT_SSAIA)) {
+ add_hypervisor_csr(CSR_HIDELEG, std::make_shared<rv32_low_csr_t>(proc, CSR_HIDELEG, hideleg));
+ add_hypervisor_csr(CSR_HIDELEGH, std::make_shared<aia_rv32_high_csr_t>(proc, CSR_HIDELEGH, hideleg));
+ } else {
+ add_hypervisor_csr(CSR_HIDELEG, hideleg);
+ }
+ const reg_t hedeleg_mask =
+ (1 << CAUSE_MISALIGNED_FETCH) |
+ (1 << CAUSE_FETCH_ACCESS) |
+ (1 << CAUSE_ILLEGAL_INSTRUCTION) |
+ (1 << CAUSE_BREAKPOINT) |
+ (1 << CAUSE_MISALIGNED_LOAD) |
+ (1 << CAUSE_LOAD_ACCESS) |
+ (1 << CAUSE_MISALIGNED_STORE) |
+ (1 << CAUSE_STORE_ACCESS) |
+ (1 << CAUSE_USER_ECALL) |
+ (1 << CAUSE_FETCH_PAGE_FAULT) |
+ (1 << CAUSE_LOAD_PAGE_FAULT) |
+ (1 << CAUSE_STORE_PAGE_FAULT) |
+ (1 << CAUSE_SOFTWARE_CHECK_FAULT) |
+ (1 << CAUSE_HARDWARE_ERROR_FAULT);
+ add_hypervisor_csr(CSR_HEDELEG, hedeleg = std::make_shared<masked_csr_t>(proc, CSR_HEDELEG, hedeleg_mask, 0));
+ add_hypervisor_csr(CSR_HCOUNTEREN, hcounteren = std::make_shared<masked_csr_t>(proc, CSR_HCOUNTEREN, counteren_mask, 0));
+ htimedelta = std::make_shared<basic_csr_t>(proc, CSR_HTIMEDELTA, 0);
+ if (xlen == 32) {
+ add_hypervisor_csr(CSR_HTIMEDELTA, std::make_shared<rv32_low_csr_t>(proc, CSR_HTIMEDELTA, htimedelta));
+ add_hypervisor_csr(CSR_HTIMEDELTAH, std::make_shared<rv32_high_csr_t>(proc, CSR_HTIMEDELTAH, htimedelta));
+ } else {
+ add_hypervisor_csr(CSR_HTIMEDELTA, htimedelta);
+ }
+ add_hypervisor_csr(CSR_HTVAL, htval = std::make_shared<basic_csr_t>(proc, CSR_HTVAL, 0));
+ add_hypervisor_csr(CSR_HTINST, htinst = std::make_shared<basic_csr_t>(proc, CSR_HTINST, 0));
+ add_hypervisor_csr(CSR_HGATP, hgatp = std::make_shared<hgatp_csr_t>(proc, CSR_HGATP));
+ nonvirtual_sstatus = std::make_shared<sstatus_proxy_csr_t>(proc, CSR_SSTATUS, mstatus);
+ add_hypervisor_csr(CSR_VSSTATUS, vsstatus = std::make_shared<vsstatus_csr_t>(proc, CSR_VSSTATUS));
+ add_supervisor_csr(CSR_SSTATUS, sstatus = std::make_shared<sstatus_csr_t>(proc, nonvirtual_sstatus, vsstatus));
+
+ add_csr(CSR_DPC, dpc = std::make_shared<dpc_csr_t>(proc, CSR_DPC));
+ add_csr(CSR_DSCRATCH0, std::make_shared<debug_mode_csr_t>(proc, CSR_DSCRATCH0));
+ add_csr(CSR_DSCRATCH1, std::make_shared<debug_mode_csr_t>(proc, CSR_DSCRATCH1));
+ add_csr(CSR_DCSR, dcsr = std::make_shared<dcsr_csr_t>(proc, CSR_DCSR));
+
+ add_csr(CSR_TSELECT, tselect = std::make_shared<tselect_csr_t>(proc, CSR_TSELECT));
+ if (proc->get_cfg().trigger_count > 0) {
+ add_csr(CSR_TDATA1, std::make_shared<tdata1_csr_t>(proc, CSR_TDATA1));
+ add_csr(CSR_TDATA2, tdata2 = std::make_shared<tdata2_csr_t>(proc, CSR_TDATA2));
+ add_csr(CSR_TDATA3, std::make_shared<tdata3_csr_t>(proc, CSR_TDATA3));
+ add_csr(CSR_TINFO, std::make_shared<tinfo_csr_t>(proc, CSR_TINFO));
+ if (!proc->extension_enabled_const('S')) {
+ add_csr(CSR_TCONTROL, tcontrol = std::make_shared<masked_csr_t>(proc, CSR_TCONTROL, CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE, 0));
+ }
+ } else {
+ add_csr(CSR_TDATA1, std::make_shared<const_csr_t>(proc, CSR_TDATA1, 0));
+ add_csr(CSR_TDATA2, tdata2 = std::make_shared<const_csr_t>(proc, CSR_TDATA2, 0));
+ add_csr(CSR_TDATA3, std::make_shared<const_csr_t>(proc, CSR_TDATA3, 0));
+ add_csr(CSR_TINFO, std::make_shared<const_csr_t>(proc, CSR_TINFO, 0));
+ }
+ unsigned scontext_length = (xlen == 32 ? 16 : 32); // debug spec suggests 16-bit for RV32 and 32-bit for RV64
+ add_supervisor_csr(CSR_SCONTEXT, scontext = std::make_shared<masked_csr_t>(proc, CSR_SCONTEXT, (reg_t(1) << scontext_length) - 1, 0));
+ unsigned hcontext_length = (xlen == 32 ? 6 : 13) + (proc->extension_enabled('H') ? 1 : 0); // debug spec suggest 7-bit (6-bit) for RV32 and 14-bit (13-bit) for RV64 with (without) H extension
+ auto hcontext = std::make_shared<masked_csr_t>(proc, CSR_HCONTEXT, (reg_t(1) << hcontext_length) - 1, 0);
+ add_hypervisor_csr(CSR_HCONTEXT, hcontext);
+ add_csr(CSR_MCONTEXT, mcontext = std::make_shared<proxy_csr_t>(proc, CSR_MCONTEXT, hcontext));
+ add_csr(CSR_MSECCFG, mseccfg = std::make_shared<mseccfg_csr_t>(proc, CSR_MSECCFG));
+
+ for (int i = 0; i < max_pmp; ++i) {
+ add_csr(CSR_PMPADDR0 + i, pmpaddr[i] = std::make_shared<pmpaddr_csr_t>(proc, CSR_PMPADDR0 + i));
+ }
+ for (int i = 0; i < max_pmp; i += xlen / 8) {
+ reg_t addr = CSR_PMPCFG0 + i / 4;
+ add_csr(addr, std::make_shared<pmpcfg_csr_t>(proc, addr));
+ }
+
+ add_csr(CSR_FFLAGS, fflags = std::make_shared<float_csr_t>(proc, CSR_FFLAGS, FSR_AEXC >> FSR_AEXC_SHIFT, 0));
+ add_csr(CSR_FRM, frm = std::make_shared<float_csr_t>(proc, CSR_FRM, FSR_RD >> FSR_RD_SHIFT, 0));
+ assert(FSR_AEXC_SHIFT == 0); // composite_csr_t assumes fflags begins at bit 0
+ add_csr(CSR_FCSR, std::make_shared<composite_csr_t>(proc, CSR_FCSR, frm, fflags, FSR_RD_SHIFT));
+
+ add_ext_csr(EXT_ZKR, CSR_SEED, std::make_shared<seed_csr_t>(proc, CSR_SEED));
+
+ add_csr(CSR_MARCHID, std::make_shared<const_csr_t>(proc, CSR_MARCHID, 5));
+ add_csr(CSR_MIMPID, std::make_shared<const_csr_t>(proc, CSR_MIMPID, 0));
+ add_csr(CSR_MVENDORID, std::make_shared<const_csr_t>(proc, CSR_MVENDORID, 0));
+ add_csr(CSR_MHARTID, std::make_shared<const_csr_t>(proc, CSR_MHARTID, proc->get_id()));
+ add_csr(CSR_MCONFIGPTR, std::make_shared<const_csr_t>(proc, CSR_MCONFIGPTR, 0));
+ const reg_t menvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? MENVCFG_CBCFE | MENVCFG_CBIE : 0) |
+ (proc->extension_enabled(EXT_ZICBOZ) ? MENVCFG_CBZE : 0) |
+ (proc->extension_enabled(EXT_SMNPM) ? MENVCFG_PMM : 0) |
+ (proc->extension_enabled(EXT_SVADU) ? MENVCFG_ADUE: 0) |
+ (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0) |
+ (proc->extension_enabled(EXT_SSTC) ? MENVCFG_STCE : 0) |
+ (proc->extension_enabled(EXT_ZICFILP) ? MENVCFG_LPE : 0) |
+ (proc->extension_enabled(EXT_ZICFISS) ? MENVCFG_SSE : 0) |
+ (proc->extension_enabled(EXT_SSDBLTRP) ? MENVCFG_DTE : 0)|
+ (proc->extension_enabled(EXT_SMCDELEG) ? MENVCFG_CDE : 0);
+ menvcfg = std::make_shared<envcfg_csr_t>(proc, CSR_MENVCFG, menvcfg_mask, 0);
+ if (xlen == 32) {
+ add_user_csr(CSR_MENVCFG, std::make_shared<rv32_low_csr_t>(proc, CSR_MENVCFG, menvcfg));
+ add_user_csr(CSR_MENVCFGH, std::make_shared<rv32_high_csr_t>(proc, CSR_MENVCFGH, menvcfg));
+ } else {
+ add_user_csr(CSR_MENVCFG, menvcfg);
+ }
+ const reg_t senvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? SENVCFG_CBCFE | SENVCFG_CBIE : 0) |
+ (proc->extension_enabled(EXT_ZICBOZ) ? SENVCFG_CBZE : 0) |
+ (proc->extension_enabled(EXT_SSNPM) ? SENVCFG_PMM : 0) |
+ (proc->extension_enabled(EXT_ZICFILP) ? SENVCFG_LPE : 0) |
+ (proc->extension_enabled(EXT_ZICFISS) ? SENVCFG_SSE : 0);
+ add_supervisor_csr(CSR_SENVCFG, senvcfg = std::make_shared<senvcfg_csr_t>(proc, CSR_SENVCFG, senvcfg_mask, 0));
+ const reg_t henvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? HENVCFG_CBCFE | HENVCFG_CBIE : 0) |
+ (proc->extension_enabled(EXT_ZICBOZ) ? HENVCFG_CBZE : 0) |
+ (proc->extension_enabled(EXT_SSNPM) ? HENVCFG_PMM : 0) |
+ (proc->extension_enabled(EXT_SVADU) ? HENVCFG_ADUE: 0) |
+ (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0) |
+ (proc->extension_enabled(EXT_SSTC) ? HENVCFG_STCE : 0) |
+ (proc->extension_enabled(EXT_ZICFILP) ? HENVCFG_LPE : 0) |
+ (proc->extension_enabled(EXT_ZICFISS) ? HENVCFG_SSE : 0) |
+ (proc->extension_enabled(EXT_SSDBLTRP) ? HENVCFG_DTE : 0);
+ henvcfg = std::make_shared<henvcfg_csr_t>(proc, CSR_HENVCFG, henvcfg_mask, 0, menvcfg);
+ if (xlen == 32) {
+ add_hypervisor_csr(CSR_HENVCFG, std::make_shared<rv32_low_csr_t>(proc, CSR_HENVCFG, henvcfg));
+ add_hypervisor_csr(CSR_HENVCFGH, std::make_shared<rv32_high_csr_t>(proc, CSR_HENVCFGH, henvcfg));
+ } else {
+ add_hypervisor_csr(CSR_HENVCFG, henvcfg);
+ }
+ if (proc->extension_enabled_const(EXT_SMSTATEEN)) {
+ const reg_t sstateen0_mask = (proc->extension_enabled(EXT_ZFINX) ? SSTATEEN0_FCSR : 0) |
+ (proc->extension_enabled(EXT_ZCMT) ? SSTATEEN0_JVT : 0) |
+ SSTATEEN0_CS;
+ const reg_t hstateen0_mask = sstateen0_mask | HSTATEEN0_CSRIND | HSTATEEN0_SENVCFG | HSTATEEN_SSTATEEN;
+ const reg_t mstateen0_mask = hstateen0_mask | (proc->extension_enabled(EXT_SSQOSID) ? MSTATEEN0_PRIV114 : 0);
+ for (int i = 0; i < 4; i++) {
+ const reg_t mstateen_mask = i == 0 ? mstateen0_mask : MSTATEEN_HSTATEEN;
+ mstateen[i] = std::make_shared<masked_csr_t>(proc, CSR_MSTATEEN0 + i, mstateen_mask, 0);
+ if (xlen == 32) {
+ add_csr(CSR_MSTATEEN0 + i, std::make_shared<rv32_low_csr_t>(proc, CSR_MSTATEEN0 + i, mstateen[i]));
+ add_csr(CSR_MSTATEEN0H + i, std::make_shared<rv32_high_csr_t>(proc, CSR_MSTATEEN0H + i, mstateen[i]));
+ } else {
+ add_csr(CSR_MSTATEEN0 + i, mstateen[i]);
+ }
+
+ const reg_t hstateen_mask = i == 0 ? hstateen0_mask : HSTATEEN_SSTATEEN;
+ hstateen[i] = std::make_shared<hstateen_csr_t>(proc, CSR_HSTATEEN0 + i, hstateen_mask, 0, i);
+ if (xlen == 32) {
+ add_hypervisor_csr(CSR_HSTATEEN0 + i, std::make_shared<rv32_low_csr_t>(proc, CSR_HSTATEEN0 + i, hstateen[i]));
+ add_hypervisor_csr(CSR_HSTATEEN0H + i, std::make_shared<rv32_high_csr_t>(proc, CSR_HSTATEEN0H + i, hstateen[i]));
+ } else {
+ add_hypervisor_csr(CSR_HSTATEEN0 + i, hstateen[i]);
+ }
+
+ const reg_t sstateen_mask = i == 0 ? sstateen0_mask : 0;
+ add_supervisor_csr(CSR_SSTATEEN0 + i, sstateen[i] = std::make_shared<sstateen_csr_t>(proc, CSR_SSTATEEN0 + i, sstateen_mask, 0, i));
+ }
+ }
+
+ if (proc->extension_enabled_const(EXT_SMRNMI)) {
+ add_csr(CSR_MNSCRATCH, std::make_shared<basic_csr_t>(proc, CSR_MNSCRATCH, 0));
+ add_csr(CSR_MNEPC, mnepc = std::make_shared<epc_csr_t>(proc, CSR_MNEPC));
+ add_csr(CSR_MNCAUSE, std::make_shared<const_csr_t>(proc, CSR_MNCAUSE, (reg_t)1 << (xlen - 1)));
+ add_csr(CSR_MNSTATUS, mnstatus = std::make_shared<mnstatus_csr_t>(proc, CSR_MNSTATUS));
+ }
+
+ if (proc->extension_enabled_const(EXT_SSTC)) {
+ stimecmp = std::make_shared<stimecmp_csr_t>(proc, CSR_STIMECMP, MIP_STIP);
+ vstimecmp = std::make_shared<stimecmp_csr_t>(proc, CSR_VSTIMECMP, MIP_VSTIP);
+ auto virtualized_stimecmp = std::make_shared<virtualized_with_special_permission_csr_t>(proc, stimecmp, vstimecmp);
+ if (xlen == 32) {
+ add_supervisor_csr(CSR_STIMECMP, std::make_shared<rv32_low_csr_t>(proc, CSR_STIMECMP, virtualized_stimecmp));
+ add_supervisor_csr(CSR_STIMECMPH, std::make_shared<rv32_high_csr_t>(proc, CSR_STIMECMPH, virtualized_stimecmp));
+ add_hypervisor_csr(CSR_VSTIMECMP, std::make_shared<rv32_low_csr_t>(proc, CSR_VSTIMECMP, vstimecmp));
+ add_hypervisor_csr(CSR_VSTIMECMPH, std::make_shared<rv32_high_csr_t>(proc, CSR_VSTIMECMPH, vstimecmp));
+ } else {
+ add_supervisor_csr(CSR_STIMECMP, virtualized_stimecmp);
+ add_hypervisor_csr(CSR_VSTIMECMP, vstimecmp);
+ }
+ }
+
+ add_ext_csr(EXT_ZCMT, CSR_JVT, jvt = std::make_shared<jvt_csr_t>(proc, CSR_JVT, 0));
+
+ const reg_t ssp_mask = -reg_t(xlen / 8);
+ add_ext_csr(EXT_ZICFISS, CSR_SSP, ssp = std::make_shared<ssp_csr_t>(proc, CSR_SSP, ssp_mask, 0));
+
+ // Smcdeleg
+ if (proc->extension_enabled_const(EXT_SMCDELEG) || proc->extension_enabled_const(EXT_SSCCFG)) {
+ add_supervisor_csr(CSR_SCOUNTINHIBIT, scountinhibit = std::make_shared<scntinhibit_csr_t>(proc, CSR_SCOUNTINHIBIT, mcountinhibit));
+ }
+
+ // Smcsrind / Sscsrind
+ if (proc->extension_enabled_const(EXT_SMCSRIND)) {
+ csr_t_p miselect = std::make_shared<basic_csr_t>(proc, CSR_MISELECT, 0);
+ add_csr(CSR_MISELECT, miselect);
+
+ sscsrind_reg_csr_t::sscsrind_reg_csr_t_p mireg;
+ add_csr(CSR_MIREG, mireg = std::make_shared<sscsrind_reg_csr_t>(proc, CSR_MIREG, miselect));
+ add_ireg_proxy(proc, mireg);
+ const reg_t mireg_csrs[] = { CSR_MIREG2, CSR_MIREG3, CSR_MIREG4, CSR_MIREG5, CSR_MIREG6 };
+ for (auto csr : mireg_csrs)
+ add_csr(csr, std::make_shared<sscsrind_reg_csr_t>(proc, csr, miselect));
+ }
+
+ if (proc->extension_enabled_const(EXT_SSCSRIND)) {
+ csr_t_p vsiselect = std::make_shared<siselect_csr_t>(proc, CSR_VSISELECT, 0);
+ add_hypervisor_csr(CSR_VSISELECT, vsiselect);
+
+ csr_t_p siselect = std::make_shared<siselect_csr_t>(proc, CSR_SISELECT, 0);
+ add_supervisor_csr(CSR_SISELECT, std::make_shared<virtualized_with_special_permission_csr_t>(proc, siselect, vsiselect));
+
+ auto vsireg = std::make_shared<sscsrind_reg_csr_t>(proc, CSR_VSIREG, vsiselect);
+ add_hypervisor_csr(CSR_VSIREG, vsireg);
+
+ auto sireg = std::make_shared<sscsrind_reg_csr_t>(proc, CSR_SIREG, siselect);
+ add_ireg_proxy(proc, sireg);
+ add_supervisor_csr(CSR_SIREG, std::make_shared<virtualized_indirect_csr_t>(proc, sireg, vsireg));
+
+ const reg_t vsireg_csrs[] = { CSR_VSIREG2, CSR_VSIREG3, CSR_VSIREG4, CSR_VSIREG5, CSR_VSIREG6 };
+ const reg_t sireg_csrs[] = { CSR_SIREG2, CSR_SIREG3, CSR_SIREG4, CSR_SIREG5, CSR_SIREG6 };
+ for (size_t i = 0; i < std::size(vsireg_csrs); i++) {
+ auto vsireg = std::make_shared<sscsrind_reg_csr_t>(proc, vsireg_csrs[i], vsiselect);
+ add_hypervisor_csr(vsireg_csrs[i], vsireg);
+
+ auto sireg = std::make_shared<sscsrind_reg_csr_t>(proc, sireg_csrs[i], siselect);
+ add_supervisor_csr(sireg_csrs[i], std::make_shared<virtualized_indirect_csr_t>(proc, sireg, vsireg));
+
+ // Smcdeleg
+ if (proc->extension_enabled(EXT_SSCCFG) || proc->extension_enabled(EXT_SMCDELEG)) {
+ switch (sireg_csrs[i]) {
+ case CSR_SIREG:
+ if (proc->extension_enabled_const(EXT_ZICNTR)) {
+ sireg->add_ireg_proxy(SISELECT_SMCDELEG_START, mcycle);
+ sireg->add_ireg_proxy(SISELECT_SMCDELEG_INSTRET, minstret);
+ }
+ if (proc->extension_enabled_const(EXT_ZIHPM)) {
+ for (size_t j = 0; j < (SISELECT_SMCDELEG_END - SISELECT_SMCDELEG_HPMEVENT_3 + 1); j++)
+ sireg->add_ireg_proxy(SISELECT_SMCDELEG_HPMCOUNTER_3 + j, csrmap[CSR_HPMCOUNTER3 + j]);
+ }
+ break;
+ case CSR_SIREG4:
+ if (xlen == 32) {
+ if (proc->extension_enabled_const(EXT_ZICNTR)) {
+ sireg->add_ireg_proxy(SISELECT_SMCDELEG_START, csrmap[CSR_CYCLEH]);
+ sireg->add_ireg_proxy(SISELECT_SMCDELEG_INSTRET, csrmap[CSR_INSTRETH]);
+ }
+ if (proc->extension_enabled_const(EXT_ZIHPM)) {
+ for (size_t j = 0; j < (SISELECT_SMCDELEG_END - SISELECT_SMCDELEG_HPMEVENT_3 + 1); j++)
+ sireg->add_ireg_proxy(SISELECT_SMCDELEG_HPMCOUNTER_3 + j, csrmap[CSR_HPMCOUNTER3H + j]);
+ }
+ }
+ break;
+ case CSR_SIREG2:
+ if (proc->extension_enabled_const(EXT_ZICNTR)) {
+ sireg->add_ireg_proxy(SISELECT_SMCDELEG_START, mcyclecfg);
+ sireg->add_ireg_proxy(SISELECT_SMCDELEG_INSTRETCFG, minstretcfg);
+ }
+ if (proc->extension_enabled_const(EXT_ZIHPM)) {
+ for (size_t j = 0; j < (SISELECT_SMCDELEG_END - SISELECT_SMCDELEG_HPMEVENT_3 + 1); j++)
+ sireg->add_ireg_proxy(SISELECT_SMCDELEG_HPMEVENT_3 + j, csrmap[CSR_MHPMEVENT3H + j]);
+ }
+ break;
+ case CSR_SIREG5:
+ if (xlen == 32) {
+ if (proc->extension_enabled_const(EXT_ZICNTR)) {
+ sireg->add_ireg_proxy(SISELECT_SMCDELEG_START, mcycle);
+ sireg->add_ireg_proxy(SISELECT_SMCDELEG_INSTRET, minstret);
+ }
+ if (proc->extension_enabled_const(EXT_ZIHPM)) {
+ for (size_t j = 0; j < (SISELECT_SMCDELEG_END - SISELECT_SMCDELEG_HPMEVENT_3); j++)
+ sireg->add_ireg_proxy(SISELECT_SMCDELEG_HPMCOUNTER_3 + j, csrmap[CSR_HPMCOUNTER3 + j]);
+ }
+ }
+ case CSR_SIREG3:
+ case CSR_SIREG6:
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ if (proc->extension_enabled_const(EXT_SMCNTRPMF)) {
+ if (xlen == 32) {
+ add_csr(CSR_MCYCLECFG, std::make_shared<rv32_low_csr_t>(proc, CSR_MCYCLECFG, mcyclecfg));
+ add_csr(CSR_MCYCLECFGH, std::make_shared<rv32_high_csr_t>(proc, CSR_MCYCLECFGH, mcyclecfg));
+ add_csr(CSR_MINSTRETCFG, std::make_shared<rv32_low_csr_t>(proc, CSR_MINSTRETCFG, minstretcfg));
+ add_csr(CSR_MINSTRETCFGH, std::make_shared<rv32_high_csr_t>(proc, CSR_MINSTRETCFGH, minstretcfg));
+ } else {
+ add_csr(CSR_MCYCLECFG, mcyclecfg);
+ add_csr(CSR_MINSTRETCFG, minstretcfg);
+ }
+ }
+
+ const reg_t srmcfg_mask = SRMCFG_MCID | SRMCFG_RCID;
+ add_const_ext_csr(EXT_SSQOSID, CSR_SRMCFG, std::make_shared<srmcfg_csr_t>(proc, CSR_SRMCFG, srmcfg_mask, 0));
+
+ mvien = std::make_shared<masked_csr_t>(proc, CSR_MVIEN, MIP_SEIP | MIP_SSIP, 0);
+ mvip = std::make_shared<mvip_csr_t>(proc, CSR_MVIP, 0);
+ if (proc->extension_enabled_const(EXT_SMAIA)) {
+ add_csr(CSR_MTOPI, std::make_shared<mtopi_csr_t>(proc, CSR_MTOPI));
+ if (xlen == 32) {
+ add_supervisor_csr(CSR_MVIEN, std::make_shared<rv32_low_csr_t>(proc, CSR_MVIEN, mvien));
+ add_supervisor_csr(CSR_MVIENH, std::make_shared<rv32_high_csr_t>(proc, CSR_MVIENH, mvien));
+ add_supervisor_csr(CSR_MVIP, std::make_shared<rv32_low_csr_t>(proc, CSR_MVIP, mvip));
+ add_supervisor_csr(CSR_MVIPH, std::make_shared<rv32_high_csr_t>(proc, CSR_MVIPH, mvip));
+ } else {
+ add_supervisor_csr(CSR_MVIEN, mvien);
+ add_supervisor_csr(CSR_MVIP, mvip);
+ }
+ }
+
+ hvictl = std::make_shared<aia_csr_t>(proc, CSR_HVICTL, HVICTL_VTI | HVICTL_IID | HVICTL_DPR | HVICTL_IPRIOM | HVICTL_IPRIO, 0);
+ vstopi = std::make_shared<vstopi_csr_t>(proc, CSR_VSTOPI);
+ if (proc->extension_enabled_const(EXT_SSAIA)) { // Included by EXT_SMAIA
+ csr_t_p nonvirtual_stopi = std::make_shared<nonvirtual_stopi_csr_t>(proc, CSR_STOPI);
+ add_supervisor_csr(CSR_STOPI, std::make_shared<virtualized_with_special_permission_csr_t>(proc, nonvirtual_stopi, vstopi));
+ add_supervisor_csr(CSR_STOPEI, std::make_shared<inaccessible_csr_t>(proc, CSR_STOPEI));
+ auto hvien = std::make_shared<aia_csr_t>(proc, CSR_HVIEN, 0, 0);
+ auto hviprio1 = std::make_shared<aia_csr_t>(proc, CSR_HVIPRIO1, 0, 0);
+ auto hviprio2 = std::make_shared<aia_csr_t>(proc, CSR_HVIPRIO2, 0, 0);
+ if (xlen == 32) {
+ add_hypervisor_csr(CSR_HVIEN, std::make_shared<rv32_low_csr_t>(proc, CSR_HVIEN, hvien));
+ add_hypervisor_csr(CSR_HVIENH, std::make_shared<rv32_high_csr_t>(proc, CSR_HVIENH, hvien));
+ add_hypervisor_csr(CSR_HVIPRIO1, std::make_shared<rv32_low_csr_t>(proc, CSR_HVIPRIO1, hviprio1));
+ add_hypervisor_csr(CSR_HVIPRIO1H, std::make_shared<rv32_high_csr_t>(proc, CSR_HVIPRIO1H, hviprio1));
+ add_hypervisor_csr(CSR_HVIPRIO2, std::make_shared<rv32_low_csr_t>(proc, CSR_HVIPRIO2, hviprio2));
+ add_hypervisor_csr(CSR_HVIPRIO2H, std::make_shared<rv32_high_csr_t>(proc, CSR_HVIPRIO2H, hviprio2));
+ } else {
+ add_hypervisor_csr(CSR_HVIEN, hvien);
+ add_hypervisor_csr(CSR_HVIPRIO1, hviprio1);
+ add_hypervisor_csr(CSR_HVIPRIO2, hviprio2);
+ }
+ add_hypervisor_csr(CSR_HVICTL, hvictl);
+ add_hypervisor_csr(CSR_VSTOPI, vstopi);
+ }
+}
diff --git a/riscv/csrs.cc b/riscv/csrs.cc
index 02a2c4f..3a32712 100644
--- a/riscv/csrs.cc
+++ b/riscv/csrs.cc
@@ -15,6 +15,8 @@
#include "insn_macros.h"
// For CSR_DCSR_V:
#include "debug_defines.h"
+// For ctz:
+#include "arith.h"
// STATE macro used by require_privilege() macro:
#undef STATE
@@ -197,13 +199,13 @@ bool pmpaddr_csr_t::access_ok(access_type type, reg_t mode, bool hlvx) const noe
if (mseccfg_mml) {
if (cfgx && cfgw && cfgr && cfgl) {
// Locked Shared data region: Read only on both M and S/U mode.
- return typer;
+ return typer && !hlvx;
} else {
const bool mml_shared_region = !cfgr && cfgw;
const bool mml_chk_normal = (prvm == cfgl) && normal_rwx;
const bool mml_chk_shared =
- (!cfgl && cfgx && (typer || typew)) ||
- (!cfgl && !cfgx && (typer || (typew && prvm))) ||
+ (!cfgl && cfgx && ((typer && !hlvx) || typew)) ||
+ (!cfgl && !cfgx && ((typer && !hlvx) || (typew && prvm))) ||
(cfgl && typex) ||
(cfgl && typer && cfgx && prvm);
return mml_shared_region ? mml_chk_shared : mml_chk_normal;
@@ -286,7 +288,9 @@ mseccfg_csr_t::mseccfg_csr_t(processor_t* const proc, const reg_t addr):
void mseccfg_csr_t::verify_permissions(insn_t insn, bool write) const {
basic_csr_t::verify_permissions(insn, write);
if (!proc->extension_enabled(EXT_SMEPMP) &&
- !proc->extension_enabled(EXT_ZICFILP))
+ !proc->extension_enabled(EXT_SMMPM) &&
+ !proc->extension_enabled(EXT_ZICFILP) &&
+ !proc->extension_enabled(EXT_ZKR))
throw trap_illegal_instruction(insn.bits());
}
@@ -302,32 +306,51 @@ bool mseccfg_csr_t::get_rlb() const noexcept {
return (read() & MSECCFG_RLB);
}
-bool mseccfg_csr_t::unlogged_write(const reg_t val) noexcept {
- if (proc->n_pmp == 0)
- return false;
+bool mseccfg_csr_t::get_useed() const noexcept {
+ return (read() & MSECCFG_USEED);
+}
- // pmpcfg.L is 1 in any rule or entry (including disabled entries)
- const bool pmplock_recorded = std::any_of(state->pmpaddr, state->pmpaddr + proc->n_pmp,
- [](const pmpaddr_csr_t_p & c) { return c->is_locked(); } );
+bool mseccfg_csr_t::get_sseed() const noexcept {
+ return (read() & MSECCFG_SSEED);
+}
+
+bool mseccfg_csr_t::unlogged_write(const reg_t val) noexcept {
reg_t new_val = read();
- // When RLB is 0 and pmplock_recorded, RLB is locked to 0.
- // Otherwise set the RLB bit according val
- if (!(pmplock_recorded && (read() & MSECCFG_RLB) == 0)) {
- new_val &= ~MSECCFG_RLB;
- new_val |= (val & MSECCFG_RLB);
- }
+ if (proc->n_pmp != 0) {
+ // pmpcfg.L is 1 in any rule or entry (including disabled entries)
+ const bool pmplock_recorded = std::any_of(state->pmpaddr, state->pmpaddr + proc->n_pmp,
+ [](const pmpaddr_csr_t_p & c) { return c->is_locked(); } );
- new_val |= (val & MSECCFG_MMWP); //MMWP is sticky
- new_val |= (val & MSECCFG_MML); //MML is sticky
+ // When RLB is 0 and pmplock_recorded, RLB is locked to 0.
+ // Otherwise set the RLB bit according val
+ if (!(pmplock_recorded && (read() & MSECCFG_RLB) == 0)) {
+ new_val &= ~MSECCFG_RLB;
+ new_val |= (val & MSECCFG_RLB);
+ }
- proc->get_mmu()->flush_tlb();
+ new_val |= (val & MSECCFG_MMWP); //MMWP is sticky
+ new_val |= (val & MSECCFG_MML); //MML is sticky
+
+ proc->get_mmu()->flush_tlb();
+ }
+
+ if (proc->extension_enabled(EXT_ZKR)) {
+ uint64_t mask = MSECCFG_USEED | MSECCFG_SSEED;
+ new_val = (new_val & ~mask) | (val & mask);
+ }
if (proc->extension_enabled(EXT_ZICFILP)) {
new_val &= ~MSECCFG_MLPE;
new_val |= (val & MSECCFG_MLPE);
}
+ if (proc->extension_enabled(EXT_SMMPM)) {
+ const reg_t pmm_reserved = 1; // Reserved value of mseccfg.PMM
+ reg_t pmm = get_field(val, MSECCFG_PMM);
+ new_val = set_field(new_val, MSECCFG_PMM, pmm != pmm_reserved ? pmm : 0);
+ }
+
return basic_csr_t::unlogged_write(new_val);
}
@@ -421,6 +444,7 @@ reg_t base_status_csr_t::compute_sstatus_write_mask() const noexcept {
| (proc->any_custom_extensions() ? SSTATUS_XS : 0)
| (has_vs ? SSTATUS_VS : 0)
| (proc->extension_enabled(EXT_ZICFILP) ? SSTATUS_SPELP : 0)
+ | (proc->extension_enabled(EXT_SSDBLTRP) ? SSTATUS_SDT : 0)
;
}
@@ -464,12 +488,23 @@ vsstatus_csr_t::vsstatus_csr_t(processor_t* const proc, const reg_t addr):
}
bool vsstatus_csr_t::unlogged_write(const reg_t val) noexcept {
- const reg_t newval = (this->val & ~sstatus_write_mask) | (val & sstatus_write_mask);
+ const reg_t hDTE = (state->henvcfg->read() & HENVCFG_DTE);
+ const reg_t adj_write_mask = sstatus_write_mask & ~(hDTE ? 0 : SSTATUS_SDT);
+ reg_t newval = (this->val & ~adj_write_mask) | (val & adj_write_mask);
+
+ newval = (newval & SSTATUS_SDT) ? (newval & ~SSTATUS_SIE) : newval;
+
if (state->v) maybe_flush_tlb(newval);
this->val = adjust_sd(newval);
return true;
}
+reg_t vsstatus_csr_t::read() const noexcept {
+ const reg_t hDTE = state->henvcfg->read() & HENVCFG_DTE;
+ const reg_t adj_read_mask = sstatus_read_mask & ~(hDTE ? 0 : SSTATUS_SDT);
+ return this->val & adj_read_mask;
+}
+
// implement class sstatus_proxy_csr_t
sstatus_proxy_csr_t::sstatus_proxy_csr_t(processor_t* const proc, const reg_t addr, mstatus_csr_t_p mstatus):
base_status_csr_t(proc, addr),
@@ -477,16 +512,26 @@ sstatus_proxy_csr_t::sstatus_proxy_csr_t(processor_t* const proc, const reg_t ad
}
bool sstatus_proxy_csr_t::unlogged_write(const reg_t val) noexcept {
- const reg_t new_mstatus = (mstatus->read() & ~sstatus_write_mask) | (val & sstatus_write_mask);
+ const reg_t mDTE = (state->menvcfg->read() & MENVCFG_DTE);
+ const reg_t adj_write_mask = sstatus_write_mask & ~(mDTE ? 0 : SSTATUS_SDT);
+ reg_t new_mstatus = (mstatus->read() & ~adj_write_mask) | (val & adj_write_mask);
+
+ new_mstatus = (new_mstatus & SSTATUS_SDT) ? (new_mstatus & ~SSTATUS_SIE) : new_mstatus;
// On RV32 this will only log the low 32 bits, so make sure we're
// not modifying anything in the upper 32 bits.
- assert((sstatus_write_mask & 0xffffffffU) == sstatus_write_mask);
+ assert((adj_write_mask & 0xffffffffU) == adj_write_mask);
mstatus->write(new_mstatus);
return false; // avoid double logging: already logged by mstatus->write()
}
+reg_t sstatus_proxy_csr_t::read() const noexcept {
+ const reg_t mDTE = state->menvcfg->read() & MENVCFG_DTE;
+ const reg_t adj_read_mask = sstatus_read_mask & ~(mDTE ? 0 : SSTATUS_SDT);
+ return mstatus->read() & adj_read_mask;
+}
+
// implement class mstatus_csr_t
mstatus_csr_t::mstatus_csr_t(processor_t* const proc, const reg_t addr):
base_status_csr_t(proc, addr),
@@ -505,12 +550,16 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept {
| (has_page ? MSTATUS_TVM : 0)
| (has_gva ? MSTATUS_GVA : 0)
| (has_mpv ? MSTATUS_MPV : 0)
+ | (proc->extension_enabled(EXT_SMDBLTRP) ? MSTATUS_MDT : 0)
| (proc->extension_enabled(EXT_ZICFILP) ? (MSTATUS_SPELP | MSTATUS_MPELP) : 0)
+ | (proc->extension_enabled(EXT_SSDBLTRP) ? SSTATUS_SDT : 0)
;
const reg_t requested_mpp = proc->legalize_privilege(get_field(val, MSTATUS_MPP));
const reg_t adjusted_val = set_field(val, MSTATUS_MPP, requested_mpp);
- const reg_t new_mstatus = (read() & ~mask) | (adjusted_val & mask);
+ reg_t new_mstatus = (read() & ~mask) | (adjusted_val & mask);
+ new_mstatus = (new_mstatus & MSTATUS_MDT) ? (new_mstatus & ~MSTATUS_MIE) : new_mstatus;
+ new_mstatus = (new_mstatus & MSTATUS_SDT) ? (new_mstatus & ~MSTATUS_SIE) : new_mstatus;
maybe_flush_tlb(new_mstatus);
this->val = adjust_sd(new_mstatus);
return true;
@@ -525,6 +574,7 @@ reg_t mstatus_csr_t::compute_mstatus_initial_value() const noexcept {
| (proc->extension_enabled_const('U') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_UXL, xlen_to_uxl(proc->get_const_xlen())) : 0)
| (proc->extension_enabled_const('S') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_SXL, xlen_to_uxl(proc->get_const_xlen())) : 0)
| (proc->get_mmu()->is_target_big_endian() ? big_endian_bits : 0)
+ | (proc->extension_enabled(EXT_SMDBLTRP) ? MSTATUS_MDT : 0)
| 0; // initial value for mstatus
}
@@ -537,6 +587,7 @@ bool mnstatus_csr_t::unlogged_write(const reg_t val) noexcept {
// NMIE can be set but not cleared
const reg_t mask = (~read() & MNSTATUS_NMIE)
| (proc->extension_enabled('H') ? MNSTATUS_MNPV : 0)
+ | (proc->extension_enabled(EXT_ZICFILP) ? MNSTATUS_MNPELP : 0)
| MNSTATUS_MNPP;
const reg_t requested_mnpp = proc->legalize_privilege(get_field(val, MNSTATUS_MNPP));
@@ -590,6 +641,22 @@ reg_t rv32_high_csr_t::written_value() const noexcept {
return (orig->written_value() >> 32) & 0xffffffffU;
}
+aia_rv32_high_csr_t::aia_rv32_high_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig):
+ rv32_high_csr_t(proc, addr, orig) {
+}
+
+void aia_rv32_high_csr_t::verify_permissions(insn_t insn, bool write) const {
+ if (proc->extension_enabled(EXT_SMSTATEEN)) {
+ if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & MSTATEEN0_AIA))
+ throw trap_illegal_instruction(insn.bits());
+
+ if (state->v && !(state->hstateen[0]->read() & HSTATEEN0_AIA))
+ throw trap_virtual_instruction(insn.bits());
+ }
+
+ rv32_high_csr_t::verify_permissions(insn, write);
+}
+
// implement class sstatus_csr_t
sstatus_csr_t::sstatus_csr_t(processor_t* const proc, sstatus_proxy_csr_t_p orig, vsstatus_csr_t_p virt):
virtualized_csr_t(proc, orig, virt),
@@ -619,11 +686,6 @@ bool sstatus_csr_t::enabled(const reg_t which) {
if (!state->v || (virt_sstatus->read() & which) != 0)
return true;
}
-
- // If the field doesn't exist, it is always enabled. See #823.
- if (!orig_sstatus->field_exists(which))
- return true;
-
return false;
}
@@ -699,9 +761,9 @@ bool misa_csr_t::unlogged_write(const reg_t val) noexcept {
state->mie->write_with_mask(MIP_HS_MASK, 0); // also takes care of hie, sie
state->mip->write_with_mask(MIP_HS_MASK, 0); // also takes care of hip, sip, hvip
state->hstatus->write(0);
- for (reg_t i = 3; i < N_HPMCOUNTERS + 3; ++i) {
- const reg_t new_mevent = state->mevent[i - 3]->read() & ~(MHPMEVENT_VUINH | MHPMEVENT_VSINH);
- state->mevent[i - 3]->write(new_mevent);
+ for (reg_t i = 0; i < N_HPMCOUNTERS; ++i) {
+ const reg_t new_mevent = state->mevent[i]->read() & ~(MHPMEVENT_VUINH | MHPMEVENT_VSINH);
+ state->mevent[i]->write(new_mevent);
}
}
@@ -737,8 +799,14 @@ mip_csr_t::mip_csr_t(processor_t* const proc, const reg_t addr):
mip_or_mie_csr_t(proc, addr) {
}
+void mip_csr_t::write_with_mask(const reg_t mask, const reg_t val) noexcept {
+ if (!(state->mvien->read() & MIP_SEIP) && (mask & MIP_SEIP))
+ state->mvip->write_with_mask(MIP_SEIP, val); // mvip.SEIP is an alias of mip.SEIP when mvien.SEIP=0
+ mip_or_mie_csr_t::write_with_mask(mask & ~MIP_SEIP, val);
+}
+
reg_t mip_csr_t::read() const noexcept {
- return val | state->hvip->basic_csr_t::read();
+ return val | state->hvip->basic_csr_t::read() | ((state->mvien->read() & MIP_SEIP) ? 0 : (state->mvip->basic_csr_t::read() & MIP_SEIP));
}
void mip_csr_t::backdoor_write_with_mask(const reg_t mask, const reg_t val) noexcept {
@@ -820,6 +888,15 @@ mip_proxy_csr_t::mip_proxy_csr_t(processor_t* const proc, const reg_t addr, gene
accr(accr) {
}
+void mip_proxy_csr_t::verify_permissions(insn_t insn, bool write) const {
+ csr_t::verify_permissions(insn, write);
+ if (proc->extension_enabled_const(EXT_SSAIA) && proc->extension_enabled('H')) {
+ if ((state->csrmap[CSR_HVICTL]->read() & HVICTL_VTI) &&
+ proc->extension_enabled('S') && state->v)
+ throw trap_virtual_instruction(insn.bits()); // VS-mode attempts to access sip when hvictl.VTI=1
+ }
+}
+
reg_t mip_proxy_csr_t::read() const noexcept {
return accr->ip_read();
}
@@ -835,6 +912,15 @@ mie_proxy_csr_t::mie_proxy_csr_t(processor_t* const proc, const reg_t addr, gene
accr(accr) {
}
+void mie_proxy_csr_t::verify_permissions(insn_t insn, bool write) const {
+ csr_t::verify_permissions(insn, write);
+ if (proc->extension_enabled_const(EXT_SSAIA) && proc->extension_enabled('H')) {
+ if ((state->csrmap[CSR_HVICTL]->read() & HVICTL_VTI) &&
+ proc->extension_enabled('S') && state->v)
+ throw trap_virtual_instruction(insn.bits()); // VS-mode attempts to access sie when hvictl.VTI=1
+ }
+}
+
reg_t mie_proxy_csr_t::read() const noexcept {
return accr->ie_read();
}
@@ -907,10 +993,43 @@ bool medeleg_csr_t::unlogged_write(const reg_t val) noexcept {
| (1 << CAUSE_STORE_PAGE_FAULT)
| (proc->extension_enabled('H') ? hypervisor_exceptions : 0)
| (1 << CAUSE_SOFTWARE_CHECK_FAULT)
+ | (1 << CAUSE_HARDWARE_ERROR_FAULT)
;
return basic_csr_t::unlogged_write((read() & ~mask) | (val & mask));
}
+sip_csr_t::sip_csr_t(processor_t* const proc, const reg_t addr, generic_int_accessor_t_p accr):
+ mip_proxy_csr_t(proc, addr, accr) {
+}
+
+reg_t sip_csr_t::read() const noexcept {
+ const reg_t mask = ~state->mideleg->read() & state->mvien->read();
+ return (mip_proxy_csr_t::read() & ~mask) | (state->mvip->read() & mask);
+}
+
+bool sip_csr_t::unlogged_write(const reg_t val) noexcept {
+ const reg_t mask = ~state->mideleg->read() & state->mvien->read();
+ state->mvip->write_with_mask(mask & accr->get_ip_write_mask(), val);
+ return mip_proxy_csr_t::unlogged_write(val & ~mask);
+}
+
+sie_csr_t::sie_csr_t(processor_t* const proc, const reg_t addr, generic_int_accessor_t_p accr):
+ mie_proxy_csr_t(proc, addr, accr),
+ val(0) {
+}
+
+reg_t sie_csr_t::read() const noexcept {
+ const reg_t mask = ~state->mideleg->read() & state->mvien->read();
+ return (mie_proxy_csr_t::read() & ~mask) | (val & mask);
+}
+
+bool sie_csr_t::unlogged_write(const reg_t val) noexcept {
+ const reg_t mask = ~state->mideleg->read() & state->mvien->read();
+ this->val = (this->val & ~mask) | (val & mask);
+ mie_proxy_csr_t::unlogged_write(val & ~mask);
+ return true;
+}
+
// implement class masked_csr_t
masked_csr_t::masked_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init):
basic_csr_t(proc, addr, init),
@@ -930,7 +1049,15 @@ envcfg_csr_t::envcfg_csr_t(processor_t* const proc, const reg_t addr, const reg_
bool envcfg_csr_t::unlogged_write(const reg_t val) noexcept {
const reg_t cbie_reserved = 2; // Reserved value of xenvcfg.CBIE
- const reg_t adjusted_val = get_field(val, MENVCFG_CBIE) != cbie_reserved ? val : set_field(val, MENVCFG_CBIE, 0);
+ reg_t adjusted_val = get_field(val, MENVCFG_CBIE) != cbie_reserved ? val : set_field(val, MENVCFG_CBIE, 0);
+
+ const reg_t pmm_reserved = 1; // Reserved value of xseccfg.PMM
+ const reg_t pmm = get_field(adjusted_val, MENVCFG_PMM);
+ adjusted_val = set_field(adjusted_val, MENVCFG_PMM, pmm != pmm_reserved ? pmm : 0);
+
+ if (get_field(adjusted_val, MENVCFG_PMM) != get_field(read(), MENVCFG_PMM))
+ proc->get_mmu()->flush_tlb();
+
return masked_csr_t::unlogged_write(adjusted_val);
}
@@ -1022,6 +1149,7 @@ bool virtualized_satp_csr_t::unlogged_write(const reg_t val) noexcept {
wide_counter_csr_t::wide_counter_csr_t(processor_t* const proc, const reg_t addr, smcntrpmf_csr_t_p config_csr):
csr_t(proc, addr),
val(0),
+ written(false),
config_csr(config_csr) {
}
@@ -1030,7 +1158,15 @@ reg_t wide_counter_csr_t::read() const noexcept {
}
void wide_counter_csr_t::bump(const reg_t howmuch) noexcept {
- if (is_counting_enabled()) {
+ if (written) {
+ // Because writing a CSR serializes the simulator, howmuch should
+ // reflect exactly one instruction: the explicit CSR write.
+ // If counting is disabled, though, howmuch will be zero.
+ assert(howmuch <= 1);
+ // The ISA mandates that explicit writes to instret take precedence
+ // over the instret, so simply skip the increment.
+ written = false;
+ } else if (is_counting_enabled()) {
val += howmuch; // to keep log reasonable size, don't log every bump
}
// Clear cached value
@@ -1038,23 +1174,15 @@ void wide_counter_csr_t::bump(const reg_t howmuch) noexcept {
}
bool wide_counter_csr_t::unlogged_write(const reg_t val) noexcept {
+ // Because writing a CSR serializes the simulator and is followed by a
+ // bump, back-to-back writes with no intervening bump should never occur.
+ assert(!written);
+ written = true;
+
this->val = val;
- // The ISA mandates that if an instruction writes instret, the write
- // takes precedence over the increment to instret. However, Spike
- // unconditionally increments instret after executing an instruction.
- // Correct for this artifact by decrementing instret here.
- // Ensure that Smctrpmf hasn't disabled counting.
- if (is_counting_enabled()) {
- this->val--;
- }
return true;
}
-reg_t wide_counter_csr_t::written_value() const noexcept {
- // Re-adjust for upcoming bump()
- return this->val + 1;
-}
-
// Returns true if counting is not inhibited by Smcntrpmf.
// Note that minstretcfg / mcyclecfg / mhpmevent* share the same inhibit bits.
bool wide_counter_csr_t::is_counting_enabled() const noexcept {
@@ -1177,7 +1305,7 @@ hideleg_csr_t::hideleg_csr_t(processor_t* const proc, const reg_t addr, csr_t_p
reg_t hideleg_csr_t::read() const noexcept {
return masked_csr_t::read() & mideleg->read();
-};
+}
hgatp_csr_t::hgatp_csr_t(processor_t* const proc, const reg_t addr):
basic_csr_t(proc, addr, 0) {
@@ -1292,9 +1420,11 @@ dcsr_csr_t::dcsr_csr_t(processor_t* const proc, const reg_t addr):
ebreaku(false),
ebreakvs(false),
ebreakvu(false),
- halt(false),
v(false),
+ mprven(false),
cause(0),
+ ext_cause(0),
+ cetrig(0),
pelp(elp_t::NO_LP_EXPECTED) {
}
@@ -1306,18 +1436,22 @@ void dcsr_csr_t::verify_permissions(insn_t insn, bool write) const {
reg_t dcsr_csr_t::read() const noexcept {
reg_t result = 0;
- result = set_field(result, DCSR_XDEBUGVER, 1);
+ result = set_field(result, DCSR_XDEBUGVER, 4);
result = set_field(result, DCSR_EBREAKM, ebreakm);
result = set_field(result, DCSR_EBREAKS, ebreaks);
result = set_field(result, DCSR_EBREAKU, ebreaku);
result = set_field(result, CSR_DCSR_EBREAKVS, ebreakvs);
result = set_field(result, CSR_DCSR_EBREAKVU, ebreakvu);
- result = set_field(result, DCSR_STOPCYCLE, 0);
+ result = set_field(result, DCSR_STOPCOUNT, 0);
result = set_field(result, DCSR_STOPTIME, 0);
result = set_field(result, DCSR_CAUSE, cause);
+ result = set_field(result, DCSR_EXTCAUSE, ext_cause);
+ if (proc->extension_enabled(EXT_SMDBLTRP))
+ result = set_field(result, DCSR_CETRIG, cetrig);
result = set_field(result, DCSR_STEP, step);
result = set_field(result, DCSR_PRV, prv);
result = set_field(result, CSR_DCSR_V, v);
+ result = set_field(result, DCSR_MPRVEN, mprven);
result = set_field(result, DCSR_PELP, pelp);
return result;
}
@@ -1331,16 +1465,18 @@ bool dcsr_csr_t::unlogged_write(const reg_t val) noexcept {
ebreaku = proc->extension_enabled('U') ? get_field(val, DCSR_EBREAKU) : false;
ebreakvs = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_EBREAKVS) : false;
ebreakvu = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_EBREAKVU) : false;
- halt = get_field(val, DCSR_HALT);
v = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_V) : false;
+ mprven = get_field(val, CSR_DCSR_MPRVEN);
pelp = proc->extension_enabled(EXT_ZICFILP) ?
static_cast<elp_t>(get_field(val, DCSR_PELP)) : elp_t::NO_LP_EXPECTED;
+ cetrig = proc->extension_enabled(EXT_SMDBLTRP) ? get_field(val, DCSR_CETRIG) : false;
return true;
}
-void dcsr_csr_t::update_fields(const uint8_t cause, const reg_t prv,
+void dcsr_csr_t::update_fields(const uint8_t cause, uint8_t ext_cause, const reg_t prv,
const bool v, const elp_t pelp) noexcept {
this->cause = cause;
+ this->ext_cause = ext_cause;
this->prv = prv;
this->v = v;
this->pelp = pelp;
@@ -1353,8 +1489,9 @@ float_csr_t::float_csr_t(processor_t* const proc, const reg_t addr, const reg_t
void float_csr_t::verify_permissions(insn_t insn, bool write) const {
masked_csr_t::verify_permissions(insn, write);
- require_fs;
- if (!proc->extension_enabled('F') && !proc->extension_enabled(EXT_ZFINX))
+
+ if (!((proc->extension_enabled('F') && STATE.sstatus->enabled(SSTATUS_FS))
+ || proc->extension_enabled(EXT_ZFINX)))
throw trap_illegal_instruction(insn.bits());
if (proc->extension_enabled(EXT_SMSTATEEN) && proc->extension_enabled(EXT_ZFINX)) {
@@ -1374,7 +1511,8 @@ void float_csr_t::verify_permissions(insn_t insn, bool write) const {
}
bool float_csr_t::unlogged_write(const reg_t val) noexcept {
- dirty_fp_state;
+ if (!proc->extension_enabled(EXT_ZFINX))
+ dirty_fp_state;
return masked_csr_t::unlogged_write(val);
}
@@ -1411,6 +1549,16 @@ void seed_csr_t::verify_permissions(insn_t insn, bool write) const {
if (!proc->extension_enabled(EXT_ZKR) || !write)
throw trap_illegal_instruction(insn.bits());
csr_t::verify_permissions(insn, write);
+
+ if (state->v) {
+ if (state->mseccfg->get_sseed() && write)
+ throw trap_virtual_instruction(insn.bits());
+ else
+ throw trap_illegal_instruction(insn.bits());
+ } else if ((state->prv == PRV_U && !state->mseccfg->get_useed()) ||
+ (state->prv == PRV_S && !state->mseccfg->get_sseed())) {
+ throw trap_illegal_instruction(insn.bits());
+ }
}
reg_t seed_csr_t::read() const noexcept {
@@ -1428,7 +1576,7 @@ vector_csr_t::vector_csr_t(processor_t* const proc, const reg_t addr, const reg_
}
void vector_csr_t::verify_permissions(insn_t insn, bool write) const {
- require_vector_vs;
+ require(proc->any_vector_extensions() && STATE.sstatus->enabled(SSTATUS_VS));
basic_csr_t::verify_permissions(insn, write);
}
@@ -1449,7 +1597,7 @@ vxsat_csr_t::vxsat_csr_t(processor_t* const proc, const reg_t addr):
}
void vxsat_csr_t::verify_permissions(insn_t insn, bool write) const {
- require_vector_vs;
+ require(proc->any_vector_extensions() && STATE.sstatus->enabled(SSTATUS_VS));
masked_csr_t::verify_permissions(insn, write);
}
@@ -1538,6 +1686,18 @@ void senvcfg_csr_t::verify_permissions(insn_t insn, bool write) const {
masked_csr_t::verify_permissions(insn, write);
}
+// senvcfg.sse is read_only 0 when menvcfg.sse = 0
+reg_t senvcfg_csr_t::read() const noexcept {
+ reg_t envcfg = state->v ? state->henvcfg->read() : state->menvcfg->read();
+ return masked_csr_t::read() & ~(envcfg & MENVCFG_SSE ? 0 : MENVCFG_SSE);
+}
+
+bool senvcfg_csr_t::unlogged_write(const reg_t val) noexcept {
+ reg_t envcfg = state->v ? state->henvcfg->read() : state->menvcfg->read();
+ const reg_t mask = envcfg | ~MENVCFG_SSE;
+ return envcfg_csr_t::unlogged_write((masked_csr_t::read() & ~mask) | (val & mask));
+}
+
void henvcfg_csr_t::verify_permissions(insn_t insn, bool write) const {
if (proc->extension_enabled(EXT_SMSTATEEN)) {
if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & MSTATEEN0_HENVCFG))
@@ -1548,7 +1708,7 @@ void henvcfg_csr_t::verify_permissions(insn_t insn, bool write) const {
}
bool henvcfg_csr_t::unlogged_write(const reg_t val) noexcept {
- const reg_t mask = menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE);
+ const reg_t mask = menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE | MENVCFG_DTE | MENVCFG_SSE);
return envcfg_csr_t::unlogged_write((masked_csr_t::read() & ~mask) | (val & mask));
}
@@ -1562,10 +1722,6 @@ bool stimecmp_csr_t::unlogged_write(const reg_t val) noexcept {
return basic_csr_t::unlogged_write(val);
}
-virtualized_stimecmp_csr_t::virtualized_stimecmp_csr_t(processor_t* const proc, csr_t_p orig, csr_t_p virt):
- virtualized_csr_t(proc, orig, virt) {
-}
-
void stimecmp_csr_t::verify_permissions(insn_t insn, bool write) const {
if (!(state->menvcfg->read() & MENVCFG_STCE)) {
// access to (v)stimecmp with MENVCFG.STCE = 0
@@ -1581,9 +1737,18 @@ void stimecmp_csr_t::verify_permissions(insn_t insn, bool write) const {
}
basic_csr_t::verify_permissions(insn, write);
+
+ if (proc->extension_enabled_const(EXT_SSAIA) && proc->extension_enabled('H')) {
+ if ((state->csrmap[CSR_HVICTL]->read() & HVICTL_VTI) && state->v && write)
+ throw trap_virtual_instruction(insn.bits());
+ }
+}
+
+virtualized_with_special_permission_csr_t::virtualized_with_special_permission_csr_t(processor_t* const proc, csr_t_p orig, csr_t_p virt):
+ virtualized_csr_t(proc, orig, virt) {
}
-void virtualized_stimecmp_csr_t::verify_permissions(insn_t insn, bool write) const {
+void virtualized_with_special_permission_csr_t::verify_permissions(insn_t insn, bool write) const {
orig_csr->verify_permissions(insn, write);
}
@@ -1594,14 +1759,22 @@ scountovf_csr_t::scountovf_csr_t(processor_t* const proc, const reg_t addr):
void scountovf_csr_t::verify_permissions(insn_t insn, bool write) const {
if (!proc->extension_enabled(EXT_SSCOFPMF))
throw trap_illegal_instruction(insn.bits());
+
+ if (proc->extension_enabled('H') &&
+ (proc->extension_enabled_const(EXT_SMCDELEG) || proc->extension_enabled(EXT_SSCCFG))
+ ) {
+ if (state->v && (state->menvcfg->read() & MENVCFG_CDE)) {
+ throw trap_virtual_instruction(insn.bits());
+ }
+ }
csr_t::verify_permissions(insn, write);
}
reg_t scountovf_csr_t::read() const noexcept {
reg_t val = 0;
- for (reg_t i = 3; i < N_HPMCOUNTERS + 3; ++i) {
- bool of = state->mevent[i - 3]->read() & MHPMEVENT_OF;
- val |= of << i;
+ for (reg_t i = 0; i < N_HPMCOUNTERS; ++i) {
+ bool of = state->mevent[i]->read() & MHPMEVENT_OF;
+ val |= of << (i + FIRST_HPMCOUNTER);
}
/* In M and S modes, scountovf bit X is readable when mcounteren bit X is set, */
@@ -1663,10 +1836,74 @@ sscsrind_reg_csr_t::sscsrind_reg_csr_t(processor_t* const proc, const reg_t addr
}
void sscsrind_reg_csr_t::verify_permissions(insn_t insn, bool write) const {
+ if (proc->extension_enabled(EXT_SMSTATEEN)) {
+ if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & MSTATEEN0_CSRIND))
+ throw trap_illegal_instruction(insn.bits());
+ }
+
// Don't call base verify_permission for VS registers remapped to S-mode
if (insn.csr() == address)
csr_t::verify_permissions(insn, write);
+ if (proc->extension_enabled(EXT_SMSTATEEN)) {
+ if (state->v && !(state->hstateen[0]->read() & HSTATEEN0_CSRIND))
+ throw trap_virtual_instruction(insn.bits());
+ }
+
+ if (proc->extension_enabled(EXT_SMCDELEG)) {
+ if (insn.csr() >= CSR_VSIREG && insn.csr() <= CSR_VSIREG6) {
+ if (!state->v) {
+ // An attempt to access any vsireg* from M or S mode raises an illegal instruction exception.
+ throw trap_illegal_instruction(insn.bits());
+ } else {
+ if (state->prv == PRV_S) {
+ // An attempt from VS-mode to access any vsireg raises an illegal instruction
+ // exception if menvcfg.CDE = 0, or a virtual instruction exception if menvcfg.CDE = 1
+ if ((state->menvcfg->read() & MENVCFG_CDE) != MENVCFG_CDE) {
+ throw trap_illegal_instruction(insn.bits());
+ } else {
+ throw trap_virtual_instruction(insn.bits());
+ }
+ } else {
+ throw trap_virtual_instruction(insn.bits());
+ }
+ }
+ }
+ if (insn.csr() >= CSR_SIREG && insn.csr() <= CSR_SIREG6) {
+ // attempts to access any sireg* when menvcfg.CDE = 0;
+ if ((state->menvcfg->read() & MENVCFG_CDE) != MENVCFG_CDE) {
+ if (!state->v) {
+ throw trap_illegal_instruction(insn.bits());
+ } else {
+ if (state->prv == PRV_S) {
+ // An attempt from VS-mode to access any sireg* causes illegal instruction exception if menvcfg.CDE = 0
+ throw trap_illegal_instruction(insn.bits());
+ } else {
+ throw trap_virtual_instruction(insn.bits());
+ }
+ }
+ } else {
+ // menvcfg.CDE = 1;
+ if (state->v) {
+ // An attempt from VS-mode to access any sireg* causes a virtual instruction exception if menvcfg.CDE = 1
+ throw trap_virtual_instruction(insn.bits());
+ }
+ // counter selected by siselect is not delegated to S-mode (the corresponding bit in mcounteren = 0).
+ auto iselect_addr = iselect->read();
+ if (iselect_addr >= SISELECT_SMCDELEG_START && iselect_addr <= SISELECT_SMCDELEG_END) {
+ reg_t counter_id_offset = iselect_addr - SISELECT_SMCDELEG_START;
+ if (!(state->mcounteren->read() & (1U << counter_id_offset))) {
+ if (!state->v) {
+ throw trap_illegal_instruction(insn.bits());
+ } else {
+ throw trap_virtual_instruction(insn.bits());
+ }
+ }
+ }
+ }
+ }
+ }
+
csr_t_p proxy_csr = get_reg();
if (proxy_csr == nullptr) {
if (!state->v) {
@@ -1728,9 +1965,7 @@ srmcfg_csr_t::srmcfg_csr_t(processor_t* const proc, const reg_t addr, const reg_
masked_csr_t(proc, addr, mask, init) {
}
-void srmcfg_csr_t::verify_permissions(insn_t insn, bool write) const {
- csr_t::verify_permissions(insn, write);
-
+void srmcfg_csr_t::verify_permissions(insn_t insn, bool write UNUSED) const {
if (!proc->extension_enabled(EXT_SSQOSID))
throw trap_illegal_instruction(insn.bits());
@@ -1741,6 +1976,10 @@ void srmcfg_csr_t::verify_permissions(insn_t insn, bool write) const {
if (state->v)
throw trap_virtual_instruction(insn.bits());
+
+ if (state->prv < PRV_S) {
+ throw trap_illegal_instruction(insn.bits());
+ }
}
hvip_csr_t::hvip_csr_t(processor_t* const proc, const reg_t addr, const reg_t init):
@@ -1765,3 +2004,229 @@ void ssp_csr_t::verify_permissions(insn_t insn, bool write) const {
DECLARE_XENVCFG_VARS(SSE);
require_envcfg(SSE);
}
+
+mtval2_csr_t::mtval2_csr_t(processor_t* const proc, const reg_t addr):
+ hypervisor_csr_t(proc, addr) {
+}
+
+void mtval2_csr_t::verify_permissions(insn_t insn, bool write) const {
+ basic_csr_t::verify_permissions(insn, write);
+ if (!proc->extension_enabled('H') && !proc->extension_enabled(EXT_SSDBLTRP))
+ throw trap_illegal_instruction(insn.bits());
+}
+
+hstatus_csr_t::hstatus_csr_t(processor_t* const proc, const reg_t addr):
+ basic_csr_t(proc, addr, set_field((reg_t)0, HSTATUS_VSXL, xlen_to_uxl(proc->get_const_xlen()))) {
+}
+
+bool hstatus_csr_t::unlogged_write(const reg_t val) noexcept {
+ const reg_t mask = HSTATUS_VTSR | HSTATUS_VTW
+ | (proc->supports_impl(IMPL_MMU) ? HSTATUS_VTVM : 0)
+ | (proc->extension_enabled(EXT_SSNPM) ? HSTATUS_HUPMM : 0)
+ | HSTATUS_HU | HSTATUS_SPVP | HSTATUS_SPV | HSTATUS_GVA;
+
+ const reg_t pmm_reserved = 1; // Reserved value of mseccfg.PMM
+ reg_t pmm = get_field(val, HSTATUS_HUPMM);
+ const reg_t adjusted_val = set_field(val, HSTATUS_HUPMM, pmm != pmm_reserved ? pmm : 0);
+
+ const reg_t new_hstatus = (read() & ~mask) | (adjusted_val & mask);
+ if (get_field(new_hstatus, HSTATUS_HUPMM) != get_field(read(), HSTATUS_HUPMM))
+ proc->get_mmu()->flush_tlb();
+ return basic_csr_t::unlogged_write(new_hstatus);
+}
+
+scntinhibit_csr_t::scntinhibit_csr_t(processor_t* const proc, const reg_t addr, csr_t_p mcountinhibit):
+ basic_csr_t(proc, addr, mcountinhibit->read()) {
+}
+
+void scntinhibit_csr_t::verify_permissions(insn_t insn, bool write) const {
+ if (insn.csr() == address) {
+ csr_t::verify_permissions(insn, write);
+ }
+
+ if ((state->menvcfg->read() & MENVCFG_CDE) != MENVCFG_CDE) {
+ throw trap_illegal_instruction(insn.bits());
+ }
+}
+
+bool scntinhibit_csr_t::unlogged_write(const reg_t val) noexcept {
+ state->mcountinhibit->write(state->mcounteren->read() & val);
+ return true;
+}
+
+reg_t scntinhibit_csr_t::read() const noexcept {
+ return state->mcounteren->read() & state->mcountinhibit->read();
+}
+
+mtopi_csr_t::mtopi_csr_t(processor_t* const proc, const reg_t addr):
+ csr_t(proc, addr) {
+}
+
+reg_t mtopi_csr_t::read() const noexcept {
+ reg_t enabled_interrupts = state->mip->read() & state->mie->read() & ~state->mideleg->read();
+ if (!enabled_interrupts)
+ return 0; // no enabled pending interrupt to M-mode
+
+ reg_t selected_interrupt = proc->select_an_interrupt_with_default_priority(enabled_interrupts);
+ reg_t identity = ctz(selected_interrupt);
+ return set_field((reg_t)1, MTOPI_IID, identity); // IPRIO always 1 if iprio array is RO0
+}
+
+bool mtopi_csr_t::unlogged_write(const reg_t UNUSED val) noexcept {
+ return false;
+}
+
+mvip_csr_t::mvip_csr_t(processor_t* const proc, const reg_t addr, const reg_t init):
+ basic_csr_t(proc, addr, init) {
+}
+
+reg_t mvip_csr_t::read() const noexcept {
+ const reg_t val = basic_csr_t::read();
+ const reg_t mvien = state->mvien->read();
+ const reg_t mip = state->mip->read();
+ const reg_t menvcfg = state->menvcfg->read();
+ return 0
+ | (val & MIP_SEIP)
+ | ((menvcfg & MENVCFG_STCE) ? 0 : (mip & MIP_STIP))
+ | (((mvien & MIP_SSIP) ? val : mip) & MIP_SSIP)
+ ;
+}
+
+bool mvip_csr_t::unlogged_write(const reg_t val) noexcept {
+ if (!(state->menvcfg->read() & MENVCFG_STCE))
+ state->mip->write_with_mask(MIP_STIP, val); // mvip.STIP is an alias of mip.STIP when mip.STIP is writable
+ if (!(state->mvien->read() & MIP_SSIP))
+ state->mip->write_with_mask(MIP_SSIP, val); // mvip.SSIP is an alias of mip.SSIP when mvien.SSIP=0
+
+ const reg_t new_val = (val & MIP_SEIP) | (((state->mvien->read() & MIP_SSIP) ? val : basic_csr_t::read()) & MIP_SSIP);
+ return basic_csr_t::unlogged_write(new_val);
+}
+
+void mvip_csr_t::write_with_mask(const reg_t mask, const reg_t val) noexcept {
+ basic_csr_t::unlogged_write((basic_csr_t::read() & ~mask) | (val & mask));
+ log_write();
+}
+
+nonvirtual_stopi_csr_t::nonvirtual_stopi_csr_t(processor_t* const proc, const reg_t addr):
+ csr_t(proc, addr) {
+}
+
+void nonvirtual_stopi_csr_t::verify_permissions(insn_t insn, bool write) const {
+ if (proc->extension_enabled(EXT_SMSTATEEN)) {
+ if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & MSTATEEN0_AIA))
+ throw trap_illegal_instruction(insn.bits());
+
+ if (state->v && !(state->hstateen[0]->read() & HSTATEEN0_AIA))
+ throw trap_virtual_instruction(insn.bits());
+ }
+
+ csr_t::verify_permissions(insn, write);
+}
+
+reg_t nonvirtual_stopi_csr_t::read() const noexcept {
+ reg_t enabled_interrupts = state->nonvirtual_sip->read() & state->nonvirtual_sie->read() & ~state->hideleg->read();
+ if (!enabled_interrupts)
+ return 0; // no enabled pending interrupt to S-mode
+
+ reg_t selected_interrupt = proc->select_an_interrupt_with_default_priority(enabled_interrupts);
+ reg_t identity = ctz(selected_interrupt);
+ return set_field((reg_t)1, MTOPI_IID, identity); // IPRIO always 1 if iprio array is RO0
+}
+
+bool nonvirtual_stopi_csr_t::unlogged_write(const reg_t UNUSED val) noexcept {
+ return false;
+}
+
+inaccessible_csr_t::inaccessible_csr_t(processor_t* const proc, const reg_t addr):
+ csr_t(proc, addr) {
+}
+
+void inaccessible_csr_t::verify_permissions(insn_t insn, bool write) const {
+ if (state->v)
+ throw trap_virtual_instruction(insn.bits());
+ else
+ throw trap_illegal_instruction(insn.bits());
+}
+
+vstopi_csr_t::vstopi_csr_t(processor_t* const proc, const reg_t addr):
+ csr_t(proc, addr) {
+}
+
+void vstopi_csr_t::verify_permissions(insn_t insn, bool write) const {
+ if (proc->extension_enabled(EXT_SMSTATEEN)) {
+ if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & MSTATEEN0_AIA))
+ throw trap_illegal_instruction(insn.bits());
+
+ if (state->v && !(state->hstateen[0]->read() & HSTATEEN0_AIA))
+ throw trap_virtual_instruction(insn.bits());
+ }
+
+ csr_t::verify_permissions(insn, write);
+}
+
+reg_t vstopi_csr_t::read() const noexcept {
+ reg_t hvictl = state->hvictl->read();
+ bool vti = hvictl & HVICTL_VTI;
+ reg_t iid = get_field(hvictl, HVICTL_IID);
+ bool dpr = hvictl & HVICTL_DPR;
+ bool ipriom = hvictl & HVICTL_IPRIOM;
+ reg_t iprio = get_field(hvictl, HVICTL_IPRIO);
+
+ reg_t enabled_interrupts = state->mip->read() & state->mie->read() & state->hideleg->read();
+ enabled_interrupts >>= 1; // VSSIP -> SSIP, etc
+ reg_t vgein = get_field(state->hstatus->read(), HSTATUS_VGEIN);
+ reg_t virtual_sei_priority = (vgein == 0 && iid == IRQ_S_EXT && iprio != 0) ? iprio : 255; // vstopi.IPRIO is 255 for priority number 256
+
+ reg_t identity, priority;
+ if (vti) {
+ if (!(enabled_interrupts & MIP_SEIP) && iid == IRQ_S_EXT)
+ return 0;
+
+ identity = ((enabled_interrupts & MIP_SEIP) && (iid == IRQ_S_EXT || dpr)) ? IRQ_S_EXT : iid;
+ priority = (identity == IRQ_S_EXT) ? virtual_sei_priority : ((iprio != 0 || !dpr) ? iprio : 255);
+ } else {
+ if (!enabled_interrupts)
+ return 0; // no enabled pending interrupt to VS-mode
+
+ reg_t selected_interrupt = proc->select_an_interrupt_with_default_priority(enabled_interrupts);
+ identity = ctz(selected_interrupt);
+ priority = (identity == IRQ_S_EXT) ? virtual_sei_priority : 255; // vstopi.IPRIO is 255 for interrupt with default priority lower than VSEI
+ }
+ return set_field((reg_t)(ipriom ? priority : 1), MTOPI_IID, identity);
+}
+
+bool vstopi_csr_t::unlogged_write(const reg_t UNUSED val) noexcept {
+ return false;
+}
+
+siselect_csr_t::siselect_csr_t(processor_t* const proc, const reg_t addr, const reg_t init):
+ basic_csr_t(proc, addr, init) {
+}
+
+void siselect_csr_t::verify_permissions(insn_t insn, bool write) const {
+ if (proc->extension_enabled(EXT_SMSTATEEN)) {
+ if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & MSTATEEN0_CSRIND))
+ throw trap_illegal_instruction(insn.bits());
+
+ if (state->v && !(state->hstateen[0]->read() & HSTATEEN0_CSRIND))
+ throw trap_virtual_instruction(insn.bits());
+ }
+
+ basic_csr_t::verify_permissions(insn, write);
+}
+
+aia_csr_t::aia_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init):
+ masked_csr_t(proc, addr, mask, init) {
+}
+
+void aia_csr_t::verify_permissions(insn_t insn, bool write) const {
+ if (proc->extension_enabled(EXT_SMSTATEEN)) {
+ if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & MSTATEEN0_AIA))
+ throw trap_illegal_instruction(insn.bits());
+
+ if (state->v && !(state->hstateen[0]->read() & HSTATEEN0_AIA))
+ throw trap_virtual_instruction(insn.bits());
+ }
+
+ basic_csr_t::verify_permissions(insn, write);
+}
diff --git a/riscv/csrs.h b/riscv/csrs.h
index 658ffdb..f076aaa 100644
--- a/riscv/csrs.h
+++ b/riscv/csrs.h
@@ -150,6 +150,8 @@ class mseccfg_csr_t: public basic_csr_t {
bool get_mml() const noexcept;
bool get_mmwp() const noexcept;
bool get_rlb() const noexcept;
+ bool get_useed() const noexcept;
+ bool get_sseed() const noexcept;
protected:
virtual bool unlogged_write(const reg_t val) noexcept override;
};
@@ -234,13 +236,12 @@ typedef std::shared_ptr<base_status_csr_t> base_status_csr_t_p;
// For vsstatus, which is its own separate architectural register
// (unlike sstatus)
+// vstatus.sdt is read_only 0 when henvcfg.dte = 0
class vsstatus_csr_t final: public base_status_csr_t {
public:
vsstatus_csr_t(processor_t* const proc, const reg_t addr);
- reg_t read() const noexcept override {
- return val;
- }
+ virtual reg_t read() const noexcept override;
protected:
virtual bool unlogged_write(const reg_t val) noexcept override;
@@ -300,13 +301,18 @@ class rv32_high_csr_t: public csr_t {
csr_t_p orig;
};
+class aia_rv32_high_csr_t: public rv32_high_csr_t {
+ public:
+ aia_rv32_high_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig);
+ virtual void verify_permissions(insn_t insn, bool write) const override;
+};
+
+// sstatus.sdt is read_only 0 when menvcfg.dte = 0
class sstatus_proxy_csr_t final: public base_status_csr_t {
public:
sstatus_proxy_csr_t(processor_t* const proc, const reg_t addr, mstatus_csr_t_p mstatus);
- reg_t read() const noexcept override {
- return mstatus->read() & sstatus_read_mask;
- }
+ virtual reg_t read() const noexcept override;
protected:
virtual bool unlogged_write(const reg_t val) noexcept override;
@@ -356,7 +362,7 @@ class mip_or_mie_csr_t: public csr_t {
mip_or_mie_csr_t(processor_t* const proc, const reg_t addr);
virtual reg_t read() const noexcept override;
- void write_with_mask(const reg_t mask, const reg_t val) noexcept;
+ virtual void write_with_mask(const reg_t mask, const reg_t val) noexcept;
protected:
virtual bool unlogged_write(const reg_t val) noexcept override final;
@@ -371,6 +377,8 @@ class mip_csr_t: public mip_or_mie_csr_t {
mip_csr_t(processor_t* const proc, const reg_t addr);
virtual reg_t read() const noexcept override final;
+ void write_with_mask(const reg_t mask, const reg_t val) noexcept override;
+
// Does not log. Used by external things (clint) that wiggle bits in mip.
void backdoor_write_with_mask(const reg_t mask, const reg_t val) noexcept;
private:
@@ -406,6 +414,7 @@ class generic_int_accessor_t {
void ip_write(const reg_t val) noexcept;
reg_t ie_read() const noexcept;
void ie_write(const reg_t val) noexcept;
+ reg_t get_ip_write_mask() { return ip_write_mask; }
private:
state_t* const state;
const reg_t read_mask;
@@ -423,10 +432,10 @@ typedef std::shared_ptr<generic_int_accessor_t> generic_int_accessor_t_p;
class mip_proxy_csr_t: public csr_t {
public:
mip_proxy_csr_t(processor_t* const proc, const reg_t addr, generic_int_accessor_t_p accr);
+ virtual void verify_permissions(insn_t insn, bool write) const override;
virtual reg_t read() const noexcept override;
protected:
virtual bool unlogged_write(const reg_t val) noexcept override;
- private:
generic_int_accessor_t_p accr;
};
@@ -434,6 +443,7 @@ class mip_proxy_csr_t: public csr_t {
class mie_proxy_csr_t: public csr_t {
public:
mie_proxy_csr_t(processor_t* const proc, const reg_t addr, generic_int_accessor_t_p accr);
+ virtual void verify_permissions(insn_t insn, bool write) const override;
virtual reg_t read() const noexcept override;
protected:
virtual bool unlogged_write(const reg_t val) noexcept override;
@@ -460,6 +470,24 @@ class medeleg_csr_t: public basic_csr_t {
const reg_t hypervisor_exceptions;
};
+class sip_csr_t: public mip_proxy_csr_t {
+ public:
+ sip_csr_t(processor_t* const proc, const reg_t addr, generic_int_accessor_t_p accr);
+ virtual reg_t read() const noexcept override;
+ protected:
+ virtual bool unlogged_write(const reg_t val) noexcept override;
+};
+
+class sie_csr_t: public mie_proxy_csr_t {
+ public:
+ sie_csr_t(processor_t* const proc, const reg_t addr, generic_int_accessor_t_p accr);
+ virtual reg_t read() const noexcept override;
+ protected:
+ virtual bool unlogged_write(const reg_t val) noexcept override;
+ private:
+ reg_t val;
+};
+
// For CSRs with certain bits hardwired
class masked_csr_t: public basic_csr_t {
public:
@@ -480,14 +508,14 @@ class envcfg_csr_t: public masked_csr_t {
// henvcfg.pbmte is read_only 0 when menvcfg.pbmte = 0
// henvcfg.stce is read_only 0 when menvcfg.stce = 0
// henvcfg.hade is read_only 0 when menvcfg.hade = 0
+// henvcfg.dte is read_only 0 when menvcfg.dte = 0
+// henvcfg.sse is read_only 0 when menvcfg.sse = 0
class henvcfg_csr_t final: public envcfg_csr_t {
public:
henvcfg_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init, csr_t_p menvcfg);
-
reg_t read() const noexcept override {
- return (menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE)) & masked_csr_t::read();
+ return (menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE | MENVCFG_DTE | MENVCFG_SSE)) & masked_csr_t::read();
}
-
virtual void verify_permissions(insn_t insn, bool write) const override;
protected:
@@ -542,10 +570,10 @@ class wide_counter_csr_t: public csr_t {
void bump(const reg_t howmuch) noexcept;
protected:
virtual bool unlogged_write(const reg_t val) noexcept override;
- virtual reg_t written_value() const noexcept override;
private:
bool is_counting_enabled() const noexcept;
reg_t val;
+ bool written;
smcntrpmf_csr_t_p config_csr;
};
@@ -684,7 +712,7 @@ class dcsr_csr_t: public csr_t {
dcsr_csr_t(processor_t* const proc, const reg_t addr);
virtual void verify_permissions(insn_t insn, bool write) const override;
virtual reg_t read() const noexcept override;
- void update_fields(const uint8_t cause, const reg_t prv,
+ void update_fields(const uint8_t cause, const uint8_t ext_cause, const reg_t prv,
const bool v, const elp_t pelp) noexcept;
protected:
virtual bool unlogged_write(const reg_t val) noexcept override;
@@ -696,9 +724,11 @@ class dcsr_csr_t: public csr_t {
bool ebreaku;
bool ebreakvs;
bool ebreakvu;
- bool halt;
bool v;
+ bool mprven;
uint8_t cause;
+ uint8_t ext_cause;
+ bool cetrig;
elp_t pelp;
};
@@ -787,7 +817,11 @@ class sstateen_csr_t: public hstateen_csr_t {
class senvcfg_csr_t final: public envcfg_csr_t {
public:
senvcfg_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init);
+ reg_t read() const noexcept override;
virtual void verify_permissions(insn_t insn, bool write) const override;
+
+ protected:
+ virtual bool unlogged_write(const reg_t val) noexcept override;
};
class stimecmp_csr_t: public basic_csr_t {
@@ -800,9 +834,9 @@ class stimecmp_csr_t: public basic_csr_t {
reg_t intr_mask;
};
-class virtualized_stimecmp_csr_t: public virtualized_csr_t {
+class virtualized_with_special_permission_csr_t: public virtualized_csr_t {
public:
- virtualized_stimecmp_csr_t(processor_t* const proc, csr_t_p orig, csr_t_p virt);
+ virtualized_with_special_permission_csr_t(processor_t* const proc, csr_t_p orig, csr_t_p virt);
virtual void verify_permissions(insn_t insn, bool write) const override;
};
@@ -880,4 +914,87 @@ class ssp_csr_t final : public masked_csr_t {
ssp_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init);
virtual void verify_permissions(insn_t insn, bool write) const override;
};
+
+// mtval2 CSR provided by H extension - but required if Ssdbltrp is implemented
+class mtval2_csr_t: public hypervisor_csr_t {
+ public:
+ mtval2_csr_t(processor_t* const proc, const reg_t addr);
+ virtual void verify_permissions(insn_t insn, bool write) const override;
+};
+
+class hstatus_csr_t final: public basic_csr_t {
+ public:
+ hstatus_csr_t(processor_t* const proc, const reg_t addr);
+ protected:
+ virtual bool unlogged_write(const reg_t val) noexcept override;
+};
+
+class scntinhibit_csr_t: public basic_csr_t {
+ public:
+ scntinhibit_csr_t(processor_t* const proc, const reg_t addr, csr_t_p mcountinhibit);
+ reg_t read() const noexcept override;
+ virtual void verify_permissions(insn_t insn, bool write) const override;
+ protected:
+ virtual bool unlogged_write(const reg_t val) noexcept override;
+};
+
+class mtopi_csr_t: public csr_t {
+ public:
+ mtopi_csr_t(processor_t* const proc, const reg_t addr);
+ virtual reg_t read() const noexcept override;
+ protected:
+ bool unlogged_write(const reg_t val) noexcept override;
+};
+
+class mvip_csr_t : public basic_csr_t {
+ public:
+ mvip_csr_t(processor_t* const proc, const reg_t addr, const reg_t init);
+ reg_t read() const noexcept override;
+
+ void write_with_mask(const reg_t mask, const reg_t val) noexcept;
+
+ protected:
+ virtual bool unlogged_write(const reg_t val) noexcept override;
+};
+
+typedef std::shared_ptr<mvip_csr_t> mvip_csr_t_p;
+
+class nonvirtual_stopi_csr_t: public csr_t {
+ public:
+ nonvirtual_stopi_csr_t(processor_t* const proc, const reg_t addr);
+ virtual void verify_permissions(insn_t insn, bool write) const override;
+ virtual reg_t read() const noexcept override;
+ protected:
+ bool unlogged_write(const reg_t val) noexcept override;
+};
+
+class inaccessible_csr_t: public csr_t {
+ public:
+ inaccessible_csr_t(processor_t* const proc, const reg_t addr);
+ virtual void verify_permissions(insn_t insn, bool write) const override;
+ reg_t read() const noexcept override { return 0; }
+ protected:
+ bool unlogged_write(const reg_t UNUSED val) noexcept override { return false; }
+};
+
+class vstopi_csr_t: public csr_t {
+ public:
+ vstopi_csr_t(processor_t* const proc, const reg_t addr);
+ virtual void verify_permissions(insn_t insn, bool write) const override;
+ virtual reg_t read() const noexcept override;
+ protected:
+ bool unlogged_write(const reg_t val) noexcept override;
+};
+
+class siselect_csr_t: public basic_csr_t {
+ public:
+ siselect_csr_t(processor_t* const proc, const reg_t addr, const reg_t init);
+ virtual void verify_permissions(insn_t insn, bool write) const override;
+};
+
+class aia_csr_t: public masked_csr_t {
+ public:
+ aia_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init);
+ virtual void verify_permissions(insn_t insn, bool write) const override;
+};
#endif
diff --git a/riscv/debug_module.cc b/riscv/debug_module.cc
index 5d49605..a89a4ff 100644
--- a/riscv/debug_module.cc
+++ b/riscv/debug_module.cc
@@ -13,7 +13,7 @@
#if 0
# define D(x) x
#else
-# define D(x)
+# define D(x) (void) 0
#endif
// Return the number of bits wide that a field has to be to encode up to n
@@ -249,6 +249,11 @@ bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
return false;
}
+reg_t debug_module_t::size()
+{
+ return PGSIZE;
+}
+
void debug_module_t::write32(uint8_t *memory, unsigned int index, uint32_t value)
{
uint8_t* base = memory + index * 4;
@@ -445,7 +450,6 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
} else {
dmstatus.allresumeack = false;
}
- auto hart = sim->get_harts().at(hart_id);
if (!hart_available(hart_id)) {
dmstatus.allrunning = false;
dmstatus.allhalted = false;
@@ -462,9 +466,9 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
}
}
- // We don't allow selecting non-existant harts through
+ // We don't allow selecting non-existent harts through
// hart_array_mask, so the only way it's possible is by writing a
- // non-existant hartsel.
+ // non-existent hartsel.
dmstatus.anynonexistant = dmcontrol.hartsel >= sim->get_cfg().nprocs();
result = set_field(result, DM_DMSTATUS_IMPEBREAK,
diff --git a/riscv/debug_module.h b/riscv/debug_module.h
index 3771489..904f03e 100644
--- a/riscv/debug_module.h
+++ b/riscv/debug_module.h
@@ -114,8 +114,9 @@ class debug_module_t : public abstract_device_t
debug_module_t(simif_t *sim, const debug_module_config_t &config);
~debug_module_t();
- bool load(reg_t addr, size_t len, uint8_t* bytes);
- bool store(reg_t addr, size_t len, const uint8_t* bytes);
+ bool load(reg_t addr, size_t len, uint8_t* bytes) override;
+ bool store(reg_t addr, size_t len, const uint8_t* bytes) override;
+ reg_t size() override;
// Debug Module Interface that the debugger (in our case through JTAG DTM)
// uses to access the DM.
diff --git a/riscv/decode.h b/riscv/decode.h
index f36c04e..51ecbeb 100644
--- a/riscv/decode.h
+++ b/riscv/decode.h
@@ -79,6 +79,10 @@ public:
insn_t(insn_bits_t bits) : b(bits) {}
insn_bits_t bits() { return b; }
int length() { return insn_length(b); }
+ [[maybe_unused]] int64_t opcode() { return x(0, 7); }
+ [[maybe_unused]] int64_t funct7() { return x(25, 7); }
+ [[maybe_unused]] int64_t funct3() { return x(12, 3); }
+ [[maybe_unused]] int64_t funct2() { return x(25, 2); }
int64_t i_imm() { return xs(20, 12); }
int64_t shamt() { return x(20, 6); }
int64_t s_imm() { return x(7, 5) + (xs(25, 7) << 5); }
@@ -95,6 +99,7 @@ public:
uint64_t bs() { return x(30, 2); } // Crypto ISE - SM4/AES32 byte select.
uint64_t rcon() { return x(20, 4); } // Crypto ISE - AES64 round const.
+ [[maybe_unused]] int64_t rvc_opcode() { return x(0, 2); }
int64_t rvc_imm() { return x(2, 5) + (xs(12, 1) << 5); }
int64_t rvc_zimm() { return x(2, 5) + (x(12, 1) << 5); }
int64_t rvc_addi4spn_imm() { return (x(6, 1) << 2) + (x(5, 1) << 3) + (x(11, 2) << 4) + (x(7, 4) << 6); }
@@ -170,23 +175,29 @@ public:
switch (rvc_rlist()) {
case 15:
stack_adj_base += 16;
+ [[fallthrough]];
case 14:
if (xlen == 64)
stack_adj_base += 16;
+ [[fallthrough]];
case 13:
case 12:
stack_adj_base += 16;
+ [[fallthrough]];
case 11:
case 10:
if (xlen == 64)
stack_adj_base += 16;
+ [[fallthrough]];
case 9:
case 8:
stack_adj_base += 16;
+ [[fallthrough]];
case 7:
case 6:
if (xlen == 64)
stack_adj_base += 16;
+ [[fallthrough]];
case 5:
case 4:
stack_adj_base += 16;
diff --git a/riscv/decode_macros.h b/riscv/decode_macros.h
index 675634a..892515f 100644
--- a/riscv/decode_macros.h
+++ b/riscv/decode_macros.h
@@ -22,6 +22,7 @@
#define RS2 READ_REG(insn.rs2())
#define RS3 READ_REG(insn.rs3())
#define WRITE_RD(value) WRITE_REG(insn.rd(), value)
+#define CHECK_RD() CHECK_REG(insn.rd())
/* 0 : int
* 1 : floating
@@ -30,9 +31,9 @@
* 4 : csr
*/
#define WRITE_REG(reg, value) ({ \
+ CHECK_REG(reg); \
reg_t wdata = (value); /* value may have side effects */ \
if (DECODE_MACRO_USAGE_LOGGED) STATE.log_reg_write[(reg) << 4] = {wdata, 0}; \
- CHECK_REG(reg); \
STATE.XPR.write(reg, wdata); \
})
#define WRITE_FREG(reg, value) ({ \
@@ -83,7 +84,7 @@
// Zilsd macros
#define WRITE_RD_D(value) (xlen == 32 ? WRITE_RD_PAIR(value) : WRITE_RD(value))
-// Zcmlsd macros
+// Zclsd macros
#define WRITE_RVC_RS2S_PAIR(value) WRITE_REG_PAIR(insn.rvc_rs2s(), value)
#define RVC_RS2S_PAIR READ_REG_PAIR(insn.rvc_rs2s())
#define RVC_RS2_PAIR READ_REG_PAIR(insn.rvc_rs2())
@@ -164,10 +165,9 @@ static inline bool is_aligned(const unsigned val, const unsigned pos)
#define require_extension(s) require(p->extension_enabled(s))
#define require_either_extension(A,B) require(p->extension_enabled(A) || p->extension_enabled(B));
#define require_impl(s) require(p->supports_impl(s))
-#define require_fs require(STATE.sstatus->enabled(SSTATUS_FS))
#define require_fp STATE.fflags->verify_permissions(insn, false)
#define require_accelerator require(STATE.sstatus->enabled(SSTATUS_XS))
-#define require_vector_vs require(STATE.sstatus->enabled(SSTATUS_VS))
+#define require_vector_vs require(p->any_vector_extensions() && STATE.sstatus->enabled(SSTATUS_VS))
#define require_vector(alu) \
do { \
require_vector_vs; \
@@ -211,15 +211,18 @@ static inline bool is_aligned(const unsigned val, const unsigned pos)
} \
} while (0);
-#define set_fp_exceptions ({ if (softfloat_exceptionFlags) { \
- STATE.fflags->write(STATE.fflags->read() | softfloat_exceptionFlags); \
- } \
- softfloat_exceptionFlags = 0; })
+#define raise_fp_exceptions(flags) do { if (flags) STATE.fflags->write(STATE.fflags->read() | (flags)); } while (0);
+#define set_fp_exceptions \
+ do { \
+ raise_fp_exceptions(softfloat_exceptionFlags); \
+ softfloat_exceptionFlags = 0; \
+ } while (0);
#define sext32(x) ((sreg_t)(int32_t)(x))
#define zext32(x) ((reg_t)(uint32_t)(x))
-#define sext_xlen(x) (((sreg_t)(x) << (64 - xlen)) >> (64 - xlen))
+#define sext(x, pos) (((sreg_t)(x) << (64 - (pos))) >> (64 - (pos)))
#define zext(x, pos) (((reg_t)(x) << (64 - (pos))) >> (64 - (pos)))
+#define sext_xlen(x) sext(x, xlen)
#define zext_xlen(x) zext(x, xlen)
#define set_pc(x) \
@@ -334,10 +337,10 @@ inline long double to_f(float128_t f) { long double r; memcpy(&r, &f, sizeof(r))
#define DEBUG_RVV_FMA_VF \
printf("vfma(%lu) vd=%f vs1=%f vs2=%f vd_old=%f\n", i, to_f(vd), to_f(rs1), to_f(vs2), to_f(vd_old));
#else
-#define DEBUG_RVV_FP_VV 0
-#define DEBUG_RVV_FP_VF 0
-#define DEBUG_RVV_FMA_VV 0
-#define DEBUG_RVV_FMA_VF 0
+#define DEBUG_RVV_FP_VV (void) 0
+#define DEBUG_RVV_FP_VF (void) 0
+#define DEBUG_RVV_FMA_VV (void) 0
+#define DEBUG_RVV_FMA_VF (void) 0
#endif
#define DECLARE_XENVCFG_VARS(field) \
diff --git a/riscv/devices.cc b/riscv/devices.cc
index 2c06f78..b816ca1 100644
--- a/riscv/devices.cc
+++ b/riscv/devices.cc
@@ -8,53 +8,92 @@ mmio_device_map_t& mmio_device_map()
return device_map;
}
+static auto empty_device = rom_device_t(std::vector<char>());
+
+bus_t::bus_t()
+ : bus_t(&empty_device)
+{
+}
+
+bus_t::bus_t(abstract_device_t* fallback)
+ : fallback(fallback)
+{
+}
+
void bus_t::add_device(reg_t addr, abstract_device_t* dev)
{
- // Searching devices via lower_bound/upper_bound
- // implicitly relies on the underlying std::map
- // container to sort the keys and provide ordered
- // iteration over this sort, which it does. (python's
- // SortedDict is a good analogy)
+ // Allow empty devices by omitting them
+ auto size = dev->size();
+ if (size == 0)
+ return;
+
+ // Reject devices that overflow address size
+ if (addr + size - 1 < addr) {
+ fprintf(stderr, "device at [%" PRIx64 ", %" PRIx64 ") overflows address size\n",
+ addr, addr + size);
+ abort();
+ }
+
+ // Reject devices that overlap other devices
+ if (auto it = devices.upper_bound(addr);
+ (it != devices.end() && addr + size - 1 >= it->first) ||
+ (it != devices.begin() && (it--, it->first + it->second->size() - 1 >= addr))) {
+ fprintf(stderr, "devices at [%" PRIx64 ", %" PRIx64 ") and [%" PRIx64 ", %" PRIx64 ") overlap\n",
+ it->first, it->first + it->second->size(), addr, addr + size);
+ abort();
+ }
+
devices[addr] = dev;
}
bool bus_t::load(reg_t addr, size_t len, uint8_t* bytes)
{
- // Find the device with the base address closest to but
- // less than addr (price-is-right search)
- auto it = devices.upper_bound(addr);
- if (devices.empty() || it == devices.begin()) {
- // Either the bus is empty, or there weren't
- // any items with a base address <= addr
- return false;
- }
- // Found at least one item with base address <= addr
- // The iterator points to the device after this, so
- // go back by one item.
- it--;
- return it->second->load(addr - it->first, len, bytes);
+ if (auto [base, dev] = find_device(addr, len); dev)
+ return dev->load(addr - base, len, bytes);
+ return false;
}
bool bus_t::store(reg_t addr, size_t len, const uint8_t* bytes)
{
- // See comments in bus_t::load
- auto it = devices.upper_bound(addr);
- if (devices.empty() || it == devices.begin()) {
- return false;
- }
- it--;
- return it->second->store(addr - it->first, len, bytes);
+ if (auto [base, dev] = find_device(addr, len); dev)
+ return dev->store(addr - base, len, bytes);
+ return false;
}
-std::pair<reg_t, abstract_device_t*> bus_t::find_device(reg_t addr)
+reg_t bus_t::size()
{
- // See comments in bus_t::load
- auto it = devices.upper_bound(addr);
- if (devices.empty() || it == devices.begin()) {
- return std::make_pair((reg_t)0, (abstract_device_t*)NULL);
+ if (auto last = devices.rbegin(); last != devices.rend())
+ return last->first + last->second->size();
+ return 0;
+}
+
+std::pair<reg_t, abstract_device_t*> bus_t::find_device(reg_t addr, size_t len)
+{
+ if (unlikely(!len || addr + len - 1 < addr))
+ return std::make_pair(0, nullptr);
+
+ // Obtain iterator to device immediately after the one that might match
+ auto it_after = devices.upper_bound(addr);
+ reg_t base, size;
+ if (likely(it_after != devices.begin())) {
+ // Obtain iterator to device that might match
+ auto it = std::prev(it_after);
+ base = it->first;
+ size = it->second->size();
+ if (likely(addr - base + len - 1 < size)) {
+ // it fully contains [addr, addr + len)
+ return std::make_pair(it->first, it->second);
+ }
}
- it--;
- return std::make_pair(it->first, it->second);
+
+ if (unlikely((it_after != devices.end() && addr + len - 1 >= it_after->first)
+ || (it_after != devices.begin() && addr - base < size))) {
+ // it_after or it contains part of, but not all of, [addr, add + len)
+ return std::make_pair(0, nullptr);
+ }
+
+ // No matching device
+ return std::make_pair(0, fallback);
}
mem_t::mem_t(reg_t size)
@@ -116,3 +155,25 @@ void mem_t::dump(std::ostream& o) {
}
}
}
+
+external_sim_device_t::external_sim_device_t(abstract_sim_if_t* sim)
+ : external_simulator(sim) {}
+
+void external_sim_device_t::set_simulator(abstract_sim_if_t* sim) {
+ external_simulator = sim;
+}
+
+bool external_sim_device_t::load(reg_t addr, size_t len, uint8_t* bytes) {
+ if (unlikely(external_simulator == nullptr)) return false;
+ return external_simulator->load(addr, len, bytes);
+}
+
+bool external_sim_device_t::store(reg_t addr, size_t len, const uint8_t* bytes) {
+ if (unlikely(external_simulator == nullptr)) return false;
+ return external_simulator->store(addr, len, bytes);
+}
+
+reg_t external_sim_device_t::size() {
+ if (unlikely(external_simulator == nullptr)) return 0;
+ return PGSIZE; // TODO: proper size
+}
diff --git a/riscv/devices.h b/riscv/devices.h
index 6ef32e9..ccb5c9b 100644
--- a/riscv/devices.h
+++ b/riscv/devices.h
@@ -16,14 +16,21 @@ class simif_t;
class bus_t : public abstract_device_t {
public:
+ bus_t();
+
+ // the fallback device owns all addresses not owned by other devices
+ bus_t(abstract_device_t* fallback);
+
bool load(reg_t addr, size_t len, uint8_t* bytes) override;
bool store(reg_t addr, size_t len, const uint8_t* bytes) override;
+ reg_t size() override;
void add_device(reg_t addr, abstract_device_t* dev);
- std::pair<reg_t, abstract_device_t*> find_device(reg_t addr);
+ std::pair<reg_t, abstract_device_t*> find_device(reg_t addr, size_t len);
private:
std::map<reg_t, abstract_device_t*> devices;
+ abstract_device_t* fallback;
};
class rom_device_t : public abstract_device_t {
@@ -31,6 +38,7 @@ class rom_device_t : public abstract_device_t {
rom_device_t(std::vector<char> data);
bool load(reg_t addr, size_t len, uint8_t* bytes) override;
bool store(reg_t addr, size_t len, const uint8_t* bytes) override;
+ reg_t size() override { return data.size(); }
const std::vector<char>& contents() { return data; }
private:
std::vector<char> data;
@@ -41,7 +49,6 @@ class abstract_mem_t : public abstract_device_t {
virtual ~abstract_mem_t() = default;
virtual char* contents(reg_t addr) = 0;
- virtual reg_t size() = 0;
virtual void dump(std::ostream& o) = 0;
};
@@ -64,12 +71,31 @@ class mem_t : public abstract_mem_t {
reg_t sz;
};
+class abstract_sim_if_t {
+public:
+ virtual ~abstract_sim_if_t() = default;
+ virtual bool load(reg_t addr, size_t len, uint8_t* bytes) = 0;
+ virtual bool store(reg_t addr, size_t len, const uint8_t* bytes) = 0;
+};
+
+class external_sim_device_t : public abstract_device_t {
+public:
+ external_sim_device_t(abstract_sim_if_t* sim);
+ void set_simulator(abstract_sim_if_t* sim);
+ bool load(reg_t addr, size_t len, uint8_t* bytes) override;
+ bool store(reg_t addr, size_t len, const uint8_t* bytes) override;
+ reg_t size() override;
+
+private:
+ abstract_sim_if_t* external_simulator;
+};
+
class clint_t : public abstract_device_t {
public:
clint_t(const simif_t*, uint64_t freq_hz, bool real_time);
bool load(reg_t addr, size_t len, uint8_t* bytes) override;
bool store(reg_t addr, size_t len, const uint8_t* bytes) override;
- size_t size() { return CLINT_SIZE; }
+ reg_t size() override { return CLINT_SIZE; }
void tick(reg_t rtc_ticks) override;
uint64_t get_mtimecmp(reg_t hartid) { return mtimecmp[hartid]; }
uint64_t get_mtime() { return mtime; }
@@ -109,7 +135,7 @@ class plic_t : public abstract_device_t, public abstract_interrupt_controller_t
bool load(reg_t addr, size_t len, uint8_t* bytes) override;
bool store(reg_t addr, size_t len, const uint8_t* bytes) override;
void set_interrupt_level(uint32_t id, int lvl) override;
- size_t size() { return PLIC_SIZE; }
+ reg_t size() override { return PLIC_SIZE; }
private:
std::vector<plic_context_t> contexts;
uint32_t num_ids;
@@ -140,7 +166,7 @@ class ns16550_t : public abstract_device_t {
bool load(reg_t addr, size_t len, uint8_t* bytes) override;
bool store(reg_t addr, size_t len, const uint8_t* bytes) override;
void tick(reg_t rtc_ticks) override;
- size_t size() { return NS16550_SIZE; }
+ reg_t size() override { return NS16550_SIZE; }
private:
abstract_interrupt_controller_t *intctrl;
uint32_t interrupt_id;
diff --git a/riscv/disasm.h b/riscv/disasm.h
index d4b8c2c..4a1ea42 100644
--- a/riscv/disasm.h
+++ b/riscv/disasm.h
@@ -82,7 +82,7 @@ class disasm_insn_t
class disassembler_t
{
public:
- disassembler_t(const isa_parser_t *isa);
+ disassembler_t(const isa_parser_t *isa, bool strict = false);
~disassembler_t();
std::string disassemble(insn_t insn) const;
@@ -94,7 +94,7 @@ class disassembler_t
static const int HASH_SIZE = 255;
std::vector<const disasm_insn_t*> chain[HASH_SIZE+1];
- void add_instructions(const isa_parser_t* isa);
+ void add_instructions(const isa_parser_t* isa, bool strict);
const disasm_insn_t* probe_once(insn_t insn, size_t idx) const;
diff --git a/riscv/dts.cc b/riscv/dts.cc
index 8304171..5be9d57 100644
--- a/riscv/dts.cc
+++ b/riscv/dts.cc
@@ -13,14 +13,17 @@
#include <sys/types.h>
std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
- reg_t initrd_start, reg_t initrd_end,
- const char* bootargs,
- size_t pmpregions,
- size_t pmpgranularity,
- std::vector<processor_t*> procs,
+ const cfg_t* cfg,
std::vector<std::pair<reg_t, abstract_mem_t*>> mems,
std::string device_nodes)
{
+ reg_t initrd_start = cfg->initrd_bounds.first;
+ reg_t initrd_end = cfg->initrd_bounds.second;
+ const char* bootargs = cfg->bootargs;
+ reg_t pmpregions = cfg->pmpregions;
+ reg_t pmpgranularity = cfg->pmpgranularity;
+ isa_parser_t isa(cfg->isa, cfg->priv);
+
std::stringstream s;
s << std::dec <<
"/dts-v1/;\n"
@@ -54,14 +57,14 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
" #address-cells = <1>;\n"
" #size-cells = <0>;\n"
" timebase-frequency = <" << (cpu_hz/insns_per_rtc_tick) << ">;\n";
- for (size_t i = 0; i < procs.size(); i++) {
+ for (size_t i = 0; i < cfg->nprocs(); i++) {
s << " CPU" << i << ": cpu@" << i << " {\n"
" device_type = \"cpu\";\n"
- " reg = <" << i << ">;\n"
+ " reg = <" << cfg->hartids[i] << ">;\n"
" status = \"okay\";\n"
" compatible = \"riscv\";\n"
- " riscv,isa = \"" << procs[i]->get_isa().get_isa_string() << "\";\n"
- " mmu-type = \"riscv," << (procs[i]->get_isa().get_max_xlen() <= 32 ? "sv32" : "sv57") << "\";\n"
+ " riscv,isa = \"" << isa.get_isa_string() << "\";\n"
+ " mmu-type = \"riscv," << (isa.get_max_xlen() <= 32 ? "sv32" : "sv57") << "\";\n"
" riscv,pmpregions = <" << pmpregions << ">;\n"
" riscv,pmpgranularity = <" << pmpgranularity << ">;\n"
" clock-frequency = <" << cpu_hz << ">;\n"
@@ -96,86 +99,98 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
return s.str();
}
-std::string dts_compile(const std::string& dts)
+static std::string dtc_compile(const std::string& dtc_input, bool compile)
{
- // Convert the DTS to DTB
- int dts_pipe[2];
- pid_t dts_pid;
+ const char* input_type = compile ? "dts" : "dtb";
+ const char* output_type = compile ? "dtb" : "dts";
+
+ int dtc_input_pipe[2];
+ pid_t dtc_input_pid;
fflush(NULL); // flush stdout/stderr before forking
- if (pipe(dts_pipe) != 0 || (dts_pid = fork()) < 0) {
- std::cerr << "Failed to fork dts child: " << strerror(errno) << std::endl;
+ if (pipe(dtc_input_pipe) != 0 || (dtc_input_pid = fork()) < 0) {
+ std::cerr << "Failed to fork dtc_input child: " << strerror(errno) << std::endl;
exit(1);
}
- // Child process to output dts
- if (dts_pid == 0) {
- close(dts_pipe[0]);
- int step, len = dts.length();
- const char *buf = dts.c_str();
+ // Child process to output dtc_input
+ if (dtc_input_pid == 0) {
+ close(dtc_input_pipe[0]);
+ int step, len = dtc_input.length();
+ const char *buf = dtc_input.c_str();
for (int done = 0; done < len; done += step) {
- step = write(dts_pipe[1], buf+done, len-done);
+ step = write(dtc_input_pipe[1], buf+done, len-done);
if (step == -1) {
- std::cerr << "Failed to write dts: " << strerror(errno) << std::endl;
+ std::cerr << "Failed to write dtc_input: " << strerror(errno) << std::endl;
exit(1);
}
}
- close(dts_pipe[1]);
+ close(dtc_input_pipe[1]);
exit(0);
}
- pid_t dtb_pid;
- int dtb_pipe[2];
- if (pipe(dtb_pipe) != 0 || (dtb_pid = fork()) < 0) {
- std::cerr << "Failed to fork dtb child: " << strerror(errno) << std::endl;
+ pid_t dtc_output_pid;
+ int dtc_output_pipe[2];
+ if (pipe(dtc_output_pipe) != 0 || (dtc_output_pid = fork()) < 0) {
+ std::cerr << "Failed to fork dtc_output child: " << strerror(errno) << std::endl;
exit(1);
}
- // Child process to output dtb
- if (dtb_pid == 0) {
- dup2(dts_pipe[0], 0);
- dup2(dtb_pipe[1], 1);
- close(dts_pipe[0]);
- close(dts_pipe[1]);
- close(dtb_pipe[0]);
- close(dtb_pipe[1]);
- execlp(DTC, DTC, "-O", "dtb", (char *)0);
+ // Child process to output dtc_output
+ if (dtc_output_pid == 0) {
+ dup2(dtc_input_pipe[0], 0);
+ dup2(dtc_output_pipe[1], 1);
+ close(dtc_input_pipe[0]);
+ close(dtc_input_pipe[1]);
+ close(dtc_output_pipe[0]);
+ close(dtc_output_pipe[1]);
+ execlp(DTC, DTC, "-O", output_type, "-I", input_type, nullptr);
std::cerr << "Failed to run " DTC ": " << strerror(errno) << std::endl;
exit(1);
}
- close(dts_pipe[1]);
- close(dts_pipe[0]);
- close(dtb_pipe[1]);
+ close(dtc_input_pipe[1]);
+ close(dtc_input_pipe[0]);
+ close(dtc_output_pipe[1]);
- // Read-out dtb
- std::stringstream dtb;
+ // Read-out dtc_output
+ std::stringstream dtc_output;
int got;
char buf[4096];
- while ((got = read(dtb_pipe[0], buf, sizeof(buf))) > 0) {
- dtb.write(buf, got);
+ while ((got = read(dtc_output_pipe[0], buf, sizeof(buf))) > 0) {
+ dtc_output.write(buf, got);
}
if (got == -1) {
- std::cerr << "Failed to read dtb: " << strerror(errno) << std::endl;
+ std::cerr << "Failed to read dtc_output: " << strerror(errno) << std::endl;
exit(1);
}
- close(dtb_pipe[0]);
+ close(dtc_output_pipe[0]);
// Reap children
int status;
- waitpid(dts_pid, &status, 0);
+ waitpid(dtc_input_pid, &status, 0);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
- std::cerr << "Child dts process failed" << std::endl;
+ std::cerr << "Child dtc_input process failed" << std::endl;
exit(1);
}
- waitpid(dtb_pid, &status, 0);
+ waitpid(dtc_output_pid, &status, 0);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
- std::cerr << "Child dtb process failed" << std::endl;
+ std::cerr << "Child dtc_output process failed" << std::endl;
exit(1);
}
- return dtb.str();
+ return dtc_output.str();
+}
+
+std::string dtb_to_dts(const std::string& dtc_input)
+{
+ return dtc_compile(dtc_input, false);
+}
+
+std::string dts_to_dtb(const std::string& dtc_input)
+{
+ return dtc_compile(dtc_input, true);
}
int fdt_get_node_addr_size(const void *fdt, int node, reg_t *addr,
@@ -386,3 +401,43 @@ int fdt_parse_mmu_type(const void *fdt, int cpu_offset, const char **mmu_type)
return 0;
}
+
+int fdt_parse_isa(const void *fdt, int cpu_offset, const char **isa)
+{
+ assert(isa);
+
+ int len, rc;
+ const void *prop;
+
+ if ((rc = check_cpu_node(fdt, cpu_offset)) < 0)
+ return rc;
+
+ prop = fdt_getprop(fdt, cpu_offset, "riscv,isa", &len);
+ if (!prop || !len)
+ return -EINVAL;
+
+ *isa = (const char *)prop;
+
+ return 0;
+}
+
+int fdt_parse_hartid(const void *fdt, int cpu_offset, uint32_t *hartid)
+{
+ int len, rc;
+ const fdt32_t *val;
+
+ if ((rc = check_cpu_node(fdt, cpu_offset)) < 0)
+ return rc;
+
+ val = (fdt32_t*) fdt_getprop(fdt, cpu_offset, "reg", &len);
+ if (!val || len < (int) sizeof(fdt32_t))
+ return -EINVAL;
+
+ if (len > (int) sizeof(fdt32_t))
+ val++;
+
+ if (hartid)
+ *hartid = fdt32_to_cpu(*val);
+
+ return 0;
+}
diff --git a/riscv/dts.h b/riscv/dts.h
index 7afe376..730dea7 100644
--- a/riscv/dts.h
+++ b/riscv/dts.h
@@ -7,15 +7,12 @@
#include <string>
std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
- reg_t initrd_start, reg_t initrd_end,
- const char* bootargs,
- size_t pmpregions,
- size_t pmpgranularity,
- std::vector<processor_t*> procs,
+ const cfg_t* cfg,
std::vector<std::pair<reg_t, abstract_mem_t*>> mems,
std::string device_nodes);
-std::string dts_compile(const std::string& dts);
+std::string dts_to_dtb(const std::string& dtc_input);
+std::string dtb_to_dts(const std::string& dtc_input);
int fdt_get_node_addr_size(const void *fdt, int node, reg_t *addr,
unsigned long *size, const char *field);
@@ -33,4 +30,6 @@ int fdt_parse_ns16550(const void *fdt, reg_t *ns16550_addr,
int fdt_parse_pmp_num(const void *fdt, int cpu_offset, reg_t *pmp_num);
int fdt_parse_pmp_alignment(const void *fdt, int cpu_offset, reg_t *pmp_align);
int fdt_parse_mmu_type(const void *fdt, int cpu_offset, const char **mmu_type);
+int fdt_parse_isa(const void *fdt, int cpu_offset, const char **isa_str);
+int fdt_parse_hartid(const void *fdt, int cpu_offset, uint32_t *hartid);
#endif
diff --git a/riscv/encoding.h b/riscv/encoding.h
index 4b2e0b6..bcc1ace 100644
--- a/riscv/encoding.h
+++ b/riscv/encoding.h
@@ -4,7 +4,7 @@
/*
* This file is auto-generated by running 'make' in
- * https://github.com/riscv/riscv-opcodes (7bed351)
+ * https://github.com/riscv/riscv-opcodes (8899b32)
*/
#ifndef RISCV_CSR_ENCODING_H
@@ -30,6 +30,7 @@
#define MSTATUS_TW 0x00200000
#define MSTATUS_TSR 0x00400000
#define MSTATUS_SPELP 0x00800000
+#define MSTATUS_SDT 0x01000000
#define MSTATUS32_SD 0x80000000
#define MSTATUS_UXL 0x0000000300000000
#define MSTATUS_SXL 0x0000000C00000000
@@ -38,12 +39,14 @@
#define MSTATUS_GVA 0x0000004000000000
#define MSTATUS_MPV 0x0000008000000000
#define MSTATUS_MPELP 0x0000020000000000
+#define MSTATUS_MDT 0x0000040000000000
#define MSTATUS64_SD 0x8000000000000000
#define MSTATUSH_SBE 0x00000010
#define MSTATUSH_MBE 0x00000020
#define MSTATUSH_GVA 0x00000040
#define MSTATUSH_MPV 0x00000080
+#define MSTATUSH_MDT 0x00000400
#define SSTATUS_UIE 0x00000001
#define SSTATUS_SIE 0x00000002
@@ -57,6 +60,7 @@
#define SSTATUS_SUM 0x00040000
#define SSTATUS_MXR 0x00080000
#define SSTATUS_SPELP 0x00800000
+#define SSTATUS_SDT 0x01000000
#define SSTATUS32_SD 0x80000000
#define SSTATUS_UXL 0x0000000300000000
#define SSTATUS64_SD 0x8000000000000000
@@ -71,27 +75,32 @@
#define HSTATUS_SPV 0x00000080
#define HSTATUS_GVA 0x00000040
#define HSTATUS_VSBE 0x00000020
+#define HSTATUS_HUPMM 0x0003000000000000
#define USTATUS_UIE 0x00000001
#define USTATUS_UPIE 0x00000010
#define MNSTATUS_NMIE 0x00000008
-#define MNSTATUS_MNPP 0x00001800
#define MNSTATUS_MNPV 0x00000080
+#define MNSTATUS_MNPELP 0x00000200
+#define MNSTATUS_MNPP 0x00001800
-#define DCSR_XDEBUGVER (3U<<30)
-#define DCSR_NDRESET (1<<29)
-#define DCSR_FULLRESET (1<<28)
+#define DCSR_XDEBUGVER (15U<<28)
+#define DCSR_EXTCAUSE (7<<24)
+#define DCSR_CETRIG (1<<19)
#define DCSR_PELP (1<<18)
+#define DCSR_EBREAKVS (1<<17)
+#define DCSR_EBREAKVU (1<<16)
#define DCSR_EBREAKM (1<<15)
-#define DCSR_EBREAKH (1<<14)
#define DCSR_EBREAKS (1<<13)
#define DCSR_EBREAKU (1<<12)
-#define DCSR_STOPCYCLE (1<<10)
+#define DCSR_STEPIE (1<<11)
+#define DCSR_STOPCOUNT (1<<10)
#define DCSR_STOPTIME (1<<9)
#define DCSR_CAUSE (7<<6)
-#define DCSR_DEBUGINT (1<<5)
-#define DCSR_HALT (1<<3)
+#define DCSR_V (1<<5)
+#define DCSR_MPRVEN (1<<4)
+#define DCSR_NMIP (1<<3)
#define DCSR_STEP (1<<2)
#define DCSR_PRV (3<<0)
@@ -102,6 +111,9 @@
#define DCSR_CAUSE_STEP 4
#define DCSR_CAUSE_HALT 5
#define DCSR_CAUSE_GROUP 6
+#define DCSR_CAUSE_EXTCAUSE 7
+
+#define DCSR_EXTCAUSE_CRITERR 0
#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4))
#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5))
@@ -109,7 +121,7 @@
#define MCONTROL_SELECT (1<<19)
#define MCONTROL_TIMING (1<<18)
-#define MCONTROL_ACTION (0x3f<<12)
+#define MCONTROL_ACTION (0xf<<12)
#define MCONTROL_CHAIN (1<<11)
#define MCONTROL_MATCH (0xf<<7)
#define MCONTROL_M (1<<6)
@@ -168,10 +180,15 @@
#define MENVCFG_CBIE 0x00000030
#define MENVCFG_CBCFE 0x00000040
#define MENVCFG_CBZE 0x00000080
+#define MENVCFG_PMM 0x0000000300000000
+#define MENVCFG_DTE 0x0800000000000000
+#define MENVCFG_CDE 0x1000000000000000
#define MENVCFG_ADUE 0x2000000000000000
#define MENVCFG_PBMTE 0x4000000000000000
#define MENVCFG_STCE 0x8000000000000000
+#define MENVCFGH_DTE 0x08000000
+#define MENVCFGH_CDE 0x10000000
#define MENVCFGH_ADUE 0x20000000
#define MENVCFGH_PBMTE 0x40000000
#define MENVCFGH_STCE 0x80000000
@@ -179,6 +196,8 @@
#define MSTATEEN0_CS 0x00000001
#define MSTATEEN0_FCSR 0x00000002
#define MSTATEEN0_JVT 0x00000004
+#define MSTATEEN0_CTR 0x0040000000000000
+#define MSTATEEN0_PRIV113 0x0100000000000000
#define MSTATEEN0_PRIV114 0x0080000000000000
#define MSTATEEN0_HCONTEXT 0x0200000000000000
#define MSTATEEN0_AIA 0x0800000000000000
@@ -186,6 +205,8 @@
#define MSTATEEN0_HENVCFG 0x4000000000000000
#define MSTATEEN_HSTATEEN 0x8000000000000000
+#define MSTATEEN0H_CTR 0x00400000
+#define MSTATEEN0H_PRIV113 0x01000000
#define MSTATEEN0H_PRIV114 0x00800000
#define MSTATEEN0H_HCONTEXT 0x02000000
#define MSTATEEN0H_AIA 0x08000000
@@ -207,16 +228,30 @@
#define MHPMEVENTH_MINH 0x40000000
#define MHPMEVENTH_OF 0x80000000
+#define MCOUNTEREN_CY_SHIFT 0
+#define MCOUNTEREN_TIME_SHIFT 1
+#define MCOUNTEREN_IR_SHIFT 2
+
+#define MCOUNTEREN_CY (1U << MCOUNTEREN_CY_SHIFT)
+#define MCOUNTEREN_TIME (1U << MCOUNTEREN_TIME_SHIFT)
+#define MCOUNTEREN_IR (1U << MCOUNTEREN_IR_SHIFT)
+
+#define MCOUNTINHIBIT_CY MCOUNTEREN_CY
+#define MCOUNTINHIBIT_IR MCOUNTEREN_IR
+
#define HENVCFG_FIOM 0x00000001
#define HENVCFG_LPE 0x00000004
#define HENVCFG_SSE 0x00000008
#define HENVCFG_CBIE 0x00000030
#define HENVCFG_CBCFE 0x00000040
#define HENVCFG_CBZE 0x00000080
+#define HENVCFG_PMM 0x0000000300000000
+#define HENVCFG_DTE 0x0800000000000000
#define HENVCFG_ADUE 0x2000000000000000
#define HENVCFG_PBMTE 0x4000000000000000
#define HENVCFG_STCE 0x8000000000000000
+#define HENVCFGH_DTE 0x08000000
#define HENVCFGH_ADUE 0x20000000
#define HENVCFGH_PBMTE 0x40000000
#define HENVCFGH_STCE 0x80000000
@@ -236,12 +271,14 @@
#define HSTATEEN0_CS 0x00000001
#define HSTATEEN0_FCSR 0x00000002
#define HSTATEEN0_JVT 0x00000004
+#define HSTATEEN0_CTR 0x0040000000000000
#define HSTATEEN0_SCONTEXT 0x0200000000000000
#define HSTATEEN0_AIA 0x0800000000000000
#define HSTATEEN0_CSRIND 0x1000000000000000
#define HSTATEEN0_SENVCFG 0x4000000000000000
#define HSTATEEN_SSTATEEN 0x8000000000000000
+#define HSTATEEN0H_CTR 0x00400000
#define HSTATEEN0H_SCONTEXT 0x02000000
#define HSTATEEN0H_AIA 0x08000000
#define HSTATEEN0H_CSRIND 0x10000000
@@ -254,6 +291,7 @@
#define SENVCFG_CBIE 0x00000030
#define SENVCFG_CBCFE 0x00000040
#define SENVCFG_CBZE 0x00000080
+#define SENVCFG_PMM 0x0000000300000000
#define SSTATEEN0_CS 0x00000001
#define SSTATEEN0_FCSR 0x00000002
@@ -265,6 +303,7 @@
#define MSECCFG_USEED 0x00000100
#define MSECCFG_SSEED 0x00000200
#define MSECCFG_MLPE 0x00000400
+#define MSECCFG_PMM 0x0000000300000000
/* jvt fields */
#define JVT_MODE 0x3F
@@ -324,6 +363,73 @@
#define PMP_NA4 0x10
#define PMP_NAPOT 0x18
+#define MCTRCTL_U 0x0000000000000001
+#define MCTRCTL_S 0x0000000000000002
+#define MCTRCTL_M 0x0000000000000004
+#define MCTRCTL_RASEMU 0x0000000000000080
+#define MCTRCTL_STE 0x0000000000000100
+#define MCTRCTL_MTE 0x0000000000000200
+#define MCTRCTL_BPFRZ 0x0000000000000800
+#define MCTRCTL_LCOFIFRZ 0x0000000000001000
+#define MCTRCTL_EXCINH 0x0000000200000000
+#define MCTRCTL_INTRINH 0x0000000400000000
+#define MCTRCTL_TRETINH 0x0000000800000000
+#define MCTRCTL_NTBREN 0x0000001000000000
+#define MCTRCTL_TKBRINH 0x0000002000000000
+#define MCTRCTL_INDCALLINH 0x0000010000000000
+#define MCTRCTL_DIRCALLINH 0x0000020000000000
+#define MCTRCTL_INDJMPINH 0x0000040000000000
+#define MCTRCTL_DIRJMPINH 0x0000080000000000
+#define MCTRCTL_CORSWAPINH 0x0000100000000000
+#define MCTRCTL_RETINH 0x0000200000000000
+#define MCTRCTL_INDLJMPINH 0x0000400000000000
+#define MCTRCTL_DIRLJMPINH 0x0000800000000000
+
+#define SCTRCTL_U 0x0000000000000001
+#define SCTRCTL_S 0x0000000000000002
+#define SCTRCTL_RASEMU 0x0000000000000080
+#define SCTRCTL_STE 0x0000000000000100
+#define SCTRCTL_BPFRZ 0x0000000000000800
+#define SCTRCTL_LCOFIFRZ 0x0000000000001000
+#define SCTRCTL_EXCINH 0x0000000200000000
+#define SCTRCTL_INTRINH 0x0000000400000000
+#define SCTRCTL_TRETINH 0x0000000800000000
+#define SCTRCTL_NTBREN 0x0000001000000000
+#define SCTRCTL_TKBRINH 0x0000002000000000
+#define SCTRCTL_INDCALLINH 0x0000010000000000
+#define SCTRCTL_DIRCALLINH 0x0000020000000000
+#define SCTRCTL_INDJMPINH 0x0000040000000000
+#define SCTRCTL_DIRJMPINH 0x0000080000000000
+#define SCTRCTL_CORSWAPINH 0x0000100000000000
+#define SCTRCTL_RETINH 0x0000200000000000
+#define SCTRCTL_INDLJMPINH 0x0000400000000000
+#define SCTRCTL_DIRLJMPINH 0x0000800000000000
+
+#define VSCTRCTL_U 0x0000000000000001
+#define VSCTRCTL_S 0x0000000000000002
+#define VSCTRCTL_RASEMU 0x0000000000000080
+#define VSCTRCTL_STE 0x0000000000000100
+#define VSCTRCTL_BPFRZ 0x0000000000000800
+#define VSCTRCTL_LCOFIFRZ 0x0000000000001000
+#define VSCTRCTL_EXCINH 0x0000000200000000
+#define VSCTRCTL_INTRINH 0x0000000400000000
+#define VSCTRCTL_TRETINH 0x0000000800000000
+#define VSCTRCTL_NTBREN 0x0000001000000000
+#define VSCTRCTL_TKBRINH 0x0000002000000000
+#define VSCTRCTL_INDCALLINH 0x0000010000000000
+#define VSCTRCTL_DIRCALLINH 0x0000020000000000
+#define VSCTRCTL_INDJMPINH 0x0000040000000000
+#define VSCTRCTL_DIRJMPINH 0x0000080000000000
+#define VSCTRCTL_CORSWAPINH 0x0000100000000000
+#define VSCTRCTL_RETINH 0x0000200000000000
+#define VSCTRCTL_INDLJMPINH 0x0000400000000000
+#define VSCTRCTL_DIRLJMPINH 0x0000800000000000
+
+#define SCTRDEPTH_DEPTH 0x00000007
+
+#define SCTRSTATUS_WRPTR 0x000000FF
+#define SCTRSTATUS_FROZEN 0x80000000
+
#define IRQ_U_SOFT 0
#define IRQ_S_SOFT 1
#define IRQ_VS_SOFT 2
@@ -425,8 +531,6 @@
#define RISCV_ENCODING_H
#define MATCH_ADD 0x33
#define MASK_ADD 0xfe00707f
-#define MATCH_ADD64 0xc0001077
-#define MASK_ADD64 0xfe00707f
#define MATCH_ADD_UW 0x800003b
#define MASK_ADD_UW 0xfe00707f
#define MATCH_ADDI 0x13
@@ -1151,14 +1255,6 @@
#define MASK_JAL 0x7f
#define MATCH_JALR 0x67
#define MASK_JALR 0x707f
-#define MATCH_KADD64 0x90001077
-#define MASK_KADD64 0xfe00707f
-#define MATCH_KMAR64 0x94001077
-#define MASK_KMAR64 0xfe00707f
-#define MATCH_KMSR64 0x96001077
-#define MASK_KMSR64 0xfe00707f
-#define MATCH_KSUB64 0x92001077
-#define MASK_KSUB64 0xfe00707f
#define MATCH_LB 0x3
#define MASK_LB 0x707f
#define MATCH_LB_AQ 0x3400002f
@@ -1293,10 +1389,6 @@
#define MASK_MULHSU 0xfe00707f
#define MATCH_MULHU 0x2003033
#define MASK_MULHU 0xfe00707f
-#define MATCH_MULR64 0xf0001077
-#define MASK_MULR64 0xfe00707f
-#define MATCH_MULSR64 0xe0001077
-#define MASK_MULSR64 0xfe00707f
#define MATCH_MULW 0x200003b
#define MASK_MULW 0xfe00707f
#define MATCH_OR 0x6033
@@ -1319,8 +1411,6 @@
#define MASK_PREFETCH_R 0x1f07fff
#define MATCH_PREFETCH_W 0x306013
#define MASK_PREFETCH_W 0x1f07fff
-#define MATCH_RADD64 0x80001077
-#define MASK_RADD64 0xfe00707f
#define MATCH_REM 0x2006033
#define MASK_REM 0xfe00707f
#define MATCH_REMU 0x2007033
@@ -1341,8 +1431,6 @@
#define MASK_RORIW 0xfe00707f
#define MATCH_RORW 0x6000503b
#define MASK_RORW 0xfe00707f
-#define MATCH_RSUB64 0x82001077
-#define MASK_RSUB64 0xfe00707f
#define MATCH_SB 0x23
#define MASK_SB 0x707f
#define MATCH_SB_RL 0x3a00002f
@@ -1351,6 +1439,8 @@
#define MASK_SC_D 0xf800707f
#define MATCH_SC_W 0x1800202f
#define MASK_SC_W 0xf800707f
+#define MATCH_SCTRCLR 0x10400073
+#define MASK_SCTRCLR 0xffffffff
#define MATCH_SD 0x3023
#define MASK_SD 0x707f
#define MATCH_SD_RL 0x3a00302f
@@ -1425,14 +1515,6 @@
#define MASK_SLLIW 0xfe00707f
#define MATCH_SLLW 0x103b
#define MASK_SLLW 0xfe00707f
-#define MATCH_SLO 0x20001033
-#define MASK_SLO 0xfe00707f
-#define MATCH_SLOI 0x20001013
-#define MASK_SLOI 0xfc00707f
-#define MATCH_SLOIW 0x2000101b
-#define MASK_SLOIW 0xfe00707f
-#define MATCH_SLOW 0x2000103b
-#define MASK_SLOW 0xfe00707f
#define MATCH_SLT 0x2033
#define MASK_SLT 0xfe00707f
#define MATCH_SLTI 0x2013
@@ -1449,40 +1531,6 @@
#define MASK_SM4ED 0x3e00707f
#define MATCH_SM4KS 0x34000033
#define MASK_SM4KS 0x3e00707f
-#define MATCH_SMAL 0x5e001077
-#define MASK_SMAL 0xfe00707f
-#define MATCH_SMALBB 0x88001077
-#define MASK_SMALBB 0xfe00707f
-#define MATCH_SMALBT 0x98001077
-#define MASK_SMALBT 0xfe00707f
-#define MATCH_SMALDA 0x8c001077
-#define MASK_SMALDA 0xfe00707f
-#define MATCH_SMALDRS 0x9a001077
-#define MASK_SMALDRS 0xfe00707f
-#define MATCH_SMALDS 0x8a001077
-#define MASK_SMALDS 0xfe00707f
-#define MATCH_SMALTT 0xa8001077
-#define MASK_SMALTT 0xfe00707f
-#define MATCH_SMALXDA 0x9c001077
-#define MASK_SMALXDA 0xfe00707f
-#define MATCH_SMALXDS 0xaa001077
-#define MASK_SMALXDS 0xfe00707f
-#define MATCH_SMAR64 0x84001077
-#define MASK_SMAR64 0xfe00707f
-#define MATCH_SMSLDA 0xac001077
-#define MASK_SMSLDA 0xfe00707f
-#define MATCH_SMSLXDA 0xbc001077
-#define MASK_SMSLXDA 0xfe00707f
-#define MATCH_SMSR64 0x86001077
-#define MASK_SMSR64 0xfe00707f
-#define MATCH_SMUL16 0xa0000077
-#define MASK_SMUL16 0xfe00707f
-#define MATCH_SMUL8 0xa8000077
-#define MASK_SMUL8 0xfe00707f
-#define MATCH_SMULX16 0xa2000077
-#define MASK_SMULX16 0xfe00707f
-#define MATCH_SMULX8 0xaa000077
-#define MASK_SMULX8 0xfe00707f
#define MATCH_SRA 0x40005033
#define MASK_SRA 0xfe00707f
#define MATCH_SRAI 0x40005013
@@ -1505,14 +1553,6 @@
#define MASK_SRLIW 0xfe00707f
#define MATCH_SRLW 0x503b
#define MASK_SRLW 0xfe00707f
-#define MATCH_SRO 0x20005033
-#define MASK_SRO 0xfe00707f
-#define MATCH_SROI 0x20005013
-#define MASK_SROI 0xfc00707f
-#define MATCH_SROIW 0x2000501b
-#define MASK_SROIW 0xfe00707f
-#define MATCH_SROW 0x2000503b
-#define MASK_SROW 0xfe00707f
#define MATCH_SSAMOSWAP_D 0x4800302f
#define MASK_SSAMOSWAP_D 0xf800707f
#define MATCH_SSAMOSWAP_W 0x4800202f
@@ -1529,40 +1569,14 @@
#define MASK_SSRDP 0xfffff07f
#define MATCH_SUB 0x40000033
#define MASK_SUB 0xfe00707f
-#define MATCH_SUB64 0xc2001077
-#define MASK_SUB64 0xfe00707f
#define MATCH_SUBW 0x4000003b
#define MASK_SUBW 0xfe00707f
#define MATCH_SW 0x2023
#define MASK_SW 0x707f
#define MATCH_SW_RL 0x3a00202f
#define MASK_SW_RL 0xfa007fff
-#define MATCH_UKADD64 0xb0001077
-#define MASK_UKADD64 0xfe00707f
-#define MATCH_UKMAR64 0xb4001077
-#define MASK_UKMAR64 0xfe00707f
-#define MATCH_UKMSR64 0xb6001077
-#define MASK_UKMSR64 0xfe00707f
-#define MATCH_UKSUB64 0xb2001077
-#define MASK_UKSUB64 0xfe00707f
-#define MATCH_UMAR64 0xa4001077
-#define MASK_UMAR64 0xfe00707f
-#define MATCH_UMSR64 0xa6001077
-#define MASK_UMSR64 0xfe00707f
-#define MATCH_UMUL16 0xb0000077
-#define MASK_UMUL16 0xfe00707f
-#define MATCH_UMUL8 0xb8000077
-#define MASK_UMUL8 0xfe00707f
-#define MATCH_UMULX16 0xb2000077
-#define MASK_UMULX16 0xfe00707f
-#define MATCH_UMULX8 0xba000077
-#define MASK_UMULX8 0xfe00707f
#define MATCH_UNSHFLI 0x8005013
#define MASK_UNSHFLI 0xfe00707f
-#define MATCH_URADD64 0xa0001077
-#define MASK_URADD64 0xfe00707f
-#define MATCH_URSUB64 0xa2001077
-#define MASK_URSUB64 0xfe00707f
#define MATCH_VAADD_VV 0x24002057
#define MASK_VAADD_VV 0xfc00707f
#define MATCH_VAADD_VX 0x24006057
@@ -2131,6 +2145,20 @@
#define MASK_VOR_VV 0xfc00707f
#define MATCH_VOR_VX 0x28004057
#define MASK_VOR_VX 0xfc00707f
+#define MATCH_VQDOT_VV 0xb0002057
+#define MASK_VQDOT_VV 0xfc00707f
+#define MATCH_VQDOT_VX 0xb0006057
+#define MASK_VQDOT_VX 0xfc00707f
+#define MATCH_VQDOTSU_VV 0xa8002057
+#define MASK_VQDOTSU_VV 0xfc00707f
+#define MATCH_VQDOTSU_VX 0xa8006057
+#define MASK_VQDOTSU_VX 0xfc00707f
+#define MATCH_VQDOTU_VV 0xa0002057
+#define MASK_VQDOTU_VV 0xfc00707f
+#define MATCH_VQDOTU_VX 0xa0006057
+#define MASK_VQDOTU_VX 0xfc00707f
+#define MATCH_VQDOTUS_VX 0xb8006057
+#define MASK_VQDOTUS_VX 0xfc00707f
#define MATCH_VREDAND_VS 0x4002057
#define MASK_VREDAND_VS 0xfc00707f
#define MATCH_VREDMAX_VS 0x1c002057
@@ -2487,6 +2515,8 @@
#define CSR_STVAL 0x143
#define CSR_SIP 0x144
#define CSR_STIMECMP 0x14d
+#define CSR_SCTRCTL 0x14e
+#define CSR_SCTRSTATUS 0x14f
#define CSR_SISELECT 0x150
#define CSR_SIREG 0x151
#define CSR_SIREG2 0x152
@@ -2495,6 +2525,7 @@
#define CSR_SIREG5 0x156
#define CSR_SIREG6 0x157
#define CSR_STOPEI 0x15c
+#define CSR_SCTRDEPTH 0x15f
#define CSR_SATP 0x180
#define CSR_SRMCFG 0x181
#define CSR_SCONTEXT 0x5a8
@@ -2507,6 +2538,7 @@
#define CSR_VSTVAL 0x243
#define CSR_VSIP 0x244
#define CSR_VSTIMECMP 0x24d
+#define CSR_VSCTRCTL 0x24e
#define CSR_VSISELECT 0x250
#define CSR_VSIREG 0x251
#define CSR_VSIREG2 0x252
@@ -2579,6 +2611,7 @@
#define CSR_MIP 0x344
#define CSR_MTINST 0x34a
#define CSR_MTVAL2 0x34b
+#define CSR_MCTRCTL 0x34e
#define CSR_MISELECT 0x350
#define CSR_MIREG 0x351
#define CSR_MIREG2 0x352
@@ -2754,6 +2787,7 @@
#define CSR_VSIEH 0x214
#define CSR_VSIPH 0x254
#define CSR_VSTIMECMPH 0x25d
+#define CSR_HEDELEGH 0x612
#define CSR_HTIMEDELTAH 0x615
#define CSR_HIDELEGH 0x613
#define CSR_HVIENH 0x618
@@ -2891,6 +2925,7 @@
#define CAUSE_FETCH_PAGE_FAULT 0xc
#define CAUSE_LOAD_PAGE_FAULT 0xd
#define CAUSE_STORE_PAGE_FAULT 0xf
+#define CAUSE_DOUBLE_TRAP 0x10
#define CAUSE_SOFTWARE_CHECK_FAULT 0x12
#define CAUSE_HARDWARE_ERROR_FAULT 0x13
#define CAUSE_FETCH_GUEST_PAGE_FAULT 0x14
@@ -3004,10 +3039,10 @@
#define INSN_FIELD_MOP_RR_T_30 0x40000000
#define INSN_FIELD_MOP_RR_T_27_26 0xc000000
#define INSN_FIELD_C_MOP_T 0x700
+#define INSN_FIELD_RS2_EQ_RS1 0x1f00000
#endif
#ifdef DECLARE_INSN
DECLARE_INSN(add, MATCH_ADD, MASK_ADD)
-DECLARE_INSN(add64, MATCH_ADD64, MASK_ADD64)
DECLARE_INSN(add_uw, MATCH_ADD_UW, MASK_ADD_UW)
DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI)
DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW)
@@ -3370,10 +3405,6 @@ DECLARE_INSN(hsv_h, MATCH_HSV_H, MASK_HSV_H)
DECLARE_INSN(hsv_w, MATCH_HSV_W, MASK_HSV_W)
DECLARE_INSN(jal, MATCH_JAL, MASK_JAL)
DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR)
-DECLARE_INSN(kadd64, MATCH_KADD64, MASK_KADD64)
-DECLARE_INSN(kmar64, MATCH_KMAR64, MASK_KMAR64)
-DECLARE_INSN(kmsr64, MATCH_KMSR64, MASK_KMSR64)
-DECLARE_INSN(ksub64, MATCH_KSUB64, MASK_KSUB64)
DECLARE_INSN(lb, MATCH_LB, MASK_LB)
DECLARE_INSN(lb_aq, MATCH_LB_AQ, MASK_LB_AQ)
DECLARE_INSN(lbu, MATCH_LBU, MASK_LBU)
@@ -3441,8 +3472,6 @@ DECLARE_INSN(mul, MATCH_MUL, MASK_MUL)
DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH)
DECLARE_INSN(mulhsu, MATCH_MULHSU, MASK_MULHSU)
DECLARE_INSN(mulhu, MATCH_MULHU, MASK_MULHU)
-DECLARE_INSN(mulr64, MATCH_MULR64, MASK_MULR64)
-DECLARE_INSN(mulsr64, MATCH_MULSR64, MASK_MULSR64)
DECLARE_INSN(mulw, MATCH_MULW, MASK_MULW)
DECLARE_INSN(or, MATCH_OR, MASK_OR)
DECLARE_INSN(ori, MATCH_ORI, MASK_ORI)
@@ -3454,7 +3483,6 @@ DECLARE_INSN(pause, MATCH_PAUSE, MASK_PAUSE)
DECLARE_INSN(prefetch_i, MATCH_PREFETCH_I, MASK_PREFETCH_I)
DECLARE_INSN(prefetch_r, MATCH_PREFETCH_R, MASK_PREFETCH_R)
DECLARE_INSN(prefetch_w, MATCH_PREFETCH_W, MASK_PREFETCH_W)
-DECLARE_INSN(radd64, MATCH_RADD64, MASK_RADD64)
DECLARE_INSN(rem, MATCH_REM, MASK_REM)
DECLARE_INSN(remu, MATCH_REMU, MASK_REMU)
DECLARE_INSN(remuw, MATCH_REMUW, MASK_REMUW)
@@ -3465,11 +3493,11 @@ DECLARE_INSN(ror, MATCH_ROR, MASK_ROR)
DECLARE_INSN(rori, MATCH_RORI, MASK_RORI)
DECLARE_INSN(roriw, MATCH_RORIW, MASK_RORIW)
DECLARE_INSN(rorw, MATCH_RORW, MASK_RORW)
-DECLARE_INSN(rsub64, MATCH_RSUB64, MASK_RSUB64)
DECLARE_INSN(sb, MATCH_SB, MASK_SB)
DECLARE_INSN(sb_rl, MATCH_SB_RL, MASK_SB_RL)
DECLARE_INSN(sc_d, MATCH_SC_D, MASK_SC_D)
DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W)
+DECLARE_INSN(sctrclr, MATCH_SCTRCLR, MASK_SCTRCLR)
DECLARE_INSN(sd, MATCH_SD, MASK_SD)
DECLARE_INSN(sd_rl, MATCH_SD_RL, MASK_SD_RL)
DECLARE_INSN(sext_b, MATCH_SEXT_B, MASK_SEXT_B)
@@ -3507,10 +3535,6 @@ DECLARE_INSN(slli_rv32, MATCH_SLLI_RV32, MASK_SLLI_RV32)
DECLARE_INSN(slli_uw, MATCH_SLLI_UW, MASK_SLLI_UW)
DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW)
DECLARE_INSN(sllw, MATCH_SLLW, MASK_SLLW)
-DECLARE_INSN(slo, MATCH_SLO, MASK_SLO)
-DECLARE_INSN(sloi, MATCH_SLOI, MASK_SLOI)
-DECLARE_INSN(sloiw, MATCH_SLOIW, MASK_SLOIW)
-DECLARE_INSN(slow, MATCH_SLOW, MASK_SLOW)
DECLARE_INSN(slt, MATCH_SLT, MASK_SLT)
DECLARE_INSN(slti, MATCH_SLTI, MASK_SLTI)
DECLARE_INSN(sltiu, MATCH_SLTIU, MASK_SLTIU)
@@ -3519,23 +3543,6 @@ DECLARE_INSN(sm3p0, MATCH_SM3P0, MASK_SM3P0)
DECLARE_INSN(sm3p1, MATCH_SM3P1, MASK_SM3P1)
DECLARE_INSN(sm4ed, MATCH_SM4ED, MASK_SM4ED)
DECLARE_INSN(sm4ks, MATCH_SM4KS, MASK_SM4KS)
-DECLARE_INSN(smal, MATCH_SMAL, MASK_SMAL)
-DECLARE_INSN(smalbb, MATCH_SMALBB, MASK_SMALBB)
-DECLARE_INSN(smalbt, MATCH_SMALBT, MASK_SMALBT)
-DECLARE_INSN(smalda, MATCH_SMALDA, MASK_SMALDA)
-DECLARE_INSN(smaldrs, MATCH_SMALDRS, MASK_SMALDRS)
-DECLARE_INSN(smalds, MATCH_SMALDS, MASK_SMALDS)
-DECLARE_INSN(smaltt, MATCH_SMALTT, MASK_SMALTT)
-DECLARE_INSN(smalxda, MATCH_SMALXDA, MASK_SMALXDA)
-DECLARE_INSN(smalxds, MATCH_SMALXDS, MASK_SMALXDS)
-DECLARE_INSN(smar64, MATCH_SMAR64, MASK_SMAR64)
-DECLARE_INSN(smslda, MATCH_SMSLDA, MASK_SMSLDA)
-DECLARE_INSN(smslxda, MATCH_SMSLXDA, MASK_SMSLXDA)
-DECLARE_INSN(smsr64, MATCH_SMSR64, MASK_SMSR64)
-DECLARE_INSN(smul16, MATCH_SMUL16, MASK_SMUL16)
-DECLARE_INSN(smul8, MATCH_SMUL8, MASK_SMUL8)
-DECLARE_INSN(smulx16, MATCH_SMULX16, MASK_SMULX16)
-DECLARE_INSN(smulx8, MATCH_SMULX8, MASK_SMULX8)
DECLARE_INSN(sra, MATCH_SRA, MASK_SRA)
DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI)
DECLARE_INSN(srai_rv32, MATCH_SRAI_RV32, MASK_SRAI_RV32)
@@ -3547,10 +3554,6 @@ DECLARE_INSN(srli, MATCH_SRLI, MASK_SRLI)
DECLARE_INSN(srli_rv32, MATCH_SRLI_RV32, MASK_SRLI_RV32)
DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW)
DECLARE_INSN(srlw, MATCH_SRLW, MASK_SRLW)
-DECLARE_INSN(sro, MATCH_SRO, MASK_SRO)
-DECLARE_INSN(sroi, MATCH_SROI, MASK_SROI)
-DECLARE_INSN(sroiw, MATCH_SROIW, MASK_SROIW)
-DECLARE_INSN(srow, MATCH_SROW, MASK_SROW)
DECLARE_INSN(ssamoswap_d, MATCH_SSAMOSWAP_D, MASK_SSAMOSWAP_D)
DECLARE_INSN(ssamoswap_w, MATCH_SSAMOSWAP_W, MASK_SSAMOSWAP_W)
DECLARE_INSN(sspopchk_x1, MATCH_SSPOPCHK_X1, MASK_SSPOPCHK_X1)
@@ -3559,23 +3562,10 @@ DECLARE_INSN(sspush_x1, MATCH_SSPUSH_X1, MASK_SSPUSH_X1)
DECLARE_INSN(sspush_x5, MATCH_SSPUSH_X5, MASK_SSPUSH_X5)
DECLARE_INSN(ssrdp, MATCH_SSRDP, MASK_SSRDP)
DECLARE_INSN(sub, MATCH_SUB, MASK_SUB)
-DECLARE_INSN(sub64, MATCH_SUB64, MASK_SUB64)
DECLARE_INSN(subw, MATCH_SUBW, MASK_SUBW)
DECLARE_INSN(sw, MATCH_SW, MASK_SW)
DECLARE_INSN(sw_rl, MATCH_SW_RL, MASK_SW_RL)
-DECLARE_INSN(ukadd64, MATCH_UKADD64, MASK_UKADD64)
-DECLARE_INSN(ukmar64, MATCH_UKMAR64, MASK_UKMAR64)
-DECLARE_INSN(ukmsr64, MATCH_UKMSR64, MASK_UKMSR64)
-DECLARE_INSN(uksub64, MATCH_UKSUB64, MASK_UKSUB64)
-DECLARE_INSN(umar64, MATCH_UMAR64, MASK_UMAR64)
-DECLARE_INSN(umsr64, MATCH_UMSR64, MASK_UMSR64)
-DECLARE_INSN(umul16, MATCH_UMUL16, MASK_UMUL16)
-DECLARE_INSN(umul8, MATCH_UMUL8, MASK_UMUL8)
-DECLARE_INSN(umulx16, MATCH_UMULX16, MASK_UMULX16)
-DECLARE_INSN(umulx8, MATCH_UMULX8, MASK_UMULX8)
DECLARE_INSN(unshfli, MATCH_UNSHFLI, MASK_UNSHFLI)
-DECLARE_INSN(uradd64, MATCH_URADD64, MASK_URADD64)
-DECLARE_INSN(ursub64, MATCH_URSUB64, MASK_URSUB64)
DECLARE_INSN(vaadd_vv, MATCH_VAADD_VV, MASK_VAADD_VV)
DECLARE_INSN(vaadd_vx, MATCH_VAADD_VX, MASK_VAADD_VX)
DECLARE_INSN(vaaddu_vv, MATCH_VAADDU_VV, MASK_VAADDU_VV)
@@ -3860,6 +3850,13 @@ DECLARE_INSN(vnsrl_wx, MATCH_VNSRL_WX, MASK_VNSRL_WX)
DECLARE_INSN(vor_vi, MATCH_VOR_VI, MASK_VOR_VI)
DECLARE_INSN(vor_vv, MATCH_VOR_VV, MASK_VOR_VV)
DECLARE_INSN(vor_vx, MATCH_VOR_VX, MASK_VOR_VX)
+DECLARE_INSN(vqdot_vv, MATCH_VQDOT_VV, MASK_VQDOT_VV)
+DECLARE_INSN(vqdot_vx, MATCH_VQDOT_VX, MASK_VQDOT_VX)
+DECLARE_INSN(vqdotsu_vv, MATCH_VQDOTSU_VV, MASK_VQDOTSU_VV)
+DECLARE_INSN(vqdotsu_vx, MATCH_VQDOTSU_VX, MASK_VQDOTSU_VX)
+DECLARE_INSN(vqdotu_vv, MATCH_VQDOTU_VV, MASK_VQDOTU_VV)
+DECLARE_INSN(vqdotu_vx, MATCH_VQDOTU_VX, MASK_VQDOTU_VX)
+DECLARE_INSN(vqdotus_vx, MATCH_VQDOTUS_VX, MASK_VQDOTUS_VX)
DECLARE_INSN(vredand_vs, MATCH_VREDAND_VS, MASK_VREDAND_VS)
DECLARE_INSN(vredmax_vs, MATCH_VREDMAX_VS, MASK_VREDMAX_VS)
DECLARE_INSN(vredmaxu_vs, MATCH_VREDMAXU_VS, MASK_VREDMAXU_VS)
@@ -4071,6 +4068,8 @@ DECLARE_CSR(scause, CSR_SCAUSE)
DECLARE_CSR(stval, CSR_STVAL)
DECLARE_CSR(sip, CSR_SIP)
DECLARE_CSR(stimecmp, CSR_STIMECMP)
+DECLARE_CSR(sctrctl, CSR_SCTRCTL)
+DECLARE_CSR(sctrstatus, CSR_SCTRSTATUS)
DECLARE_CSR(siselect, CSR_SISELECT)
DECLARE_CSR(sireg, CSR_SIREG)
DECLARE_CSR(sireg2, CSR_SIREG2)
@@ -4079,6 +4078,7 @@ DECLARE_CSR(sireg4, CSR_SIREG4)
DECLARE_CSR(sireg5, CSR_SIREG5)
DECLARE_CSR(sireg6, CSR_SIREG6)
DECLARE_CSR(stopei, CSR_STOPEI)
+DECLARE_CSR(sctrdepth, CSR_SCTRDEPTH)
DECLARE_CSR(satp, CSR_SATP)
DECLARE_CSR(srmcfg, CSR_SRMCFG)
DECLARE_CSR(scontext, CSR_SCONTEXT)
@@ -4091,6 +4091,7 @@ DECLARE_CSR(vscause, CSR_VSCAUSE)
DECLARE_CSR(vstval, CSR_VSTVAL)
DECLARE_CSR(vsip, CSR_VSIP)
DECLARE_CSR(vstimecmp, CSR_VSTIMECMP)
+DECLARE_CSR(vsctrctl, CSR_VSCTRCTL)
DECLARE_CSR(vsiselect, CSR_VSISELECT)
DECLARE_CSR(vsireg, CSR_VSIREG)
DECLARE_CSR(vsireg2, CSR_VSIREG2)
@@ -4163,6 +4164,7 @@ DECLARE_CSR(mtval, CSR_MTVAL)
DECLARE_CSR(mip, CSR_MIP)
DECLARE_CSR(mtinst, CSR_MTINST)
DECLARE_CSR(mtval2, CSR_MTVAL2)
+DECLARE_CSR(mctrctl, CSR_MCTRCTL)
DECLARE_CSR(miselect, CSR_MISELECT)
DECLARE_CSR(mireg, CSR_MIREG)
DECLARE_CSR(mireg2, CSR_MIREG2)
@@ -4338,6 +4340,7 @@ DECLARE_CSR(stimecmph, CSR_STIMECMPH)
DECLARE_CSR(vsieh, CSR_VSIEH)
DECLARE_CSR(vsiph, CSR_VSIPH)
DECLARE_CSR(vstimecmph, CSR_VSTIMECMPH)
+DECLARE_CSR(hedelegh, CSR_HEDELEGH)
DECLARE_CSR(htimedeltah, CSR_HTIMEDELTAH)
DECLARE_CSR(hidelegh, CSR_HIDELEGH)
DECLARE_CSR(hvienh, CSR_HVIENH)
@@ -4469,13 +4472,14 @@ DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD)
DECLARE_CAUSE("load access", CAUSE_LOAD_ACCESS)
DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE)
DECLARE_CAUSE("store access", CAUSE_STORE_ACCESS)
-DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL)
-DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL)
-DECLARE_CAUSE("virtual_supervisor_ecall", CAUSE_VIRTUAL_SUPERVISOR_ECALL)
-DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL)
+DECLARE_CAUSE("user ecall", CAUSE_USER_ECALL)
+DECLARE_CAUSE("supervisor ecall", CAUSE_SUPERVISOR_ECALL)
+DECLARE_CAUSE("virtual supervisor ecall", CAUSE_VIRTUAL_SUPERVISOR_ECALL)
+DECLARE_CAUSE("machine ecall", CAUSE_MACHINE_ECALL)
DECLARE_CAUSE("fetch page fault", CAUSE_FETCH_PAGE_FAULT)
DECLARE_CAUSE("load page fault", CAUSE_LOAD_PAGE_FAULT)
DECLARE_CAUSE("store page fault", CAUSE_STORE_PAGE_FAULT)
+DECLARE_CAUSE("double trap", CAUSE_DOUBLE_TRAP)
DECLARE_CAUSE("software check fault", CAUSE_SOFTWARE_CHECK_FAULT)
DECLARE_CAUSE("hardware error fault", CAUSE_HARDWARE_ERROR_FAULT)
DECLARE_CAUSE("fetch guest page fault", CAUSE_FETCH_GUEST_PAGE_FAULT)
diff --git a/riscv/entropy_source.h b/riscv/entropy_source.h
index 148e6b0..64e12a1 100644
--- a/riscv/entropy_source.h
+++ b/riscv/entropy_source.h
@@ -1,3 +1,7 @@
+// See LICENSE for license details.
+
+#ifndef _RISCV_ENTROPY_SOURCE_H
+#define _RISCV_ENTROPY_SOURCE_H
#include <fstream>
#include <iostream>
@@ -116,3 +120,4 @@ public:
};
+#endif
diff --git a/riscv/execute.cc b/riscv/execute.cc
index f263dce..1b572a7 100644
--- a/riscv/execute.cc
+++ b/riscv/execute.cc
@@ -40,13 +40,12 @@ static void commit_log_print_value(FILE *log_file, int width, const void *data)
fprintf(log_file, "0x%016" PRIx64, *(const uint64_t *)data);
break;
default:
- // max lengh of vector
- if (((width - 1) & width) == 0) {
- const uint64_t *arr = (const uint64_t *)data;
+ if (width % 8 == 0) {
+ const uint8_t *arr = (const uint8_t *)data;
fprintf(log_file, "0x");
- for (int idx = width / 64 - 1; idx >= 0; --idx) {
- fprintf(log_file, "%016" PRIx64, arr[idx]);
+ for (int idx = width / 8 - 1; idx >= 0; --idx) {
+ fprintf(log_file, "%02" PRIx8, arr[idx]);
}
} else {
abort();
@@ -202,7 +201,7 @@ static inline reg_t execute_insn_logged(processor_t* p, reg_t pc, insn_fetch_t f
return npc;
}
-bool processor_t::slow_path()
+bool processor_t::slow_path() const
{
return debug || state.single_step != state.STEP_NONE || state.debug_mode ||
log_commits_enabled || histogram_enabled || in_wfi || check_triggers_icount;
@@ -211,21 +210,31 @@ bool processor_t::slow_path()
// fetch/decode/execute loop
void processor_t::step(size_t n)
{
+ mmu_t* _mmu = mmu;
+
if (!state.debug_mode) {
if (halt_request == HR_REGULAR) {
- enter_debug_mode(DCSR_CAUSE_DEBUGINT);
+ enter_debug_mode(DCSR_CAUSE_DEBUGINT, 0);
} else if (halt_request == HR_GROUP) {
- enter_debug_mode(DCSR_CAUSE_GROUP);
- } // !!!The halt bit in DCSR is deprecated.
- else if (state.dcsr->halt) {
- enter_debug_mode(DCSR_CAUSE_HALT);
+ enter_debug_mode(DCSR_CAUSE_GROUP, 0);
+ } else if (halt_on_reset) {
+ halt_on_reset = false;
+ enter_debug_mode(DCSR_CAUSE_HALT, 0);
+ }
+ }
+
+ if (extension_enabled(EXT_ZICCID)) {
+ // Ziccid requires stores eventually become visible to instruction fetch,
+ // so periodically flush the I$
+ if (ziccid_flush_count-- == 0) {
+ ziccid_flush_count += ZICCID_FLUSH_PERIOD;
+ _mmu->flush_icache();
}
}
while (n > 0) {
size_t instret = 0;
reg_t pc = state.pc;
- mmu_t* _mmu = mmu;
state.prv_changed = false;
state.v_changed = false;
@@ -257,7 +266,7 @@ void processor_t::step(size_t n)
if (unlikely(!state.serialized && state.single_step == state.STEP_STEPPED)) {
state.single_step = state.STEP_NONE;
if (!state.debug_mode) {
- enter_debug_mode(DCSR_CAUSE_STEP);
+ enter_debug_mode(DCSR_CAUSE_STEP, 0);
// enter_debug_mode changed state.pc, so we can't just continue.
break;
}
@@ -286,6 +295,17 @@ void processor_t::step(size_t n)
disasm(fetch.insn);
pc = execute_insn_logged(this, pc, fetch);
advance_pc();
+
+ // Resume from debug mode in critical error
+ if (state.critical_error && !state.debug_mode) {
+ if (state.dcsr->read() & DCSR_CETRIG) {
+ enter_debug_mode(DCSR_CAUSE_EXTCAUSE, DCSR_EXTCAUSE_CRITERR);
+ } else {
+ // Handling of critical error is implementation defined
+ // For now just enter debug mode
+ enter_debug_mode(DCSR_CAUSE_HALT, 0);
+ }
+ }
}
}
else while (instret < n)
@@ -311,26 +331,32 @@ void processor_t::step(size_t n)
take_trap(t, pc);
n = instret;
+ // If critical error then enter debug mode critical error trigger enabled
+ if (state.critical_error) {
+ if (state.dcsr->read() & DCSR_CETRIG) {
+ enter_debug_mode(DCSR_CAUSE_EXTCAUSE, DCSR_EXTCAUSE_CRITERR);
+ } else {
+ // Handling of critical error is implementation defined
+ // For now just enter debug mode
+ enter_debug_mode(DCSR_CAUSE_HALT, 0);
+ }
+ }
// Trigger action takes priority over single step
auto match = TM.detect_trap_match(t);
if (match.has_value())
take_trigger_action(match->action, 0, state.pc, 0);
else if (unlikely(state.single_step == state.STEP_STEPPED)) {
state.single_step = state.STEP_NONE;
- enter_debug_mode(DCSR_CAUSE_STEP);
+ enter_debug_mode(DCSR_CAUSE_STEP, 0);
}
}
catch (triggers::matched_t& t)
{
- if (mmu->matched_trigger) {
- delete mmu->matched_trigger;
- mmu->matched_trigger = NULL;
- }
take_trigger_action(t.action, t.address, pc, t.gva);
}
catch(trap_debug_mode&)
{
- enter_debug_mode(DCSR_CAUSE_SWBP);
+ enter_debug_mode(DCSR_CAUSE_SWBP, 0);
}
catch (wait_for_interrupt_t &t)
{
@@ -344,10 +370,10 @@ void processor_t::step(size_t n)
in_wfi = true;
}
- state.minstret->bump(instret);
+ state.minstret->bump((state.mcountinhibit->read() & MCOUNTINHIBIT_IR) ? 0 : instret);
// Model a hart whose CPI is 1.
- state.mcycle->bump(instret);
+ state.mcycle->bump((state.mcountinhibit->read() & MCOUNTINHIBIT_CY) ? 0 : instret);
n -= instret;
}
diff --git a/riscv/extension.cc b/riscv/extension.cc
index 520c2ed..195eea1 100644
--- a/riscv/extension.cc
+++ b/riscv/extension.cc
@@ -3,21 +3,15 @@
#include "extension.h"
#include "trap.h"
-extension_t::~extension_t()
-{
-}
-
-void extension_t::illegal_instruction()
+void extension_t::illegal_instruction([[maybe_unused]] processor_t &proc)
{
throw trap_illegal_instruction(0);
}
-void extension_t::raise_interrupt()
+void extension_t::raise_interrupt([[maybe_unused]] processor_t &proc)
{
- p->take_interrupt((reg_t)1 << IRQ_COP); // must not return
+ proc.take_interrupt((reg_t)1 << IRQ_COP); // must not return
throw std::logic_error("a COP exception was posted, but interrupts are disabled!");
}
-void extension_t::clear_interrupt()
-{
-}
+void extension_t::clear_interrupt([[maybe_unused]] processor_t &proc) {}
diff --git a/riscv/extension.h b/riscv/extension.h
index de6ece3..411e65b 100644
--- a/riscv/extension.h
+++ b/riscv/extension.h
@@ -11,20 +11,18 @@
class extension_t
{
public:
- virtual std::vector<insn_desc_t> get_instructions() = 0;
- virtual std::vector<disasm_insn_t*> get_disasms() = 0;
- virtual const char* name() = 0;
- virtual void reset() {};
- virtual void set_debug(bool UNUSED value) {}
- virtual ~extension_t();
+ virtual std::vector<insn_desc_t> get_instructions(const processor_t &proc) = 0;
+ virtual std::vector<disasm_insn_t*> get_disasms(const processor_t *proc = nullptr) = 0;
+ virtual std::vector<csr_t_p> get_csrs(processor_t &) const { return {}; };
+ virtual const char* name() const = 0;
+ virtual void reset(processor_t &) {};
+ virtual void set_debug(bool UNUSED value, const processor_t &) {}
+ virtual ~extension_t() = default;
- void set_processor(processor_t* _p) { p = _p; }
protected:
- processor_t* p;
-
- void illegal_instruction();
- void raise_interrupt();
- void clear_interrupt();
+ void illegal_instruction(processor_t &proc);
+ void raise_interrupt(processor_t &proc);
+ void clear_interrupt(processor_t &proc);
};
std::function<extension_t*()> find_extension(const char* name);
diff --git a/riscv/insn_template.cc b/riscv/insn_template.cc
index 9194d19..168e2dc 100644
--- a/riscv/insn_template.cc
+++ b/riscv/insn_template.cc
@@ -5,24 +5,29 @@
#define DECODE_MACRO_USAGE_LOGGED 0
+#define PROLOGUE \
+ reg_t npc = sext_xlen(pc + insn_length(OPCODE))
+
+#define EPILOGUE \
+ trace_opcode(p, OPCODE, insn); \
+ return npc
+
reg_t fast_rv32i_NAME(processor_t* p, insn_t insn, reg_t pc)
{
#define xlen 32
- reg_t npc = sext_xlen(pc + insn_length(OPCODE));
+ PROLOGUE;
#include "insns/NAME.h"
- trace_opcode(p, OPCODE, insn);
+ EPILOGUE;
#undef xlen
- return npc;
}
reg_t fast_rv64i_NAME(processor_t* p, insn_t insn, reg_t pc)
{
#define xlen 64
- reg_t npc = sext_xlen(pc + insn_length(OPCODE));
+ PROLOGUE;
#include "insns/NAME.h"
- trace_opcode(p, OPCODE, insn);
+ EPILOGUE;
#undef xlen
- return npc;
}
#undef DECODE_MACRO_USAGE_LOGGED
@@ -31,21 +36,19 @@ reg_t fast_rv64i_NAME(processor_t* p, insn_t insn, reg_t pc)
reg_t logged_rv32i_NAME(processor_t* p, insn_t insn, reg_t pc)
{
#define xlen 32
- reg_t npc = sext_xlen(pc + insn_length(OPCODE));
+ PROLOGUE;
#include "insns/NAME.h"
- trace_opcode(p, OPCODE, insn);
+ EPILOGUE;
#undef xlen
- return npc;
}
reg_t logged_rv64i_NAME(processor_t* p, insn_t insn, reg_t pc)
{
#define xlen 64
- reg_t npc = sext_xlen(pc + insn_length(OPCODE));
+ PROLOGUE;
#include "insns/NAME.h"
- trace_opcode(p, OPCODE, insn);
+ EPILOGUE;
#undef xlen
- return npc;
}
#undef CHECK_REG
@@ -57,21 +60,19 @@ reg_t logged_rv64i_NAME(processor_t* p, insn_t insn, reg_t pc)
reg_t fast_rv32e_NAME(processor_t* p, insn_t insn, reg_t pc)
{
#define xlen 32
- reg_t npc = sext_xlen(pc + insn_length(OPCODE));
+ PROLOGUE;
#include "insns/NAME.h"
- trace_opcode(p, OPCODE, insn);
+ EPILOGUE;
#undef xlen
- return npc;
}
reg_t fast_rv64e_NAME(processor_t* p, insn_t insn, reg_t pc)
{
#define xlen 64
- reg_t npc = sext_xlen(pc + insn_length(OPCODE));
+ PROLOGUE;
#include "insns/NAME.h"
- trace_opcode(p, OPCODE, insn);
+ EPILOGUE;
#undef xlen
- return npc;
}
#undef DECODE_MACRO_USAGE_LOGGED
@@ -80,19 +81,17 @@ reg_t fast_rv64e_NAME(processor_t* p, insn_t insn, reg_t pc)
reg_t logged_rv32e_NAME(processor_t* p, insn_t insn, reg_t pc)
{
#define xlen 32
- reg_t npc = sext_xlen(pc + insn_length(OPCODE));
+ PROLOGUE;
#include "insns/NAME.h"
- trace_opcode(p, OPCODE, insn);
+ EPILOGUE;
#undef xlen
- return npc;
}
reg_t logged_rv64e_NAME(processor_t* p, insn_t insn, reg_t pc)
{
#define xlen 64
- reg_t npc = sext_xlen(pc + insn_length(OPCODE));
+ PROLOGUE;
#include "insns/NAME.h"
- trace_opcode(p, OPCODE, insn);
+ EPILOGUE;
#undef xlen
- return npc;
}
diff --git a/riscv/insns/bclri.h b/riscv/insns/bclri.h
index 8df6a5f..7ab4250 100644
--- a/riscv/insns/bclri.h
+++ b/riscv/insns/bclri.h
@@ -1,3 +1,4 @@
require_extension(EXT_ZBS);
+require(SHAMT < xlen);
int shamt = SHAMT & (xlen-1);
WRITE_RD(sext_xlen(RS1 & ~(1LL << shamt)));
diff --git a/riscv/insns/bexti.h b/riscv/insns/bexti.h
index 31d2316..bf86ab4 100644
--- a/riscv/insns/bexti.h
+++ b/riscv/insns/bexti.h
@@ -1,3 +1,4 @@
require_extension(EXT_ZBS);
+require(SHAMT < xlen);
int shamt = SHAMT & (xlen-1);
WRITE_RD(sext_xlen(1 & (RS1 >> shamt)));
diff --git a/riscv/insns/binvi.h b/riscv/insns/binvi.h
index 3272d39..7f6723c 100644
--- a/riscv/insns/binvi.h
+++ b/riscv/insns/binvi.h
@@ -1,3 +1,4 @@
require_extension(EXT_ZBS);
+require(SHAMT < xlen);
int shamt = SHAMT & (xlen-1);
WRITE_RD(sext_xlen(RS1 ^ (1LL << shamt)));
diff --git a/riscv/insns/bseti.h b/riscv/insns/bseti.h
index 4952378..8ef4b37 100644
--- a/riscv/insns/bseti.h
+++ b/riscv/insns/bseti.h
@@ -1,3 +1,4 @@
require_extension(EXT_ZBS);
+require(SHAMT < xlen);
int shamt = SHAMT & (xlen-1);
WRITE_RD(sext_xlen(RS1 | (1LL << shamt)));
diff --git a/riscv/insns/c_ld.h b/riscv/insns/c_ld.h
index 18e0d5e..951243c 100644
--- a/riscv/insns/c_ld.h
+++ b/riscv/insns/c_ld.h
@@ -1,5 +1,5 @@
require_extension(EXT_ZCA);
-require((xlen == 64) || p->extension_enabled(EXT_ZCMLSD));
+require((xlen == 64) || p->extension_enabled(EXT_ZCLSD));
if (xlen == 32) {
WRITE_RVC_RS2S_PAIR(MMU.load<int64_t>(RVC_RS1S + insn.rvc_ld_imm()));
diff --git a/riscv/insns/c_ldsp.h b/riscv/insns/c_ldsp.h
index d8c8ec8..9f44fec 100644
--- a/riscv/insns/c_ldsp.h
+++ b/riscv/insns/c_ldsp.h
@@ -1,5 +1,5 @@
require_extension(EXT_ZCA);
-require((xlen == 64) || p->extension_enabled(EXT_ZCMLSD));
+require((xlen == 64) || p->extension_enabled(EXT_ZCLSD));
require(insn.rvc_rd() != 0);
if (xlen == 32) {
diff --git a/riscv/insns/c_sd.h b/riscv/insns/c_sd.h
index dba9b07..860e2de 100644
--- a/riscv/insns/c_sd.h
+++ b/riscv/insns/c_sd.h
@@ -1,5 +1,5 @@
require_extension(EXT_ZCA);
-require((xlen == 64) || p->extension_enabled(EXT_ZCMLSD));
+require((xlen == 64) || p->extension_enabled(EXT_ZCLSD));
if (xlen == 32) {
MMU.store<uint64_t>(RVC_RS1S + insn.rvc_ld_imm(), RVC_RS2S_PAIR);
diff --git a/riscv/insns/c_sdsp.h b/riscv/insns/c_sdsp.h
index e95aefa..e6b1f62 100644
--- a/riscv/insns/c_sdsp.h
+++ b/riscv/insns/c_sdsp.h
@@ -1,5 +1,5 @@
require_extension(EXT_ZCA);
-require((xlen == 64) || p->extension_enabled(EXT_ZCMLSD));
+require((xlen == 64) || p->extension_enabled(EXT_ZCLSD));
if (xlen == 32) {
MMU.store<uint64_t>(RVC_SP + insn.rvc_sdsp_imm(), RVC_RS2_PAIR);
diff --git a/riscv/insns/dret.h b/riscv/insns/dret.h
index bdcf3db..0f94f88 100644
--- a/riscv/insns/dret.h
+++ b/riscv/insns/dret.h
@@ -4,8 +4,22 @@ if (ZICFILP_xLPE(STATE.dcsr->v, STATE.dcsr->prv)) {
STATE.elp = STATE.dcsr->pelp;
}
p->set_privilege(STATE.dcsr->prv, STATE.dcsr->v);
-if (STATE.prv < PRV_M)
+if (STATE.prv < PRV_M) {
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MPRV);
+ STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MDT);
+}
+
+if (STATE.dcsr->prv == PRV_U || STATE.dcsr->v)
+ STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_SDT);
+
+if (STATE.dcsr->v && STATE.dcsr->prv == PRV_U)
+ STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT);
+
+if (STATE.dcsr->prv == PRV_U || STATE.dcsr->v)
+ STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_SDT);
+
+if (STATE.dcsr->v && STATE.dcsr->prv == PRV_U)
+ STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT);
/* We're not in Debug Mode anymore. */
STATE.debug_mode = false;
diff --git a/riscv/insns/fcvtmod_w_d.h b/riscv/insns/fcvtmod_w_d.h
index e39400d..231f605 100644
--- a/riscv/insns/fcvtmod_w_d.h
+++ b/riscv/insns/fcvtmod_w_d.h
@@ -55,6 +55,5 @@ if (exp == 0) {
}
WRITE_RD(sext32(frac));
-STATE.fflags->write(STATE.fflags->read() |
- (inexact ? softfloat_flag_inexact : 0) |
+raise_fp_exceptions((inexact ? softfloat_flag_inexact : 0) |
(invalid ? softfloat_flag_invalid : 0));
diff --git a/riscv/insns/jal.h b/riscv/insns/jal.h
index cd59964..e7a75c7 100644
--- a/riscv/insns/jal.h
+++ b/riscv/insns/jal.h
@@ -1,3 +1,4 @@
+CHECK_RD();
reg_t tmp = npc;
set_pc(JUMP_TARGET);
WRITE_RD(tmp);
diff --git a/riscv/insns/jalr.h b/riscv/insns/jalr.h
index 0606f67..de84e89 100644
--- a/riscv/insns/jalr.h
+++ b/riscv/insns/jalr.h
@@ -1,3 +1,4 @@
+CHECK_RD();
reg_t tmp = npc;
set_pc((RS1 + insn.i_imm()) & ~reg_t(1));
WRITE_RD(tmp);
diff --git a/riscv/insns/mnret.h b/riscv/insns/mnret.h
index 30f1081..2003cbe 100644
--- a/riscv/insns/mnret.h
+++ b/riscv/insns/mnret.h
@@ -10,5 +10,11 @@ if (prev_prv != PRV_M) {
STATE.mstatus->write(mstatus);
}
s = set_field(s, MNSTATUS_NMIE, 1);
+if (ZICFILP_xLPE(prev_virt, prev_prv)) {
+ STATE.elp = static_cast<elp_t>(get_field(s, MNSTATUS_MNPELP));
+}
+if (p->extension_enabled(EXT_ZICFILP)) {
+ s = set_field(s, MNSTATUS_MNPELP, elp_t::NO_LP_EXPECTED);
+}
STATE.mnstatus->write(s);
p->set_privilege(prev_prv, prev_virt);
diff --git a/riscv/insns/mret.h b/riscv/insns/mret.h
index 3fe920c..479bfca 100644
--- a/riscv/insns/mret.h
+++ b/riscv/insns/mret.h
@@ -13,7 +13,12 @@ if (ZICFILP_xLPE(prev_virt, prev_prv)) {
STATE.elp = static_cast<elp_t>(get_field(s, MSTATUS_MPELP));
}
s = set_field(s, MSTATUS_MPELP, elp_t::NO_LP_EXPECTED);
+s = set_field(s, MSTATUS_MDT, 0);
+if (prev_prv == PRV_U || (prev_virt && prev_prv != PRV_M))
+ s = set_field(s, MSTATUS_SDT, 0);
+if (prev_virt && prev_prv == PRV_U)
+ STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT);
STATE.mstatus->write(s);
if (STATE.mstatush) STATE.mstatush->write(s >> 32); // log mstatush change
-STATE.tcontrol->write((STATE.tcontrol->read() & CSR_TCONTROL_MPTE) ? (CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE) : 0);
+if (STATE.tcontrol) STATE.tcontrol->write((STATE.tcontrol->read() & CSR_TCONTROL_MPTE) ? (CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE) : 0);
p->set_privilege(prev_prv, prev_virt);
diff --git a/riscv/insns/sret.h b/riscv/insns/sret.h
index 23a13b5..efb4fa6 100644
--- a/riscv/insns/sret.h
+++ b/riscv/insns/sret.h
@@ -26,6 +26,22 @@ if (!STATE.v) {
if (ZICFILP_xLPE(prev_virt, prev_prv)) {
STATE.elp = static_cast<elp_t>(get_field(s, SSTATUS_SPELP));
}
+
+if (STATE.prv == PRV_M) {
+ STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MDT);
+ if (prev_prv == PRV_U || prev_virt)
+ STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_SDT);
+ if (prev_virt && prev_prv == PRV_U)
+ STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT);
+}
+
s = set_field(s, SSTATUS_SPELP, elp_t::NO_LP_EXPECTED);
+
+if (STATE.prv == PRV_S) {
+ s = set_field(s, SSTATUS_SDT, 0);
+ if (!STATE.v && prev_virt && prev_prv == PRV_U)
+ STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT);
+}
+
STATE.sstatus->write(s);
p->set_privilege(prev_prv, prev_virt);
diff --git a/riscv/insns/ssrdp.h b/riscv/insns/ssrdp.h
index 20b0856..bf20504 100644
--- a/riscv/insns/ssrdp.h
+++ b/riscv/insns/ssrdp.h
@@ -1,7 +1,7 @@
#include "zicfiss.h"
if (xSSE()) {
- WRITE_RD(STATE.ssp->read());
+ WRITE_RD(sext_xlen(STATE.ssp->read()));
} else {
#include "mop_r_N.h"
}
diff --git a/riscv/insns/vcompress_vm.h b/riscv/insns/vcompress_vm.h
index d35b8ba..6624d8b 100644
--- a/riscv/insns/vcompress_vm.h
+++ b/riscv/insns/vcompress_vm.h
@@ -1,4 +1,5 @@
// vcompress vd, vs2, vs1
+require(P.any_vector_extensions());
require(P.VU.vstart->read() == 0);
require_align(insn.rd(), P.VU.vflmul);
require_align(insn.rs2(), P.VU.vflmul);
@@ -8,11 +9,7 @@ require_noover(insn.rd(), P.VU.vflmul, insn.rs1(), 1);
reg_t pos = 0;
VI_GENERAL_LOOP_BASE
- const int midx = i / 64;
- const int mpos = i % 64;
-
- bool do_mask = (P.VU.elt<uint64_t>(rs1_num, midx) >> mpos) & 0x1;
- if (do_mask) {
+ if (P.VU.mask_elt(rs1_num, i)) {
switch (sew) {
case e8:
P.VU.elt<uint8_t>(rd_num, pos, true) = P.VU.elt<uint8_t>(rs2_num, i);
diff --git a/riscv/insns/vcpop_m.h b/riscv/insns/vcpop_m.h
index f909311..26a1276 100644
--- a/riscv/insns/vcpop_m.h
+++ b/riscv/insns/vcpop_m.h
@@ -6,15 +6,7 @@ reg_t rs2_num = insn.rs2();
require(P.VU.vstart->read() == 0);
reg_t popcount = 0;
for (reg_t i=P.VU.vstart->read(); i<vl; ++i) {
- const int midx = i / 32;
- const int mpos = i % 32;
-
- bool vs2_lsb = ((P.VU.elt<uint32_t>(rs2_num, midx ) >> mpos) & 0x1) == 1;
- if (insn.v_vm() == 1) {
- popcount += vs2_lsb;
- } else {
- bool do_mask = (P.VU.elt<uint32_t>(0, midx) >> mpos) & 0x1;
- popcount += (vs2_lsb && do_mask);
- }
+ bool vs2_bit = P.VU.mask_elt(rs2_num, i);
+ popcount += vs2_bit && (insn.v_vm() || P.VU.mask_elt(0, i));
}
WRITE_RD(popcount);
diff --git a/riscv/insns/vfirst_m.h b/riscv/insns/vfirst_m.h
index a130e5d..e3f5263 100644
--- a/riscv/insns/vfirst_m.h
+++ b/riscv/insns/vfirst_m.h
@@ -8,8 +8,7 @@ reg_t pos = -1;
for (reg_t i=P.VU.vstart->read(); i < vl; ++i) {
VI_LOOP_ELEMENT_SKIP()
- bool vs2_lsb = ((P.VU.elt<uint64_t>(rs2_num, midx ) >> mpos) & 0x1) == 1;
- if (vs2_lsb) {
+ if (P.VU.mask_elt(rs2_num, i)) {
pos = i;
break;
}
diff --git a/riscv/insns/vfrsqrt7_v.h b/riscv/insns/vfrsqrt7_v.h
index a073764..2505639 100644
--- a/riscv/insns/vfrsqrt7_v.h
+++ b/riscv/insns/vfrsqrt7_v.h
@@ -1,4 +1,4 @@
-// vfclass.v vd, vs2, vm
+// vfrsqrt7.v vd, vs2, vm
VI_VFP_V_LOOP
({
vd = f16_rsqrte7(vs2);
diff --git a/riscv/insns/vghsh_vv.h b/riscv/insns/vghsh_vv.h
index bcbfe74..728678c 100644
--- a/riscv/insns/vghsh_vv.h
+++ b/riscv/insns/vghsh_vv.h
@@ -2,9 +2,13 @@
#include "zvk_ext_macros.h"
+const uint32_t EGS = 4;
+
require_zvkg;
require(P.VU.vsew == 32);
require_egw_fits(128);
+require(P.VU.vl->read() % EGS == 0);
+VI_CHECK_SSS(true)
VI_ZVK_VD_VS1_VS2_EGU32x4_NOVM_LOOP(
{},
diff --git a/riscv/insns/vgmul_vv.h b/riscv/insns/vgmul_vv.h
index 820b396..0d223e8 100644
--- a/riscv/insns/vgmul_vv.h
+++ b/riscv/insns/vgmul_vv.h
@@ -2,9 +2,13 @@
#include "zvk_ext_macros.h"
+const uint32_t EGS = 4;
+
require_zvkg;
require(P.VU.vsew == 32);
require_egw_fits(128);
+require(P.VU.vl->read() % EGS == 0);
+VI_CHECK_SSS(false)
VI_ZVK_VD_VS2_EGU32x4_NOVM_LOOP(
{},
diff --git a/riscv/insns/viota_m.h b/riscv/insns/viota_m.h
index 1ee9229..00155db 100644
--- a/riscv/insns/viota_m.h
+++ b/riscv/insns/viota_m.h
@@ -12,36 +12,31 @@ require_noover(rd_num, P.VU.vflmul, rs2_num, 1);
int cnt = 0;
for (reg_t i = 0; i < vl; ++i) {
- const int midx = i / 64;
- const int mpos = i % 64;
-
- bool vs2_lsb = ((P.VU.elt<uint64_t>(rs2_num, midx) >> mpos) & 0x1) == 1;
- bool do_mask = (P.VU.elt<uint64_t>(0, midx) >> mpos) & 0x1;
+ bool do_mask = P.VU.mask_elt(0, i);
bool has_one = false;
if (insn.v_vm() == 1 || (insn.v_vm() == 0 && do_mask)) {
- if (vs2_lsb) {
+ if (P.VU.mask_elt(rs2_num, i)) {
has_one = true;
}
}
- bool use_ori = (insn.v_vm() == 0) && !do_mask;
+ // Bypass masked-off elements
+ if ((insn.v_vm() == 0) && !do_mask)
+ continue;
+
switch (sew) {
case e8:
- P.VU.elt<uint8_t>(rd_num, i, true) = use_ori ?
- P.VU.elt<uint8_t>(rd_num, i) : cnt;
+ P.VU.elt<uint8_t>(rd_num, i, true) = cnt;
break;
case e16:
- P.VU.elt<uint16_t>(rd_num, i, true) = use_ori ?
- P.VU.elt<uint16_t>(rd_num, i) : cnt;
+ P.VU.elt<uint16_t>(rd_num, i, true) = cnt;
break;
case e32:
- P.VU.elt<uint32_t>(rd_num, i, true) = use_ori ?
- P.VU.elt<uint32_t>(rd_num, i) : cnt;
+ P.VU.elt<uint32_t>(rd_num, i, true) = cnt;
break;
default:
- P.VU.elt<uint64_t>(rd_num, i, true) = use_ori ?
- P.VU.elt<uint64_t>(rd_num, i) : cnt;
+ P.VU.elt<uint64_t>(rd_num, i, true) = cnt;
break;
}
diff --git a/riscv/insns/vmandn_mm.h b/riscv/insns/vmandn_mm.h
index e9a87cf..49129f7 100644
--- a/riscv/insns/vmandn_mm.h
+++ b/riscv/insns/vmandn_mm.h
@@ -1,2 +1,2 @@
// vmandn.mm vd, vs2, vs1
-VI_LOOP_MASK(vs2 & ~vs1);
+VI_LOOP_MASK(vs2 & !vs1);
diff --git a/riscv/insns/vmnand_mm.h b/riscv/insns/vmnand_mm.h
index 5a3ab09..4659e2f 100644
--- a/riscv/insns/vmnand_mm.h
+++ b/riscv/insns/vmnand_mm.h
@@ -1,2 +1,2 @@
// vmnand.mm vd, vs2, vs1
-VI_LOOP_MASK(~(vs2 & vs1));
+VI_LOOP_MASK(!(vs2 & vs1));
diff --git a/riscv/insns/vmnor_mm.h b/riscv/insns/vmnor_mm.h
index ab93378..37327c0 100644
--- a/riscv/insns/vmnor_mm.h
+++ b/riscv/insns/vmnor_mm.h
@@ -1,2 +1,2 @@
// vmnor.mm vd, vs2, vs1
-VI_LOOP_MASK(~(vs2 | vs1));
+VI_LOOP_MASK(!(vs2 | vs1));
diff --git a/riscv/insns/vmorn_mm.h b/riscv/insns/vmorn_mm.h
index 23026f5..71acc05 100644
--- a/riscv/insns/vmorn_mm.h
+++ b/riscv/insns/vmorn_mm.h
@@ -1,2 +1,2 @@
// vmorn.mm vd, vs2, vs1
-VI_LOOP_MASK(vs2 | ~vs1);
+VI_LOOP_MASK(vs2 | !vs1);
diff --git a/riscv/insns/vmsbf_m.h b/riscv/insns/vmsbf_m.h
index 1275872..3f736e0 100644
--- a/riscv/insns/vmsbf_m.h
+++ b/riscv/insns/vmsbf_m.h
@@ -11,22 +11,17 @@ reg_t rs2_num = insn.rs2();
bool has_one = false;
for (reg_t i = P.VU.vstart->read(); i < vl; ++i) {
- const int midx = i / 64;
- const int mpos = i % 64;
- const uint64_t mmask = UINT64_C(1) << mpos; \
-
- bool vs2_lsb = ((P.VU.elt<uint64_t>(rs2_num, midx) >> mpos) & 0x1) == 1;
- bool do_mask = (P.VU.elt<uint64_t>(0, midx) >> mpos) & 0x1;
-
+ bool vs2_lsb = P.VU.mask_elt(rs2_num, i);
+ bool do_mask = P.VU.mask_elt(0, i);
if (insn.v_vm() == 1 || (insn.v_vm() == 0 && do_mask)) {
- auto &vd = P.VU.elt<uint64_t>(rd_num, midx, true);
- uint64_t res = 0;
+ bool res = false;
if (!has_one && !vs2_lsb) {
- res = 1;
+ res = true;
} else if (!has_one && vs2_lsb) {
has_one = true;
}
- vd = (vd & ~mmask) | ((res << mpos) & mmask);
+
+ P.VU.set_mask_elt(rd_num, i, res);
}
}
diff --git a/riscv/insns/vmsif_m.h b/riscv/insns/vmsif_m.h
index cbcbc2a..b029327 100644
--- a/riscv/insns/vmsif_m.h
+++ b/riscv/insns/vmsif_m.h
@@ -11,22 +11,18 @@ reg_t rs2_num = insn.rs2();
bool has_one = false;
for (reg_t i = P.VU.vstart->read(); i < vl; ++i) {
- const int midx = i / 64;
- const int mpos = i % 64;
- const uint64_t mmask = UINT64_C(1) << mpos; \
-
- bool vs2_lsb = ((P.VU.elt<uint64_t>(rs2_num, midx ) >> mpos) & 0x1) == 1;
- bool do_mask = (P.VU.elt<uint64_t>(0, midx) >> mpos) & 0x1;
+ bool vs2_lsb = P.VU.mask_elt(rs2_num, i);
+ bool do_mask = P.VU.mask_elt(0, i);
if (insn.v_vm() == 1 || (insn.v_vm() == 0 && do_mask)) {
- auto &vd = P.VU.elt<uint64_t>(rd_num, midx, true);
- uint64_t res = 0;
+ bool res = false;
if (!has_one && !vs2_lsb) {
- res = 1;
+ res = true;
} else if (!has_one && vs2_lsb) {
has_one = true;
- res = 1;
+ res = true;
}
- vd = (vd & ~mmask) | ((res << mpos) & mmask);
+
+ P.VU.set_mask_elt(rd_num, i, res);
}
}
diff --git a/riscv/insns/vmsof_m.h b/riscv/insns/vmsof_m.h
index 9bd4f0c..5753dbf 100644
--- a/riscv/insns/vmsof_m.h
+++ b/riscv/insns/vmsof_m.h
@@ -11,20 +11,16 @@ reg_t rs2_num = insn.rs2();
bool has_one = false;
for (reg_t i = P.VU.vstart->read() ; i < vl; ++i) {
- const int midx = i / 64;
- const int mpos = i % 64;
- const uint64_t mmask = UINT64_C(1) << mpos; \
-
- bool vs2_lsb = ((P.VU.elt<uint64_t>(rs2_num, midx ) >> mpos) & 0x1) == 1;
- bool do_mask = (P.VU.elt<uint64_t>(0, midx) >> mpos) & 0x1;
+ bool vs2_lsb = P.VU.mask_elt(rs2_num, i);
+ bool do_mask = P.VU.mask_elt(0, i);
if (insn.v_vm() == 1 || (insn.v_vm() == 0 && do_mask)) {
- uint64_t &vd = P.VU.elt<uint64_t>(rd_num, midx, true);
- uint64_t res = 0;
+ bool res = false;
if (!has_one && vs2_lsb) {
has_one = true;
- res = 1;
+ res = true;
}
- vd = (vd & ~mmask) | ((res << mpos) & mmask);
+
+ P.VU.set_mask_elt(rd_num, i, res);
}
}
diff --git a/riscv/insns/vmulhu_vv.h b/riscv/insns/vmulhu_vv.h
index 8e318ed..0ff488c 100644
--- a/riscv/insns/vmulhu_vv.h
+++ b/riscv/insns/vmulhu_vv.h
@@ -1,4 +1,4 @@
-// vmulhu vd ,vs2, vs1
+// vmulhu vd, vs2, vs1
VI_VV_ULOOP
({
vd = ((uint128_t)vs2 * vs1) >> sew;
diff --git a/riscv/insns/vmxnor_mm.h b/riscv/insns/vmxnor_mm.h
index 0736d5b..8db61c2 100644
--- a/riscv/insns/vmxnor_mm.h
+++ b/riscv/insns/vmxnor_mm.h
@@ -1,2 +1,2 @@
// vmnxor.mm vd, vs2, vs1
-VI_LOOP_MASK(~(vs2 ^ vs1));
+VI_LOOP_MASK(!(vs2 ^ vs1));
diff --git a/riscv/insns/vnclip_wi.h b/riscv/insns/vnclip_wi.h
index ea6898c..4805173 100644
--- a/riscv/insns/vnclip_wi.h
+++ b/riscv/insns/vnclip_wi.h
@@ -1,9 +1,9 @@
// vnclip: vd[i] = clip(round(vs2[i] + rnd) >> simm)
-VRM xrm = P.VU.get_vround_mode();
-int64_t int_max = INT64_MAX >> (64 - P.VU.vsew);
-int64_t int_min = INT64_MIN >> (64 - P.VU.vsew);
VI_VI_LOOP_NARROW
({
+ VRM xrm = P.VU.get_vround_mode();
+ int64_t int_max = INT64_MAX >> (64 - P.VU.vsew);
+ int64_t int_min = INT64_MIN >> (64 - P.VU.vsew);
int128_t result = vs2;
unsigned shift = zimm5 & ((sew * 2) - 1);
diff --git a/riscv/insns/vnclip_wv.h b/riscv/insns/vnclip_wv.h
index 63b84c6..1f7558a 100644
--- a/riscv/insns/vnclip_wv.h
+++ b/riscv/insns/vnclip_wv.h
@@ -1,9 +1,9 @@
// vnclip: vd[i] = clip(round(vs2[i] + rnd) >> vs1[i])
-VRM xrm = P.VU.get_vround_mode();
-int64_t int_max = INT64_MAX >> (64 - P.VU.vsew);
-int64_t int_min = INT64_MIN >> (64 - P.VU.vsew);
VI_VV_LOOP_NARROW
({
+ VRM xrm = P.VU.get_vround_mode();
+ int64_t int_max = INT64_MAX >> (64 - P.VU.vsew);
+ int64_t int_min = INT64_MIN >> (64 - P.VU.vsew);
int128_t result = vs2;
unsigned shift = vs1 & ((sew * 2) - 1);
diff --git a/riscv/insns/vnclip_wx.h b/riscv/insns/vnclip_wx.h
index 482eace..fffebaf 100644
--- a/riscv/insns/vnclip_wx.h
+++ b/riscv/insns/vnclip_wx.h
@@ -1,9 +1,9 @@
// vnclip: vd[i] = clip(round(vs2[i] + rnd) >> rs1[i])
-VRM xrm = P.VU.get_vround_mode();
-int64_t int_max = INT64_MAX >> (64 - P.VU.vsew);
-int64_t int_min = INT64_MIN >> (64 - P.VU.vsew);
VI_VX_LOOP_NARROW
({
+ VRM xrm = P.VU.get_vround_mode();
+ int64_t int_max = INT64_MAX >> (64 - P.VU.vsew);
+ int64_t int_min = INT64_MIN >> (64 - P.VU.vsew);
int128_t result = vs2;
unsigned shift = rs1 & ((sew * 2) - 1);
diff --git a/riscv/insns/vnclipu_wi.h b/riscv/insns/vnclipu_wi.h
index 441a3a7..10735ba 100644
--- a/riscv/insns/vnclipu_wi.h
+++ b/riscv/insns/vnclipu_wi.h
@@ -1,9 +1,9 @@
// vnclipu: vd[i] = clip(round(vs2[i] + rnd) >> simm)
-VRM xrm = P.VU.get_vround_mode();
-uint64_t uint_max = UINT64_MAX >> (64 - P.VU.vsew);
-uint64_t sign_mask = UINT64_MAX << P.VU.vsew;
VI_VI_LOOP_NARROW
({
+ VRM xrm = P.VU.get_vround_mode();
+ uint64_t uint_max = UINT64_MAX >> (64 - P.VU.vsew);
+ uint64_t sign_mask = UINT64_MAX << P.VU.vsew;
uint128_t result = vs2_u;
unsigned shift = zimm5 & ((sew * 2) - 1);
diff --git a/riscv/insns/vnclipu_wv.h b/riscv/insns/vnclipu_wv.h
index 8072489..0e3e8b0 100644
--- a/riscv/insns/vnclipu_wv.h
+++ b/riscv/insns/vnclipu_wv.h
@@ -1,9 +1,9 @@
// vnclipu: vd[i] = clip(round(vs2[i] + rnd) >> vs1[i])
-VRM xrm = P.VU.get_vround_mode();
-uint64_t uint_max = UINT64_MAX >> (64 - P.VU.vsew);
-uint64_t sign_mask = UINT64_MAX << P.VU.vsew;
VI_VV_LOOP_NARROW
({
+ VRM xrm = P.VU.get_vround_mode();
+ uint64_t uint_max = UINT64_MAX >> (64 - P.VU.vsew);
+ uint64_t sign_mask = UINT64_MAX << P.VU.vsew;
uint128_t result = vs2_u;
unsigned shift = vs1 & ((sew * 2) - 1);
diff --git a/riscv/insns/vnclipu_wx.h b/riscv/insns/vnclipu_wx.h
index b2d91c3..d7c6bea 100644
--- a/riscv/insns/vnclipu_wx.h
+++ b/riscv/insns/vnclipu_wx.h
@@ -1,9 +1,9 @@
// vnclipu: vd[i] = clip(round(vs2[i] + rnd) >> rs1[i])
-VRM xrm = P.VU.get_vround_mode();
-uint64_t uint_max = UINT64_MAX >> (64 - P.VU.vsew);
-uint64_t sign_mask = UINT64_MAX << P.VU.vsew;
VI_VX_LOOP_NARROW
({
+ VRM xrm = P.VU.get_vround_mode();
+ uint64_t uint_max = UINT64_MAX >> (64 - P.VU.vsew);
+ uint64_t sign_mask = UINT64_MAX << P.VU.vsew;
uint128_t result = vs2_u;
unsigned shift = rs1 & ((sew * 2) - 1);
diff --git a/riscv/insns/vnsra_wi.h b/riscv/insns/vnsra_wi.h
index 0502ff1..ec7f637 100644
--- a/riscv/insns/vnsra_wi.h
+++ b/riscv/insns/vnsra_wi.h
@@ -1,5 +1,5 @@
// vnsra.vi vd, vs2, zimm5
VI_VI_LOOP_NSHIFT
({
- vd = vs2 >> (zimm5 & (sew * 2 - 1) & 0x1f);
+ vd = vs2 >> (zimm5 & (sew * 2 - 1));
})
diff --git a/riscv/insns/vqdot_common.h b/riscv/insns/vqdot_common.h
new file mode 100644
index 0000000..381e1a4
--- /dev/null
+++ b/riscv/insns/vqdot_common.h
@@ -0,0 +1,15 @@
+#define UNPACK_32_TO_8(IN, TYPE, OUT_ARR) \
+ int64_t OUT_ARR[4]; \
+ OUT_ARR[0] = (TYPE)((IN) & 0xff); \
+ OUT_ARR[1] = (TYPE)((IN >> 8) & 0xff); \
+ OUT_ARR[2] = (TYPE)((IN >> 16) & 0xff); \
+ OUT_ARR[3] = (TYPE)((IN >> 24) & 0xff); \
+
+#define VQDOT(IN1, IN2, TYPE1, TYPE2) \
+ UNPACK_32_TO_8(IN1, TYPE1, unpacked_vs1) \
+ UNPACK_32_TO_8(IN2, TYPE2, unpacked_vs2) \
+ uint64_t result = unpacked_vs1[0]*unpacked_vs2[0] + \
+ unpacked_vs1[1]*unpacked_vs2[1] + \
+ unpacked_vs1[2]*unpacked_vs2[2] + \
+ unpacked_vs1[3]*unpacked_vs2[3] \
+
diff --git a/riscv/insns/vqdot_vv.h b/riscv/insns/vqdot_vv.h
new file mode 100644
index 0000000..47a95ce
--- /dev/null
+++ b/riscv/insns/vqdot_vv.h
@@ -0,0 +1,11 @@
+// vqdot.vv vd, vs2, vs1, vm
+#include "vqdot_common.h"
+
+require_extension(EXT_ZVQDOTQ);
+require(P.VU.vsew == e32);
+
+VI_VV_LOOP
+({
+ VQDOT(vs1, vs2, int8_t, int8_t);
+ vd = (vd + result) & 0xffffffff;
+})
diff --git a/riscv/insns/vqdot_vx.h b/riscv/insns/vqdot_vx.h
new file mode 100644
index 0000000..6143b90
--- /dev/null
+++ b/riscv/insns/vqdot_vx.h
@@ -0,0 +1,11 @@
+// vqdot.vx vd, vs2, rs1, vm
+#include "vqdot_common.h"
+
+require_extension(EXT_ZVQDOTQ);
+require(P.VU.vsew == e32);
+
+VI_VX_LOOP
+({
+ VQDOT(rs1, vs2, int8_t, int8_t);
+ vd = (vd + result) & 0xffffffff;
+})
diff --git a/riscv/insns/vqdotsu_vv.h b/riscv/insns/vqdotsu_vv.h
new file mode 100644
index 0000000..e08b536
--- /dev/null
+++ b/riscv/insns/vqdotsu_vv.h
@@ -0,0 +1,11 @@
+// vqdotsu.vv vd, vs2, vs1, vm
+#include "vqdot_common.h"
+
+require_extension(EXT_ZVQDOTQ);
+require(P.VU.vsew == e32);
+
+VI_VV_LOOP
+({
+ VQDOT(vs1, vs2, uint8_t, int8_t);
+ vd = (vd + result) & 0xffffffff;
+})
diff --git a/riscv/insns/vqdotsu_vx.h b/riscv/insns/vqdotsu_vx.h
new file mode 100644
index 0000000..f3f3b5c
--- /dev/null
+++ b/riscv/insns/vqdotsu_vx.h
@@ -0,0 +1,11 @@
+// vqdotsu.vx vd, vs2, rs1, vm
+#include "vqdot_common.h"
+
+require_extension(EXT_ZVQDOTQ);
+require(P.VU.vsew == e32);
+
+VI_VX_LOOP
+({
+ VQDOT(rs1, vs2, uint8_t, int8_t);
+ vd = (vd + result) & 0xffffffff;
+})
diff --git a/riscv/insns/vqdotu_vv.h b/riscv/insns/vqdotu_vv.h
new file mode 100644
index 0000000..3404156
--- /dev/null
+++ b/riscv/insns/vqdotu_vv.h
@@ -0,0 +1,11 @@
+// vqdotu.vv vd, vs2, vs1, vm
+#include "vqdot_common.h"
+
+require_extension(EXT_ZVQDOTQ);
+require(P.VU.vsew == e32);
+
+VI_VV_LOOP
+({
+ VQDOT(vs1, vs2, uint8_t, uint8_t);
+ vd = (vd + result) & 0xffffffff;
+})
diff --git a/riscv/insns/vqdotu_vx.h b/riscv/insns/vqdotu_vx.h
new file mode 100644
index 0000000..7ef1048
--- /dev/null
+++ b/riscv/insns/vqdotu_vx.h
@@ -0,0 +1,11 @@
+// vqdotu.vx vd, vs2, rs1, vm
+#include "vqdot_common.h"
+
+require_extension(EXT_ZVQDOTQ);
+require(P.VU.vsew == e32);
+
+VI_VX_LOOP
+({
+ VQDOT(rs1, vs2, uint8_t, uint8_t);
+ vd = (vd + result) & 0xffffffff;
+})
diff --git a/riscv/insns/vqdotus_vx.h b/riscv/insns/vqdotus_vx.h
new file mode 100644
index 0000000..f1676e9
--- /dev/null
+++ b/riscv/insns/vqdotus_vx.h
@@ -0,0 +1,11 @@
+// vqdotus.vx vd, vs2, rs1, vm
+#include "vqdot_common.h"
+
+require_extension(EXT_ZVQDOTQ);
+require(P.VU.vsew == e32);
+
+VI_VX_LOOP
+({
+ VQDOT(rs1, vs2, int8_t, uint8_t);
+ vd = (vd + result) & 0xffffffff;
+})
diff --git a/riscv/insns/vredand_vs.h b/riscv/insns/vredand_vs.h
index 6c2d908..2e11182 100644
--- a/riscv/insns/vredand_vs.h
+++ b/riscv/insns/vredand_vs.h
@@ -1,4 +1,4 @@
-// vredand.vs vd, vs2 ,vs1
+// vredand.vs vd, vs2, vs1
VI_VV_LOOP_REDUCTION
({
vd_0_res &= vs2;
diff --git a/riscv/insns/vredmaxu_vs.h b/riscv/insns/vredmaxu_vs.h
index 960f486..8499258 100644
--- a/riscv/insns/vredmaxu_vs.h
+++ b/riscv/insns/vredmaxu_vs.h
@@ -1,4 +1,4 @@
-// vredmaxu.vs vd, vs2 ,vs1
+// vredmaxu.vs vd, vs2, vs1
VI_VV_ULOOP_REDUCTION
({
vd_0_res = (vd_0_res >= vs2) ? vd_0_res : vs2;
diff --git a/riscv/insns/vredmin_vs.h b/riscv/insns/vredmin_vs.h
index 50359b7..9cbfa42 100644
--- a/riscv/insns/vredmin_vs.h
+++ b/riscv/insns/vredmin_vs.h
@@ -1,4 +1,4 @@
-// vredmin.vs vd, vs2 ,vs1
+// vredmin.vs vd, vs2, vs1
VI_VV_LOOP_REDUCTION
({
vd_0_res = (vd_0_res <= vs2) ? vd_0_res : vs2;
diff --git a/riscv/insns/vredminu_vs.h b/riscv/insns/vredminu_vs.h
index 7082475..ac3c080 100644
--- a/riscv/insns/vredminu_vs.h
+++ b/riscv/insns/vredminu_vs.h
@@ -1,4 +1,4 @@
-// vredminu.vs vd, vs2 ,vs1
+// vredminu.vs vd, vs2, vs1
VI_VV_ULOOP_REDUCTION
({
vd_0_res = (vd_0_res <= vs2) ? vd_0_res : vs2;
diff --git a/riscv/insns/vredor_vs.h b/riscv/insns/vredor_vs.h
index f7acd9a..24e1496 100644
--- a/riscv/insns/vredor_vs.h
+++ b/riscv/insns/vredor_vs.h
@@ -1,4 +1,4 @@
-// vredor.vs vd, vs2 ,vs1
+// vredor.vs vd, vs2, vs1
VI_VV_LOOP_REDUCTION
({
vd_0_res |= vs2;
diff --git a/riscv/insns/vredsum_vs.h b/riscv/insns/vredsum_vs.h
index c4fefe5..d470ec0 100644
--- a/riscv/insns/vredsum_vs.h
+++ b/riscv/insns/vredsum_vs.h
@@ -1,4 +1,4 @@
-// vredsum.vs vd, vs2 ,vs1
+// vredsum.vs vd, vs2, vs1
VI_VV_LOOP_REDUCTION
({
vd_0_res += vs2;
diff --git a/riscv/insns/vredxor_vs.h b/riscv/insns/vredxor_vs.h
index bb81ad9..3b3709a 100644
--- a/riscv/insns/vredxor_vs.h
+++ b/riscv/insns/vredxor_vs.h
@@ -1,4 +1,4 @@
-// vredxor.vs vd, vs2 ,vs1
+// vredxor.vs vd, vs2, vs1
VI_VV_LOOP_REDUCTION
({
vd_0_res ^= vs2;
diff --git a/riscv/insns/vsll_vi.h b/riscv/insns/vsll_vi.h
index be46506..d9ef5db 100644
--- a/riscv/insns/vsll_vi.h
+++ b/riscv/insns/vsll_vi.h
@@ -1,5 +1,5 @@
// vsll.vi vd, vs2, zimm5
-VI_VI_LOOP
+VI_VI_ULOOP
({
- vd = vs2 << (simm5 & (sew - 1) & 0x1f);
+ vd = vs2 << (zimm5 & (sew - 1));
})
diff --git a/riscv/insns/vsll_vv.h b/riscv/insns/vsll_vv.h
index ce82022..3a3ee18 100644
--- a/riscv/insns/vsll_vv.h
+++ b/riscv/insns/vsll_vv.h
@@ -1,5 +1,5 @@
// vsll
-VI_VV_LOOP
+VI_VV_ULOOP
({
vd = vs2 << (vs1 & (sew - 1));
})
diff --git a/riscv/insns/vsll_vx.h b/riscv/insns/vsll_vx.h
index 823510b..d669b41 100644
--- a/riscv/insns/vsll_vx.h
+++ b/riscv/insns/vsll_vx.h
@@ -1,5 +1,5 @@
// vsll
-VI_VX_LOOP
+VI_VX_ULOOP
({
vd = vs2 << (rs1 & (sew - 1));
})
diff --git a/riscv/insns/vsm3c_vi.h b/riscv/insns/vsm3c_vi.h
index b3e8121..f9375a5 100644
--- a/riscv/insns/vsm3c_vi.h
+++ b/riscv/insns/vsm3c_vi.h
@@ -3,6 +3,7 @@
#include "zvksh_ext_macros.h"
require_vsm3_constraints;
+VI_CHECK_SSS(false)
VI_ZVK_VD_VS2_ZIMM5_EGU32x8_NOVM_LOOP(
{},
diff --git a/riscv/insns/vsm3me_vv.h b/riscv/insns/vsm3me_vv.h
index dd6cb52..388b79f 100644
--- a/riscv/insns/vsm3me_vv.h
+++ b/riscv/insns/vsm3me_vv.h
@@ -13,6 +13,7 @@
(ZVKSH_P1((M16) ^ (M9) ^ ZVK_ROL32((M3), 15)) ^ ZVK_ROL32((M13), 7) ^ (M6))
require_vsm3_constraints;
+VI_CHECK_SSS(true)
VI_ZVK_VD_VS1_VS2_EGU32x8_NOVM_LOOP(
{},
diff --git a/riscv/insns/vsm4k_vi.h b/riscv/insns/vsm4k_vi.h
index 8f52e68..dd6f67d 100644
--- a/riscv/insns/vsm4k_vi.h
+++ b/riscv/insns/vsm4k_vi.h
@@ -15,6 +15,7 @@ static constexpr uint32_t zvksed_ck[32] = {
};
require_vsm4_constraints;
+VI_CHECK_SSS(false)
VI_ZVK_VD_VS2_ZIMM5_EGU32x4_NOVM_LOOP(
{},
diff --git a/riscv/insns/vsm4r_vs.h b/riscv/insns/vsm4r_vs.h
index 44011eb..8db1050 100644
--- a/riscv/insns/vsm4r_vs.h
+++ b/riscv/insns/vsm4r_vs.h
@@ -3,8 +3,10 @@
#include "zvksed_ext_macros.h"
require_vsm4_constraints;
+require_align(insn.rd(), P.VU.vflmul);
+require_vs2_align_eglmul(128);
// No overlap of vd and vs2.
-require(insn.rd() != insn.rs2());
+require_noover_eglmul(insn.rd(), insn.rs2());
VI_ZVK_VD_VS2_NOOPERANDS_PRELOOP_EGU32x4_NOVM_LOOP(
{},
diff --git a/riscv/insns/vsm4r_vv.h b/riscv/insns/vsm4r_vv.h
index 9a18cec..18afee6 100644
--- a/riscv/insns/vsm4r_vv.h
+++ b/riscv/insns/vsm4r_vv.h
@@ -2,7 +2,9 @@
#include "zvksed_ext_macros.h"
+
require_vsm4_constraints;
+VI_CHECK_SSS(false)
VI_ZVK_VD_VS2_EGU32x4_NOVM_LOOP(
{},
diff --git a/riscv/insns/vsmul_vv.h b/riscv/insns/vsmul_vv.h
index 49e42c1..c1d0a57 100644
--- a/riscv/insns/vsmul_vv.h
+++ b/riscv/insns/vsmul_vv.h
@@ -1,10 +1,10 @@
// vsmul.vv vd, vs2, vs1
-VRM xrm = P.VU.get_vround_mode();
-int64_t int_max = INT64_MAX >> (64 - P.VU.vsew);
-int64_t int_min = INT64_MIN >> (64 - P.VU.vsew);
-
VI_VV_LOOP
({
+ VRM xrm = P.VU.get_vround_mode();
+ int64_t int_max = INT64_MAX >> (64 - P.VU.vsew);
+ int64_t int_min = INT64_MIN >> (64 - P.VU.vsew);
+
bool overflow = vs1 == vs2 && vs1 == int_min;
int128_t result = (int128_t)vs1 * (int128_t)vs2;
diff --git a/riscv/insns/vsmul_vx.h b/riscv/insns/vsmul_vx.h
index d2724ee..c2e531c 100644
--- a/riscv/insns/vsmul_vx.h
+++ b/riscv/insns/vsmul_vx.h
@@ -1,10 +1,10 @@
// vsmul.vx vd, vs2, rs1
-VRM xrm = P.VU.get_vround_mode();
-int64_t int_max = INT64_MAX >> (64 - P.VU.vsew);
-int64_t int_min = INT64_MIN >> (64 - P.VU.vsew);
-
VI_VX_LOOP
({
+ VRM xrm = P.VU.get_vround_mode();
+ int64_t int_max = INT64_MAX >> (64 - P.VU.vsew);
+ int64_t int_min = INT64_MIN >> (64 - P.VU.vsew);
+
bool overflow = rs1 == vs2 && rs1 == int_min;
int128_t result = (int128_t)rs1 * (int128_t)vs2;
diff --git a/riscv/insns/vsra_vi.h b/riscv/insns/vsra_vi.h
index 5c58927..4cf616d 100644
--- a/riscv/insns/vsra_vi.h
+++ b/riscv/insns/vsra_vi.h
@@ -1,5 +1,5 @@
// vsra.vi vd, vs2, zimm5
VI_VI_LOOP
({
- vd = vs2 >> (simm5 & (sew - 1) & 0x1f);
+ vd = vs2 >> (insn.v_zimm5() & (sew - 1));
})
diff --git a/riscv/insns/vsrl_vi.h b/riscv/insns/vsrl_vi.h
index fe5d272..6a3d13c 100644
--- a/riscv/insns/vsrl_vi.h
+++ b/riscv/insns/vsrl_vi.h
@@ -1,5 +1,5 @@
// vsrl.vi vd, vs2, zimm5
VI_VI_ULOOP
({
- vd = vs2 >> (zimm5 & (sew - 1) & 0x1f);
+ vd = vs2 >> (zimm5 & (sew - 1));
})
diff --git a/riscv/insns/vssra_vi.h b/riscv/insns/vssra_vi.h
index ff2e1c5..12f1240 100644
--- a/riscv/insns/vssra_vi.h
+++ b/riscv/insns/vssra_vi.h
@@ -1,8 +1,8 @@
-// vssra.vi vd, vs2, simm5
-VRM xrm = P.VU.get_vround_mode();
+// vssra.vi vd, vs2, zimm5
VI_VI_LOOP
({
- int sh = simm5 & (sew - 1) & 0x1f;
+ VRM xrm = P.VU.get_vround_mode();
+ int sh = insn.v_zimm5() & (sew - 1);
int128_t val = vs2;
INT_ROUNDING(val, xrm, sh);
diff --git a/riscv/insns/vssra_vv.h b/riscv/insns/vssra_vv.h
index 7bbc766..babca47 100644
--- a/riscv/insns/vssra_vv.h
+++ b/riscv/insns/vssra_vv.h
@@ -1,7 +1,7 @@
// vssra.vv vd, vs2, vs1
-VRM xrm = P.VU.get_vround_mode();
VI_VV_LOOP
({
+ VRM xrm = P.VU.get_vround_mode();
int sh = vs1 & (sew - 1);
int128_t val = vs2;
diff --git a/riscv/insns/vssra_vx.h b/riscv/insns/vssra_vx.h
index 068a22b..3d70726 100644
--- a/riscv/insns/vssra_vx.h
+++ b/riscv/insns/vssra_vx.h
@@ -1,7 +1,7 @@
// vssra.vx vd, vs2, rs1
-VRM xrm = P.VU.get_vround_mode();
VI_VX_LOOP
({
+ VRM xrm = P.VU.get_vround_mode();
int sh = rs1 & (sew - 1);
int128_t val = vs2;
diff --git a/riscv/insns/vssrl_vi.h b/riscv/insns/vssrl_vi.h
index d125164..a2de49e 100644
--- a/riscv/insns/vssrl_vi.h
+++ b/riscv/insns/vssrl_vi.h
@@ -1,8 +1,8 @@
-// vssra.vi vd, vs2, simm5
-VRM xrm = P.VU.get_vround_mode();
+// vssra.vi vd, vs2, zimm5
VI_VI_ULOOP
({
- int sh = zimm5 & (sew - 1) & 0x1f;
+ VRM xrm = P.VU.get_vround_mode();
+ int sh = zimm5 & (sew - 1);
uint128_t val = vs2;
INT_ROUNDING(val, xrm, sh);
diff --git a/riscv/insns/vssrl_vv.h b/riscv/insns/vssrl_vv.h
index a8e5d16..f8924ba 100644
--- a/riscv/insns/vssrl_vv.h
+++ b/riscv/insns/vssrl_vv.h
@@ -1,7 +1,7 @@
// vssrl.vv vd, vs2, vs1
-VRM xrm = P.VU.get_vround_mode();
VI_VV_ULOOP
({
+ VRM xrm = P.VU.get_vround_mode();
int sh = vs1 & (sew - 1);
uint128_t val = vs2;
diff --git a/riscv/insns/vssrl_vx.h b/riscv/insns/vssrl_vx.h
index ee3cb34..04468d5 100644
--- a/riscv/insns/vssrl_vx.h
+++ b/riscv/insns/vssrl_vx.h
@@ -1,7 +1,7 @@
// vssrl.vx vd, vs2, rs1
-VRM xrm = P.VU.get_vround_mode();
VI_VX_ULOOP
({
+ VRM xrm = P.VU.get_vround_mode();
int sh = rs1 & (sew - 1);
uint128_t val = vs2;
diff --git a/riscv/insns/vwsll_vi.h b/riscv/insns/vwsll_vi.h
index 13b5eb4..866cd78 100644
--- a/riscv/insns/vwsll_vi.h
+++ b/riscv/insns/vwsll_vi.h
@@ -3,6 +3,7 @@
#include "zvk_ext_macros.h"
require_zvbb;
+VI_CHECK_DSS(false);
VI_ZVK_VI_WIDENING_ULOOP({
const reg_t shift = zimm5 & ((2 * sew) - 1);
diff --git a/riscv/insns/vwsll_vv.h b/riscv/insns/vwsll_vv.h
index 5a64c6c..180fe97 100644
--- a/riscv/insns/vwsll_vv.h
+++ b/riscv/insns/vwsll_vv.h
@@ -3,6 +3,7 @@
#include "zvk_ext_macros.h"
require_zvbb;
+VI_CHECK_DSS(true);
VI_ZVK_VV_WIDENING_ULOOP({
const reg_t shift = (vs1 & ((2 * sew) - 1));
diff --git a/riscv/insns/vwsll_vx.h b/riscv/insns/vwsll_vx.h
index 5264e80..4137d39 100644
--- a/riscv/insns/vwsll_vx.h
+++ b/riscv/insns/vwsll_vx.h
@@ -3,6 +3,7 @@
#include "zvk_ext_macros.h"
require_zvbb;
+VI_CHECK_DSS(false);
VI_ZVK_VX_WIDENING_ULOOP({
const reg_t shift = (rs1 & ((2 * sew) - 1));
diff --git a/riscv/interactive.cc b/riscv/interactive.cc
index b0855fa..9afc718 100644
--- a/riscv/interactive.cc
+++ b/riscv/interactive.cc
@@ -83,8 +83,7 @@ static void clear_str(bool noncanonical, int fd, std::string target_str)
clear_motion += ' ';
}
clear_motion += '\r';
- if (write(fd, clear_motion.c_str(), clear_motion.size() + 1))
- ; // shut up gcc
+ (void) write(fd, clear_motion.c_str(), clear_motion.size() + 1);
}
}
@@ -97,8 +96,7 @@ static void send_key(bool noncanonical, int fd, keybuffer_t key_code, const int
{
key_motion += (char) ((key_code >> (i * BITS_PER_CHAR)) & 0xff);
}
- if (write(fd, key_motion.c_str(), len) != len)
- ; // shut up gcc
+ (void) write(fd, key_motion.c_str(), len);
}
}
@@ -145,8 +143,8 @@ static std::string readline(int fd)
clear_str(noncanonical, fd, s);
cursor_pos--;
s.erase(cursor_pos, 1);
- if (noncanonical && write(fd, s.c_str(), s.size() + 1) != 1)
- ; // shut up gcc
+ if (noncanonical)
+ (void) write(fd, s.c_str(), s.size() + 1);
// move cursor by left arrow key
for (unsigned i = 0; i < s.size() - cursor_pos; i++) {
send_key(noncanonical, fd, KEYCODE_LEFT, 3);
@@ -177,8 +175,8 @@ static std::string readline(int fd)
clear_str(noncanonical, fd, s);
history_index = std::min(history_commands.size(), history_index + 1);
s = history_commands[history_commands.size() - history_index];
- if (noncanonical && write(fd, s.c_str(), s.size() + 1))
- ; // shut up gcc
+ if (noncanonical)
+ (void) write(fd, s.c_str(), s.size() + 1);
cursor_pos = s.size();
}
key_buffer = 0;
@@ -193,8 +191,8 @@ static std::string readline(int fd)
} else {
s = history_commands[history_commands.size() - history_index];
}
- if (noncanonical && write(fd, s.c_str(), s.size() + 1))
- ; // shut up gcc
+ if (noncanonical)
+ (void) write(fd, s.c_str(), s.size() + 1);
cursor_pos = s.size();
}
key_buffer = 0;
@@ -222,14 +220,13 @@ static std::string readline(int fd)
key_buffer = 0;
break;
case KEYCODE_ENTER:
- if (noncanonical && write(fd, &ch, 1) != 1)
- ; // shut up gcc
+ if (noncanonical)
+ (void) write(fd, &ch, 1);
if (s.size() > initial_s_len && (history_commands.size() == 0 || s != history_commands[history_commands.size() - 1])) {
history_commands.push_back(s);
}
return s.substr(initial_s_len);
default:
- DEFAULT_KEY:
// unknown buffered key, do nothing
if (key_buffer != 0) {
key_buffer = 0;
@@ -238,8 +235,8 @@ static std::string readline(int fd)
clear_str(noncanonical, fd, s);
s.insert(cursor_pos, 1, ch);
cursor_pos++;
- if (noncanonical && write(fd, s.c_str(), s.size() + 1) != 1)
- ; // shut up gcc
+ if (noncanonical)
+ (void) write(fd, s.c_str(), s.size() + 1);
// send left arrow key to move cursor
for (unsigned i = 0; i < s.size() - cursor_pos; i++) {
send_key(noncanonical, fd, KEYCODE_LEFT, 3);
@@ -342,8 +339,10 @@ void sim_t::interactive()
(this->*funcs[cmd])(cmd, args);
else
out << "Unknown command " << cmd << std::endl;
- } catch(trap_t& t) {
+ } catch(trap_interactive& t) {
out << "Bad or missing arguments for command " << cmd << std::endl;
+ } catch(trap_t& t){
+ out << "Received trap: " << t.name() << std::endl;
}
#ifdef HAVE_BOOST_ASIO
if (socketif)
@@ -452,37 +451,16 @@ void sim_t::interactive_pc(const std::string& cmd, const std::vector<std::string
<< zext(get_pc(args), max_xlen) << std::endl;
}
-static reg_t load(mmu_t* mmu, reg_t addr) {
- reg_t val;
-
- switch (addr % 8)
- {
- case 0:
- val = mmu->load<uint64_t>(addr);
- break;
- case 4:
- val = mmu->load<uint32_t>(addr);
- break;
- case 2:
- case 6:
- val = mmu->load<uint16_t>(addr);
- break;
- default:
- val = mmu->load<uint8_t>(addr);
- break;
- }
- return val;
-}
-
reg_t sim_t::get_insn(const std::vector<std::string>& args)
{
if (args.size() != 1)
throw trap_interactive();
processor_t *p = get_core(args[0]);
- reg_t addr = p->get_state()->pc;
+ reg_t pc = p->get_state()->pc;
mmu_t* mmu = p->get_mmu();
- return load(mmu, addr);
+ icache_entry_t* ic_entry = mmu->access_icache(pc);
+ return ic_entry->data.insn.bits();
}
void sim_t::interactive_insn(const std::string& cmd, const std::vector<std::string>& args)
@@ -493,9 +471,8 @@ void sim_t::interactive_insn(const std::string& cmd, const std::vector<std::stri
processor_t *p = get_core(args[0]);
int max_xlen = p->get_isa().get_max_xlen();
- insn_t insn(get_insn(args));
-
std::ostream out(sout_.rdbuf());
+ insn_t insn(get_insn(args)); // ensure this is outside of ostream to not pollute output on non-interactive trap
out << std::hex << std::setfill('0') << "0x" << std::setw(max_xlen/4)
<< zext(insn.bits(), max_xlen) << " " << p->get_disassembler()->disassemble(insn) << std::endl;
}
@@ -708,7 +685,24 @@ reg_t sim_t::get_mem(const std::vector<std::string>& args)
if (addr == LONG_MAX)
addr = strtoul(addr_str.c_str(),NULL,16);
- return load(mmu, addr);
+ reg_t val;
+ switch (addr % 8)
+ {
+ case 0:
+ val = mmu->load<uint64_t>(addr);
+ break;
+ case 4:
+ val = mmu->load<uint32_t>(addr);
+ break;
+ case 2:
+ case 6:
+ val = mmu->load<uint16_t>(addr);
+ break;
+ default:
+ val = mmu->load<uint8_t>(addr);
+ break;
+ }
+ return val;
}
void sim_t::interactive_mem(const std::string& cmd, const std::vector<std::string>& args)
@@ -716,8 +710,9 @@ void sim_t::interactive_mem(const std::string& cmd, const std::vector<std::strin
int max_xlen = procs[0]->get_isa().get_max_xlen();
std::ostream out(sout_.rdbuf());
+ reg_t mem_val = get_mem(args); // ensure this is outside of ostream to not pollute output on non-interactive trap
out << std::hex << "0x" << std::setfill('0') << std::setw(max_xlen/4)
- << zext(get_mem(args), max_xlen) << std::endl;
+ << zext(mem_val, max_xlen) << std::endl;
}
void sim_t::interactive_str(const std::string& cmd, const std::vector<std::string>& args)
diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h
index afb49f2..e99f720 100644
--- a/riscv/isa_parser.h
+++ b/riscv/isa_parser.h
@@ -23,7 +23,7 @@ typedef enum {
EXT_ZCB,
EXT_ZCD,
EXT_ZCF,
- EXT_ZCMLSD,
+ EXT_ZCLSD,
EXT_ZCMP,
EXT_ZCMT,
EXT_ZKND,
@@ -40,6 +40,7 @@ typedef enum {
EXT_SMRNMI,
EXT_SSCOFPMF,
EXT_SVADU,
+ EXT_SVADE,
EXT_SVNAPOT,
EXT_SVPBMT,
EXT_SVINVAL,
@@ -49,6 +50,7 @@ typedef enum {
EXT_ZFINX,
EXT_ZHINX,
EXT_ZHINXMIN,
+ EXT_ZICCID,
EXT_ZICBOM,
EXT_ZICBOZ,
EXT_ZICNTR,
@@ -65,6 +67,7 @@ typedef enum {
EXT_ZVKNHB,
EXT_ZVKSED,
EXT_ZVKSH,
+ EXT_ZVQDOTQ,
EXT_SSTC,
EXT_ZAAMO,
EXT_ZALRSC,
@@ -74,6 +77,8 @@ typedef enum {
EXT_INTERNAL_ZFH_MOVE,
EXT_SMCSRIND,
EXT_SSCSRIND,
+ EXT_SMCDELEG,
+ EXT_SSCCFG,
EXT_SMCNTRPMF,
EXT_ZIMOP,
EXT_ZCMOP,
@@ -81,6 +86,13 @@ typedef enum {
EXT_SSQOSID,
EXT_ZICFILP,
EXT_ZICFISS,
+ EXT_SSDBLTRP,
+ EXT_SMDBLTRP,
+ EXT_SMMPM,
+ EXT_SMNPM,
+ EXT_SSNPM,
+ EXT_SMAIA,
+ EXT_SSAIA,
NUM_ISA_EXTENSIONS
} isa_extension_t;
diff --git a/riscv/jtag_dtm.h b/riscv/jtag_dtm.h
index 23a54be..bc681de 100644
--- a/riscv/jtag_dtm.h
+++ b/riscv/jtag_dtm.h
@@ -51,7 +51,9 @@ class jtag_dtm_t
// abits must come before dtmcontrol so it can easily be used in the
// constructor.
- const unsigned abits = 6;
+ // From RISC-V Debug Spec (both 0.13.2 and 1.0):
+ // The DMI uses between 7 and 32 address bits.
+ const unsigned abits = 7;
uint32_t dtmcontrol;
uint64_t dmi;
unsigned bypass;
diff --git a/riscv/log_file.h b/riscv/log_file.h
index d039859..9e210bb 100644
--- a/riscv/log_file.h
+++ b/riscv/log_file.h
@@ -31,7 +31,7 @@ public:
FILE *get() { return wrapped_file ? wrapped_file.get() : stderr; }
private:
- std::unique_ptr<FILE, decltype(&fclose)> wrapped_file;
+ std::unique_ptr<FILE, int(*)(FILE*)> wrapped_file;
};
#endif
diff --git a/riscv/mmu.cc b/riscv/mmu.cc
index d10e23a..30fc47a 100644
--- a/riscv/mmu.cc
+++ b/riscv/mmu.cc
@@ -5,16 +5,16 @@
#include "arith.h"
#include "simif.h"
#include "processor.h"
+#include "decode_macros.h"
-mmu_t::mmu_t(simif_t* sim, endianness_t endianness, processor_t* proc)
- : sim(sim), proc(proc),
+mmu_t::mmu_t(simif_t* sim, endianness_t endianness, processor_t* proc, reg_t cache_blocksz)
+ : sim(sim), proc(proc), blocksz(cache_blocksz),
#ifdef RISCV_ENABLE_DUAL_ENDIAN
target_big_endian(endianness == endianness_big),
#endif
check_triggers_fetch(false),
check_triggers_load(false),
- check_triggers_store(false),
- matched_trigger(NULL)
+ check_triggers_store(false)
{
#ifndef RISCV_ENABLE_DUAL_ENDIAN
assert(endianness == endianness_little);
@@ -35,9 +35,9 @@ void mmu_t::flush_icache()
void mmu_t::flush_tlb()
{
- memset(tlb_insn_tag, -1, sizeof(tlb_insn_tag));
- memset(tlb_load_tag, -1, sizeof(tlb_load_tag));
- memset(tlb_store_tag, -1, sizeof(tlb_store_tag));
+ memset(tlb_insn, -1, sizeof(tlb_insn));
+ memset(tlb_load, -1, sizeof(tlb_load));
+ memset(tlb_store, -1, sizeof(tlb_store));
flush_icache();
}
@@ -54,7 +54,7 @@ void throw_access_exception(bool virt, reg_t addr, access_type type)
reg_t mmu_t::translate(mem_access_info_t access_info, reg_t len)
{
- reg_t addr = access_info.vaddr;
+ reg_t addr = access_info.transformed_vaddr;
access_type type = access_info.type;
if (!proc)
return addr;
@@ -64,33 +64,51 @@ reg_t mmu_t::translate(mem_access_info_t access_info, reg_t len)
reg_t paddr = walk(access_info) | (addr & (PGSIZE-1));
if (!pmp_ok(paddr, len, access_info.flags.ss_access ? STORE : type, mode, access_info.flags.hlvx))
- throw_access_exception(virt, addr, type);
+ throw_access_exception(virt, addr, access_info.flags.ss_access ? STORE : type);
return paddr;
}
-tlb_entry_t mmu_t::fetch_slow_path(reg_t vaddr)
+inline mmu_t::insn_parcel_t mmu_t::perform_intrapage_fetch(reg_t vaddr, uintptr_t host_addr, reg_t paddr)
{
+ insn_parcel_t res;
+
+ if (host_addr)
+ memcpy(&res, (char*)host_addr, sizeof(res));
+ else if (!mmio_fetch(paddr, sizeof(res), (uint8_t*)&res))
+ throw trap_instruction_access_fault(proc->state.v, vaddr, 0, 0);
+
+ return res;
+}
+
+mmu_t::insn_parcel_t mmu_t::fetch_slow_path(reg_t vaddr)
+{
+ if (matched_trigger) {
+ auto trig = matched_trigger.value();
+ matched_trigger.reset();
+ throw trig;
+ }
+
+ if (auto [tlb_hit, host_addr, paddr] = access_tlb(tlb_insn, vaddr, TLB_FLAGS & ~TLB_CHECK_TRIGGERS); tlb_hit) {
+ // Fast path for simple cases
+ return perform_intrapage_fetch(vaddr, host_addr, paddr);
+ }
+
+ auto [tlb_hit, host_addr, paddr] = access_tlb(tlb_insn, vaddr, TLB_FLAGS);
auto access_info = generate_access_info(vaddr, FETCH, {});
check_triggers(triggers::OPERATION_EXECUTE, vaddr, access_info.effective_virt);
- tlb_entry_t result;
- reg_t vpn = vaddr >> PGSHIFT;
- if (unlikely(tlb_insn_tag[vpn % TLB_ENTRIES] != (vpn | TLB_CHECK_TRIGGERS))) {
- reg_t paddr = translate(access_info, sizeof(fetch_temp));
- if (auto host_addr = sim->addr_to_mem(paddr)) {
- result = refill_tlb(vaddr, paddr, host_addr, FETCH);
- } else {
- if (!mmio_fetch(paddr, sizeof fetch_temp, (uint8_t*)&fetch_temp))
- throw trap_instruction_access_fault(proc->state.v, vaddr, 0, 0);
- result = {(char*)&fetch_temp - vaddr, paddr - vaddr};
- }
- } else {
- result = tlb_data[vpn % TLB_ENTRIES];
+ if (!tlb_hit) {
+ paddr = translate(access_info, sizeof(insn_parcel_t));
+ host_addr = (uintptr_t)sim->addr_to_mem(paddr);
+
+ refill_tlb(vaddr, paddr, (char*)host_addr, FETCH);
}
- check_triggers(triggers::OPERATION_EXECUTE, vaddr, access_info.effective_virt, from_le(*(const uint16_t*)(result.host_offset + vaddr)));
+ auto res = perform_intrapage_fetch(vaddr, host_addr, paddr);
+
+ check_triggers(triggers::OPERATION_EXECUTE, vaddr, access_info.effective_virt, from_le(res));
- return result;
+ return res;
}
reg_t reg_from_bytes(size_t len, const uint8_t* bytes)
@@ -122,7 +140,8 @@ reg_t reg_from_bytes(size_t len, const uint8_t* bytes)
bool mmu_t::mmio_ok(reg_t paddr, access_type UNUSED type)
{
// Disallow access to debug region when not in debug mode
- if (paddr >= DEBUG_START && paddr <= DEBUG_END && proc && !proc->state.debug_mode)
+ static_assert(DEBUG_START == 0);
+ if (/* paddr >= DEBUG_START && */ paddr <= DEBUG_END && proc && !proc->state.debug_mode)
return false;
return true;
@@ -183,160 +202,210 @@ void mmu_t::check_triggers(triggers::operation_t operation, reg_t address, bool
case triggers::TIMING_AFTER:
// We want to take this exception on the next instruction. We check
- // whether to do so in the I$ refill path, so flush the I$.
- flush_icache();
- matched_trigger = new triggers::matched_t(operation, tval, match->action, virt);
+ // whether to do so in the I$ refill slow path, which we can force by
+ // flushing the TLB.
+ flush_tlb();
+ matched_trigger = triggers::matched_t(operation, tval, match->action, virt);
}
}
-void mmu_t::load_slow_path_intrapage(reg_t len, uint8_t* bytes, mem_access_info_t access_info)
+inline void mmu_t::perform_intrapage_load(reg_t vaddr, uintptr_t host_addr, reg_t paddr, reg_t len, uint8_t* bytes, xlate_flags_t xlate_flags)
{
- reg_t addr = access_info.vaddr;
- reg_t vpn = addr >> PGSHIFT;
- if (!access_info.flags.is_special_access() && vpn == (tlb_load_tag[vpn % TLB_ENTRIES] & ~TLB_CHECK_TRIGGERS)) {
- auto host_addr = tlb_data[vpn % TLB_ENTRIES].host_offset + addr;
- memcpy(bytes, host_addr, len);
- return;
+ if (host_addr) {
+ memcpy(bytes, (char*)host_addr, len);
+ } else if (!mmio_load(paddr, len, bytes)) {
+ auto access_info = generate_access_info(vaddr, LOAD, xlate_flags);
+ if (access_info.flags.ss_access)
+ throw trap_store_access_fault(access_info.effective_virt, access_info.transformed_vaddr, 0, 0);
+ else
+ throw trap_load_access_fault(access_info.effective_virt, access_info.transformed_vaddr, 0, 0);
}
- reg_t paddr = translate(access_info, len);
+ if (tracer.interested_in_range(paddr, paddr + len, LOAD))
+ tracer.trace(paddr, len, LOAD);
+}
- if (access_info.flags.lr && !sim->reservable(paddr)) {
- throw trap_load_access_fault(access_info.effective_virt, addr, 0, 0);
- }
+void mmu_t::load_slow_path_intrapage(reg_t len, uint8_t* bytes, mem_access_info_t access_info)
+{
+ reg_t vaddr = access_info.vaddr;
+ auto [tlb_hit, host_addr, paddr] = access_tlb(tlb_load, vaddr, TLB_FLAGS);
+ if (!tlb_hit || access_info.flags.is_special_access()) {
+ paddr = translate(access_info, len);
+ host_addr = (uintptr_t)sim->addr_to_mem(paddr);
- if (auto host_addr = sim->addr_to_mem(paddr)) {
- memcpy(bytes, host_addr, len);
- if (tracer.interested_in_range(paddr, paddr + PGSIZE, LOAD))
- tracer.trace(paddr, len, LOAD);
- else if (!access_info.flags.is_special_access())
- refill_tlb(addr, paddr, host_addr, LOAD);
+ if (!access_info.flags.is_special_access())
+ refill_tlb(vaddr, paddr, (char*)host_addr, LOAD);
- } else if (!mmio_load(paddr, len, bytes)) {
- throw trap_load_access_fault(access_info.effective_virt, addr, 0, 0);
+ if (access_info.flags.lr && !sim->reservable(paddr)) {
+ throw trap_load_access_fault(access_info.effective_virt, access_info.transformed_vaddr, 0, 0);
+ }
}
+ perform_intrapage_load(vaddr, host_addr, paddr, len, bytes, access_info.flags);
+
if (access_info.flags.lr) {
load_reservation_address = paddr;
}
}
-void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, xlate_flags_t xlate_flags)
+void mmu_t::load_slow_path(reg_t original_addr, reg_t len, uint8_t* bytes, xlate_flags_t xlate_flags)
{
- auto access_info = generate_access_info(addr, LOAD, xlate_flags);
- check_triggers(triggers::OPERATION_LOAD, addr, access_info.effective_virt);
+ if (likely(!xlate_flags.is_special_access())) {
+ // Fast path for simple cases
+ auto [tlb_hit, host_addr, paddr] = access_tlb(tlb_load, original_addr, TLB_FLAGS & ~TLB_CHECK_TRIGGERS);
+ bool intrapage = (original_addr % PGSIZE) + len <= PGSIZE;
+ bool aligned = (original_addr & (len - 1)) == 0;
+
+ if (likely(tlb_hit && (aligned || (intrapage && is_misaligned_enabled())))) {
+ return perform_intrapage_load(original_addr, host_addr, paddr, len, bytes, xlate_flags);
+ }
+ }
- if ((addr & (len - 1)) == 0) {
+ auto access_info = generate_access_info(original_addr, LOAD, xlate_flags);
+ reg_t transformed_addr = access_info.transformed_vaddr;
+ check_triggers(triggers::OPERATION_LOAD, transformed_addr, access_info.effective_virt);
+
+ if ((transformed_addr & (len - 1)) == 0) {
load_slow_path_intrapage(len, bytes, access_info);
} else {
bool gva = access_info.effective_virt;
if (!is_misaligned_enabled())
- throw trap_load_address_misaligned(gva, addr, 0, 0);
+ throw trap_load_address_misaligned(gva, transformed_addr, 0, 0);
if (access_info.flags.lr)
- throw trap_load_access_fault(gva, addr, 0, 0);
+ throw trap_load_access_fault(gva, transformed_addr, 0, 0);
- reg_t len_page0 = std::min(len, PGSIZE - addr % PGSIZE);
+ reg_t len_page0 = std::min(len, PGSIZE - transformed_addr % PGSIZE);
load_slow_path_intrapage(len_page0, bytes, access_info);
- if (len_page0 != len)
- load_slow_path_intrapage(len - len_page0, bytes + len_page0, access_info.split_misaligned_access(len_page0));
+ if (len_page0 != len) {
+ auto tail_access_info = generate_access_info(original_addr + len_page0, LOAD, xlate_flags);
+ load_slow_path_intrapage(len - len_page0, bytes + len_page0, tail_access_info);
+ }
}
while (len > sizeof(reg_t)) {
- check_triggers(triggers::OPERATION_LOAD, addr, access_info.effective_virt, reg_from_bytes(sizeof(reg_t), bytes));
+ check_triggers(triggers::OPERATION_LOAD, transformed_addr, access_info.effective_virt, reg_from_bytes(sizeof(reg_t), bytes));
len -= sizeof(reg_t);
bytes += sizeof(reg_t);
}
- check_triggers(triggers::OPERATION_LOAD, addr, access_info.effective_virt, reg_from_bytes(len, bytes));
+ check_triggers(triggers::OPERATION_LOAD, transformed_addr, access_info.effective_virt, reg_from_bytes(len, bytes));
+
+ if (proc && unlikely(proc->get_log_commits_enabled()))
+ proc->state.log_mem_read.push_back(std::make_tuple(original_addr, 0, len));
}
-void mmu_t::store_slow_path_intrapage(reg_t len, const uint8_t* bytes, mem_access_info_t access_info, bool actually_store)
+inline void mmu_t::perform_intrapage_store(reg_t vaddr, uintptr_t host_addr, reg_t paddr, reg_t len, const uint8_t* bytes, xlate_flags_t xlate_flags)
{
- reg_t addr = access_info.vaddr;
- reg_t vpn = addr >> PGSHIFT;
- if (!access_info.flags.is_special_access() && vpn == (tlb_store_tag[vpn % TLB_ENTRIES] & ~TLB_CHECK_TRIGGERS)) {
- if (actually_store) {
- auto host_addr = tlb_data[vpn % TLB_ENTRIES].host_offset + addr;
- memcpy(host_addr, bytes, len);
- }
- return;
+ if (host_addr) {
+ memcpy((char*)host_addr, bytes, len);
+ } else if (!mmio_store(paddr, len, bytes)) {
+ auto access_info = generate_access_info(vaddr, STORE, xlate_flags);
+ throw trap_store_access_fault(access_info.effective_virt, access_info.transformed_vaddr, 0, 0);
}
- reg_t paddr = translate(access_info, len);
+ if (tracer.interested_in_range(paddr, paddr + len, STORE))
+ tracer.trace(paddr, len, STORE);
+}
- if (actually_store) {
- if (auto host_addr = sim->addr_to_mem(paddr)) {
- memcpy(host_addr, bytes, len);
- if (tracer.interested_in_range(paddr, paddr + PGSIZE, STORE))
- tracer.trace(paddr, len, STORE);
- else if (!access_info.flags.is_special_access())
- refill_tlb(addr, paddr, host_addr, STORE);
- } else if (!mmio_store(paddr, len, bytes)) {
- throw trap_store_access_fault(access_info.effective_virt, addr, 0, 0);
- }
+void mmu_t::store_slow_path_intrapage(reg_t len, const uint8_t* bytes, mem_access_info_t access_info, bool actually_store)
+{
+ reg_t vaddr = access_info.vaddr;
+ auto [tlb_hit, host_addr, paddr] = access_tlb(tlb_store, vaddr, TLB_FLAGS);
+ if (!tlb_hit || access_info.flags.is_special_access()) {
+ paddr = translate(access_info, len);
+ host_addr = (uintptr_t)sim->addr_to_mem(paddr);
+
+ if (!access_info.flags.is_special_access())
+ refill_tlb(vaddr, paddr, (char*)host_addr, STORE);
}
+
+ if (actually_store)
+ perform_intrapage_store(vaddr, host_addr, paddr, len, bytes, access_info.flags);
}
-void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, xlate_flags_t xlate_flags, bool actually_store, bool UNUSED require_alignment)
+void mmu_t::store_slow_path(reg_t original_addr, reg_t len, const uint8_t* bytes, xlate_flags_t xlate_flags, bool actually_store, bool UNUSED require_alignment)
{
- auto access_info = generate_access_info(addr, STORE, xlate_flags);
+ if (likely(!xlate_flags.is_special_access())) {
+ // Fast path for simple cases
+ auto [tlb_hit, host_addr, paddr] = access_tlb(tlb_store, original_addr, TLB_FLAGS & ~TLB_CHECK_TRIGGERS);
+ bool intrapage = (original_addr % PGSIZE) + len <= PGSIZE;
+ bool aligned = (original_addr & (len - 1)) == 0;
+
+ if (likely(tlb_hit && (aligned || (intrapage && is_misaligned_enabled())))) {
+ if (actually_store)
+ perform_intrapage_store(original_addr, host_addr, paddr, len, bytes, xlate_flags);
+ return;
+ }
+ }
+
+ auto access_info = generate_access_info(original_addr, STORE, xlate_flags);
+ reg_t transformed_addr = access_info.transformed_vaddr;
if (actually_store) {
reg_t trig_len = len;
const uint8_t* trig_bytes = bytes;
while (trig_len > sizeof(reg_t)) {
- check_triggers(triggers::OPERATION_STORE, addr, access_info.effective_virt, reg_from_bytes(sizeof(reg_t), trig_bytes));
+ check_triggers(triggers::OPERATION_STORE, transformed_addr, access_info.effective_virt, reg_from_bytes(sizeof(reg_t), trig_bytes));
trig_len -= sizeof(reg_t);
trig_bytes += sizeof(reg_t);
}
- check_triggers(triggers::OPERATION_STORE, addr, access_info.effective_virt, reg_from_bytes(trig_len, trig_bytes));
+ check_triggers(triggers::OPERATION_STORE, transformed_addr, access_info.effective_virt, reg_from_bytes(trig_len, trig_bytes));
}
- if (addr & (len - 1)) {
+ if (transformed_addr & (len - 1)) {
bool gva = access_info.effective_virt;
if (!is_misaligned_enabled())
- throw trap_store_address_misaligned(gva, addr, 0, 0);
+ throw trap_store_address_misaligned(gva, transformed_addr, 0, 0);
if (require_alignment)
- throw trap_store_access_fault(gva, addr, 0, 0);
+ throw trap_store_access_fault(gva, transformed_addr, 0, 0);
- reg_t len_page0 = std::min(len, PGSIZE - addr % PGSIZE);
+ reg_t len_page0 = std::min(len, PGSIZE - transformed_addr % PGSIZE);
store_slow_path_intrapage(len_page0, bytes, access_info, actually_store);
- if (len_page0 != len)
- store_slow_path_intrapage(len - len_page0, bytes + len_page0, access_info.split_misaligned_access(len_page0), actually_store);
+ if (len_page0 != len) {
+ auto tail_access_info = generate_access_info(original_addr + len_page0, STORE, xlate_flags);
+ store_slow_path_intrapage(len - len_page0, bytes + len_page0, tail_access_info, actually_store);
+ }
} else {
store_slow_path_intrapage(len, bytes, access_info, actually_store);
}
+
+ if (actually_store && proc && unlikely(proc->get_log_commits_enabled()))
+ proc->state.log_mem_write.push_back(std::make_tuple(original_addr, reg_from_bytes(len, bytes), len));
}
tlb_entry_t mmu_t::refill_tlb(reg_t vaddr, reg_t paddr, char* host_addr, access_type type)
{
reg_t idx = (vaddr >> PGSHIFT) % TLB_ENTRIES;
reg_t expected_tag = vaddr >> PGSHIFT;
+ reg_t base_paddr = paddr & ~reg_t(PGSIZE - 1);
- tlb_entry_t entry = {host_addr - vaddr, paddr - vaddr};
+ tlb_entry_t entry = {uintptr_t(host_addr) - (vaddr % PGSIZE), paddr - (vaddr % PGSIZE)};
- if (in_mprv())
+ if (in_mprv()
+ || !pmp_homogeneous(base_paddr, PGSIZE)
+ || (proc && proc->get_log_commits_enabled()))
return entry;
- if ((tlb_load_tag[idx] & ~TLB_CHECK_TRIGGERS) != expected_tag)
- tlb_load_tag[idx] = -1;
- if ((tlb_store_tag[idx] & ~TLB_CHECK_TRIGGERS) != expected_tag)
- tlb_store_tag[idx] = -1;
- if ((tlb_insn_tag[idx] & ~TLB_CHECK_TRIGGERS) != expected_tag)
- tlb_insn_tag[idx] = -1;
-
- if ((check_triggers_fetch && type == FETCH) ||
- (check_triggers_load && type == LOAD) ||
- (check_triggers_store && type == STORE))
- expected_tag |= TLB_CHECK_TRIGGERS;
-
- if (pmp_homogeneous(paddr & ~reg_t(PGSIZE - 1), PGSIZE)) {
- if (type == FETCH) tlb_insn_tag[idx] = expected_tag;
- else if (type == STORE) tlb_store_tag[idx] = expected_tag;
- else tlb_load_tag[idx] = expected_tag;
+ auto trace_flag = tracer.interested_in_range(base_paddr, base_paddr + PGSIZE, type) ? TLB_CHECK_TRACER : 0;
+ auto mmio_flag = host_addr ? 0 : TLB_MMIO;
+
+ switch (type) {
+ case FETCH:
+ tlb_insn[idx].data = entry;
+ tlb_insn[idx].tag = expected_tag | (check_triggers_fetch ? TLB_CHECK_TRIGGERS : 0) | trace_flag | mmio_flag;
+ break;
+ case LOAD:
+ tlb_load[idx].data = entry;
+ tlb_load[idx].tag = expected_tag | (check_triggers_load ? TLB_CHECK_TRIGGERS : 0) | trace_flag | mmio_flag;
+ break;
+ case STORE:
+ tlb_store[idx].data = entry;
+ tlb_store[idx].tag = expected_tag | (check_triggers_store ? TLB_CHECK_TRIGGERS : 0) | trace_flag | mmio_flag;
+ break;
+ default:
+ abort();
}
- tlb_data[idx] = entry;
return entry;
}
@@ -399,7 +468,7 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty
int maxgpabits = vm.levels * vm.idxbits + vm.widenbits + PGSHIFT;
reg_t maxgpa = (1ULL << maxgpabits) - 1;
- bool mxr = proc->state.sstatus->readvirt(false) & MSTATUS_MXR;
+ bool mxr = !is_for_vs_pt_addr && (proc->state.sstatus->readvirt(false) & MSTATUS_MXR);
// tinst is set to 0x3000/0x3020 - for RV64 read/write respectively for
// VS-stage address translation (for spike HSXLEN == VSXLEN always) else
// tinst is set to 0x2000/0x2020 - for RV32 read/write respectively for
@@ -422,6 +491,7 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty
reg_t ppn = (pte & ~reg_t(PTE_ATTR)) >> PTE_PPN_SHIFT;
bool pbmte = proc->get_state()->menvcfg->read() & MENVCFG_PBMTE;
bool hade = proc->get_state()->menvcfg->read() & MENVCFG_ADUE;
+ int napot_bits = ((pte & PTE_N) ? (ctz(ppn) + 1) : 0);
if (pte & PTE_RSVD) {
break;
@@ -437,6 +507,8 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty
base = ppn << PGSHIFT;
} else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
break;
+ } else if (((pte & PTE_N) && (ppn == 0 || i != 0)) || (napot_bits != 0 && napot_bits != 4)) {
+ break;
} else if (!(pte & PTE_U)) {
break;
} else if (type == FETCH || hlvx ? !(pte & PTE_X) :
@@ -461,10 +533,6 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty
reg_t vpn = gpa >> PGSHIFT;
reg_t page_mask = (reg_t(1) << PGSHIFT) - 1;
- int napot_bits = ((pte & PTE_N) ? (ctz(ppn) + 1) : 0);
- if (((pte & PTE_N) && (ppn == 0 || i != 0)) || (napot_bits != 0 && napot_bits != 4))
- break;
-
reg_t page_base = ((ppn & ~((reg_t(1) << napot_bits) - 1))
| (vpn & ((reg_t(1) << napot_bits) - 1))
| (vpn & ((reg_t(1) << ptshift) - 1))) << PGSHIFT;
@@ -484,7 +552,7 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty
reg_t mmu_t::walk(mem_access_info_t access_info)
{
access_type type = access_info.type;
- reg_t addr = access_info.vaddr;
+ reg_t addr = access_info.transformed_vaddr;
bool virt = access_info.effective_virt;
bool hlvx = access_info.flags.hlvx;
reg_t mode = access_info.effective_priv;
@@ -496,7 +564,7 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
if (ss_access) {
if (vm.levels == 0)
- trap_store_access_fault(virt, addr, 0, 0);
+ throw trap_store_access_fault(virt, addr, 0, 0);
type = STORE;
}
@@ -526,6 +594,8 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
bool pbmte = virt ? (proc->get_state()->henvcfg->read() & HENVCFG_PBMTE) : (proc->get_state()->menvcfg->read() & MENVCFG_PBMTE);
bool hade = virt ? (proc->get_state()->henvcfg->read() & HENVCFG_ADUE) : (proc->get_state()->menvcfg->read() & MENVCFG_ADUE);
bool sse = virt ? (proc->get_state()->henvcfg->read() & HENVCFG_SSE) : (proc->get_state()->menvcfg->read() & MENVCFG_SSE);
+ bool ss_page = !(pte & PTE_R) && (pte & PTE_W) && !(pte & PTE_X);
+ int napot_bits = ((pte & PTE_N) ? (ctz(ppn) + 1) : 0);
if (pte & PTE_RSVD) {
break;
@@ -547,21 +617,23 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
// not shadow stack access xwr=110 or xwr=010 page cause page fault
// shadow stack access with PTE_X moved to following check
break;
- } else if ((!(pte & PTE_R) && (pte & PTE_W) && !(pte & PTE_X)) && (type == STORE && !ss_access)) {
- // not shadow stack store and xwr = 010 cause access-fault
+ } else if (((pte & PTE_N) && (ppn == 0 || i != 0)) || (napot_bits != 0 && napot_bits != 4)) {
+ break;
+ } else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) {
+ break;
+ } else if (ss_page && ((type == STORE && !ss_access) || access_info.flags.clean_inval)) {
+ // non-shadow-stack store or CBO with xwr = 010 causes access-fault
throw trap_store_access_fault(virt, addr, 0, 0);
- } else if ((!(pte & PTE_R) && (pte & PTE_W) && !(pte & PTE_X)) && type == FETCH) {
+ } else if (ss_page && type == FETCH) {
// fetch from shadow stack pages cause instruction access-fault
throw trap_instruction_access_fault(virt, addr, 0, 0);
} else if ((((pte & PTE_R) && (pte & PTE_W)) || (pte & PTE_X)) && ss_access) {
// shadow stack access cause store access fault if xwr!=010 and xwr!=001
throw trap_store_access_fault(virt, addr, 0, 0);
} else if (type == FETCH || hlvx ? !(pte & PTE_X) :
- type == LOAD ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) :
+ type == LOAD ? !(sse && ss_page) && !(pte & PTE_R) && !(mxr && (pte & PTE_X)) :
!(pte & PTE_W)) {
break;
- } else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) {
- break;
} else {
reg_t ad = PTE_A | ((type == STORE) * PTE_D);
@@ -581,10 +653,6 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
// for superpage or Svnapot NAPOT mappings, make a fake leaf PTE for the TLB's benefit.
reg_t vpn = addr >> PGSHIFT;
- int napot_bits = ((pte & PTE_N) ? (ctz(ppn) + 1) : 0);
- if (((pte & PTE_N) && (ppn == 0 || i != 0)) || (napot_bits != 0 && napot_bits != 4))
- break;
-
reg_t page_base = ((ppn & ~((reg_t(1) << napot_bits) - 1))
| (vpn & ((reg_t(1) << napot_bits) - 1))
| (vpn & ((reg_t(1) << ptshift) - 1))) << PGSHIFT;
@@ -606,3 +674,55 @@ void mmu_t::register_memtracer(memtracer_t* t)
flush_tlb();
tracer.hook(t);
}
+
+reg_t mmu_t::get_pmlen(bool effective_virt, reg_t effective_priv, xlate_flags_t flags) const {
+ if (!proc || proc->get_xlen() != 64 || flags.hlvx)
+ return 0;
+
+ reg_t pmm = 0;
+ if (effective_priv == PRV_M)
+ pmm = get_field(proc->state.mseccfg->read(), MSECCFG_PMM);
+ else if ((proc->state.sstatus->readvirt(false) | proc->state.sstatus->readvirt(effective_virt)) & MSTATUS_MXR)
+ pmm = 0;
+ else if (!effective_virt && (effective_priv == PRV_S || (!proc->extension_enabled('S') && effective_priv == PRV_U)))
+ pmm = get_field(proc->state.menvcfg->read(), MENVCFG_PMM);
+ else if (effective_virt && effective_priv == PRV_S)
+ pmm = get_field(proc->state.henvcfg->read(), HENVCFG_PMM);
+ else if (proc->state.prv == PRV_U && flags.forced_virt)
+ pmm = get_field(proc->state.hstatus->read(), HSTATUS_HUPMM);
+ else if (effective_priv == PRV_U)
+ pmm = get_field(proc->state.senvcfg->read(), SENVCFG_PMM);
+ else
+ assert(false);
+
+ switch (pmm) {
+ case 2: return 7;
+ case 3: return 16;
+ }
+ return 0;
+}
+
+mem_access_info_t mmu_t::generate_access_info(reg_t addr, access_type type, xlate_flags_t xlate_flags) {
+ if (!proc)
+ return {addr, addr, 0, false, {}, type};
+ bool virt = proc->state.v;
+ reg_t mode = proc->state.prv;
+ reg_t transformed_addr = addr;
+ if (type != FETCH) {
+ if (in_mprv()) {
+ mode = get_field(proc->state.mstatus->read(), MSTATUS_MPP);
+ if (get_field(proc->state.mstatus->read(), MSTATUS_MPV) && mode != PRV_M)
+ virt = true;
+ }
+ if (xlate_flags.forced_virt) {
+ virt = true;
+ mode = get_field(proc->state.hstatus->read(), HSTATUS_SPVP);
+ }
+ auto xlen = proc->get_const_xlen();
+ reg_t pmlen = get_pmlen(virt, mode, xlate_flags);
+ reg_t satp = proc->state.satp->readvirt(virt);
+ bool is_physical_addr = mode == PRV_M || get_field(satp, SATP64_MODE) == SATP_MODE_OFF;
+ transformed_addr = is_physical_addr ? zext(addr, xlen - pmlen) : sext(addr, xlen - pmlen);
+ }
+ return {addr, transformed_addr, mode, virt, xlate_flags, type};
+}
diff --git a/riscv/mmu.h b/riscv/mmu.h
index 3e4ae9a..94f3a97 100644
--- a/riscv/mmu.h
+++ b/riscv/mmu.h
@@ -18,8 +18,22 @@
// virtual memory configuration
#define PGSHIFT 12
const reg_t PGSIZE = 1 << PGSHIFT;
-const reg_t PGMASK = ~(PGSIZE-1);
-#define MAX_PADDR_BITS 56 // imposed by Sv39 / Sv48
+#define MAX_PADDR_BITS 64
+
+// observability hooks for load, store and fetch
+// intentionally empty not to cause runtime overhead
+// can be redefined if needed
+#ifndef MMU_OBSERVE_FETCH
+#define MMU_OBSERVE_FETCH(addr, insn, length)
+#endif
+
+#ifndef MMU_OBSERVE_LOAD
+#define MMU_OBSERVE_LOAD(addr, data, length)
+#endif
+
+#ifndef MMU_OBSERVE_STORE
+#define MMU_OBSERVE_STORE(addr, data, length)
+#endif
struct insn_fetch_t
{
@@ -34,8 +48,13 @@ struct icache_entry_t {
};
struct tlb_entry_t {
- char* host_offset;
- reg_t target_offset;
+ uintptr_t host_addr;
+ reg_t target_addr;
+};
+
+struct dtlb_entry_t {
+ tlb_entry_t data;
+ reg_t tag;
};
struct xlate_flags_t {
@@ -43,22 +62,20 @@ struct xlate_flags_t {
const bool hlvx : 1 {false};
const bool lr : 1 {false};
const bool ss_access : 1 {false};
+ const bool clean_inval : 1 {false};
bool is_special_access() const {
- return forced_virt || hlvx || lr || ss_access;
+ return forced_virt || hlvx || lr || ss_access || clean_inval;
}
};
struct mem_access_info_t {
const reg_t vaddr;
+ const reg_t transformed_vaddr;
const reg_t effective_priv;
const bool effective_virt;
const xlate_flags_t flags;
const access_type type;
-
- mem_access_info_t split_misaligned_access(reg_t offset) const {
- return {vaddr + offset, effective_priv, effective_virt, flags, type};
- }
};
void throw_access_exception(bool virt, reg_t addr, access_type type);
@@ -68,47 +85,26 @@ void throw_access_exception(bool virt, reg_t addr, access_type type);
class mmu_t
{
private:
- std::map<reg_t, reg_t> alloc_cache;
- std::vector<std::pair<reg_t, reg_t >> addr_tbl;
-
- mem_access_info_t generate_access_info(reg_t addr, access_type type, xlate_flags_t xlate_flags) {
- if (!proc)
- return {addr, 0, false, {}, type};
- bool virt = proc->state.v;
- reg_t mode = proc->state.prv;
- if (type != FETCH) {
- if (in_mprv()) {
- mode = get_field(proc->state.mstatus->read(), MSTATUS_MPP);
- if (get_field(proc->state.mstatus->read(), MSTATUS_MPV) && mode != PRV_M)
- virt = true;
- }
- if (xlate_flags.forced_virt) {
- virt = true;
- mode = get_field(proc->state.hstatus->read(), HSTATUS_SPVP);
- }
- }
- return {addr, mode, virt, xlate_flags, type};
- }
+ reg_t get_pmlen(bool effective_virt, reg_t effective_priv, xlate_flags_t flags) const;
+ mem_access_info_t generate_access_info(reg_t addr, access_type type, xlate_flags_t xlate_flags);
public:
- mmu_t(simif_t* sim, endianness_t endianness, processor_t* proc);
+ mmu_t(simif_t* sim, endianness_t endianness, processor_t* proc, reg_t cache_blocksz);
~mmu_t();
template<typename T>
T ALWAYS_INLINE load(reg_t addr, xlate_flags_t xlate_flags = {}) {
target_endian<T> res;
- reg_t vpn = addr >> PGSHIFT;
bool aligned = (addr & (sizeof(T) - 1)) == 0;
- bool tlb_hit = tlb_load_tag[vpn % TLB_ENTRIES] == vpn;
+ auto [tlb_hit, host_addr, _] = access_tlb(tlb_load, addr);
if (likely(!xlate_flags.is_special_access() && aligned && tlb_hit)) {
- res = *(target_endian<T>*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr);
+ res = *(target_endian<T>*)host_addr;
} else {
load_slow_path(addr, sizeof(T), (uint8_t*)&res, xlate_flags);
}
- if (unlikely(proc && proc->get_log_commits_enabled()))
- proc->state.log_mem_read.push_back(std::make_tuple(addr, 0, sizeof(T)));
+ MMU_OBSERVE_LOAD(addr,from_target(res),sizeof(T));
return from_target(res);
}
@@ -138,19 +134,16 @@ public:
template<typename T>
void ALWAYS_INLINE store(reg_t addr, T val, xlate_flags_t xlate_flags = {}) {
- reg_t vpn = addr >> PGSHIFT;
+ MMU_OBSERVE_STORE(addr, val, sizeof(T));
bool aligned = (addr & (sizeof(T) - 1)) == 0;
- bool tlb_hit = tlb_store_tag[vpn % TLB_ENTRIES] == vpn;
+ auto [tlb_hit, host_addr, _] = access_tlb(tlb_store, addr);
if (!xlate_flags.is_special_access() && likely(aligned && tlb_hit)) {
- *(target_endian<T>*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr) = to_target(val);
+ *(target_endian<T>*)host_addr = to_target(val);
} else {
target_endian<T> target_val = to_target(val);
store_slow_path(addr, sizeof(T), (const uint8_t*)&target_val, xlate_flags, true, false);
}
-
- if (unlikely(proc && proc->get_log_commits_enabled()))
- proc->state.log_mem_write.push_back(std::make_tuple(addr, val, sizeof(T)));
}
template<typename T>
@@ -232,28 +225,37 @@ public:
throw trap_load_address_misaligned((proc) ? proc->state.v : false, addr, 0, 0);
}
- return (float128_t){load<uint64_t>(addr), load<uint64_t>(addr + 8)};
+ float128_t res;
+ res.v[0] = load<uint64_t>(addr);
+ res.v[1] = load<uint64_t>(addr + 8);
+ return res;
}
void cbo_zero(reg_t addr) {
- auto base = addr & ~(blocksz - 1);
+ auto access_info = generate_access_info(addr, STORE, {});
+ reg_t transformed_addr = access_info.transformed_vaddr;
+
+ auto base = transformed_addr & ~(blocksz - 1);
for (size_t offset = 0; offset < blocksz; offset += 1) {
- check_triggers(triggers::OPERATION_STORE, base + offset, false, addr, std::nullopt);
+ check_triggers(triggers::OPERATION_STORE, base + offset, false, transformed_addr, std::nullopt);
store<uint8_t>(base + offset, 0);
}
}
void clean_inval(reg_t addr, bool clean, bool inval) {
- auto base = addr & ~(blocksz - 1);
+ auto access_info = generate_access_info(addr, LOAD, {.clean_inval = true});
+ reg_t transformed_addr = access_info.transformed_vaddr;
+
+ auto base = transformed_addr & ~(blocksz - 1);
for (size_t offset = 0; offset < blocksz; offset += 1)
- check_triggers(triggers::OPERATION_STORE, base + offset, false, addr, std::nullopt);
+ check_triggers(triggers::OPERATION_STORE, base + offset, false, transformed_addr, std::nullopt);
convert_load_traps_to_store_traps({
- const reg_t paddr = translate(generate_access_info(addr, LOAD, {}), 1);
+ const reg_t paddr = translate(access_info, 1);
if (sim->reservable(paddr)) {
if (tracer.interested_in_range(paddr, paddr + PGSIZE, LOAD))
tracer.clean_invalidate(paddr, blocksz, clean, inval);
} else {
- throw trap_store_access_fault((proc) ? proc->state.v : false, addr, 0, 0);
+ throw trap_store_access_fault((proc) ? proc->state.v : false, transformed_addr, 0, 0);
}
})
}
@@ -299,31 +301,32 @@ public:
template<typename T>
T ALWAYS_INLINE fetch_jump_table(reg_t addr) {
- auto tlb_entry = translate_insn_addr(addr);
- return from_target(*(target_endian<T>*)(tlb_entry.host_offset + addr));
+ T res = 0;
+ for (size_t i = 0; i < sizeof(T) / sizeof(insn_parcel_t); i++)
+ res |= (T)fetch_insn_parcel(addr + i * sizeof(insn_parcel_t)) << (i * sizeof(insn_parcel_t) * 8);
+
+ // table accesses use data endianness, not instruction (little) endianness
+ return target_big_endian ? to_be(res) : res;
}
inline icache_entry_t* refill_icache(reg_t addr, icache_entry_t* entry)
{
- if (matched_trigger)
- throw *matched_trigger;
+ insn_bits_t insn = fetch_insn_parcel(addr);
- auto tlb_entry = translate_insn_addr(addr);
- insn_bits_t insn = from_le(*(uint16_t*)(tlb_entry.host_offset + addr));
int length = insn_length(insn);
if (likely(length == 4)) {
- insn |= (insn_bits_t)from_le(*(const uint16_t*)translate_insn_addr_to_host(addr + 2)) << 16;
+ insn |= (insn_bits_t)fetch_insn_parcel(addr + 2) << 16;
} else if (length == 2) {
// entire instruction already fetched
} else if (length == 6) {
- insn |= (insn_bits_t)from_le(*(const uint16_t*)translate_insn_addr_to_host(addr + 2)) << 16;
- insn |= (insn_bits_t)from_le(*(const uint16_t*)translate_insn_addr_to_host(addr + 4)) << 32;
+ insn |= (insn_bits_t)fetch_insn_parcel(addr + 2) << 16;
+ insn |= (insn_bits_t)fetch_insn_parcel(addr + 4) << 32;
} else {
static_assert(sizeof(insn_bits_t) == 8, "insn_bits_t must be uint64_t");
- insn |= (insn_bits_t)from_le(*(const uint16_t*)translate_insn_addr_to_host(addr + 2)) << 16;
- insn |= (insn_bits_t)from_le(*(const uint16_t*)translate_insn_addr_to_host(addr + 4)) << 32;
- insn |= (insn_bits_t)from_le(*(const uint16_t*)translate_insn_addr_to_host(addr + 6)) << 48;
+ insn |= (insn_bits_t)fetch_insn_parcel(addr + 2) << 16;
+ insn |= (insn_bits_t)fetch_insn_parcel(addr + 4) << 32;
+ insn |= (insn_bits_t)fetch_insn_parcel(addr + 6) << 48;
}
insn_fetch_t fetch = {proc->decode_insn(insn), insn};
@@ -331,19 +334,24 @@ public:
entry->next = &icache[icache_index(addr + length)];
entry->data = fetch;
- reg_t paddr = tlb_entry.target_offset + addr;;
- if (tracer.interested_in_range(paddr, paddr + 1, FETCH)) {
- entry->tag = -1;
- tracer.trace(paddr, length, FETCH);
+ auto [check_tracer, _, paddr] = access_tlb(tlb_insn, addr, TLB_FLAGS, TLB_CHECK_TRACER);
+ if (unlikely(check_tracer)) {
+ if (tracer.interested_in_range(paddr, paddr + 1, FETCH)) {
+ entry->tag = -1;
+ tracer.trace(paddr, paddr + length, FETCH);
+ }
}
+ MMU_OBSERVE_FETCH(addr, insn, length);
return entry;
}
inline icache_entry_t* access_icache(reg_t addr)
{
icache_entry_t* entry = &icache[icache_index(addr)];
- if (likely(entry->tag == addr))
+ if (likely(entry->tag == addr)){
+ MMU_OBSERVE_FETCH(addr, entry->data.insn, insn_length(entry->data.insn.bits()));
return entry;
+ }
return refill_icache(addr, entry);
}
@@ -353,6 +361,17 @@ public:
return refill_icache(addr, &entry)->data;
}
+ std::tuple<bool, uintptr_t, reg_t> ALWAYS_INLINE access_tlb(const dtlb_entry_t* tlb, reg_t vaddr, reg_t allowed_flags = 0, reg_t required_flags = 0)
+ {
+ auto vpn = vaddr / PGSIZE, pgoff = vaddr % PGSIZE;
+ auto& entry = tlb[vpn % TLB_ENTRIES];
+ auto hit = likely((entry.tag & (~allowed_flags | required_flags)) == (vpn | required_flags));
+ bool mmio = allowed_flags & TLB_MMIO & entry.tag;
+ auto host_addr = mmio ? 0 : entry.data.host_addr + pgoff;
+ auto paddr = entry.data.target_addr + pgoff;
+ return std::make_tuple(hit, host_addr, paddr);
+ }
+
void flush_tlb();
void flush_icache();
@@ -378,17 +397,11 @@ public:
return target_big_endian? target_endian<T>::to_be(n) : target_endian<T>::to_le(n);
}
- void set_cache_blocksz(reg_t size)
- {
- blocksz = size;
- }
-
private:
simif_t* sim;
processor_t* proc;
memtracer_list_t tracer;
reg_t load_reservation_address;
- uint16_t fetch_temp;
reg_t blocksz;
// implement an instruction cache for simulator performance
@@ -399,10 +412,12 @@ private:
// If a TLB tag has TLB_CHECK_TRIGGERS set, then the MMU must check for a
// trigger match before completing an access.
static const reg_t TLB_CHECK_TRIGGERS = reg_t(1) << 63;
- tlb_entry_t tlb_data[TLB_ENTRIES];
- reg_t tlb_insn_tag[TLB_ENTRIES];
- reg_t tlb_load_tag[TLB_ENTRIES];
- reg_t tlb_store_tag[TLB_ENTRIES];
+ static const reg_t TLB_CHECK_TRACER = reg_t(1) << 62;
+ static const reg_t TLB_MMIO = reg_t(1) << 61;
+ static const reg_t TLB_FLAGS = TLB_CHECK_TRIGGERS | TLB_CHECK_TRACER | TLB_MMIO;
+ dtlb_entry_t tlb_load[TLB_ENTRIES];
+ dtlb_entry_t tlb_store[TLB_ENTRIES];
+ dtlb_entry_t tlb_insn[TLB_ENTRIES];
// finish translation on a TLB miss and update the TLB
tlb_entry_t refill_tlb(reg_t vaddr, reg_t paddr, char* host_addr, access_type type);
@@ -415,11 +430,15 @@ private:
reg_t walk(mem_access_info_t access_info);
// handle uncommon cases: TLB misses, page faults, MMIO
- tlb_entry_t fetch_slow_path(reg_t addr);
- void load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, xlate_flags_t xlate_flags);
+ typedef uint16_t insn_parcel_t;
+ insn_parcel_t fetch_slow_path(reg_t addr);
+ insn_parcel_t perform_intrapage_fetch(reg_t vaddr, uintptr_t host_addr, reg_t paddr);
+ void load_slow_path(reg_t original_addr, reg_t len, uint8_t* bytes, xlate_flags_t xlate_flags);
void load_slow_path_intrapage(reg_t len, uint8_t* bytes, mem_access_info_t access_info);
- void store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, xlate_flags_t xlate_flags, bool actually_store, bool require_alignment);
+ void perform_intrapage_load(reg_t vaddr, uintptr_t host_addr, reg_t paddr, reg_t len, uint8_t* bytes, xlate_flags_t xlate_flags);
+ void store_slow_path(reg_t original_addr, reg_t len, const uint8_t* bytes, xlate_flags_t xlate_flags, bool actually_store, bool require_alignment);
void store_slow_path_intrapage(reg_t len, const uint8_t* bytes, mem_access_info_t access_info, bool actually_store);
+ void perform_intrapage_store(reg_t vaddr, uintptr_t host_addr, reg_t paddr, reg_t len, const uint8_t* bytes, xlate_flags_t xlate_flags);
bool mmio_fetch(reg_t paddr, size_t len, uint8_t* bytes);
bool mmio_load(reg_t paddr, size_t len, uint8_t* bytes);
bool mmio_store(reg_t paddr, size_t len, const uint8_t* bytes);
@@ -478,23 +497,18 @@ private:
}
}
- // ITLB lookup
- inline tlb_entry_t translate_insn_addr(reg_t addr) {
- reg_t vpn = addr >> PGSHIFT;
- if (likely(tlb_insn_tag[vpn % TLB_ENTRIES] == vpn))
- return tlb_data[vpn % TLB_ENTRIES];
- return fetch_slow_path(addr);
- }
+ inline insn_parcel_t fetch_insn_parcel(reg_t addr) {
+ if (auto [tlb_hit, host_addr, paddr] = access_tlb(tlb_insn, addr); tlb_hit)
+ return from_le(*(insn_parcel_t*)host_addr);
- inline const uint16_t* translate_insn_addr_to_host(reg_t addr) {
- return (uint16_t*)(translate_insn_addr(addr).host_offset + addr);
+ return from_le(fetch_slow_path(addr));
}
- inline bool in_mprv()
+ inline bool in_mprv() const
{
return proc != nullptr
&& !(proc->state.mnstatus && !get_field(proc->state.mnstatus->read(), MNSTATUS_NMIE))
- && !proc->state.debug_mode
+ && (!proc->state.debug_mode || get_field(proc->state.dcsr->read(), DCSR_MPRVEN))
&& get_field(proc->state.mstatus->read(), MSTATUS_MPRV);
}
@@ -509,8 +523,7 @@ private:
bool check_triggers_fetch;
bool check_triggers_load;
bool check_triggers_store;
- // The exception describing a matched trigger, or NULL.
- triggers::matched_t *matched_trigger;
+ std::optional<triggers::matched_t> matched_trigger;
friend class processor_t;
};
diff --git a/riscv/ns16550.cc b/riscv/ns16550.cc
index 2805fd8..15e0873 100644
--- a/riscv/ns16550.cc
+++ b/riscv/ns16550.cc
@@ -328,7 +328,7 @@ void ns16550_t::tick(reg_t UNUSED rtc_ticks)
update_interrupt();
}
-std::string ns16550_generate_dts(const sim_t* sim, const std::vector<std::string>& UNUSED sargs)
+std::string ns16550_generate_dts(const sim_t* sim, const std::vector<std::string>& sargs UNUSED)
{
std::stringstream s;
s << std::hex
@@ -348,7 +348,7 @@ std::string ns16550_generate_dts(const sim_t* sim, const std::vector<std::string
return s.str();
}
-ns16550_t* ns16550_parse_from_fdt(const void* fdt, const sim_t* sim, reg_t* base, const std::vector<std::string>& UNUSED sargs)
+ns16550_t* ns16550_parse_from_fdt(const void* fdt, const sim_t* sim, reg_t* base, const std::vector<std::string>& sargs UNUSED)
{
uint32_t ns16550_shift, ns16550_io_width, ns16550_int_id;
if (fdt_parse_ns16550(fdt, base,
diff --git a/riscv/platform.h b/riscv/platform.h
index 7fffdc8..c8a5bf4 100644
--- a/riscv/platform.h
+++ b/riscv/platform.h
@@ -4,6 +4,8 @@
#define DEFAULT_KERNEL_BOOTARGS "console=ttyS0 earlycon"
#define DEFAULT_RSTVEC 0x00001000
+#define DEFAULT_ISA "rv64imafdc_zicntr_zihpm"
+#define DEFAULT_PRIV "MSU"
#define CLINT_BASE 0x02000000
#define CLINT_SIZE 0x000c0000
#define PLIC_BASE 0x0c000000
diff --git a/riscv/plic.cc b/riscv/plic.cc
index 78eb1d2..b6d204b 100644
--- a/riscv/plic.cc
+++ b/riscv/plic.cc
@@ -55,7 +55,7 @@
#define PENDING_BASE 0x1000
/*
- * Each hart context has a vector of interupt enable bits associated with it.
+ * Each hart context has a vector of interrupt enable bits associated with it.
* There's one bit for each interrupt source.
*/
#define ENABLE_BASE 0x2000
@@ -343,7 +343,8 @@ bool plic_t::load(reg_t addr, size_t len, uint8_t* bytes)
return false;
}
- if (PRIORITY_BASE <= addr && addr < PENDING_BASE) {
+ static_assert(PRIORITY_BASE == 0);
+ if (/* PRIORITY_BASE <= addr && */ addr < PENDING_BASE) {
ret = priority_read(addr, &val);
} else if (PENDING_BASE <= addr && addr < ENABLE_BASE) {
ret = pending_read(addr - PENDING_BASE, &val);
@@ -384,7 +385,8 @@ bool plic_t::store(reg_t addr, size_t len, const uint8_t* bytes)
write_little_endian_reg(&val, addr, len, bytes);
- if (PRIORITY_BASE <= addr && addr < ENABLE_BASE) {
+ static_assert(PRIORITY_BASE == 0);
+ if (/* PRIORITY_BASE <= addr && */ addr < ENABLE_BASE) {
ret = priority_write(addr, val);
} else if (ENABLE_BASE <= addr && addr < CONTEXT_BASE) {
uint32_t cntx = (addr - ENABLE_BASE) / ENABLE_PER_HART;
@@ -401,7 +403,7 @@ bool plic_t::store(reg_t addr, size_t len, const uint8_t* bytes)
return ret;
}
-std::string plic_generate_dts(const sim_t* sim, const std::vector<std::string>& UNUSED sargs)
+std::string plic_generate_dts(const sim_t* sim, const std::vector<std::string>& sargs UNUSED)
{
std::stringstream s;
s << std::hex
@@ -424,7 +426,7 @@ std::string plic_generate_dts(const sim_t* sim, const std::vector<std::string>&
return s.str();
}
-plic_t* plic_parse_from_fdt(const void* fdt, const sim_t* sim, reg_t* base, const std::vector<std::string>& UNUSED sargs)
+plic_t* plic_parse_from_fdt(const void* fdt, const sim_t* sim, reg_t* base, const std::vector<std::string>& sargs UNUSED)
{
uint32_t plic_ndev;
if (fdt_parse_plic(fdt, base, &plic_ndev, "riscv,plic0") == 0 ||
diff --git a/riscv/processor.cc b/riscv/processor.cc
index 9498b8f..6fe64ab 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -30,49 +30,51 @@
#undef STATE
#define STATE state
-processor_t::processor_t(const isa_parser_t *isa, const cfg_t *cfg,
+processor_t::processor_t(const char* isa_str, const char* priv_str,
+ const cfg_t *cfg,
simif_t* sim, uint32_t id, bool halt_on_reset,
FILE* log_file, std::ostream& sout_)
- : debug(false), halt_request(HR_NONE), isa(isa), cfg(cfg), sim(sim), id(id), xlen(0),
+: debug(false), halt_request(HR_NONE), isa(isa_str, priv_str), cfg(cfg),
+ sim(sim), id(id), xlen(isa.get_max_xlen()),
histogram_enabled(false), log_commits_enabled(false),
log_file(log_file), sout_(sout_.rdbuf()), halt_on_reset(halt_on_reset),
in_wfi(false), check_triggers_icount(false),
- impl_table(256, false), extension_enable_table(isa->get_extension_table()),
+ impl_table(256, false), extension_enable_table(isa.get_extension_table()),
last_pc(1), executions(1), TM(cfg->trigger_count)
{
VU.p = this;
TM.proc = this;
#ifndef HAVE_INT128
- if (isa->has_any_vector()) {
+ if (isa.has_any_vector()) {
fprintf(stderr, "V extension is not supported on platforms without __int128 type\n");
abort();
}
- if (isa->extension_enabled(EXT_ZACAS) && isa->get_max_xlen() == 64) {
+ if (isa.extension_enabled(EXT_ZACAS) && isa.get_max_xlen() == 64) {
fprintf(stderr, "Zacas extension is not supported on 64-bit platforms without __int128 type\n");
abort();
}
#endif
- VU.VLEN = isa->get_vlen();
- VU.ELEN = isa->get_elen();
- VU.vlenb = isa->get_vlen() / 8;
+ VU.VLEN = isa.get_vlen();
+ VU.ELEN = isa.get_elen();
+ VU.vlenb = isa.get_vlen() / 8;
VU.vstart_alu = 0;
register_base_instructions();
- mmu = new mmu_t(sim, cfg->endianness, this);
+ mmu = new mmu_t(sim, cfg->endianness, this, cfg->cache_blocksz);
- disassembler = new disassembler_t(isa);
- for (auto e : isa->get_extensions())
+ disassembler = new disassembler_t(&isa);
+ for (auto e : isa.get_extensions())
register_extension(find_extension(e.c_str())());
set_pmp_granularity(cfg->pmpgranularity);
set_pmp_num(cfg->pmpregions);
- if (isa->get_max_xlen() == 32)
+ if (isa.get_max_xlen() == 32)
set_mmu_capability(IMPL_MMU_SV32);
- else if (isa->get_max_xlen() == 64)
+ else if (isa.get_max_xlen() == 64)
set_mmu_capability(IMPL_MMU_SV57);
set_impl(IMPL_MMU_ASID, true);
@@ -98,449 +100,21 @@ processor_t::~processor_t()
delete disassembler;
}
-static void bad_option_string(const char *option, const char *value,
- const char *msg)
-{
- fprintf(stderr, "error: bad %s option '%s'. %s\n", option, value, msg);
- abort();
-}
-
-static std::string get_string_token(std::string str, const char delimiter, size_t& pos)
-{
- size_t _pos = pos;
- while (pos < str.length() && str[pos] != delimiter) ++pos;
- return str.substr(_pos, pos - _pos);
-}
-
-static bool check_pow2(int val)
-{
- return ((val & (val - 1))) == 0;
-}
-
-static std::string strtolower(const char* str)
-{
- std::string res;
- for (const char *r = str; *r; r++)
- res += std::tolower(*r);
- return res;
-}
-
-static int xlen_to_uxl(int xlen)
-{
- if (xlen == 32)
- return 1;
- if (xlen == 64)
- return 2;
- abort();
-}
-
void state_t::reset(processor_t* const proc, reg_t max_isa)
{
pc = DEFAULT_RSTVEC;
XPR.reset();
FPR.reset();
- // This assumes xlen is always max_xlen, which is true today (see
- // mstatus_csr_t::unlogged_write()):
- auto xlen = proc->get_isa().get_max_xlen();
-
prv = prev_prv = PRV_M;
v = prev_v = false;
prv_changed = false;
v_changed = false;
- csrmap[CSR_MISA] = misa = std::make_shared<misa_csr_t>(proc, CSR_MISA, max_isa);
- mstatus = std::make_shared<mstatus_csr_t>(proc, CSR_MSTATUS);
- if (xlen == 32) {
- csrmap[CSR_MSTATUS] = std::make_shared<rv32_low_csr_t>(proc, CSR_MSTATUS, mstatus);
- csrmap[CSR_MSTATUSH] = mstatush = std::make_shared<rv32_high_csr_t>(proc, CSR_MSTATUSH, mstatus);
- } else {
- csrmap[CSR_MSTATUS] = mstatus;
- }
- csrmap[CSR_MEPC] = mepc = std::make_shared<epc_csr_t>(proc, CSR_MEPC);
- csrmap[CSR_MTVAL] = mtval = std::make_shared<basic_csr_t>(proc, CSR_MTVAL, 0);
- csrmap[CSR_MSCRATCH] = std::make_shared<basic_csr_t>(proc, CSR_MSCRATCH, 0);
- csrmap[CSR_MTVEC] = mtvec = std::make_shared<tvec_csr_t>(proc, CSR_MTVEC);
- csrmap[CSR_MCAUSE] = mcause = std::make_shared<cause_csr_t>(proc, CSR_MCAUSE);
-
- auto smcntrpmf_enabled = proc->extension_enabled_const(EXT_SMCNTRPMF);
- const reg_t mask = smcntrpmf_enabled ? MHPMEVENT_MINH | MHPMEVENT_SINH |
- MHPMEVENT_UINH | MHPMEVENT_VSINH | MHPMEVENT_VUINH : 0;
- auto minstretcfg = std::make_shared<smcntrpmf_csr_t>(proc, CSR_MINSTRETCFG, mask, 0);
- auto mcyclecfg = std::make_shared<smcntrpmf_csr_t>(proc, CSR_MCYCLECFG, mask, 0);
-
- minstret = std::make_shared<wide_counter_csr_t>(proc, CSR_MINSTRET, minstretcfg);
- mcycle = std::make_shared<wide_counter_csr_t>(proc, CSR_MCYCLE, mcyclecfg);
- time = std::make_shared<time_counter_csr_t>(proc, CSR_TIME);
- if (proc->extension_enabled_const(EXT_ZICNTR)) {
- csrmap[CSR_INSTRET] = std::make_shared<counter_proxy_csr_t>(proc, CSR_INSTRET, minstret);
- csrmap[CSR_CYCLE] = std::make_shared<counter_proxy_csr_t>(proc, CSR_CYCLE, mcycle);
- csrmap[CSR_TIME] = time_proxy = std::make_shared<counter_proxy_csr_t>(proc, CSR_TIME, time);
- }
- if (xlen == 32) {
- csr_t_p minstreth, mcycleh;
- csrmap[CSR_MINSTRET] = std::make_shared<rv32_low_csr_t>(proc, CSR_MINSTRET, minstret);
- csrmap[CSR_MINSTRETH] = minstreth = std::make_shared<rv32_high_csr_t>(proc, CSR_MINSTRETH, minstret);
- csrmap[CSR_MCYCLE] = std::make_shared<rv32_low_csr_t>(proc, CSR_MCYCLE, mcycle);
- csrmap[CSR_MCYCLEH] = mcycleh = std::make_shared<rv32_high_csr_t>(proc, CSR_MCYCLEH, mcycle);
- if (proc->extension_enabled_const(EXT_ZICNTR)) {
- auto timeh = std::make_shared<rv32_high_csr_t>(proc, CSR_TIMEH, time);
- csrmap[CSR_INSTRETH] = std::make_shared<counter_proxy_csr_t>(proc, CSR_INSTRETH, minstreth);
- csrmap[CSR_CYCLEH] = std::make_shared<counter_proxy_csr_t>(proc, CSR_CYCLEH, mcycleh);
- csrmap[CSR_TIMEH] = std::make_shared<counter_proxy_csr_t>(proc, CSR_TIMEH, timeh);
- }
- } else {
- csrmap[CSR_MINSTRET] = minstret;
- csrmap[CSR_MCYCLE] = mcycle;
- }
- for (reg_t i = 3; i < N_HPMCOUNTERS + 3; ++i) {
- const reg_t which_mevent = CSR_MHPMEVENT3 + i - 3;
- const reg_t which_meventh = CSR_MHPMEVENT3H + i - 3;
- const reg_t which_mcounter = CSR_MHPMCOUNTER3 + i - 3;
- const reg_t which_mcounterh = CSR_MHPMCOUNTER3H + i - 3;
- const reg_t which_counter = CSR_HPMCOUNTER3 + i - 3;
- const reg_t which_counterh = CSR_HPMCOUNTER3H + i - 3;
- mevent[i - 3] = std::make_shared<mevent_csr_t>(proc, which_mevent);
- auto mcounter = std::make_shared<const_csr_t>(proc, which_mcounter, 0);
- csrmap[which_mcounter] = mcounter;
-
- if (proc->extension_enabled_const(EXT_ZIHPM)) {
- auto counter = std::make_shared<counter_proxy_csr_t>(proc, which_counter, mcounter);
- csrmap[which_counter] = counter;
- }
- if (xlen == 32) {
- csrmap[which_mevent] = std::make_shared<rv32_low_csr_t>(proc, which_mevent, mevent[i - 3]);;
- auto mcounterh = std::make_shared<const_csr_t>(proc, which_mcounterh, 0);
- csrmap[which_mcounterh] = mcounterh;
- if (proc->extension_enabled_const(EXT_ZIHPM)) {
- auto counterh = std::make_shared<counter_proxy_csr_t>(proc, which_counterh, mcounterh);
- csrmap[which_counterh] = counterh;
- }
- if (proc->extension_enabled_const(EXT_SSCOFPMF)) {
- auto meventh = std::make_shared<rv32_high_csr_t>(proc, which_meventh, mevent[i - 3]);
- csrmap[which_meventh] = meventh;
- }
- } else {
- csrmap[which_mevent] = mevent[i - 3];
- }
- }
- csrmap[CSR_MCOUNTINHIBIT] = std::make_shared<const_csr_t>(proc, CSR_MCOUNTINHIBIT, 0);
- if (proc->extension_enabled_const(EXT_SSCOFPMF))
- csrmap[CSR_SCOUNTOVF] = std::make_shared<scountovf_csr_t>(proc, CSR_SCOUNTOVF);
- csrmap[CSR_MIE] = mie = std::make_shared<mie_csr_t>(proc, CSR_MIE);
- csrmap[CSR_MIP] = mip = std::make_shared<mip_csr_t>(proc, CSR_MIP);
- auto sip_sie_accr = std::make_shared<generic_int_accessor_t>(
- this,
- ~MIP_HS_MASK, // read_mask
- MIP_SSIP | MIP_LCOFIP, // ip_write_mask
- ~MIP_HS_MASK, // ie_write_mask
- generic_int_accessor_t::mask_mode_t::MIDELEG,
- 0 // shiftamt
- );
-
- auto hip_hie_accr = std::make_shared<generic_int_accessor_t>(
- this,
- MIP_HS_MASK, // read_mask
- MIP_VSSIP, // ip_write_mask
- MIP_HS_MASK, // ie_write_mask
- generic_int_accessor_t::mask_mode_t::MIDELEG,
- 0 // shiftamt
- );
-
- auto vsip_vsie_accr = std::make_shared<generic_int_accessor_t>(
- this,
- MIP_VS_MASK, // read_mask
- MIP_VSSIP, // ip_write_mask
- MIP_VS_MASK, // ie_write_mask
- generic_int_accessor_t::mask_mode_t::HIDELEG,
- 1 // shiftamt
- );
-
- auto nonvirtual_sip = std::make_shared<mip_proxy_csr_t>(proc, CSR_SIP, sip_sie_accr);
- auto vsip = std::make_shared<mip_proxy_csr_t>(proc, CSR_VSIP, vsip_vsie_accr);
- csrmap[CSR_VSIP] = vsip;
- csrmap[CSR_SIP] = std::make_shared<virtualized_csr_t>(proc, nonvirtual_sip, vsip);
- csrmap[CSR_HIP] = std::make_shared<mip_proxy_csr_t>(proc, CSR_HIP, hip_hie_accr);
- csrmap[CSR_HVIP] = hvip = std::make_shared<hvip_csr_t>(proc, CSR_HVIP, 0);
-
- auto nonvirtual_sie = std::make_shared<mie_proxy_csr_t>(proc, CSR_SIE, sip_sie_accr);
- auto vsie = std::make_shared<mie_proxy_csr_t>(proc, CSR_VSIE, vsip_vsie_accr);
- csrmap[CSR_VSIE] = vsie;
- csrmap[CSR_SIE] = std::make_shared<virtualized_csr_t>(proc, nonvirtual_sie, vsie);
- csrmap[CSR_HIE] = std::make_shared<mie_proxy_csr_t>(proc, CSR_HIE, hip_hie_accr);
-
- csrmap[CSR_MEDELEG] = medeleg = std::make_shared<medeleg_csr_t>(proc, CSR_MEDELEG);
- csrmap[CSR_MIDELEG] = mideleg = std::make_shared<mideleg_csr_t>(proc, CSR_MIDELEG);
- const reg_t counteren_mask = (proc->extension_enabled_const(EXT_ZICNTR) ? 0x7UL : 0x0) | (proc->extension_enabled_const(EXT_ZIHPM) ? 0xfffffff8ULL : 0x0);
- mcounteren = std::make_shared<masked_csr_t>(proc, CSR_MCOUNTEREN, counteren_mask, 0);
- if (proc->extension_enabled_const('U')) csrmap[CSR_MCOUNTEREN] = mcounteren;
- csrmap[CSR_SCOUNTEREN] = scounteren = std::make_shared<masked_csr_t>(proc, CSR_SCOUNTEREN, counteren_mask, 0);
- nonvirtual_sepc = std::make_shared<epc_csr_t>(proc, CSR_SEPC);
- csrmap[CSR_VSEPC] = vsepc = std::make_shared<epc_csr_t>(proc, CSR_VSEPC);
- csrmap[CSR_SEPC] = sepc = std::make_shared<virtualized_csr_t>(proc, nonvirtual_sepc, vsepc);
- nonvirtual_stval = std::make_shared<basic_csr_t>(proc, CSR_STVAL, 0);
- csrmap[CSR_VSTVAL] = vstval = std::make_shared<basic_csr_t>(proc, CSR_VSTVAL, 0);
- csrmap[CSR_STVAL] = stval = std::make_shared<virtualized_csr_t>(proc, nonvirtual_stval, vstval);
- auto sscratch = std::make_shared<basic_csr_t>(proc, CSR_SSCRATCH, 0);
- auto vsscratch = std::make_shared<basic_csr_t>(proc, CSR_VSSCRATCH, 0);
- // Note: if max_isa does not include H, we don't really need this virtualized_csr_t at all (though it doesn't hurt):
- csrmap[CSR_SSCRATCH] = std::make_shared<virtualized_csr_t>(proc, sscratch, vsscratch);
- csrmap[CSR_VSSCRATCH] = vsscratch;
- nonvirtual_stvec = std::make_shared<tvec_csr_t>(proc, CSR_STVEC);
- csrmap[CSR_VSTVEC] = vstvec = std::make_shared<tvec_csr_t>(proc, CSR_VSTVEC);
- csrmap[CSR_STVEC] = stvec = std::make_shared<virtualized_csr_t>(proc, nonvirtual_stvec, vstvec);
- auto nonvirtual_satp = std::make_shared<satp_csr_t>(proc, CSR_SATP);
- csrmap[CSR_VSATP] = vsatp = std::make_shared<base_atp_csr_t>(proc, CSR_VSATP);
- csrmap[CSR_SATP] = satp = std::make_shared<virtualized_satp_csr_t>(proc, nonvirtual_satp, vsatp);
- nonvirtual_scause = std::make_shared<cause_csr_t>(proc, CSR_SCAUSE);
- csrmap[CSR_VSCAUSE] = vscause = std::make_shared<cause_csr_t>(proc, CSR_VSCAUSE);
- csrmap[CSR_SCAUSE] = scause = std::make_shared<virtualized_csr_t>(proc, nonvirtual_scause, vscause);
- csrmap[CSR_MTVAL2] = mtval2 = std::make_shared<hypervisor_csr_t>(proc, CSR_MTVAL2);
- csrmap[CSR_MTINST] = mtinst = std::make_shared<hypervisor_csr_t>(proc, CSR_MTINST);
- const reg_t hstatus_init = set_field((reg_t)0, HSTATUS_VSXL, xlen_to_uxl(proc->get_const_xlen()));
- const reg_t hstatus_mask = HSTATUS_VTSR | HSTATUS_VTW
- | (proc->supports_impl(IMPL_MMU) ? HSTATUS_VTVM : 0)
- | HSTATUS_HU | HSTATUS_SPVP | HSTATUS_SPV | HSTATUS_GVA;
- csrmap[CSR_HSTATUS] = hstatus = std::make_shared<masked_csr_t>(proc, CSR_HSTATUS, hstatus_mask, hstatus_init);
- csrmap[CSR_HGEIE] = std::make_shared<const_csr_t>(proc, CSR_HGEIE, 0);
- csrmap[CSR_HGEIP] = std::make_shared<const_csr_t>(proc, CSR_HGEIP, 0);
- csrmap[CSR_HIDELEG] = hideleg = std::make_shared<hideleg_csr_t>(proc, CSR_HIDELEG, mideleg);
- const reg_t hedeleg_mask =
- (1 << CAUSE_MISALIGNED_FETCH) |
- (1 << CAUSE_FETCH_ACCESS) |
- (1 << CAUSE_ILLEGAL_INSTRUCTION) |
- (1 << CAUSE_BREAKPOINT) |
- (1 << CAUSE_MISALIGNED_LOAD) |
- (1 << CAUSE_LOAD_ACCESS) |
- (1 << CAUSE_MISALIGNED_STORE) |
- (1 << CAUSE_STORE_ACCESS) |
- (1 << CAUSE_USER_ECALL) |
- (1 << CAUSE_FETCH_PAGE_FAULT) |
- (1 << CAUSE_LOAD_PAGE_FAULT) |
- (1 << CAUSE_STORE_PAGE_FAULT) |
- (1 << CAUSE_SOFTWARE_CHECK_FAULT);
- csrmap[CSR_HEDELEG] = hedeleg = std::make_shared<masked_csr_t>(proc, CSR_HEDELEG, hedeleg_mask, 0);
- csrmap[CSR_HCOUNTEREN] = hcounteren = std::make_shared<masked_csr_t>(proc, CSR_HCOUNTEREN, counteren_mask, 0);
- htimedelta = std::make_shared<basic_csr_t>(proc, CSR_HTIMEDELTA, 0);
- if (xlen == 32) {
- csrmap[CSR_HTIMEDELTA] = std::make_shared<rv32_low_csr_t>(proc, CSR_HTIMEDELTA, htimedelta);
- csrmap[CSR_HTIMEDELTAH] = std::make_shared<rv32_high_csr_t>(proc, CSR_HTIMEDELTAH, htimedelta);
- } else {
- csrmap[CSR_HTIMEDELTA] = htimedelta;
- }
- csrmap[CSR_HTVAL] = htval = std::make_shared<basic_csr_t>(proc, CSR_HTVAL, 0);
- csrmap[CSR_HTINST] = htinst = std::make_shared<basic_csr_t>(proc, CSR_HTINST, 0);
- csrmap[CSR_HGATP] = hgatp = std::make_shared<hgatp_csr_t>(proc, CSR_HGATP);
- nonvirtual_sstatus = std::make_shared<sstatus_proxy_csr_t>(proc, CSR_SSTATUS, mstatus);
- csrmap[CSR_VSSTATUS] = vsstatus = std::make_shared<vsstatus_csr_t>(proc, CSR_VSSTATUS);
- csrmap[CSR_SSTATUS] = sstatus = std::make_shared<sstatus_csr_t>(proc, nonvirtual_sstatus, vsstatus);
-
- csrmap[CSR_DPC] = dpc = std::make_shared<dpc_csr_t>(proc, CSR_DPC);
- csrmap[CSR_DSCRATCH0] = std::make_shared<debug_mode_csr_t>(proc, CSR_DSCRATCH0);
- csrmap[CSR_DSCRATCH1] = std::make_shared<debug_mode_csr_t>(proc, CSR_DSCRATCH1);
- csrmap[CSR_DCSR] = dcsr = std::make_shared<dcsr_csr_t>(proc, CSR_DCSR);
-
- csrmap[CSR_TSELECT] = tselect = std::make_shared<tselect_csr_t>(proc, CSR_TSELECT);
- if (proc->get_cfg().trigger_count > 0) {
- csrmap[CSR_TDATA1] = std::make_shared<tdata1_csr_t>(proc, CSR_TDATA1);
- csrmap[CSR_TDATA2] = tdata2 = std::make_shared<tdata2_csr_t>(proc, CSR_TDATA2);
- csrmap[CSR_TDATA3] = std::make_shared<tdata3_csr_t>(proc, CSR_TDATA3);
- csrmap[CSR_TINFO] = std::make_shared<tinfo_csr_t>(proc, CSR_TINFO);
- csrmap[CSR_TCONTROL] = tcontrol = std::make_shared<masked_csr_t>(proc, CSR_TCONTROL, CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE, 0);
- } else {
- csrmap[CSR_TDATA1] = std::make_shared<const_csr_t>(proc, CSR_TDATA1, 0);
- csrmap[CSR_TDATA2] = tdata2 = std::make_shared<const_csr_t>(proc, CSR_TDATA2, 0);
- csrmap[CSR_TDATA3] = std::make_shared<const_csr_t>(proc, CSR_TDATA3, 0);
- csrmap[CSR_TINFO] = std::make_shared<const_csr_t>(proc, CSR_TINFO, 0);
- csrmap[CSR_TCONTROL] = tcontrol = std::make_shared<const_csr_t>(proc, CSR_TCONTROL, 0);
- }
- unsigned scontext_length = (xlen == 32 ? 16 : 32); // debug spec suggests 16-bit for RV32 and 32-bit for RV64
- csrmap[CSR_SCONTEXT] = scontext = std::make_shared<masked_csr_t>(proc, CSR_SCONTEXT, (reg_t(1) << scontext_length) - 1, 0);
- unsigned hcontext_length = (xlen == 32 ? 6 : 13) + (proc->extension_enabled('H') ? 1 : 0); // debug spec suggest 7-bit (6-bit) for RV32 and 14-bit (13-bit) for RV64 with (without) H extension
- csrmap[CSR_HCONTEXT] = std::make_shared<masked_csr_t>(proc, CSR_HCONTEXT, (reg_t(1) << hcontext_length) - 1, 0);
- csrmap[CSR_MCONTEXT] = mcontext = std::make_shared<proxy_csr_t>(proc, CSR_MCONTEXT, csrmap[CSR_HCONTEXT]);
+ serialized = false;
debug_mode = false;
single_step = STEP_NONE;
- csrmap[CSR_MSECCFG] = mseccfg = std::make_shared<mseccfg_csr_t>(proc, CSR_MSECCFG);
-
- for (int i = 0; i < max_pmp; ++i) {
- csrmap[CSR_PMPADDR0 + i] = pmpaddr[i] = std::make_shared<pmpaddr_csr_t>(proc, CSR_PMPADDR0 + i);
- }
- for (int i = 0; i < max_pmp; i += xlen / 8) {
- reg_t addr = CSR_PMPCFG0 + i / 4;
- csrmap[addr] = std::make_shared<pmpcfg_csr_t>(proc, addr);
- }
-
- csrmap[CSR_FFLAGS] = fflags = std::make_shared<float_csr_t>(proc, CSR_FFLAGS, FSR_AEXC >> FSR_AEXC_SHIFT, 0);
- csrmap[CSR_FRM] = frm = std::make_shared<float_csr_t>(proc, CSR_FRM, FSR_RD >> FSR_RD_SHIFT, 0);
- assert(FSR_AEXC_SHIFT == 0); // composite_csr_t assumes fflags begins at bit 0
- csrmap[CSR_FCSR] = std::make_shared<composite_csr_t>(proc, CSR_FCSR, frm, fflags, FSR_RD_SHIFT);
-
- csrmap[CSR_SEED] = std::make_shared<seed_csr_t>(proc, CSR_SEED);
-
- csrmap[CSR_MARCHID] = std::make_shared<const_csr_t>(proc, CSR_MARCHID, 5);
- csrmap[CSR_MIMPID] = std::make_shared<const_csr_t>(proc, CSR_MIMPID, 0);
- csrmap[CSR_MVENDORID] = std::make_shared<const_csr_t>(proc, CSR_MVENDORID, 0);
- csrmap[CSR_MHARTID] = std::make_shared<const_csr_t>(proc, CSR_MHARTID, proc->get_id());
- csrmap[CSR_MCONFIGPTR] = std::make_shared<const_csr_t>(proc, CSR_MCONFIGPTR, 0);
- if (proc->extension_enabled_const('U')) {
- const reg_t menvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? MENVCFG_CBCFE | MENVCFG_CBIE : 0) |
- (proc->extension_enabled(EXT_ZICBOZ) ? MENVCFG_CBZE : 0) |
- (proc->extension_enabled(EXT_SVADU) ? MENVCFG_ADUE: 0) |
- (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0) |
- (proc->extension_enabled(EXT_SSTC) ? MENVCFG_STCE : 0) |
- (proc->extension_enabled(EXT_ZICFILP) ? MENVCFG_LPE : 0) |
- (proc->extension_enabled(EXT_ZICFISS) ? MENVCFG_SSE : 0);
- const reg_t menvcfg_init = (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0);
- menvcfg = std::make_shared<envcfg_csr_t>(proc, CSR_MENVCFG, menvcfg_mask, menvcfg_init);
- if (xlen == 32) {
- csrmap[CSR_MENVCFG] = std::make_shared<rv32_low_csr_t>(proc, CSR_MENVCFG, menvcfg);
- csrmap[CSR_MENVCFGH] = std::make_shared<rv32_high_csr_t>(proc, CSR_MENVCFGH, menvcfg);
- } else {
- csrmap[CSR_MENVCFG] = menvcfg;
- }
- const reg_t senvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? SENVCFG_CBCFE | SENVCFG_CBIE : 0) |
- (proc->extension_enabled(EXT_ZICBOZ) ? SENVCFG_CBZE : 0) |
- (proc->extension_enabled(EXT_ZICFILP) ? SENVCFG_LPE : 0) |
- (proc->extension_enabled(EXT_ZICFISS) ? SENVCFG_SSE : 0);
- csrmap[CSR_SENVCFG] = senvcfg = std::make_shared<senvcfg_csr_t>(proc, CSR_SENVCFG, senvcfg_mask, 0);
- const reg_t henvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? HENVCFG_CBCFE | HENVCFG_CBIE : 0) |
- (proc->extension_enabled(EXT_ZICBOZ) ? HENVCFG_CBZE : 0) |
- (proc->extension_enabled(EXT_SVADU) ? HENVCFG_ADUE: 0) |
- (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0) |
- (proc->extension_enabled(EXT_SSTC) ? HENVCFG_STCE : 0) |
- (proc->extension_enabled(EXT_ZICFILP) ? HENVCFG_LPE : 0) |
- (proc->extension_enabled(EXT_ZICFISS) ? HENVCFG_SSE : 0);
- const reg_t henvcfg_init = (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0);
- henvcfg = std::make_shared<henvcfg_csr_t>(proc, CSR_HENVCFG, henvcfg_mask, henvcfg_init, menvcfg);
- if (xlen == 32) {
- csrmap[CSR_HENVCFG] = std::make_shared<rv32_low_csr_t>(proc, CSR_HENVCFG, henvcfg);
- csrmap[CSR_HENVCFGH] = std::make_shared<rv32_high_csr_t>(proc, CSR_HENVCFGH, henvcfg);
- } else {
- csrmap[CSR_HENVCFG] = henvcfg;
- }
- }
- if (proc->extension_enabled_const(EXT_SMSTATEEN)) {
- const reg_t sstateen0_mask = (proc->extension_enabled(EXT_ZFINX) ? SSTATEEN0_FCSR : 0) |
- (proc->extension_enabled(EXT_ZCMT) ? SSTATEEN0_JVT : 0) |
- SSTATEEN0_CS;
- const reg_t hstateen0_mask = sstateen0_mask | HSTATEEN0_SENVCFG | HSTATEEN_SSTATEEN;
- const reg_t mstateen0_mask = hstateen0_mask | (proc->extension_enabled(EXT_SSQOSID) ? MSTATEEN0_PRIV114 : 0);
- for (int i = 0; i < 4; i++) {
- const reg_t mstateen_mask = i == 0 ? mstateen0_mask : MSTATEEN_HSTATEEN;
- mstateen[i] = std::make_shared<masked_csr_t>(proc, CSR_MSTATEEN0 + i, mstateen_mask, 0);
- if (xlen == 32) {
- csrmap[CSR_MSTATEEN0 + i] = std::make_shared<rv32_low_csr_t>(proc, CSR_MSTATEEN0 + i, mstateen[i]);
- csrmap[CSR_MSTATEEN0H + i] = std::make_shared<rv32_high_csr_t>(proc, CSR_MSTATEEN0H + i, mstateen[i]);
- } else {
- csrmap[CSR_MSTATEEN0 + i] = mstateen[i];
- }
-
- const reg_t hstateen_mask = i == 0 ? hstateen0_mask : HSTATEEN_SSTATEEN;
- hstateen[i] = std::make_shared<hstateen_csr_t>(proc, CSR_HSTATEEN0 + i, hstateen_mask, 0, i);
- if (xlen == 32) {
- csrmap[CSR_HSTATEEN0 + i] = std::make_shared<rv32_low_csr_t>(proc, CSR_HSTATEEN0 + i, hstateen[i]);
- csrmap[CSR_HSTATEEN0H + i] = std::make_shared<rv32_high_csr_t>(proc, CSR_HSTATEEN0H + i, hstateen[i]);
- } else {
- csrmap[CSR_HSTATEEN0 + i] = hstateen[i];
- }
-
- const reg_t sstateen_mask = i == 0 ? sstateen0_mask : 0;
- csrmap[CSR_SSTATEEN0 + i] = sstateen[i] = std::make_shared<sstateen_csr_t>(proc, CSR_SSTATEEN0 + i, sstateen_mask, 0, i);
- }
- }
-
- if (proc->extension_enabled_const(EXT_SMRNMI)) {
- csrmap[CSR_MNSCRATCH] = std::make_shared<basic_csr_t>(proc, CSR_MNSCRATCH, 0);
- csrmap[CSR_MNEPC] = mnepc = std::make_shared<epc_csr_t>(proc, CSR_MNEPC);
- csrmap[CSR_MNCAUSE] = std::make_shared<const_csr_t>(proc, CSR_MNCAUSE, (reg_t)1 << (xlen - 1));
- csrmap[CSR_MNSTATUS] = mnstatus = std::make_shared<mnstatus_csr_t>(proc, CSR_MNSTATUS);
- }
-
- if (proc->extension_enabled_const(EXT_SSTC)) {
- stimecmp = std::make_shared<stimecmp_csr_t>(proc, CSR_STIMECMP, MIP_STIP);
- vstimecmp = std::make_shared<stimecmp_csr_t>(proc, CSR_VSTIMECMP, MIP_VSTIP);
- auto virtualized_stimecmp = std::make_shared<virtualized_stimecmp_csr_t>(proc, stimecmp, vstimecmp);
- if (xlen == 32) {
- csrmap[CSR_STIMECMP] = std::make_shared<rv32_low_csr_t>(proc, CSR_STIMECMP, virtualized_stimecmp);
- csrmap[CSR_STIMECMPH] = std::make_shared<rv32_high_csr_t>(proc, CSR_STIMECMPH, virtualized_stimecmp);
- csrmap[CSR_VSTIMECMP] = std::make_shared<rv32_low_csr_t>(proc, CSR_VSTIMECMP, vstimecmp);
- csrmap[CSR_VSTIMECMPH] = std::make_shared<rv32_high_csr_t>(proc, CSR_VSTIMECMPH, vstimecmp);
- } else {
- csrmap[CSR_STIMECMP] = virtualized_stimecmp;
- csrmap[CSR_VSTIMECMP] = vstimecmp;
- }
- }
-
- if (proc->extension_enabled(EXT_ZCMT))
- csrmap[CSR_JVT] = jvt = std::make_shared<jvt_csr_t>(proc, CSR_JVT, 0);
-
- if (proc->extension_enabled(EXT_ZICFISS)) {
- reg_t ssp_mask = -reg_t(xlen / 8);
- csrmap[CSR_SSP] = ssp = std::make_shared<ssp_csr_t>(proc, CSR_SSP, ssp_mask, 0);
- }
-
-
- // Smcsrind / Sscsrind
- sscsrind_reg_csr_t::sscsrind_reg_csr_t_p mireg[6];
- sscsrind_reg_csr_t::sscsrind_reg_csr_t_p sireg[6];
- sscsrind_reg_csr_t::sscsrind_reg_csr_t_p vsireg[6];
-
- if (proc->extension_enabled_const(EXT_SMCSRIND)) {
- csr_t_p miselect = std::make_shared<basic_csr_t>(proc, CSR_MISELECT, 0);
- csrmap[CSR_MISELECT] = miselect;
-
- const reg_t mireg_csrs[] = { CSR_MIREG, CSR_MIREG2, CSR_MIREG3, CSR_MIREG4, CSR_MIREG5, CSR_MIREG6 };
- auto i = 0;
- for (auto csr : mireg_csrs) {
- csrmap[csr] = mireg[i] = std::make_shared<sscsrind_reg_csr_t>(proc, csr, miselect);
- i++;
- }
- }
-
- if (proc->extension_enabled_const(EXT_SSCSRIND)) {
- csr_t_p vsiselect = std::make_shared<basic_csr_t>(proc, CSR_VSISELECT, 0);
- csrmap[CSR_VSISELECT] = vsiselect;
- csr_t_p siselect = std::make_shared<basic_csr_t>(proc, CSR_SISELECT, 0);
- csrmap[CSR_SISELECT] = std::make_shared<virtualized_csr_t>(proc, siselect, vsiselect);
-
- const reg_t vsireg_csrs[] = { CSR_VSIREG, CSR_VSIREG2, CSR_VSIREG3, CSR_VSIREG4, CSR_VSIREG5, CSR_VSIREG6 };
- auto i = 0;
- for (auto csr : vsireg_csrs) {
- csrmap[csr] = vsireg[i] = std::make_shared<sscsrind_reg_csr_t>(proc, csr, vsiselect);
- i++;
- }
-
- const reg_t sireg_csrs[] = { CSR_SIREG, CSR_SIREG2, CSR_SIREG3, CSR_SIREG4, CSR_SIREG5, CSR_SIREG6 };
- i = 0;
- for (auto csr : sireg_csrs) {
- sireg[i] = std::make_shared<sscsrind_reg_csr_t>(proc, csr, siselect);
- csrmap[csr] = std::make_shared<virtualized_indirect_csr_t>(proc, sireg[i], vsireg[i]);
- i++;
- }
- }
-
- if (smcntrpmf_enabled) {
- if (xlen == 32) {
- csrmap[CSR_MCYCLECFG] = std::make_shared<rv32_low_csr_t>(proc, CSR_MCYCLECFG, mcyclecfg);
- csrmap[CSR_MCYCLECFGH] = std::make_shared<rv32_high_csr_t>(proc, CSR_MCYCLECFGH, mcyclecfg);
- csrmap[CSR_MINSTRETCFG] = std::make_shared<rv32_low_csr_t>(proc, CSR_MINSTRETCFG, minstretcfg);
- csrmap[CSR_MINSTRETCFGH] = std::make_shared<rv32_high_csr_t>(proc, CSR_MINSTRETCFGH, minstretcfg);
- } else {
- csrmap[CSR_MCYCLECFG] = mcyclecfg;
- csrmap[CSR_MINSTRETCFG] = minstretcfg;
- }
- }
-
- if (proc->extension_enabled_const(EXT_SSQOSID)) {
- const reg_t srmcfg_mask = SRMCFG_MCID | SRMCFG_RCID;
- srmcfg = std::make_shared<srmcfg_csr_t>(proc, CSR_SRMCFG, srmcfg_mask, 0);
- csrmap[CSR_SRMCFG] = srmcfg;
- }
-
- serialized = false;
-
log_reg_write.clear();
log_mem_read.clear();
log_mem_write.clear();
@@ -549,6 +123,10 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
last_inst_flen = 0;
elp = elp_t::NO_LP_EXPECTED;
+
+ critical_error = false;
+
+ csr_init(proc, max_isa);
}
void processor_t::set_debug(bool value)
@@ -556,7 +134,7 @@ void processor_t::set_debug(bool value)
debug = value;
for (auto e : custom_extensions)
- e.second->set_debug(value);
+ e.second->set_debug(value, *this);
}
void processor_t::set_histogram(bool value)
@@ -567,15 +145,15 @@ void processor_t::set_histogram(bool value)
void processor_t::enable_log_commits()
{
log_commits_enabled = true;
+ mmu->flush_tlb(); // the TLB caches this setting
}
void processor_t::reset()
{
- xlen = isa->get_max_xlen();
- state.reset(this, isa->get_max_isa());
- state.dcsr->halt = halt_on_reset;
- halt_on_reset = false;
- VU.reset();
+ xlen = isa.get_max_xlen();
+ state.reset(this, isa.get_max_isa());
+ if (any_vector_extensions())
+ VU.reset();
in_wfi = false;
if (n_pmp > 0) {
@@ -585,8 +163,11 @@ void processor_t::reset()
put_csr(CSR_PMPCFG0, PMP_R | PMP_W | PMP_X | PMP_NAPOT);
}
- for (auto e : custom_extensions) // reset any extensions
- e.second->reset();
+ for (auto e : custom_extensions) { // reset any extensions
+ for (auto &csr: e.second->get_csrs(*this))
+ state.add_csr(csr->address, csr);
+ e.second->reset(*this);
+ }
if (sim)
sim->proc_reset(id);
@@ -643,10 +224,10 @@ void processor_t::set_mmu_capability(int cap)
break;
case IMPL_MMU_SV57:
set_impl(IMPL_MMU_SV57, true);
- // Fall through
+ [[fallthrough]];
case IMPL_MMU_SV48:
set_impl(IMPL_MMU_SV48, true);
- // Fall through
+ [[fallthrough]];
case IMPL_MMU_SV39:
set_impl(IMPL_MMU_SV39, true);
set_impl(IMPL_MMU, true);
@@ -661,10 +242,79 @@ void processor_t::set_mmu_capability(int cap)
}
}
+reg_t processor_t::select_an_interrupt_with_default_priority(reg_t enabled_interrupts) const
+{
+ // nonstandard interrupts have highest priority
+ if (enabled_interrupts >> (IRQ_LCOF + 1))
+ enabled_interrupts = enabled_interrupts >> (IRQ_LCOF + 1) << (IRQ_LCOF + 1);
+ // standard interrupt priority is MEI, MSI, MTI, SEI, SSI, STI
+ else if (enabled_interrupts & MIP_MEIP)
+ enabled_interrupts = MIP_MEIP;
+ else if (enabled_interrupts & MIP_MSIP)
+ enabled_interrupts = MIP_MSIP;
+ else if (enabled_interrupts & MIP_MTIP)
+ enabled_interrupts = MIP_MTIP;
+ else if (enabled_interrupts & MIP_SEIP)
+ enabled_interrupts = MIP_SEIP;
+ else if (enabled_interrupts & MIP_SSIP)
+ enabled_interrupts = MIP_SSIP;
+ else if (enabled_interrupts & MIP_STIP)
+ enabled_interrupts = MIP_STIP;
+ else if (enabled_interrupts & MIP_LCOFIP)
+ enabled_interrupts = MIP_LCOFIP;
+ else if (enabled_interrupts & MIP_VSEIP)
+ enabled_interrupts = MIP_VSEIP;
+ else if (enabled_interrupts & MIP_VSSIP)
+ enabled_interrupts = MIP_VSSIP;
+ else if (enabled_interrupts & MIP_VSTIP)
+ enabled_interrupts = MIP_VSTIP;
+
+ return enabled_interrupts;
+}
+
+bool processor_t::is_handled_in_vs()
+{
+ reg_t pending_interrupts = state.mip->read() & state.mie->read();
+
+ const reg_t s_pending_interrupts = state.nonvirtual_sip->read() & state.nonvirtual_sie->read();
+ const reg_t vstopi = state.vstopi->read();
+ const reg_t vs_pending_interrupt = vstopi ? (reg_t(1) << get_field(vstopi, MTOPI_IID)) : 0; // SSIP -> VSSIP, etc
+
+ // M-ints have higher priority over HS-ints and VS-ints
+ const reg_t mie = get_field(state.mstatus->read(), MSTATUS_MIE);
+ const reg_t m_enabled = state.prv < PRV_M || (state.prv == PRV_M && mie);
+ reg_t enabled_interrupts = pending_interrupts & ~state.mideleg->read() & -m_enabled;
+ if (enabled_interrupts == 0) {
+ // HS-ints have higher priority over VS-ints
+ const reg_t deleg_to_hs = state.mideleg->read() & ~state.hideleg->read();
+ const reg_t sie = get_field(state.sstatus->read(), MSTATUS_SIE);
+ const reg_t hs_enabled = state.v || state.prv < PRV_S || (state.prv == PRV_S && sie);
+ enabled_interrupts = ((pending_interrupts & deleg_to_hs) | (s_pending_interrupts & ~state.hideleg->read())) & -hs_enabled;
+ if (state.v && enabled_interrupts == 0) {
+ // VS-ints have least priority and can only be taken with virt enabled
+ const reg_t vs_enabled = state.prv < PRV_S || (state.prv == PRV_S && sie);
+ enabled_interrupts = vs_pending_interrupt & -vs_enabled;
+ if (enabled_interrupts)
+ return true;
+ }
+ }
+ return false;
+}
+
void processor_t::take_interrupt(reg_t pending_interrupts)
{
+ reg_t s_pending_interrupts = 0;
+ reg_t vstopi = 0;
+ reg_t vs_pending_interrupt = 0;
+
+ if (extension_enable_table[EXT_SSAIA]) {
+ s_pending_interrupts = state.nonvirtual_sip->read() & state.nonvirtual_sie->read();
+ vstopi = state.vstopi->read();
+ vs_pending_interrupt = vstopi ? (reg_t(1) << get_field(vstopi, MTOPI_IID)) : 0;
+ }
+
// Do nothing if no pending interrupts
- if (!pending_interrupts) {
+ if (!pending_interrupts && !s_pending_interrupts && !vs_pending_interrupt) {
return;
}
@@ -680,46 +330,20 @@ void processor_t::take_interrupt(reg_t pending_interrupts)
const reg_t deleg_to_hs = state.mideleg->read() & ~state.hideleg->read();
const reg_t sie = get_field(state.sstatus->read(), MSTATUS_SIE);
const reg_t hs_enabled = state.v || state.prv < PRV_S || (state.prv == PRV_S && sie);
- enabled_interrupts = pending_interrupts & deleg_to_hs & -hs_enabled;
+ enabled_interrupts = ((pending_interrupts & deleg_to_hs) | (s_pending_interrupts & ~state.hideleg->read())) & -hs_enabled;
if (state.v && enabled_interrupts == 0) {
// VS-ints have least priority and can only be taken with virt enabled
- const reg_t deleg_to_vs = state.hideleg->read();
const reg_t vs_enabled = state.prv < PRV_S || (state.prv == PRV_S && sie);
- enabled_interrupts = pending_interrupts & deleg_to_vs & -vs_enabled;
+ enabled_interrupts = vs_pending_interrupt & -vs_enabled;
}
}
const bool nmie = !(state.mnstatus && !get_field(state.mnstatus->read(), MNSTATUS_NMIE));
if (!state.debug_mode && nmie && enabled_interrupts) {
- // nonstandard interrupts have highest priority
- if (enabled_interrupts >> (IRQ_M_EXT + 1))
- enabled_interrupts = enabled_interrupts >> (IRQ_M_EXT + 1) << (IRQ_M_EXT + 1);
- // standard interrupt priority is MEI, MSI, MTI, SEI, SSI, STI
- else if (enabled_interrupts & MIP_MEIP)
- enabled_interrupts = MIP_MEIP;
- else if (enabled_interrupts & MIP_MSIP)
- enabled_interrupts = MIP_MSIP;
- else if (enabled_interrupts & MIP_MTIP)
- enabled_interrupts = MIP_MTIP;
- else if (enabled_interrupts & MIP_SEIP)
- enabled_interrupts = MIP_SEIP;
- else if (enabled_interrupts & MIP_SSIP)
- enabled_interrupts = MIP_SSIP;
- else if (enabled_interrupts & MIP_STIP)
- enabled_interrupts = MIP_STIP;
- else if (enabled_interrupts & MIP_LCOFIP)
- enabled_interrupts = MIP_LCOFIP;
- else if (enabled_interrupts & MIP_VSEIP)
- enabled_interrupts = MIP_VSEIP;
- else if (enabled_interrupts & MIP_VSSIP)
- enabled_interrupts = MIP_VSSIP;
- else if (enabled_interrupts & MIP_VSTIP)
- enabled_interrupts = MIP_VSTIP;
- else
- abort();
+ reg_t selected_interrupt = select_an_interrupt_with_default_priority(enabled_interrupts);
if (check_triggers_icount) TM.detect_icount_match();
- throw trap_t(((reg_t)1 << (isa->get_max_xlen() - 1)) | ctz(enabled_interrupts));
+ throw trap_t(((reg_t)1 << (isa.get_max_xlen() - 1)) | ctz(selected_interrupt));
}
}
@@ -747,7 +371,7 @@ void processor_t::set_privilege(reg_t prv, bool virt)
state.v_changed = state.v != state.prev_v;
}
-const char* processor_t::get_privilege_string()
+const char* processor_t::get_privilege_string() const
{
if (state.debug_mode)
return "D";
@@ -767,11 +391,11 @@ const char* processor_t::get_privilege_string()
abort();
}
-void processor_t::enter_debug_mode(uint8_t cause)
+void processor_t::enter_debug_mode(uint8_t cause, uint8_t extcause)
{
const bool has_zicfilp = extension_enabled(EXT_ZICFILP);
state.debug_mode = true;
- state.dcsr->update_fields(cause, state.prv, state.v, state.elp);
+ state.dcsr->update_fields(cause, extcause, state.prv, state.v, state.elp);
state.elp = elp_t::NO_LP_EXPECTED;
set_privilege(PRV_M, false);
state.dpc->write(state.pc);
@@ -791,7 +415,7 @@ void processor_t::debug_output_log(std::stringstream *s)
void processor_t::take_trap(trap_t& t, reg_t epc)
{
- unsigned max_xlen = isa->get_max_xlen();
+ unsigned max_xlen = isa.get_max_xlen();
if (debug) {
std::stringstream s; // first put everything in a string, later send it to output
@@ -820,17 +444,30 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
bool curr_virt = state.v;
const reg_t interrupt_bit = (reg_t)1 << (max_xlen - 1);
bool interrupt = (bit & interrupt_bit) != 0;
+ bool supv_double_trap = false;
if (interrupt) {
vsdeleg = (curr_virt && state.prv <= PRV_S) ? state.hideleg->read() : 0;
- hsdeleg = (state.prv <= PRV_S) ? state.mideleg->read() : 0;
+ vsdeleg >>= 1;
+ hsdeleg = (state.prv <= PRV_S) ? (state.mideleg->read() | state.nonvirtual_sip->read()) : 0;
bit &= ~((reg_t)1 << (max_xlen - 1));
} else {
vsdeleg = (curr_virt && state.prv <= PRV_S) ? (state.medeleg->read() & state.hedeleg->read()) : 0;
hsdeleg = (state.prv <= PRV_S) ? state.medeleg->read() : 0;
}
- if (state.prv <= PRV_S && bit < max_xlen && ((vsdeleg >> bit) & 1)) {
+ // An unexpected trap - a trap when SDT is 1 - traps to M-mode
+ if ((state.prv <= PRV_S && bit < max_xlen) &&
+ (((vsdeleg >> bit) & 1) || ((hsdeleg >> bit) & 1))) {
+ // Trap is handled in VS-mode or HS-mode. Read the sstatus of the
+ // mode that will handle the trap based on the delegation control
+ reg_t s = (((vsdeleg >> bit) & 1)) ? state.sstatus->read() :
+ state.nonvirtual_sstatus->read();
+ supv_double_trap = get_field(s, MSTATUS_SDT);
+ if (supv_double_trap)
+ vsdeleg = hsdeleg = 0;
+ }
+ if ((state.prv <= PRV_S && bit < max_xlen && ((vsdeleg >> bit) & 1)) || (state.v && interrupt && is_handled_in_vs())) {
// Handle the trap in VS-mode
- const reg_t adjusted_cause = interrupt ? bit - 1 : bit; // VSSIP -> SSIP, etc
+ const reg_t adjusted_cause = bit;
reg_t vector = (state.vstvec->read() & 1) && interrupt ? 4 * adjusted_cause : 0;
state.pc = (state.vstvec->read() & ~(reg_t)1) + vector;
state.vscause->write(adjusted_cause | (interrupt ? interrupt_bit : 0));
@@ -842,6 +479,8 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
s = set_field(s, MSTATUS_SPP, state.prv);
s = set_field(s, MSTATUS_SIE, 0);
s = set_field(s, MSTATUS_SPELP, state.elp);
+ if ((state.menvcfg->read() & MENVCFG_DTE) && (state.henvcfg->read() & HENVCFG_DTE))
+ s = set_field(s, MSTATUS_SDT, 1);
state.elp = elp_t::NO_LP_EXPECTED;
state.sstatus->write(s);
set_privilege(PRV_S, true);
@@ -860,6 +499,8 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
s = set_field(s, MSTATUS_SPP, state.prv);
s = set_field(s, MSTATUS_SIE, 0);
s = set_field(s, MSTATUS_SPELP, state.elp);
+ if (state.menvcfg->read() & MENVCFG_DTE)
+ s = set_field(s, MSTATUS_SDT, 1);
state.elp = elp_t::NO_LP_EXPECTED;
state.nonvirtual_sstatus->write(s);
if (extension_enabled('H')) {
@@ -875,18 +516,30 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
// Handle the trap in M-mode
const reg_t vector = (state.mtvec->read() & 1) && interrupt ? 4 * bit : 0;
const reg_t trap_handler_address = (state.mtvec->read() & ~(reg_t)1) + vector;
- // RNMI exception vector is implementation-defined. Since we don't model
// RNMI sources, the feature isn't very useful, so pick an invalid address.
+ // RNMI exception vector is implementation-defined. Since we don't model
const reg_t rnmi_trap_handler_address = 0;
const bool nmie = !(state.mnstatus && !get_field(state.mnstatus->read(), MNSTATUS_NMIE));
+
+ reg_t s = state.mstatus->read();
+ if ( extension_enabled(EXT_SMDBLTRP)) {
+ if (get_field(s, MSTATUS_MDT) || !nmie) {
+ // Critical error - Double trap in M-mode or trap when nmie is 0
+ // RNMI is not modeled else double trap in M-mode would trap to
+ // RNMI handler instead of leading to a critical error
+ state.critical_error = 1;
+ return;
+ }
+ s = set_field(s, MSTATUS_MDT, 1);
+ }
+
state.pc = !nmie ? rnmi_trap_handler_address : trap_handler_address;
state.mepc->write(epc);
- state.mcause->write(t.cause());
+ state.mcause->write(supv_double_trap ? CAUSE_DOUBLE_TRAP : t.cause());
state.mtval->write(t.get_tval());
- state.mtval2->write(t.get_tval2());
+ state.mtval2->write(supv_double_trap ? t.cause() : t.get_tval2());
state.mtinst->write(t.get_tinst());
- reg_t s = state.mstatus->read();
s = set_field(s, MSTATUS_MPIE, get_field(s, MSTATUS_MIE));
s = set_field(s, MSTATUS_MPP, state.prv);
s = set_field(s, MSTATUS_MIE, 0);
@@ -896,7 +549,7 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
state.elp = elp_t::NO_LP_EXPECTED;
state.mstatus->write(s);
if (state.mstatush) state.mstatush->write(s >> 32); // log mstatush change
- state.tcontrol->write((state.tcontrol->read() & CSR_TCONTROL_MTE) ? CSR_TCONTROL_MPTE : 0);
+ if (state.tcontrol) state.tcontrol->write((state.tcontrol->read() & CSR_TCONTROL_MTE) ? CSR_TCONTROL_MPTE : 0);
set_privilege(PRV_M, false);
}
}
@@ -912,7 +565,7 @@ void processor_t::take_trigger_action(triggers::action_t action, reg_t breakpoin
switch (action) {
case triggers::ACTION_DEBUG_MODE:
- enter_debug_mode(DCSR_CAUSE_HWBP);
+ enter_debug_mode(DCSR_CAUSE_HWBP, 0);
break;
case triggers::ACTION_DEBUG_EXCEPTION: {
trap_breakpoint trap(virt, breakpoint_tval);
@@ -956,7 +609,7 @@ void processor_t::disasm(insn_t insn)
<< ": Executed " << executions << " times" << std::endl;
}
- unsigned max_xlen = isa->get_max_xlen();
+ unsigned max_xlen = isa.get_max_xlen();
s << "core " << std::dec << std::setfill(' ') << std::setw(3) << id
<< std::hex << ": 0x" << std::setfill('0') << std::setw(max_xlen / 4)
@@ -975,7 +628,7 @@ void processor_t::disasm(insn_t insn)
int processor_t::paddr_bits()
{
- unsigned max_xlen = isa->get_max_xlen();
+ unsigned max_xlen = isa.get_max_xlen();
assert(xlen == max_xlen);
return max_xlen == 64 ? 50 : 34;
}
@@ -1063,18 +716,17 @@ void processor_t::build_opcode_map()
}
void processor_t::register_extension(extension_t *x) {
- for (auto insn : x->get_instructions())
+ for (auto insn : x->get_instructions(*this))
register_custom_insn(insn);
build_opcode_map();
- for (auto disasm_insn : x->get_disasms())
+ for (auto disasm_insn : x->get_disasms(this))
disassembler->add_insn(disasm_insn);
if (!custom_extensions.insert(std::make_pair(x->name(), x)).second) {
fprintf(stderr, "extensions must have unique names (got two named \"%s\"!)\n", x->name());
abort();
}
- x->set_processor(this);
}
void processor_t::register_base_instructions()
@@ -1099,21 +751,27 @@ void processor_t::register_base_instructions()
#include "insn_list.h"
#undef DEFINE_INSN
+ #define DEFINE_INSN_UNCOND(name) { \
+ insn_desc_t insn = { \
+ name##_match, \
+ name##_mask, \
+ fast_rv32i_##name, \
+ fast_rv64i_##name, \
+ fast_rv32e_##name, \
+ fast_rv64e_##name, \
+ logged_rv32i_##name, \
+ logged_rv64i_##name, \
+ logged_rv32e_##name, \
+ logged_rv64e_##name \
+ }; \
+ register_base_insn(insn); \
+ }
+
// add overlapping instructions first, in order
#define DECLARE_OVERLAP_INSN(name, ext) \
name##_overlapping = true; \
- if (isa->extension_enabled(ext)) \
- register_base_insn((insn_desc_t) { \
- name##_match, \
- name##_mask, \
- fast_rv32i_##name, \
- fast_rv64i_##name, \
- fast_rv32e_##name, \
- fast_rv64e_##name, \
- logged_rv32i_##name, \
- logged_rv64i_##name, \
- logged_rv32e_##name, \
- logged_rv64e_##name});
+ if (isa.extension_enabled(ext)) \
+ DEFINE_INSN_UNCOND(name);
#include "overlap_list.h"
#undef DECLARE_OVERLAP_INSN
@@ -1122,19 +780,10 @@ void processor_t::register_base_instructions()
// appear earlier to improve search time on opcode_cache misses.
#define DEFINE_INSN(name) \
if (!name##_overlapping) \
- register_base_insn((insn_desc_t) { \
- name##_match, \
- name##_mask, \
- fast_rv32i_##name, \
- fast_rv64i_##name, \
- fast_rv32e_##name, \
- fast_rv64e_##name, \
- logged_rv32i_##name, \
- logged_rv64i_##name, \
- logged_rv32e_##name, \
- logged_rv64e_##name});
+ DEFINE_INSN_UNCOND(name);
#include "insn_list.h"
#undef DEFINE_INSN
+ #undef DEFINE_INSN_UNCOND
// terminate instruction list with a catch-all
register_base_insn(insn_desc_t::illegal_instruction);
@@ -1173,6 +822,11 @@ bool processor_t::store(reg_t addr, size_t len, const uint8_t* bytes)
return false;
}
+reg_t processor_t::size()
+{
+ return PGSIZE;
+}
+
void processor_t::trigger_updated(const std::vector<triggers::trigger_t *> &triggers)
{
mmu->flush_tlb();
diff --git a/riscv/processor.h b/riscv/processor.h
index 14b828c..a6e9eeb 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -18,6 +18,7 @@
#include "../fesvr/memif.h"
#include "vector_unit.h"
+#define FIRST_HPMCOUNTER 3
#define N_HPMCOUNTERS 29
class processor_t;
@@ -61,7 +62,7 @@ struct insn_desc_t
};
// regnum, data
-typedef std::unordered_map<reg_t, freg_t> commit_log_reg_t;
+typedef std::map<reg_t, freg_t> commit_log_reg_t;
// addr, value, size
typedef std::vector<std::tuple<reg_t, uint64_t, uint8_t>> commit_log_mem_t;
@@ -69,7 +70,9 @@ typedef std::vector<std::tuple<reg_t, uint64_t, uint8_t>> commit_log_mem_t;
// architectural state of a RISC-V hart
struct state_t
{
+ void add_ireg_proxy(processor_t* const proc, sscsrind_reg_csr_t::sscsrind_reg_csr_t_p ireg);
void reset(processor_t* const proc, reg_t max_isa);
+ void add_csr(reg_t addr, const csr_t_p& csr);
reg_t pc;
regfile_t<reg_t, NXPR, true> XPR;
@@ -94,9 +97,12 @@ struct state_t
wide_counter_csr_t_p mcycle;
mie_csr_t_p mie;
mip_csr_t_p mip;
+ csr_t_p nonvirtual_sip;
+ csr_t_p nonvirtual_sie;
csr_t_p medeleg;
csr_t_p mideleg;
csr_t_p mcounteren;
+ csr_t_p mcountinhibit;
csr_t_p mevent[N_HPMCOUNTERS];
csr_t_p mnstatus;
csr_t_p mnepc;
@@ -106,6 +112,7 @@ struct state_t
csr_t_p stvec;
virtualized_csr_t_p satp;
csr_t_p scause;
+ csr_t_p scountinhibit;
// When taking a trap into HS-mode, we must access the nonvirtualized HS-mode CSRs directly:
csr_t_p nonvirtual_stvec;
@@ -167,10 +174,13 @@ struct state_t
csr_t_p stimecmp;
csr_t_p vstimecmp;
- csr_t_p srmcfg;
-
csr_t_p ssp;
+ csr_t_p mvien;
+ mvip_csr_t_p mvip;
+ csr_t_p hvictl;
+ csr_t_p vstopi;
+
bool serialized; // whether timer CSRs are in a well-defined state
// When true, execute a single instruction and then enter debug mode. This
@@ -189,6 +199,11 @@ struct state_t
int last_inst_flen;
elp_t elp;
+
+ bool critical_error;
+
+ private:
+ void csr_init(processor_t* const proc, reg_t max_isa);
};
class opcode_cache_entry_t {
@@ -236,13 +251,14 @@ class opcode_cache_entry_t {
class processor_t : public abstract_device_t
{
public:
- processor_t(const isa_parser_t *isa, const cfg_t* cfg,
+ processor_t(const char* isa_str, const char* priv_str,
+ const cfg_t* cfg,
simif_t* sim, uint32_t id, bool halt_on_reset,
FILE *log_file, std::ostream& sout_); // because of command line option --log and -s we need both
~processor_t();
- const isa_parser_t &get_isa() { return *isa; }
- const cfg_t &get_cfg() { return *cfg; }
+ const isa_parser_t &get_isa() const & { return isa; }
+ const cfg_t &get_cfg() const & { return *cfg; }
void set_debug(bool value);
void set_histogram(bool value);
@@ -303,7 +319,7 @@ public:
void set_extension_enable(unsigned char ext, bool enable) {
assert(!extension_assumed_const[ext]);
extension_dynamic[ext] = true;
- extension_enable_table[ext] = enable && isa->extension_enabled(ext);
+ extension_enable_table[ext] = enable && isa.extension_enabled(ext);
}
void set_impl(uint8_t impl, bool val) { impl_table[impl] = val; }
bool supports_impl(uint8_t impl) const {
@@ -319,7 +335,7 @@ public:
}
reg_t legalize_privilege(reg_t);
void set_privilege(reg_t, bool);
- const char* get_privilege_string();
+ const char* get_privilege_string() const;
void update_histogram(reg_t pc);
const disassembler_t* get_disassembler() { return disassembler; }
@@ -334,14 +350,15 @@ public:
void register_extension(extension_t*);
// MMIO slave interface
- bool load(reg_t addr, size_t len, uint8_t* bytes);
- bool store(reg_t addr, size_t len, const uint8_t* bytes);
+ bool load(reg_t addr, size_t len, uint8_t* bytes) override;
+ bool store(reg_t addr, size_t len, const uint8_t* bytes) override;
+ reg_t size() override;
// When true, display disassembly of each instruction that's executed.
bool debug;
// When true, take the slow simulation path.
- bool slow_path();
- bool halted() { return state.debug_mode; }
+ bool slow_path() const;
+ bool halted() const { return state.debug_mode; }
enum {
HR_NONE, /* Halt request is inactive. */
HR_REGULAR, /* Regular halt request/debug interrupt. */
@@ -361,8 +378,10 @@ public:
void check_if_lpad_required();
+ reg_t select_an_interrupt_with_default_priority(reg_t enabled_interrupts) const;
+
private:
- const isa_parser_t * const isa;
+ const isa_parser_t isa;
const cfg_t * const cfg;
simif_t* sim;
@@ -393,6 +412,10 @@ private:
static const size_t OPCODE_CACHE_SIZE = 4095;
opcode_cache_entry_t opcode_cache[OPCODE_CACHE_SIZE];
+ unsigned ziccid_flush_count = 0;
+ static const unsigned ZICCID_FLUSH_PERIOD = 10;
+
+ bool is_handled_in_vs();
void take_pending_interrupt() { take_interrupt(state.mip->read() & state.mie->read()); }
void take_interrupt(reg_t mask); // take first enabled interrupt in mask
void take_trap(trap_t& t, reg_t epc); // take an exception
@@ -401,7 +424,7 @@ private:
void register_insn(insn_desc_t, bool);
int paddr_bits();
- void enter_debug_mode(uint8_t cause);
+ void enter_debug_mode(uint8_t cause, uint8_t ext_cause);
void debug_output_log(std::stringstream *s); // either output to interactive user or write to log file
diff --git a/riscv/riscv.ac b/riscv/riscv.ac
index 378fd10..d848d9b 100644
--- a/riscv/riscv.ac
+++ b/riscv/riscv.ac
@@ -1,4 +1,4 @@
-AC_LANG_CPLUSPLUS
+AC_LANG([C++])
AX_BOOST_BASE([1.53])
AX_BOOST_ASIO
@@ -8,18 +8,6 @@ AC_CHECK_LIB([boost_system], [main], [], [])
AC_CHECK_LIB([boost_regex], [main], [], [])
-AC_ARG_WITH(isa,
- [AS_HELP_STRING([--with-isa=RV64IMAFDC_zicntr_zihpm],
- [Sets the default RISC-V ISA])],
- AC_DEFINE_UNQUOTED([DEFAULT_ISA], "$withval", [Default value for --isa switch]),
- AC_DEFINE_UNQUOTED([DEFAULT_ISA], "RV64IMAFDC_zicntr_zihpm", [Default value for --isa switch]))
-
-AC_ARG_WITH(priv,
- [AS_HELP_STRING([--with-priv=MSU],
- [Sets the default RISC-V privilege modes supported])],
- AC_DEFINE_UNQUOTED([DEFAULT_PRIV], "$withval", [Default value for --priv switch]),
- AC_DEFINE_UNQUOTED([DEFAULT_PRIV], "MSU", [Default value for --priv switch]))
-
AC_ARG_WITH(target,
[AS_HELP_STRING([--with-target=riscv64-unknown-elf],
[Sets the default target config])],
diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in
index 60723b5..4239a66 100644
--- a/riscv/riscv.mk.in
+++ b/riscv/riscv.mk.in
@@ -33,11 +33,13 @@ riscv_install_hdrs = \
entropy_source.h \
extension.h \
isa_parser.h \
+ jtag_dtm.h \
log_file.h \
memtracer.h \
mmu.h \
platform.h \
processor.h \
+ remote_bitbang.h \
rocc.h \
sim.h \
simif.h \
@@ -68,6 +70,7 @@ riscv_srcs = \
remote_bitbang.cc \
jtag_dtm.cc \
csrs.cc \
+ csr_init.cc \
triggers.cc \
vector_unit.cc \
socketif.cc \
@@ -859,11 +862,21 @@ riscv_insn_ext_v_ctrl = \
vsetvli \
vsetvl \
+riscv_insn_ext_zvqdotq = \
+ vqdot_vv \
+ vqdot_vx \
+ vqdotu_vv \
+ vqdotu_vx \
+ vqdotsu_vv \
+ vqdotsu_vx \
+ vqdotus_vx \
+
riscv_insn_ext_v = \
$(riscv_insn_ext_v_alu_fp) \
$(riscv_insn_ext_v_alu_int) \
$(riscv_insn_ext_v_ctrl) \
$(riscv_insn_ext_v_ldst) \
+ $(riscv_insn_ext_zvqdotq) \
riscv_insn_ext_h = \
hfence_gvma \
diff --git a/riscv/rocc.cc b/riscv/rocc.cc
index 53ee051..9ba4fc1 100644
--- a/riscv/rocc.cc
+++ b/riscv/rocc.cc
@@ -14,15 +14,15 @@
u.i = insn; \
reg_t xs1 = u.r.xs1 ? RS1 : -1; \
reg_t xs2 = u.r.xs2 ? RS2 : -1; \
- reg_t xd = rocc->custom##n(u.r, xs1, xs2); \
+ reg_t xd = rocc->custom##n(p, u.r, xs1, xs2); \
if (u.r.xd) \
WRITE_RD(xd); \
return pc+4; \
} \
\
- reg_t rocc_t::custom##n(rocc_insn_t UNUSED insn, reg_t UNUSED xs1, reg_t UNUSED xs2) \
+ reg_t rocc_t::custom##n(processor_t *p, rocc_insn_t UNUSED insn, reg_t UNUSED xs1, reg_t UNUSED xs2) \
{ \
- illegal_instruction(); \
+ illegal_instruction(*p); \
return 0; \
}
@@ -31,25 +31,17 @@ customX(1)
customX(2)
customX(3)
-std::vector<insn_desc_t> rocc_t::get_instructions()
+std::vector<insn_desc_t> rocc_t::get_instructions(const processor_t &)
{
- std::vector<insn_desc_t> insns;
- insns.push_back((insn_desc_t){0x0b, 0x7f,
- &::illegal_instruction, c0, &::illegal_instruction, c0,
- &::illegal_instruction, c0, &::illegal_instruction, c0});
- insns.push_back((insn_desc_t){0x2b, 0x7f,
- &::illegal_instruction, c1, &::illegal_instruction, c1,
- &::illegal_instruction, c1, &::illegal_instruction, c1});
- insns.push_back((insn_desc_t){0x5b, 0x7f,
- &::illegal_instruction, c2, &::illegal_instruction, c2,
- &::illegal_instruction, c2, &::illegal_instruction, c2});
- insns.push_back((insn_desc_t){0x7b, 0x7f,
- &::illegal_instruction, c3, &::illegal_instruction, c3,
- &::illegal_instruction, c0, &::illegal_instruction, c3});
+ std::vector<insn_desc_t> insns = {
+ {0x0b, 0x7f, &::illegal_instruction, c0, &::illegal_instruction, c0, &::illegal_instruction, c0, &::illegal_instruction, c0},
+ {0x2b, 0x7f, &::illegal_instruction, c1, &::illegal_instruction, c1, &::illegal_instruction, c1, &::illegal_instruction, c1},
+ {0x5b, 0x7f, &::illegal_instruction, c2, &::illegal_instruction, c2, &::illegal_instruction, c2, &::illegal_instruction, c2},
+ {0x7b, 0x7f, &::illegal_instruction, c3, &::illegal_instruction, c3, &::illegal_instruction, c0, &::illegal_instruction, c3}};
return insns;
}
-std::vector<disasm_insn_t*> rocc_t::get_disasms()
+std::vector<disasm_insn_t *> rocc_t::get_disasms(const processor_t *)
{
std::vector<disasm_insn_t*> insns;
return insns;
diff --git a/riscv/rocc.h b/riscv/rocc.h
index d65ec97..d7fee26 100644
--- a/riscv/rocc.h
+++ b/riscv/rocc.h
@@ -24,12 +24,12 @@ union rocc_insn_union_t
class rocc_t : public extension_t
{
public:
- virtual reg_t custom0(rocc_insn_t insn, reg_t xs1, reg_t xs2);
- virtual reg_t custom1(rocc_insn_t insn, reg_t xs1, reg_t xs2);
- virtual reg_t custom2(rocc_insn_t insn, reg_t xs1, reg_t xs2);
- virtual reg_t custom3(rocc_insn_t insn, reg_t xs1, reg_t xs2);
- std::vector<insn_desc_t> get_instructions();
- std::vector<disasm_insn_t*> get_disasms();
+ virtual reg_t custom0(processor_t *, rocc_insn_t insn, reg_t xs1, reg_t xs2);
+ virtual reg_t custom1(processor_t *, rocc_insn_t insn, reg_t xs1, reg_t xs2);
+ virtual reg_t custom2(processor_t *, rocc_insn_t insn, reg_t xs1, reg_t xs2);
+ virtual reg_t custom3(processor_t *, rocc_insn_t insn, reg_t xs1, reg_t xs2);
+ std::vector<insn_desc_t> get_instructions(const processor_t &proc) override;
+ std::vector<disasm_insn_t *> get_disasms(const processor_t *proc = nullptr) override;
};
#define define_custom_func(type_name, ext_name_str, func_name, method_name) \
diff --git a/riscv/sim.cc b/riscv/sim.cc
index d08e274..388d729 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -44,15 +44,15 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
const char *log_path,
bool dtb_enabled, const char *dtb_file,
bool socket_enabled,
- FILE *cmd_file) // needed for command line option --cmd
+ FILE *cmd_file, // needed for command line option --cmd
+ std::optional<unsigned long long> instruction_limit)
: htif_t(args),
- isa(cfg->isa, cfg->priv),
cfg(cfg),
mems(mems),
- procs(std::max(cfg->nprocs(), size_t(1))),
dtb_enabled(dtb_enabled),
log_file(log_path),
cmd_file(cmd_file),
+ instruction_limit(instruction_limit),
sout_(nullptr),
current_step(0),
current_proc(0),
@@ -96,16 +96,18 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
}
#endif
- debug_mmu = new mmu_t(this, cfg->endianness, NULL);
-
- for (size_t i = 0; i < cfg->nprocs(); i++) {
- procs[i] = new processor_t(&isa, cfg, this, cfg->hartids[i], halted,
- log_file.get(), sout_);
- harts[cfg->hartids[i]] = procs[i];
- }
+ debug_mmu = new mmu_t(this, cfg->endianness, NULL, cfg->cache_blocksz);
// When running without using a dtb, skip the fdt-based configuration steps
- if (!dtb_enabled) return;
+ if (!dtb_enabled) {
+ for (size_t i = 0; i < cfg->nprocs(); i++) {
+ procs.push_back(new processor_t(cfg->isa, cfg->priv,
+ cfg, this, cfg->hartids[i], halted,
+ log_file.get(), sout_));
+ harts[cfg->hartids[i]] = procs[i];
+ }
+ return;
+ } // otherwise, generate the procs by parsing the DTS
// Only make a CLINT (Core-Local INTerrupt controller) and PLIC (Platform-
// Level-Interrupt-Controller) if they are specified in the device tree
@@ -133,19 +135,16 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
std::stringstream strstream;
strstream << fin.rdbuf();
dtb = strstream.str();
+ dts = dtb_to_dts(dtb);
} else {
- std::pair<reg_t, reg_t> initrd_bounds = cfg->initrd_bounds;
std::string device_nodes;
for (const device_factory_sargs_t& factory_sargs: device_factories) {
const device_factory_t* factory = factory_sargs.first;
const std::vector<std::string>& sargs = factory_sargs.second;
device_nodes.append(factory->generate_dts(this, sargs));
}
- dts = make_dts(INSNS_PER_RTC_TICK, CPU_HZ,
- initrd_bounds.first, initrd_bounds.second,
- cfg->bootargs, cfg->pmpregions, cfg->pmpgranularity,
- procs, mems, device_nodes);
- dtb = dts_compile(dts);
+ dts = make_dts(INSNS_PER_RTC_TICK, CPU_HZ, cfg, mems, device_nodes);
+ dtb = dts_to_dtb(dts);
}
int fdt_code = fdt_check_header(dtb.c_str());
@@ -162,24 +161,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
void *fdt = (void *)dtb.c_str();
- for (size_t i = 0; i < device_factories.size(); i++) {
- const device_factory_t* factory = device_factories[i].first;
- const std::vector<std::string>& sargs = device_factories[i].second;
- reg_t device_base = 0;
- abstract_device_t* device = factory->parse_from_fdt(fdt, this, &device_base, sargs);
- if (device) {
- assert(device_base);
- std::shared_ptr<abstract_device_t> dev_ptr(device);
- add_device(device_base, dev_ptr);
-
- if (i == 0) // clint_factory
- clint = std::static_pointer_cast<clint_t>(dev_ptr);
- else if (i == 1) // plic_factory
- plic = std::static_pointer_cast<plic_t>(dev_ptr);
- }
- }
-
- //per core attribute
+ // per core attribute
int cpu_offset = 0, cpu_map_offset, rc;
size_t cpu_idx = 0;
cpu_offset = fdt_get_offset(fdt, "/cpus");
@@ -193,10 +175,33 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
if (!(cpu_map_offset < 0) && cpu_offset == cpu_map_offset)
continue;
- if (cpu_idx >= nprocs())
- break;
+ if (cpu_idx != procs.size()) {
+ std::cerr << "Spike only supports contiguous CPU IDs in the DTS" << std::endl;
+ exit(1);
+ }
+
+ // handle isa string
+ const char* isa_str;
+ rc = fdt_parse_isa(fdt, cpu_offset, &isa_str);
+ if (rc != 0) {
+ std::cerr << "core (" << cpu_idx << ") has an invalid or missing 'riscv,isa'\n";
+ exit(1);
+ }
+
+ // handle hartid
+ uint32_t hartid;
+ rc = fdt_parse_hartid(fdt, cpu_offset, &hartid);
+ if (rc != 0) {
+ std::cerr << "core (" << cpu_idx << ") has an invalid or missing `reg` (hartid)\n";
+ exit(1);
+ }
- //handle pmp
+ procs.push_back(new processor_t(isa_str, cfg->priv,
+ cfg, this, hartid, halted,
+ log_file.get(), sout_));
+ harts[hartid] = procs[cpu_idx];
+
+ // handle pmp
reg_t pmp_num, pmp_granularity;
if (fdt_parse_pmp_num(fdt, cpu_offset, &pmp_num) != 0)
pmp_num = 0;
@@ -206,7 +211,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
procs[cpu_idx]->set_pmp_granularity(pmp_granularity);
}
- //handle mmu-type
+ // handle mmu-type
const char *mmu_type;
rc = fdt_parse_mmu_type(fdt, cpu_offset, &mmu_type);
if (rc == 0) {
@@ -220,7 +225,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
} else if (strncmp(mmu_type, "riscv,sv57", strlen("riscv,sv57")) == 0) {
procs[cpu_idx]->set_mmu_capability(IMPL_MMU_SV57);
} else if (strncmp(mmu_type, "riscv,sbare", strlen("riscv,sbare")) == 0) {
- //has been set in the beginning
+ // has been set in the beginning
} else {
std::cerr << "core ("
<< cpu_idx
@@ -232,15 +237,27 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
procs[cpu_idx]->set_mmu_capability(IMPL_MMU_SBARE);
}
+ procs[cpu_idx]->reset();
+
cpu_idx++;
}
- if (cpu_idx != nprocs()) {
- std::cerr << "core number in dts ("
- << cpu_idx
- << ") doesn't match it in command line ("
- << nprocs() << ").\n";
- exit(1);
+ // must be located after procs/harts are set (devices might use sim_t get_* member functions)
+ for (size_t i = 0; i < device_factories.size(); i++) {
+ const device_factory_t* factory = device_factories[i].first;
+ const std::vector<std::string>& sargs = device_factories[i].second;
+ reg_t device_base = 0;
+ abstract_device_t* device = factory->parse_from_fdt(fdt, this, &device_base, sargs);
+ if (device) {
+ assert(device_base);
+ std::shared_ptr<abstract_device_t> dev_ptr(device);
+ add_device(device_base, dev_ptr);
+
+ if (i == 0) // clint_factory
+ clint = std::static_pointer_cast<clint_t>(dev_ptr);
+ else if (i == 1) // plic_factory
+ plic = std::static_pointer_cast<plic_t>(dev_ptr);
+ }
}
}
@@ -256,7 +273,7 @@ int sim_t::run()
if (!debug && log)
set_procs_debug(true);
- htif_t::set_expected_xlen(isa.get_max_xlen());
+ htif_t::set_expected_xlen(harts[0]->get_isa().get_max_xlen());
// htif_t::run() will repeatedly call back into sim_t::idle(), each
// invocation of which will advance target time
@@ -322,7 +339,8 @@ void sim_t::set_procs_debug(bool value)
static bool paddr_ok(reg_t addr)
{
- return (addr >> MAX_PADDR_BITS) == 0;
+ static_assert(MAX_PADDR_BITS == 8 * sizeof(addr));
+ return true;
}
bool sim_t::mmio_load(reg_t paddr, size_t len, uint8_t* bytes)
@@ -387,10 +405,9 @@ void sim_t::set_rom()
char* sim_t::addr_to_mem(reg_t paddr) {
if (!paddr_ok(paddr))
return NULL;
- auto desc = bus.find_device(paddr);
+ auto desc = bus.find_device(paddr >> PGSHIFT << PGSHIFT, PGSIZE);
if (auto mem = dynamic_cast<abstract_mem_t*>(desc.second))
- if (paddr - desc.first < mem->size())
- return mem->contents(paddr - desc.first);
+ return mem->contents(paddr - desc.first);
return NULL;
}
@@ -414,8 +431,19 @@ void sim_t::idle()
if (debug || ctrlc_pressed)
interactive();
- else
+ else {
+ if (instruction_limit.has_value()) {
+ if (*instruction_limit < INTERLEAVE) {
+ // Final step.
+ step(*instruction_limit);
+ htif_exit(0);
+ *instruction_limit = 0;
+ return;
+ }
+ *instruction_limit -= INTERLEAVE;
+ }
step(INTERLEAVE);
+ }
if (remote_bitbang)
remote_bitbang->tick();
diff --git a/riscv/sim.h b/riscv/sim.h
index 540d80d..da04a88 100644
--- a/riscv/sim.h
+++ b/riscv/sim.h
@@ -35,10 +35,10 @@ public:
const debug_module_config_t &dm_config, const char *log_path,
bool dtb_enabled, const char *dtb_file,
bool socket_enabled,
- FILE *cmd_file); // needed for command line option --cmd
+ FILE *cmd_file, // needed for command line option --cmd
+ std::optional<unsigned long long> instruction_limit);
~sim_t();
- // run the simulation to completion
int run();
void set_debug(bool value);
void set_histogram(bool value);
@@ -69,7 +69,6 @@ public:
static const size_t CPU_HZ = 1000000000; // 1GHz CPU
private:
- isa_parser_t isa;
const cfg_t * const cfg;
std::vector<std::pair<reg_t, abstract_mem_t*>> mems;
std::vector<processor_t*> procs;
@@ -86,6 +85,8 @@ private:
FILE *cmd_file; // pointer to debug command input file
+ std::optional<unsigned long long> instruction_limit;
+
socketif_t *socketif;
std::ostream sout_; // used for socket and terminal interface
@@ -99,8 +100,13 @@ private:
remote_bitbang_t* remote_bitbang;
std::optional<std::function<void()>> next_interactive_action;
- // memory-mapped I/O routines
+ // If padd corresponds to memory (as opposed to an I/O device), return a
+ // host pointer corresponding to paddr.
+ // For these purposes, only memories that include the entire base page
+ // surrounding paddr are considered; smaller memories are treated as I/O.
virtual char* addr_to_mem(reg_t paddr) override;
+
+ // memory-mapped I/O routines
virtual bool mmio_load(reg_t paddr, size_t len, uint8_t* bytes) override;
virtual bool mmio_store(reg_t paddr, size_t len, const uint8_t* bytes) override;
void set_rom();
diff --git a/riscv/trap.h b/riscv/trap.h
index 5eb62cf..5ea56e2 100644
--- a/riscv/trap.h
+++ b/riscv/trap.h
@@ -115,6 +115,7 @@ DECLARE_TRAP(CAUSE_MACHINE_ECALL, machine_ecall)
DECLARE_MEM_TRAP(CAUSE_FETCH_PAGE_FAULT, instruction_page_fault)
DECLARE_MEM_TRAP(CAUSE_LOAD_PAGE_FAULT, load_page_fault)
DECLARE_MEM_TRAP(CAUSE_STORE_PAGE_FAULT, store_page_fault)
+DECLARE_TRAP(CAUSE_DOUBLE_TRAP, double_trap)
DECLARE_MEM_GVA_TRAP(CAUSE_FETCH_GUEST_PAGE_FAULT, instruction_guest_page_fault)
DECLARE_MEM_GVA_TRAP(CAUSE_LOAD_GUEST_PAGE_FAULT, load_guest_page_fault)
DECLARE_INST_TRAP(CAUSE_VIRTUAL_INSTRUCTION, virtual_instruction)
diff --git a/riscv/triggers.cc b/riscv/triggers.cc
index de3da40..9c21330 100644
--- a/riscv/triggers.cc
+++ b/riscv/triggers.cc
@@ -52,15 +52,57 @@ void trigger_t::tdata3_write(processor_t * const proc, const reg_t val) noexcept
mhselect = get_field(val, CSR_TEXTRA_MHSELECT(xlen));
sbytemask = get_field(val, CSR_TEXTRA_SBYTEMASK(xlen));
svalue = proc->extension_enabled_const('S') ? get_field(val, CSR_TEXTRA_SVALUE(xlen)) : 0;
- sselect = (sselect_t)((proc->extension_enabled_const('S') && get_field(val, CSR_TEXTRA_SSELECT(xlen)) <= SSELECT_MAXVAL) ? get_field(val, CSR_TEXTRA_SSELECT(xlen)) : SSELECT_IGNORE);
+ sselect = (sselect_t)((proc->extension_enabled_const('S') && get_field(val, CSR_TEXTRA_SSELECT(xlen)) <= SSELECT_MAXVAL) ? get_field(val, CSR_TEXTRA_SSELECT(xlen)) : (reg_t)SSELECT_IGNORE);
+}
+
+static reg_t tcontrol_value(const state_t * state) {
+ if (state->tcontrol)
+ return state->tcontrol->read();
+ else
+ return 0;
}
bool trigger_t::common_match(processor_t * const proc, bool use_prev_prv) const noexcept {
auto state = proc->get_state();
auto prv = use_prev_prv ? state->prev_prv : state->prv;
auto v = use_prev_prv ? state->prev_v : state->v;
- auto m_enabled = get_action() != 0 || (state->tcontrol->read() & CSR_TCONTROL_MTE);
- return (prv < PRV_M || m_enabled) && mode_match(prv, v) && textra_match(proc);
+
+ if (!mode_match(prv, v))
+ return false;
+
+ if (!textra_match(proc))
+ return false;
+
+ if (get_action() == ACTION_DEBUG_EXCEPTION) {
+ if (proc->extension_enabled('S')) {
+ // The hardware prevents triggers with action=0 from matching or firing
+ // while in M-mode and while MIE in mstatus is 0. If medeleg [3]=1 then it
+ // prevents triggers with action=0 from matching or firing while in S-mode
+ // and while SIE in sstatus is 0. If medeleg [3]=1 and hedeleg [3]=1 then
+ // it prevents triggers with action=0 from matching or firing while in
+ // VS-mode and while SIE in vstatus is 0.
+
+ const bool mstatus_mie = state->mstatus->read() & MSTATUS_MIE;
+ if (prv == PRV_M && !mstatus_mie)
+ return false;
+
+ const bool sstatus_sie = state->sstatus->read() & MSTATUS_SIE;
+ const bool medeleg_breakpoint = (state->medeleg->read() >> CAUSE_BREAKPOINT) & 1;
+ if (prv == PRV_S && !v && medeleg_breakpoint && !sstatus_sie)
+ return false;
+
+ const bool vsstatus_sie = state->vsstatus->read() & MSTATUS_SIE;
+ const bool hedeleg_breakpoint = (state->hedeleg->read() >> CAUSE_BREAKPOINT) & 1;
+ if (prv == PRV_S && v && medeleg_breakpoint && hedeleg_breakpoint && !vsstatus_sie)
+ return false;
+ } else {
+ // mte and mpte in tcontrol is implemented. medeleg [3] is hard-wired to 0.
+ if (prv == PRV_M && !(tcontrol_value(state) & CSR_TCONTROL_MTE))
+ return false;
+ }
+ }
+
+ return true;
}
bool trigger_t::mode_match(reg_t prv, bool v) const noexcept
@@ -110,21 +152,6 @@ bool trigger_t::textra_match(processor_t * const proc) const noexcept
return true;
}
-bool trigger_t::allow_action(const state_t * const state) const
-{
- if (get_action() == ACTION_DEBUG_EXCEPTION) {
- const bool mstatus_mie = state->mstatus->read() & MSTATUS_MIE;
- const bool sstatus_sie = state->sstatus->read() & MSTATUS_SIE;
- const bool vsstatus_sie = state->vsstatus->read() & MSTATUS_SIE;
- const bool medeleg_breakpoint = (state->medeleg->read() >> CAUSE_BREAKPOINT) & 1;
- const bool hedeleg_breakpoint = (state->hedeleg->read() >> CAUSE_BREAKPOINT) & 1;
- return (state->prv != PRV_M || mstatus_mie) &&
- (state->prv != PRV_S || state->v || !medeleg_breakpoint || sstatus_sie) &&
- (state->prv != PRV_S || !state->v || !medeleg_breakpoint || !hedeleg_breakpoint || vsstatus_sie);
- }
- return true;
-}
-
reg_t disabled_trigger_t::tdata1_read(const processor_t * const proc) const noexcept
{
auto xlen = proc->get_xlen();
@@ -146,7 +173,7 @@ reg_t mcontrol_t::tdata1_read(const processor_t * const proc) const noexcept {
auto xlen = proc->get_xlen();
v = set_field(v, MCONTROL_TYPE(xlen), CSR_TDATA1_TYPE_MCONTROL);
v = set_field(v, CSR_MCONTROL_DMODE(xlen), dmode);
- v = set_field(v, MCONTROL_MASKMAX(xlen), 0);
+ v = set_field(v, MCONTROL_MASKMAX(xlen), maskmax);
v = set_field(v, CSR_MCONTROL_HIT, hit);
v = set_field(v, MCONTROL_SELECT, select);
v = set_field(v, MCONTROL_TIMING, timing);
@@ -171,7 +198,7 @@ void mcontrol_t::tdata1_write(processor_t * const proc, const reg_t val, const b
timing = legalize_timing(val, MCONTROL_TIMING, MCONTROL_SELECT, MCONTROL_EXECUTE, MCONTROL_LOAD);
action = legalize_action(val, MCONTROL_ACTION, CSR_MCONTROL_DMODE(xlen));
chain = allow_chain ? get_field(val, MCONTROL_CHAIN) : 0;
- match = legalize_match(get_field(val, MCONTROL_MATCH));
+ match = legalize_match(get_field(val, MCONTROL_MATCH), maskmax);
m = get_field(val, MCONTROL_M);
s = proc->extension_enabled_const('S') ? get_field(val, CSR_MCONTROL_S) : 0;
u = proc->extension_enabled_const('U') ? get_field(val, CSR_MCONTROL_U) : 0;
@@ -195,13 +222,17 @@ bool mcontrol_common_t::simple_match(unsigned xlen, reg_t value) const {
return value < tdata2;
case MATCH_MASK_LOW:
{
- reg_t mask = tdata2 >> (xlen/2);
- return (value & mask) == (tdata2 & mask);
+ reg_t tdata2_high = tdata2 >> (xlen/2);
+ reg_t tdata2_low = tdata2 & ((reg_t(1) << (xlen/2)) - 1);
+ reg_t value_low = value & ((reg_t(1) << (xlen/2)) - 1);
+ return (value_low & tdata2_high) == tdata2_low;
}
case MATCH_MASK_HIGH:
{
- reg_t mask = tdata2 >> (xlen/2);
- return ((value >> (xlen/2)) & mask) == (tdata2 & mask);
+ reg_t tdata2_high = tdata2 >> (xlen/2);
+ reg_t tdata2_low = tdata2 & ((reg_t(1) << (xlen/2)) - 1);
+ reg_t value_high = value >> (xlen/2);
+ return (value_high & tdata2_high) == tdata2_low;
}
}
assert(0);
@@ -231,7 +262,7 @@ std::optional<match_result_t> mcontrol_common_t::detect_memory_access_match(proc
value &= 0xffffffff;
}
- if (simple_match(xlen, value) && allow_action(proc->get_state())) {
+ if (simple_match(xlen, value)) {
/* This is OK because this function is only called if the trigger was not
* inhibited by the previous trigger in the chain. */
set_hit(timing ? HIT_IMMEDIATELY_AFTER : HIT_BEFORE);
@@ -240,11 +271,14 @@ std::optional<match_result_t> mcontrol_common_t::detect_memory_access_match(proc
return std::nullopt;
}
-mcontrol_common_t::match_t mcontrol_common_t::legalize_match(reg_t val) noexcept
+mcontrol_common_t::match_t mcontrol_common_t::legalize_match(reg_t val, reg_t maskmax) noexcept
{
switch (val) {
- case MATCH_EQUAL:
case MATCH_NAPOT:
+ if (maskmax == 0)
+ return MATCH_EQUAL;
+ [[fallthrough]];
+ case MATCH_EQUAL:
case MATCH_GE:
case MATCH_LT:
case MATCH_MASK_LOW:
@@ -261,7 +295,14 @@ bool mcontrol_common_t::legalize_timing(reg_t val, reg_t timing_mask, reg_t sele
return TIMING_AFTER;
if (get_field(val, execute_mask))
return TIMING_BEFORE;
- return get_field(val, timing_mask);
+ if (timing_mask) {
+ // Use the requested timing.
+ return get_field(val, timing_mask);
+ } else {
+ // For mcontrol6 you can't request a timing. Default to before since that's
+ // most useful to the user.
+ return TIMING_BEFORE;
+ }
}
reg_t mcontrol6_t::tdata1_read(const processor_t * const proc) const noexcept {
@@ -290,13 +331,14 @@ void mcontrol6_t::tdata1_write(processor_t * const proc, const reg_t val, const
auto xlen = proc->get_const_xlen();
assert(get_field(val, CSR_MCONTROL6_TYPE(xlen)) == CSR_TDATA1_TYPE_MCONTROL6);
dmode = get_field(val, CSR_MCONTROL6_DMODE(xlen));
+ const reg_t maskmax6 = xlen - 1;
vs = get_field(val, CSR_MCONTROL6_VS);
vu = get_field(val, CSR_MCONTROL6_VU);
hit = hit_t(2 * get_field(val, CSR_MCONTROL6_HIT1) + get_field(val, CSR_MCONTROL6_HIT0)); // 2-bit field {hit1,hit0}
select = get_field(val, CSR_MCONTROL6_SELECT);
action = legalize_action(val, CSR_MCONTROL6_ACTION, CSR_MCONTROL6_DMODE(xlen));
chain = allow_chain ? get_field(val, CSR_MCONTROL6_CHAIN) : 0;
- match = legalize_match(get_field(val, CSR_MCONTROL6_MATCH));
+ match = legalize_match(get_field(val, CSR_MCONTROL6_MATCH), maskmax6);
m = get_field(val, CSR_MCONTROL6_M);
s = proc->extension_enabled_const('S') ? get_field(val, CSR_MCONTROL6_S) : 0;
u = proc->extension_enabled_const('U') ? get_field(val, CSR_MCONTROL6_U) : 0;
@@ -312,7 +354,7 @@ void mcontrol6_t::tdata1_write(processor_t * const proc, const reg_t val, const
std::optional<match_result_t> icount_t::detect_icount_fire(processor_t * const proc) noexcept
{
- if (!common_match(proc) || !allow_action(proc->get_state()))
+ if (!common_match(proc))
return std::nullopt;
std::optional<match_result_t> ret = std::nullopt;
@@ -327,7 +369,7 @@ std::optional<match_result_t> icount_t::detect_icount_fire(processor_t * const p
void icount_t::detect_icount_decrement(processor_t * const proc) noexcept
{
- if (!common_match(proc) || !allow_action(proc->get_state()))
+ if (!common_match(proc))
return;
if (count >= 1) {
@@ -419,7 +461,7 @@ std::optional<match_result_t> trap_common_t::detect_trap_match(processor_t * con
bool interrupt = (t.cause() & ((reg_t)1 << (xlen - 1))) != 0;
reg_t bit = t.cause() & ~((reg_t)1 << (xlen - 1));
assert(bit < xlen);
- if (simple_match(interrupt, bit) && allow_action(proc->get_state())) {
+ if (simple_match(interrupt, bit)) {
hit = true;
return match_result_t(TIMING_AFTER, action);
}
@@ -636,4 +678,4 @@ reg_t module_t::tinfo_read(unsigned UNUSED index) const noexcept
(CSR_TINFO_VERSION_1 << CSR_TINFO_VERSION_OFFSET);
}
-};
+}
diff --git a/riscv/triggers.h b/riscv/triggers.h
index 24f9206..60ee5ca 100644
--- a/riscv/triggers.h
+++ b/riscv/triggers.h
@@ -99,7 +99,6 @@ public:
protected:
static action_t legalize_action(reg_t val, reg_t action_mask, reg_t dmode_mask) noexcept;
bool common_match(processor_t * const proc, bool use_prev_prv = false) const noexcept;
- bool allow_action(const state_t * const state) const;
reg_t tdata2;
bool vs = false;
@@ -221,7 +220,7 @@ private:
bool simple_match(unsigned xlen, reg_t value) const;
protected:
- static match_t legalize_match(reg_t val) noexcept;
+ static match_t legalize_match(reg_t val, reg_t maskmax) noexcept;
static bool legalize_timing(reg_t val, reg_t timing_mask, reg_t select_mask, reg_t execute_mask, reg_t load_mask) noexcept;
bool dmode = false;
action_t action = ACTION_DEBUG_EXCEPTION;
@@ -243,6 +242,7 @@ public:
private:
bool hit = false;
+ const reg_t maskmax = 0;
};
class mcontrol6_t : public mcontrol_common_t {
@@ -301,6 +301,6 @@ private:
std::vector<trigger_t *> triggers;
};
-};
+}
#endif
diff --git a/riscv/v_ext_macros.h b/riscv/v_ext_macros.h
index 3e8a653..1e33232 100644
--- a/riscv/v_ext_macros.h
+++ b/riscv/v_ext_macros.h
@@ -8,16 +8,10 @@
//
// vector: masking skip helper
//
-#define VI_MASK_VARS \
- const int midx = i / 64; \
- const int mpos = i % 64;
-
#define VI_LOOP_ELEMENT_SKIP(BODY) \
- VI_MASK_VARS \
if (insn.v_vm() == 0) { \
BODY; \
- bool skip = ((P.VU.elt<uint64_t>(0, midx) >> mpos) & 0x1) == 0; \
- if (skip) { \
+ if (!P.VU.mask_elt(0, i)) { \
continue; \
} \
}
@@ -206,7 +200,7 @@ static inline bool is_overlapped_widen(const int astart, int asize,
require_vector(true); \
reg_t vl = P.VU.vl->read(); \
reg_t UNUSED sew = P.VU.vsew; \
- reg_t rd_num = insn.rd(); \
+ reg_t UNUSED rd_num = insn.rd(); \
reg_t UNUSED rs1_num = insn.rs1(); \
reg_t rs2_num = insn.rs2(); \
for (reg_t i = P.VU.vstart->read(); i < vl; ++i) {
@@ -231,24 +225,18 @@ static inline bool is_overlapped_widen(const int astart, int asize,
#define VI_LOOP_CARRY_BASE \
VI_GENERAL_LOOP_BASE \
- VI_MASK_VARS \
- auto v0 = P.VU.elt<uint64_t>(0, midx); \
- const uint64_t mmask = UINT64_C(1) << mpos; \
const uint128_t op_mask = (UINT64_MAX >> (64 - sew)); \
- uint64_t carry = insn.v_vm() == 0 ? (v0 >> mpos) & 0x1 : 0; \
- uint128_t res = 0; \
- auto &vd = P.VU.elt<uint64_t>(rd_num, midx, true);
+ uint64_t carry = insn.v_vm() == 0 ? P.VU.mask_elt(0, i) : 0; \
+ bool res = false;
#define VI_LOOP_CARRY_END \
- vd = (vd & ~mmask) | (((res) << mpos) & mmask); \
+ P.VU.set_mask_elt(insn.rd(), i, res); \
} \
P.VU.vstart->write(0);
#define VI_LOOP_WITH_CARRY_BASE \
VI_GENERAL_LOOP_BASE \
- VI_MASK_VARS \
- auto &v0 = P.VU.elt<uint64_t>(0, midx); \
const uint128_t op_mask = (UINT64_MAX >> (64 - sew)); \
- uint64_t carry = (v0 >> mpos) & 0x1;
+ uint64_t carry = P.VU.mask_elt(0, i);
#define VI_LOOP_CMP_BASE \
require(P.VU.vsew >= e8 && P.VU.vsew <= e64); \
@@ -260,12 +248,10 @@ static inline bool is_overlapped_widen(const int astart, int asize,
reg_t rs2_num = insn.rs2(); \
for (reg_t i = P.VU.vstart->read(); i < vl; ++i) { \
VI_LOOP_ELEMENT_SKIP(); \
- uint64_t mmask = UINT64_C(1) << mpos; \
- uint64_t &vdi = P.VU.elt<uint64_t>(insn.rd(), midx, true); \
- uint64_t res = 0;
+ bool res = false;
#define VI_LOOP_CMP_END \
- vdi = (vdi & ~mmask) | (((res) << mpos) & mmask); \
+ P.VU.set_mask_elt(insn.rd(), i, res); \
} \
P.VU.vstart->write(0);
@@ -274,13 +260,9 @@ static inline bool is_overlapped_widen(const int astart, int asize,
require_vector(true); \
reg_t vl = P.VU.vl->read(); \
for (reg_t i = P.VU.vstart->read(); i < vl; ++i) { \
- int midx = i / 64; \
- int mpos = i % 64; \
- uint64_t mmask = UINT64_C(1) << mpos; \
- uint64_t vs2 = P.VU.elt<uint64_t>(insn.rs2(), midx); \
- uint64_t vs1 = P.VU.elt<uint64_t>(insn.rs1(), midx); \
- uint64_t &res = P.VU.elt<uint64_t>(insn.rd(), midx, true); \
- res = (res & ~mmask) | ((op) & (1ULL << mpos)); \
+ bool vs2 = P.VU.mask_elt(insn.rs2(), i); \
+ bool vs1 = P.VU.mask_elt(insn.rs1(), i); \
+ P.VU.set_mask_elt(insn.rd(), i, (op)); \
} \
P.VU.vstart->write(0);
@@ -354,7 +336,7 @@ static inline bool is_overlapped_widen(const int astart, int asize,
#define VI_PARAMS(x) \
type_sew_t<x>::type &vd = P.VU.elt<type_sew_t<x>::type>(rd_num, i, true); \
- type_sew_t<x>::type simm5 = (type_sew_t<x>::type)insn.v_simm5(); \
+ type_sew_t<x>::type UNUSED simm5 = (type_sew_t<x>::type)insn.v_simm5(); \
type_sew_t<x>::type UNUSED vs2 = P.VU.elt<type_sew_t<x>::type>(rs2_num, i);
#define XV_PARAMS(x) \
@@ -454,7 +436,7 @@ static inline bool is_overlapped_widen(const int astart, int asize,
#define VFP_VF_CMP_PARAMS(width) \
float##width##_t rs1 = f##width(READ_FREG(rs1_num)); \
- float##width##_t vs2 = P.VU.elt<float##width##_t>(rs2_num, i);
+ float##width##_t UNUSED vs2 = P.VU.elt<float##width##_t>(rs2_num, i);
#define VFP_VF_PARAMS(width) \
float##width##_t &vd = P.VU.elt<float##width##_t>(rd_num, i, true); \
@@ -491,7 +473,7 @@ static inline bool is_overlapped_widen(const int astart, int asize,
BODY; \
}
-// comparision result to masking register
+// comparison result to masking register
#define VI_LOOP_CMP_BODY(PARAMS, BODY) \
VI_LOOP_CMP_BASE \
INSNS_BASE(PARAMS, BODY) \
@@ -523,8 +505,7 @@ static inline bool is_overlapped_widen(const int astart, int asize,
// merge and copy loop
#define VI_MERGE_VARS \
- VI_MASK_VARS \
- bool UNUSED use_first = (P.VU.elt<uint64_t>(0, midx) >> mpos) & 0x1;
+ bool UNUSED use_first = P.VU.mask_elt(0, i);
#define VI_MERGE_LOOP_BASE \
VI_GENERAL_LOOP_BASE \
@@ -1144,32 +1125,32 @@ static inline bool is_overlapped_widen(const int astart, int asize,
// average loop
#define VI_VV_LOOP_AVG(op) \
-VRM xrm = p->VU.get_vround_mode(); \
VI_VV_LOOP({ \
+ VRM xrm = p->VU.get_vround_mode(); \
uint128_t res = ((uint128_t)vs2) op vs1; \
INT_ROUNDING(res, xrm, 1); \
vd = res >> 1; \
})
#define VI_VX_LOOP_AVG(op) \
-VRM xrm = p->VU.get_vround_mode(); \
VI_VX_LOOP({ \
+ VRM xrm = p->VU.get_vround_mode(); \
uint128_t res = ((uint128_t)vs2) op rs1; \
INT_ROUNDING(res, xrm, 1); \
vd = res >> 1; \
})
#define VI_VV_ULOOP_AVG(op) \
-VRM xrm = p->VU.get_vround_mode(); \
VI_VV_ULOOP({ \
+ VRM xrm = p->VU.get_vround_mode(); \
uint128_t res = ((uint128_t)vs2) op vs1; \
INT_ROUNDING(res, xrm, 1); \
vd = res >> 1; \
})
#define VI_VX_ULOOP_AVG(op) \
-VRM xrm = p->VU.get_vround_mode(); \
VI_VX_ULOOP({ \
+ VRM xrm = p->VU.get_vround_mode(); \
uint128_t res = ((uint128_t)vs2) op rs1; \
INT_ROUNDING(res, xrm, 1); \
vd = res >> 1; \
@@ -1181,31 +1162,12 @@ VI_VX_ULOOP({ \
#define VI_STRIP(inx) \
reg_t vreg_inx = inx;
-#define VI_DUPLICATE_VREG(reg_num, idx_sew) \
-reg_t index[P.VU.vlmax]; \
- for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl->read() != 0; ++i) { \
- switch (idx_sew) { \
- case e8: \
- index[i] = P.VU.elt<uint8_t>(reg_num, i); \
- break; \
- case e16: \
- index[i] = P.VU.elt<uint16_t>(reg_num, i); \
- break; \
- case e32: \
- index[i] = P.VU.elt<uint32_t>(reg_num, i); \
- break; \
- case e64: \
- index[i] = P.VU.elt<uint64_t>(reg_num, i); \
- break; \
- } \
-}
-
#define VI_LD(stride, offset, elt_width, is_mask_ldst) \
const reg_t nf = insn.v_nf() + 1; \
+ VI_CHECK_LOAD(elt_width, is_mask_ldst); \
const reg_t vl = is_mask_ldst ? ((P.VU.vl->read() + 7) / 8) : P.VU.vl->read(); \
const reg_t baseAddr = RS1; \
const reg_t vd = insn.rd(); \
- VI_CHECK_LOAD(elt_width, is_mask_ldst); \
for (reg_t i = 0; i < vl; ++i) { \
VI_ELEMENT_SKIP; \
VI_STRIP(i); \
@@ -1218,16 +1180,33 @@ reg_t index[P.VU.vlmax]; \
} \
P.VU.vstart->write(0);
+#define VI_LDST_GET_INDEX(elt_width) \
+ reg_t index; \
+ switch (elt_width) { \
+ case e8: \
+ index = P.VU.elt<uint8_t>(insn.rs2(), i); \
+ break; \
+ case e16: \
+ index = P.VU.elt<uint16_t>(insn.rs2(), i); \
+ break; \
+ case e32: \
+ index = P.VU.elt<uint32_t>(insn.rs2(), i); \
+ break; \
+ case e64: \
+ index = P.VU.elt<uint64_t>(insn.rs2(), i); \
+ break; \
+ } \
+
#define VI_LD_INDEX(elt_width, is_seg) \
const reg_t nf = insn.v_nf() + 1; \
+ VI_CHECK_LD_INDEX(elt_width); \
const reg_t vl = P.VU.vl->read(); \
const reg_t baseAddr = RS1; \
const reg_t vd = insn.rd(); \
if (!is_seg) \
require(nf == 1); \
- VI_CHECK_LD_INDEX(elt_width); \
- VI_DUPLICATE_VREG(insn.rs2(), elt_width); \
for (reg_t i = 0; i < vl; ++i) { \
+ VI_LDST_GET_INDEX(elt_width); \
VI_ELEMENT_SKIP; \
VI_STRIP(i); \
P.VU.vstart->write(i); \
@@ -1235,19 +1214,19 @@ reg_t index[P.VU.vlmax]; \
switch (P.VU.vsew) { \
case e8: \
P.VU.elt<uint8_t>(vd + fn * flmul, vreg_inx, true) = \
- MMU.load<uint8_t>(baseAddr + index[i] + fn * 1); \
+ MMU.load<uint8_t>(baseAddr + index + fn * 1); \
break; \
case e16: \
P.VU.elt<uint16_t>(vd + fn * flmul, vreg_inx, true) = \
- MMU.load<uint16_t>(baseAddr + index[i] + fn * 2); \
+ MMU.load<uint16_t>(baseAddr + index + fn * 2); \
break; \
case e32: \
P.VU.elt<uint32_t>(vd + fn * flmul, vreg_inx, true) = \
- MMU.load<uint32_t>(baseAddr + index[i] + fn * 4); \
+ MMU.load<uint32_t>(baseAddr + index + fn * 4); \
break; \
default: \
P.VU.elt<uint64_t>(vd + fn * flmul, vreg_inx, true) = \
- MMU.load<uint64_t>(baseAddr + index[i] + fn * 8); \
+ MMU.load<uint64_t>(baseAddr + index + fn * 8); \
break; \
} \
} \
@@ -1256,10 +1235,10 @@ reg_t index[P.VU.vlmax]; \
#define VI_ST(stride, offset, elt_width, is_mask_ldst) \
const reg_t nf = insn.v_nf() + 1; \
+ VI_CHECK_STORE(elt_width, is_mask_ldst); \
const reg_t vl = is_mask_ldst ? ((P.VU.vl->read() + 7) / 8) : P.VU.vl->read(); \
const reg_t baseAddr = RS1; \
const reg_t vs3 = insn.rd(); \
- VI_CHECK_STORE(elt_width, is_mask_ldst); \
for (reg_t i = 0; i < vl; ++i) { \
VI_STRIP(i) \
VI_ELEMENT_SKIP; \
@@ -1274,33 +1253,33 @@ reg_t index[P.VU.vlmax]; \
#define VI_ST_INDEX(elt_width, is_seg) \
const reg_t nf = insn.v_nf() + 1; \
+ VI_CHECK_ST_INDEX(elt_width); \
const reg_t vl = P.VU.vl->read(); \
const reg_t baseAddr = RS1; \
const reg_t vs3 = insn.rd(); \
if (!is_seg) \
require(nf == 1); \
- VI_CHECK_ST_INDEX(elt_width); \
- VI_DUPLICATE_VREG(insn.rs2(), elt_width); \
for (reg_t i = 0; i < vl; ++i) { \
+ VI_LDST_GET_INDEX(elt_width); \
VI_STRIP(i) \
VI_ELEMENT_SKIP; \
P.VU.vstart->write(i); \
for (reg_t fn = 0; fn < nf; ++fn) { \
switch (P.VU.vsew) { \
case e8: \
- MMU.store<uint8_t>(baseAddr + index[i] + fn * 1, \
+ MMU.store<uint8_t>(baseAddr + index + fn * 1, \
P.VU.elt<uint8_t>(vs3 + fn * flmul, vreg_inx)); \
break; \
case e16: \
- MMU.store<uint16_t>(baseAddr + index[i] + fn * 2, \
+ MMU.store<uint16_t>(baseAddr + index + fn * 2, \
P.VU.elt<uint16_t>(vs3 + fn * flmul, vreg_inx)); \
break; \
case e32: \
- MMU.store<uint32_t>(baseAddr + index[i] + fn * 4, \
+ MMU.store<uint32_t>(baseAddr + index + fn * 4, \
P.VU.elt<uint32_t>(vs3 + fn * flmul, vreg_inx)); \
break; \
default: \
- MMU.store<uint64_t>(baseAddr + index[i] + fn * 8, \
+ MMU.store<uint64_t>(baseAddr + index + fn * 8, \
P.VU.elt<uint64_t>(vs3 + fn * flmul, vreg_inx)); \
break; \
} \
@@ -1310,10 +1289,10 @@ reg_t index[P.VU.vlmax]; \
#define VI_LDST_FF(elt_width) \
const reg_t nf = insn.v_nf() + 1; \
+ VI_CHECK_LOAD(elt_width, false); \
const reg_t vl = p->VU.vl->read(); \
const reg_t baseAddr = RS1; \
const reg_t rd_num = insn.rd(); \
- VI_CHECK_LOAD(elt_width, false); \
bool early_stop = false; \
for (reg_t i = p->VU.vstart->read(); i < vl; ++i) { \
VI_STRIP(i); \
@@ -1484,9 +1463,7 @@ reg_t index[P.VU.vlmax]; \
VI_VFP_COMMON \
for (reg_t i = P.VU.vstart->read(); i < vl; ++i) { \
VI_LOOP_ELEMENT_SKIP(); \
- uint64_t mmask = UINT64_C(1) << mpos; \
- uint64_t &vd = P.VU.elt<uint64_t>(rd_num, midx, true); \
- uint64_t res = 0;
+ bool res = false;
#define VI_VFP_LOOP_REDUCTION_BASE(width) \
float##width##_t vd_0 = P.VU.elt<float##width##_t>(rd_num, 0); \
@@ -1564,7 +1541,7 @@ reg_t index[P.VU.vlmax]; \
case e16: \
case e32: \
case e64: { \
- vd = (vd & ~mmask) | (((res) << mpos) & mmask); \
+ P.VU.set_mask_elt(insn.rd(), i, res); \
break; \
} \
default: \
diff --git a/riscv/vector_unit.cc b/riscv/vector_unit.cc
index 08adc61..7c6633c 100644
--- a/riscv/vector_unit.cc
+++ b/riscv/vector_unit.cc
@@ -13,15 +13,15 @@ void vectorUnit_t::vectorUnit_t::reset()
reg_file = malloc(NVPR * vlenb);
memset(reg_file, 0, NVPR * vlenb);
- auto& csrmap = p->get_state()->csrmap;
- csrmap[CSR_VXSAT] = vxsat = std::make_shared<vxsat_csr_t>(p, CSR_VXSAT);
- csrmap[CSR_VSTART] = vstart = std::make_shared<vector_csr_t>(p, CSR_VSTART, /*mask*/ VLEN - 1);
- csrmap[CSR_VXRM] = vxrm = std::make_shared<vector_csr_t>(p, CSR_VXRM, /*mask*/ 0x3ul);
- csrmap[CSR_VL] = vl = std::make_shared<vector_csr_t>(p, CSR_VL, /*mask*/ 0);
- csrmap[CSR_VTYPE] = vtype = std::make_shared<vector_csr_t>(p, CSR_VTYPE, /*mask*/ 0);
- csrmap[CSR_VLENB] = std::make_shared<vector_csr_t>(p, CSR_VLENB, /*mask*/ 0, /*init*/ vlenb);
+ auto state = p->get_state();
+ state->add_csr(CSR_VXSAT, vxsat = std::make_shared<vxsat_csr_t>(p, CSR_VXSAT));
+ state->add_csr(CSR_VSTART, vstart = std::make_shared<vector_csr_t>(p, CSR_VSTART, /*mask*/ VLEN - 1));
+ state->add_csr(CSR_VXRM, vxrm = std::make_shared<vector_csr_t>(p, CSR_VXRM, /*mask*/ 0x3ul));
+ state->add_csr(CSR_VL, vl = std::make_shared<vector_csr_t>(p, CSR_VL, /*mask*/ 0));
+ state->add_csr(CSR_VTYPE, vtype = std::make_shared<vector_csr_t>(p, CSR_VTYPE, /*mask*/ 0));
+ state->add_csr(CSR_VLENB, std::make_shared<vector_csr_t>(p, CSR_VLENB, /*mask*/ 0, /*init*/ vlenb));
assert(VCSR_VXSAT_SHIFT == 0); // composite_csr_t assumes vxsat begins at bit 0
- csrmap[CSR_VCSR] = std::make_shared<composite_csr_t>(p, CSR_VCSR, vxrm, vxsat, VCSR_VXRM_SHIFT);
+ state->add_csr(CSR_VCSR, std::make_shared<composite_csr_t>(p, CSR_VCSR, vxrm, vxsat, VCSR_VXRM_SHIFT));
vtype->write_raw(0);
set_vl(0, 0, 0, -1); // default to illegal configuration
@@ -29,10 +29,11 @@ void vectorUnit_t::vectorUnit_t::reset()
reg_t vectorUnit_t::vectorUnit_t::set_vl(int rd, int rs1, reg_t reqVL, reg_t newType)
{
- int new_vlmul = 0;
if (vtype->read() != newType) {
+ int new_vlmul = int8_t(extract64(newType, 0, 3) << 5) >> 5;
+ auto old_vlmax = vlmax;
+
vsew = 1 << (extract64(newType, 3, 3) + 3);
- new_vlmul = int8_t(extract64(newType, 0, 3) << 5) >> 5;
vflmul = new_vlmul >= 0 ? 1 << new_vlmul : 1.0 / (1 << -new_vlmul);
vlmax = (VLEN/vsew) * vflmul;
vta = extract64(newType, 6, 1);
@@ -40,7 +41,8 @@ reg_t vectorUnit_t::vectorUnit_t::set_vl(int rd, int rs1, reg_t reqVL, reg_t new
vill = !(vflmul >= 0.125 && vflmul <= 8)
|| vsew > std::min(vflmul, 1.0f) * ELEN
- || (newType >> 8) != 0;
+ || (newType >> 8) != 0
+ || (rd == 0 && rs1 == 0 && old_vlmax != vlmax);
if (vill) {
vlmax = 0;
@@ -54,7 +56,7 @@ reg_t vectorUnit_t::vectorUnit_t::set_vl(int rd, int rs1, reg_t reqVL, reg_t new
if (vlmax == 0) {
vl->write_raw(0);
} else if (rd == 0 && rs1 == 0) {
- vl->write_raw(std::min(vl->read(), vlmax));
+ ; // retain current VL
} else if (rd != 0 && rs1 == 0) {
vl->write_raw(vlmax);
} else if (rs1 != 0) {
diff --git a/riscv/vector_unit.h b/riscv/vector_unit.h
index a057c62..0e80618 100644
--- a/riscv/vector_unit.h
+++ b/riscv/vector_unit.h
@@ -108,6 +108,17 @@ public:
template<typename EG> EG&
elt_group(reg_t vReg, reg_t n, bool is_write = false);
+ bool mask_elt(reg_t vReg, reg_t n)
+ {
+ return (elt<uint8_t>(vReg, n / 8) >> (n % 8)) & 1;
+ }
+
+ void set_mask_elt(reg_t vReg, reg_t n, bool value)
+ {
+ auto& e = elt<uint8_t>(vReg, n / 8, true);
+ e = (e & ~(1U << (n % 8))) | (value << (n % 8));
+ }
+
public:
void reset();
diff --git a/riscv/zicfiss.h b/riscv/zicfiss.h
index 83c166d..c7aef64 100644
--- a/riscv/zicfiss.h
+++ b/riscv/zicfiss.h
@@ -25,7 +25,7 @@
shadow_return_addr = MMU.ss_load<uint32_t>(STATE.ssp->read()); \
else \
shadow_return_addr = MMU.ss_load<uint64_t>(STATE.ssp->read()); \
- software_check(value == shadow_return_addr, SHADOW_STACK_FAULT); \
+ software_check(zext_xlen(value) == shadow_return_addr, SHADOW_STACK_FAULT); \
STATE.ssp->write(STATE.ssp->read() + xlen / 8);
#endif
diff --git a/riscv/zvk_ext_macros.h b/riscv/zvk_ext_macros.h
index f094629..702ad91 100644
--- a/riscv/zvk_ext_macros.h
+++ b/riscv/zvk_ext_macros.h
@@ -86,6 +86,32 @@
// (LMUL * VLEN) <= EGW
#define require_egw_fits(EGW) require((EGW) <= (P.VU.VLEN * P.VU.vflmul))
+// Ensures that a register index is aligned to EMUL
+// evaluated as EGW / VLEN.
+// The check is only enabled if this value is greater
+// than one (no index alignment check required for fractional EMUL)
+#define require_vreg_align_eglmul(EGW, VREG_NUM) \
+ do { \
+ float vfeglmul = EGW / P.VU.VLEN; \
+ if (vfeglmul > 1) { \
+ require_align(VREG_NUM, vfeglmul); \
+ }\
+ } while (0)
+
+#define require_vs2_align_eglmul(EGW) require_vreg_align_eglmul(EGW, insn.rs2())
+
+// ensure that rs2 and rd do not overlap, assuming rd encodes an LMUL wide
+// vector register group and rs2 encodes an vs2_EMUL=ceil(EGW / VLEN) vector register
+// group.
+// Assumption: LMUL >= vs2_EMUL which is enforced independently through require_egw_fits.
+#define require_noover_eglmul(vd, vs2) \
+ do { \
+ int vd_emul = P.VU.vflmul < 1.f ? 1 : (int) P.VU.vflmul; \
+ int aligned_vd = vd / vd_emul; \
+ int aligned_vs2 = vs2 / vd_emul; \
+ require(aligned_vd != aligned_vs2); \
+ } while (0)
+
// Checks that the vector unit state (vtype and vl) can be interpreted
// as element groups with EEW=32, EGS=4 (four 32-bits elements per group),
// for an effective element group width of EGW=128 bits.
diff --git a/riscv/zvkned_ext_macros.h b/riscv/zvkned_ext_macros.h
index db705c7..d94ddc2 100644
--- a/riscv/zvkned_ext_macros.h
+++ b/riscv/zvkned_ext_macros.h
@@ -2,6 +2,7 @@
// the RISC-V Zvkned extension (vector AES single round).
#include "insns/aes_common.h"
+#include "zvk_ext_macros.h"
#ifndef RISCV_ZVKNED_EXT_MACROS_H_
#define RISCV_ZVKNED_EXT_MACROS_H_
@@ -9,16 +10,22 @@
// vaes*.vs instruction constraints:
// - Zvkned is enabled
// - EGW (128) <= LMUL * VLEN
+// - vd is LMUL aligned
+// - vs2 is ceil(EGW / VLEN) aligned
// - vd and vs2 cannot overlap
//
// The constraint that vstart and vl are both EGS (4) aligned
// is checked in the VI_ZVK_..._EGU32x4_..._LOOP macros.
#define require_vaes_vs_constraints \
do { \
+ const uint32_t EGS = 4; \
require_zvkned; \
+ require(P.VU.vl->read() % EGS == 0); \
require(P.VU.vsew == 32); \
require_egw_fits(128); \
- require(insn.rd() != insn.rs2()); \
+ require_align(insn.rd(), P.VU.vflmul); \
+ require_vs2_align_eglmul(128); \
+ require_noover_eglmul(insn.rd(), insn.rs2()); \
} while (false)
// vaes*.vv instruction constraints. Those are the same as the .vs ones,
@@ -30,17 +37,24 @@
// is checked in the VI_ZVK_..._EGU32x4_..._LOOP macros.
#define require_vaes_vv_constraints \
do { \
+ const uint32_t EGS = 4; \
require_zvkned; \
+ require(P.VU.vl->read() % EGS == 0); \
require(P.VU.vsew == 32); \
require_egw_fits(128); \
+ VI_CHECK_SSS(false) \
} while (false)
// vaeskf*.vi instruction constraints. Those are the same as the .vv ones.
#define require_vaeskf_vi_constraints \
do { \
+ const uint32_t EGS = 4; \
require_zvkned; \
+ require(P.VU.vstart->read() % EGS == 0); \
+ require(P.VU.vl->read() % EGS == 0); \
require(P.VU.vsew == 32); \
require_egw_fits(128); \
+ VI_CHECK_SSS(false) \
} while (false)
#define VAES_XTIME(A) (((A) << 1) ^ (((A) & 0x80) ? 0x1b : 0))
diff --git a/riscv/zvknh_ext_macros.h b/riscv/zvknh_ext_macros.h
index b50818b..98236b0 100644
--- a/riscv/zvknh_ext_macros.h
+++ b/riscv/zvknh_ext_macros.h
@@ -15,6 +15,7 @@
// macros.
#define require_vsha2_common_constraints \
do { \
+ VI_CHECK_SSS(true) \
require(P.VU.vsew == 32 || P.VU.vsew == 64); \
require(insn.rd() != insn.rs1()); \
require(insn.rd() != insn.rs2()); \
diff --git a/riscv/zvksed_ext_macros.h b/riscv/zvksed_ext_macros.h
index 46e399b..3ffa272 100644
--- a/riscv/zvksed_ext_macros.h
+++ b/riscv/zvksed_ext_macros.h
@@ -16,9 +16,12 @@
// is checked in the VI_ZVK_..._EGU32x4_..._LOOP macros.
#define require_vsm4_constraints \
do { \
+ const uint32_t EGS = 4; \
require_zvksed; \
require(P.VU.vsew == 32); \
require_egw_fits(128); \
+ require(P.VU.vstart->read() % EGS == 0); \
+ require(P.VU.vl->read() % EGS == 0); \
} while (false)
// Returns a uint32_t value constructed from the 4 bytes (uint8_t)
diff --git a/riscv/zvksh_ext_macros.h b/riscv/zvksh_ext_macros.h
index 71c5a09..c4549da 100644
--- a/riscv/zvksh_ext_macros.h
+++ b/riscv/zvksh_ext_macros.h
@@ -16,9 +16,12 @@
// is checked in the VI_ZVK_..._EGU32x8_..._LOOP macros.
#define require_vsm3_constraints \
do { \
+ const uint32_t EGS = 8; \
require_zvksh; \
require(P.VU.vsew == 32); \
require_egw_fits(256); \
+ require(P.VU.vstart->read() % EGS == 0); \
+ require(P.VU.vl->read() % EGS == 0); \
require(insn.rd() != insn.rs2()); \
} while (false)
diff --git a/scripts/config.guess b/scripts/config.guess
index 699b3a1..cdfc439 100644..100755
--- a/scripts/config.guess
+++ b/scripts/config.guess
@@ -1,12 +1,14 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2020 Free Software Foundation, Inc.
+# Copyright 1992-2023 Free Software Foundation, Inc.
-timestamp='2020-11-19'
+# shellcheck disable=SC2006,SC2268 # see below for rationale
+
+timestamp='2023-08-22'
# This file 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
+# 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
@@ -32,12 +34,20 @@ timestamp='2020-11-19'
# Please send patches to <config-patches@gnu.org>.
-me=$(echo "$0" | sed -e 's,.*/,,')
+# The "shellcheck disable" line above the timestamp inhibits complaints
+# about features and limitations of the classic Bourne shell that were
+# superseded or lifted in POSIX. However, this script identifies a wide
+# variety of pre-POSIX systems that do not have POSIX shells at all, and
+# even some reasonably current systems (Solaris 10 as case-in-point) still
+# have a pre-POSIX /bin/sh.
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION]
-Output the configuration name of the system \`$me' is run on.
+Output the configuration name of the system '$me' is run on.
Options:
-h, --help print this help, then exit
@@ -50,13 +60,13 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2020 Free Software Foundation, Inc.
+Copyright 1992-2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
-Try \`$me --help' for more information."
+Try '$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
@@ -84,13 +94,16 @@ if test $# != 0; then
exit 1
fi
+# Just in case it came from the environment.
+GUESS=
+
# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
# compiler to aid in system detection is discouraged as it requires
# temporary files to be created and, as you can see below, it is a
# headache to deal with in a portable fashion.
-# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
-# use `HOST_CC' if defined, but it is deprecated.
+# Historically, 'CC_FOR_BUILD' used to be named 'HOST_CC'. We still
+# use 'HOST_CC' if defined, but it is deprecated.
# Portable tmp directory creation inspired by the Autoconf team.
@@ -102,8 +115,8 @@ set_cc_for_build() {
# prevent multiple calls if $tmp is already set
test "$tmp" && return 0
: "${TMPDIR=/tmp}"
- # shellcheck disable=SC2039
- { tmp=$( (umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null) && test -n "$tmp" && test -d "$tmp" ; } ||
+ # shellcheck disable=SC2039,SC3028
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
@@ -112,7 +125,7 @@ set_cc_for_build() {
,,) echo "int x;" > "$dummy.c"
for driver in cc gcc c89 c99 ; do
if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
- CC_FOR_BUILD="$driver"
+ CC_FOR_BUILD=$driver
break
fi
done
@@ -131,17 +144,20 @@ if test -f /.attbin/uname ; then
PATH=$PATH:/.attbin ; export PATH
fi
-UNAME_MACHINE=$( (uname -m) 2>/dev/null) || UNAME_MACHINE=unknown
-UNAME_RELEASE=$( (uname -r) 2>/dev/null) || UNAME_RELEASE=unknown
-UNAME_SYSTEM=$( (uname -s) 2>/dev/null) || UNAME_SYSTEM=unknown
-UNAME_VERSION=$( (uname -v) 2>/dev/null) || UNAME_VERSION=unknown
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
-case "$UNAME_SYSTEM" in
+case $UNAME_SYSTEM in
Linux|GNU|GNU/*)
LIBC=unknown
set_cc_for_build
cat <<-EOF > "$dummy.c"
+ #if defined(__ANDROID__)
+ LIBC=android
+ #else
#include <features.h>
#if defined(__UCLIBC__)
LIBC=uclibc
@@ -156,8 +172,10 @@ Linux|GNU|GNU/*)
LIBC=musl
#endif
#endif
+ #endif
EOF
- eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g')"
+ cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ eval "$cc_set_libc"
# Second heuristic to detect musl libc.
if [ "$LIBC" = unknown ] &&
@@ -176,7 +194,7 @@ esac
# Note: order is significant - the case branches are not exclusive.
-case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
+case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
@@ -188,12 +206,11 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
#
# Note: NetBSD doesn't particularly care about the vendor
# portion of the name. We always set it to "unknown".
- sysctl="sysctl -n hw.machine_arch"
- UNAME_MACHINE_ARCH=$( (uname -p 2>/dev/null || \
- "/sbin/$sysctl" 2>/dev/null || \
- "/usr/sbin/$sysctl" 2>/dev/null || \
- echo unknown))
- case "$UNAME_MACHINE_ARCH" in
+ UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+ /sbin/sysctl -n hw.machine_arch 2>/dev/null || \
+ /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
+ echo unknown)`
+ case $UNAME_MACHINE_ARCH in
aarch64eb) machine=aarch64_be-unknown ;;
armeb) machine=armeb-unknown ;;
arm*) machine=arm-unknown ;;
@@ -201,15 +218,15 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;;
earmv*)
- arch=$(echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,')
- endian=$(echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p')
- machine="${arch}${endian}"-unknown
+ arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
+ machine=${arch}${endian}-unknown
;;
- *) machine="$UNAME_MACHINE_ARCH"-unknown ;;
+ *) machine=$UNAME_MACHINE_ARCH-unknown ;;
esac
# The Operating System including object format, if it has switched
# to ELF recently (or will in the future) and ABI.
- case "$UNAME_MACHINE_ARCH" in
+ case $UNAME_MACHINE_ARCH in
earm*)
os=netbsdelf
;;
@@ -230,10 +247,10 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
;;
esac
# Determine ABI tags.
- case "$UNAME_MACHINE_ARCH" in
+ case $UNAME_MACHINE_ARCH in
earm*)
expr='s/^earmv[0-9]/-eabi/;s/eb$//'
- abi=$(echo "$UNAME_MACHINE_ARCH" | sed -e "$expr")
+ abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
;;
esac
# The OS release
@@ -241,76 +258,82 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
# thus, need a distinct triplet. However, they do not need
# kernel version information, so it can be replaced with a
# suitable tag, in the style of linux-gnu.
- case "$UNAME_VERSION" in
+ case $UNAME_VERSION in
Debian*)
release='-gnu'
;;
*)
- release=$(echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2)
+ release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
;;
esac
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
- echo "$machine-${os}${release}${abi-}"
- exit ;;
+ GUESS=$machine-${os}${release}${abi-}
+ ;;
*:Bitrig:*:*)
- UNAME_MACHINE_ARCH=$(arch | sed 's/Bitrig.//')
- echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
- exit ;;
+ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE
+ ;;
*:OpenBSD:*:*)
- UNAME_MACHINE_ARCH=$(arch | sed 's/OpenBSD.//')
- echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
- exit ;;
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE
+ ;;
+ *:SecBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE
+ ;;
*:LibertyBSD:*:*)
- UNAME_MACHINE_ARCH=$(arch | sed 's/^.*BSD\.//')
- echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
- exit ;;
+ UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE
+ ;;
*:MidnightBSD:*:*)
- echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE
+ ;;
*:ekkoBSD:*:*)
- echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE
+ ;;
*:SolidBSD:*:*)
- echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE
+ ;;
*:OS108:*:*)
- echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE
+ ;;
macppc:MirBSD:*:*)
- echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
- exit ;;
+ GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE
+ ;;
*:MirBSD:*:*)
- echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE
+ ;;
*:Sortix:*:*)
- echo "$UNAME_MACHINE"-unknown-sortix
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-sortix
+ ;;
*:Twizzler:*:*)
- echo "$UNAME_MACHINE"-unknown-twizzler
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-twizzler
+ ;;
*:Redox:*:*)
- echo "$UNAME_MACHINE"-unknown-redox
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-redox
+ ;;
mips:OSF1:*.*)
- echo mips-dec-osf1
- exit ;;
+ GUESS=mips-dec-osf1
+ ;;
alpha:OSF1:*:*)
+ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+ trap '' 0
case $UNAME_RELEASE in
*4.0)
- UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $3}')
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
;;
*5.*)
- UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $4}')
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
;;
esac
# According to Compaq, /usr/sbin/psrinfo has been available on
# OSF/1 and Tru64 systems produced since 1995. I hope that
# covers most systems running today. This code pipes the CPU
# types through head -n 1, so we only detect the type of CPU 0.
- ALPHA_CPU_TYPE=$(/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1)
- case "$ALPHA_CPU_TYPE" in
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case $ALPHA_CPU_TYPE in
"EV4 (21064)")
UNAME_MACHINE=alpha ;;
"EV4.5 (21064)")
@@ -347,68 +370,69 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
- echo "$UNAME_MACHINE"-dec-osf"$(echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)"
- # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
- exitcode=$?
- trap '' 0
- exit $exitcode ;;
+ OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ GUESS=$UNAME_MACHINE-dec-osf$OSF_REL
+ ;;
Amiga*:UNIX_System_V:4.0:*)
- echo m68k-unknown-sysv4
- exit ;;
+ GUESS=m68k-unknown-sysv4
+ ;;
*:[Aa]miga[Oo][Ss]:*:*)
- echo "$UNAME_MACHINE"-unknown-amigaos
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-amigaos
+ ;;
*:[Mm]orph[Oo][Ss]:*:*)
- echo "$UNAME_MACHINE"-unknown-morphos
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-morphos
+ ;;
*:OS/390:*:*)
- echo i370-ibm-openedition
- exit ;;
+ GUESS=i370-ibm-openedition
+ ;;
*:z/VM:*:*)
- echo s390-ibm-zvmoe
- exit ;;
+ GUESS=s390-ibm-zvmoe
+ ;;
*:OS400:*:*)
- echo powerpc-ibm-os400
- exit ;;
+ GUESS=powerpc-ibm-os400
+ ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
- echo arm-acorn-riscix"$UNAME_RELEASE"
- exit ;;
+ GUESS=arm-acorn-riscix$UNAME_RELEASE
+ ;;
arm*:riscos:*:*|arm*:RISCOS:*:*)
- echo arm-unknown-riscos
- exit ;;
+ GUESS=arm-unknown-riscos
+ ;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
- echo hppa1.1-hitachi-hiuxmpp
- exit ;;
+ GUESS=hppa1.1-hitachi-hiuxmpp
+ ;;
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
- if test "$( (/bin/universe) 2>/dev/null)" = att ; then
- echo pyramid-pyramid-sysv3
- else
- echo pyramid-pyramid-bsd
- fi
- exit ;;
+ case `(/bin/universe) 2>/dev/null` in
+ att) GUESS=pyramid-pyramid-sysv3 ;;
+ *) GUESS=pyramid-pyramid-bsd ;;
+ esac
+ ;;
NILE*:*:*:dcosx)
- echo pyramid-pyramid-svr4
- exit ;;
+ GUESS=pyramid-pyramid-svr4
+ ;;
DRS?6000:unix:4.0:6*)
- echo sparc-icl-nx6
- exit ;;
+ GUESS=sparc-icl-nx6
+ ;;
DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
- case $(/usr/bin/uname -p) in
- sparc) echo sparc-icl-nx7; exit ;;
- esac ;;
+ case `/usr/bin/uname -p` in
+ sparc) GUESS=sparc-icl-nx7 ;;
+ esac
+ ;;
s390x:SunOS:*:*)
- echo "$UNAME_MACHINE"-ibm-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')"
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL
+ ;;
sun4H:SunOS:5.*:*)
- echo sparc-hal-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-hal-solaris2$SUN_REL
+ ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
- echo sparc-sun-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')"
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-sun-solaris2$SUN_REL
+ ;;
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
- echo i386-pc-auroraux"$UNAME_RELEASE"
- exit ;;
+ GUESS=i386-pc-auroraux$UNAME_RELEASE
+ ;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
set_cc_for_build
SUN_ARCH=i386
@@ -417,47 +441,50 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
# This test works for both compilers.
if test "$CC_FOR_BUILD" != no_compiler_found; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
SUN_ARCH=x86_64
fi
fi
- echo "$SUN_ARCH"-pc-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=$SUN_ARCH-pc-solaris2$SUN_REL
+ ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
- echo sparc-sun-solaris3"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-sun-solaris3$SUN_REL
+ ;;
sun4*:SunOS:*:*)
- case "$(/usr/bin/arch -k)" in
+ case `/usr/bin/arch -k` in
Series*|S4*)
- UNAME_RELEASE=$(uname -v)
+ UNAME_RELEASE=`uname -v`
;;
esac
- # Japanese Language versions have a version number like `4.1.3-JL'.
- echo sparc-sun-sunos"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/')"
- exit ;;
+ # Japanese Language versions have a version number like '4.1.3-JL'.
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
+ GUESS=sparc-sun-sunos$SUN_REL
+ ;;
sun3*:SunOS:*:*)
- echo m68k-sun-sunos"$UNAME_RELEASE"
- exit ;;
+ GUESS=m68k-sun-sunos$UNAME_RELEASE
+ ;;
sun*:*:4.2BSD:*)
- UNAME_RELEASE=$( (sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
- case "$(/bin/arch)" in
+ case `/bin/arch` in
sun3)
- echo m68k-sun-sunos"$UNAME_RELEASE"
+ GUESS=m68k-sun-sunos$UNAME_RELEASE
;;
sun4)
- echo sparc-sun-sunos"$UNAME_RELEASE"
+ GUESS=sparc-sun-sunos$UNAME_RELEASE
;;
esac
- exit ;;
+ ;;
aushp:SunOS:*:*)
- echo sparc-auspex-sunos"$UNAME_RELEASE"
- exit ;;
+ GUESS=sparc-auspex-sunos$UNAME_RELEASE
+ ;;
# The situation for MiNT is a little confusing. The machine name
# can be virtually everything (everything which is not
# "atarist" or "atariste" at least should have a processor
@@ -467,41 +494,41 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint"$UNAME_RELEASE"
- exit ;;
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint"$UNAME_RELEASE"
- exit ;;
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
- echo m68k-atari-mint"$UNAME_RELEASE"
- exit ;;
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
- echo m68k-milan-mint"$UNAME_RELEASE"
- exit ;;
+ GUESS=m68k-milan-mint$UNAME_RELEASE
+ ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
- echo m68k-hades-mint"$UNAME_RELEASE"
- exit ;;
+ GUESS=m68k-hades-mint$UNAME_RELEASE
+ ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
- echo m68k-unknown-mint"$UNAME_RELEASE"
- exit ;;
+ GUESS=m68k-unknown-mint$UNAME_RELEASE
+ ;;
m68k:machten:*:*)
- echo m68k-apple-machten"$UNAME_RELEASE"
- exit ;;
+ GUESS=m68k-apple-machten$UNAME_RELEASE
+ ;;
powerpc:machten:*:*)
- echo powerpc-apple-machten"$UNAME_RELEASE"
- exit ;;
+ GUESS=powerpc-apple-machten$UNAME_RELEASE
+ ;;
RISC*:Mach:*:*)
- echo mips-dec-mach_bsd4.3
- exit ;;
+ GUESS=mips-dec-mach_bsd4.3
+ ;;
RISC*:ULTRIX:*:*)
- echo mips-dec-ultrix"$UNAME_RELEASE"
- exit ;;
+ GUESS=mips-dec-ultrix$UNAME_RELEASE
+ ;;
VAX*:ULTRIX*:*:*)
- echo vax-dec-ultrix"$UNAME_RELEASE"
- exit ;;
+ GUESS=vax-dec-ultrix$UNAME_RELEASE
+ ;;
2020:CLIX:*:* | 2430:CLIX:*:*)
- echo clipper-intergraph-clix"$UNAME_RELEASE"
- exit ;;
+ GUESS=clipper-intergraph-clix$UNAME_RELEASE
+ ;;
mips:*:*:UMIPS | mips:*:*:RISCos)
set_cc_for_build
sed 's/^ //' << EOF > "$dummy.c"
@@ -526,78 +553,79 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
}
EOF
$CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
- dummyarg=$(echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p') &&
- SYSTEM_NAME=$("$dummy" "$dummyarg") &&
+ dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
{ echo "$SYSTEM_NAME"; exit; }
- echo mips-mips-riscos"$UNAME_RELEASE"
- exit ;;
+ GUESS=mips-mips-riscos$UNAME_RELEASE
+ ;;
Motorola:PowerMAX_OS:*:*)
- echo powerpc-motorola-powermax
- exit ;;
+ GUESS=powerpc-motorola-powermax
+ ;;
Motorola:*:4.3:PL8-*)
- echo powerpc-harris-powermax
- exit ;;
+ GUESS=powerpc-harris-powermax
+ ;;
Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
- echo powerpc-harris-powermax
- exit ;;
+ GUESS=powerpc-harris-powermax
+ ;;
Night_Hawk:Power_UNIX:*:*)
- echo powerpc-harris-powerunix
- exit ;;
+ GUESS=powerpc-harris-powerunix
+ ;;
m88k:CX/UX:7*:*)
- echo m88k-harris-cxux7
- exit ;;
+ GUESS=m88k-harris-cxux7
+ ;;
m88k:*:4*:R4*)
- echo m88k-motorola-sysv4
- exit ;;
+ GUESS=m88k-motorola-sysv4
+ ;;
m88k:*:3*:R3*)
- echo m88k-motorola-sysv3
- exit ;;
+ GUESS=m88k-motorola-sysv3
+ ;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
- UNAME_PROCESSOR=$(/usr/bin/uname -p)
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
then
if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
test "$TARGET_BINARY_INTERFACE"x = x
then
- echo m88k-dg-dgux"$UNAME_RELEASE"
+ GUESS=m88k-dg-dgux$UNAME_RELEASE
else
- echo m88k-dg-dguxbcs"$UNAME_RELEASE"
+ GUESS=m88k-dg-dguxbcs$UNAME_RELEASE
fi
else
- echo i586-dg-dgux"$UNAME_RELEASE"
+ GUESS=i586-dg-dgux$UNAME_RELEASE
fi
- exit ;;
+ ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
- echo m88k-dolphin-sysv3
- exit ;;
+ GUESS=m88k-dolphin-sysv3
+ ;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
- echo m88k-motorola-sysv3
- exit ;;
+ GUESS=m88k-motorola-sysv3
+ ;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
- echo m88k-tektronix-sysv3
- exit ;;
+ GUESS=m88k-tektronix-sysv3
+ ;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
- echo m68k-tektronix-bsd
- exit ;;
+ GUESS=m68k-tektronix-bsd
+ ;;
*:IRIX*:*:*)
- echo mips-sgi-irix"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/g')"
- exit ;;
+ IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'`
+ GUESS=mips-sgi-irix$IRIX_REL
+ ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
- echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
- exit ;; # Note that: echo "'$(uname -s)'" gives 'AIX '
+ GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ ;; # Note that: echo "'`uname -s`'" gives 'AIX '
i*86:AIX:*:*)
- echo i386-ibm-aix
- exit ;;
+ GUESS=i386-ibm-aix
+ ;;
ia64:AIX:*:*)
if test -x /usr/bin/oslevel ; then
- IBM_REV=$(/usr/bin/oslevel)
+ IBM_REV=`/usr/bin/oslevel`
else
- IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
+ IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
fi
- echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV"
- exit ;;
+ GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV
+ ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
set_cc_for_build
@@ -612,68 +640,68 @@ EOF
exit(0);
}
EOF
- if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy")
+ if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
then
- echo "$SYSTEM_NAME"
+ GUESS=$SYSTEM_NAME
else
- echo rs6000-ibm-aix3.2.5
+ GUESS=rs6000-ibm-aix3.2.5
fi
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
- echo rs6000-ibm-aix3.2.4
+ GUESS=rs6000-ibm-aix3.2.4
else
- echo rs6000-ibm-aix3.2
+ GUESS=rs6000-ibm-aix3.2
fi
- exit ;;
+ ;;
*:AIX:*:[4567])
- IBM_CPU_ID=$(/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }')
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
fi
if test -x /usr/bin/lslpp ; then
- IBM_REV=$(/usr/bin/lslpp -Lqc bos.rte.libc |
- awk -F: '{ print $3 }' | sed s/[0-9]*$/0/)
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \
+ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
else
- IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
+ IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
fi
- echo "$IBM_ARCH"-ibm-aix"$IBM_REV"
- exit ;;
+ GUESS=$IBM_ARCH-ibm-aix$IBM_REV
+ ;;
*:AIX:*:*)
- echo rs6000-ibm-aix
- exit ;;
+ GUESS=rs6000-ibm-aix
+ ;;
ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
- echo romp-ibm-bsd4.4
- exit ;;
+ GUESS=romp-ibm-bsd4.4
+ ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
- echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to
- exit ;; # report: romp-ibm BSD 4.3
+ GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to
+ ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
- echo rs6000-bull-bosx
- exit ;;
+ GUESS=rs6000-bull-bosx
+ ;;
DPX/2?00:B.O.S.:*:*)
- echo m68k-bull-sysv3
- exit ;;
+ GUESS=m68k-bull-sysv3
+ ;;
9000/[34]??:4.3bsd:1.*:*)
- echo m68k-hp-bsd
- exit ;;
+ GUESS=m68k-hp-bsd
+ ;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
- echo m68k-hp-bsd4.4
- exit ;;
+ GUESS=m68k-hp-bsd4.4
+ ;;
9000/[34678]??:HP-UX:*:*)
- HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//')
- case "$UNAME_MACHINE" in
+ HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
+ case $UNAME_MACHINE in
9000/31?) HP_ARCH=m68000 ;;
9000/[34]??) HP_ARCH=m68k ;;
9000/[678][0-9][0-9])
if test -x /usr/bin/getconf; then
- sc_cpu_version=$(/usr/bin/getconf SC_CPU_VERSION 2>/dev/null)
- sc_kernel_bits=$(/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null)
- case "$sc_cpu_version" in
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case $sc_cpu_version in
523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
- case "$sc_kernel_bits" in
+ case $sc_kernel_bits in
32) HP_ARCH=hppa2.0n ;;
64) HP_ARCH=hppa2.0w ;;
'') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
@@ -715,7 +743,7 @@ EOF
exit (0);
}
EOF
- (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=$("$dummy")
+ (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
@@ -740,12 +768,12 @@ EOF
HP_ARCH=hppa64
fi
fi
- echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
- exit ;;
+ GUESS=$HP_ARCH-hp-hpux$HPUX_REV
+ ;;
ia64:HP-UX:*:*)
- HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//')
- echo ia64-hp-hpux"$HPUX_REV"
- exit ;;
+ HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
+ GUESS=ia64-hp-hpux$HPUX_REV
+ ;;
3050*:HI-UX:*:*)
set_cc_for_build
sed 's/^ //' << EOF > "$dummy.c"
@@ -773,38 +801,38 @@ EOF
exit (0);
}
EOF
- $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") &&
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
{ echo "$SYSTEM_NAME"; exit; }
- echo unknown-hitachi-hiuxwe2
- exit ;;
+ GUESS=unknown-hitachi-hiuxwe2
+ ;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
- echo hppa1.1-hp-bsd
- exit ;;
+ GUESS=hppa1.1-hp-bsd
+ ;;
9000/8??:4.3bsd:*:*)
- echo hppa1.0-hp-bsd
- exit ;;
+ GUESS=hppa1.0-hp-bsd
+ ;;
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
- echo hppa1.0-hp-mpeix
- exit ;;
+ GUESS=hppa1.0-hp-mpeix
+ ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
- echo hppa1.1-hp-osf
- exit ;;
+ GUESS=hppa1.1-hp-osf
+ ;;
hp8??:OSF1:*:*)
- echo hppa1.0-hp-osf
- exit ;;
+ GUESS=hppa1.0-hp-osf
+ ;;
i*86:OSF1:*:*)
if test -x /usr/sbin/sysversion ; then
- echo "$UNAME_MACHINE"-unknown-osf1mk
+ GUESS=$UNAME_MACHINE-unknown-osf1mk
else
- echo "$UNAME_MACHINE"-unknown-osf1
+ GUESS=$UNAME_MACHINE-unknown-osf1
fi
- exit ;;
+ ;;
parisc*:Lites*:*:*)
- echo hppa1.1-hp-lites
- exit ;;
+ GUESS=hppa1.1-hp-lites
+ ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
- echo c1-convex-bsd
- exit ;;
+ GUESS=c1-convex-bsd
+ ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
@@ -812,17 +840,18 @@ EOF
fi
exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
- echo c34-convex-bsd
- exit ;;
+ GUESS=c34-convex-bsd
+ ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
- echo c38-convex-bsd
- exit ;;
+ GUESS=c38-convex-bsd
+ ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
- echo c4-convex-bsd
- exit ;;
+ GUESS=c4-convex-bsd
+ ;;
CRAY*Y-MP:*:*:*)
- echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=ymp-cray-unicos$CRAY_REL
+ ;;
CRAY*[A-Z]90:*:*:*)
echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
@@ -830,114 +859,155 @@ EOF
-e 's/\.[^.]*$/.X/'
exit ;;
CRAY*TS:*:*:*)
- echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=t90-cray-unicos$CRAY_REL
+ ;;
CRAY*T3E:*:*:*)
- echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=alphaev5-cray-unicosmk$CRAY_REL
+ ;;
CRAY*SV1:*:*:*)
- echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=sv1-cray-unicos$CRAY_REL
+ ;;
*:UNICOS/mp:*:*)
- echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
- exit ;;
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=craynv-cray-unicosmp$CRAY_REL
+ ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
- FUJITSU_PROC=$(uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)
- FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///')
- FUJITSU_REL=$(echo "$UNAME_RELEASE" | sed -e 's/ /_/')
- echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
+ FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
+ GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
+ ;;
5000:UNIX_System_V:4.*:*)
- FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///')
- FUJITSU_REL=$(echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/')
- echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+ GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
+ ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
- echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE"
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE
+ ;;
sparc*:BSD/OS:*:*)
- echo sparc-unknown-bsdi"$UNAME_RELEASE"
- exit ;;
+ GUESS=sparc-unknown-bsdi$UNAME_RELEASE
+ ;;
*:BSD/OS:*:*)
- echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE
+ ;;
arm:FreeBSD:*:*)
- UNAME_PROCESSOR=$(uname -p)
+ UNAME_PROCESSOR=`uname -p`
set_cc_for_build
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
- echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabi
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi
else
- echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabihf
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf
fi
- exit ;;
+ ;;
*:FreeBSD:*:*)
- UNAME_PROCESSOR=$(/usr/bin/uname -p)
- case "$UNAME_PROCESSOR" in
+ UNAME_PROCESSOR=`uname -p`
+ case $UNAME_PROCESSOR in
amd64)
UNAME_PROCESSOR=x86_64 ;;
i386)
UNAME_PROCESSOR=i586 ;;
esac
- echo "$UNAME_PROCESSOR"-unknown-freebsd"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')"
- exit ;;
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL
+ ;;
i*:CYGWIN*:*)
- echo "$UNAME_MACHINE"-pc-cygwin
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-cygwin
+ ;;
*:MINGW64*:*)
- echo "$UNAME_MACHINE"-pc-mingw64
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-mingw64
+ ;;
*:MINGW*:*)
- echo "$UNAME_MACHINE"-pc-mingw32
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-mingw32
+ ;;
*:MSYS*:*)
- echo "$UNAME_MACHINE"-pc-msys
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-msys
+ ;;
i*:PW*:*)
- echo "$UNAME_MACHINE"-pc-pw32
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-pw32
+ ;;
+ *:SerenityOS:*:*)
+ GUESS=$UNAME_MACHINE-pc-serenity
+ ;;
*:Interix*:*)
- case "$UNAME_MACHINE" in
+ case $UNAME_MACHINE in
x86)
- echo i586-pc-interix"$UNAME_RELEASE"
- exit ;;
+ GUESS=i586-pc-interix$UNAME_RELEASE
+ ;;
authenticamd | genuineintel | EM64T)
- echo x86_64-unknown-interix"$UNAME_RELEASE"
- exit ;;
+ GUESS=x86_64-unknown-interix$UNAME_RELEASE
+ ;;
IA64)
- echo ia64-unknown-interix"$UNAME_RELEASE"
- exit ;;
+ GUESS=ia64-unknown-interix$UNAME_RELEASE
+ ;;
esac ;;
i*:UWIN*:*)
- echo "$UNAME_MACHINE"-pc-uwin
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-uwin
+ ;;
amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
- echo x86_64-pc-cygwin
- exit ;;
+ GUESS=x86_64-pc-cygwin
+ ;;
prep*:SunOS:5.*:*)
- echo powerpcle-unknown-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
- exit ;;
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=powerpcle-unknown-solaris2$SUN_REL
+ ;;
*:GNU:*:*)
# the GNU system
- echo "$(echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,')-unknown-$LIBC$(echo "$UNAME_RELEASE"|sed -e 's,/.*$,,')"
- exit ;;
+ GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'`
+ GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'`
+ GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL
+ ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
- echo "$UNAME_MACHINE-unknown-$(echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]")$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')-$LIBC"
- exit ;;
+ GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"`
+ GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC
+ ;;
+ x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*)
+ GUESS="$UNAME_MACHINE-pc-managarm-mlibc"
+ ;;
+ *:[Mm]anagarm:*:*)
+ GUESS="$UNAME_MACHINE-unknown-managarm-mlibc"
+ ;;
*:Minix:*:*)
- echo "$UNAME_MACHINE"-unknown-minix
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-minix
+ ;;
aarch64:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ set_cc_for_build
+ CPU=$UNAME_MACHINE
+ LIBCABI=$LIBC
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ ABI=64
+ sed 's/^ //' << EOF > "$dummy.c"
+ #ifdef __ARM_EABI__
+ #ifdef __ARM_PCS_VFP
+ ABI=eabihf
+ #else
+ ABI=eabi
+ #endif
+ #endif
+EOF
+ cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
+ eval "$cc_set_abi"
+ case $ABI in
+ eabi | eabihf) CPU=armv8l; LIBCABI=$LIBC$ABI ;;
+ esac
+ fi
+ GUESS=$CPU-unknown-linux-$LIBCABI
+ ;;
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
alpha:Linux:*:*)
- case $(sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null) in
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
EV5) UNAME_MACHINE=alphaev5 ;;
EV56) UNAME_MACHINE=alphaev56 ;;
PCA56) UNAME_MACHINE=alphapca56 ;;
@@ -948,60 +1018,72 @@ EOF
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- arc:Linux:*:* | arceb:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
arm*:Linux:*:*)
set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi
+ GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi
else
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf
+ GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf
fi
fi
- exit ;;
+ ;;
avr32*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
cris:Linux:*:*)
- echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-axis-linux-$LIBC
+ ;;
crisv32:Linux:*:*)
- echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-axis-linux-$LIBC
+ ;;
e2k:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
frv:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
hexagon:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
i*86:Linux:*:*)
- echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-linux-$LIBC
+ ;;
ia64:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
k1om:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ kvx:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ kvx:cos:*:*)
+ GUESS=$UNAME_MACHINE-unknown-cos
+ ;;
+ kvx:mbr:*:*)
+ GUESS=$UNAME_MACHINE-unknown-mbr
+ ;;
+ loongarch32:Linux:*:* | loongarch64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
m32r*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
m68*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
mips:Linux:*:* | mips64:Linux:*:*)
set_cc_for_build
IS_GLIBC=0
@@ -1046,138 +1128,150 @@ EOF
#endif
#endif
EOF
- eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI')"
+ cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`
+ eval "$cc_set_vars"
test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
;;
mips64el:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
openrisc*:Linux:*:*)
- echo or1k-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=or1k-unknown-linux-$LIBC
+ ;;
or32:Linux:*:* | or1k*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
padre:Linux:*:*)
- echo sparc-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=sparc-unknown-linux-$LIBC
+ ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=hppa64-unknown-linux-$LIBC
+ ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
- case $(grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2) in
- PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;;
- PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
- *) echo hppa-unknown-linux-"$LIBC" ;;
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;;
+ PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;;
+ *) GUESS=hppa-unknown-linux-$LIBC ;;
esac
- exit ;;
+ ;;
ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=powerpc64-unknown-linux-$LIBC
+ ;;
ppc:Linux:*:*)
- echo powerpc-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=powerpc-unknown-linux-$LIBC
+ ;;
ppc64le:Linux:*:*)
- echo powerpc64le-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=powerpc64le-unknown-linux-$LIBC
+ ;;
ppcle:Linux:*:*)
- echo powerpcle-unknown-linux-"$LIBC"
- exit ;;
- riscv32:Linux:*:* | riscv64:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=powerpcle-unknown-linux-$LIBC
+ ;;
+ riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
s390:Linux:*:* | s390x:Linux:*:*)
- echo "$UNAME_MACHINE"-ibm-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-ibm-linux-$LIBC
+ ;;
sh64*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
sh*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
tile*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
vax:Linux:*:*)
- echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-dec-linux-$LIBC
+ ;;
x86_64:Linux:*:*)
set_cc_for_build
+ CPU=$UNAME_MACHINE
LIBCABI=$LIBC
if test "$CC_FOR_BUILD" != no_compiler_found; then
- if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_X32 >/dev/null
- then
- LIBCABI="$LIBC"x32
- fi
+ ABI=64
+ sed 's/^ //' << EOF > "$dummy.c"
+ #ifdef __i386__
+ ABI=x86
+ #else
+ #ifdef __ILP32__
+ ABI=x32
+ #endif
+ #endif
+EOF
+ cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
+ eval "$cc_set_abi"
+ case $ABI in
+ x86) CPU=i686 ;;
+ x32) LIBCABI=${LIBC}x32 ;;
+ esac
fi
- echo "$UNAME_MACHINE"-pc-linux-"$LIBCABI"
- exit ;;
+ GUESS=$CPU-pc-linux-$LIBCABI
+ ;;
xtensa*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
# earlier versions are messed up and put the nodename in both
# sysname and nodename.
- echo i386-sequent-sysv4
- exit ;;
+ GUESS=i386-sequent-sysv4
+ ;;
i*86:UNIX_SV:4.2MP:2.*)
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
- echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION"
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
+ ;;
i*86:OS/2:*:*)
- # If we were able to find `uname', then EMX Unix compatibility
+ # If we were able to find 'uname', then EMX Unix compatibility
# is probably installed.
- echo "$UNAME_MACHINE"-pc-os2-emx
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-os2-emx
+ ;;
i*86:XTS-300:*:STOP)
- echo "$UNAME_MACHINE"-unknown-stop
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-stop
+ ;;
i*86:atheos:*:*)
- echo "$UNAME_MACHINE"-unknown-atheos
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-atheos
+ ;;
i*86:syllable:*:*)
- echo "$UNAME_MACHINE"-pc-syllable
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-syllable
+ ;;
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
- echo i386-unknown-lynxos"$UNAME_RELEASE"
- exit ;;
+ GUESS=i386-unknown-lynxos$UNAME_RELEASE
+ ;;
i*86:*DOS:*:*)
- echo "$UNAME_MACHINE"-pc-msdosdjgpp
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-msdosdjgpp
+ ;;
i*86:*:4.*:*)
- UNAME_REL=$(echo "$UNAME_RELEASE" | sed 's/\/MP$//')
+ UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
- echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
+ GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL
else
- echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL"
+ GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL
fi
- exit ;;
+ ;;
i*86:*:5:[678]*)
# UnixWare 7.x, OpenUNIX and OpenServer 6.
- case $(/bin/uname -X | grep "^Machine") in
+ case `/bin/uname -X | grep "^Machine"` in
*486*) UNAME_MACHINE=i486 ;;
*Pentium) UNAME_MACHINE=i586 ;;
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;
esac
- echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ ;;
i*86:*:3.2:*)
if test -f /usr/options/cb.name; then
- UNAME_REL=$(sed -n 's/.*Version //p' </usr/options/cb.name)
- echo "$UNAME_MACHINE"-pc-isc"$UNAME_REL"
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ GUESS=$UNAME_MACHINE-pc-isc$UNAME_REL
elif /bin/uname -X 2>/dev/null >/dev/null ; then
- UNAME_REL=$( (/bin/uname -X|grep Release|sed -e 's/.*= //'))
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
&& UNAME_MACHINE=i586
@@ -1185,11 +1279,11 @@ EOF
&& UNAME_MACHINE=i686
(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
&& UNAME_MACHINE=i686
- echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL"
+ GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL
else
- echo "$UNAME_MACHINE"-pc-sysv32
+ GUESS=$UNAME_MACHINE-pc-sysv32
fi
- exit ;;
+ ;;
pc:*:*:*)
# Left here for compatibility:
# uname -m prints for DJGPP always 'pc', but it prints nothing about
@@ -1197,37 +1291,37 @@ EOF
# Note: whatever this is, it MUST be the same as what config.sub
# prints for the "djgpp" host, or else GDB configure will decide that
# this is a cross-build.
- echo i586-pc-msdosdjgpp
- exit ;;
+ GUESS=i586-pc-msdosdjgpp
+ ;;
Intel:Mach:3*:*)
- echo i386-pc-mach3
- exit ;;
+ GUESS=i386-pc-mach3
+ ;;
paragon:*:*:*)
- echo i860-intel-osf1
- exit ;;
+ GUESS=i860-intel-osf1
+ ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
- echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4
+ GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
- echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4
+ GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4
fi
- exit ;;
+ ;;
mini*:CTIX:SYS*5:*)
# "miniframe"
- echo m68010-convergent-sysv
- exit ;;
+ GUESS=m68010-convergent-sysv
+ ;;
mc68k:UNIX:SYSTEM5:3.51m)
- echo m68k-convergent-sysv
- exit ;;
+ GUESS=m68k-convergent-sysv
+ ;;
M680?0:D-NIX:5.3:*)
- echo m68k-diab-dnix
- exit ;;
+ GUESS=m68k-diab-dnix
+ ;;
M68*:*:R3V[5678]*:*)
test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
OS_REL=''
test -r /etc/.relid \
- && OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid)
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
@@ -1238,7 +1332,7 @@ EOF
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
OS_REL='.3'
test -r /etc/.relid \
- && OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid)
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
@@ -1246,118 +1340,121 @@ EOF
/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
&& { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
- echo m68k-unknown-lynxos"$UNAME_RELEASE"
- exit ;;
+ GUESS=m68k-unknown-lynxos$UNAME_RELEASE
+ ;;
mc68030:UNIX_System_V:4.*:*)
- echo m68k-atari-sysv4
- exit ;;
+ GUESS=m68k-atari-sysv4
+ ;;
TSUNAMI:LynxOS:2.*:*)
- echo sparc-unknown-lynxos"$UNAME_RELEASE"
- exit ;;
+ GUESS=sparc-unknown-lynxos$UNAME_RELEASE
+ ;;
rs6000:LynxOS:2.*:*)
- echo rs6000-unknown-lynxos"$UNAME_RELEASE"
- exit ;;
+ GUESS=rs6000-unknown-lynxos$UNAME_RELEASE
+ ;;
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
- echo powerpc-unknown-lynxos"$UNAME_RELEASE"
- exit ;;
+ GUESS=powerpc-unknown-lynxos$UNAME_RELEASE
+ ;;
SM[BE]S:UNIX_SV:*:*)
- echo mips-dde-sysv"$UNAME_RELEASE"
- exit ;;
+ GUESS=mips-dde-sysv$UNAME_RELEASE
+ ;;
RM*:ReliantUNIX-*:*:*)
- echo mips-sni-sysv4
- exit ;;
+ GUESS=mips-sni-sysv4
+ ;;
RM*:SINIX-*:*:*)
- echo mips-sni-sysv4
- exit ;;
+ GUESS=mips-sni-sysv4
+ ;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
- UNAME_MACHINE=$( (uname -p) 2>/dev/null)
- echo "$UNAME_MACHINE"-sni-sysv4
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ GUESS=$UNAME_MACHINE-sni-sysv4
else
- echo ns32k-sni-sysv
+ GUESS=ns32k-sni-sysv
fi
- exit ;;
- PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ ;;
+ PENTIUM:*:4.0*:*) # Unisys 'ClearPath HMP IX 4000' SVR4/MP effort
# says <Richard.M.Bartel@ccMail.Census.GOV>
- echo i586-unisys-sysv4
- exit ;;
+ GUESS=i586-unisys-sysv4
+ ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes <hewes@openmarket.com>.
# How about differentiating between stratus architectures? -djm
- echo hppa1.1-stratus-sysv4
- exit ;;
+ GUESS=hppa1.1-stratus-sysv4
+ ;;
*:*:*:FTX*)
# From seanf@swdc.stratus.com.
- echo i860-stratus-sysv4
- exit ;;
+ GUESS=i860-stratus-sysv4
+ ;;
i*86:VOS:*:*)
# From Paul.Green@stratus.com.
- echo "$UNAME_MACHINE"-stratus-vos
- exit ;;
+ GUESS=$UNAME_MACHINE-stratus-vos
+ ;;
*:VOS:*:*)
# From Paul.Green@stratus.com.
- echo hppa1.1-stratus-vos
- exit ;;
+ GUESS=hppa1.1-stratus-vos
+ ;;
mc68*:A/UX:*:*)
- echo m68k-apple-aux"$UNAME_RELEASE"
- exit ;;
+ GUESS=m68k-apple-aux$UNAME_RELEASE
+ ;;
news*:NEWS-OS:6*:*)
- echo mips-sony-newsos6
- exit ;;
+ GUESS=mips-sony-newsos6
+ ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if test -d /usr/nec; then
- echo mips-nec-sysv"$UNAME_RELEASE"
+ GUESS=mips-nec-sysv$UNAME_RELEASE
else
- echo mips-unknown-sysv"$UNAME_RELEASE"
+ GUESS=mips-unknown-sysv$UNAME_RELEASE
fi
- exit ;;
+ ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
- echo powerpc-be-beos
- exit ;;
+ GUESS=powerpc-be-beos
+ ;;
BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
- echo powerpc-apple-beos
- exit ;;
+ GUESS=powerpc-apple-beos
+ ;;
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
- echo i586-pc-beos
- exit ;;
+ GUESS=i586-pc-beos
+ ;;
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
- echo i586-pc-haiku
- exit ;;
- x86_64:Haiku:*:*)
- echo x86_64-unknown-haiku
- exit ;;
+ GUESS=i586-pc-haiku
+ ;;
+ ppc:Haiku:*:*) # Haiku running on Apple PowerPC
+ GUESS=powerpc-apple-haiku
+ ;;
+ *:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat)
+ GUESS=$UNAME_MACHINE-unknown-haiku
+ ;;
SX-4:SUPER-UX:*:*)
- echo sx4-nec-superux"$UNAME_RELEASE"
- exit ;;
+ GUESS=sx4-nec-superux$UNAME_RELEASE
+ ;;
SX-5:SUPER-UX:*:*)
- echo sx5-nec-superux"$UNAME_RELEASE"
- exit ;;
+ GUESS=sx5-nec-superux$UNAME_RELEASE
+ ;;
SX-6:SUPER-UX:*:*)
- echo sx6-nec-superux"$UNAME_RELEASE"
- exit ;;
+ GUESS=sx6-nec-superux$UNAME_RELEASE
+ ;;
SX-7:SUPER-UX:*:*)
- echo sx7-nec-superux"$UNAME_RELEASE"
- exit ;;
+ GUESS=sx7-nec-superux$UNAME_RELEASE
+ ;;
SX-8:SUPER-UX:*:*)
- echo sx8-nec-superux"$UNAME_RELEASE"
- exit ;;
+ GUESS=sx8-nec-superux$UNAME_RELEASE
+ ;;
SX-8R:SUPER-UX:*:*)
- echo sx8r-nec-superux"$UNAME_RELEASE"
- exit ;;
+ GUESS=sx8r-nec-superux$UNAME_RELEASE
+ ;;
SX-ACE:SUPER-UX:*:*)
- echo sxace-nec-superux"$UNAME_RELEASE"
- exit ;;
+ GUESS=sxace-nec-superux$UNAME_RELEASE
+ ;;
Power*:Rhapsody:*:*)
- echo powerpc-apple-rhapsody"$UNAME_RELEASE"
- exit ;;
+ GUESS=powerpc-apple-rhapsody$UNAME_RELEASE
+ ;;
*:Rhapsody:*:*)
- echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
- exit ;;
+ GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE
+ ;;
arm64:Darwin:*:*)
- echo aarch64-apple-darwin"$UNAME_RELEASE"
- exit ;;
+ GUESS=aarch64-apple-darwin$UNAME_RELEASE
+ ;;
*:Darwin:*:*)
- UNAME_PROCESSOR=$(uname -p)
+ UNAME_PROCESSOR=`uname -p`
case $UNAME_PROCESSOR in
unknown) UNAME_PROCESSOR=powerpc ;;
esac
@@ -1391,109 +1488,119 @@ EOF
# uname -m returns i386 or x86_64
UNAME_PROCESSOR=$UNAME_MACHINE
fi
- echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
- exit ;;
+ GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE
+ ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
- UNAME_PROCESSOR=$(uname -p)
+ UNAME_PROCESSOR=`uname -p`
if test "$UNAME_PROCESSOR" = x86; then
UNAME_PROCESSOR=i386
UNAME_MACHINE=pc
fi
- echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE"
- exit ;;
+ GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE
+ ;;
*:QNX:*:4*)
- echo i386-pc-qnx
- exit ;;
+ GUESS=i386-pc-qnx
+ ;;
NEO-*:NONSTOP_KERNEL:*:*)
- echo neo-tandem-nsk"$UNAME_RELEASE"
- exit ;;
+ GUESS=neo-tandem-nsk$UNAME_RELEASE
+ ;;
NSE-*:NONSTOP_KERNEL:*:*)
- echo nse-tandem-nsk"$UNAME_RELEASE"
- exit ;;
+ GUESS=nse-tandem-nsk$UNAME_RELEASE
+ ;;
NSR-*:NONSTOP_KERNEL:*:*)
- echo nsr-tandem-nsk"$UNAME_RELEASE"
- exit ;;
+ GUESS=nsr-tandem-nsk$UNAME_RELEASE
+ ;;
NSV-*:NONSTOP_KERNEL:*:*)
- echo nsv-tandem-nsk"$UNAME_RELEASE"
- exit ;;
+ GUESS=nsv-tandem-nsk$UNAME_RELEASE
+ ;;
NSX-*:NONSTOP_KERNEL:*:*)
- echo nsx-tandem-nsk"$UNAME_RELEASE"
- exit ;;
+ GUESS=nsx-tandem-nsk$UNAME_RELEASE
+ ;;
*:NonStop-UX:*:*)
- echo mips-compaq-nonstopux
- exit ;;
+ GUESS=mips-compaq-nonstopux
+ ;;
BS2000:POSIX*:*:*)
- echo bs2000-siemens-sysv
- exit ;;
+ GUESS=bs2000-siemens-sysv
+ ;;
DS/*:UNIX_System_V:*:*)
- echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE"
- exit ;;
+ GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE
+ ;;
*:Plan9:*:*)
# "uname -m" is not consistent, so use $cputype instead. 386
# is converted to i386 for consistency with other x86
# operating systems.
- # shellcheck disable=SC2154
- if test "$cputype" = 386; then
+ if test "${cputype-}" = 386; then
UNAME_MACHINE=i386
- else
- UNAME_MACHINE="$cputype"
+ elif test "x${cputype-}" != x; then
+ UNAME_MACHINE=$cputype
fi
- echo "$UNAME_MACHINE"-unknown-plan9
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-plan9
+ ;;
*:TOPS-10:*:*)
- echo pdp10-unknown-tops10
- exit ;;
+ GUESS=pdp10-unknown-tops10
+ ;;
*:TENEX:*:*)
- echo pdp10-unknown-tenex
- exit ;;
+ GUESS=pdp10-unknown-tenex
+ ;;
KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
- echo pdp10-dec-tops20
- exit ;;
+ GUESS=pdp10-dec-tops20
+ ;;
XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
- echo pdp10-xkl-tops20
- exit ;;
+ GUESS=pdp10-xkl-tops20
+ ;;
*:TOPS-20:*:*)
- echo pdp10-unknown-tops20
- exit ;;
+ GUESS=pdp10-unknown-tops20
+ ;;
*:ITS:*:*)
- echo pdp10-unknown-its
- exit ;;
+ GUESS=pdp10-unknown-its
+ ;;
SEI:*:*:SEIUX)
- echo mips-sei-seiux"$UNAME_RELEASE"
- exit ;;
+ GUESS=mips-sei-seiux$UNAME_RELEASE
+ ;;
*:DragonFly:*:*)
- echo "$UNAME_MACHINE"-unknown-dragonfly"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')"
- exit ;;
+ DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL
+ ;;
*:*VMS:*:*)
- UNAME_MACHINE=$( (uname -p) 2>/dev/null)
- case "$UNAME_MACHINE" in
- A*) echo alpha-dec-vms ; exit ;;
- I*) echo ia64-dec-vms ; exit ;;
- V*) echo vax-dec-vms ; exit ;;
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case $UNAME_MACHINE in
+ A*) GUESS=alpha-dec-vms ;;
+ I*) GUESS=ia64-dec-vms ;;
+ V*) GUESS=vax-dec-vms ;;
esac ;;
*:XENIX:*:SysV)
- echo i386-pc-xenix
- exit ;;
+ GUESS=i386-pc-xenix
+ ;;
i*86:skyos:*:*)
- echo "$UNAME_MACHINE"-pc-skyos"$(echo "$UNAME_RELEASE" | sed -e 's/ .*$//')"
- exit ;;
+ SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`
+ GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL
+ ;;
i*86:rdos:*:*)
- echo "$UNAME_MACHINE"-pc-rdos
- exit ;;
- i*86:AROS:*:*)
- echo "$UNAME_MACHINE"-pc-aros
- exit ;;
+ GUESS=$UNAME_MACHINE-pc-rdos
+ ;;
+ i*86:Fiwix:*:*)
+ GUESS=$UNAME_MACHINE-pc-fiwix
+ ;;
+ *:AROS:*:*)
+ GUESS=$UNAME_MACHINE-unknown-aros
+ ;;
x86_64:VMkernel:*:*)
- echo "$UNAME_MACHINE"-unknown-esx
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-esx
+ ;;
amd64:Isilon\ OneFS:*:*)
- echo x86_64-unknown-onefs
- exit ;;
+ GUESS=x86_64-unknown-onefs
+ ;;
*:Unleashed:*:*)
- echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE"
- exit ;;
+ GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
+ ;;
esac
+# Do we have a guess based on uname results?
+if test "x$GUESS" != x; then
+ echo "$GUESS"
+ exit
+fi
+
# No uname command or uname output not recognized.
set_cc_for_build
cat > "$dummy.c" <<EOF
@@ -1533,7 +1640,7 @@ main ()
#define __ARCHITECTURE__ "m68k"
#endif
int version;
- version=$( (hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null);
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
if (version < 4)
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
else
@@ -1625,7 +1732,7 @@ main ()
}
EOF
-$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=$($dummy) &&
+$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` &&
{ echo "$SYSTEM_NAME"; exit; }
# Apollos put the system type in the environment.
@@ -1633,7 +1740,7 @@ test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
echo "$0: unable to guess system type" >&2
-case "$UNAME_MACHINE:$UNAME_SYSTEM" in
+case $UNAME_MACHINE:$UNAME_SYSTEM in
mips:Linux | mips64:Linux)
# If we got here on MIPS GNU/Linux, output extra information.
cat >&2 <<EOF
@@ -1655,9 +1762,11 @@ and
https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
EOF
-year=$(echo $timestamp | sed 's,-.*,,')
+our_year=`echo $timestamp | sed 's,-.*,,'`
+thisyear=`date +%Y`
# shellcheck disable=SC2003
-if test "$(expr "$(date +%Y)" - "$year")" -lt 3 ; then
+script_age=`expr "$thisyear" - "$our_year"`
+if test "$script_age" -lt 3 ; then
cat >&2 <<EOF
If $0 has already been updated, send the following data and any
@@ -1666,20 +1775,20 @@ provide the necessary information to handle your system.
config.guess timestamp = $timestamp
-uname -m = $( (uname -m) 2>/dev/null || echo unknown)
-uname -r = $( (uname -r) 2>/dev/null || echo unknown)
-uname -s = $( (uname -s) 2>/dev/null || echo unknown)
-uname -v = $( (uname -v) 2>/dev/null || echo unknown)
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
-/usr/bin/uname -p = $( (/usr/bin/uname -p) 2>/dev/null)
-/bin/uname -X = $( (/bin/uname -X) 2>/dev/null)
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
-hostinfo = $( (hostinfo) 2>/dev/null)
-/bin/universe = $( (/bin/universe) 2>/dev/null)
-/usr/bin/arch -k = $( (/usr/bin/arch -k) 2>/dev/null)
-/bin/arch = $( (/bin/arch) 2>/dev/null)
-/usr/bin/oslevel = $( (/usr/bin/oslevel) 2>/dev/null)
-/usr/convex/getsysinfo = $( (/usr/convex/getsysinfo) 2>/dev/null)
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
UNAME_MACHINE = "$UNAME_MACHINE"
UNAME_RELEASE = "$UNAME_RELEASE"
diff --git a/scripts/config.sub b/scripts/config.sub
index 19c9553..defe52c 100644..100755
--- a/scripts/config.sub
+++ b/scripts/config.sub
@@ -1,12 +1,14 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2020 Free Software Foundation, Inc.
+# Copyright 1992-2023 Free Software Foundation, Inc.
-timestamp='2020-12-02'
+# shellcheck disable=SC2006,SC2268 # see below for rationale
+
+timestamp='2023-09-19'
# This file 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
+# 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
@@ -50,7 +52,14 @@ timestamp='2020-12-02'
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
-me=$(echo "$0" | sed -e 's,.*/,,')
+# The "shellcheck disable" line above the timestamp inhibits complaints
+# about features and limitations of the classic Bourne shell that were
+# superseded or lifted in POSIX. However, this script identifies a wide
+# variety of pre-POSIX systems that do not have POSIX shells at all, and
+# even some reasonably current systems (Solaris 10 as case-in-point) still
+# have a pre-POSIX /bin/sh.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
@@ -67,13 +76,13 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2020 Free Software Foundation, Inc.
+Copyright 1992-2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
-Try \`$me --help' for more information."
+Try '$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
@@ -112,14 +121,16 @@ esac
# Split fields of configuration type
# shellcheck disable=SC2162
+saved_IFS=$IFS
IFS="-" read field1 field2 field3 field4 <<EOF
$1
EOF
+IFS=$saved_IFS
# Separate into logical components for further validation
case $1 in
*-*-*-*-*)
- echo Invalid configuration \`"$1"\': more than four components >&2
+ echo "Invalid configuration '$1': more than four components" >&2
exit 1
;;
*-*-*-*)
@@ -134,7 +145,8 @@ case $1 in
nto-qnx* | linux-* | uclinux-uclibc* \
| uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
| netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
- | storm-chaos* | os2-emx* | rtmk-nova*)
+ | storm-chaos* | os2-emx* | rtmk-nova* | managarm-* \
+ | windows-* )
basic_machine=$field1
basic_os=$maybe_os
;;
@@ -163,6 +175,10 @@ case $1 in
basic_machine=$field1
basic_os=$field2
;;
+ zephyr*)
+ basic_machine=$field1-unknown
+ basic_os=$field2
+ ;;
# Manufacturers
dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
| att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
@@ -769,22 +785,22 @@ case $basic_machine in
vendor=hp
;;
i*86v32)
- cpu=$(echo "$1" | sed -e 's/86.*/86/')
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=sysv32
;;
i*86v4*)
- cpu=$(echo "$1" | sed -e 's/86.*/86/')
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=sysv4
;;
i*86v)
- cpu=$(echo "$1" | sed -e 's/86.*/86/')
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=sysv
;;
i*86sol2)
- cpu=$(echo "$1" | sed -e 's/86.*/86/')
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=solaris2
;;
@@ -917,16 +933,18 @@ case $basic_machine in
;;
leon-*|leon[3-9]-*)
cpu=sparc
- vendor=$(echo "$basic_machine" | sed 's/-.*//')
+ vendor=`echo "$basic_machine" | sed 's/-.*//'`
;;
*-*)
# shellcheck disable=SC2162
+ saved_IFS=$IFS
IFS="-" read cpu vendor <<EOF
$basic_machine
EOF
+ IFS=$saved_IFS
;;
- # We use `pc' rather than `unknown'
+ # We use 'pc' rather than 'unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
i*86 | x86_64)
@@ -1003,6 +1021,11 @@ case $cpu-$vendor in
;;
# Here we normalize CPU types with a missing or matching vendor
+ armh-unknown | armh-alt)
+ cpu=armv7l
+ vendor=alt
+ basic_os=${basic_os:-linux-gnueabihf}
+ ;;
dpx20-unknown | dpx20-bull)
cpu=rs6000
vendor=bull
@@ -1053,7 +1076,7 @@ case $cpu-$vendor in
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
cpu=i586
;;
- pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)
+ pentiumpro-* | p6-* | 6x86-* | athlon-* | athlon_*-*)
cpu=i686
;;
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
@@ -1084,7 +1107,7 @@ case $cpu-$vendor in
cpu=mipsisa64sb1el
;;
sh5e[lb]-*)
- cpu=$(echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/')
+ cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'`
;;
spur-*)
cpu=spur
@@ -1102,9 +1125,9 @@ case $cpu-$vendor in
cpu=x86_64
;;
xscale-* | xscalee[bl]-*)
- cpu=$(echo "$cpu" | sed 's/^xscale/arm/')
+ cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
;;
- arm64-*)
+ arm64-* | aarch64le-*)
cpu=aarch64
;;
@@ -1158,14 +1181,14 @@ case $cpu-$vendor in
case $cpu in
1750a | 580 \
| a29k \
- | aarch64 | aarch64_be \
+ | aarch64 | aarch64_be | aarch64c | arm64ec \
| abacus \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
| alphapca5[67] | alpha64pca5[67] \
| am33_2.0 \
| amdgcn \
- | arc | arceb \
+ | arc | arceb | arc32 | arc64 \
| arm | arm[lb]e | arme[lb] | armv* \
| avr | avr32 \
| asmjs \
@@ -1177,40 +1200,23 @@ case $cpu-$vendor in
| d10v | d30v | dlx | dsp16xx \
| e2k | elxsi | epiphany \
| f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
+ | javascript \
| h8300 | h8500 \
| hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
| i370 | i*86 | i860 | i960 | ia16 | ia64 \
| ip2k | iq2000 \
| k1om \
+ | kvx \
| le32 | le64 \
| lm32 \
+ | loongarch32 | loongarch64 \
| m32c | m32r | m32rle \
| m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
| m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
| m88110 | m88k | maxq | mb | mcore | mep | metag \
| microblaze | microblazeel \
- | mips | mipsbe | mipseb | mipsel | mipsle \
- | mips16 \
- | mips64 | mips64eb | mips64el \
- | mips64octeon | mips64octeonel \
- | mips64orion | mips64orionel \
- | mips64r5900 | mips64r5900el \
- | mips64vr | mips64vrel \
- | mips64vr4100 | mips64vr4100el \
- | mips64vr4300 | mips64vr4300el \
- | mips64vr5000 | mips64vr5000el \
- | mips64vr5900 | mips64vr5900el \
- | mipsisa32 | mipsisa32el \
- | mipsisa32r2 | mipsisa32r2el \
- | mipsisa32r6 | mipsisa32r6el \
- | mipsisa64 | mipsisa64el \
- | mipsisa64r2 | mipsisa64r2el \
- | mipsisa64r6 | mipsisa64r6el \
- | mipsisa64sb1 | mipsisa64sb1el \
- | mipsisa64sr71k | mipsisa64sr71kel \
- | mipsr5900 | mipsr5900el \
- | mipstx39 | mipstx39el \
+ | mips* \
| mmix \
| mn10200 | mn10300 \
| moxie \
@@ -1229,7 +1235,7 @@ case $cpu-$vendor in
| powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
| pru \
| pyramid \
- | riscv | riscv32 | riscv64 \
+ | riscv | riscv32 | riscv32be | riscv64 | riscv64be \
| rl78 | romp | rs6000 | rx \
| s390 | s390x \
| score \
@@ -1258,7 +1264,7 @@ case $cpu-$vendor in
;;
*)
- echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
+ echo "Invalid configuration '$1': machine '$cpu-$vendor' not recognized" 1>&2
exit 1
;;
esac
@@ -1279,38 +1285,45 @@ esac
# Decode manufacturer-specific aliases for certain operating systems.
-if test x$basic_os != x
+if test x"$basic_os" != x
then
-# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just
+# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just
# set os.
+obj=
case $basic_os in
gnu/linux*)
kernel=linux
- os=$(echo $basic_os | sed -e 's|gnu/linux|gnu|')
+ os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'`
;;
os2-emx)
kernel=os2
- os=$(echo $basic_os | sed -e 's|os2-emx|emx|')
+ os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'`
;;
nto-qnx*)
kernel=nto
- os=$(echo $basic_os | sed -e 's|nto-qnx|qnx|')
+ os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'`
;;
*-*)
# shellcheck disable=SC2162
+ saved_IFS=$IFS
IFS="-" read kernel os <<EOF
$basic_os
EOF
+ IFS=$saved_IFS
;;
# Default OS when just kernel was specified
nto*)
kernel=nto
- os=$(echo $basic_os | sed -e 's|nto|qnx|')
+ os=`echo "$basic_os" | sed -e 's|nto|qnx|'`
;;
linux*)
kernel=linux
- os=$(echo $basic_os | sed -e 's|linux|gnu|')
+ os=`echo "$basic_os" | sed -e 's|linux|gnu|'`
+ ;;
+ managarm*)
+ kernel=managarm
+ os=`echo "$basic_os" | sed -e 's|managarm|mlibc|'`
;;
*)
kernel=
@@ -1331,7 +1344,7 @@ case $os in
os=cnk
;;
solaris1 | solaris1.*)
- os=$(echo $os | sed -e 's|solaris1|sunos4|')
+ os=`echo "$os" | sed -e 's|solaris1|sunos4|'`
;;
solaris)
os=solaris2
@@ -1360,7 +1373,7 @@ case $os in
os=sco3.2v4
;;
sco3.2.[4-9]*)
- os=$(echo $os | sed -e 's/sco3.2./sco3.2v/')
+ os=`echo "$os" | sed -e 's/sco3.2./sco3.2v/'`
;;
sco*v* | scout)
# Don't match below
@@ -1390,7 +1403,7 @@ case $os in
os=lynxos
;;
mac[0-9]*)
- os=$(echo "$os" | sed -e 's|mac|macos|')
+ os=`echo "$os" | sed -e 's|mac|macos|'`
;;
opened*)
os=openedition
@@ -1399,10 +1412,10 @@ case $os in
os=os400
;;
sunos5*)
- os=$(echo "$os" | sed -e 's|sunos5|solaris2|')
+ os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
;;
sunos6*)
- os=$(echo "$os" | sed -e 's|sunos6|solaris3|')
+ os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
;;
wince*)
os=wince
@@ -1436,7 +1449,7 @@ case $os in
;;
# Preserve the version number of sinix5.
sinix5.*)
- os=$(echo $os | sed -e 's|sinix|sysv|')
+ os=`echo "$os" | sed -e 's|sinix|sysv|'`
;;
sinix*)
os=sysv4
@@ -1477,10 +1490,16 @@ case $os in
os=eabi
;;
*)
- os=elf
+ os=
+ obj=elf
;;
esac
;;
+ aout* | coff* | elf* | pe*)
+ # These are machine code file formats, not OSes
+ obj=$os
+ os=
+ ;;
*)
# No normalization, but not necessarily accepted, that comes below.
;;
@@ -1499,12 +1518,15 @@ else
# system, and we'll never get to this point.
kernel=
+obj=
case $cpu-$vendor in
score-*)
- os=elf
+ os=
+ obj=elf
;;
spu-*)
- os=elf
+ os=
+ obj=elf
;;
*-acorn)
os=riscix1.2
@@ -1514,28 +1536,35 @@ case $cpu-$vendor in
os=gnu
;;
arm*-semi)
- os=aout
+ os=
+ obj=aout
;;
c4x-* | tic4x-*)
- os=coff
+ os=
+ obj=coff
;;
c8051-*)
- os=elf
+ os=
+ obj=elf
;;
clipper-intergraph)
os=clix
;;
hexagon-*)
- os=elf
+ os=
+ obj=elf
;;
tic54x-*)
- os=coff
+ os=
+ obj=coff
;;
tic55x-*)
- os=coff
+ os=
+ obj=coff
;;
tic6x-*)
- os=coff
+ os=
+ obj=coff
;;
# This must come before the *-dec entry.
pdp10-*)
@@ -1557,19 +1586,24 @@ case $cpu-$vendor in
os=sunos3
;;
m68*-cisco)
- os=aout
+ os=
+ obj=aout
;;
mep-*)
- os=elf
+ os=
+ obj=elf
;;
mips*-cisco)
- os=elf
+ os=
+ obj=elf
;;
mips*-*)
- os=elf
+ os=
+ obj=elf
;;
or32-*)
- os=coff
+ os=
+ obj=coff
;;
*-tti) # must be before sparc entry or we get the wrong os.
os=sysv3
@@ -1578,7 +1612,8 @@ case $cpu-$vendor in
os=sunos4.1.1
;;
pru-*)
- os=elf
+ os=
+ obj=elf
;;
*-be)
os=beos
@@ -1659,10 +1694,12 @@ case $cpu-$vendor in
os=uxpv
;;
*-rom68k)
- os=coff
+ os=
+ obj=coff
;;
*-*bug)
- os=coff
+ os=
+ obj=coff
;;
*-apple)
os=macos
@@ -1680,13 +1717,20 @@ esac
fi
-# Now, validate our (potentially fixed-up) OS.
+# Now, validate our (potentially fixed-up) individual pieces (OS, OBJ).
+
case $os in
- # Sometimes we do "kernel-abi", so those need to count as OSes.
- musl* | newlib* | uclibc*)
+ # Sometimes we do "kernel-libc", so those need to count as OSes.
+ musl* | newlib* | relibc* | uclibc*)
+ ;;
+ # Likewise for "kernel-abi"
+ eabi* | gnueabi*)
+ ;;
+ # VxWorks passes extra cpu info in the 4th filed.
+ simlinux | simwindows | spe)
;;
- # Likewise for "kernel-libc"
- eabi | eabihf | gnueabi | gnueabihf)
+ # See `case $cpu-$os` validation below
+ ghcjs)
;;
# Now accept the basic system types.
# The portable systems comes first.
@@ -1696,20 +1740,20 @@ case $os in
| hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
| sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \
| hiux* | abug | nacl* | netware* | windows* \
- | os9* | macos* | osx* | ios* \
+ | os9* | macos* | osx* | ios* | tvos* | watchos* \
| mpw* | magic* | mmixware* | mon960* | lnews* \
| amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
| aos* | aros* | cloudabi* | sortix* | twizzler* \
| nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
| clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
| mirbsd* | netbsd* | dicos* | openedition* | ose* \
- | bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \
+ | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \
| ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
- | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
- | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
+ | bosx* | nextstep* | cxux* | oabi* \
+ | ptx* | ecoff* | winnt* | domain* | vsta* \
| udi* | lites* | ieee* | go32* | aux* | hcos* \
- | chorusrdb* | cegcc* | glidix* \
- | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
+ | chorusrdb* | cegcc* | glidix* | serenity* \
+ | cygwin* | msys* | moss* | proelf* | rtems* \
| midipix* | mingw32* | mingw64* | mint* \
| uxpv* | beos* | mpeix* | udk* | moxiebox* \
| interix* | uwin* | mks* | rhapsody* | darwin* \
@@ -1721,7 +1765,8 @@ case $os in
| skyos* | haiku* | rdos* | toppers* | drops* | es* \
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
- | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx*)
+ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
+ | fiwix* | mlibc* | cos* | mbr* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
@@ -1729,38 +1774,99 @@ case $os in
;;
none)
;;
+ kernel* | msvc* )
+ # Restricted further below
+ ;;
+ '')
+ if test x"$obj" = x
+ then
+ echo "Invalid configuration '$1': Blank OS only allowed with explicit machine code file format" 1>&2
+ fi
+ ;;
+ *)
+ echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2
+ exit 1
+ ;;
+esac
+
+case $obj in
+ aout* | coff* | elf* | pe*)
+ ;;
+ '')
+ # empty is fine
+ ;;
*)
- echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2
+ echo "Invalid configuration '$1': Machine code format '$obj' not recognized" 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we handle the constraint that a (synthetic) cpu and os are
+# valid only in combination with each other and nowhere else.
+case $cpu-$os in
+ # The "javascript-unknown-ghcjs" triple is used by GHC; we
+ # accept it here in order to tolerate that, but reject any
+ # variations.
+ javascript-ghcjs)
+ ;;
+ javascript-* | *-ghcjs)
+ echo "Invalid configuration '$1': cpu '$cpu' is not valid with os '$os$obj'" 1>&2
exit 1
;;
esac
# As a final step for OS-related things, validate the OS-kernel combination
# (given a valid OS), if there is a kernel.
-case $kernel-$os in
- linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* )
+case $kernel-$os-$obj in
+ linux-gnu*- | linux-dietlibc*- | linux-android*- | linux-newlib*- \
+ | linux-musl*- | linux-relibc*- | linux-uclibc*- | linux-mlibc*- )
+ ;;
+ uclinux-uclibc*- )
;;
- uclinux-uclibc* )
+ managarm-mlibc*- | managarm-kernel*- )
;;
- -dietlibc* | -newlib* | -musl* | -uclibc* )
+ windows*-msvc*-)
+ ;;
+ -dietlibc*- | -newlib*- | -musl*- | -relibc*- | -uclibc*- | -mlibc*- )
# These are just libc implementations, not actual OSes, and thus
# require a kernel.
- echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
+ echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2
exit 1
;;
- kfreebsd*-gnu* | kopensolaris*-gnu*)
+ -kernel*- )
+ echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2
+ exit 1
;;
- nto-qnx*)
+ *-kernel*- )
+ echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2
+ exit 1
;;
- os2-emx)
+ *-msvc*- )
+ echo "Invalid configuration '$1': '$os' needs 'windows'." 1>&2
+ exit 1
+ ;;
+ kfreebsd*-gnu*- | kopensolaris*-gnu*-)
+ ;;
+ vxworks-simlinux- | vxworks-simwindows- | vxworks-spe-)
+ ;;
+ nto-qnx*-)
+ ;;
+ os2-emx-)
;;
- *-eabi* | *-gnueabi*)
+ *-eabi*- | *-gnueabi*-)
;;
- -*)
+ none--*)
+ # None (no kernel, i.e. freestanding / bare metal),
+ # can be paired with an machine code file format
+ ;;
+ -*-)
# Blank kernel with real OS is always fine.
;;
- *-*)
- echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
+ --*)
+ # Blank kernel and OS with real machine code file format is always fine.
+ ;;
+ *-*-*)
+ echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2
exit 1
;;
esac
@@ -1843,7 +1949,7 @@ case $vendor in
;;
esac
-echo "$cpu-$vendor-${kernel:+$kernel-}$os"
+echo "$cpu-$vendor${kernel:+-$kernel}${os:+-$os}${obj:+-$obj}"
exit
# Local variables:
diff --git a/scripts/install-sh b/scripts/install-sh
new file mode 100755
index 0000000..7c56c9c
--- /dev/null
+++ b/scripts/install-sh
@@ -0,0 +1,541 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2023-11-23.18; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# 'make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+tab=' '
+nl='
+'
+IFS=" $tab$nl"
+
+# Set DOITPROG to "echo" to test this script.
+
+doit=${DOITPROG-}
+doit_exec=${doit:-exec}
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+# Create dirs (including intermediate dirs) using mode 755.
+# This is like GNU 'install' as of coreutils 8.32 (2020).
+mkdir_umask=22
+
+backupsuffix=
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+is_target_a_directory=possibly
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
+
+ -c (ignored)
+ -C install only if different (preserve data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -p pass -p to $cpprog.
+ -s $stripprog installed files.
+ -S SUFFIX attempt to back up existing files, with suffix SUFFIX.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
+
+By default, rm is invoked with -f; when overridden with RMPROG,
+it's up to you to specify -f if you want it.
+
+If -S is not specified, no backups are attempted.
+
+Report bugs to <bug-automake@gnu.org>.
+GNU Automake home page: <https://www.gnu.org/software/automake/>.
+General help using GNU software: <https://www.gnu.org/gethelp/>."
+
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
+
+ -C) copy_on_change=true;;
+
+ -d) dir_arg=true;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) mode=$2
+ case $mode in
+ *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -p) cpprog="$cpprog -p";;
+
+ -s) stripcmd=$stripprog;;
+
+ -S) backupsuffix="$2"
+ shift;;
+
+ -t)
+ is_target_a_directory=always
+ dst_arg=$2
+ # Protect names problematic for 'test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
+ shift;;
+
+ -T) is_target_a_directory=never;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+# We allow the use of options -d and -T together, by making -d
+# take the precedence; this is for compatibility with GNU install.
+
+if test -n "$dir_arg"; then
+ if test -n "$dst_arg"; then
+ echo "$0: target directory not allowed when installing a directory." >&2
+ exit 1
+ fi
+fi
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ # Protect names problematic for 'test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
+ done
+fi
+
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call 'install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+if test -z "$dir_arg"; then
+ if test $# -gt 1 || test "$is_target_a_directory" = always; then
+ if test ! -d "$dst_arg"; then
+ echo "$0: $dst_arg: Is not a directory." >&2
+ exit 1
+ fi
+ fi
+fi
+
+if test -z "$dir_arg"; then
+ do_exit='(exit $ret); exit $ret'
+ trap "ret=129; $do_exit" 1
+ trap "ret=130; $do_exit" 2
+ trap "ret=141; $do_exit" 13
+ trap "ret=143; $do_exit" 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
+
+for src
+do
+ # Protect names problematic for 'test' and other utilities.
+ case $src in
+ -* | [=\(\)!]) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ # Don't chown directories that already exist.
+ if test $dstdir_status = 0; then
+ chowncmd=""
+ fi
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+ dst=$dst_arg
+
+ # If destination is a directory, append the input filename.
+ if test -d "$dst"; then
+ if test "$is_target_a_directory" = never; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dstbase=`basename "$src"`
+ case $dst in
+ */) dst=$dst$dstbase;;
+ *) dst=$dst/$dstbase;;
+ esac
+ dstdir_status=0
+ else
+ dstdir=`dirname "$dst"`
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ case $dstdir in
+ */) dstdirslash=$dstdir;;
+ *) dstdirslash=$dstdir/;;
+ esac
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ # The $RANDOM variable is not portable (e.g., dash). Use it
+ # here however when possible just to lower collision chance.
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+
+ trap '
+ ret=$?
+ rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
+ exit $ret
+ ' 0
+
+ # Because "mkdir -p" follows existing symlinks and we likely work
+ # directly in world-writeable /tmp, make sure that the '$tmpdir'
+ # directory is successfully created first before we actually test
+ # 'mkdir -p'.
+ if (umask $mkdir_umask &&
+ $mkdirprog $mkdir_mode "$tmpdir" &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ test_tmpdir="$tmpdir/a"
+ ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
+ fi
+ trap '' 0;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ [-=\(\)!]*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ oIFS=$IFS
+ IFS=/
+ set -f
+ set fnord $dstdir
+ shift
+ set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test X"$d" = X && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=${dstdirslash}_inst.$$_
+ rmtmp=${dstdirslash}_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask &&
+ { test -z "$stripcmd" || {
+ # Create $dsttmp read-write so that cp doesn't create it read-only,
+ # which would cause strip to fail.
+ if test -z "$doit"; then
+ : >"$dsttmp" # No need to fork-exec 'touch'.
+ else
+ $doit touch "$dsttmp"
+ fi
+ }
+ } &&
+ $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+ set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ set +f &&
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # If $backupsuffix is set, and the file being installed
+ # already exists, attempt a backup. Don't worry if it fails,
+ # e.g., if mv doesn't support -f.
+ if test -n "$backupsuffix" && test -f "$dst"; then
+ $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
+ fi
+
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/scripts/install.sh b/scripts/install.sh
deleted file mode 100755
index 89fc9b0..0000000
--- a/scripts/install.sh
+++ /dev/null
@@ -1,238 +0,0 @@
-#! /bin/sh
-#
-# install - install a program, script, or datafile
-# This comes from X11R5.
-#
-# Calling this script install-sh is preferred over install.sh, to prevent
-# `make' implicit rules from creating a file called install from it
-# when there is no Makefile.
-#
-# This script is compatible with the BSD install script, but was written
-# from scratch.
-#
-
-
-# set DOITPROG to echo to test this script
-
-# Don't use :- since 4.3BSD and earlier shells don't like it.
-doit="${DOITPROG-}"
-
-
-# put in absolute paths if you don't have them in your path; or use env. vars.
-
-mvprog="${MVPROG-mv}"
-cpprog="${CPPROG-cp}"
-chmodprog="${CHMODPROG-chmod}"
-chownprog="${CHOWNPROG-chown}"
-chgrpprog="${CHGRPPROG-chgrp}"
-stripprog="${STRIPPROG-strip}"
-rmprog="${RMPROG-rm}"
-mkdirprog="${MKDIRPROG-mkdir}"
-
-tranformbasename=""
-transform_arg=""
-instcmd="$mvprog"
-chmodcmd="$chmodprog 0755"
-chowncmd=""
-chgrpcmd=""
-stripcmd=""
-rmcmd="$rmprog -f"
-mvcmd="$mvprog"
-src=""
-dst=""
-dir_arg=""
-
-while [ x"$1" != x ]; do
- case $1 in
- -c) instcmd="$cpprog"
- shift
- continue;;
-
- -d) dir_arg=true
- shift
- continue;;
-
- -m) chmodcmd="$chmodprog $2"
- shift
- shift
- continue;;
-
- -o) chowncmd="$chownprog $2"
- shift
- shift
- continue;;
-
- -g) chgrpcmd="$chgrpprog $2"
- shift
- shift
- continue;;
-
- -s) stripcmd="$stripprog"
- shift
- continue;;
-
- -t=*) transformarg=`echo $1 | sed 's/-t=//'`
- shift
- continue;;
-
- -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
- shift
- continue;;
-
- *) if [ x"$src" = x ]
- then
- src=$1
- else
- # this colon is to work around a 386BSD /bin/sh bug
- :
- dst=$1
- fi
- shift
- continue;;
- esac
-done
-
-if [ x"$src" = x ]
-then
- echo "install: no input file specified"
- exit 1
-else
- true
-fi
-
-if [ x"$dir_arg" != x ]; then
- dst=$src
- src=""
-
- if [ -d $dst ]; then
- instcmd=:
- else
- instcmd=mkdir
- fi
-else
-
-# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
-# might cause directories to be created, which would be especially bad
-# if $src (and thus $dsttmp) contains '*'.
-
- if [ -f $src -o -d $src ]
- then
- true
- else
- echo "install: $src does not exist"
- exit 1
- fi
-
- if [ x"$dst" = x ]
- then
- echo "install: no destination specified"
- exit 1
- else
- true
- fi
-
-# If destination is a directory, append the input filename; if your system
-# does not like double slashes in filenames, you may need to add some logic
-
- if [ -d $dst ]
- then
- dst="$dst"/`basename $src`
- else
- true
- fi
-fi
-
-## this sed command emulates the dirname command
-dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
-
-# Make sure that the destination directory exists.
-# this part is taken from Noah Friedman's mkinstalldirs script
-
-# Skip lots of stat calls in the usual case.
-if [ ! -d "$dstdir" ]; then
-defaultIFS='
-'
-IFS="${IFS-${defaultIFS}}"
-
-oIFS="${IFS}"
-# Some sh's can't handle IFS=/ for some reason.
-IFS='%'
-set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
-IFS="${oIFS}"
-
-pathcomp=''
-
-while [ $# -ne 0 ] ; do
- pathcomp="${pathcomp}${1}"
- shift
-
- if [ ! -d "${pathcomp}" ] ;
- then
- $mkdirprog "${pathcomp}"
- else
- true
- fi
-
- pathcomp="${pathcomp}/"
-done
-fi
-
-if [ x"$dir_arg" != x ]
-then
- $doit $instcmd $dst &&
-
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
-else
-
-# If we're going to rename the final executable, determine the name now.
-
- if [ x"$transformarg" = x ]
- then
- dstfile=`basename $dst`
- else
- dstfile=`basename $dst $transformbasename |
- sed $transformarg`$transformbasename
- fi
-
-# don't allow the sed command to completely eliminate the filename
-
- if [ x"$dstfile" = x ]
- then
- dstfile=`basename $dst`
- else
- true
- fi
-
-# Make a temp file name in the proper directory.
-
- dsttmp=$dstdir/#inst.$$#
-
-# Move or copy the file name to the temp name
-
- $doit $instcmd $src $dsttmp &&
-
- trap "rm -f ${dsttmp}" 0 &&
-
-# and set any options; do chmod last to preserve setuid bits
-
-# If any of these fail, we abort the whole thing. If we want to
-# ignore errors from any of these, just make sure not to ignore
-# errors from the above "$doit $instcmd $src $dsttmp" command.
-
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
-
-# Now rename the file to the real destination.
-
- $doit $rmcmd -f $dstdir/$dstfile &&
- $doit $mvcmd $dsttmp $dstdir/$dstfile
-
-fi &&
-
-
-exit 0
diff --git a/softfloat/bf16_classify.c b/softfloat/bf16_classify.c
new file mode 100644
index 0000000..d1c6428
--- /dev/null
+++ b/softfloat/bf16_classify.c
@@ -0,0 +1,36 @@
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast16_t bf16_classify( bfloat16_t a )
+{
+ union ui16_f16 uA;
+ uint_fast16_t uiA;
+
+ uA.f = a;
+ uiA = uA.ui;
+
+ uint_fast16_t infOrNaN = expBF16UI( uiA ) == 0xFF;
+ uint_fast16_t subnormalOrZero = expBF16UI( uiA ) == 0;
+ bool sign = signBF16UI( uiA );
+ bool fracZero = fracBF16UI( uiA ) == 0;
+ bool isNaN = isNaNBF16UI( uiA );
+ bool isSNaN = softfloat_isSigNaNBF16UI( uiA );
+
+ return
+ ( sign && infOrNaN && fracZero ) << 0 |
+ ( sign && !infOrNaN && !subnormalOrZero ) << 1 |
+ ( sign && subnormalOrZero && !fracZero ) << 2 |
+ ( sign && subnormalOrZero && fracZero ) << 3 |
+ ( !sign && infOrNaN && fracZero ) << 7 |
+ ( !sign && !infOrNaN && !subnormalOrZero ) << 6 |
+ ( !sign && subnormalOrZero && !fracZero ) << 5 |
+ ( !sign && subnormalOrZero && fracZero ) << 4 |
+ ( isNaN && isSNaN ) << 8 |
+ ( isNaN && !isSNaN ) << 9;
+}
+
diff --git a/softfloat/bf16_cmp.c b/softfloat/bf16_cmp.c
new file mode 100644
index 0000000..25daeef
--- /dev/null
+++ b/softfloat/bf16_cmp.c
@@ -0,0 +1,65 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions, and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+bool bf16_eq( bfloat16_t a, bfloat16_t b )
+{
+ float32_t f32A = { (uint_fast32_t)a.v << 16 };
+ float32_t f32B = { (uint_fast32_t)b.v << 16 };
+
+ return f32_eq ( f32A, f32B );
+}
+
+bool bf16_le( bfloat16_t a, bfloat16_t b )
+{
+ float32_t f32A = { (uint_fast32_t)a.v << 16 };
+ float32_t f32B = { (uint_fast32_t)b.v << 16 };
+
+ return f32_le ( f32A, f32B );
+}
+
+bool bf16_lt( bfloat16_t a, bfloat16_t b )
+{
+ float32_t f32A = { (uint_fast32_t)a.v << 16 };
+ float32_t f32B = { (uint_fast32_t)b.v << 16 };
+
+ return f32_lt ( f32A, f32B );
+}
diff --git a/softfloat/bf16_to_i32.c b/softfloat/bf16_to_i32.c
new file mode 100644
index 0000000..86e4b37
--- /dev/null
+++ b/softfloat/bf16_to_i32.c
@@ -0,0 +1,48 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions, and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast32_t bf16_to_i32( bfloat16_t a, uint_fast8_t roundingMode, bool exact )
+{
+ return f32_to_i32(bf16_to_f32(a), roundingMode, exact);
+}
+
diff --git a/softfloat/bf16_to_i8.c b/softfloat/bf16_to_i8.c
new file mode 100644
index 0000000..21b6f28
--- /dev/null
+++ b/softfloat/bf16_to_i8.c
@@ -0,0 +1,57 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions, and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast8_t bf16_to_i8( bfloat16_t a, uint_fast8_t roundingMode, bool exact )
+{
+ uint_fast8_t old_flags = softfloat_exceptionFlags;
+
+ int_fast32_t sig32 = bf16_to_i32(a, roundingMode, exact);
+
+ if (sig32 > INT8_MAX) {
+ softfloat_exceptionFlags = old_flags | softfloat_flag_invalid;
+ return i8_fromPosOverflow;
+ } else if (sig32 < INT8_MIN) {
+ softfloat_exceptionFlags = old_flags | softfloat_flag_invalid;
+ return i8_fromNegOverflow;
+ } else {
+ return sig32;
+ }
+}
+
diff --git a/softfloat/bf16_to_ui32.c b/softfloat/bf16_to_ui32.c
new file mode 100644
index 0000000..284bc7f
--- /dev/null
+++ b/softfloat/bf16_to_ui32.c
@@ -0,0 +1,48 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions, and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast32_t bf16_to_ui32( float16_t a, uint_fast8_t roundingMode, bool exact )
+{
+ return f32_to_ui32(bf16_to_f32(a), roundingMode, exact);
+}
+
diff --git a/softfloat/bf16_to_ui8.c b/softfloat/bf16_to_ui8.c
new file mode 100644
index 0000000..a05c53f
--- /dev/null
+++ b/softfloat/bf16_to_ui8.c
@@ -0,0 +1,54 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions, and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast8_t bf16_to_ui8( bfloat16_t a, uint_fast8_t roundingMode, bool exact )
+{
+ uint_fast8_t old_flags = softfloat_exceptionFlags;
+
+ uint_fast32_t sig32 = bf16_to_ui32(a, roundingMode, exact);
+
+ if (sig32 > UINT8_MAX) {
+ softfloat_exceptionFlags = old_flags | softfloat_flag_invalid;
+ return ui8_fromPosOverflow;
+ } else {
+ return sig32;
+ }
+}
+
diff --git a/softfloat/f128_classify.c b/softfloat/f128_classify.c
index 1092a9b..1092a9b 100755..100644
--- a/softfloat/f128_classify.c
+++ b/softfloat/f128_classify.c
diff --git a/softfloat/f16_classify.c b/softfloat/f16_classify.c
index 9402ff1..9402ff1 100755..100644
--- a/softfloat/f16_classify.c
+++ b/softfloat/f16_classify.c
diff --git a/softfloat/f32_classify.c b/softfloat/f32_classify.c
index 83fad87..83fad87 100755..100644
--- a/softfloat/f32_classify.c
+++ b/softfloat/f32_classify.c
diff --git a/softfloat/f64_classify.c b/softfloat/f64_classify.c
index 180abde..180abde 100755..100644
--- a/softfloat/f64_classify.c
+++ b/softfloat/f64_classify.c
diff --git a/softfloat/f64_to_bf16.c b/softfloat/f64_to_bf16.c
index a320979..73ecf0e 100644
--- a/softfloat/f64_to_bf16.c
+++ b/softfloat/f64_to_bf16.c
@@ -43,12 +43,44 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
bfloat16_t f64_to_bf16( float64_t a )
{
- uint_fast8_t roundingMode = softfloat_roundingMode;
- softfloat_roundingMode = softfloat_round_odd;
+ union ui64_f64 uA;
+ uint_fast64_t uiA;
+ bool sign;
+ int_fast16_t exp;
+ uint_fast64_t frac;
+ struct commonNaN commonNaN;
+ uint_fast16_t uiZ, frac16;
+ union ui16_f16 uZ;
- float32_t f32A = f64_to_f32( a );
-
- softfloat_roundingMode = roundingMode;
-
- return f32_to_bf16( f32A );
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uA.f = a;
+ uiA = uA.ui;
+ sign = signF64UI( uiA );
+ exp = expF64UI( uiA );
+ frac = fracF64UI( uiA );
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if ( exp == 0x7FF ) {
+ if ( frac ) {
+ softfloat_f64UIToCommonNaN( uiA, &commonNaN );
+ uiZ = softfloat_commonNaNToBF16UI( &commonNaN );
+ } else {
+ uiZ = packToBF16UI( sign, 0xFF, 0 );
+ }
+ goto uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ frac16 = softfloat_shortShiftRightJam64( frac, 38 );
+ if ( ! (exp | frac16) ) {
+ uiZ = packToBF16UI( sign, 0, 0 );
+ goto uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ return softfloat_roundPackToBF16( sign, exp - 0x381, frac16 | 0x4000 );
+ uiZ:
+ uZ.ui = uiZ;
+ return uZ.f;
}
diff --git a/softfloat/fall_maxmin.c b/softfloat/fall_maxmin.c
index 32a9ade..f1efa87 100644
--- a/softfloat/fall_maxmin.c
+++ b/softfloat/fall_maxmin.c
@@ -72,10 +72,26 @@ float ## bits ## _t f ## bits ## _min( float ## bits ## _t a, float ## bits ## _
} \
}
-COMPARE_MAX(a, b, 16);
-COMPARE_MAX(a, b, 32);
-COMPARE_MAX(a, b, 64);
+COMPARE_MAX(a, b, 16)
+COMPARE_MAX(a, b, 32)
+COMPARE_MAX(a, b, 64)
-COMPARE_MIN(a, b, 16);
-COMPARE_MIN(a, b, 32);
-COMPARE_MIN(a, b, 64);
+COMPARE_MIN(a, b, 16)
+COMPARE_MIN(a, b, 32)
+COMPARE_MIN(a, b, 64)
+
+bfloat16_t bf16_max( bfloat16_t a, bfloat16_t b )
+{
+ float32_t f32A = { (uint32_t)a.v << 16 };
+ float32_t f32B = { (uint32_t)b.v << 16 };
+
+ return f32_to_bf16 ( f32_max( f32A, f32B ) );
+}
+
+bfloat16_t bf16_min( bfloat16_t a, bfloat16_t b )
+{
+ float32_t f32A = { (uint32_t)a.v << 16 };
+ float32_t f32B = { (uint32_t)b.v << 16 };
+
+ return f32_to_bf16 ( f32_min( f32A, f32B ) );
+}
diff --git a/softfloat/fall_reciprocal.c b/softfloat/fall_reciprocal.c
index 1c96458..622be1c 100644
--- a/softfloat/fall_reciprocal.c
+++ b/softfloat/fall_reciprocal.c
@@ -93,6 +93,43 @@ static inline uint64_t rsqrte7(uint64_t val, int e, int s, bool sub) {
return (sign << (s+e)) | (out_exp << s) | out_sig;
}
+bfloat16_t bf16_rsqrte7(bfloat16_t in)
+{
+ union ui16_bf16 uA;
+
+ uA.f = in;
+ unsigned int ret = bf16_classify(in);
+ bool sub = false;
+ switch(ret) {
+ case 0x001: // -inf
+ case 0x002: // -normal
+ case 0x004: // -subnormal
+ case 0x100: // sNaN
+ softfloat_exceptionFlags |= softfloat_flag_invalid;
+ case 0x200: //qNaN
+ uA.ui = defaultNaNBF16UI;
+ break;
+ case 0x008: // -0
+ uA.ui = 0xff80;
+ softfloat_exceptionFlags |= softfloat_flag_infinite;
+ break;
+ case 0x010: // +0
+ uA.ui = 0x7f80;
+ softfloat_exceptionFlags |= softfloat_flag_infinite;
+ break;
+ case 0x080: //+inf
+ uA.ui = 0x0;
+ break;
+ case 0x020: //+ sub
+ sub = true;
+ default: // +num
+ uA.ui = rsqrte7(uA.ui, 8, 7, sub);
+ break;
+ }
+
+ return uA.f;
+}
+
float16_t f16_rsqrte7(float16_t in)
{
union ui16_f16 uA;
@@ -262,6 +299,49 @@ static inline uint64_t recip7(uint64_t val, int e, int s, int rm, bool sub,
return (sign << (s+e)) | (out_exp << s) | out_sig;
}
+bfloat16_t bf16_recip7(bfloat16_t in)
+{
+ union ui16_bf16 uA;
+
+ uA.f = in;
+ unsigned int ret = bf16_classify(in);
+ bool sub = false;
+ bool round_abnormal = false;
+ switch(ret) {
+ case 0x001: // -inf
+ uA.ui = 0x8000;
+ break;
+ case 0x080: //+inf
+ uA.ui = 0x0;
+ break;
+ case 0x008: // -0
+ uA.ui = 0xff80;
+ softfloat_exceptionFlags |= softfloat_flag_infinite;
+ break;
+ case 0x010: // +0
+ uA.ui = 0x7f80;
+ softfloat_exceptionFlags |= softfloat_flag_infinite;
+ break;
+ case 0x100: // sNaN
+ softfloat_exceptionFlags |= softfloat_flag_invalid;
+ case 0x200: //qNaN
+ uA.ui = defaultNaNBF16UI;
+ break;
+ case 0x004: // -subnormal
+ case 0x020: //+ sub
+ sub = true;
+ default: // +- normal
+ uA.ui = recip7(uA.ui, 8, 7,
+ softfloat_roundingMode, sub, &round_abnormal);
+ if (round_abnormal)
+ softfloat_exceptionFlags |= softfloat_flag_inexact |
+ softfloat_flag_overflow;
+ break;
+ }
+
+ return uA.f;
+}
+
float16_t f16_recip7(float16_t in)
{
union ui16_f16 uA;
diff --git a/softfloat/fall_sign.c b/softfloat/fall_sign.c
new file mode 100644
index 0000000..4e9c186
--- /dev/null
+++ b/softfloat/fall_sign.c
@@ -0,0 +1,63 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions, and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool bf16_sign( bfloat16_t a )
+{
+ return signBF16UI(a.v);
+}
+
+bool f16_sign( float16_t a )
+{
+ return signF16UI(a.v);
+}
+
+bool f32_sign( float32_t a )
+{
+ return signF32UI(a.v);
+}
+
+bool f64_sign( float64_t a )
+{
+ return signF64UI(a.v);
+}
diff --git a/softfloat/i32_to_bf16.c b/softfloat/i32_to_bf16.c
new file mode 100644
index 0000000..e1f6ac8
--- /dev/null
+++ b/softfloat/i32_to_bf16.c
@@ -0,0 +1,52 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions, and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+bfloat16_t i32_to_bf16( int32_t a )
+{
+ uint_fast8_t origin_rounding_mode = softfloat_roundingMode;
+ softfloat_roundingMode = softfloat_round_odd;
+ float32_t tmp_val = i32_to_f32(a);
+
+ softfloat_roundingMode = origin_rounding_mode;
+ return f32_to_bf16(tmp_val);
+}
+
diff --git a/softfloat/internals.h b/softfloat/internals.h
index ae94427..f397ce5 100644
--- a/softfloat/internals.h
+++ b/softfloat/internals.h
@@ -46,6 +46,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
extern "C" {
#endif
+union ui16_bf16 { uint16_t ui; bfloat16_t f; };
union ui16_f16 { uint16_t ui; float16_t f; };
union ui32_f32 { uint32_t ui; float32_t f; };
union ui64_f64 { uint64_t ui; float64_t f; };
@@ -84,16 +85,20 @@ int_fast64_t softfloat_roundMToI64( bool, uint32_t *, uint_fast8_t, bool );
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
-#define signF16UI( a ) ((bool) ((uint16_t) (a)>>15))
-#define expF16UI( a ) ((int_fast8_t) ((a)>>10) & 0x1F)
-#define fracF16UI( a ) ((a) & 0x03FF)
-#define packToF16UI( sign, exp, sig ) (((uint16_t) (sign)<<15) + ((uint16_t) (exp)<<10) + (sig))
-
#define signBF16UI( a ) ((bool) ((uint16_t) (a)>>15))
#define expBF16UI( a ) ((int_fast16_t) ((a)>>7) & 0xFF)
#define fracBF16UI( a ) ((a) & 0x07F)
#define packToBF16UI( sign, exp, sig ) (((uint16_t) (sign)<<15) + ((uint16_t) (exp)<<7) + (sig))
+#define isNaNBF16UI( a ) (((~(a) & 0x7F80) == 0) && ((a) & 0x007F))
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+#define signF16UI( a ) ((bool) ((uint16_t) (a)>>15))
+#define expF16UI( a ) ((int_fast8_t) ((a)>>10) & 0x1F)
+#define fracF16UI( a ) ((a) & 0x03FF)
+#define packToF16UI( sign, exp, sig ) (((uint16_t) (sign)<<15) + ((uint16_t) (exp)<<10) + (sig))
+
#define isNaNF16UI( a ) (((~(a) & 0x7C00) == 0) && ((a) & 0x03FF))
struct exp8_sig16 { int_fast8_t exp; uint_fast16_t sig; };
diff --git a/softfloat/softfloat.h b/softfloat/softfloat.h
index 81d63f3..9c57404 100644
--- a/softfloat/softfloat.h
+++ b/softfloat/softfloat.h
@@ -103,6 +103,7 @@ void softfloat_raiseFlags( uint_fast8_t );
/*----------------------------------------------------------------------------
| Integer-to-floating-point conversion routines.
*----------------------------------------------------------------------------*/
+bfloat16_t ui32_to_bf16( uint32_t );
float16_t ui32_to_f16( uint32_t );
float32_t ui32_to_f32( uint32_t );
float64_t ui32_to_f64( uint32_t );
@@ -121,6 +122,7 @@ float128_t ui64_to_f128( uint64_t );
#endif
void ui64_to_extF80M( uint64_t, extFloat80_t * );
void ui64_to_f128M( uint64_t, float128_t * );
+bfloat16_t i32_to_bf16( int32_t );
float16_t i32_to_f16( int32_t );
float32_t i32_to_f32( int32_t );
float64_t i32_to_f64( int32_t );
@@ -180,6 +182,7 @@ bool f16_eq_signaling( float16_t, float16_t );
bool f16_le_quiet( float16_t, float16_t );
bool f16_lt_quiet( float16_t, float16_t );
bool f16_isSignalingNaN( float16_t );
+bool f16_sign( float16_t );
uint_fast16_t f16_classify( float16_t );
float16_t f16_rsqrte7( float16_t );
float16_t f16_recip7( float16_t );
@@ -187,6 +190,10 @@ float16_t f16_recip7( float16_t );
/*----------------------------------------------------------------------------
| BFloat16 operations.
*----------------------------------------------------------------------------*/
+uint_fast8_t bf16_to_ui8( bfloat16_t, uint_fast8_t, bool );
+uint_fast32_t bf16_to_ui32( bfloat16_t, uint_fast8_t, bool );
+int_fast8_t bf16_to_i8( bfloat16_t, uint_fast8_t, bool );
+int_fast32_t bf16_to_i32( bfloat16_t, uint_fast8_t, bool );
float32_t bf16_to_f32( bfloat16_t );
float64_t bf16_to_f64( bfloat16_t );
bfloat16_t bf16_add( bfloat16_t, bfloat16_t );
@@ -195,6 +202,15 @@ bfloat16_t bf16_mul( bfloat16_t, bfloat16_t );
bfloat16_t bf16_mulAdd( bfloat16_t, bfloat16_t, bfloat16_t );
bfloat16_t bf16_div( bfloat16_t, bfloat16_t );
bfloat16_t bf16_sqrt( bfloat16_t );
+bfloat16_t bf16_max( bfloat16_t, bfloat16_t );
+bfloat16_t bf16_min( bfloat16_t, bfloat16_t );
+bool bf16_eq( bfloat16_t, bfloat16_t );
+bool bf16_le( bfloat16_t, bfloat16_t );
+bool bf16_lt( bfloat16_t, bfloat16_t );
+bool bf16_sign( bfloat16_t );
+uint_fast16_t bf16_classify( bfloat16_t );
+bfloat16_t bf16_rsqrte7( bfloat16_t );
+bfloat16_t bf16_recip7( bfloat16_t );
/*----------------------------------------------------------------------------
| 32-bit (single-precision) floating-point operations.
@@ -235,6 +251,7 @@ bool f32_eq_signaling( float32_t, float32_t );
bool f32_le_quiet( float32_t, float32_t );
bool f32_lt_quiet( float32_t, float32_t );
bool f32_isSignalingNaN( float32_t );
+bool f32_sign( float32_t );
uint_fast16_t f32_classify( float32_t );
float32_t f32_rsqrte7( float32_t );
float32_t f32_recip7( float32_t );
@@ -276,6 +293,7 @@ bool f64_eq_signaling( float64_t, float64_t );
bool f64_le_quiet( float64_t, float64_t );
bool f64_lt_quiet( float64_t, float64_t );
bool f64_isSignalingNaN( float64_t );
+bool f64_sign( float64_t );
uint_fast16_t f64_classify( float64_t );
float64_t f64_rsqrte7( float64_t );
float64_t f64_recip7( float64_t );
diff --git a/softfloat/softfloat.mk.in b/softfloat/softfloat.mk.in
index 626b611..899f00a 100644
--- a/softfloat/softfloat.mk.in
+++ b/softfloat/softfloat.mk.in
@@ -7,8 +7,14 @@ softfloat_c_srcs = \
bf16_mulAdd.c \
bf16_sqrt.c \
bf16_sub.c \
+ bf16_cmp.c \
+ bf16_classify.c \
bf16_to_f32.c \
bf16_to_f64.c \
+ bf16_to_i8.c \
+ bf16_to_i32.c \
+ bf16_to_ui8.c \
+ bf16_to_ui32.c \
f128_add.c \
f128_classify.c \
f128_div.c \
@@ -127,7 +133,9 @@ softfloat_c_srcs = \
f64_to_ui64_r_minMag.c \
fall_maxmin.c \
fall_reciprocal.c \
+ fall_sign.c \
i32_to_f128.c \
+ i32_to_bf16.c \
i32_to_f16.c \
i32_to_f32.c \
i32_to_f64.c \
@@ -228,6 +236,7 @@ softfloat_c_srcs = \
s_subMagsF64.c \
s_subM.c \
ui32_to_f128.c \
+ ui32_to_bf16.c \
ui32_to_f16.c \
ui32_to_f32.c \
ui32_to_f64.c \
@@ -243,8 +252,5 @@ softfloat_test_srcs =
softfloat_install_hdrs = \
softfloat.h \
softfloat_types.h \
- primitives.h \
- internals.h \
- platform.h \
- primitiveTypes.h \
- specialize.h \
+
+softfloat_CFLAGS = -Wno-sign-compare -Wno-implicit-fallthrough
diff --git a/softfloat/specialize.h b/softfloat/specialize.h
index fb3761d..adbc081 100644
--- a/softfloat/specialize.h
+++ b/softfloat/specialize.h
@@ -105,6 +105,13 @@ struct commonNaN { char _unused; };
/*----------------------------------------------------------------------------
| Returns true when 16-bit unsigned integer `uiA' has the bit pattern of a
+| 16-bit bfloating-point signaling NaN.
+| Note: This macro evaluates its argument more than once.
+*----------------------------------------------------------------------------*/
+#define softfloat_isSigNaNBF16UI( uiA ) ((((uiA) & 0x7FC0) == 0x7F80) && ((uiA) & 0x007F))
+
+/*----------------------------------------------------------------------------
+| Returns true when 16-bit unsigned integer `uiA' has the bit pattern of a
| 16-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
diff --git a/softfloat/ui32_to_bf16.c b/softfloat/ui32_to_bf16.c
new file mode 100644
index 0000000..7b2d770
--- /dev/null
+++ b/softfloat/ui32_to_bf16.c
@@ -0,0 +1,51 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California. All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions, and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+bfloat16_t ui32_to_bf16( uint32_t a )
+{
+ uint_fast8_t origin_rounding_mode = softfloat_roundingMode;
+ softfloat_roundingMode = softfloat_round_odd;
+ float32_t tmp_val = ui32_to_f32(a);
+
+ softfloat_roundingMode = origin_rounding_mode;
+ return f32_to_bf16(tmp_val);
+}
+
diff --git a/spike_dasm/spike-dasm.cc b/spike_dasm/spike-dasm.cc
index 3e42df5..a093297 100644
--- a/spike_dasm/spike-dasm.cc
+++ b/spike_dasm/spike-dasm.cc
@@ -6,9 +6,9 @@
// enclosed hexadecimal number, interpreted as a RISC-V
// instruction.
-#include "config.h"
#include "disasm.h"
#include "extension.h"
+#include "platform.h"
#include <iostream>
#include <string>
#include <cstdint>
@@ -19,6 +19,7 @@ int main(int UNUSED argc, char** argv)
{
string s;
const char* isa = DEFAULT_ISA;
+ bool strict = false;
std::function<extension_t*()> extension;
option_parser_t parser;
@@ -26,10 +27,11 @@ int main(int UNUSED argc, char** argv)
parser.option(0, "extension", 1, [&](const char* s){extension = find_extension(s);});
#endif
parser.option(0, "isa", 1, [&](const char* s){isa = s;});
+ parser.option(0, "strict", 0, [&](const char UNUSED *s){strict = true;});
parser.parse(argv);
isa_parser_t isa_parser(isa, DEFAULT_PRIV);
- disassembler_t* disassembler = new disassembler_t(&isa_parser);
+ disassembler_t* disassembler = new disassembler_t(&isa_parser, strict);
if (extension) {
for (auto disasm_insn : extension()->get_disasms()) {
disassembler->add_insn(disasm_insn);
diff --git a/spike_main/spike-log-parser.cc b/spike_main/spike-log-parser.cc
index a054e95..21166ad 100644
--- a/spike_main/spike-log-parser.cc
+++ b/spike_main/spike-log-parser.cc
@@ -5,7 +5,6 @@
// in its inputs, then output the RISC-V instruction with the disassembly
// enclosed hexadecimal number.
-#include "config.h"
#include <iostream>
#include <string>
#include <cstdint>
@@ -14,6 +13,7 @@
#include "disasm.h"
#include "extension.h"
+#include "platform.h"
using namespace std;
@@ -31,14 +31,13 @@ int main(int UNUSED argc, char** argv)
cfg_t cfg;
isa_parser_t isa(isa_string, DEFAULT_PRIV);
- processor_t p(&isa, &cfg, 0, 0, false, nullptr, cerr);
+ processor_t p(isa_string, DEFAULT_PRIV, &cfg, 0, 0, false, nullptr, cerr);
if (extension) {
p.register_extension(extension());
}
std::regex reg("^core\\s+\\d+:\\s+0x[0-9a-f]+\\s+\\(0x([0-9a-f]+)\\)", std::regex_constants::icase);
std::smatch m;
- std::ssub_match sm ;
while (getline(cin,s)){
if (regex_search(s, m, reg)){
diff --git a/spike_main/spike.cc b/spike_main/spike.cc
index 1a298f2..3b0e004 100644
--- a/spike_main/spike.cc
+++ b/spike_main/spike.cc
@@ -38,7 +38,7 @@ static void help(int exit_code = 1)
fprintf(stderr, " -s Command I/O via socket (use with -d)\n");
#endif
fprintf(stderr, " -h, --help Print this help message\n");
- fprintf(stderr, " -H Start halted, allowing a debugger to connect\n");
+ fprintf(stderr, " --halted Start halted, allowing a debugger to connect\n");
fprintf(stderr, " --log=<name> File name for option -l\n");
fprintf(stderr, " --debug-cmd=<name> Read commands from file (use with -d)\n");
fprintf(stderr, " --isa=<name> RISC-V ISA string [default %s]\n", DEFAULT_ISA);
@@ -78,12 +78,13 @@ static void help(int exit_code = 1)
"required for a DMI access [default 0]\n");
fprintf(stderr, " --dm-abstract-rti=<n> Number of Run-Test/Idle cycles "
"required for an abstract command to execute [default 0]\n");
- fprintf(stderr, " --dm-no-hasel Debug module supports hasel\n");
+ fprintf(stderr, " --dm-no-hasel Debug module won't support hasel\n");
fprintf(stderr, " --dm-no-abstract-csr Debug module won't support abstract CSR access\n");
fprintf(stderr, " --dm-no-abstract-fpr Debug module won't support abstract FPR access\n");
fprintf(stderr, " --dm-no-halt-groups Debug module won't support halt groups\n");
fprintf(stderr, " --dm-no-impebreak Debug module won't support implicit ebreak in program buffer\n");
fprintf(stderr, " --blocksz=<size> Cache block size (B) for CMO operations(powers of 2) [default 64]\n");
+ fprintf(stderr, " --instructions=<n> Stop after n instructions\n");
exit(exit_code);
}
@@ -191,6 +192,31 @@ merge_overlapping_memory_regions(std::vector<mem_cfg_t> mems)
return merged_mem;
}
+static mem_cfg_t create_mem_region(unsigned long long base, unsigned long long size)
+{
+ // page-align base and size
+ auto base0 = base, size0 = size;
+ size += base0 % PGSIZE;
+ base -= base0 % PGSIZE;
+ if (size % PGSIZE != 0)
+ size += PGSIZE - size % PGSIZE;
+
+ if (size != size0) {
+ fprintf(stderr, "Warning: the memory at [0x%llX, 0x%llX] has been realigned\n"
+ "to the %ld KiB page size: [0x%llX, 0x%llX]\n",
+ base0, base0 + size0 - 1, long(PGSIZE / 1024), base, base + size - 1);
+ }
+
+ if (!mem_cfg_t::check_if_supported(base, size)) {
+ fprintf(stderr, "Unsupported memory region "
+ "{base = 0x%llX, size = 0x%llX} specified\n",
+ base, size);
+ exit(EXIT_FAILURE);
+ }
+
+ return mem_cfg_t(base, size);
+}
+
static std::vector<mem_cfg_t> parse_mem_layout(const char* arg)
{
std::vector<mem_cfg_t> res;
@@ -200,9 +226,9 @@ static std::vector<mem_cfg_t> parse_mem_layout(const char* arg)
auto mb = strtoull(arg, &p, 0);
if (*p == 0) {
reg_t size = reg_t(mb) << 20;
- if (size != (size_t)size)
- throw std::runtime_error("Size would overflow size_t");
- res.push_back(mem_cfg_t(reg_t(DRAM_BASE), size));
+ if ((size >> 20) != mb)
+ throw std::runtime_error("Memory size too large");
+ res.push_back(create_mem_region(DRAM_BASE, size));
return res;
}
@@ -213,42 +239,7 @@ static std::vector<mem_cfg_t> parse_mem_layout(const char* arg)
help();
auto size = strtoull(p + 1, &p, 0);
- // page-align base and size
- auto base0 = base, size0 = size;
- size += base0 % PGSIZE;
- base -= base0 % PGSIZE;
- if (size % PGSIZE != 0)
- size += PGSIZE - size % PGSIZE;
-
- if (size != size0) {
- fprintf(stderr, "Warning: the memory at [0x%llX, 0x%llX] has been realigned\n"
- "to the %ld KiB page size: [0x%llX, 0x%llX]\n",
- base0, base0 + size0 - 1, long(PGSIZE / 1024), base, base + size - 1);
- }
-
- if (!mem_cfg_t::check_if_supported(base, size)) {
- fprintf(stderr, "Unsupported memory region "
- "{base = 0x%llX, size = 0x%llX} specified\n",
- base, size);
- exit(EXIT_FAILURE);
- }
-
- const unsigned long long max_allowed_pa = (1ull << MAX_PADDR_BITS) - 1ull;
- assert(max_allowed_pa <= std::numeric_limits<reg_t>::max());
- mem_cfg_t mem_region(base, size);
- if (mem_region.get_inclusive_end() > max_allowed_pa) {
- int bits_required = 64 - clz(mem_region.get_inclusive_end());
- fprintf(stderr, "Unsupported memory region "
- "{base = 0x%" PRIX64 ", size = 0x%" PRIX64 "} specified,"
- " which requires %d bits of physical address\n"
- " The largest accessible physical address "
- "is 0x%llX (defined by MAX_PADDR_BITS constant, which is %d)\n",
- mem_region.get_base(), mem_region.get_size(), bits_required,
- max_allowed_pa, MAX_PADDR_BITS);
- exit(EXIT_FAILURE);
- }
-
- res.push_back(mem_region);
+ res.push_back(create_mem_region(base, size));
if (!*p)
break;
@@ -348,6 +339,7 @@ int main(int argc, char** argv)
bool use_rbb = false;
unsigned dmi_rti = 0;
reg_t blocksz = 64;
+ std::optional<unsigned long long> instructions;
debug_module_config_t dm_config;
cfg_arg_t<size_t> nprocs(1);
@@ -385,8 +377,7 @@ int main(int argc, char** argv)
#endif
parser.option('p', 0, 1, [&](const char* s){nprocs = atoul_nonzero_safe(s);});
parser.option('m', 0, 1, [&](const char* s){cfg.mem_layout = parse_mem_layout(s);});
- // I wanted to use --halted, but for some reason that doesn't work.
- parser.option('H', 0, 0, [&](const char UNUSED *s){halted = true;});
+ parser.option(0, "halted", 0, [&](const char UNUSED *s){halted = true;});
parser.option(0, "rbb-port", 1, [&](const char* s){use_rbb = true; rbb_port = atoul_safe(s);});
parser.option(0, "pc", 1, [&](const char* s){cfg.start_pc = strtoull(s, 0, 0);});
parser.option(0, "hartids", 1, [&](const char* s){
@@ -460,6 +451,10 @@ int main(int argc, char** argv)
min_blocksz, max_blocksz);
exit(-1);
}
+ cfg.cache_blocksz = blocksz;
+ });
+ parser.option(0, "instructions", 1, [&](const char* s){
+ instructions = strtoull(s, 0, 0);
});
auto argv1 = parser.parse(argv);
@@ -522,7 +517,8 @@ int main(int argc, char** argv)
sim_t s(&cfg, halted,
mems, plugin_device_factories, htif_args, dm_config, log_path, dtb_enabled, dtb_file,
socket,
- cmd_file);
+ cmd_file,
+ instructions);
std::unique_ptr<remote_bitbang_t> remote_bitbang((remote_bitbang_t *) NULL);
std::unique_ptr<jtag_dtm_t> jtag_dtm(
new jtag_dtm_t(&s.debug_module, dmi_rti));
@@ -546,7 +542,6 @@ int main(int argc, char** argv)
if (dc) s.get_core(i)->get_mmu()->register_memtracer(&*dc);
for (auto e : extensions)
s.get_core(i)->register_extension(e());
- s.get_core(i)->get_mmu()->set_cache_blocksz(blocksz);
}
s.set_debug(debug);