-
Notifications
You must be signed in to change notification settings - Fork 121
Description
First trial of refactoring, the wasm branch's latest commit is the result.
Since state_t is a user-provided data, so all runtime defined value(often change) shall be stored there. For instance, the emulated target program's argc and argv, and the emulator's parameter. The following have been adjusted to reflect the changes:
-
state_t *state_new(void)----->state_t *state_new(uint32_t mem_size, int argc, char **argv, bool allow_misalign, bool quiet_output)
mem_sizeis used formemory_newbecause different runtimes may have memory requirements (for example, the page size in WebAssembly is 64KiB), the defaultMEM_SIZE(2^32 - 1) is not appropriate for that. The rest of parameters are runtime defined value. -
riscv_t *rv_create(const riscv_io_t *io, riscv_user_t userdata, int argc, char **args, bool output_exit_code)----->riscv_t *rv_create(riscv_user_t userdata)
Much cleaner function signature. -
void rv_reset(riscv_t *rv, riscv_word_t pc, int argc, char **args)----->void rv_reset(riscv_t *rv, riscv_word_t pc)
We can userv->userdatato get the requiredargcandargv. -
Since memory I/O handlers are rarely changed, it makes less sense to define them during runtime (makes porting difficult). Instead, I believe it is preferable to link them during build time. If really want to change the implementations, make a new C file and link it during build time might be a better choice.
To do this, some changes are made:- define memory I/O handlers in
rv_createand link during build time - to make memory write interfaces match to compatible with the function pointers,
MEM_WRITE_IMPLmacro has to be changed: -
src/io.c
- define memory I/O handlers in
// old
#define MEM_WRITE_IMPL(size, type) \
void memory_write_##size(uint32_t addr, const uint8_t *src) \
{ \
*(type *) (data_memory_base + addr) = *(const type *) src; \
}
// new
#define MEM_WRITE_IMPL(size, type) \
void memory_write_##size(uint32_t addr, const type src) \
{ \
*(type *) (data_memory_base + addr) = src; \
}- the calling of
memory_write_win "src/syscall.c" shall be changed accordingly: -
src/syscall.c
// old
memory_write_w(tv + 0, (const uint8_t *) &tv_s.tv_sec);
// new
memory_write_w(tv + 0, *((const uint32_t *) &tv_s.tv_sec));For notably change, the "pre.js" of the wasm branch do not define IO on its own anymore compare to first attempt.(more abstraction)
-
Change all
uint32_tanduint16_tanduint8_tin riscv.[ch] toriscv_word_tandriscv_half_tandriscv_byte_tin function signature respectively for consistency. -
bool elf_load(elf_t *e, riscv_t *rv, memory_t *mem);----->bool elf_load(elf_t *e, riscv_t *rv);
The memory instance required byelf_loadcan be accessed viarv's userdata.
I am wondering shall we abstract the FILE defined in state_new as a parameter of state_new. Without abstraction, the emulator always depends on standard io(e.g., stdin, stdout, stderr). What if the user want to use a file instead of stdout?
Related to: #75