Skip to content

Commit b787dc2

Browse files
authored
Merge pull request #340 from ChinYikMing/refine-vm-API
Refine the API in the public header
2 parents d877c20 + 820cd9b commit b787dc2

File tree

14 files changed

+391
-235
lines changed

14 files changed

+391
-235
lines changed

Makefile

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@ CFLAGS = -std=gnu99 -O2 -Wall -Wextra
1111
CFLAGS += -Wno-unused-label
1212
CFLAGS += -include src/common.h
1313

14-
# Set the default stack pointer
15-
CFLAGS += -D DEFAULT_STACK_ADDR=0xFFFFE000
16-
# Set the default args starting address
17-
CFLAGS += -D DEFAULT_ARGS_ADDR=0xFFFFF000
18-
1914
# Enable link-time optimization (LTO)
2015
ENABLE_LTO ?= 1
2116
ifeq ($(call has, LTO), 1)
@@ -121,7 +116,7 @@ endif
121116
ENABLE_JIT ?= 0
122117
$(call set-feature, JIT)
123118
ifeq ($(call has, JIT), 1)
124-
OBJS_EXT += jit.o
119+
OBJS_EXT += jit.o
125120
ifneq ($(processor),$(filter $(processor),x86_64 aarch64 arm64))
126121
$(error JIT mode only supports for x64 and arm64 target currently.)
127122
endif

