diff options
author | dweller <dweller@cabin.digital> | 2025-03-26 18:25:34 +0200 |
---|---|---|
committer | dweller <dweller@cabin.digital> | 2025-03-26 18:25:34 +0200 |
commit | 42e9b31e0d7324106a65ad9ff42ea2377a80fa51 (patch) | |
tree | ceee87f9e0067b6d5c71f5e728fe0b3fd0fd8b72 | |
parent | 76d89eb9973671726dc7fffaf22b06a7a77be550 (diff) |
fix disasm not showing instruction hex; implement a few instructions exec; add report logger
-rwxr-xr-x | build/x11 | 2 | ||||
-rw-r--r-- | sources/instr.c | 8 | ||||
-rw-r--r-- | sources/log.c | 40 | ||||
-rw-r--r-- | sources/main.c | 230 | ||||
-rw-r--r-- | sources/meta/disasm.c | 72 | ||||
-rw-r--r-- | sources/meta/exec.c | 82 |
6 files changed, 204 insertions, 230 deletions
@@ -10,5 +10,5 @@ bench() fi } ->&2 bench cc -std=c89 -Wall -Wextra sources/main.c -static -o artifacts/xip-8 +>&2 bench cc -std=c89 -Wall -Wextra -Wno-comment sources/main.c -static -o artifacts/xip-8 >&2 echo "------------------------------------------------\n" diff --git a/sources/instr.c b/sources/instr.c index 8c0b132..72511f1 100644 --- a/sources/instr.c +++ b/sources/instr.c @@ -61,6 +61,13 @@ void c8_##name(u8* code, u16 offset, void* usrdat) \ n = (instr & 0x000F); \ kk = (instr & 0x00FF); \ \ + (void)o; \ + (void)nnn; \ + (void)x; \ + (void)y; \ + (void)n; \ + (void)kk; \ + \ if(o == 0 && nnn == 0x0E0) X_C8_CLS; \ else if(o == 0 && nnn == 0x0EE) X_C8_RET; \ else if(o == 0) X_C8_SYS; \ @@ -100,3 +107,4 @@ void c8_##name(u8* code, u16 offset, void* usrdat) \ } #include "meta/disasm.c" +#include "meta/exec.c" diff --git a/sources/log.c b/sources/log.c new file mode 100644 index 0000000..ba0aa86 --- /dev/null +++ b/sources/log.c @@ -0,0 +1,40 @@ +typedef enum log_kind +{ + LK_DEBUG, + LK_INFO, + LK_WARN, + LK_ERROR, + LK_FATAL, + + LK_ENUM_LEN + +} log_kind; + +static char* log_kind_names[LK_ENUM_LEN] = +{ + "DEBUG", + "INFO", + "WARN", + "ERROR", + "FATAL", +}; + +#define DBG LK_DEBUG, __FILE__, __LINE__ +#define INFO LK_INFO, __FILE__, __LINE__ +#define WARN LK_WARN, __FILE__, __LINE__ +#define ERR LK_ERROR, __FILE__, __LINE__ +#define FATAL LK_FATAL, __FILE__, __LINE__ + +void report(log_kind kind, const char* file, int line, const char* fmt, ...) +{ + va_list ap; + + /* TODO: log levels */ + + printf("[%s] %s:%d - ", log_kind_names[kind], file, line); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + + if(kind == LK_FATAL) abort(); +} diff --git a/sources/main.c b/sources/main.c index 56630df..8c4ac97 100644 --- a/sources/main.c +++ b/sources/main.c @@ -4,11 +4,13 @@ #include <string.h> #include <assert.h> #include <time.h> +#include <stdarg.h> #include <endian.h> #include "bits.c" #include "fnt.c" +#include "log.c" #define C8_RESET_VECTOR 0x200 @@ -46,14 +48,13 @@ typedef struct } chip8; -#include "instr.c" - #define V mem.sys.v #define STACK mem.sys.stack #define DISPLAY mem.sys.disp #define FONT mem.sys.font #define RAM mem.ram +#include "instr.c" void c8_reset(chip8* c8) { @@ -64,6 +65,7 @@ void c8_reset(chip8* c8) memcpy(c8->FONT, fnt, sizeof(fnt)); c8->pc = C8_RESET_VECTOR; + c8->running = true; } void c8_dump_state(chip8* c8, bool stack) @@ -91,197 +93,6 @@ void c8_dump_state(chip8* c8, bool stack) } } -void _c8_loop(chip8* c8, bool disasm, u16 from, u16 len) -{ - u16 to = 0; - u16 pc = 0; - - assert(c8); - - if(disasm) - { - pc = c8->pc; - c8->pc = from; - to = from + len*2; - } - - c8->running = true; - while(c8->running) - { - int tmp; - u16 word, instr, nnn; - u8 o, x, y, n, kk; - - if(c8->pc >= sizeof(c8->mem)) - { - printf("PC Overflow!\n"); - c8->running = false; - break; - } - - if(c8->pc & 0x0001) - { - printf("PC is not aligned!\n"); - c8->running = false; - break; - } - - word = *(u16*)(c8->RAM + c8->pc); - instr = be16toh(word); - o = (instr & 0xF000) >> 12; - nnn = (instr & 0x0FFF); - x = (instr & 0x0F00) >> 8; - y = (instr & 0x00F0) >> 4; - n = (instr & 0x000F); - kk = (instr & 0x00FF); - - printf("%04X: ", c8->pc); - switch(o) - { - case 1: - printf(" %04X JP 0x%03X\n", instr, nnn); - if(disasm) break; - c8->pc = nnn - 2; - break; - - case 2: - printf(" %04X CALL 0x%03X\n", instr, nnn); - if(disasm) break; - c8->STACK[c8->sp++] = c8->pc; /* docs says ++sp then stack[sp] = pc ??? */ - c8->pc = nnn - 2; - break; - - case 3: - printf(" %04X SE V%x, 0x%02X\n", instr, x, kk); - if(disasm) break; - if(c8->V[x] == kk) c8->pc += 2; - break; - - case 5: - printf(" %04X SE V%x, V%x\n", instr, x, y); - if(disasm) break; - if(c8->V[x] == c8->V[y]) c8->pc += 2; - break; - - case 6: - printf(" %04X LD V%x, 0x%02X\n", instr, x, kk); - if(disasm) break; - c8->V[x] = kk; - break; - - case 7: - printf(" %04X ADD V%x, 0x%02X\n", instr, x, kk); - if(disasm) break; - tmp = (int)c8->V[x] + (int)kk; - c8->V[0xf] = (tmp > 255); - /* c8->V[x] = (u8)tmp; /* spec says Vf not set */ - break; - - case 8: - { - switch(n) - { - case 4: - printf(" %04X ADD V%x, V%x\n", instr, x, y); - if(disasm) break; - tmp = (int)c8->V[x] + (int)c8->V[y]; - c8->V[0xf] = (tmp > 255); - c8->V[x] = (u8)tmp; - break; - - default: - printf(" %04X Unknown instruction\n", instr); - if(disasm) break; - c8->running = false; - break; - } - } - break; - - case 0xA: - printf(" %04X LD I, 0x%03X\n", instr, nnn); - if(disasm) break; - c8->i = nnn; - break; - - case 0xC: - printf(" %04X RND V%x, 0x%02X\n", instr, x, kk); - if(disasm) break; - c8->V[x] = (rand() % 256) & kk; - break; - - case 0xD: - printf(" %04X DRW V%x, V%x, %d\n", instr, x, y, n); - if(disasm) break; - /* TODO: implement */ - break; - - case 0xE: - if(kk == 0x9E) - { - printf(" %04X SKP V%x\n", instr, x); - if(disasm) break; - if(c8->keys & bit(x)) c8->pc += 2; - } - else if(kk == 0xA1) - { - printf(" %04X SKNP V%x\n", instr, x); - if(disasm) break; - if(!(c8->keys & bit(x))) c8->pc += 2; - } - else - { - printf(" %04X Unknown instruction\n", instr); - if(disasm) break; - c8->running = false; - } - break; - - case 0xF: - if(kk == 0x07) - { - printf(" %04X LD V%x, DT\n", instr, x); - if(disasm) break; - c8->V[x] = c8->dt; - } - else if(kk == 0x15) - { - printf(" %04X LD DT, V%x\n", instr, x); - if(disasm) break; - c8->dt= c8->V[x]; - } - else - { - printf(" %04X Unknown instruction\n", instr); - if(disasm) break; - c8->running = false; - } - break; - - default: - printf(" %04X Unknown instruction\n", instr); - if(disasm) break; - c8->running = false; - break; - } - - if(!disasm) c8_dump_state(c8, false); - - c8->pc += 2; - c8->cycles++; - if((c8->cycles % C8_CYCLES_PER_FRAME) == 0) - { - if(c8->dt) c8->dt--; - if(c8->st) c8->st--; - } - - if(disasm && (c8->pc >= to)) c8->running = false; - } - - if(disasm) c8->pc = pc; -} - - int main(int argc, char** argv) { u64 sz = 0; @@ -346,5 +157,38 @@ int main(int argc, char** argv) } } + printf("\nExec:\n"); + while(c8.running) + { + char buf[512] = {0}; + + if(c8.pc >= sizeof(c8.mem)) + { + report(ERR, "PC Overflow!\n"); + c8.running = false; + } + + if(c8.pc & 0x0001) + { + report(ERR, "PC is not aligned!\n"); + c8.running = false; + } + + c8_disasm(c8.RAM, c8.pc, buf); + printf("%04X: %s\n", c8.pc, buf); + + c8_exec(c8.RAM, c8.pc, &c8); + c8_dump_state(&c8, false); + + c8.cycles++; + if((c8.cycles % C8_CYCLES_PER_FRAME) == 0) + { + if(c8.dt) c8.dt--; + if(c8.st) c8.st--; + } + + c8.pc += 2; + } + return 0; } diff --git a/sources/meta/disasm.c b/sources/meta/disasm.c index 2a33aed..66c1478 100644 --- a/sources/meta/disasm.c +++ b/sources/meta/disasm.c @@ -1,39 +1,39 @@ -#define X_C8_ILL sprintf(usrdat, "ILL unknown") -#define X_C8_CLS sprintf(usrdat, "CLS") -#define X_C8_RET sprintf(usrdat, "RET") -#define X_C8_SYS sprintf(usrdat, "SYS 0x%03X", nnn) -#define X_C8_JP sprintf(usrdat, "JP 0x%03X", nnn) -#define X_C8_CALL sprintf(usrdat, "CALL 0x%03X", nnn) -#define X_C8_LDI sprintf(usrdat, "LD I, 0x%03X", nnn) -#define X_C8_JPV sprintf(usrdat, "JP V0, 0x%03X", nnn) -#define X_C8_SEB sprintf(usrdat, "SE V%x, %d", x, kk) -#define X_C8_SNEB sprintf(usrdat, "SNE V%x, %d", x, kk) -#define X_C8_LD sprintf(usrdat, "LD V%x, %d", x, kk) -#define X_C8_ADDB sprintf(usrdat, "ADD V%x, %d", x, kk) -#define X_C8_RND sprintf(usrdat, "RND V%x, %d", x, kk) -#define X_C8_SKP sprintf(usrdat, "SKP V%x", x) -#define X_C8_SKNP sprintf(usrdat, "SKNP V%x", x) -#define X_C8_MVDT sprintf(usrdat, "LD V%x, DT", x) -#define X_C8_LDK sprintf(usrdat, "LD V%x, K", x) -#define X_C8_LDDT sprintf(usrdat, "LD DT, V%x", x) -#define X_C8_LDST sprintf(usrdat, "LD ST, V%x", x) -#define X_C8_ADDI sprintf(usrdat, "ADD I, V%x", x) -#define X_C8_HEX sprintf(usrdat, "LD F, V%x", x) -#define X_C8_BCD sprintf(usrdat, "LD B, V%x", x) -#define X_C8_SAVE sprintf(usrdat, "LD [I], V%x", x) -#define X_C8_RESTORE sprintf(usrdat, "LD V%x, [I]", x) -#define X_C8_SE sprintf(usrdat, "SE V%x, V%x", x, y) -#define X_C8_MOVE sprintf(usrdat, "LD V%x, V%x", x, y) -#define X_C8_OR sprintf(usrdat, "OR V%x, V%x", x, y) -#define X_C8_AND sprintf(usrdat, "AND V%x, V%x", x, y) -#define X_C8_XOR sprintf(usrdat, "XOR V%x, V%x", x, y) -#define X_C8_ADD sprintf(usrdat, "ADD V%x, V%x", x, y) -#define X_C8_SUB sprintf(usrdat, "SUB V%x, V%x", x, y) -#define X_C8_SHR sprintf(usrdat, "SHR V%x, V%x", x, y) -#define X_C8_SUBN sprintf(usrdat, "SUBN V%x, V%x", x, y) -#define X_C8_SHL sprintf(usrdat, "SHL V%x, V%x", x, y) -#define X_C8_SNE sprintf(usrdat, "SNE V%x, V%x", x, y) -#define X_C8_DRW sprintf(usrdat, "DRW V%x, V%x, %d", x, y, n) +#define X_C8_ILL sprintf(usrdat, "%04X ILL unknown", instr) +#define X_C8_CLS sprintf(usrdat, "%04X CLS", instr) +#define X_C8_RET sprintf(usrdat, "%04X RET", instr) +#define X_C8_SYS sprintf(usrdat, "%04X SYS 0x%03X", instr, nnn) +#define X_C8_JP sprintf(usrdat, "%04X JP 0x%03X", instr, nnn) +#define X_C8_CALL sprintf(usrdat, "%04X CALL 0x%03X", instr, nnn) +#define X_C8_LDI sprintf(usrdat, "%04X LD I, 0x%03X", instr, nnn) +#define X_C8_JPV sprintf(usrdat, "%04X JP V0, 0x%03X", instr, nnn) +#define X_C8_SEB sprintf(usrdat, "%04X SE V%x, %d", instr, x, kk) +#define X_C8_SNEB sprintf(usrdat, "%04X SNE V%x, %d", instr, x, kk) +#define X_C8_LD sprintf(usrdat, "%04X LD V%x, %d", instr, x, kk) +#define X_C8_ADDB sprintf(usrdat, "%04X ADD V%x, %d", instr, x, kk) +#define X_C8_RND sprintf(usrdat, "%04X RND V%x, %d", instr, x, kk) +#define X_C8_SKP sprintf(usrdat, "%04X SKP V%x", instr, x) +#define X_C8_SKNP sprintf(usrdat, "%04X SKNP V%x", instr, x) +#define X_C8_MVDT sprintf(usrdat, "%04X LD V%x, DT", instr, x) +#define X_C8_LDK sprintf(usrdat, "%04X LD V%x, K", instr, x) +#define X_C8_LDDT sprintf(usrdat, "%04X LD DT, V%x", instr, x) +#define X_C8_LDST sprintf(usrdat, "%04X LD ST, V%x", instr, x) +#define X_C8_ADDI sprintf(usrdat, "%04X ADD I, V%x", instr, x) +#define X_C8_HEX sprintf(usrdat, "%04X LD F, V%x", instr, x) +#define X_C8_BCD sprintf(usrdat, "%04X LD B, V%x", instr, x) +#define X_C8_SAVE sprintf(usrdat, "%04X LD [I], V%x", instr, x) +#define X_C8_RESTORE sprintf(usrdat, "%04X LD V%x, [I]", instr, x) +#define X_C8_SE sprintf(usrdat, "%04X SE V%x, V%x", instr, x, y) +#define X_C8_MOVE sprintf(usrdat, "%04X LD V%x, V%x", instr, x, y) +#define X_C8_OR sprintf(usrdat, "%04X OR V%x, V%x", instr, x, y) +#define X_C8_AND sprintf(usrdat, "%04X AND V%x, V%x", instr, x, y) +#define X_C8_XOR sprintf(usrdat, "%04X XOR V%x, V%x", instr, x, y) +#define X_C8_ADD sprintf(usrdat, "%04X ADD V%x, V%x", instr, x, y) +#define X_C8_SUB sprintf(usrdat, "%04X SUB V%x, V%x", instr, x, y) +#define X_C8_SHR sprintf(usrdat, "%04X SHR V%x, V%x", instr, x, y) +#define X_C8_SUBN sprintf(usrdat, "%04X SUBN V%x, V%x", instr, x, y) +#define X_C8_SHL sprintf(usrdat, "%04X SHL V%x, V%x", instr, x, y) +#define X_C8_SNE sprintf(usrdat, "%04X SNE V%x, V%x", instr, x, y) +#define X_C8_DRW sprintf(usrdat, "%04X DRW V%x, V%x, %d", instr, x, y, n) c8_decode_generate(disasm) diff --git a/sources/meta/exec.c b/sources/meta/exec.c new file mode 100644 index 0000000..69e9a8a --- /dev/null +++ b/sources/meta/exec.c @@ -0,0 +1,82 @@ +#define BEGIN \ +do{ \ + chip8* c8 = usrdat; \ + assert(c8); + +#define END }while(0) + +#define X_C8_ILL \ +BEGIN \ + \ + c8->running = false; \ + report(ERR, "Illegal instruction (%04X) @ %04X\n", instr, offset); \ +END + +#define X_C8_CLS X_C8_ILL +#define X_C8_RET X_C8_ILL +#define X_C8_SYS X_C8_ILL + +#define X_C8_JP \ +BEGIN \ + c8->pc = nnn - 2; \ +END + +#define X_C8_CALL X_C8_ILL +#define X_C8_LDI X_C8_ILL +#define X_C8_JPV X_C8_ILL + +#define X_C8_SEB \ +BEGIN \ + if(c8->V[x] == kk) c8->pc += 2; \ +END + +#define X_C8_SNEB X_C8_ILL + +#define X_C8_LD \ +BEGIN \ + c8->V[x] = kk; \ +END + +#define X_C8_ADDB \ +BEGIN \ + int tmp = (int)c8->V[x] + (int)kk; \ + c8->V[x] = tmp & 0xFF; \ +END + +#define X_C8_RND X_C8_ILL +#define X_C8_SKP X_C8_ILL +#define X_C8_SKNP X_C8_ILL +#define X_C8_MVDT X_C8_ILL +#define X_C8_LDK X_C8_ILL +#define X_C8_LDDT X_C8_ILL +#define X_C8_LDST X_C8_ILL +#define X_C8_ADDI X_C8_ILL +#define X_C8_HEX X_C8_ILL +#define X_C8_BCD X_C8_ILL +#define X_C8_SAVE X_C8_ILL +#define X_C8_RESTORE X_C8_ILL +#define X_C8_SE X_C8_ILL +#define X_C8_MOVE X_C8_ILL +#define X_C8_OR X_C8_ILL +#define X_C8_AND X_C8_ILL +#define X_C8_XOR X_C8_ILL + +#define X_C8_ADD \ +BEGIN \ + int tmp = (int)c8->V[x] + (int)c8->V[y]; \ + c8->V[0xf] = (tmp > 255); \ + c8->V[x] = tmp & 0xFF; \ +END + +#define X_C8_SUB X_C8_ILL +#define X_C8_SHR X_C8_ILL +#define X_C8_SUBN X_C8_ILL +#define X_C8_SHL X_C8_ILL +#define X_C8_SNE X_C8_ILL +#define X_C8_DRW X_C8_ILL + +c8_decode_generate(exec) + +#undef BEGIN +#undef END +#include "undef.c" |