From a5fdc4543134dbf3ae093d749c4db4974511ded3 Mon Sep 17 00:00:00 2001 From: Stefan Arentz Date: Wed, 28 Dec 2016 23:13:05 -0500 Subject: [PATCH] Fixes #108 Bring back the --strict option --- src/cpu.c | 6 +- src/ins.c | 214 +++++++++++++++++++++++++++--------------------------- src/one.c | 11 ++- src/two.c | 10 ++- 4 files changed, 132 insertions(+), 109 deletions(-) diff --git a/src/cpu.c b/src/cpu.c index ff6ad3f..aeef933 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -111,8 +111,10 @@ static int cpu_execute_instruction(struct cpu_t *cpu) { /* Fetch instruction */ struct cpu_instruction_t *i = &cpu->instructions[mem_get_byte(cpu, cpu->state.pc)]; - if (i->handler == NULL) { - return EWM_CPU_ERR_UNIMPLEMENTED_INSTRUCTION; + if (i->name[0] == '?') { + if (cpu->strict) { + return EWM_CPU_ERR_UNIMPLEMENTED_INSTRUCTION; + } } // If strict mode and if we need the stack, check if that works out diff --git a/src/ins.c b/src/ins.c index db19737..c2da5f8 100644 --- a/src/ins.c +++ b/src/ins.c @@ -907,272 +907,276 @@ static void tya(struct cpu_t *cpu) { update_zn(cpu, cpu->state.a); } +static void unimplemented(struct cpu_t *cpu) { + // This is handled in cpu_execute_instruction() if strict mode is enabled. +} + /* Instruction dispatch table */ struct cpu_instruction_t instructions[256] = { /* 0x00 */ { "BRK", 0x00, 1, 2, 3, (void*) brk }, /* 0x01 */ { "ORA", 0x01, 2, 6, 0, (void*) ora_indx }, - /* 0x02 */ { "???", 0x02, 1, 2, 0, (void*) NULL }, - /* 0x03 */ { "???", 0x03, 1, 2, 0, (void*) NULL }, - /* 0x04 */ { "???", 0x04, 1, 2, 0, (void*) NULL }, + /* 0x02 */ { "???", 0x02, 1, 2, 0, (void*) unimplemented }, + /* 0x03 */ { "???", 0x03, 1, 2, 0, (void*) unimplemented }, + /* 0x04 */ { "???", 0x04, 1, 2, 0, (void*) unimplemented }, /* 0x05 */ { "ORA", 0x05, 2, 2, 0, (void*) ora_zpg }, /* 0x06 */ { "ASL", 0x06, 2, 5, 0, (void*) asl_zpg }, - /* 0x07 */ { "???", 0x07, 1, 2, 0, (void*) NULL }, + /* 0x07 */ { "???", 0x07, 1, 2, 0, (void*) unimplemented }, /* 0x08 */ { "PHP", 0x08, 1, 3, 0, (void*) php }, /* 0x09 */ { "ORA", 0x09, 2, 2, 0, (void*) ora_imm }, /* 0x0a */ { "ASL", 0x0a, 1, 2, 0, (void*) asl_acc }, - /* 0x0b */ { "???", 0x0b, 1, 2, 0, (void*) NULL }, - /* 0x0c */ { "???", 0x0c, 1, 2, 0, (void*) NULL }, + /* 0x0b */ { "???", 0x0b, 1, 2, 0, (void*) unimplemented }, + /* 0x0c */ { "???", 0x0c, 1, 2, 0, (void*) unimplemented }, /* 0x0d */ { "ORA", 0x0d, 3, 4, 0, (void*) ora_abs }, /* 0x0e */ { "ASL", 0x0e, 3, 6, 0, (void*) asl_abs }, - /* 0x0f */ { "???", 0x0f, 1, 2, 0, (void*) NULL }, + /* 0x0f */ { "???", 0x0f, 1, 2, 0, (void*) unimplemented }, /* 0x10 */ { "BPL", 0x10, 2, 2, 0, (void*) bpl }, /* 0x11 */ { "ORA", 0x11, 2, 5, 0, (void*) ora_indy }, - /* 0x12 */ { "???", 0x12, 1, 2, 0, (void*) NULL }, - /* 0x13 */ { "???", 0x13, 1, 2, 0, (void*) NULL }, - /* 0x14 */ { "???", 0x14, 1, 2, 0, (void*) NULL }, + /* 0x12 */ { "???", 0x12, 1, 2, 0, (void*) unimplemented }, + /* 0x13 */ { "???", 0x13, 1, 2, 0, (void*) unimplemented }, + /* 0x14 */ { "???", 0x14, 1, 2, 0, (void*) unimplemented }, /* 0x15 */ { "ORA", 0x15, 2, 3, 0, (void*) ora_zpgx }, /* 0x16 */ { "ASL", 0x16, 2, 6, 0, (void*) asl_zpgx }, - /* 0x17 */ { "???", 0x17, 1, 2, 0, (void*) NULL }, + /* 0x17 */ { "???", 0x17, 1, 2, 0, (void*) unimplemented }, /* 0x18 */ { "CLC", 0x18, 1, 2, 0, (void*) clc }, /* 0x19 */ { "ORA", 0x19, 3, 4, 0, (void*) ora_absy }, - /* 0x1a */ { "???", 0x1a, 1, 2, 0, (void*) NULL }, - /* 0x1b */ { "???", 0x1b, 1, 2, 0, (void*) NULL }, - /* 0x1c */ { "???", 0x1c, 1, 2, 0, (void*) NULL }, + /* 0x1a */ { "???", 0x1a, 1, 2, 0, (void*) unimplemented }, + /* 0x1b */ { "???", 0x1b, 1, 2, 0, (void*) unimplemented }, + /* 0x1c */ { "???", 0x1c, 1, 2, 0, (void*) unimplemented }, /* 0x1d */ { "ORA", 0x1d, 3, 4, 0, (void*) ora_absx }, /* 0x1e */ { "ASL", 0x1e, 3, 7, 0, (void*) asl_absx }, - /* 0x1f */ { "???", 0x1f, 1, 2, 0, (void*) NULL }, + /* 0x1f */ { "???", 0x1f, 1, 2, 0, (void*) unimplemented }, /* 0x20 */ { "JSR", 0x20, 3, 6, 2, (void*) jsr_abs }, /* 0x21 */ { "AND", 0x21, 2, 6, 0, (void*) and_indx }, - /* 0x22 */ { "???", 0x22, 1, 2, 0, (void*) NULL }, - /* 0x23 */ { "???", 0x23, 1, 2, 0, (void*) NULL }, + /* 0x22 */ { "???", 0x22, 1, 2, 0, (void*) unimplemented }, + /* 0x23 */ { "???", 0x23, 1, 2, 0, (void*) unimplemented }, /* 0x24 */ { "BIT", 0x24, 2, 3, 0, (void*) bit_zpg }, /* 0x25 */ { "AND", 0x25, 2, 3, 0, (void*) and_zpg }, /* 0x26 */ { "ROL", 0x26, 2, 5, 0, (void*) rol_zpg }, - /* 0x27 */ { "???", 0x27, 1, 2, 0, (void*) NULL }, + /* 0x27 */ { "???", 0x27, 1, 2, 0, (void*) unimplemented }, /* 0x28 */ { "PLP", 0x28, 1, 4, 0, (void*) plp }, /* 0x29 */ { "AND", 0x29, 2, 2, 0, (void*) and_imm }, /* 0x2a */ { "ROL", 0x2a, 1, 2, 0, (void*) rol_acc }, - /* 0x2b */ { "???", 0x2b, 1, 2, 0, (void*) NULL }, + /* 0x2b */ { "???", 0x2b, 1, 2, 0, (void*) unimplemented }, /* 0x2c */ { "BIT", 0x2c, 3, 4, 0, (void*) bit_abs }, /* 0x2d */ { "AND", 0x2d, 3, 4, 0, (void*) and_abs }, /* 0x2e */ { "ROL", 0x2e, 3, 6, 0, (void*) rol_abs }, - /* 0x2f */ { "???", 0x2f, 1, 2, 0, (void*) NULL }, + /* 0x2f */ { "???", 0x2f, 1, 2, 0, (void*) unimplemented }, /* 0x30 */ { "BMI", 0x30, 2, 2, 0, (void*) bmi }, /* 0x31 */ { "AND", 0x31, 2, 5, 0, (void*) and_indy }, - /* 0x32 */ { "???", 0x32, 1, 2, 0, (void*) NULL }, - /* 0x33 */ { "???", 0x33, 1, 2, 0, (void*) NULL }, - /* 0x34 */ { "???", 0x34, 1, 2, 0, (void*) NULL }, + /* 0x32 */ { "???", 0x32, 1, 2, 0, (void*) unimplemented }, + /* 0x33 */ { "???", 0x33, 1, 2, 0, (void*) unimplemented }, + /* 0x34 */ { "???", 0x34, 1, 2, 0, (void*) unimplemented }, /* 0x35 */ { "AND", 0x35, 2, 4, 0, (void*) and_zpgx }, /* 0x36 */ { "ROL", 0x36, 2, 6, 0, (void*) rol_zpgx }, - /* 0x37 */ { "???", 0x37, 1, 2, 0, (void*) NULL }, + /* 0x37 */ { "???", 0x37, 1, 2, 0, (void*) unimplemented }, /* 0x38 */ { "SEC", 0x38, 1, 2, 0, (void*) sec }, /* 0x39 */ { "AND", 0x39, 3, 4, 0, (void*) and_absy }, - /* 0x3a */ { "???", 0x3a, 1, 2, 0, (void*) NULL }, - /* 0x3b */ { "???", 0x3b, 1, 2, 0, (void*) NULL }, - /* 0x3c */ { "???", 0x3c, 1, 2, 0, (void*) NULL }, + /* 0x3a */ { "???", 0x3a, 1, 2, 0, (void*) unimplemented }, + /* 0x3b */ { "???", 0x3b, 1, 2, 0, (void*) unimplemented }, + /* 0x3c */ { "???", 0x3c, 1, 2, 0, (void*) unimplemented }, /* 0x3d */ { "AND", 0x3d, 3, 4, 0, (void*) and_absx }, /* 0x3e */ { "ROL", 0x3e, 3, 7, 0, (void*) rol_absx }, - /* 0x3f */ { "???", 0x3f, 1, 2, 0, (void*) NULL }, + /* 0x3f */ { "???", 0x3f, 1, 2, 0, (void*) unimplemented }, /* 0x40 */ { "RTI", 0x40, 1, 6, -3, (void*) rti }, /* 0x41 */ { "EOR", 0x41, 2, 6, 0, (void*) eor_indx }, - /* 0x42 */ { "???", 0x42, 1, 2, 0, (void*) NULL }, - /* 0x43 */ { "???", 0x43, 1, 2, 0, (void*) NULL }, - /* 0x44 */ { "???", 0x44, 1, 2, 0, (void*) NULL }, + /* 0x42 */ { "???", 0x42, 1, 2, 0, (void*) unimplemented }, + /* 0x43 */ { "???", 0x43, 1, 2, 0, (void*) unimplemented }, + /* 0x44 */ { "???", 0x44, 1, 2, 0, (void*) unimplemented }, /* 0x45 */ { "EOR", 0x45, 2, 3, 0, (void*) eor_zpg }, /* 0x46 */ { "LSR", 0x46, 2, 5, 0, (void*) lsr_zpg }, - /* 0x47 */ { "???", 0x47, 1, 2, 0, (void*) NULL }, + /* 0x47 */ { "???", 0x47, 1, 2, 0, (void*) unimplemented }, /* 0x48 */ { "PHA", 0x48, 1, 3, 1, (void*) pha }, /* 0x49 */ { "EOR", 0x49, 2, 2, 0, (void*) eor_imm }, /* 0x4a */ { "LSR", 0x4a, 1, 2, 0, (void*) lsr_acc }, - /* 0x4b */ { "???", 0x4b, 1, 2, 0, (void*) NULL }, + /* 0x4b */ { "???", 0x4b, 1, 2, 0, (void*) unimplemented }, /* 0x4c */ { "JMP", 0x4c, 3, 3, 0, (void*) jmp_abs }, /* 0x4d */ { "EOR", 0x4d, 3, 4, 0, (void*) eor_abs }, /* 0x4e */ { "LSR", 0x4e, 3, 6, 0, (void*) lsr_abs }, - /* 0x4f */ { "???", 0x4f, 1, 2, 0, (void*) NULL }, + /* 0x4f */ { "???", 0x4f, 1, 2, 0, (void*) unimplemented }, /* 0x50 */ { "BVC", 0x50, 2, 2, 0, (void*) bvc }, /* 0x51 */ { "EOR", 0x51, 2, 5, 0, (void*) eor_indy }, - /* 0x52 */ { "???", 0x52, 1, 2, 0, (void*) NULL }, - /* 0x53 */ { "???", 0x53, 1, 2, 0, (void*) NULL }, - /* 0x54 */ { "???", 0x54, 1, 2, 0, (void*) NULL }, + /* 0x52 */ { "???", 0x52, 1, 2, 0, (void*) unimplemented }, + /* 0x53 */ { "???", 0x53, 1, 2, 0, (void*) unimplemented }, + /* 0x54 */ { "???", 0x54, 1, 2, 0, (void*) unimplemented }, /* 0x55 */ { "EOR", 0x55, 2, 4, 0, (void*) eor_zpgx }, /* 0x56 */ { "LSR", 0x56, 2, 6, 0, (void*) lsr_zpgx }, - /* 0x57 */ { "???", 0x57, 1, 2, 0, (void*) NULL }, + /* 0x57 */ { "???", 0x57, 1, 2, 0, (void*) unimplemented }, /* 0x58 */ { "CLI", 0x58, 1, 2, 0, (void*) cli }, /* 0x59 */ { "EOR", 0x59, 3, 4, 0, (void*) eor_absy }, - /* 0x5a */ { "???", 0x5a, 1, 2, 0, (void*) NULL }, - /* 0x5b */ { "???", 0x5b, 1, 2, 0, (void*) NULL }, - /* 0x5c */ { "???", 0x5c, 1, 2, 0, (void*) NULL }, + /* 0x5a */ { "???", 0x5a, 1, 2, 0, (void*) unimplemented }, + /* 0x5b */ { "???", 0x5b, 1, 2, 0, (void*) unimplemented }, + /* 0x5c */ { "???", 0x5c, 1, 2, 0, (void*) unimplemented }, /* 0x5d */ { "EOR", 0x5d, 3, 4, 0, (void*) eor_absx }, /* 0x5e */ { "LSR", 0x5e, 3, 7, 0, (void*) lsr_absx }, - /* 0x5f */ { "???", 0x5f, 1, 2, 0, (void*) NULL }, + /* 0x5f */ { "???", 0x5f, 1, 2, 0, (void*) unimplemented }, /* 0x60 */ { "RTS", 0x60, 1, 6, -2, (void*) rts }, /* 0x61 */ { "ADC", 0x61, 2, 6, 0, (void*) adc_indx }, - /* 0x62 */ { "???", 0x62, 1, 2, 0, (void*) NULL }, - /* 0x63 */ { "???", 0x63, 1, 2, 0, (void*) NULL }, - /* 0x64 */ { "???", 0x64, 1, 2, 0, (void*) NULL }, + /* 0x62 */ { "???", 0x62, 1, 2, 0, (void*) unimplemented }, + /* 0x63 */ { "???", 0x63, 1, 2, 0, (void*) unimplemented }, + /* 0x64 */ { "???", 0x64, 1, 2, 0, (void*) unimplemented }, /* 0x65 */ { "ADC", 0x65, 2, 3, 0, (void*) adc_zpg }, /* 0x66 */ { "ROR", 0x66, 2, 5, 0, (void*) ror_zpg }, - /* 0x67 */ { "???", 0x67, 1, 2, 0, (void*) NULL }, + /* 0x67 */ { "???", 0x67, 1, 2, 0, (void*) unimplemented }, /* 0x68 */ { "PLA", 0x68, 1, 4, -1, (void*) pla }, /* 0x69 */ { "ADC", 0x69, 2, 2, 0, (void*) adc_imm }, /* 0x6a */ { "ROR", 0x6a, 1, 2, 0, (void*) ror_acc }, - /* 0x6b */ { "???", 0x6b, 1, 2, 0, (void*) NULL }, + /* 0x6b */ { "???", 0x6b, 1, 2, 0, (void*) unimplemented }, /* 0x6c */ { "JMP", 0x6c, 3, 5, 0, (void*) jmp_ind }, /* 0x6d */ { "ADC", 0x6d, 3, 4, 0, (void*) adc_abs }, /* 0x6e */ { "ROR", 0x6e, 3, 6, 0, (void*) ror_abs }, - /* 0x6f */ { "???", 0x6f, 1, 2, 0, (void*) NULL }, + /* 0x6f */ { "???", 0x6f, 1, 2, 0, (void*) unimplemented }, /* 0x70 */ { "BVS", 0x70, 2, 2, 0, (void*) bvs }, /* 0x71 */ { "ADC", 0x71, 2, 5, 0, (void*) adc_indy }, - /* 0x72 */ { "???", 0x72, 1, 2, 0, (void*) NULL }, - /* 0x73 */ { "???", 0x73, 1, 2, 0, (void*) NULL }, - /* 0x74 */ { "???", 0x74, 1, 2, 0, (void*) NULL }, + /* 0x72 */ { "???", 0x72, 1, 2, 0, (void*) unimplemented }, + /* 0x73 */ { "???", 0x73, 1, 2, 0, (void*) unimplemented }, + /* 0x74 */ { "???", 0x74, 1, 2, 0, (void*) unimplemented }, /* 0x75 */ { "ADC", 0x75, 2, 4, 0, (void*) adc_zpgx }, /* 0x76 */ { "ROR", 0x76, 2, 6, 0, (void*) ror_zpgx }, - /* 0x77 */ { "???", 0x77, 1, 2, 0, (void*) NULL }, + /* 0x77 */ { "???", 0x77, 1, 2, 0, (void*) unimplemented }, /* 0x78 */ { "SEI", 0x78, 1, 2, 0, (void*) sei }, /* 0x79 */ { "ADC", 0x79, 3, 4, 0, (void*) adc_absy }, - /* 0x7a */ { "???", 0x7a, 1, 2, 0, (void*) NULL }, - /* 0x7b */ { "???", 0x7b, 1, 2, 0, (void*) NULL }, - /* 0x7c */ { "???", 0x7c, 1, 2, 0, (void*) NULL }, + /* 0x7a */ { "???", 0x7a, 1, 2, 0, (void*) unimplemented }, + /* 0x7b */ { "???", 0x7b, 1, 2, 0, (void*) unimplemented }, + /* 0x7c */ { "???", 0x7c, 1, 2, 0, (void*) unimplemented }, /* 0x7d */ { "ADC", 0x7d, 3, 4, 0, (void*) adc_absx }, /* 0x7e */ { "ROR", 0x7e, 3, 7, 0, (void*) ror_absx }, - /* 0x7f */ { "???", 0x7f, 1, 2, 0, (void*) NULL }, + /* 0x7f */ { "???", 0x7f, 1, 2, 0, (void*) unimplemented }, - /* 0x80 */ { "???", 0x80, 1, 2, 0, (void*) NULL }, + /* 0x80 */ { "???", 0x80, 1, 2, 0, (void*) unimplemented }, /* 0x81 */ { "STA", 0x81, 2, 6, 0, (void*) sta_indx }, - /* 0x82 */ { "???", 0x82, 1, 2, 0, (void*) NULL }, - /* 0x83 */ { "???", 0x83, 1, 2, 0, (void*) NULL }, + /* 0x82 */ { "???", 0x82, 1, 2, 0, (void*) unimplemented }, + /* 0x83 */ { "???", 0x83, 1, 2, 0, (void*) unimplemented }, /* 0x84 */ { "STY", 0x84, 2, 3, 0, (void*) sty_zpg }, /* 0x85 */ { "STA", 0x85, 2, 3, 0, (void*) sta_zpg }, /* 0x86 */ { "STX", 0x86, 2, 3, 0, (void*) stx_zpg }, - /* 0x87 */ { "???", 0x87, 1, 2, 0, (void*) NULL }, + /* 0x87 */ { "???", 0x87, 1, 2, 0, (void*) unimplemented }, /* 0x88 */ { "DEY", 0x88, 1, 2, 0, (void*) dey }, - /* 0x89 */ { "???", 0x89, 1, 2, 0, (void*) NULL }, + /* 0x89 */ { "???", 0x89, 1, 2, 0, (void*) unimplemented }, /* 0x8a */ { "TXA", 0x8a, 1, 2, 0, (void*) txa }, - /* 0x8b */ { "???", 0x8b, 1, 2, 0, (void*) NULL }, + /* 0x8b */ { "???", 0x8b, 1, 2, 0, (void*) unimplemented }, /* 0x8c */ { "STY", 0x8c, 3, 4, 0, (void*) sty_abs }, /* 0x8d */ { "STA", 0x8d, 3, 4, 0, (void*) sta_abs }, /* 0x8e */ { "STX", 0x8e, 3, 4, 0, (void*) stx_abs }, - /* 0x8f */ { "???", 0x8f, 1, 2, 0, (void*) NULL }, + /* 0x8f */ { "???", 0x8f, 1, 2, 0, (void*) unimplemented }, /* 0x90 */ { "BCC", 0x90, 2, 2, 0, (void*) bcc }, /* 0x91 */ { "STA", 0x91, 2, 6, 0, (void*) sta_indy }, - /* 0x92 */ { "???", 0x92, 1, 2, 0, (void*) NULL }, - /* 0x93 */ { "???", 0x93, 1, 2, 0, (void*) NULL }, + /* 0x92 */ { "???", 0x92, 1, 2, 0, (void*) unimplemented }, + /* 0x93 */ { "???", 0x93, 1, 2, 0, (void*) unimplemented }, /* 0x94 */ { "STY", 0x94, 2, 4, 0, (void*) sty_zpgx }, /* 0x95 */ { "STA", 0x95, 2, 4, 0, (void*) sta_zpgx }, /* 0x96 */ { "STX", 0x96, 2, 4, 0, (void*) stx_zpgy }, - /* 0x97 */ { "???", 0x97, 1, 2, 0, (void*) NULL }, + /* 0x97 */ { "???", 0x97, 1, 2, 0, (void*) unimplemented }, /* 0x98 */ { "TYA", 0x98, 1, 2, 0, (void*) tya }, /* 0x99 */ { "STA", 0x99, 3, 5, 0, (void*) sta_absy }, /* 0x9a */ { "TXS", 0x9a, 1, 2, 0, (void*) txs }, - /* 0x9b */ { "???", 0x9b, 1, 2, 0, (void*) NULL }, - /* 0x9c */ { "???", 0x9c, 1, 2, 0, (void*) NULL }, + /* 0x9b */ { "???", 0x9b, 1, 2, 0, (void*) unimplemented }, + /* 0x9c */ { "???", 0x9c, 1, 2, 0, (void*) unimplemented }, /* 0x9d */ { "STA", 0x9d, 3, 5, 0, (void*) sta_absx }, - /* 0x9e */ { "???", 0x9e, 1, 2, 0, (void*) NULL }, - /* 0x9f */ { "???", 0x9f, 1, 2, 0, (void*) NULL }, + /* 0x9e */ { "???", 0x9e, 1, 2, 0, (void*) unimplemented }, + /* 0x9f */ { "???", 0x9f, 1, 2, 0, (void*) unimplemented }, /* 0xa0 */ { "LDY", 0xa0, 2, 2, 0, (void*) ldy_imm }, /* 0xa1 */ { "LDA", 0xa1, 2, 6, 0, (void*) lda_indx }, /* 0xa2 */ { "LDX", 0xa2, 2, 2, 0, (void*) ldx_imm }, - /* 0xa3 */ { "???", 0xa3, 1, 2, 0, (void*) NULL }, + /* 0xa3 */ { "???", 0xa3, 1, 2, 0, (void*) unimplemented }, /* 0xa4 */ { "LDY", 0xa4, 2, 3, 0, (void*) ldy_zpg }, /* 0xa5 */ { "LDA", 0xa5, 2, 3, 0, (void*) lda_zpg }, /* 0xa6 */ { "LDX", 0xa6, 2, 3, 0, (void*) ldx_zpg }, - /* 0xa7 */ { "???", 0xa7, 1, 2, 0, (void*) NULL }, + /* 0xa7 */ { "???", 0xa7, 1, 2, 0, (void*) unimplemented }, /* 0xa8 */ { "TAY", 0xa8, 1, 2, 0, (void*) tay }, /* 0xa9 */ { "LDA", 0xa9, 2, 2, 0, (void*) lda_imm }, /* 0xaa */ { "TAX", 0xaa, 1, 2, 0, (void*) tax }, - /* 0xab */ { "???", 0xab, 1, 2, 0, (void*) NULL }, + /* 0xab */ { "???", 0xab, 1, 2, 0, (void*) unimplemented }, /* 0xac */ { "LDY", 0xac, 3, 4, 0, (void*) ldy_abs }, /* 0xad */ { "LDA", 0xad, 3, 4, 0, (void*) lda_abs }, /* 0xae */ { "LDX", 0xae, 3, 4, 0, (void*) ldx_abs }, - /* 0xaf */ { "???", 0xaf, 1, 2, 0, (void*) NULL }, + /* 0xaf */ { "???", 0xaf, 1, 2, 0, (void*) unimplemented }, /* 0xb0 */ { "BCS", 0xb0, 2, 2, 0, (void*) bcs }, /* 0xb1 */ { "LDA", 0xb1, 2, 5, 0, (void*) lda_indy }, - /* 0xb2 */ { "???", 0xb2, 1, 2, 0, (void*) NULL }, - /* 0xb3 */ { "???", 0xb3, 1, 2, 0, (void*) NULL }, + /* 0xb2 */ { "???", 0xb2, 1, 2, 0, (void*) unimplemented }, + /* 0xb3 */ { "???", 0xb3, 1, 2, 0, (void*) unimplemented }, /* 0xb4 */ { "LDY", 0xb4, 2, 4, 0, (void*) ldy_zpgx }, /* 0xb5 */ { "LDA", 0xb5, 2, 4, 0, (void*) lda_zpgx }, /* 0xb6 */ { "LDX", 0xb6, 2, 4, 0, (void*) ldx_zpgy }, - /* 0xb7 */ { "???", 0xb7, 1, 2, 0, (void*) NULL }, + /* 0xb7 */ { "???", 0xb7, 1, 2, 0, (void*) unimplemented }, /* 0xb8 */ { "CLV", 0xb8, 1, 2, 0, (void*) clv }, /* 0xb9 */ { "LDA", 0xb9, 3, 4, 0, (void*) lda_absy }, /* 0xba */ { "TSX", 0xba, 1, 2, 0, (void*) tsx }, - /* 0xbb */ { "???", 0xbb, 1, 2, 0, (void*) NULL }, + /* 0xbb */ { "???", 0xbb, 1, 2, 0, (void*) unimplemented }, /* 0xbc */ { "LDY", 0xbc, 3, 4, 0, (void*) ldy_absx }, /* 0xbd */ { "LDA", 0xbd, 3, 4, 0, (void*) lda_absx }, /* 0xbe */ { "LDX", 0xbe, 3, 4, 0, (void*) ldx_absy }, - /* 0xbf */ { "???", 0xbf, 1, 2, 0, (void*) NULL }, + /* 0xbf */ { "???", 0xbf, 1, 2, 0, (void*) unimplemented }, /* 0xc0 */ { "CPY", 0xc0, 2, 2, 0, (void*) cpy_imm }, /* 0xc1 */ { "CMP", 0xc1, 2, 6, 0, (void*) cmp_indx }, - /* 0xc2 */ { "???", 0xc2, 1, 2, 0, (void*) NULL }, - /* 0xc3 */ { "???", 0xc3, 1, 2, 0, (void*) NULL }, + /* 0xc2 */ { "???", 0xc2, 1, 2, 0, (void*) unimplemented }, + /* 0xc3 */ { "???", 0xc3, 1, 2, 0, (void*) unimplemented }, /* 0xc4 */ { "CPY", 0xc4, 2, 3, 0, (void*) cpy_zpg }, /* 0xc5 */ { "CMP", 0xc5, 2, 3, 0, (void*) cmp_zpg }, /* 0xc6 */ { "DEC", 0xc6, 2, 5, 0, (void*) dec_zpg }, - /* 0xc7 */ { "???", 0xc7, 1, 2, 0, (void*) NULL }, + /* 0xc7 */ { "???", 0xc7, 1, 2, 0, (void*) unimplemented }, /* 0xc8 */ { "INY", 0xc8, 1, 2, 0, (void*) iny }, /* 0xc9 */ { "CMP", 0xc9, 2, 2, 0, (void*) cmp_imm }, /* 0xca */ { "DEX", 0xca, 1, 2, 0, (void*) dex }, - /* 0xcb */ { "???", 0xcb, 1, 2, 0, (void*) NULL }, + /* 0xcb */ { "???", 0xcb, 1, 2, 0, (void*) unimplemented }, /* 0xcc */ { "CPY", 0xcc, 3, 4, 0, (void*) cpy_abs }, /* 0xcd */ { "CMP", 0xcd, 3, 4, 0, (void*) cmp_abs }, /* 0xce */ { "DEC", 0xce, 3, 3, 0, (void*) dec_abs }, - /* 0xcf */ { "???", 0xcf, 1, 2, 0, (void*) NULL }, + /* 0xcf */ { "???", 0xcf, 1, 2, 0, (void*) unimplemented }, /* 0xd0 */ { "BNE", 0xd0, 2, 2, 0, (void*) bne }, /* 0xd1 */ { "CMP", 0xd1, 2, 5, 0, (void*) cmp_indy }, - /* 0xd2 */ { "???", 0xd2, 1, 2, 0, (void*) NULL }, - /* 0xd3 */ { "???", 0xd3, 1, 2, 0, (void*) NULL }, - /* 0xd4 */ { "???", 0xd4, 1, 2, 0, (void*) NULL }, + /* 0xd2 */ { "???", 0xd2, 1, 2, 0, (void*) unimplemented }, + /* 0xd3 */ { "???", 0xd3, 1, 2, 0, (void*) unimplemented }, + /* 0xd4 */ { "???", 0xd4, 1, 2, 0, (void*) unimplemented }, /* 0xd5 */ { "CMP", 0xd5, 2, 4, 0, (void*) cmp_zpgx }, /* 0xd6 */ { "DEC", 0xd6, 2, 6, 0, (void*) dec_zpgx }, - /* 0xd7 */ { "???", 0xd7, 1, 2, 0, (void*) NULL }, + /* 0xd7 */ { "???", 0xd7, 1, 2, 0, (void*) unimplemented }, /* 0xd8 */ { "CLD", 0xd8, 1, 2, 0, (void*) cld }, /* 0xd9 */ { "CMP", 0xd9, 3, 4, 0, (void*) cmp_absy }, - /* 0xda */ { "???", 0xda, 1, 2, 0, (void*) NULL }, - /* 0xdb */ { "???", 0xdb, 1, 2, 0, (void*) NULL }, - /* 0xdc */ { "???", 0xdc, 1, 2, 0, (void*) NULL }, + /* 0xda */ { "???", 0xda, 1, 2, 0, (void*) unimplemented }, + /* 0xdb */ { "???", 0xdb, 1, 2, 0, (void*) unimplemented }, + /* 0xdc */ { "???", 0xdc, 1, 2, 0, (void*) unimplemented }, /* 0xdd */ { "CMP", 0xdd, 3, 4, 0, (void*) cmp_absx }, /* 0xde */ { "DEC", 0xde, 3, 7, 0, (void*) dec_absx }, - /* 0xdf */ { "???", 0xdf, 1, 2, 0, (void*) NULL }, + /* 0xdf */ { "???", 0xdf, 1, 2, 0, (void*) unimplemented }, /* 0xe0 */ { "CPX", 0xe0, 2, 2, 0, (void*) cpx_imm }, /* 0xe1 */ { "SBC", 0xe1, 2, 2, 0, (void*) sbc_indx }, - /* 0xe2 */ { "???", 0xe2, 1, 2, 0, (void*) NULL }, - /* 0xe3 */ { "???", 0xe3, 1, 2, 0, (void*) NULL }, + /* 0xe2 */ { "???", 0xe2, 1, 2, 0, (void*) unimplemented }, + /* 0xe3 */ { "???", 0xe3, 1, 2, 0, (void*) unimplemented }, /* 0xe4 */ { "CPX", 0xe4, 2, 3, 0, (void*) cpx_zpg }, /* 0xe5 */ { "SBC", 0xe5, 2, 2, 0, (void*) sbc_zpg }, /* 0xe6 */ { "INC", 0xe6, 2, 5, 0, (void*) inc_zpg }, - /* 0xe7 */ { "???", 0xe7, 1, 2, 0, (void*) NULL }, + /* 0xe7 */ { "???", 0xe7, 1, 2, 0, (void*) unimplemented }, /* 0xe8 */ { "INX", 0xe8, 1, 2, 0, (void*) inx }, /* 0xe9 */ { "SBC", 0xe9, 2, 2, 0, (void*) sbc_imm }, /* 0xea */ { "NOP", 0xea, 1, 2, 0, (void*) nop }, - /* 0xeb */ { "???", 0xeb, 1, 2, 0, (void*) NULL }, + /* 0xeb */ { "???", 0xeb, 1, 2, 0, (void*) unimplemented }, /* 0xec */ { "CPX", 0xec, 3, 4, 0, (void*) cpx_abs }, /* 0xed */ { "SBC", 0xed, 3, 2, 0, (void*) sbc_abs }, /* 0xee */ { "INC", 0xee, 3, 6, 0, (void*) inc_abs }, - /* 0xef */ { "???", 0xef, 1, 2, 0, (void*) NULL }, + /* 0xef */ { "???", 0xef, 1, 2, 0, (void*) unimplemented }, /* 0xf0 */ { "BEQ", 0xf0, 2, 2, 0, (void*) beq }, /* 0xf1 */ { "SBC", 0xf1, 2, 2, 0, (void*) sbc_indy }, - /* 0xf2 */ { "???", 0xf2, 1, 2, 0, (void*) NULL }, - /* 0xf3 */ { "???", 0xf3, 1, 2, 0, (void*) NULL }, - /* 0xf4 */ { "???", 0xf4, 1, 2, 0, (void*) NULL }, + /* 0xf2 */ { "???", 0xf2, 1, 2, 0, (void*) unimplemented }, + /* 0xf3 */ { "???", 0xf3, 1, 2, 0, (void*) unimplemented }, + /* 0xf4 */ { "???", 0xf4, 1, 2, 0, (void*) unimplemented }, /* 0xf5 */ { "SBC", 0xf5, 2, 2, 0, (void*) sbc_zpgx }, /* 0xf6 */ { "INC", 0xf6, 2, 6, 0, (void*) inc_zpgx }, - /* 0xf7 */ { "???", 0xf7, 1, 2, 0, (void*) NULL }, + /* 0xf7 */ { "???", 0xf7, 1, 2, 0, (void*) unimplemented }, /* 0xf8 */ { "SED", 0xf8, 1, 2, 0, (void*) sed }, /* 0xf9 */ { "SBC", 0xf9, 3, 2, 0, (void*) sbc_absy }, - /* 0xfa */ { "???", 0xfa, 1, 2, 0, (void*) NULL }, - /* 0xfb */ { "???", 0xfb, 1, 2, 0, (void*) NULL }, - /* 0xfc */ { "???", 0xfc, 1, 2, 0, (void*) NULL }, + /* 0xfa */ { "???", 0xfa, 1, 2, 0, (void*) unimplemented }, + /* 0xfb */ { "???", 0xfb, 1, 2, 0, (void*) unimplemented }, + /* 0xfc */ { "???", 0xfc, 1, 2, 0, (void*) unimplemented }, /* 0xfd */ { "SBC", 0xfd, 3, 2, 0, (void*) sbc_absx }, /* 0xfe */ { "INC", 0xfe, 3, 7, 0, (void*) inc_absx }, - /* 0xff */ { "???", 0xff, 1, 2, 0, (void*) NULL } + /* 0xff */ { "???", 0xff, 1, 2, 0, (void*) unimplemented } }; // EWM_CPU_MODEL_65C02 diff --git a/src/one.c b/src/one.c index be37b55..3ff34cc 100644 --- a/src/one.c +++ b/src/one.c @@ -155,6 +155,7 @@ static bool ewm_one_step_cpu(struct ewm_one_t *one, int cycles) { while (true) { int ret = cpu_step(one->cpu); if (ret < 0) { + // These only happen in strict mode switch (ret) { case EWM_CPU_ERR_UNIMPLEMENTED_INSTRUCTION: fprintf(stderr, "CPU: Exited because of unimplemented instructions 0x%.2x at 0x%.4x\n", @@ -167,7 +168,7 @@ static bool ewm_one_step_cpu(struct ewm_one_t *one, int cycles) { fprintf(stderr, "CPU: Exited because of stack underflow at 0x%.4x\n", one->cpu->state.pc); break; } - cpu_nmi(one->cpu); + return false; } cycles -= ret; @@ -181,11 +182,13 @@ static bool ewm_one_step_cpu(struct ewm_one_t *one, int cycles) { #define EWM_ONE_OPT_MODEL (0) #define EWM_ONE_OPT_MEMORY (1) #define EWM_ONE_OPT_TRACE (2) +#define EWM_ONE_OPT_STRICT (3) static struct option one_options[] = { { "model", required_argument, NULL, EWM_ONE_OPT_MODEL }, { "memory", required_argument, NULL, EWM_ONE_OPT_MEMORY }, { "trace", optional_argument, NULL, EWM_ONE_OPT_TRACE }, + { "strict", no_argument, NULL, EWM_ONE_OPT_STRICT }, { NULL, 0, NULL, 0 } }; @@ -194,6 +197,7 @@ int ewm_one_main(int argc, char **argv) { int model = EWM_ONE_MODEL_DEFAULT; struct ewm_memory_option_t *extra_memory = NULL; char *trace_path = NULL; + bool strict = false; int ch; while ((ch = getopt_long_only(argc, argv, "", one_options, NULL)) != -1) { @@ -222,6 +226,10 @@ int ewm_one_main(int argc, char **argv) { trace_path = optarg ? optarg : "/dev/stderr"; break; } + case EWM_ONE_OPT_STRICT: { + strict = true; + break; + } } } @@ -262,6 +270,7 @@ int ewm_one_main(int argc, char **argv) { } } + cpu_strict(one->cpu, strict); cpu_trace(one->cpu, trace_path); cpu_reset(one->cpu); diff --git a/src/two.c b/src/two.c index 6d1e867..3118818 100644 --- a/src/two.c +++ b/src/two.c @@ -470,6 +470,7 @@ static bool ewm_two_step_cpu(struct ewm_two_t *two, int cycles) { while (true) { int ret = cpu_step(two->cpu); if (ret < 0) { + // These only happen in strict mode switch (ret) { case EWM_CPU_ERR_UNIMPLEMENTED_INSTRUCTION: fprintf(stderr, "CPU: Exited because of unimplemented instructions 0x%.2x at 0x%.4x\n", @@ -482,7 +483,7 @@ static bool ewm_two_step_cpu(struct ewm_two_t *two, int cycles) { fprintf(stderr, "CPU: Exited because of stack underflow at 0x%.4x\n", two->cpu->state.pc); break; } - cpu_nmi(two->cpu); + return false; } cycles -= ret; if (cycles <= 0) { @@ -498,6 +499,7 @@ static bool ewm_two_step_cpu(struct ewm_two_t *two, int cycles) { #define EWM_TWO_OPT_FPS (3) #define EWM_TWO_OPT_MEMORY (4) #define EWM_TWO_OPT_TRACE (5) +#define EWM_TWO_OPT_STRICT (6) static struct option one_options[] = { { "drive1", required_argument, NULL, EWM_TWO_OPT_DRIVE1 }, @@ -506,6 +508,7 @@ static struct option one_options[] = { { "fps", required_argument, NULL, EWM_TWO_OPT_FPS }, { "memory", required_argument, NULL, EWM_TWO_OPT_MEMORY }, { "trace", optional_argument, NULL, EWM_TWO_OPT_TRACE }, + { "strict", no_argument, NULL, EWM_TWO_OPT_STRICT }, { NULL, 0, NULL, 0 } }; @@ -518,6 +521,7 @@ int ewm_two_main(int argc, char **argv) { uint32_t fps = EWM_TWO_FPS_DEFAULT; struct ewm_memory_option_t *extra_memory = NULL; char *trace_path = NULL; + bool strict = false; int ch; while ((ch = getopt_long_only(argc, argv, "", one_options, NULL)) != -1) { @@ -546,6 +550,9 @@ int ewm_two_main(int argc, char **argv) { case EWM_TWO_OPT_TRACE: trace_path = optarg ? optarg : "/dev/stderr"; break; + case EWM_TWO_OPT_STRICT: + strict = true; + break; } } @@ -611,6 +618,7 @@ int ewm_two_main(int argc, char **argv) { } } + cpu_strict(two->cpu, strict); cpu_trace(two->cpu, trace_path); cpu_reset(two->cpu);