static void handle_queued_ops(int queued_op, int num_queued) { switch(queued_op) { case '+': op_inc(num_queued); break; case '-': op_dec(num_queued); break; case '>': op_mvr(num_queued); break; case '<': op_mvl(num_queued); break; } }
//------------------------------------------------------------------------ static void process_immediate_number(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { // case DSP56_asl: // case DSP56_asr: case DSP56_bchg: case DSP56_bclr: case DSP56_brclr: case DSP56_brset: case DSP56_bsclr: case DSP56_bset: case DSP56_bsset: case DSP56_btst: case DSP56_jclr: case DSP56_jset: case DSP56_jsclr: case DSP56_jsset: // case DSP56_lsl: // case DSP56_lsr: op_dec(cmd.ea, n); break; case DSP56_add: case DSP56_and: case DSP56_andi: case DSP56_cmp: case DSP56_eor: case DSP56_extract: case DSP56_extractu: case DSP56_insert: case DSP56_mac: case DSP56_maci: case DSP56_macr: case DSP56_macri: case DSP56_mpy: case DSP56_mpyi: case DSP56_mpyr: case DSP56_mpyri: case DSP56_or: case DSP56_ori: case DSP56_sub: case DSP56_do: case DSP56_dor: case DSP56_rep: op_num(cmd.ea, n); break; } }
//-------------------------------------------------------------------------- static void declare_class(ea_t ea, const char *entryname) { static const char class_name[] = "ClassStruct"; struc_t *sptr = get_struc(get_struc_id(class_name)); if ( sptr == NULL ) { sptr = get_struc(add_struc(BADADDR, class_name)); if ( sptr == NULL ) return; opinfo_t mt; mt.ri.flags = REF_OFF32; mt.ri.target = BADADDR; mt.ri.base = 0; mt.ri.tdelta = 0; add_struc_member(sptr, "superClass", BADADDR, offflag()|dwrdflag(), &mt, 4); add_struc_member(sptr, "masterOffset", BADADDR, wordflag(), NULL, 2); add_struc_member(sptr, "methodCount", BADADDR, decflag()|wordflag(), NULL, 2); add_struc_member(sptr, "instanceSize", BADADDR, decflag()|wordflag(), NULL, 2); add_struc_member(sptr, "vdRelocTable", BADADDR, wordflag(), NULL, 2); add_struc_member(sptr, "relocTable", BADADDR, wordflag(), NULL, 2); mt.ec.tid = get_class_struct_flags_enum(); mt.ec.serial = 0; add_struc_member(sptr, "flags", BADADDR, enumflag()|byteflag(), &mt, 1); add_struc_member(sptr, "masterMethods",BADADDR, byteflag(), NULL, 1); } asize_t size = get_struc_size(sptr); doStruct(ea, size, sptr->id); int count = get_word(ea+6); // bool c_handlers = get_byte(ea+14) & (1<<6); ea += size; ea_t messages = ea; doWord(ea, count*2); op_dec(ea, 0); ea += 2*count; doDwrd(ea, count*4); set_offset(ea, 0, 0); for ( int i=0; i < count; i++ ) { ea_t idx = ea + 4*i; ea_t pea = toEA(get_word(idx+2), get_word(idx)); auto_make_proc(pea); char name[MAXSTR]; qsnprintf(name, sizeof(name), "%s_%u", entryname, get_word(messages+2*i)); add_entry(pea, pea, name, true); } // commented out because it doesn't work properly // see geoplan.geo, entry number 1 for example // if ( c_handlers ) // declare_parameter_types(ea+count*4, count); }
//------------------------------------------------------------------------ static void process_immediate_number(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { case H8500_add_q: case H8500_bclr: case H8500_bnot: case H8500_bset: case H8500_btst: op_dec(cmd.ea, n); break; case H8500_and: case H8500_or: case H8500_xor: case H8500_andc: case H8500_orc: case H8500_xorc: op_num(cmd.ea, n); break; } }
//------------------------------------------------------------------------ static void process_immediate_number(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { case H8_shal: case H8_shar: case H8_shll: case H8_shlr: case H8_rotl: case H8_rotr: case H8_rotxl: case H8_rotxr: op_dec(cmd.ea, n); break; case H8_and: case H8_or: case H8_xor: op_num(cmd.ea, n); break; } }
static void op_imm(int n) { doImmd(cmd.ea); if (isDefArg(uFlag, n)) return; switch (cmd.itype) { case M8B_ADD: case M8B_ADC: case M8B_SUB: case M8B_SBB: op_dec(cmd.ea, n); break; case M8B_CMP: case M8B_MOV: case M8B_AND: case M8B_OR: case M8B_XOR: op_num(cmd.ea, n); break; } }
void ucom4_cpu_device::execute_run() { while (m_icount > 0) { m_icount--; // remember previous opcode m_prev_op = m_op; // handle interrupt - it not accepted during LI($9x) or EI($31), or while skipping if (m_int_f && m_inte_f && (m_prev_op & 0xf0) != 0x90 && m_prev_op != 0x31 && !m_skip) { m_icount--; push_stack(); m_pc = 0xf << 2; m_int_f = 0; m_inte_f = (m_family == NEC_UCOM43) ? 0 : 1; standard_irq_callback(0); } // fetch next opcode debugger_instruction_hook(this, m_pc); m_op = m_program->read_byte(m_pc); m_bitmask = 1 << (m_op & 0x03); increment_pc(); fetch_arg(); if (m_skip) { m_skip = false; m_op = 0; // nop } // handle opcode switch (m_op & 0xf0) { case 0x80: op_ldz(); break; case 0x90: op_li(); break; case 0xa0: op_jmpcal(); break; case 0xb0: op_czp(); break; case 0xc0: case 0xd0: case 0xe0: case 0xf0: op_jcp(); break; default: switch (m_op) { case 0x00: op_nop(); break; case 0x01: op_di(); break; case 0x02: op_s(); break; case 0x03: op_tit(); break; case 0x04: op_tc(); break; case 0x05: op_ttm(); break; case 0x06: op_daa(); break; case 0x07: op_tal(); break; case 0x08: op_ad(); break; case 0x09: op_ads(); break; case 0x0a: op_das(); break; case 0x0b: op_clc(); break; case 0x0c: op_cm(); break; case 0x0d: op_inc(); break; case 0x0e: op_op(); break; case 0x0f: op_dec(); break; case 0x10: op_cma(); break; case 0x11: op_cia(); break; case 0x12: op_tla(); break; case 0x13: op_ded(); break; case 0x14: op_stm(); break; case 0x15: op_ldi(); break; case 0x16: op_cli(); break; case 0x17: op_ci(); break; case 0x18: op_exl(); break; case 0x19: op_adc(); break; case 0x1a: op_xc(); break; case 0x1b: op_stc(); break; case 0x1c: op_illegal(); break; case 0x1d: op_inm(); break; case 0x1e: op_ocd(); break; case 0x1f: op_dem(); break; case 0x30: op_rar(); break; case 0x31: op_ei(); break; case 0x32: op_ip(); break; case 0x33: op_ind(); break; case 0x40: op_ia(); break; case 0x41: op_jpa(); break; case 0x42: op_taz(); break; case 0x43: op_taw(); break; case 0x44: op_oe(); break; case 0x45: op_illegal(); break; case 0x46: op_tly(); break; case 0x47: op_thx(); break; case 0x48: op_rt(); break; case 0x49: op_rts(); break; case 0x4a: op_xaz(); break; case 0x4b: op_xaw(); break; case 0x4c: op_xls(); break; case 0x4d: op_xhr(); break; case 0x4e: op_xly(); break; case 0x4f: op_xhx(); break; default: switch (m_op & 0xfc) { case 0x20: op_fbf(); break; case 0x24: op_tab(); break; case 0x28: op_xm(); break; case 0x2c: op_xmd(); break; case 0x34: op_cmb(); break; case 0x38: op_lm(); break; case 0x3c: op_xmi(); break; case 0x50: op_tpb(); break; case 0x54: op_tpa(); break; case 0x58: op_tmb(); break; case 0x5c: op_fbt(); break; case 0x60: op_rpb(); break; case 0x64: op_reb(); break; case 0x68: op_rmb(); break; case 0x6c: op_rfb(); break; case 0x70: op_spb(); break; case 0x74: op_seb(); break; case 0x78: op_smb(); break; case 0x7c: op_sfb(); break; } break; // 0xfc } break; // 0xff } // big switch } }
//------------------------------------------------------------------------ static void process_immediate_number(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { case OAK_Dsp_shfi: case OAK_Dsp_movsi: op_dec(cmd.ea, n); uFlag = getFlags(cmd.ea); break; case OAK_Dsp_lpg: case OAK_Dsp_mpyi: case OAK_Dsp_mov: case OAK_Dsp_rets: case OAK_Dsp_rep: case OAK_Dsp_load: case OAK_Dsp_push: case OAK_Dsp_bkrep: case OAK_Dsp_msu: case OAK_Dsp_tstb: case OAK_Dsp_or: case OAK_Dsp_and: case OAK_Dsp_xor: case OAK_Dsp_add: case OAK_Dsp_alm_tst0: case OAK_Dsp_alm_tst1: case OAK_Dsp_cmp: case OAK_Dsp_sub: case OAK_Dsp_alm_msu: case OAK_Dsp_addh: case OAK_Dsp_addl: case OAK_Dsp_subh: case OAK_Dsp_subl: case OAK_Dsp_sqr: case OAK_Dsp_sqra: case OAK_Dsp_cmpu: case OAK_Dsp_set: case OAK_Dsp_rst: case OAK_Dsp_chng: case OAK_Dsp_addv: case OAK_Dsp_alb_tst0: case OAK_Dsp_alb_tst1: case OAK_Dsp_cmpv: case OAK_Dsp_subv: case OAK_Dsp_mpy: case OAK_Dsp_mpysu: case OAK_Dsp_mac: case OAK_Dsp_macus: case OAK_Dsp_maa: case OAK_Dsp_macuu: case OAK_Dsp_macsu: case OAK_Dsp_maasu: op_num(cmd.ea, n); uFlag = getFlags(cmd.ea); break; } }
void Step() { Opcodes OP = (Opcodes)Fetch8(); //printf("%08X:%08X\n", Registers[sp], Registers[pc]); switch (OP) { case O_NOP: op_nop(); break; case O_MOV: op_mov(); break; case O_ADD: op_add(); break; case O_SUB: op_sub(); break; case O_MUL: op_mul(); break; case O_DIV: op_div(); break; case O_LI: op_li(); break; case O_MOVF: op_movf(); break; case O_ADDF: op_addf(); break; case O_SUBF: op_subf(); break; case O_MULF: op_mulf(); break; case O_DIVF: op_divf(); break; case O_LIF: op_lif(); break; case O_XOR: op_xor(); break; case O_AND: op_and(); break; case O_MOD: op_mod(); break; case O_OR: op_or(); break; case O_NOT: op_not(); break; case O_SHR: op_shr(); break; case O_SHL: op_shl(); break; case O_PUSH: op_push(); break; case O_POP: op_pop(); break; case O_STB: op_stb(); break; case O_LDB: op_ldb(); break; case O_STH: op_sth(); break; case O_LDH: op_ldh(); break; case O_STW: op_stw(); break; case O_LDW: op_ldw(); break; case O_LDF: op_ldf(); break; case O_STF: op_stf(); break; case O_CMP: op_cmp(); break; case O_B: op_b(0); break; case O_BC: op_b(1); break; case O_BEQ: op_bcond(ctr0_eq); break; case O_BNE: op_bcond(ctr0_ne); break; case O_BGT: op_bcond(ctr0_gt); break; case O_BLT: op_bcond(ctr0_lt); break; case O_BTC: op_btc(); break; case O_INC: op_inc(); break; case O_DEC: op_dec(); break; default: Error("Error: Unknown Opcode PC = %d OP = %08X\n", Registers[pc], OP); } Ticks++; }
static void mc6809_run(struct MC6809 *cpu) { do { _Bool nmi_active = cpu->nmi && ((cpu->cycle - cpu->nmi_cycle) <= (UINT_MAX/2)); _Bool firq_active = cpu->firq && ((cpu->cycle - cpu->firq_cycle) <= (UINT_MAX/2)); _Bool irq_active = cpu->irq && ((cpu->cycle - cpu->irq_cycle) <= (UINT_MAX/2)); // Prevent overflow if (firq_active) cpu->firq_cycle = cpu->cycle; if (irq_active) cpu->irq_cycle = cpu->cycle; switch (cpu->state) { case mc6809_state_reset: REG_DP = 0; REG_CC |= (CC_F | CC_I); cpu->nmi = 0; cpu->nmi_armed = 0; cpu->state = mc6809_state_reset_check_halt; // fall through case mc6809_state_reset_check_halt: if (cpu->halt) { NVMA_CYCLE; continue; } REG_PC = fetch_byte(cpu, MC6809_INT_VEC_RESET) << 8; REG_PC |= fetch_byte(cpu, MC6809_INT_VEC_RESET + 1); NVMA_CYCLE; cpu->state = mc6809_state_label_a; continue; // done_instruction case for backwards-compatibility case mc6809_state_done_instruction: case mc6809_state_label_a: if (cpu->halt) { NVMA_CYCLE; continue; } cpu->state = mc6809_state_label_b; // fall through case mc6809_state_label_b: if (cpu->nmi_armed && nmi_active) { peek_byte(cpu, REG_PC); peek_byte(cpu, REG_PC); stack_irq_registers(cpu, 1); cpu->state = mc6809_state_dispatch_irq; continue; } if (!(REG_CC & CC_F) && firq_active) { peek_byte(cpu, REG_PC); peek_byte(cpu, REG_PC); stack_irq_registers(cpu, 0); cpu->state = mc6809_state_dispatch_irq; continue; } if (!(REG_CC & CC_I) && irq_active) { peek_byte(cpu, REG_PC); peek_byte(cpu, REG_PC); stack_irq_registers(cpu, 1); cpu->state = mc6809_state_dispatch_irq; continue; } cpu->state = mc6809_state_next_instruction; // Instruction fetch hook called here so that machine // can be stopped beforehand. DELEGATE_SAFE_CALL0(cpu->instruction_hook); continue; case mc6809_state_dispatch_irq: if (cpu->nmi_armed && nmi_active) { cpu->nmi = 0; REG_CC |= (CC_F | CC_I); take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_NMI); cpu->state = mc6809_state_label_a; continue; } if (!(REG_CC & CC_F) && firq_active) { REG_CC |= (CC_F | CC_I); take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_FIRQ); cpu->state = mc6809_state_label_a; continue; } if (!(REG_CC & CC_I) && irq_active) { REG_CC |= CC_I; take_interrupt(cpu, CC_I, MC6809_INT_VEC_IRQ); cpu->state = mc6809_state_label_a; continue; } cpu->state = mc6809_state_cwai_check_halt; continue; case mc6809_state_cwai_check_halt: NVMA_CYCLE; if (cpu->halt) { continue; } cpu->state = mc6809_state_dispatch_irq; continue; case mc6809_state_sync: if (nmi_active || firq_active || irq_active) { NVMA_CYCLE; NVMA_CYCLE; instruction_posthook(cpu); cpu->state = mc6809_state_label_b; continue; } NVMA_CYCLE; if (cpu->halt) cpu->state = mc6809_state_sync_check_halt; continue; case mc6809_state_sync_check_halt: NVMA_CYCLE; if (!cpu->halt) { cpu->state = mc6809_state_sync; } continue; case mc6809_state_next_instruction: { unsigned op; // Fetch op-code and process op = byte_immediate(cpu); switch (op) { // 0x00 - 0x0f direct mode ops // 0x40 - 0x4f inherent A register ops // 0x50 - 0x5f inherent B register ops // 0x60 - 0x6f indexed mode ops // 0x70 - 0x7f extended mode ops case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0f: case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4f: case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5f: case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6f: case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7f: { uint16_t ea; unsigned tmp1; switch ((op >> 4) & 0xf) { case 0x0: ea = ea_direct(cpu); tmp1 = fetch_byte(cpu, ea); break; case 0x4: ea = 0; tmp1 = RREG_A; break; case 0x5: ea = 0; tmp1 = RREG_B; break; case 0x6: ea = ea_indexed(cpu); tmp1 = fetch_byte(cpu, ea); break; case 0x7: ea = ea_extended(cpu); tmp1 = fetch_byte(cpu, ea); break; default: ea = tmp1 = 0; break; } switch (op & 0xf) { case 0x1: // NEG illegal case 0x0: tmp1 = op_neg(cpu, tmp1); break; // NEG, NEGA, NEGB case 0x2: tmp1 = op_negcom(cpu, tmp1); break; // NEGCOM illegal case 0x3: tmp1 = op_com(cpu, tmp1); break; // COM, COMA, COMB case 0x5: // LSR illegal case 0x4: tmp1 = op_lsr(cpu, tmp1); break; // LSR, LSRA, LSRB case 0x6: tmp1 = op_ror(cpu, tmp1); break; // ROR, RORA, RORB case 0x7: tmp1 = op_asr(cpu, tmp1); break; // ASR, ASRA, ASRB case 0x8: tmp1 = op_asl(cpu, tmp1); break; // ASL, ASLA, ASLB case 0x9: tmp1 = op_rol(cpu, tmp1); break; // ROL, ROLA, ROLB case 0xb: // DEC illegal case 0xa: tmp1 = op_dec(cpu, tmp1); break; // DEC, DECA, DECB case 0xc: tmp1 = op_inc(cpu, tmp1); break; // INC, INCA, INCB case 0xd: tmp1 = op_tst(cpu, tmp1); break; // TST, TSTA, TSTB case 0xf: tmp1 = op_clr(cpu, tmp1); break; // CLR, CLRA, CLRB default: break; } switch (op & 0xf) { case 0xd: // TST NVMA_CYCLE; NVMA_CYCLE; break; default: // the rest need storing switch ((op >> 4) & 0xf) { default: case 0x0: case 0x6: case 0x7: NVMA_CYCLE; store_byte(cpu, ea, tmp1); break; case 0x4: WREG_A = tmp1; peek_byte(cpu, REG_PC); break; case 0x5: WREG_B = tmp1; peek_byte(cpu, REG_PC); break; } } } break; // 0x0e JMP direct // 0x6e JMP indexed // 0x7e JMP extended case 0x0e: case 0x6e: case 0x7e: { unsigned ea; switch ((op >> 4) & 0xf) { case 0x0: ea = ea_direct(cpu); break; case 0x6: ea = ea_indexed(cpu); break; case 0x7: ea = ea_extended(cpu); break; default: ea = 0; break; } REG_PC = ea; } break; // 0x10 Page 2 case 0x10: cpu->state = mc6809_state_instruction_page_2; continue; // 0x11 Page 3 case 0x11: cpu->state = mc6809_state_instruction_page_3; continue; // 0x12 NOP inherent case 0x12: peek_byte(cpu, REG_PC); break; // 0x13 SYNC inherent case 0x13: peek_byte(cpu, REG_PC); cpu->state = mc6809_state_sync; continue; // 0x14, 0x15 HCF? (illegal) case 0x14: case 0x15: cpu->state = mc6809_state_hcf; goto done_instruction; // 0x16 LBRA relative case 0x16: { uint16_t ea; ea = long_relative(cpu); REG_PC += ea; NVMA_CYCLE; NVMA_CYCLE; } break; // 0x17 LBSR relative case 0x17: { uint16_t ea; ea = long_relative(cpu); ea += REG_PC; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; push_word(cpu, ®_S, REG_PC); REG_PC = ea; } break; // 0x18 Shift CC with mask inherent (illegal) case 0x18: REG_CC = (REG_CC << 1) & (CC_H | CC_Z); NVMA_CYCLE; peek_byte(cpu, REG_PC); break; // 0x19 DAA inherent case 0x19: { unsigned tmp = 0; if ((RREG_A&0x0f) >= 0x0a || REG_CC & CC_H) tmp |= 0x06; if (RREG_A >= 0x90 && (RREG_A&0x0f) >= 0x0a) tmp |= 0x60; if (RREG_A >= 0xa0 || REG_CC & CC_C) tmp |= 0x60; tmp += RREG_A; WREG_A = tmp; // CC.C NOT cleared, only set if appropriate CLR_NZV; SET_NZC8(tmp); peek_byte(cpu, REG_PC); } break; // 0x1a ORCC immediate case 0x1a: { unsigned data; data = byte_immediate(cpu); REG_CC |= data; peek_byte(cpu, REG_PC); } break; // 0x1b NOP inherent (illegal) case 0x1b: peek_byte(cpu, REG_PC); break; // 0x1c ANDCC immediate case 0x1c: { unsigned data; data = byte_immediate(cpu); REG_CC &= data; peek_byte(cpu, REG_PC); } break; // 0x1d SEX inherent case 0x1d: WREG_A = (RREG_B & 0x80) ? 0xff : 0; CLR_NZ; SET_NZ16(REG_D); peek_byte(cpu, REG_PC); break; // 0x1e EXG immediate case 0x1e: { unsigned postbyte; uint16_t tmp1, tmp2; postbyte = byte_immediate(cpu); switch (postbyte >> 4) { case 0x0: tmp1 = REG_D; break; case 0x1: tmp1 = REG_X; break; case 0x2: tmp1 = REG_Y; break; case 0x3: tmp1 = REG_U; break; case 0x4: tmp1 = REG_S; break; case 0x5: tmp1 = REG_PC; break; case 0x8: tmp1 = RREG_A | 0xff00; break; case 0x9: tmp1 = RREG_B | 0xff00; break; // TODO: verify this behaviour case 0xa: tmp1 = (REG_CC << 8) | REG_CC; break; case 0xb: tmp1 = (REG_DP << 8) | REG_DP; break; default: tmp1 = 0xffff; break; } switch (postbyte & 0xf) { case 0x0: tmp2 = REG_D; REG_D = tmp1; break; case 0x1: tmp2 = REG_X; REG_X = tmp1; break; case 0x2: tmp2 = REG_Y; REG_Y = tmp1; break; case 0x3: tmp2 = REG_U; REG_U = tmp1; break; case 0x4: tmp2 = REG_S; REG_S = tmp1; break; case 0x5: tmp2 = REG_PC; REG_PC = tmp1; break; case 0x8: tmp2 = RREG_A | 0xff00; WREG_A = tmp1; break; case 0x9: tmp2 = RREG_B | 0xff00; WREG_B = tmp1; break; // TODO: verify this behaviour case 0xa: tmp2 = (REG_CC << 8) | REG_CC; REG_CC = tmp1; break; case 0xb: tmp2 = (REG_DP << 8) | REG_DP; REG_DP = tmp1; break; default: tmp2 = 0xffff; break; } switch (postbyte >> 4) { case 0x0: REG_D = tmp2; break; case 0x1: REG_X = tmp2; break; case 0x2: REG_Y = tmp2; break; case 0x3: REG_U = tmp2; break; case 0x4: REG_S = tmp2; break; case 0x5: REG_PC = tmp2; break; case 0x8: WREG_A = tmp2; break; case 0x9: WREG_B = tmp2; break; case 0xa: REG_CC = tmp2; break; case 0xb: REG_DP = tmp2; break; default: break; } NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; } break; // 0x1f TFR immediate case 0x1f: { unsigned postbyte; uint16_t tmp1; postbyte = byte_immediate(cpu); switch (postbyte >> 4) { case 0x0: tmp1 = REG_D; break; case 0x1: tmp1 = REG_X; break; case 0x2: tmp1 = REG_Y; break; case 0x3: tmp1 = REG_U; break; case 0x4: tmp1 = REG_S; break; case 0x5: tmp1 = REG_PC; break; case 0x8: tmp1 = RREG_A | 0xff00; break; case 0x9: tmp1 = RREG_B | 0xff00; break; // TODO: verify this behaviour case 0xa: tmp1 = (REG_CC << 8) | REG_CC; break; case 0xb: tmp1 = (REG_DP << 8) | REG_DP; break; default: tmp1 = 0xffff; break; } switch (postbyte & 0xf) { case 0x0: REG_D = tmp1; break; case 0x1: REG_X = tmp1; break; case 0x2: REG_Y = tmp1; break; case 0x3: REG_U = tmp1; break; case 0x4: REG_S = tmp1; break; case 0x5: REG_PC = tmp1; break; case 0x8: WREG_A = tmp1; break; case 0x9: WREG_B = tmp1; break; case 0xa: REG_CC = tmp1; break; case 0xb: REG_DP = tmp1; break; default: break; } NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; } break; // 0x20 - 0x2f short branches case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: { unsigned tmp = sex8(byte_immediate(cpu)); NVMA_CYCLE; if (branch_condition(cpu, op)) REG_PC += tmp; } break; // 0x30 LEAX indexed case 0x30: REG_X = ea_indexed(cpu); CLR_Z; SET_Z(REG_X); NVMA_CYCLE; break; // 0x31 LEAY indexed case 0x31: REG_Y = ea_indexed(cpu); CLR_Z; SET_Z(REG_Y); NVMA_CYCLE; break; // 0x32 LEAS indexed case 0x32: REG_S = ea_indexed(cpu); NVMA_CYCLE; cpu->nmi_armed = 1; // XXX: Really? break; // 0x33 LEAU indexed case 0x33: REG_U = ea_indexed(cpu); NVMA_CYCLE; break; // 0x34 PSHS immediate case 0x34: psh(cpu, ®_S, REG_U); break; // 0x35 PULS immediate case 0x35: pul(cpu, ®_S, ®_U); break; // 0x36 PSHU immediate case 0x36: psh(cpu, ®_U, REG_S); break; // 0x37 PULU immediate case 0x37: pul(cpu, ®_U, ®_S); break; // 0x38 ANDCC immediate (illegal) case 0x38: { unsigned data; data = byte_immediate(cpu); REG_CC &= data; peek_byte(cpu, REG_PC); /* Differs from legal 0x1c version by * taking one more cycle: */ NVMA_CYCLE; } break; // 0x39 RTS inherent case 0x39: peek_byte(cpu, REG_PC); REG_PC = pull_word(cpu, ®_S); NVMA_CYCLE; break; // 0x3a ABX inherent case 0x3a: REG_X += RREG_B; peek_byte(cpu, REG_PC); NVMA_CYCLE; break; // 0x3b RTI inherent case 0x3b: peek_byte(cpu, REG_PC); REG_CC = pull_byte(cpu, ®_S); if (REG_CC & CC_E) { WREG_A = pull_byte(cpu, ®_S); WREG_B = pull_byte(cpu, ®_S); REG_DP = pull_byte(cpu, ®_S); REG_X = pull_word(cpu, ®_S); REG_Y = pull_word(cpu, ®_S); REG_U = pull_word(cpu, ®_S); REG_PC = pull_word(cpu, ®_S); } else { REG_PC = pull_word(cpu, ®_S); } cpu->nmi_armed = 1; peek_byte(cpu, REG_S); break; // 0x3c CWAI immediate case 0x3c: { unsigned data; data = byte_immediate(cpu); REG_CC &= data; peek_byte(cpu, REG_PC); NVMA_CYCLE; stack_irq_registers(cpu, 1); NVMA_CYCLE; cpu->state = mc6809_state_dispatch_irq; goto done_instruction; } break; // 0x3d MUL inherent case 0x3d: { unsigned tmp = RREG_A * RREG_B; REG_D = tmp; CLR_ZC; SET_Z(tmp); if (tmp & 0x80) REG_CC |= CC_C; peek_byte(cpu, REG_PC); NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; } break; // 0x3e RESET (illegal) case 0x3e: peek_byte(cpu, REG_PC); push_irq_registers(cpu); instruction_posthook(cpu); take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_RESET); cpu->state = mc6809_state_label_a; continue; // 0x3f SWI inherent case 0x3f: peek_byte(cpu, REG_PC); stack_irq_registers(cpu, 1); instruction_posthook(cpu); take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_SWI); cpu->state = mc6809_state_label_a; continue; // 0x80 - 0xbf A register arithmetic ops // 0xc0 - 0xff B register arithmetic ops case 0x80: case 0x81: case 0x82: case 0x84: case 0x85: case 0x86: case 0x87: case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x90: case 0x91: case 0x92: case 0x94: case 0x95: case 0x96: case 0x98: case 0x99: case 0x9a: case 0x9b: case 0xa0: case 0xa1: case 0xa2: case 0xa4: case 0xa5: case 0xa6: case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xb0: case 0xb1: case 0xb2: case 0xb4: case 0xb5: case 0xb6: case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xc0: case 0xc1: case 0xc2: case 0xc4: case 0xc5: case 0xc6: case 0xc7: case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xd0: case 0xd1: case 0xd2: case 0xd4: case 0xd5: case 0xd6: case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xe0: case 0xe1: case 0xe2: case 0xe4: case 0xe5: case 0xe6: case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xf0: case 0xf1: case 0xf2: case 0xf4: case 0xf5: case 0xf6: case 0xf8: case 0xf9: case 0xfa: case 0xfb: { unsigned tmp1, tmp2; tmp1 = !(op & 0x40) ? RREG_A : RREG_B; switch ((op >> 4) & 3) { case 0: tmp2 = byte_immediate(cpu); break; case 1: tmp2 = byte_direct(cpu); break; case 2: tmp2 = byte_indexed(cpu); break; case 3: tmp2 = byte_extended(cpu); break; default: tmp2 = 0; break; } switch (op & 0xf) { case 0x0: tmp1 = op_sub(cpu, tmp1, tmp2); break; // SUBA, SUBB case 0x1: (void)op_sub(cpu, tmp1, tmp2); break; // CMPA, CMPB case 0x2: tmp1 = op_sbc(cpu, tmp1, tmp2); break; // SBCA, SBCB case 0x4: tmp1 = op_and(cpu, tmp1, tmp2); break; // ANDA, ANDB case 0x5: (void)op_and(cpu, tmp1, tmp2); break; // BITA, BITB case 0x6: tmp1 = op_ld(cpu, 0, tmp2); break; // LDA, LDB case 0x7: tmp1 = op_discard(cpu, tmp1, tmp2); break; // illegal case 0x8: tmp1 = op_eor(cpu, tmp1, tmp2); break; // EORA, EORB case 0x9: tmp1 = op_adc(cpu, tmp1, tmp2); break; // ADCA, ADCB case 0xa: tmp1 = op_or(cpu, tmp1, tmp2); break; // ORA, ORB case 0xb: tmp1 = op_add(cpu, tmp1, tmp2); break; // ADDA, ADDB default: break; } if (!(op & 0x40)) { WREG_A = tmp1; } else { WREG_B = tmp1; } } break; // 0x83, 0x93, 0xa3, 0xb3 SUBD // 0x8c, 0x9c, 0xac, 0xbc CMPX // 0xc3, 0xd3, 0xe3, 0xf3 ADDD case 0x83: case 0x93: case 0xa3: case 0xb3: case 0x8c: case 0x9c: case 0xac: case 0xbc: case 0xc3: case 0xd3: case 0xe3: case 0xf3: { unsigned tmp1, tmp2; tmp1 = !(op & 0x08) ? REG_D : REG_X; switch ((op >> 4) & 3) { case 0: tmp2 = word_immediate(cpu); break; case 1: tmp2 = word_direct(cpu); break; case 2: tmp2 = word_indexed(cpu); break; case 3: tmp2 = word_extended(cpu); break; default: tmp2 = 0; break; } switch (op & 0x4f) { case 0x03: tmp1 = op_sub16(cpu, tmp1, tmp2); break; // SUBD case 0x0c: (void)op_sub16(cpu, tmp1, tmp2); break; // CMPX case 0x43: tmp1 = op_add16(cpu, tmp1, tmp2); break; // ADDD default: break; } NVMA_CYCLE; if (!(op & 0x08)) { REG_D = tmp1; } } break; // 0x8d BSR // 0x9d, 0xad, 0xbd JSR case 0x8d: case 0x9d: case 0xad: case 0xbd: { unsigned ea; switch ((op >> 4) & 3) { case 0: ea = short_relative(cpu); ea += REG_PC; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; break; case 1: ea = ea_direct(cpu); peek_byte(cpu, ea); NVMA_CYCLE; break; case 2: ea = ea_indexed(cpu); peek_byte(cpu, ea); NVMA_CYCLE; break; case 3: ea = ea_extended(cpu); peek_byte(cpu, ea); NVMA_CYCLE; break; default: ea = 0; break; } push_word(cpu, ®_S, REG_PC); REG_PC = ea; } break; // 0x8e, 0x9e, 0xae, 0xbe LDX // 0xcc, 0xdc, 0xec, 0xfc LDD // 0xce, 0xde, 0xee, 0xfe LDU case 0x8e: case 0x9e: case 0xae: case 0xbe: case 0xcc: case 0xdc: case 0xec: case 0xfc: case 0xce: case 0xde: case 0xee: case 0xfe: { unsigned tmp1, tmp2; switch ((op >> 4) & 3) { case 0: tmp2 = word_immediate(cpu); break; case 1: tmp2 = word_direct(cpu); break; case 2: tmp2 = word_indexed(cpu); break; case 3: tmp2 = word_extended(cpu); break; default: tmp2 = 0; break; } tmp1 = op_ld16(cpu, 0, tmp2); switch (op & 0x42) { case 0x02: REG_X = tmp1; break; case 0x40: REG_D = tmp1; break; case 0x42: REG_U = tmp1; break; default: break; } } break; // 0x97, 0xa7, 0xb7 STA // 0xd7, 0xe7, 0xf7 STB case 0x97: case 0xa7: case 0xb7: case 0xd7: case 0xe7: case 0xf7: { uint16_t ea; uint8_t tmp1; tmp1 = !(op & 0x40) ? RREG_A : RREG_B; switch ((op >> 4) & 3) { case 1: ea = ea_direct(cpu); break; case 2: ea = ea_indexed(cpu); break; case 3: ea = ea_extended(cpu); break; default: ea = 0; break; } store_byte(cpu, ea, tmp1); CLR_NZV; SET_NZ8(tmp1); } break; // 0x9f, 0xaf, 0xbf STX // 0xdd, 0xed, 0xfd STD // 0xdf, 0xef, 0xff STU case 0x9f: case 0xaf: case 0xbf: case 0xdd: case 0xed: case 0xfd: case 0xdf: case 0xef: case 0xff: { uint16_t ea, tmp1; switch (op & 0x42) { case 0x02: tmp1 = REG_X; break; case 0x40: tmp1 = REG_D; break; case 0x42: tmp1 = REG_U; break; default: tmp1 = 0; break; } switch ((op >> 4) & 3) { case 1: ea = ea_direct(cpu); break; case 2: ea = ea_indexed(cpu); break; case 3: ea = ea_extended(cpu); break; default: ea = 0; break; } CLR_NZV; SET_NZ16(tmp1); store_byte(cpu, ea, tmp1 >> 8); store_byte(cpu, ea+1, tmp1); } break; // 0x8f STX immediate (illegal) // 0xcf STU immediate (illegal) // Illegal instruction only part working case 0x8f: case 0xcf: { unsigned tmp1; tmp1 = !(op & 0x40) ? REG_X : REG_U; (void)fetch_byte(cpu, REG_PC); REG_PC++; store_byte(cpu, REG_PC, tmp1); REG_PC++; CLR_NZV; REG_CC |= CC_N; } break; // 0xcd HCF? (illegal) case 0xcd: cpu->state = mc6809_state_hcf; goto done_instruction; // Illegal instruction default: NVMA_CYCLE; break; } cpu->state = mc6809_state_label_a; goto done_instruction; } case mc6809_state_instruction_page_2: { unsigned op; op = byte_immediate(cpu); switch (op) { // 0x10, 0x11 Page 2 case 0x10: case 0x11: cpu->state = mc6809_state_instruction_page_2; continue; // 0x1020 - 0x102f long branches case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: { unsigned tmp = word_immediate(cpu); if (branch_condition(cpu, op)) { REG_PC += tmp; NVMA_CYCLE; } NVMA_CYCLE; } break; // 0x103f SWI2 inherent case 0x3f: peek_byte(cpu, REG_PC); stack_irq_registers(cpu, 1); instruction_posthook(cpu); take_interrupt(cpu, 0, MC6809_INT_VEC_SWI2); cpu->state = mc6809_state_label_a; continue; // 0x1083, 0x1093, 0x10a3, 0x10b3 CMPD // 0x108c, 0x109c, 0x10ac, 0x10bc CMPY case 0x83: case 0x93: case 0xa3: case 0xb3: case 0x8c: case 0x9c: case 0xac: case 0xbc: { unsigned tmp1, tmp2; tmp1 = !(op & 0x08) ? REG_D : REG_Y; switch ((op >> 4) & 3) { case 0: tmp2 = word_immediate(cpu); break; case 1: tmp2 = word_direct(cpu); break; case 2: tmp2 = word_indexed(cpu); break; case 3: tmp2 = word_extended(cpu); break; default: tmp2 = 0; break; } (void)op_sub16(cpu, tmp1, tmp2); NVMA_CYCLE; } break; // 0x108e, 0x109e, 0x10ae, 0x10be LDY // 0x10ce, 0x10de, 0x10ee, 0x10fe LDS case 0x8e: case 0x9e: case 0xae: case 0xbe: case 0xce: case 0xde: case 0xee: case 0xfe: { unsigned tmp1, tmp2; switch ((op >> 4) & 3) { case 0: tmp2 = word_immediate(cpu); break; case 1: tmp2 = word_direct(cpu); break; case 2: tmp2 = word_indexed(cpu); break; case 3: tmp2 = word_extended(cpu); break; default: tmp2 = 0; break; } tmp1 = op_ld16(cpu, 0, tmp2); if (!(op & 0x40)) { REG_Y = tmp1; } else { REG_S = tmp1; cpu->nmi_armed = 1; } } break; // 0x109f, 0x10af, 0x10bf STY // 0x10df, 0x10ef, 0x10ff STS case 0x9f: case 0xaf: case 0xbf: case 0xdf: case 0xef: case 0xff: { unsigned ea, tmp1; tmp1 = !(op & 0x40) ? REG_Y : REG_S; switch ((op >> 4) & 3) { case 1: ea = ea_direct(cpu); break; case 2: ea = ea_indexed(cpu); break; case 3: ea = ea_extended(cpu); break; default: ea = 0; break; } CLR_NZV; SET_NZ16(tmp1); store_byte(cpu, ea, tmp1 >> 8); store_byte(cpu, ea+1, tmp1); } break; // Illegal instruction default: NVMA_CYCLE; break; } cpu->state = mc6809_state_label_a; goto done_instruction; } case mc6809_state_instruction_page_3: { unsigned op; op = byte_immediate(cpu); switch (op) { // 0x10, 0x11 Page 3 case 0x10: case 0x11: cpu->state = mc6809_state_instruction_page_3; continue; // 0x113F SWI3 inherent case 0x3f: peek_byte(cpu, REG_PC); stack_irq_registers(cpu, 1); instruction_posthook(cpu); take_interrupt(cpu, 0, MC6809_INT_VEC_SWI3); cpu->state = mc6809_state_label_a; continue; // 0x1183, 0x1193, 0x11a3, 0x11b3 CMPU // 0x118c, 0x119c, 0x11ac, 0x11bc CMPS case 0x83: case 0x93: case 0xa3: case 0xb3: case 0x8c: case 0x9c: case 0xac: case 0xbc: { unsigned tmp1, tmp2; tmp1 = !(op & 0x08) ? REG_U : REG_S; switch ((op >> 4) & 3) { case 0: tmp2 = word_immediate(cpu); break; case 1: tmp2 = word_direct(cpu); break; case 2: tmp2 = word_indexed(cpu); break; case 3: tmp2 = word_extended(cpu); break; default: tmp2 = 0; break; } (void)op_sub16(cpu, tmp1, tmp2); NVMA_CYCLE; } break; // Illegal instruction default: NVMA_CYCLE; break; } cpu->state = mc6809_state_label_a; goto done_instruction; } // Certain illegal instructions cause the CPU to lock up: case mc6809_state_hcf: NVMA_CYCLE; continue; } done_instruction: instruction_posthook(cpu); continue; } while (cpu->running); }