aboutsummaryrefslogtreecommitdiff
path: root/riscv/sim.cc
diff options
context:
space:
mode:
authorMarcus Comstedt <marcus@mc.pp.se>2020-10-11 13:36:13 +0200
committerMarcus Comstedt <marcus@mc.pp.se>2020-11-07 15:03:58 +0100
commit8d09d845a7373cce52d3943f5dca1a2ac34a4f83 (patch)
tree65a8e157ac2c167c6b89d436c00fa8c12bdf6181 /riscv/sim.cc
parent641d7d03e6a8d822b720fcb1a19f261813c00c4a (diff)
downloadspike-8d09d845a7373cce52d3943f5dca1a2ac34a4f83.zip
spike-8d09d845a7373cce52d3943f5dca1a2ac34a4f83.tar.gz
spike-8d09d845a7373cce52d3943f5dca1a2ac34a4f83.tar.bz2
Implement support for big-endian targets
Diffstat (limited to 'riscv/sim.cc')
-rw-r--r--riscv/sim.cc46
1 files changed, 42 insertions, 4 deletions
diff --git a/riscv/sim.cc b/riscv/sim.cc
index 76bb3cd..ef405c3 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -254,8 +254,22 @@ void sim_t::set_rom()
(uint32_t) (start_pc & 0xffffffff),
(uint32_t) (start_pc >> 32)
};
- for(int i = 0; i < reset_vec_size; i++)
- reset_vec[i] = to_le(reset_vec[i]);
+ if (get_target_endianness() == memif_endianness_big) {
+ int i;
+ // Instuctions are little endian
+ for (i = 0; reset_vec[i] != 0; i++)
+ reset_vec[i] = to_le(reset_vec[i]);
+ // Data is big endian
+ for (; i < reset_vec_size; i++)
+ reset_vec[i] = to_be(reset_vec[i]);
+
+ // Correct the high/low order of 64-bit start PC
+ if (get_core(0)->get_xlen() != 32)
+ std::swap(reset_vec[reset_vec_size-2], reset_vec[reset_vec_size-1]);
+ } else {
+ for (int i = 0; i < reset_vec_size; i++)
+ reset_vec[i] = to_le(reset_vec[i]);
+ }
std::vector<char> rom((char*)reset_vec, (char*)reset_vec + sizeof(reset_vec));
@@ -315,7 +329,7 @@ void sim_t::idle()
void sim_t::read_chunk(addr_t taddr, size_t len, void* dst)
{
assert(len == 8);
- auto data = to_le(debug_mmu->load_uint64(taddr));
+ auto data = debug_mmu->to_target(debug_mmu->load_uint64(taddr));
memcpy(dst, &data, sizeof data);
}
@@ -324,7 +338,31 @@ void sim_t::write_chunk(addr_t taddr, size_t len, const void* src)
assert(len == 8);
uint64_t data;
memcpy(&data, src, sizeof data);
- debug_mmu->store_uint64(taddr, from_le(data));
+ debug_mmu->store_uint64(taddr, debug_mmu->from_target(data));
+}
+
+void sim_t::set_target_endianness(memif_endianness_t endianness)
+{
+#ifdef RISCV_ENABLE_DUAL_ENDIAN
+ assert(endianness == memif_endianness_little || endianness == memif_endianness_big);
+
+ bool enable = endianness == memif_endianness_big;
+ debug_mmu->set_target_big_endian(enable);
+ for (size_t i = 0; i < procs.size(); i++) {
+ procs[i]->get_mmu()->set_target_big_endian(enable);
+ }
+#else
+ assert(endianness == memif_endianness_little);
+#endif
+}
+
+memif_endianness_t sim_t::get_target_endianness() const
+{
+#ifdef RISCV_ENABLE_DUAL_ENDIAN
+ return debug_mmu->is_target_big_endian()? memif_endianness_big : memif_endianness_little;
+#else
+ return memif_endianness_little;
+#endif
}
void sim_t::proc_reset(unsigned id)