main.c (2737B)
1 #include "emu.h" 2 3 struct emulator { 4 byte memory[65536]; 5 byte a; 6 byte b; 7 byte c; 8 byte d; 9 byte e; 10 byte h; 11 byte l; 12 int pc; 13 }; 14 15 static void set_reg(emulator *e, byte c, byte val) { 16 switch (c) { 17 case reg_a: e->a = val; break; 18 case reg_b: e->b = val; break; 19 case reg_c: e->c = val; break; 20 case reg_d: e->d = val; break; 21 case reg_e: e->e = val; break; 22 case reg_h: e->h = val; break; 23 case reg_l: e->l = val; break; 24 case reg_m: 25 { 26 uint16_t hl = ((uint16_t)e->h << 8) | e->l; 27 e->memory[hl] = val; 28 break; 29 } 30 } 31 } 32 33 emulator* emu_create(void) { 34 emulator* e = malloc(sizeof(emulator)); 35 memset(e, 0, sizeof(emulator)); 36 return e; 37 } 38 39 int emu_load_program(emulator *e, const char *filename) { 40 FILE *f = fopen(filename, "rb"); 41 if (!f) return 1; 42 43 size_t bytes_read = fread(e->memory, 1, sizeof(e->memory), f); 44 45 fclose(f); 46 if (bytes_read == 0) { 47 return 1; 48 } 49 e->pc = 0; 50 return 0; 51 } 52 53 void emu_destroy(emulator *e) { free(e); } 54 55 int emu_get_pc(emulator *e) { 56 return e->pc; 57 } 58 59 void emu_set_pc(emulator *e, int pc) { 60 e->pc = pc; 61 } 62 63 int emu_step(emulator *e) { 64 byte instr = e->memory[e->pc]; 65 66 /* parse instr */ 67 byte part1 = (instr >> 6) & 0x03; /* 0b[00]000000 */ 68 byte dst = (instr >> 3) & 0x07; /* 0b00[000]000 */ 69 byte src = instr & 0x07; /* 0b00000[000] */ 70 71 switch (part1) { 72 case op_mv: 73 /* instr = 0b01110110 hlt */ 74 if (dst == reg_m && src == reg_m) { 75 return 1; 76 } 77 set_reg(e, dst, emu_get_reg(e, src)); 78 e->pc++; 79 break; 80 case op_n: 81 if (src == 0b110) { 82 set_reg(e, dst, e->memory[e->pc+1]); 83 e->pc += 2; 84 } else if (src == reg_d) { 85 uint16_t addr = (uint16_t)e->memory[e->pc + 1] | 86 ((uint16_t)e->memory[e->pc + 2] << 8); 87 88 if (dst == reg_a) { 89 e->a = e->memory[addr]; 90 } else if (dst == reg_m) { 91 e->memory[addr] = e->a; 92 } 93 e->pc += 3; 94 } else { 95 e->pc++; 96 } 97 break; 98 case op_sum_a: 99 e->pc++; 100 break; 101 case op_jmp: 102 e->pc++; 103 break; 104 default: 105 return 1; 106 } 107 108 return 0; 109 } 110 111 void emu_mem_write(emulator *e, uint16_t addr, byte val) { 112 e->memory[addr] = val; 113 } 114 115 byte emu_mem_read(emulator *e, uint16_t addr) { 116 return e->memory[addr]; 117 } 118 119 byte emu_get_reg(emulator *e, byte c) { 120 switch (c) { 121 case reg_a: return e->a; 122 case reg_b: return e->b; 123 case reg_c: return e->c; 124 case reg_d: return e->d; 125 case reg_e: return e->e; 126 case reg_h: return e->h; 127 case reg_l: return e->l; 128 case reg_m: 129 { 130 uint16_t hl = ((uint16_t)e->h << 8) | e->l; 131 return e->memory[hl]; 132 } 133 default: return 0; 134 } 135 }