mirror of
https://github.com/ringtailsoftware/uvm32.git
synced 2026-06-05 22:43:39 +00:00
ABI info
This commit is contained in:
parent
7bf906f369
commit
f6cd790fcb
5 changed files with 33 additions and 6 deletions
1
Makefile
1
Makefile
|
|
@ -1,4 +1,5 @@
|
|||
all:
|
||||
cat uvm32/uvm32.h uvm32/uvm32.c uvm32/mini-rv32ima.h common/*.h > uvm32-single-file.c
|
||||
(cd host && make)
|
||||
(cd host-mini && make)
|
||||
(cd host-parallel && make)
|
||||
|
|
|
|||
31
README.md
31
README.md
|
|
@ -33,6 +33,11 @@ Although based on a fully fledged CPU emulator, uvm32 is intended for executing
|
|||
host/host precompiled/mandel.bin
|
||||
host/host precompiled/zigtris.bin
|
||||
|
||||
Build sample apps (sets up docker for cross compiler)
|
||||
|
||||
cd apps
|
||||
make
|
||||
|
||||
Build one of the sample apps (requires docker for C, or Zig, or Rust)
|
||||
|
||||
cd apps/helloworld && make
|
||||
|
|
@ -78,7 +83,7 @@ If the bytecode attempts to execute more instructions than the the passed value
|
|||
|
||||
## Internals
|
||||
|
||||
uvm32 emulates a RISC-V 32bit CPU using [mini-rv32ima](https://github.com/cnlohr/mini-rv32ima). All IO from vm bytecode to the host is performed using `ecall` syscalls. Each "function" provided by the host requires a unique syscall value. A syscall passes a single `uint32_t` from bytecode to the host and may receive a returned `uint32_t`. The host may treat the value as a pointer and modify memory.
|
||||
uvm32 emulates a RISC-V 32bit CPU using [mini-rv32ima](https://github.com/cnlohr/mini-rv32ima). All IO from vm bytecode to the host is performed using `ecall` syscalls. Each syscall provided by the host requires a unique syscall value. A syscall passes a single `uint32_t` from bytecode to the host and may receive a returned `uint32_t`. The host may treat the value as a pointer and modify memory.
|
||||
|
||||
uvm32 is always in one of 4 states, paused, running, ended or error.
|
||||
|
||||
|
|
@ -95,6 +100,30 @@ stateDiagram
|
|||
|
||||
At boot, the whole memory is zeroed. The user program is placed at the start, the CPU registers are stored at the end. The stack pointer is set to the start of the CPU registers and grows downwards.
|
||||
|
||||
## syscall ABI
|
||||
|
||||
All communication between bytecode and the vm host is performed via syscalls.
|
||||
|
||||
To make a syscall, register `a7` is set with the syscall number (an `IOREQ_x`) and `a0` is set with the syscall parameter. The response is returned in `a1`.
|
||||
|
||||
[target.h](common/uvm32_target.h#L12)
|
||||
|
||||
```c
|
||||
static uint32_t syscall(uint32_t id, uint32_t param) {
|
||||
register uint32_t a0 asm("a0") = (uint32_t)(param);
|
||||
register uint32_t a1 asm("a1");
|
||||
register uint32_t a7 asm("a7") = (uint32_t)(id);
|
||||
|
||||
asm volatile (
|
||||
"ecall"
|
||||
: "=r"(a1) // output
|
||||
: "r"(a0), "r"(a7) // input
|
||||
: "memory"
|
||||
);
|
||||
return a1;
|
||||
}
|
||||
```
|
||||
|
||||
## ioreqs
|
||||
|
||||
There are two system ioreqs used by uvm32, `halt()` and `yield()`.
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ static uint32_t syscall(uint32_t id, uint32_t param) {
|
|||
#define yield() syscall_cast(IOREQ_YIELD, 0)
|
||||
|
||||
#include "uvm32_common_custom.h"
|
||||
#include "uvm32_target_custom.h"
|
||||
|
||||
// provide main, with setup()/loop() flow
|
||||
void setup(void);
|
||||
|
|
|
|||
|
|
@ -153,15 +153,13 @@ uint32_t uvm32_run(uvm32_state_t *vmst, uvm32_evt_t *evt, uint32_t instr_meter)
|
|||
get_safeptr_terminated(vmst, value, 0x00, &vmst->ioevt.data.ioreq.val.buf);
|
||||
break;
|
||||
case IOREQ_TYP_U32_RD:
|
||||
// get_safeptr(vmst, value, 4, &b);
|
||||
vmst->ioevt.data.ioreq.val.u32p = &vmst->core->regs[11]; // r1, //(uint32_t *)b.ptr;
|
||||
// pass link to r1 for user function to update
|
||||
vmst->ioevt.data.ioreq.val.u32p = &vmst->core->regs[11];
|
||||
break;
|
||||
}
|
||||
vmst->ioevt.typ = UVM32_EVT_IOREQ;
|
||||
vmst->ioevt.data.ioreq.code = vmst->mappings[i].code;
|
||||
vmst->ioevt.data.ioreq.typ = vmst->mappings[i].typ;
|
||||
//#warning FIXME, retval
|
||||
// vmst->core->regs[11] = 456; // r1
|
||||
setStatus(vmst, UVM32_STATUS_PAUSED);
|
||||
syscall_valid = true;
|
||||
break; // stop searching
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue