aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2023-03-01 13:05:45 -0800
committerAndrew Waterman <andrew@sifive.com>2023-03-01 13:34:07 -0800
commit9d3f3672039393675218268b447f5b039708265e (patch)
tree8bded8bf073f54ca2511c9f110c75c80c04fd80f
parent2ec72f2a84d77ac43044bf5593923468990d1b40 (diff)
downloadriscv-isa-sim-9d3f3672039393675218268b447f5b039708265e.zip
riscv-isa-sim-9d3f3672039393675218268b447f5b039708265e.tar.gz
riscv-isa-sim-9d3f3672039393675218268b447f5b039708265e.tar.bz2
Fix PLIC on big-endian hosts
-rw-r--r--riscv/devices.h23
-rw-r--r--riscv/plic.cc6
2 files changed, 26 insertions, 3 deletions
diff --git a/riscv/devices.h b/riscv/devices.h
index 0fa8885..f7e631e 100644
--- a/riscv/devices.h
+++ b/riscv/devices.h
@@ -10,6 +10,7 @@
#include <queue>
#include <vector>
#include <utility>
+#include <cassert>
class processor_t;
class sim_t;
@@ -170,4 +171,26 @@ class mmio_plugin_device_t : public abstract_device_t {
void* user_data;
};
+template<typename T>
+void write_little_endian_reg(T* word, reg_t addr, size_t len, const uint8_t* bytes)
+{
+ assert(len <= sizeof(T));
+
+ for (size_t i = 0; i < len; i++) {
+ const int shift = 8 * ((addr + i) % sizeof(T));
+ *word = (*word & ~(T(0xFF) << shift)) | (T(bytes[i]) << shift);
+ }
+}
+
+template<typename T>
+void read_little_endian_reg(T word, reg_t addr, size_t len, uint8_t* bytes)
+{
+ assert(len <= sizeof(T));
+
+ for (size_t i = 0; i < len; i++) {
+ const int shift = 8 * ((addr + i) % sizeof(T));
+ bytes[i] = word >> shift;
+ }
+}
+
#endif
diff --git a/riscv/plic.cc b/riscv/plic.cc
index 57355ef..515451a 100644
--- a/riscv/plic.cc
+++ b/riscv/plic.cc
@@ -329,7 +329,7 @@ bool plic_t::load(reg_t addr, size_t len, uint8_t* bytes)
}
}
- memcpy(bytes, (uint8_t *)&val, len);
+ read_little_endian_reg(val, addr, len, bytes);
return ret;
}
@@ -337,7 +337,7 @@ bool plic_t::load(reg_t addr, size_t len, uint8_t* bytes)
bool plic_t::store(reg_t addr, size_t len, const uint8_t* bytes)
{
bool ret = false;
- uint32_t val;
+ uint32_t val = 0;
switch (len) {
case 4:
@@ -350,7 +350,7 @@ bool plic_t::store(reg_t addr, size_t len, const uint8_t* bytes)
return false;
}
- memcpy((uint8_t *)&val, bytes, len);
+ write_little_endian_reg(&val, addr, len, bytes);
if (PRIORITY_BASE <= addr && addr < ENABLE_BASE) {
ret = priority_write(addr, val);