aboutsummaryrefslogtreecommitdiff
path: root/fesvr
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 /fesvr
parent641d7d03e6a8d822b720fcb1a19f261813c00c4a (diff)
downloadspike-8d09d845a7373cce52d3943f5dca1a2ac34a4f83.zip
spike-8d09d845a7373cce52d3943f5dca1a2ac34a4f83.tar.gz
spike-8d09d845a7373cce52d3943f5dca1a2ac34a4f83.tar.bz2
Implement support for big-endian targets
Diffstat (limited to 'fesvr')
-rw-r--r--fesvr/elfloader.cc23
-rw-r--r--fesvr/htif.cc4
-rw-r--r--fesvr/htif.h26
-rw-r--r--fesvr/memif.h19
-rw-r--r--fesvr/syscall.cc10
5 files changed, 70 insertions, 12 deletions
diff --git a/fesvr/elfloader.cc b/fesvr/elfloader.cc
index a4bae1e..6da3a41 100644
--- a/fesvr/elfloader.cc
+++ b/fesvr/elfloader.cc
@@ -31,7 +31,7 @@ std::map<std::string, uint64_t> load_elf(const char* fn, memif_t* memif, reg_t*
assert(size >= sizeof(Elf64_Ehdr));
const Elf64_Ehdr* eh64 = (const Elf64_Ehdr*)buf;
assert(IS_ELF32(*eh64) || IS_ELF64(*eh64));
- assert(IS_ELFLE(*eh64));
+ assert(IS_ELFLE(*eh64) || IS_ELFBE(*eh64));
assert(IS_ELF_EXEC(*eh64));
assert(IS_ELF_RISCV(*eh64) || IS_ELF_EM_NONE(*eh64));
assert(IS_ELF_VCURRENT(*eh64));
@@ -83,10 +83,23 @@ std::map<std::string, uint64_t> load_elf(const char* fn, memif_t* memif, reg_t*
} \
} while(0)
- if (IS_ELF32(*eh64))
- LOAD_ELF(Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Sym, from_le);
- else
- LOAD_ELF(Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Sym, from_le);
+ if (IS_ELFLE(*eh64)) {
+ memif->set_target_endianness(memif_endianness_little);
+ if (IS_ELF32(*eh64))
+ LOAD_ELF(Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Sym, from_le);
+ else
+ LOAD_ELF(Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Sym, from_le);
+ } else {
+#ifndef RISCV_ENABLE_DUAL_ENDIAN
+ throw std::invalid_argument("Specified ELF is big endian. Configure with --enable-dual-endian to enable support");
+#else
+ memif->set_target_endianness(memif_endianness_big);
+ if (IS_ELF32(*eh64))
+ LOAD_ELF(Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Sym, from_be);
+ else
+ LOAD_ELF(Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Sym, from_be);
+#endif
+ }
munmap(buf, size);
diff --git a/fesvr/htif.cc b/fesvr/htif.cc
index 30b13de..996e321 100644
--- a/fesvr/htif.cc
+++ b/fesvr/htif.cc
@@ -216,7 +216,7 @@ int htif_t::run()
while (!signal_exit && exitcode == 0)
{
- if (auto tohost = from_le(mem.read_uint64(tohost_addr))) {
+ if (auto tohost = from_target(mem.read_uint64(tohost_addr))) {
mem.write_uint64(tohost_addr, 0);
command_t cmd(mem, tohost, fromhost_callback);
device_list.handle_command(cmd);
@@ -227,7 +227,7 @@ int htif_t::run()
device_list.tick();
if (!fromhost_queue.empty() && mem.read_uint64(fromhost_addr) == 0) {
- mem.write_uint64(fromhost_addr, to_le(fromhost_queue.front()));
+ mem.write_uint64(fromhost_addr, to_target(fromhost_queue.front()));
fromhost_queue.pop();
}
}
diff --git a/fesvr/htif.h b/fesvr/htif.h
index 44a3b12..66a626d 100644
--- a/fesvr/htif.h
+++ b/fesvr/htif.h
@@ -6,9 +6,11 @@
#include "memif.h"
#include "syscall.h"
#include "device.h"
+#include "byteorder.h"
#include <string.h>
#include <map>
#include <vector>
+#include <assert.h>
class htif_t : public chunked_memif_t
{
@@ -27,6 +29,30 @@ class htif_t : public chunked_memif_t
virtual memif_t& memif() { return mem; }
+ template<typename T> inline T from_target(T n) const
+ {
+#ifdef RISCV_ENABLE_DUAL_ENDIAN
+ memif_endianness_t endianness = get_target_endianness();
+ assert(endianness == memif_endianness_little || endianness == memif_endianness_big);
+
+ return endianness == memif_endianness_big? from_be(n) : from_le(n);
+#else
+ return from_le(n);
+#endif
+ }
+
+ template<typename T> inline T to_target(T n) const
+ {
+#ifdef RISCV_ENABLE_DUAL_ENDIAN
+ memif_endianness_t endianness = get_target_endianness();
+ assert(endianness == memif_endianness_little || endianness == memif_endianness_big);
+
+ return endianness == memif_endianness_big? to_be(n) : to_le(n);
+#else
+ return to_le(n);
+#endif
+ }
+
protected:
virtual void reset() = 0;
diff --git a/fesvr/memif.h b/fesvr/memif.h
index 3854d66..aaa9f05 100644
--- a/fesvr/memif.h
+++ b/fesvr/memif.h
@@ -10,6 +10,12 @@ typedef uint64_t reg_t;
typedef int64_t sreg_t;
typedef reg_t addr_t;
+typedef enum {
+ memif_endianness_undecided,
+ memif_endianness_little,
+ memif_endianness_big
+} memif_endianness_t;
+
class chunked_memif_t
{
public:
@@ -19,6 +25,11 @@ public:
virtual size_t chunk_align() = 0;
virtual size_t chunk_max_size() = 0;
+
+ virtual void set_target_endianness(memif_endianness_t endianness) {}
+ virtual memif_endianness_t get_target_endianness() const {
+ return memif_endianness_undecided;
+ }
};
class memif_t
@@ -55,6 +66,14 @@ public:
virtual void write_uint64(addr_t addr, uint64_t val);
virtual void write_int64(addr_t addr, int64_t val);
+ // endianness
+ virtual void set_target_endianness(memif_endianness_t endianness) {
+ cmemif->set_target_endianness(endianness);
+ }
+ virtual memif_endianness_t get_target_endianness() const {
+ return cmemif->get_target_endianness();
+ }
+
protected:
chunked_memif_t* cmemif;
};
diff --git a/fesvr/syscall.cc b/fesvr/syscall.cc
index f0bdd25..6feb13b 100644
--- a/fesvr/syscall.cc
+++ b/fesvr/syscall.cc
@@ -300,21 +300,21 @@ reg_t syscall_t::sys_getmainvars(reg_t pbuf, reg_t limit, reg_t a2, reg_t a3, re
{
std::vector<std::string> args = htif->target_args();
std::vector<uint64_t> words(args.size() + 3);
- words[0] = to_le(args.size());
+ words[0] = htif->to_target<uint64_t>(args.size());
words[args.size()+1] = 0; // argv[argc] = NULL
words[args.size()+2] = 0; // envp[0] = NULL
size_t sz = (args.size() + 3) * sizeof(words[0]);
for (size_t i = 0; i < args.size(); i++)
{
- words[i+1] = to_le(sz + pbuf);
+ words[i+1] = htif->to_target<uint64_t>(sz + pbuf);
sz += args[i].length() + 1;
}
std::vector<char> bytes(sz);
memcpy(&bytes[0], &words[0], sizeof(words[0]) * words.size());
for (size_t i = 0; i < args.size(); i++)
- strcpy(&bytes[from_le(words[i+1]) - pbuf], args[i].c_str());
+ strcpy(&bytes[htif->from_target(words[i+1]) - pbuf], args[i].c_str());
if (bytes.size() > limit)
return -ENOMEM;
@@ -343,11 +343,11 @@ void syscall_t::dispatch(reg_t mm)
reg_t magicmem[8];
memif->read(mm, sizeof(magicmem), magicmem);
- reg_t n = from_le(magicmem[0]);
+ reg_t n = htif->from_target(magicmem[0]);
if (n >= table.size() || !table[n])
throw std::runtime_error("bad syscall #" + std::to_string(n));
- magicmem[0] = to_le((this->*table[n])(from_le(magicmem[1]), from_le(magicmem[2]), from_le(magicmem[3]), from_le(magicmem[4]), from_le(magicmem[5]), from_le(magicmem[6]), from_le(magicmem[7])));
+ magicmem[0] = htif->to_target((this->*table[n])(htif->from_target(magicmem[1]), htif->from_target(magicmem[2]), htif->from_target(magicmem[3]), htif->from_target(magicmem[4]), htif->from_target(magicmem[5]), htif->from_target(magicmem[6]), htif->from_target(magicmem[7])));
memif->write(mm, sizeof(magicmem), magicmem);
}