src/elf.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -259,12 +259,8 @@ bool elf_get_data_section_range(elf_t *e, uint32_t *start, uint32_t *end)
259259
* Finding data for section headers:
260260
* File start + section_header.offset -> section Data
261261
*/
262-
bool elf_load(elf_t *e, riscv_t *rv, memory_t *mem)
262+
bool elf_load(elf_t *e, memory_t *mem)
263263
{
264-
/* set the entry point */
265-
if (!rv_set_pc(rv, e->hdr->e_entry))
266-
return false;
267-
268264
/* loop over all of the program headers */
269265
for (int p = 0; p < e->hdr->e_phnum; ++p) {
270266
/* find next program header */

src/elf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ const char *elf_find_symbol(elf_t *e, uint32_t addr);
145145
bool elf_get_data_section_range(elf_t *e, uint32_t *start, uint32_t *end);
146146

147147
/* Load the ELF file into a memory abstraction */
148-
bool elf_load(elf_t *e, riscv_t *rv, memory_t *mem);
148+
bool elf_load(elf_t *e, memory_t *mem);
149149

150150
/* get the ELF header */
151151
struct Elf32_Ehdr *get_elf_header(elf_t *e);

src/emulate.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ RV_EXCEPTION_LIST
125125
*/
126126
#define RV_EXC_MISALIGN_HANDLER(mask_or_pc, type, compress, IO) \
127127
IIF(IO) \
128-
(if (!rv->io.allow_misalign && unlikely(addr & (mask_or_pc))), \
128+
(if (!PRIV(rv)->allow_misalign && unlikely(addr & (mask_or_pc))), \
129129
if (unlikely(insn_is_misaligned(PC)))) \
130130
{ \
131131
rv->compressed = compress; \
@@ -1182,15 +1182,15 @@ void ecall_handler(riscv_t *rv)
11821182

11831183
void memset_handler(riscv_t *rv)
11841184
{
1185-
memory_t *m = ((state_t *) rv->userdata)->mem;
1185+
memory_t *m = PRIV(rv)->mem;
11861186
memset((char *) m->mem_base + rv->X[rv_reg_a0], rv->X[rv_reg_a1],
11871187
rv->X[rv_reg_a2]);
11881188
rv->PC = rv->X[rv_reg_ra] & ~1U;
11891189
}
11901190

11911191
void memcpy_handler(riscv_t *rv)
11921192
{
1193-
memory_t *m = ((state_t *) rv->userdata)->mem;
1193+
memory_t *m = PRIV(rv)->mem;
11941194
memcpy((char *) m->mem_base + rv->X[rv_reg_a0],
11951195
(char *) m->mem_base + rv->X[rv_reg_a1], rv->X[rv_reg_a2]);
11961196
rv->PC = rv->X[rv_reg_ra] & ~1U;

src/io.c

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,44 +17,36 @@
1717

1818
static uint8_t *data_memory_base;
1919

20-
/*
21-
* set memory size to 2^32 - 1 bytes
22-
*
23-
* The memory size is set to 2^32 - 1 bytes in order to make this emulator
24-
* portable for both 32-bit and 64-bit platforms. As a result, it can access
25-
* any segment of the memory on either platform. Furthermore, it is safe
26-
* because most of the test cases' data memory usage will not exceed this
27-
* memory size.
28-
*/
29-
#define MEM_SIZE 0xFFFFFFFFULL
30-
31-
memory_t *memory_new(void)
20+
memory_t *memory_new(uint32_t size)
3221
{
22+
if (!size)
23+
return NULL;
24+
3325
memory_t *mem = malloc(sizeof(memory_t));
3426
assert(mem);
3527
#if HAVE_MMAP
36-
data_memory_base = mmap(NULL, MEM_SIZE, PROT_READ | PROT_WRITE,
28+
data_memory_base = mmap(NULL, size, PROT_READ | PROT_WRITE,
3729
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
3830
if (data_memory_base == MAP_FAILED) {
3931
free(mem);
4032
return NULL;
4133
}
4234
#else
43-
data_memory_base = malloc(MEM_SIZE);
35+
data_memory_base = malloc(size);
4436
if (!data_memory_base) {
4537
free(mem);
4638
return NULL;
4739
}
4840
#endif
4941
mem->mem_base = data_memory_base;
50-
mem->mem_size = MEM_SIZE;
42+
mem->mem_size = size;
5143
return mem;
5244
}
5345

5446
void memory_delete(memory_t *mem)
5547
{
5648
#if HAVE_MMAP
57-
munmap(mem->mem_base, MEM_SIZE);
49+
munmap(mem->mem_base, mem->mem_size);
5850
#else
5951
free(mem->mem_base);
6052
#endif

src/io.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ typedef struct {
1717
uint64_t mem_size;
1818
} memory_t;
1919

20-
memory_t *memory_new(void);
20+
memory_t *memory_new(uint32_t size);
2121
void memory_delete(memory_t *m);
2222

2323
/* read a C-style string from memory */

src/jit.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "io.h"
4040
#include "jit.h"
4141
#include "riscv.h"
42+
#include "riscv_private.h"
4243
#include "utils.h"
4344

4445
#define JIT_CLS_MASK 0x07
@@ -1284,7 +1285,7 @@ static void do_fuse2(struct jit_state *state, riscv_t *rv UNUSED, rv_insn_t *ir)
12841285

12851286
static void do_fuse3(struct jit_state *state, riscv_t *rv, rv_insn_t *ir)
12861287
{
1287-
memory_t *m = ((state_t *) rv->userdata)->mem;
1288+
memory_t *m = PRIV(rv)->mem;
12881289
opcode_fuse_t *fuse = ir->fuse;
12891290
for (int i = 0; i < ir->imm2; i++) {
12901291
emit_load(state, S32, parameter_reg[0], temp_reg[0],
@@ -1300,7 +1301,7 @@ static void do_fuse3(struct jit_state *state, riscv_t *rv, rv_insn_t *ir)
13001301

13011302
static void do_fuse4(struct jit_state *state, riscv_t *rv, rv_insn_t *ir)
13021303
{
1303-
memory_t *m = ((state_t *) rv->userdata)->mem;
1304+
memory_t *m = PRIV(rv)->mem;
13041305
opcode_fuse_t *fuse = ir->fuse;
13051306
for (int i = 0; i < ir->imm2; i++) {
13061307
emit_load(state, S32, parameter_reg[0], temp_reg[0],

src/main.c

Lines changed: 36 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -74,35 +74,10 @@ IO_HANDLER_IMPL(byte, write_b, W)
7474
#undef R
7575
#undef W
7676

77-
/* run: printing out an instruction trace */
78-
static void run_and_trace(riscv_t *rv, elf_t *elf)
79-
{
80-
const uint32_t cycles_per_step = 1;
81-
82-
for (; !rv_has_halted(rv);) { /* run until the flag is done */
83-
/* trace execution */
84-
uint32_t pc = rv_get_pc(rv);
85-
const char *sym = elf_find_symbol(elf, pc);
86-
printf("%08x %s\n", pc, (sym ? sym : ""));
87-
88-
/* step instructions */
89-
rv_step(rv, cycles_per_step);
90-
}
91-
}
92-
93-
static void run(riscv_t *rv)
94-
{
95-
const uint32_t cycles_per_step = 100;
96-
for (; !rv_has_halted(rv);) { /* run until the flag is done */
97-
/* step instructions */
98-
rv_step(rv, cycles_per_step);
99-
}
100-
}
101-
10277
static void print_usage(const char *filename)
10378
{
10479
fprintf(stderr,
105-
"RV32I[MA] Emulator which loads an ELF file to execute.\n"
80+
"RV32I[MACF] Emulator which loads an ELF file to execute.\n"
10681
"Usage: %s [options] [filename] [arguments]\n"
10782
"Options:\n"
10883
" -t : print executable trace\n"
@@ -188,8 +163,11 @@ static bool parse_args(int argc, char **args)
188163
return true;
189164
}
190165

191-
static void dump_test_signature(elf_t *elf)
166+
static void dump_test_signature(const char *prog_name)
192167
{
168+
elf_t *elf = elf_new();
169+
assert(elf && elf_open(elf, prog_name));
170+
193171
uint32_t start = 0, end = 0;
194172
const struct Elf32_Sym *sym;
195173
FILE *f = fopen(signature_out_file, "w");
@@ -212,21 +190,42 @@ static void dump_test_signature(elf_t *elf)
212190
fprintf(f, "%08x\n", memory_read_w(addr));
213191

214192
fclose(f);
193+
elf_delete(elf);
215194
}
216195

196+
#define MEM_SIZE 0xFFFFFFFFULL /* 2^32 - 1 */
197+
#define STACK_SIZE 0x1000 /* 4096 */
198+
#define ARGS_OFFSET_SIZE 0x1000 /* 4096 */
199+
217200
int main(int argc, char **args)
218201
{
219202
if (argc == 1 || !parse_args(argc, args)) {
220203
print_usage(args[0]);
221204
return 1;
222205
}
223206

224-
/* open the ELF file from the file system */
225-
elf_t *elf = elf_new();
226-
if (!elf_open(elf, opt_prog_name)) {
227-
fprintf(stderr, "Unable to open ELF file '%s'\n", opt_prog_name);
228-
return 1;
229-
}
207+
int run_flag = 0;
208+
run_flag |= opt_trace;
209+
#if RV32_HAS(GDBSTUB)
210+
run_flag |= opt_gdbstub << 1;
211+
#endif
212+
run_flag |= opt_prof_data << 2;
213+
214+
vm_attr_t attr = {
215+
.mem_size = MEM_SIZE,
216+
.stack_size = STACK_SIZE,
217+
.args_offset_size = ARGS_OFFSET_SIZE,
218+
.argc = prog_argc,
219+
.argv = prog_args,
220+
.log_level = 0,
221+
.run_flag = run_flag,
222+
.profile_output_file = prof_out_file,
223+
.data.user = malloc(sizeof(vm_user_t)),
224+
.cycle_per_step = 100,
225+
.allow_misalign = opt_misaligned,
226+
};
227+
assert(attr.data.user);
228+
attr.data.user->elf_program = opt_prog_name;
230229

231230
/* install the I/O handlers for the RISC-V runtime */
232231
const riscv_io_t io = {
@@ -246,57 +245,28 @@ int main(int argc, char **args)
246245
.on_ebreak = ebreak_handler,
247246
.on_memcpy = memcpy_handler,
248247
.on_memset = memset_handler,
249-
.allow_misalign = opt_misaligned,
250248
};
251249

252-
state_t *state = state_new();
253-
254-
/* find the start of the heap */
255-
const struct Elf32_Sym *end;
256-
if ((end = elf_get_symbol(elf, "_end")))
257-
state->break_addr = end->st_value;
258-
259250
/* create the RISC-V runtime */
260-
riscv_t *rv =
261-
rv_create(&io, state, prog_argc, prog_args, !opt_quiet_outputs);
251+
riscv_t *rv = rv_create(&io, &attr);
262252
if (!rv) {
263253
fprintf(stderr, "Unable to create riscv emulator\n");
264254
return 1;
265255
}
266256

267-
/* load the ELF file into the memory abstraction */
268-
if (!elf_load(elf, rv, state->mem)) {
269-
fprintf(stderr, "Unable to load ELF file '%s'\n", args[1]);
270-
return 1;
271-
}
272-
273-
/* run based on the specified mode */
274-
if (opt_trace) {
275-
run_and_trace(rv, elf);
276-
}
277-
#if RV32_HAS(GDBSTUB)
278-
else if (opt_gdbstub) {
279-
rv_debug(rv);
280-
}
281-
#endif
282-
else {
283-
run(rv);
284-
}
257+
rv_run(rv);
285258

286259
/* dump registers as JSON */
287260
if (opt_dump_regs)
288261
dump_registers(rv, registers_out_file);
289262

290263
/* dump test result in test mode */
291264
if (opt_arch_test)
292-
dump_test_signature(elf);
265+
dump_test_signature(opt_prog_name);
293266

294-
if (opt_prof_data)
295-
rv_profile(rv, prof_out_file);
296267
/* finalize the RISC-V runtime */
297-
elf_delete(elf);
298268
rv_delete(rv);
299-
state_delete(state);
300269

270+
printf("inferior exit code %d\n", attr.exit_code);
301271
return 0;
302272
}

0 commit comments

Comments
 (0)