// license:BSD-3-Clause // copyright-holders:Nathan Woods NMI: m_nmi_asserted = false; @dummy_read_opcode_arg(0); @dummy_read_opcode_arg(0); @dummy_vma(1); m_cc |= CC_E; set_regop16(m_s); m_temp.w = entire_state_registers(); %PUSH_REGISTERS; m_cc |= CC_I | CC_F; set_ea(VECTOR_NMI); standard_irq_callback(INPUT_LINE_NMI); goto INTERRUPT_VECTOR; FIRQ: @dummy_read_opcode_arg(0); @dummy_read_opcode_arg(0); @dummy_vma(1); if (firq_saves_entire_state()) { m_cc |= CC_E; m_temp.w = entire_state_registers(); } else { m_cc &= ~CC_E; m_temp.w = partial_state_registers(); } set_regop16(m_s); %PUSH_REGISTERS; m_cc |= CC_I | CC_F; set_ea(VECTOR_FIRQ); standard_irq_callback(M6809_FIRQ_LINE); goto INTERRUPT_VECTOR; IRQ: @dummy_read_opcode_arg(0); @dummy_read_opcode_arg(0); @dummy_vma(1); m_cc |= CC_E; set_regop16(m_s); m_temp.w = entire_state_registers(); %PUSH_REGISTERS; m_cc |= CC_I; set_ea(VECTOR_IRQ); standard_irq_callback(M6809_IRQ_LINE); goto INTERRUPT_VECTOR; INTERRUPT_VECTOR: @dummy_vma(1); @m_pc.b.h = read_operand(0); @m_pc.b.l = read_operand(1); @dummy_vma(1); return; NEG8: @m_temp.b.l = read_operand(); m_temp.b.l = set_flags(CC_NZVC, (uint8_t)0, m_temp.b.l, -m_temp.b.l); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } @write_operand(m_temp.b.l); return; COM8: @m_temp.b.l = read_operand(); m_cc &= ~CC_V; m_cc |= CC_C; m_temp.b.l = set_flags(CC_NZ, (uint8_t) ~m_temp.b.l); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } @write_operand(m_temp.b.l); return; LSR8: @m_temp.b.l = read_operand(); m_cc &= ~CC_C; m_cc |= (m_temp.b.l & 1) ? CC_C : 0; m_temp.b.l = set_flags(CC_NZ, m_temp.b.l >> 1); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } @write_operand(m_temp.b.l); return; ROR8: @m_temp.b.l = read_operand(); m_temp.b.l = set_flags(CC_NZ, rotate_right(m_temp.b.l)); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } @write_operand(m_temp.b.l); return; ASR8: @m_temp.b.l = read_operand(); m_cc &= ~CC_C; m_cc |= (m_temp.b.l & 1) ? CC_C : 0; m_temp.b.l = set_flags(CC_NZ, ((int8_t) m_temp.b.l) >> 1); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } @write_operand(m_temp.b.l); return; ASL8: @m_temp.b.l = read_operand(); m_temp.b.l = set_flags(CC_NZVC, m_temp.b.l, m_temp.b.l, m_temp.b.l << 1); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } @write_operand(m_temp.b.l); return; ROL8: @m_temp.b.l = read_operand(); m_temp.b.l = set_flags(CC_NZV, m_temp.b.l, m_temp.b.l, rotate_left(m_temp.b.l)); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } @write_operand(m_temp.b.l); return; DEC8: @m_temp.b.l = read_operand(); m_temp.b.l = set_flags(CC_NZV, m_temp.b.l, 1, m_temp.b.l - 1); if(!hd6309_native_mode() || !is_register_addressing_mode()) { @dummy_read_opcode_arg(0); ; } @write_operand(m_temp.b.l); return; INC8: @m_temp.b.l = read_operand(); m_temp.b.l = set_flags(CC_NZV, m_temp.b.l, 1, m_temp.b.l + 1); if(!hd6309_native_mode() || !is_register_addressing_mode()) { @dummy_read_opcode_arg(0); ; } @write_operand(m_temp.b.l); return; TST8: @m_temp.b.l = read_operand(); set_flags(CC_NZV, m_temp.b.l); if(!hd6309_native_mode()) { @dummy_vma(1); ; } if(!is_register_addressing_mode()) { @dummy_vma(1); ; } return; JMP: m_pc.w = m_ea.w; return; CLR8: @read_operand(); m_cc &= ~CC_NZVC; m_cc |= CC_Z; if(!hd6309_native_mode() || !is_register_addressing_mode()) { @dummy_read_opcode_arg(0); ; } @write_operand(0); return; NEG16: m_temp.b.h = read_operand(0); m_temp.b.l = read_operand(1); m_temp.w = set_flags(CC_NZVC, (uint16_t)0, m_temp.w, -m_temp.w); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } write_operand(0, m_temp.b.h); write_operand(1, m_temp.b.l); return; LSR16: @m_temp.b.h = read_operand(0); @m_temp.b.l = read_operand(1); m_cc &= ~CC_C; m_cc |= (m_temp.w & 1) ? CC_C : 0; m_temp.w = set_flags(CC_NZ, m_temp.w >> 1); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } @write_operand(0, m_temp.b.h); write_operand(1, m_temp.b.l); return; ROR16: @m_temp.b.h = read_operand(0); @m_temp.b.l = read_operand(1); m_temp.w = set_flags(CC_NZ, rotate_right(m_temp.w)); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } @write_operand(0, m_temp.b.h); write_operand(1, m_temp.b.l); return; ASR16: @m_temp.b.h = read_operand(0); @m_temp.b.l = read_operand(1); m_cc &= ~CC_C; m_cc |= (m_temp.w & 1) ? CC_C : 0; m_temp.w = set_flags(CC_NZ, ((int16_t) m_temp.w) >> 1); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } @write_operand(0, m_temp.b.h); write_operand(1, m_temp.b.l); return; ASL16: @m_temp.b.h = read_operand(0); @m_temp.b.l = read_operand(1); m_temp.w = set_flags(CC_NZVC, m_temp.w, m_temp.w, m_temp.w << 1); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } @write_operand(0, m_temp.b.h); write_operand(1, m_temp.b.l); return; ROL16: @m_temp.b.h = read_operand(0); @m_temp.b.l = read_operand(1); m_temp.w = set_flags(CC_NZV, rotate_left(m_temp.w)); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } @write_operand(0, m_temp.b.h); write_operand(1, m_temp.b.l); return; DEC16: m_temp.b.h = read_operand(0); m_temp.b.l = read_operand(1); m_temp.w = set_flags(CC_NZVC, m_temp.w, 1, m_temp.w - 1); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } write_operand(0, m_temp.b.h); write_operand(1, m_temp.b.l); return; INC16: m_temp.b.h = read_operand(0); m_temp.b.l = read_operand(1); m_temp.w = set_flags(CC_NZVC, m_temp.w, 1, m_temp.w + 1); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } write_operand(0, m_temp.b.h); write_operand(1, m_temp.b.l); return; TST16: m_temp.b.h = read_operand(0); m_temp.b.l = read_operand(1); set_flags(CC_NZV, m_temp.w); if(!hd6309_native_mode()) { @dummy_vma(1); ; } if(!is_register_addressing_mode()) { @dummy_vma(1); ; } return; CLR16: if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } m_cc &= ~CC_NZVC; m_cc |= CC_Z; write_operand(0, 0x00); write_operand(1, 0x00); return; SUB8: m_temp.b.l = read_operand(); regop8() = set_flags(CC_NZVC, regop8(), m_temp.b.l, regop8() - m_temp.b.l); return; CMP8: m_temp.b.l = read_operand(); set_flags(CC_NZVC, regop8(), m_temp.b.l, regop8() - m_temp.b.l); return; SBC8: m_temp.b.l = read_operand(); regop8() = set_flags(CC_NZVC, regop8(), m_temp.b.l, regop8() - m_temp.b.l - (m_cc & CC_C ? 1 : 0)); return; AND8: m_cc &= ~CC_V; regop8() = set_flags(CC_NZ, (uint8_t)0, regop8(), regop8() & read_operand()); return; BIT8: m_cc &= ~CC_V; set_flags(CC_NZ, (uint8_t)0, regop8(), regop8() & read_operand()); return; EOR8: m_cc &= ~CC_V; regop8() = set_flags(CC_NZ, (uint8_t)0, regop8(), regop8() ^ read_operand()); return; ADC8: m_temp.b.l = read_operand(); regop8() = set_flags(add8_sets_h() ? CC_HNZVC : CC_NZVC, regop8(), m_temp.b.l, regop8() + m_temp.b.l + (m_cc & CC_C ? 1 : 0)); return; OR8: m_cc &= ~CC_V; regop8() = set_flags(CC_NZ, (uint8_t)0, regop8(), regop8() | read_operand()); return; ADD8: m_temp.b.l = read_operand(); regop8() = set_flags(add8_sets_h() ? CC_HNZVC : CC_NZVC, regop8(), m_temp.b.l, regop8() + m_temp.b.l); return; ADD16: @m_temp.b.h = read_operand(0); @m_temp.b.l = read_operand(1); regop16().w = set_flags(CC_NZVC, regop16().w, m_temp.w, regop16().w + m_temp.w); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } return; SUB16: @m_temp.b.h = read_operand(0); @m_temp.b.l = read_operand(1); regop16().w = set_flags(CC_NZVC, regop16().w, m_temp.w, regop16().w - m_temp.w); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } return; CMP16: @m_temp.b.h = read_operand(0); @m_temp.b.l = read_operand(1); set_flags(CC_NZVC, regop16().w, m_temp.w, regop16().w - m_temp.w); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } return; LD8: regop8() = read_operand(); set_flags(CC_NZV, regop8()); return; LD16: @regop16().b.h = read_operand(0); @regop16().b.l = read_operand(1); set_flags(CC_NZV, regop16().w); if (®op16() == &m_s) m_lds_encountered = true; return; ST8: write_ea(set_flags(CC_NZV, regop8())); return; ST16: @write_operand(0, regop16().b.h); @write_operand(1, regop16().b.l); set_flags(CC_NZV, regop16().w); return; NOP: if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } return; SYNC: // SYNC stops processing instructions until an interrupt request happens. // This doesn't require the corresponding interrupt to be enabled: if it // is disabled, execution continues with the next instruction. @dummy_read_opcode_arg(0); while(!m_nmi_asserted && !m_firq_line && !m_irq_line) { // massaging the PC this way makes the debugger's behavior more // intuitive m_pc.w--; @eat_remaining(); // unmassage... m_pc.w++; } @eat(1); return; DAA: daa(); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } return; ORCC: m_cc |= read_operand(); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } return; ANDCC: m_cc &= read_operand(); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } return; SEX: m_q.r.d = set_flags(CC_NZ, (int8_t) m_q.r.b); if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } return; BRANCH: @m_temp.b.l = read_opcode_arg(); if(!hd6309_native_mode()) { @dummy_vma(1); ; } if (branch_taken()) { m_pc.w += (int8_t) m_temp.b.l; } return; LBRANCH: @m_temp.b.h = read_opcode_arg(); @m_temp.b.l = read_opcode_arg(); if(!hd6309_native_mode()) { @dummy_vma(1); ; } if (branch_taken()) { m_pc.w += m_temp.w; if(!hd6309_native_mode()) { @dummy_vma(1); ; } } return; BSR: @m_temp.b.l = read_opcode_arg(); m_ea.w = m_pc.w + (int8_t) m_temp.b.l; @dummy_vma(hd6309_native_mode() ? 2 : 3); goto GOTO_SUBROUTINE; LBSR: @m_temp.b.h = read_opcode_arg(); @m_temp.b.l = read_opcode_arg(); m_ea.w = m_pc.w + (int16_t) m_temp.w; @dummy_vma(hd6309_native_mode() ? 2 : 4); goto GOTO_SUBROUTINE; JSR: @dummy_read_opcode_arg(0); @dummy_vma(1); goto GOTO_SUBROUTINE; GOTO_SUBROUTINE: @write_memory(--m_s.w, m_pc.b.l); @write_memory(--m_s.w, m_pc.b.h); m_pc.w = m_ea.w; return; RTS: m_temp.w = 0x80; // RTS is equivalent to "PULS PC" if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); ; } set_regop16(m_s); goto PULL_REGISTERS; ABX: m_x.w += m_q.r.b; if(!hd6309_native_mode()) { @dummy_read_opcode_arg(0); @dummy_vma(1); ; } return; MUL: mul(); @dummy_read_opcode_arg(0); @dummy_vma(hd6309_native_mode() ? 8 : 9); return; RTI: @dummy_read_opcode_arg(0); set_regop16(m_s); @m_cc = read_memory(regop16().w++); // PULS CC m_temp.w = ((m_cc & CC_E) ? entire_state_registers() : partial_state_registers()) & ~0x01; goto PULL_REGISTERS; CWAI: @m_cc &= read_opcode_arg(); @dummy_read_opcode_arg(0); @dummy_vma(1); m_cc |= CC_E; set_regop16(m_s); m_temp.w = entire_state_registers(); %PUSH_REGISTERS; while((m_ea.w = get_pending_interrupt()) == 0) { // massaging the PC this way makes the debugger's behavior more // intuitive m_pc.w -= 2; @eat_remaining(); // unmassage... m_pc.w += 2; } if (m_nmi_asserted) m_nmi_asserted = false; set_ea(m_ea.w); // need to do this to set the addressing mode m_cc |= CC_I | (m_ea.w != VECTOR_IRQ ? CC_F : 0); // invoke standard interrupt callback for MAME core switch (m_ea.w) { case VECTOR_NMI: standard_irq_callback(INPUT_LINE_NMI); break; case VECTOR_FIRQ: standard_irq_callback(M6809_FIRQ_LINE); break; case VECTOR_IRQ: standard_irq_callback(M6809_IRQ_LINE); break; default: break; } goto INTERRUPT_VECTOR; LEA_xy: regop16().w = set_flags(CC_Z, m_ea.w); @dummy_vma(1); return; LEA_us: if (®op16() == &m_s) m_lds_encountered = true; regop16().w = m_ea.w; @dummy_vma(1); return; PSHS: @m_temp.w = read_opcode_arg(); @dummy_vma(2); set_regop16(m_s); if(!hd6309_native_mode()) { @(void)read_memory(regop16().w); ; } goto PUSH_REGISTERS; PULS: @m_temp.w = read_opcode_arg(); @dummy_vma(hd6309_native_mode() ? 1 : 2); set_regop16(m_s); goto PULL_REGISTERS; PSHU: @m_temp.w = read_opcode_arg(); @dummy_vma(2); set_regop16(m_u); if(!hd6309_native_mode()) { @(void)read_memory(regop16().w); ; } goto PUSH_REGISTERS; PULU: @m_temp.w = read_opcode_arg(); @dummy_vma(hd6309_native_mode() ? 1 : 2); set_regop16(m_u); goto PULL_REGISTERS; SWI: // doesn't use SOFTWARE_INTERRUPT label because SWI will // inhibit IRQ/FIRQ set_ea(VECTOR_SWI); standard_irq_callback(M6809_SWI); m_cc |= CC_E; set_regop16(m_s); m_temp.w = entire_state_registers(); @dummy_read_opcode_arg(0); @dummy_vma(1); %PUSH_REGISTERS; m_cc |= CC_I | CC_F; goto INTERRUPT_VECTOR; SWI2: set_ea(VECTOR_SWI2); standard_irq_callback(M6809_SWI); goto SOFTWARE_INTERRUPT; SWI3: set_ea(VECTOR_SWI3); standard_irq_callback(M6809_SWI); goto SOFTWARE_INTERRUPT; SOFTWARE_INTERRUPT: // used for SWI2/SWI3 and illegal/div0 on 6309 m_cc |= CC_E; set_regop16(m_s); m_temp.w = entire_state_registers(); @dummy_read_opcode_arg(0); @dummy_vma(1); %PUSH_REGISTERS; goto INTERRUPT_VECTOR; DIRECT: @set_ea(((uint16_t)m_dp << 8) | read_opcode_arg()); if(!hd6309_native_mode()) { @dummy_vma(1); ; } return; EXTENDED: @set_ea_h(read_opcode_arg()); @set_ea_l(read_opcode_arg()); if(!hd6309_native_mode()) { @dummy_vma(1); ; } return;