diff --git a/.gitignore b/.gitignore index 183b4be..4b06092 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ lib imgui.ini .DS_Store roms +examples/*.bin diff --git a/examples/make.sh b/examples/make.sh new file mode 100755 index 0000000..476594c --- /dev/null +++ b/examples/make.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +for src_file in *.asm; do + [ -e "$src_file" ] || continue + + + obj_file="$(basename "$src_file" .asm).obj" + bin_file="$(basename "$src_file" .asm).bin" + echo "$src_file -> $bin_file" + + rgbasm -o $obj_file $src_file + rgblink --nopad -o $bin_file $obj_file +done + +rm -f *.obj \ No newline at end of file diff --git a/examples/simple.asm b/examples/simple.asm new file mode 100644 index 0000000..236fe2b --- /dev/null +++ b/examples/simple.asm @@ -0,0 +1,23 @@ +section "main", rom0 + + nop + ld b, $0 + ld c, $11 + ld d, $22 + ld e, $33 + ld h, $44 + ld l, $55 + ld [hl], $66 + ld a, $77 + ld bc, $0123 + ld de, $4567 + ld hl, $89ab + ld sp, $cdef +simple_loop: + dec a + jr nz, simple_loop + +end: + jr end + +db $fd \ No newline at end of file diff --git a/src/compiler68k.c b/src/compiler68k.c index 8fa0f44..78604ff 100644 --- a/src/compiler68k.c +++ b/src/compiler68k.c @@ -1,6 +1,8 @@ #include #include #include +#include +#include // A -> D0 // BC -> D1 @@ -47,15 +49,40 @@ struct basic_block *compile_block(uint16_t src_address, uint8_t *gb_code) struct basic_block *bblock; uint32_t dst_ptr = 0; uint16_t src_ptr = 0; + int ret; + + printf("compile block starting at 0x%04x\n", src_address); bblock = malloc(sizeof *bblock); + + // for testing... + ret = mprotect( + (void *) ((uint64_t) bblock & 0xfffffffffffff000L), + 4096, + PROT_READ | PROT_WRITE | PROT_EXEC + ); + if (ret == -1) { + perror("mprotect"); + exit(0); + } // bblock->code = out_code + start; while (1) { instruction = gb_code[src_ptr++]; - + if (instruction == 0xfd) { + // invalid opcode for testing + break; + } } + bblock->length = 6; + bblock->code[0] = 0xb8; // mov eax, 1234h + bblock->code[1] = 0x34; + bblock->code[2] = 0x12; + bblock->code[3] = 0x00; + bblock->code[4] = 0x00; + bblock->code[5] = 0xc3; // ret + return bblock; } @@ -66,30 +93,63 @@ void run_block(struct basic_block *bblock) } // TODO -void block_cache_add(uint16_t src_address, struct basic_block *bblock); -struct basic_block *block_cache_get(uint16_t src_address); +void block_cache_add(uint16_t src_address, struct basic_block *bblock) +{ + // no-op +} + +struct basic_block *block_cache_get(uint16_t src_address) +{ + return NULL; +} // 1. compile each block ending in a jump // 2. turn the jump into a return // 3. add the compiled code to some kind of cache // 3. return back to check the cache and maybe compile the next block -int main(int argc, char *argv[]) +void run_all(uint8_t *gb_code) { struct basic_block *bblock; - - bblock = compile_block(0, test_code); - block_cache_add(0, bblock); + uint16_t jump_target = 0; while (1) { - uint16_t jump_target; - - jump_target = ((uint16_t (*)()) bblock->code)(); - bblock = block_cache_get(jump_target); if (!bblock) { - bblock = compile_block(jump_target, test_code + jump_target); + bblock = compile_block(jump_target, gb_code + jump_target); + if (bblock->length == 0) { + break; + } + block_cache_add(jump_target, bblock); } + + jump_target = ((uint16_t (*)()) bblock->code)(); } +} + +int main(int argc, char *argv[]) +{ + FILE *fp; + long len; + uint8_t *data; + + if (argc < 2) { + data = test_code; + } else { + fp = fopen(argv[1], "r"); + fseek(fp, 0, SEEK_END); + len = ftell(fp); + rewind(fp); + data = malloc(len); + fread(data, 1, len, fp); + fclose(fp); + } + + run_all(data); + + if (data != test_code) { + free(data); + } + return 0; } \ No newline at end of file