mirror of
https://github.com/ringtailsoftware/uvm32.git
synced 2026-06-05 22:43:39 +00:00
Move all host examples under host/
This commit is contained in:
parent
1213c5673f
commit
7353810199
16 changed files with 104 additions and 143 deletions
23
hosts/host-arduino/Makefile
Normal file
23
hosts/host-arduino/Makefile
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
TOPDIR=../../
|
||||
|
||||
# Auto-generate the Arduino example
|
||||
# Arduino cannot set -DUVM32_MEMORY_SIZE, so add a config file
|
||||
# Arduino expects .cpp files
|
||||
|
||||
# make test, runs in qemu
|
||||
|
||||
all:
|
||||
echo '#include "config.h"' > uvm32.cpp
|
||||
cat ${TOPDIR}/uvm32/uvm32.c >> uvm32.cpp
|
||||
cp ${TOPDIR}/uvm32/uvm32.h uvm32.h
|
||||
cp ${TOPDIR}/uvm32/mini-rv32ima.h mini-rv32ima.h
|
||||
cp ${TOPDIR}/common/uvm32_common_custom.h uvm32_common_custom.h
|
||||
cp ${TOPDIR}/common/uvm32_sys.h uvm32_sys.h
|
||||
xxd -n mandel -i ${TOPDIR}/precompiled/mandel.bin | sed -e "s/unsigned char/const unsigned char/" > mandel.h
|
||||
arduino-cli compile -b arduino:avr:uno -e
|
||||
|
||||
test: all
|
||||
qemu-system-avr -machine uno -bios build/arduino.avr.uno/host-arduino.ino.elf -nographic -serial mon:stdio
|
||||
|
||||
clean:
|
||||
rm -rf uvm32.cpp uvm32.h mini-rv32ima.h uvm32_common_custom.h uvm32_sys.h mandel.h build
|
||||
2
hosts/host-arduino/config.h
Normal file
2
hosts/host-arduino/config.h
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
// Arduino cannot do -DUVM32_MEMORY_SIZE, so set this explicitly
|
||||
#define UVM32_MEMORY_SIZE 512
|
||||
73
hosts/host-arduino/host-arduino.ino
Normal file
73
hosts/host-arduino/host-arduino.ino
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
#include "config.h"
|
||||
#include "uvm32.h"
|
||||
#include "uvm32_common_custom.h"
|
||||
|
||||
#include "mandel.h"
|
||||
|
||||
uvm32_state_t vmst;
|
||||
uvm32_evt_t evt;
|
||||
bool isrunning = false;
|
||||
uint32_t led_time = 0;
|
||||
bool led_state = false;
|
||||
|
||||
void setup(void) {
|
||||
Serial.begin(115200);
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
isrunning = false;
|
||||
}
|
||||
|
||||
void loop(void) {
|
||||
// flash LED rapidly to show main loop is still running
|
||||
if (millis() > led_time + 50) {
|
||||
digitalWrite(LED_BUILTIN, led_state);
|
||||
led_state = !led_state;
|
||||
led_time = millis();
|
||||
}
|
||||
|
||||
if (isrunning) {
|
||||
uvm32_run(&vmst, &evt, 0xFFFFFFFF); // num instructions before vm considered hung
|
||||
|
||||
switch(evt.typ) {
|
||||
case UVM32_EVT_END:
|
||||
isrunning = false;
|
||||
break;
|
||||
case UVM32_EVT_SYSCALL: // vm has paused to handle UVM32_SYSCALL
|
||||
switch(evt.data.syscall.code) {
|
||||
case UVM32_SYSCALL_YIELD:
|
||||
break;
|
||||
case UVM32_SYSCALL_PUTC:
|
||||
Serial.print((char)uvm32_getval(&vmst, &evt, ARG0));
|
||||
break;
|
||||
case UVM32_SYSCALL_PRINTLN: {
|
||||
const char *str = uvm32_getcstr(&vmst, &evt, ARG0);
|
||||
Serial.print(str);
|
||||
Serial.println("");
|
||||
} break;
|
||||
case UVM32_SYSCALL_PRINT: {
|
||||
const char *str = uvm32_getcstr(&vmst, &evt, ARG0);
|
||||
Serial.print(str);
|
||||
} break;
|
||||
case UVM32_SYSCALL_MILLIS: {
|
||||
uvm32_setval(&vmst, &evt, RET, millis());
|
||||
} break;
|
||||
default:
|
||||
Serial.print("Unhandled syscall: ");
|
||||
Serial.print(evt.data.syscall.code);
|
||||
Serial.println("");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case UVM32_EVT_ERR:
|
||||
Serial.print("Error: ");
|
||||
Serial.println(evt.data.err.errstr);
|
||||
isrunning = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
Serial.println("Running VM");
|
||||
// setup vm
|
||||
uvm32_init(&vmst);
|
||||
uvm32_load(&vmst, mandel, mandel_len);
|
||||
isrunning = true;
|
||||
}
|
||||
}
|
||||
8
hosts/host-mini/Makefile
Normal file
8
hosts/host-mini/Makefile
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
TOPDIR=../../
|
||||
|
||||
all:
|
||||
xxd -n mandel -i ${TOPDIR}/precompiled/mandel.bin | sed -e "s/unsigned char/const unsigned char/" > mandel.h
|
||||
gcc -Wall -DUVM32_MEMORY_SIZE=512 -O2 -I${TOPDIR}/uvm32 -I${TOPDIR}/common -o host-mini ${TOPDIR}/uvm32/uvm32.c host-mini.c
|
||||
|
||||
clean:
|
||||
rm -f host-mini
|
||||
48
hosts/host-mini/host-mini.c
Normal file
48
hosts/host-mini/host-mini.c
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "uvm32.h"
|
||||
#include "../common/uvm32_common_custom.h"
|
||||
#include "mandel.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
uvm32_state_t vmst;
|
||||
uvm32_evt_t evt;
|
||||
bool isrunning = true;
|
||||
|
||||
uvm32_init(&vmst);
|
||||
uvm32_load(&vmst, mandel, mandel_len);
|
||||
|
||||
while(isrunning) {
|
||||
uvm32_run(&vmst, &evt, 100); // num instructions before vm considered hung
|
||||
|
||||
switch(evt.typ) {
|
||||
case UVM32_EVT_END:
|
||||
isrunning = false;
|
||||
break;
|
||||
case UVM32_EVT_SYSCALL: // vm has paused to handle UVM32_SYSCALL
|
||||
switch(evt.data.syscall.code) {
|
||||
case UVM32_SYSCALL_YIELD:
|
||||
break;
|
||||
case UVM32_SYSCALL_PUTC:
|
||||
printf("%c", uvm32_getval(&vmst, &evt, ARG0));
|
||||
break;
|
||||
case UVM32_SYSCALL_PRINTLN: {
|
||||
const char *str = uvm32_getcstr(&vmst, &evt, ARG0);
|
||||
printf("%s\n", str);
|
||||
} break;
|
||||
default:
|
||||
printf("Unhandled syscall 0x%08x\n", evt.data.syscall.code);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case UVM32_EVT_ERR:
|
||||
printf("UVM32_EVT_ERR '%s' (%d)\n", evt.data.err.errstr, (int)evt.data.err.errcode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
28
hosts/host-mini/mandel.h
Normal file
28
hosts/host-mini/mandel.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
const unsigned char mandel[] = {
|
||||
0x17, 0x05, 0x00, 0x00, 0x13, 0x05, 0x05, 0x13, 0xb7, 0x08, 0x00, 0x01,
|
||||
0x93, 0x88, 0x28, 0x00, 0x73, 0x00, 0x00, 0x00, 0x23, 0x26, 0x11, 0x00,
|
||||
0xef, 0x00, 0xc0, 0x00, 0xb7, 0x08, 0x00, 0x01, 0x73, 0x00, 0x00, 0x00,
|
||||
0x13, 0x01, 0x01, 0xff, 0x23, 0x26, 0x81, 0x00, 0x37, 0xf5, 0xff, 0xff,
|
||||
0xb7, 0x15, 0x00, 0x00, 0x37, 0xe6, 0xff, 0xff, 0x13, 0x07, 0xf0, 0x01,
|
||||
0xb7, 0x47, 0x00, 0x00, 0xb7, 0x06, 0x00, 0x01, 0x13, 0x08, 0xd5, 0xcc,
|
||||
0x93, 0x82, 0x35, 0x33, 0x13, 0x03, 0x76, 0xe6, 0x93, 0x83, 0x35, 0xb3,
|
||||
0x13, 0x86, 0x16, 0x00, 0x63, 0xce, 0x02, 0x09, 0x13, 0x0e, 0x03, 0x00,
|
||||
0x63, 0xce, 0x63, 0x06, 0x93, 0x0f, 0x00, 0x00, 0x13, 0x0f, 0x00, 0x00,
|
||||
0x13, 0x04, 0x00, 0x00, 0x93, 0x0e, 0x00, 0x00, 0x93, 0x06, 0x00, 0x02,
|
||||
0x13, 0x85, 0x06, 0xfe, 0x63, 0x64, 0xa7, 0x04, 0x33, 0x05, 0xff, 0x01,
|
||||
0x63, 0xe0, 0xa7, 0x04, 0x13, 0x05, 0x00, 0x00, 0x93, 0x05, 0x00, 0x00,
|
||||
0x93, 0x08, 0x06, 0x00, 0xb3, 0x8e, 0x8e, 0x02, 0x33, 0x0f, 0xff, 0x41,
|
||||
0x13, 0xd4, 0xbe, 0x40, 0xb3, 0x0e, 0xcf, 0x01, 0x73, 0x00, 0x00, 0x00,
|
||||
0x33, 0x04, 0x04, 0x01, 0x33, 0x85, 0xde, 0x03, 0x13, 0x5f, 0xc5, 0x00,
|
||||
0x33, 0x05, 0x84, 0x02, 0x93, 0x5f, 0xc5, 0x00, 0x93, 0x86, 0x16, 0x00,
|
||||
0x6f, 0xf0, 0x9f, 0xfb, 0x13, 0x85, 0x06, 0x00, 0x93, 0x05, 0x00, 0x00,
|
||||
0x93, 0x08, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x13, 0x0e, 0x1e, 0x09,
|
||||
0xe3, 0xd6, 0xc3, 0xf9, 0x13, 0x05, 0xa0, 0x00, 0x93, 0x05, 0x00, 0x00,
|
||||
0x93, 0x08, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x13, 0x08, 0x98, 0x19,
|
||||
0xe3, 0xd6, 0x02, 0xf7, 0x37, 0x05, 0x00, 0x80, 0x13, 0x05, 0x05, 0x12,
|
||||
0x93, 0x08, 0x30, 0x00, 0x93, 0x05, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00,
|
||||
0x03, 0x24, 0xc1, 0x00, 0x13, 0x01, 0x01, 0x01, 0x67, 0x80, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x00
|
||||
};
|
||||
unsigned int mandel_len = 300;
|
||||
7
hosts/host-parallel/Makefile
Normal file
7
hosts/host-parallel/Makefile
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
TOPDIR = ../../
|
||||
all:
|
||||
xxd -n fib -i ${TOPDIR}/precompiled/fib.bin | sed -e "s/unsigned char/const unsigned char/" > fib.h
|
||||
gcc -Wall -DUVM32_MEMORY_SIZE=16386 -I${TOPDIR}/uvm32 -I${TOPDIR}/common -o host-parallel ${TOPDIR}/uvm32/uvm32.c host-parallel.c
|
||||
|
||||
clean:
|
||||
rm -f host-parallel
|
||||
70
hosts/host-parallel/host-parallel.c
Normal file
70
hosts/host-parallel/host-parallel.c
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "uvm32.h"
|
||||
#include "../common/uvm32_common_custom.h"
|
||||
|
||||
// Run multiple scheduled VMs in parallel until all have ended
|
||||
#define NUM_VM 4 // number of vms
|
||||
#define SCHEDULE SCHEDULE_RANDOM // scheduling algorithm
|
||||
|
||||
// scheduling algorithms
|
||||
#define SCHEDULE_ROUNDROBIN() scheduler_index = (scheduler_index + 1) % NUM_VM
|
||||
#define SCHEDULE_RANDOM() scheduler_index = rand()%NUM_VM
|
||||
|
||||
#include "fib.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
uvm32_state_t vmst[NUM_VM];
|
||||
uvm32_evt_t evt;
|
||||
int numVmRunning = NUM_VM;
|
||||
int scheduler_index = 0;
|
||||
|
||||
for (int i=0;i<NUM_VM;i++) {
|
||||
uvm32_init(&vmst[i]);
|
||||
uvm32_load(&vmst[i], fib, fib_len);
|
||||
}
|
||||
|
||||
while(numVmRunning > 0) {
|
||||
if (uvm32_hasEnded(&vmst[scheduler_index])) {
|
||||
// this vm has already completed, pick another
|
||||
SCHEDULE();
|
||||
continue;
|
||||
}
|
||||
uvm32_run(&vmst[scheduler_index], &evt, 100); // num instructions before vm considered hung
|
||||
|
||||
switch(evt.typ) {
|
||||
case UVM32_EVT_END:
|
||||
printf("[VM %d ended]\n", scheduler_index);
|
||||
numVmRunning--;
|
||||
break;
|
||||
case UVM32_EVT_SYSCALL: // vm has paused to handle UVM32_SYSCALL
|
||||
switch(evt.data.syscall.code) {
|
||||
case UVM32_SYSCALL_YIELD:
|
||||
break;
|
||||
case UVM32_SYSCALL_PRINTLN: {
|
||||
const char *str = uvm32_getcstr(&vmst[scheduler_index], &evt, ARG0);
|
||||
if (str[0] != 0) {
|
||||
printf("[VM %d] %s\n", scheduler_index, str);
|
||||
}
|
||||
} break;
|
||||
case UVM32_SYSCALL_PRINTDEC:
|
||||
printf("[VM %d] %d\n", scheduler_index, uvm32_getval(&vmst[scheduler_index], &evt, ARG0));
|
||||
break;
|
||||
default:
|
||||
printf("Unhandled syscall 0x%08x\n", evt.data.syscall.code);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case UVM32_EVT_ERR:
|
||||
printf("UVM32_EVT_ERR '%s' (%d)\n", evt.data.err.errstr, (int)evt.data.err.errcode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
SCHEDULE();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
7
hosts/host/Makefile
Normal file
7
hosts/host/Makefile
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
TOPDIR=../../
|
||||
|
||||
all:
|
||||
gcc -Wall -Werror -pedantic -std=c99 -O2 -DUVM32_MEMORY_SIZE=65536 -I${TOPDIR}/uvm32 -I${TOPDIR}/common -o host ${TOPDIR}/uvm32/uvm32.c host.c
|
||||
|
||||
clean:
|
||||
rm -f host
|
||||
261
hosts/host/host.c
Normal file
261
hosts/host/host.c
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <signal.h>
|
||||
#include "uvm32.h"
|
||||
|
||||
#include "../common/uvm32_common_custom.h"
|
||||
|
||||
// stash terminal settings on startup
|
||||
static struct termios orig_termios;
|
||||
|
||||
void disableRawMode(void) {
|
||||
tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios);
|
||||
printf("\033[?25h"); // show cursor
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void cleanexit(int sig) {
|
||||
disableRawMode();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void enableRawMode(void) {
|
||||
tcgetattr(STDIN_FILENO, &orig_termios);
|
||||
atexit(disableRawMode);
|
||||
signal(SIGINT, cleanexit);
|
||||
struct termios raw = orig_termios;
|
||||
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN);
|
||||
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
||||
raw.c_cflag |= (CS8);
|
||||
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
|
||||
raw.c_cc[VMIN] = 0;
|
||||
raw.c_cc[VTIME] = 1;
|
||||
}
|
||||
|
||||
static uint8_t *read_file(const char* filename, int *len) {
|
||||
FILE* f = fopen(filename, "rb");
|
||||
uint8_t *buf = NULL;
|
||||
|
||||
if (f == NULL) {
|
||||
fprintf(stderr, "error: can't open file '%s'.\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t file_size = ftell(f);
|
||||
rewind(f);
|
||||
|
||||
if (NULL == (buf = malloc(file_size))) {
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t result = fread(buf, sizeof(uint8_t), file_size, f);
|
||||
if (result != file_size) {
|
||||
fprintf(stderr, "error: while reading file '%s'\n", filename);
|
||||
free(buf);
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
*len = file_size;
|
||||
return buf;
|
||||
}
|
||||
|
||||
// Poll for input, inelegant, but works and doesn't confuse the main
|
||||
// flow of the program with select/poll
|
||||
bool poll_getch(uint8_t* c) {
|
||||
struct timeval tv;
|
||||
fd_set readfds;
|
||||
int ret;
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(STDIN_FILENO, &readfds);
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
ret = select(STDIN_FILENO + 1, &readfds, NULL, NULL, &tv);
|
||||
|
||||
if (ret == -1) {
|
||||
printf("console read failed\r\n");
|
||||
exit(1);
|
||||
} else if (!ret) {
|
||||
// timeout
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FD_ISSET(STDIN_FILENO, &readfds)) {
|
||||
int len;
|
||||
|
||||
len = read(STDIN_FILENO, c, 1);
|
||||
if (len == -1) {
|
||||
printf("console read failed\r\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (len) {
|
||||
if (*c == 0x03 || *c == 0x04) { // ctrl-c ctrl-d
|
||||
disableRawMode();
|
||||
exit(0);
|
||||
}
|
||||
if (*c == 0x0d) {
|
||||
*c = '\n';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void hexdump(const uint8_t *p, int len) {
|
||||
while(len--) {
|
||||
printf("%02x", *p++);
|
||||
}
|
||||
}
|
||||
|
||||
bool memdump(const char *filename, const uint8_t *buf, int len) {
|
||||
FILE* f = fopen(filename, "wb");
|
||||
|
||||
if (f == NULL) {
|
||||
fprintf(stderr, "error: can't open file '%s'.\n", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t result = fwrite(buf, sizeof(uint8_t), len, f);
|
||||
if (result != len) {
|
||||
fprintf(stderr, "error: while writing file '%s'\n", filename);
|
||||
return false;
|
||||
}
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
uvm32_state_t vmst;
|
||||
uint32_t max_instrs_per_run = 500000;
|
||||
clock_t start_time = clock() / (CLOCKS_PER_SEC / 1000);
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (argc < 1) {
|
||||
printf("<romfile> [max_instrs_per_run]\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc > 1) {
|
||||
max_instrs_per_run = strtoll(argv[1], NULL, 10);
|
||||
}
|
||||
|
||||
int romlen = 0;
|
||||
uint8_t *rom = read_file(argv[0], &romlen);
|
||||
if (NULL == rom) {
|
||||
printf("file read failed!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
uvm32_init(&vmst);
|
||||
|
||||
if (!uvm32_load(&vmst, rom, romlen)) {
|
||||
printf("load failed!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
uvm32_evt_t evt;
|
||||
bool isrunning = true;
|
||||
uint32_t total_instrs = 0;
|
||||
uint32_t num_syscalls = 0;
|
||||
|
||||
// setup terminal for getch()
|
||||
enableRawMode();
|
||||
|
||||
while(isrunning) {
|
||||
total_instrs += uvm32_run(&vmst, &evt, max_instrs_per_run); // num instructions before vm considered hung
|
||||
num_syscalls++;
|
||||
|
||||
switch(evt.typ) {
|
||||
case UVM32_EVT_END:
|
||||
printf("UVM32_EVT_END\n");
|
||||
isrunning = false;
|
||||
break;
|
||||
case UVM32_EVT_ERR:
|
||||
printf("UVM32_EVT_ERR '%s' (%d)\n", evt.data.err.errstr, (int)evt.data.err.errcode);
|
||||
if (evt.data.err.errcode == UVM32_ERR_HUNG) {
|
||||
printf("VM may have hung, increase max_instrs_per_run\n");
|
||||
uvm32_clearError(&vmst); // allow to continue
|
||||
} else {
|
||||
isrunning = false;
|
||||
memdump("host-ram.dump", vmst.memory, UVM32_MEMORY_SIZE);
|
||||
printf("memory dumped to host-ram.dump, pc=0x%08x\n", vmst.core.pc);
|
||||
}
|
||||
break;
|
||||
case UVM32_EVT_SYSCALL:
|
||||
switch(evt.data.syscall.code) {
|
||||
case UVM32_SYSCALL_PRINTBUF: {
|
||||
uvm32_evt_syscall_buf_t buf = uvm32_getbuf(&vmst, &evt, ARG0, ARG1);
|
||||
while(buf.len--) {
|
||||
printf("%02x", *buf.ptr++);
|
||||
}
|
||||
} break;
|
||||
case UVM32_SYSCALL_YIELD: {
|
||||
// uint32_t yield_typ = uvm32_getval(&vmst, &evt, ARG0);
|
||||
// printf("YIELD type=%d\n", yield_typ);
|
||||
// uvm32_setval(&vmst, &evt, RET, 123);
|
||||
} break;
|
||||
case UVM32_SYSCALL_PRINT: {
|
||||
const char *str = uvm32_getcstr(&vmst, &evt, ARG0);
|
||||
printf("%s", str);
|
||||
} break;
|
||||
case UVM32_SYSCALL_PRINTLN: {
|
||||
const char *str = uvm32_getcstr(&vmst, &evt, ARG0);
|
||||
printf("%s\n", str);
|
||||
} break;
|
||||
case UVM32_SYSCALL_PRINTDEC:
|
||||
printf("%d", uvm32_getval(&vmst, &evt, ARG0));
|
||||
break;
|
||||
case UVM32_SYSCALL_PUTC:
|
||||
printf("%c", uvm32_getval(&vmst, &evt, ARG0));
|
||||
break;
|
||||
case UVM32_SYSCALL_PRINTHEX:
|
||||
printf("%08x", uvm32_getval(&vmst, &evt, ARG0));
|
||||
break;
|
||||
case UVM32_SYSCALL_MILLIS: {
|
||||
clock_t now = clock() / (CLOCKS_PER_SEC / 1000);
|
||||
uvm32_setval(&vmst, &evt, RET, now - start_time);
|
||||
} break;
|
||||
case UVM32_SYSCALL_GETC: {
|
||||
uint8_t c;
|
||||
if (poll_getch(&c)) {
|
||||
uvm32_setval(&vmst, &evt, RET, c);
|
||||
} else {
|
||||
uvm32_setval(&vmst, &evt, RET, 0xFFFFFFFF);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
printf("Unhandled syscall 0x%08x\n", evt.data.syscall.code);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Bad evt %d\n", evt.typ);
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
printf("Executed total of %d instructions and %d syscalls\n", (int)total_instrs, (int)num_syscalls);
|
||||
|
||||
free(rom);
|
||||
|
||||
// put terminal back to how it was
|
||||
disableRawMode();
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue