/***************************************************************************** h6280.c - Portable HuC6280 emulator Copyright Bryan McPhail, mish@tendril.co.uk This source code is based (with permission!) on the 6502 emulator by Juergen Buchmueller. It is released as part of the Mame emulator project. Let me know if you intend to use this code in any other project. NOTICE: This code is around 99% complete! Several things are unimplemented, some due to lack of time, some due to lack of documentation, mainly due to lack of programs using these features. csh, csl opcodes are not supported. I am unsure if flag B is set upon execution of rti. Cycle counts should be quite accurate. Changelog, version 1.02: JMP + indirect X (0x7c) opcode fixed. SMB + RMB opcodes fixed in disassembler. change_pc function calls removed. TSB & TRB now set flags properly. BIT opcode altered. Changelog, version 1.03: Swapped IRQ mask for IRQ1 & IRQ2 (thanks Yasuhiro) Changelog, version 1.04, 28/9/99-22/10/99: Adjusted RTI (thanks Karl) TST opcodes fixed in disassembler (missing break statements in a case!). TST behaviour fixed. SMB/RMB/BBS/BBR fixed in disassembler. Changelog, version 1.05, 8/12/99-16/12/99: Added CAB's timer implementation (note: irq ack & timer reload are changed). Fixed STA IDX. Fixed B flag setting on BRK. Assumed CSH & CSL to take 2 cycles each. Todo: Performance could be improved by precalculating timer fire position. Changelog, version 1.06, 4/5/00 - last opcode bug found? JMP indirect was doing a EAL++; instead of EAD++; - Obviously causing a corrupt read when L = 0xff! This fixes Bloody Wolf and Trio The Punch! Changelog, version 1.07, 3/9/00: Changed timer to be single shot - fixes Crude Buster music in level 1. Changelog, version 1.08, 8/11/05: (Charles MacDonald) Changed timer implementation, no longer single shot and reading the timer registers returns the count only. Fixes the following: - Mesopotamia: Music tempo & in-game timer - Dragon Saber: DDA effects - Magical Chase: Music tempo and speed regulation - Cadash: Allows the first level to start - Turrican: Allows the game to start Changed PLX and PLY to set NZ flags. Fixes: - Afterburner: Graphics unpacking - Aoi Blink: Collision detection with background Fixed the decimal version of ADC/SBC to *not* update the V flag, only the binary ones do. Fixed B flag handling so it is always set outside of an interrupt; even after being set by PLP and RTI. Fixed P state after reset to set I and B, leaving T, D cleared and NVZC randomized (cleared in this case). Fixed interrupt processing order (Timer has highest priority followed by IRQ1 and finally IRQ2). Changelog, version 1.09, 1/07/06: (Rob Bohms) Added emulation of the T flag, fixes PCE Ankuku Densetsu title screen Changelog, version 1.10, 5/09/07: (Wilbert Pol) - Taking of interrupts is delayed to respect a pending instruction already in the instruction pipeline; fixes After Burner. - Added 1 cycle for decimal mode ADC and SBC instructions. - Changed cycle counts for CSH and CSL instructions to 3. - Added T flag support to the SBC instruction. - Fixed ADC T flag to set the Z flag based on the value read. - Added 3 cycle penalty to ADC, AND, EOR, ORA, and SBC instructions when the T flag is set. - Fixed cycle count and support for 65536 byte blocks for the TAI, TDD, TIA, TII, and TIN instructions. - Fixed RDWORD macro in the disassembler. - Fixed setting of N and V flags in the TST instructions. - Removed unneeded debug_mmr code. - Fixed TSB and TRB instructions. - Added 1 delay when accessing the VDC or VCE areas. - Implemented low and high speed cpu modes. Changelog, version 1.11, 18/09/07: (Wilbert Pol) - Improvements to the handling of taking of delayed interrupts. ******************************************************************************/ #include "h6280.h" #include "debugger.h" /* 6280 flags */ enum { _fC = 0x01, _fZ = 0x02, _fI = 0x04, _fD = 0x08, _fB = 0x10, _fT = 0x20, _fV = 0x40, _fN = 0x80 }; /* some shortcuts for improved readability */ #define A m_a #define X m_x #define Y m_y #define P m_p #define S m_sp.b.l #define EAL m_ea.b.l #define EAH m_ea.b.h #define EAW m_ea.w.l #define EAD m_ea.d #define ZPL m_zp.b.l #define ZPH m_zp.b.h #define ZPW m_zp.w.l #define ZPD m_zp.d #define PCL m_pc.b.l #define PCH m_pc.b.h #define PCW m_pc.w.l #define PCD m_pc.d //************************************************************************** // DEVICE INTERFACE //************************************************************************** const device_type H6280 = &device_creator; //------------------------------------------------- // h6280_device - constructor //------------------------------------------------- h6280_device::h6280_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : cpu_device(mconfig, H6280, "H6280", tag, owner, clock, "h6280", __FILE__), m_program_config("program", ENDIANNESS_LITTLE, 8, 21), m_io_config("io", ENDIANNESS_LITTLE, 8, 2) { // build the opcode table for (int op = 0; op < 256; op++) m_opcode[op] = s_opcodetable[op]; } const h6280_device::ophandler h6280_device::s_opcodetable[256] = { &h6280_device::op_00, &h6280_device::op_01, &h6280_device::op_02, &h6280_device::op_03, &h6280_device::op_04, &h6280_device::op_05, &h6280_device::op_06, &h6280_device::op_07, &h6280_device::op_08, &h6280_device::op_09, &h6280_device::op_0a, &h6280_device::op_0b, &h6280_device::op_0c, &h6280_device::op_0d, &h6280_device::op_0e, &h6280_device::op_0f, &h6280_device::op_10, &h6280_device::op_11, &h6280_device::op_12, &h6280_device::op_13, &h6280_device::op_14, &h6280_device::op_15, &h6280_device::op_16, &h6280_device::op_17, &h6280_device::op_18, &h6280_device::op_19, &h6280_device::op_1a, &h6280_device::op_1b, &h6280_device::op_1c, &h6280_device::op_1d, &h6280_device::op_1e, &h6280_device::op_1f, &h6280_device::op_20, &h6280_device::op_21, &h6280_device::op_22, &h6280_device::op_23, &h6280_device::op_24, &h6280_device::op_25, &h6280_device::op_26, &h6280_device::op_27, &h6280_device::op_28, &h6280_device::op_29, &h6280_device::op_2a, &h6280_device::op_2b, &h6280_device::op_2c, &h6280_device::op_2d, &h6280_device::op_2e, &h6280_device::op_2f, &h6280_device::op_30, &h6280_device::op_31, &h6280_device::op_32, &h6280_device::op_33, &h6280_device::op_34, &h6280_device::op_35, &h6280_device::op_36, &h6280_device::op_37, &h6280_device::op_38, &h6280_device::op_39, &h6280_device::op_3a, &h6280_device::op_3b, &h6280_device::op_3c, &h6280_device::op_3d, &h6280_device::op_3e, &h6280_device::op_3f, &h6280_device::op_40, &h6280_device::op_41, &h6280_device::op_42, &h6280_device::op_43, &h6280_device::op_44, &h6280_device::op_45, &h6280_device::op_46, &h6280_device::op_47, &h6280_device::op_48, &h6280_device::op_49, &h6280_device::op_4a, &h6280_device::op_4b, &h6280_device::op_4c, &h6280_device::op_4d, &h6280_device::op_4e, &h6280_device::op_4f, &h6280_device::op_50, &h6280_device::op_51, &h6280_device::op_52, &h6280_device::op_53, &h6280_device::op_54, &h6280_device::op_55, &h6280_device::op_56, &h6280_device::op_57, &h6280_device::op_58, &h6280_device::op_59, &h6280_device::op_5a, &h6280_device::op_5b, &h6280_device::op_5c, &h6280_device::op_5d, &h6280_device::op_5e, &h6280_device::op_5f, &h6280_device::op_60, &h6280_device::op_61, &h6280_device::op_62, &h6280_device::op_63, &h6280_device::op_64, &h6280_device::op_65, &h6280_device::op_66, &h6280_device::op_67, &h6280_device::op_68, &h6280_device::op_69, &h6280_device::op_6a, &h6280_device::op_6b, &h6280_device::op_6c, &h6280_device::op_6d, &h6280_device::op_6e, &h6280_device::op_6f, &h6280_device::op_70, &h6280_device::op_71, &h6280_device::op_72, &h6280_device::op_73, &h6280_device::op_74, &h6280_device::op_75, &h6280_device::op_76, &h6280_device::op_77, &h6280_device::op_78, &h6280_device::op_79, &h6280_device::op_7a, &h6280_device::op_7b, &h6280_device::op_7c, &h6280_device::op_7d, &h6280_device::op_7e, &h6280_device::op_7f, &h6280_device::op_80, &h6280_device::op_81, &h6280_device::op_82, &h6280_device::op_83, &h6280_device::op_84, &h6280_device::op_85, &h6280_device::op_86, &h6280_device::op_87, &h6280_device::op_88, &h6280_device::op_89, &h6280_device::op_8a, &h6280_device::op_8b, &h6280_device::op_8c, &h6280_device::op_8d, &h6280_device::op_8e, &h6280_device::op_8f, &h6280_device::op_90, &h6280_device::op_91, &h6280_device::op_92, &h6280_device::op_93, &h6280_device::op_94, &h6280_device::op_95, &h6280_device::op_96, &h6280_device::op_97, &h6280_device::op_98, &h6280_device::op_99, &h6280_device::op_9a, &h6280_device::op_9b, &h6280_device::op_9c, &h6280_device::op_9d, &h6280_device::op_9e, &h6280_device::op_9f, &h6280_device::op_a0, &h6280_device::op_a1, &h6280_device::op_a2, &h6280_device::op_a3, &h6280_device::op_a4, &h6280_device::op_a5, &h6280_device::op_a6, &h6280_device::op_a7, &h6280_device::op_a8, &h6280_device::op_a9, &h6280_device::op_aa, &h6280_device::op_ab, &h6280_device::op_ac, &h6280_device::op_ad, &h6280_device::op_ae, &h6280_device::op_af, &h6280_device::op_b0, &h6280_device::op_b1, &h6280_device::op_b2, &h6280_device::op_b3, &h6280_device::op_b4, &h6280_device::op_b5, &h6280_device::op_b6, &h6280_device::op_b7, &h6280_device::op_b8, &h6280_device::op_b9, &h6280_device::op_ba, &h6280_device::op_bb, &h6280_device::op_bc, &h6280_device::op_bd, &h6280_device::op_be, &h6280_device::op_bf, &h6280_device::op_c0, &h6280_device::op_c1, &h6280_device::op_c2, &h6280_device::op_c3, &h6280_device::op_c4, &h6280_device::op_c5, &h6280_device::op_c6, &h6280_device::op_c7, &h6280_device::op_c8, &h6280_device::op_c9, &h6280_device::op_ca, &h6280_device::op_cb, &h6280_device::op_cc, &h6280_device::op_cd, &h6280_device::op_ce, &h6280_device::op_cf, &h6280_device::op_d0, &h6280_device::op_d1, &h6280_device::op_d2, &h6280_device::op_d3, &h6280_device::op_d4, &h6280_device::op_d5, &h6280_device::op_d6, &h6280_device::op_d7, &h6280_device::op_d8, &h6280_device::op_d9, &h6280_device::op_da, &h6280_device::op_db, &h6280_device::op_dc, &h6280_device::op_dd, &h6280_device::op_de, &h6280_device::op_df, &h6280_device::op_e0, &h6280_device::op_e1, &h6280_device::op_e2, &h6280_device::op_e3, &h6280_device::op_e4, &h6280_device::op_e5, &h6280_device::op_e6, &h6280_device::op_e7, &h6280_device::op_e8, &h6280_device::op_e9, &h6280_device::op_ea, &h6280_device::op_eb, &h6280_device::op_ec, &h6280_device::op_ed, &h6280_device::op_ee, &h6280_device::op_ef, &h6280_device::op_f0, &h6280_device::op_f1, &h6280_device::op_f2, &h6280_device::op_f3, &h6280_device::op_f4, &h6280_device::op_f5, &h6280_device::op_f6, &h6280_device::op_f7, &h6280_device::op_f8, &h6280_device::op_f9, &h6280_device::op_fa, &h6280_device::op_fb, &h6280_device::op_fc, &h6280_device::op_fd, &h6280_device::op_fe, &h6280_device::op_ff }; void h6280_device::device_start() { // register our state for the debugger state_add(STATE_GENPC, "GENPC", m_pc.w.l).noshow(); state_add(STATE_GENFLAGS, "GENFLAGS", m_p).callimport().callexport().formatstr("%8s").noshow(); state_add(H6280_PC, "PC", m_pc.d).mask(0xffff); state_add(H6280_S, "S", m_sp.b.l).mask(0xff); state_add(H6280_P, "P", m_p).mask(0xff); state_add(H6280_A, "A", m_a).mask(0xff); state_add(H6280_X, "X", m_x).mask(0xff); state_add(H6280_Y, "Y", m_y).mask(0xff); state_add(H6280_IRQ_MASK, "IM", m_irq_mask).mask(0xff); state_add(H6280_TIMER_STATE,"TMR", m_timer_status).mask(0xff); state_add(H6280_NMI_STATE, "NMI", m_nmi_state).mask(0xf); state_add(H6280_IRQ1_STATE, "IRQ1", m_irq_state[0]).mask(0xf); state_add(H6280_IRQ2_STATE, "IRQ2", m_irq_state[1]).mask(0xf); state_add(H6280_IRQT_STATE, "IRQT", m_irq_state[2]).mask(0xf); state_add(H6280_M1, "M1", m_mmr[0]).mask(0xff); state_add(H6280_M2, "M2", m_mmr[1]).mask(0xff); state_add(H6280_M3, "M3", m_mmr[2]).mask(0xff); state_add(H6280_M4, "M4", m_mmr[3]).mask(0xff); state_add(H6280_M5, "M5", m_mmr[4]).mask(0xff); state_add(H6280_M6, "M6", m_mmr[5]).mask(0xff); state_add(H6280_M7, "M7", m_mmr[6]).mask(0xff); state_add(H6280_M8, "M8", m_mmr[7]).mask(0xff); save_item(NAME(m_ppc.w.l)); save_item(NAME(m_pc.w.l)); save_item(NAME(m_sp.w.l)); save_item(NAME(m_zp.w.l)); save_item(NAME(m_ea.w.l)); save_item(NAME(m_a)); save_item(NAME(m_x)); save_item(NAME(m_y)); save_item(NAME(m_p)); save_item(NAME(m_mmr)); save_item(NAME(m_irq_mask)); save_item(NAME(m_timer_status)); save_item(NAME(m_timer_ack)); save_item(NAME(m_clocks_per_cycle)); save_item(NAME(m_timer_value)); save_item(NAME(m_timer_load)); save_item(NAME(m_nmi_state)); save_item(NAME(m_irq_state[0])); save_item(NAME(m_irq_state[1])); save_item(NAME(m_irq_state[2])); save_item(NAME(m_irq_pending)); #if LAZY_FLAGS save_item(NAME(m_nz)); #endif save_item(NAME(m_io_buffer)); // set our instruction counter m_icountptr = &m_icount; m_icount = 0; /* clear pending interrupts */ for (int i = 0; i < 3; i++) { m_irq_state[i] = CLEAR_LINE; } m_nmi_state = CLEAR_LINE; } void h6280_device::device_reset() { /* wipe out the h6280 structure */ m_ppc.d = 0; m_pc.d = 0; m_zp.d = 0; m_ea.d = 0; m_a = 0; m_x = 0; m_y = 0; m_p = 0; memset(m_mmr, 0, sizeof(UINT8) * 8); m_irq_mask = 0; m_timer_ack = 0; m_timer_value = 0; #if LAZY_FLAGS m_nz = 0; #endif m_io_buffer = 0; m_program = &space(AS_PROGRAM); m_direct = &m_program->direct(); m_io = &space(AS_IO); /* set I and B flags */ P = _fI | _fB; /* stack starts at 0x01ff */ m_sp.d = 0x1ff; /* read the reset vector into PC */ PCL = program_read8(H6280_RESET_VEC); PCH = program_read8(H6280_RESET_VEC + 1); /* CPU starts in low speed mode */ m_clocks_per_cycle = 4; /* timer off by default */ m_timer_status = 0; m_timer_load = 128 * 1024; m_irq_pending = 0; } void h6280_device::device_stop() { /* nothing */ } inline UINT32 h6280_device::translated(UINT16 addr) { return ((m_mmr[((addr) >> 13) & 7] << 13) | ((addr) & 0x1fff)); } inline void h6280_device::h6280_cycles(int cyc) { m_icount -= ((cyc) * m_clocks_per_cycle); m_timer_value -= ((cyc) * m_clocks_per_cycle); } #if LAZY_FLAGS #define NZ m_NZ inline void h6280_device::set_nz(UINT8 n) { P &= ~_fT; NZ = ((n & _fN) << 8) | n; } #else inline void h6280_device::set_nz(UINT8 n) { P = (P & ~(_fN|_fT|_fZ)) | (n & _fN) | ((n == 0) ? _fZ : 0); } #endif inline void h6280_device::clear_t() { P &= ~_fT; } inline void h6280_device::do_interrupt(UINT16 vector) { h6280_cycles(7); /* 7 cycles for an int */ push(PCH); push(PCL); compose_p(0, _fB); push(P); P = (P & ~_fD) | _fI; /* knock out D and set I flag */ PCL = program_read8(vector); PCH = program_read8(vector + 1); } inline void h6280_device::check_and_take_irq_lines() { if ( m_nmi_state != CLEAR_LINE ) { m_nmi_state = CLEAR_LINE; do_interrupt(H6280_NMI_VEC); } else if( !(P & _fI) ) { if ( m_irq_state[2] != CLEAR_LINE && !(m_irq_mask & 0x4) ) { do_interrupt(H6280_TIMER_VEC); } else if ( m_irq_state[0] != CLEAR_LINE && !(m_irq_mask & 0x2) ) { do_interrupt(H6280_IRQ1_VEC); standard_irq_callback(0); } else if ( m_irq_state[1] != CLEAR_LINE && !(m_irq_mask & 0x1) ) { do_interrupt(H6280_IRQ2_VEC); standard_irq_callback(1); } } } inline void h6280_device::check_irq_lines() { if (!m_irq_pending) m_irq_pending = 2; } /*************************************************************** * CHECK_VDC_VCE_PENALTY * The CPU inserts 1 clock delay when accessing the VDC or VCE * area. ***************************************************************/ inline void h6280_device::check_vdc_vce_penalty(UINT16 addr) { if ( ( translated(addr) & 0x1FF800 ) == 0x1FE000 ) { h6280_cycles(1); } } /*************************************************************** * BRA branch relative ***************************************************************/ inline void h6280_device::bra(bool cond) { clear_t(); if (cond) { h6280_cycles(4); UINT8 tmp = read_opcode_arg(); PCW++; EAW = PCW + (signed char)tmp; PCD = EAD; } else { PCW++; h6280_cycles(2); } } /*************************************************************** * * Helper macros to build the effective address * ***************************************************************/ /*************************************************************** * EA = zero page address ***************************************************************/ inline void h6280_device::ea_zpg() { ZPL = read_opcode_arg(); PCW++; EAD = ZPD; } /*************************************************************** * EA = zero page address - T flag ***************************************************************/ inline void h6280_device::ea_tflg() { ZPL = X; EAD = ZPD; } /*************************************************************** * EA = zero page address + X ***************************************************************/ inline void h6280_device::ea_zpx() { ZPL = read_opcode_arg() + X; PCW++; EAD = ZPD; } /*************************************************************** * EA = zero page address + Y ***************************************************************/ inline void h6280_device::ea_zpy() { ZPL = read_opcode_arg() + Y; PCW++; EAD = ZPD; } /*************************************************************** * EA = absolute address ***************************************************************/ inline void h6280_device::ea_abs() { EAL = read_opcode_arg(); PCW++; EAH = read_opcode_arg(); PCW++; } /*************************************************************** * EA = absolute address + X ***************************************************************/ inline void h6280_device::ea_abx() { ea_abs(); EAW += X; } /*************************************************************** * EA = absolute address + Y ***************************************************************/ inline void h6280_device::ea_aby() { ea_abs(); EAW += Y; } /*************************************************************** * EA = zero page indirect (65c02 pre indexed w/o X) ***************************************************************/ inline void h6280_device::ea_zpi() { ZPL = read_opcode_arg(); PCW++; EAD = program_read16z(ZPD); } /*************************************************************** * EA = zero page + X indirect (pre indexed) ***************************************************************/ inline void h6280_device::ea_idx() { ZPL = read_opcode_arg() + X; PCW++; EAD = program_read16z(ZPD); } /*************************************************************** * EA = zero page indirect + Y (post indexed) ***************************************************************/ inline void h6280_device::ea_idy() { ZPL = read_opcode_arg(); PCW++; EAD = program_read16z(ZPD); EAW += Y; } /*************************************************************** * EA = indirect (only used by JMP) ***************************************************************/ inline void h6280_device::ea_ind() { ea_abs(); UINT8 tmp = program_read8(EAD); EAD++; EAH = program_read8(EAD); EAL = tmp; } /*************************************************************** * EA = indirect plus x (only used by JMP) ***************************************************************/ inline void h6280_device::ea_iax() { ea_abs(); EAD+=X; UINT8 tmp = program_read8(EAD); EAD++; EAH = program_read8(EAD); EAL = tmp; } inline UINT8 h6280_device::rd_imm() { UINT8 tmp = read_opcode_arg(); PCW++; return tmp; } inline UINT8 h6280_device::rd_zpg() { ea_zpg(); return program_read8z(EAD); } inline UINT8 h6280_device::rd_zpx() { ea_zpx(); return program_read8z(EAD); } inline UINT8 h6280_device::rd_zpy() { ea_zpy(); return program_read8z(EAD); } inline UINT8 h6280_device::rd_abs() { ea_abs(); return program_read8(EAD); } inline UINT8 h6280_device::rd_abx() { ea_abx(); return program_read8(EAD); } inline UINT8 h6280_device::rd_aby() { ea_aby(); return program_read8(EAD); } inline UINT8 h6280_device::rd_zpi() { ea_zpi(); return program_read8(EAD); } inline UINT8 h6280_device::rd_idx() { ea_idx(); return program_read8(EAD); } inline UINT8 h6280_device::rd_idy() { ea_idy(); return program_read8(EAD); } inline UINT8 h6280_device::rd_tfl() { ea_tflg(); return program_read8z(EAD); } inline void h6280_device::wr_zpg(UINT8 tmp) { ea_zpg(); wb_eaz(tmp); } inline void h6280_device::wr_zpx(UINT8 tmp) { ea_zpx(); wb_eaz(tmp); } inline void h6280_device::wr_zpy(UINT8 tmp) { ea_zpy(); wb_eaz(tmp); } inline void h6280_device::wr_abs(UINT8 tmp) { ea_abs(); wb_ea(tmp); } inline void h6280_device::wr_abx(UINT8 tmp) { ea_abx(); wb_ea(tmp); } inline void h6280_device::wr_aby(UINT8 tmp) { ea_aby(); wb_ea(tmp); } inline void h6280_device::wr_zpi(UINT8 tmp) { ea_zpi(); wb_ea(tmp); } inline void h6280_device::wr_idx(UINT8 tmp) { ea_idx(); wb_ea(tmp); } inline void h6280_device::wr_idy(UINT8 tmp) { ea_idy(); wb_ea(tmp); } inline void h6280_device::wb_ea(UINT8 tmp) { program_write8(EAD, tmp); } inline void h6280_device::wb_eaz(UINT8 tmp) { program_write8z(EAD, tmp); } /*************************************************************** * * Macros to emulate the 6280 opcodes * ***************************************************************/ /*************************************************************** * compose the real flag register by * including N and Z and set any * SET and clear any CLR bits also ***************************************************************/ #if LAZY_FLAGS inline void h6280_device::compose_p(UINT8 SET, UINT8 CLR) { P = (P & ~(_fN | _fZ | CLR)) | (NZ >> 8) | ((NZ & 0xff) ? 0 : _fZ) | SET; } #else inline void h6280_device::compose_p(UINT8 SET, UINT8 CLR) { P = (P & ~CLR) | SET; } #endif /* 6280 ******************************************************** * ADC Add with carry ***************************************************************/ inline void h6280_device::tadc(UINT8 tmp) { clear_t(); int tflagtemp = rd_tfl(); if (P & _fD) { int c = (P & _fC); int lo = (tflagtemp & 0x0f) + (tmp & 0x0f) + c; int hi = (tflagtemp & 0xf0) + (tmp & 0xf0); P &= ~_fC; if (lo > 0x09) { hi += 0x10; lo += 0x06; } if (hi > 0x90) hi += 0x60; if (hi & 0xff00) P |= _fC; tflagtemp = (lo & 0x0f) + (hi & 0xf0); h6280_cycles(1); } else { int c = (P & _fC); int sum = tflagtemp + tmp + c; P &= ~(_fV | _fC); if (~(tflagtemp^tmp) & (tflagtemp^sum) & _fN) P |= _fV; if (sum & 0xff00) P |= _fC; tflagtemp = (UINT8) sum; } set_nz(tflagtemp); wb_eaz(tflagtemp); h6280_cycles(3); } inline void h6280_device::adc(UINT8 tmp) { if(P & _fT) tadc(tmp); else { if (P & _fD) { int c = (P & _fC); int lo = (A & 0x0f) + (tmp & 0x0f) + c; int hi = (A & 0xf0) + (tmp & 0xf0); P &= ~_fC; if (lo > 0x09) { hi += 0x10; lo += 0x06; } if (hi > 0x90) hi += 0x60; if (hi & 0xff00) P |= _fC; A = (lo & 0x0f) + (hi & 0xf0); h6280_cycles(1); } else { int c = (P & _fC); int sum = A + tmp + c; P &= ~(_fV | _fC); if (~(A^tmp) & (A^sum) & _fN) P |= _fV; if (sum & 0xff00) P |= _fC; A = (UINT8) sum; } set_nz(A); } } /* 6280 ******************************************************** * AND Logical and ***************************************************************/ inline void h6280_device::tand(UINT8 tmp) { clear_t(); int tflagtemp = rd_tfl(); tflagtemp = (UINT8)(tflagtemp & tmp); wb_eaz(tflagtemp); set_nz(tflagtemp); h6280_cycles(3); } inline void h6280_device::and_a(UINT8 tmp) { if(P & _fT) tand(tmp); else { A = (UINT8)(A & tmp); set_nz(A); } } /* 6280 ******************************************************** * ASL Arithmetic shift left ***************************************************************/ inline UINT8 h6280_device::asl(UINT8 tmp) { clear_t(); P = (P & ~_fC) | ((tmp >> 7) & _fC); tmp = (UINT8)(tmp << 1); set_nz(tmp); return tmp; } /* 6280 ******************************************************** * BBR Branch if bit is reset ***************************************************************/ inline void h6280_device::bbr(int bit, UINT8 tmp) { bra(!(tmp & (1<= tmp) P |= _fC; set_nz((UINT8)(A - tmp)); } /* 6280 ******************************************************** * CPX Compare index X ***************************************************************/ inline void h6280_device::cpx(UINT8 tmp) { clear_t(); P &= ~_fC; if (X >= tmp) P |= _fC; set_nz((UINT8)(X - tmp)); } /* 6280 ******************************************************** * CPY Compare index Y ***************************************************************/ inline void h6280_device::cpy(UINT8 tmp) { clear_t(); P &= ~_fC; if (Y >= tmp) P |= _fC; set_nz((UINT8)(Y - tmp)); } /* 6280 ******************************************************** * DEC Decrement memory ***************************************************************/ inline UINT8 h6280_device::dec(UINT8 tmp) { clear_t(); tmp = (UINT8)(tmp-1); set_nz(tmp); return tmp; } /* 6280 ******************************************************** * DEX Decrement index X ***************************************************************/ inline void h6280_device::dex() { clear_t(); X = (UINT8)(X - 1); set_nz(X); } /* 6280 ******************************************************** * DEY Decrement index Y ***************************************************************/ inline void h6280_device::dey() { clear_t(); Y = (UINT8)(Y - 1); set_nz(Y); } /* 6280 ******************************************************** * EOR Logical exclusive or ***************************************************************/ inline void h6280_device::teor(UINT8 tmp) { clear_t(); int tflagtemp = rd_tfl(); tflagtemp = (UINT8)(tflagtemp ^ tmp); wb_eaz(tflagtemp); set_nz(tflagtemp); h6280_cycles(3); } inline void h6280_device::eor(UINT8 tmp) { if(P & _fT) teor(tmp); else { A = (UINT8)(A ^ tmp); set_nz(A); } } /* 6280 ******************************************************** * INC Increment memory ***************************************************************/ inline UINT8 h6280_device::inc(UINT8 tmp) { clear_t(); tmp = (UINT8)(tmp+1); set_nz(tmp); return tmp; } /* 6280 ******************************************************** * INX Increment index X ***************************************************************/ inline void h6280_device::inx() { clear_t(); X = (UINT8)(X + 1); set_nz(X); } /* 6280 ******************************************************** * INY Increment index Y ***************************************************************/ inline void h6280_device::iny() { clear_t(); Y = (UINT8)(Y + 1); set_nz(Y); } /* 6280 ******************************************************** * JMP Jump to address * set PC to the effective address ***************************************************************/ inline void h6280_device::jmp() { clear_t(); PCD = EAD; } /* 6280 ******************************************************** * JSR Jump to subroutine * decrement PC (sic!) push PC hi, push PC lo and set * PC to the effective address ***************************************************************/ inline void h6280_device::jsr() { clear_t(); PCW--; push(PCH); push(PCL); PCD = EAD; } /* 6280 ******************************************************** * LDA Load accumulator ***************************************************************/ inline void h6280_device::lda(UINT8 tmp) { clear_t(); A = (UINT8)tmp; set_nz(A); } /* 6280 ******************************************************** * LDX Load index X ***************************************************************/ inline void h6280_device::ldx(UINT8 tmp) { clear_t(); X = (UINT8)tmp; set_nz(X); } /* 6280 ******************************************************** * LDY Load index Y ***************************************************************/ inline void h6280_device::ldy(UINT8 tmp) { clear_t(); Y = (UINT8)tmp; set_nz(Y); } /* 6280 ******************************************************** * LSR Logic shift right * 0 -> [7][6][5][4][3][2][1][0] -> C ***************************************************************/ inline UINT8 h6280_device::lsr(UINT8 tmp) { clear_t(); P = (P & ~_fC) | (tmp & _fC); tmp = (UINT8)tmp >> 1; set_nz(tmp); return tmp; } /* 6280 ******************************************************** * NOP No operation ***************************************************************/ inline void h6280_device::nop() { clear_t(); } /* 6280 ******************************************************** * ORA Logical inclusive or ***************************************************************/ inline void h6280_device::tora(UINT8 tmp) { clear_t(); int tflagtemp = rd_tfl(); tflagtemp = (UINT8)(tflagtemp | tmp); wb_eaz(tflagtemp); set_nz(tflagtemp); h6280_cycles(3); } inline void h6280_device::ora(UINT8 tmp) { if(P & _fT) tora(tmp); else { A = (UINT8)(A | tmp); set_nz(A); } } /* 6280 ******************************************************** * PHA Push accumulator ***************************************************************/ inline void h6280_device::pha() { clear_t(); push(A); } /* 6280 ******************************************************** * PHP Push processor status (flags) ***************************************************************/ inline void h6280_device::php() { clear_t(); compose_p(0,0); push(P); } /* 6280 ******************************************************** * PHX Push index X ***************************************************************/ inline void h6280_device::phx() { clear_t(); push(X); } /* 6280 ******************************************************** * PHY Push index Y ***************************************************************/ inline void h6280_device::phy() { clear_t(); push(Y); } /* 6280 ******************************************************** * PLA Pull accumulator ***************************************************************/ inline void h6280_device::pla() { clear_t(); pull(A); set_nz(A); } /* 6280 ******************************************************** * PLP Pull processor status (flags) ***************************************************************/ inline void h6280_device::plp() { #if LAZY_FLAGS pull(P); P |= _fB; NZ = ((P & _fN) << 8) | ((P & _fZ) ^ _fZ); check_irq_lines(); #else pull(P); P |= _fB; check_irq_lines(); #endif } /* 6280 ******************************************************** * PLX Pull index X ***************************************************************/ inline void h6280_device::plx() { clear_t(); pull(X); set_nz(X); } /* 6280 ******************************************************** * PLY Pull index Y ***************************************************************/ inline void h6280_device::ply() { clear_t(); pull(Y); set_nz(Y); } /* 6280 ******************************************************** * RMB Reset memory bit ***************************************************************/ inline UINT8 h6280_device::rmb(int bit, UINT8 tmp) { clear_t(); tmp &= ~(1<> 8) & _fC); tmp = (UINT8)tmp9; set_nz(tmp); return tmp; } /* 6280 ******************************************************** * ROR Rotate right * C -> [7][6][5][4][3][2][1][0] -> new C ***************************************************************/ inline UINT8 h6280_device::ror(UINT8 tmp) { clear_t(); int tmp9 = tmp | (P & _fC) << 8; P = (P & ~_fC) | (tmp & _fC); tmp = (UINT8)(tmp9 >> 1); set_nz(tmp); return tmp; } /* 6280 ******************************************************** * RTI Return from interrupt * pull flags, pull PC lo, pull PC hi and increment PC ***************************************************************/ inline void h6280_device::rti() { #if LAZY_FLAGS pull(P); P |= _fB; NZ = ((P & _fN) << 8) | ((P & _fZ) ^ _fZ); pull(PCL); pull(PCH); check_irq_lines(); #else pull(P); P |= _fB; pull(PCL); pull(PCH); check_irq_lines(); #endif } /* 6280 ******************************************************** * RTS Return from subroutine * pull PC lo, PC hi and increment PC ***************************************************************/ inline void h6280_device::rts() { clear_t(); pull(PCL); pull(PCH); PCW++; } /* 6280 ******************************************************** * SAX Swap accumulator and index X ***************************************************************/ inline void h6280_device::sax() { clear_t(); UINT8 tmp = X; X = A; A = tmp; } /* 6280 ******************************************************** * SAY Swap accumulator and index Y ***************************************************************/ inline void h6280_device::say() { clear_t(); UINT8 tmp = Y; Y = A; A = tmp; } /* 6280 ******************************************************** * SBC Subtract with carry ***************************************************************/ inline void h6280_device::tsbc(UINT8 tmp) { clear_t(); int tflagtemp = rd_tfl(); if (P & _fD) { int c = (P & _fC) ^ _fC; int sum = tflagtemp - tmp -c; int lo = (tflagtemp & 0x0f) - (tmp & 0x0f) - c; int hi = (tflagtemp & 0xf0) - (tmp & 0xf0); P &= ~_fC; if (lo & 0xf0) lo -= 6; if (lo & 0x80) hi -= 0x10; if (hi & 0x0f00) hi -= 0x60; if ((sum & 0xff00) == 0) P |= _fC; tflagtemp = (lo & 0x0f) + (hi & 0xf0); h6280_cycles(1); } else { int c = (P & _fC) ^ _fC; int sum = tflagtemp - tmp - c; P &= ~(_fV | _fC); if ((tflagtemp^tmp) & (tflagtemp^sum) & _fN) P |= _fV; if ((sum & 0xff00) == 0) P |= _fC; tflagtemp = (UINT8) sum; } set_nz(tflagtemp); wb_eaz(tflagtemp); h6280_cycles(3); } inline void h6280_device::sbc(UINT8 tmp) { if(P & _fT) tsbc(tmp); else { if (P & _fD) { int c = (P & _fC) ^ _fC; int sum = A - tmp - c; int lo = (A & 0x0f) - (tmp & 0x0f) - c; int hi = (A & 0xf0) - (tmp & 0xf0); P &= ~_fC; if (lo & 0xf0) lo -= 6; if (lo & 0x80) hi -= 0x10; if (hi & 0x0f00) hi -= 0x60; if ((sum & 0xff00) == 0) P |= _fC; A = (lo & 0x0f) + (hi & 0xf0); h6280_cycles(1); } else { int c = (P & _fC) ^ _fC; int sum = A - tmp - c; P &= ~(_fV | _fC); if ((A^tmp) & (A^sum) & _fN) P |= _fV; if ((sum & 0xff00) == 0) P |= _fC; A = (UINT8) sum; } set_nz(A); } } /* 6280 ******************************************************** * SEC Set carry flag ***************************************************************/ inline void h6280_device::sec() { clear_t(); P |= _fC; } /* 6280 ******************************************************** * SED Set decimal flag ***************************************************************/ inline void h6280_device::sed() { clear_t(); P |= _fD; } /* 6280 ******************************************************** * SEI Set interrupt flag ***************************************************************/ inline void h6280_device::sei() { clear_t(); P |= _fI; } /* 6280 ******************************************************** * SET Set t flag ***************************************************************/ inline void h6280_device::set() { P |= _fT; } /* 6280 ******************************************************** * SMB Set memory bit ***************************************************************/ inline UINT8 h6280_device::smb(int bit, UINT8 tmp) { clear_t(); tmp |= (1<write_byte(0x0000,tmp); } /* 6280 ******************************************************** * ST1 Store at hardware address 2 ***************************************************************/ inline void h6280_device::st1(UINT8 tmp) { clear_t(); m_io->write_byte(0x0002,tmp); } /* 6280 ******************************************************** * ST2 Store at hardware address 3 ***************************************************************/ inline void h6280_device::st2(UINT8 tmp) { clear_t(); m_io->write_byte(0x0003,tmp); } /* 6280 ******************************************************** * STA Store accumulator ***************************************************************/ inline UINT8 h6280_device::sta() { clear_t(); return A; } /* 6280 ******************************************************** * STX Store index X ***************************************************************/ inline UINT8 h6280_device::stx() { clear_t(); return X; } /* 6280 ******************************************************** * STY Store index Y ***************************************************************/ inline UINT8 h6280_device::sty() { clear_t(); return Y; } /* 6280 ******************************************************** * STZ Store zero ***************************************************************/ inline UINT8 h6280_device::stz() { clear_t(); return 0; } /* H6280 ******************************************************* * SXY Swap index X and index Y ***************************************************************/ inline void h6280_device::sxy() { clear_t(); UINT8 tmp = X; X = Y; Y = tmp; } /* H6280 ******************************************************* * TAI Transfer Alternate Increment ***************************************************************/ inline void h6280_device::tai() { clear_t(); int from = program_read16(PCW); int to = program_read16(PCW + 2); int length = program_read16(PCW + 4); PCW += 6; int alternate = 0; if (!length) length = 0x10000; h6280_cycles( ((6 * length) + 17) ); while ((length--) != 0) { program_write8(to, program_read8(from + alternate)); to++; alternate ^= 1; } } /* H6280 ******************************************************* * TAM Transfer accumulator to memory mapper register(s) ***************************************************************/ inline void h6280_device::tam(UINT8 tmp) { clear_t(); if (tmp&0x01) m_mmr[0] = A; if (tmp&0x02) m_mmr[1] = A; if (tmp&0x04) m_mmr[2] = A; if (tmp&0x08) m_mmr[3] = A; if (tmp&0x10) m_mmr[4] = A; if (tmp&0x20) m_mmr[5] = A; if (tmp&0x40) m_mmr[6] = A; if (tmp&0x80) m_mmr[7] = A; } /* 6280 ******************************************************** * TAX Transfer accumulator to index X ***************************************************************/ inline void h6280_device::tax() { clear_t(); X = A; set_nz(X); } /* 6280 ******************************************************** * TAY Transfer accumulator to index Y ***************************************************************/ inline void h6280_device::tay() { clear_t(); Y = A; set_nz(Y); } /* 6280 ******************************************************** * TDD Transfer Decrement Decrement ***************************************************************/ inline void h6280_device::tdd() { clear_t(); int from = program_read16(PCW); int to = program_read16(PCW + 2); int length = program_read16(PCW + 4); PCW+=6; if (!length) length = 0x10000; h6280_cycles( ((6 * length) + 17) ); while ((length--) != 0) { program_write8(to, program_read8(from)); to--; from--; } } /* 6280 ******************************************************** * TIA Transfer Increment Alternate ***************************************************************/ inline void h6280_device::tia() { clear_t(); int from = program_read16(PCW); int to = program_read16(PCW + 2); int length = program_read16(PCW + 4); PCW+=6; int alternate=0; if (!length) length = 0x10000; h6280_cycles( ((6 * length) + 17) ); while ((length--) != 0) { program_write8(to + alternate, program_read8(from)); from++; alternate ^= 1; } } /* 6280 ******************************************************** * TII Transfer Increment Increment ***************************************************************/ inline void h6280_device::tii() { clear_t(); int from = program_read16(PCW); int to = program_read16(PCW + 2); int length = program_read16(PCW + 4); PCW += 6; if (!length) length = 0x10000; h6280_cycles( ((6 * length) + 17) ); while ((length--) != 0) { program_write8(to, program_read8(from)); to++; from++; } } /* 6280 ******************************************************** * TIN Transfer block, source increments every loop ***************************************************************/ inline void h6280_device::tin() { clear_t(); int from = program_read16(PCW); int to = program_read16(PCW + 2); int length = program_read16(PCW + 4); PCW+=6; if (!length) length = 0x10000; h6280_cycles( ((6 * length) + 17) ); while ((length--) != 0) { program_write8(to, program_read8(from)); from++; } } /* 6280 ******************************************************** * TMA Transfer memory mapper register(s) to accumulator * the highest bit set in tmp is the one that counts ***************************************************************/ inline void h6280_device::tma(UINT8 tmp) { clear_t(); if (tmp&0x01) A = m_mmr[0]; if (tmp&0x02) A = m_mmr[1]; if (tmp&0x04) A = m_mmr[2]; if (tmp&0x08) A = m_mmr[3]; if (tmp&0x10) A = m_mmr[4]; if (tmp&0x20) A = m_mmr[5]; if (tmp&0x40) A = m_mmr[6]; if (tmp&0x80) A = m_mmr[7]; } /* 6280 ******************************************************** * TRB Test and reset bits ***************************************************************/ inline UINT8 h6280_device::trb(UINT8 tmp) { clear_t(); P = (P & ~(_fN|_fV|_fT|_fZ)) | ((tmp&0x80) ? _fN:0) | ((tmp&0x40) ? _fV:0) | ((tmp&~A) ? 0:_fZ); tmp &= ~A; return tmp; } /* 6280 ******************************************************** * TSB Test and set bits ***************************************************************/ inline UINT8 h6280_device::tsb(UINT8 tmp) { clear_t(); P = (P & ~(_fN|_fV|_fT|_fZ)) | ((tmp&0x80) ? _fN:0) | ((tmp&0x40) ? _fV:0) | ((tmp|A) ? 0:_fZ); tmp |= A; return tmp; } /* 6280 ******************************************************** * TSX Transfer stack LSB to index X ***************************************************************/ inline void h6280_device::tsx() { clear_t(); X = S; set_nz(X); } /* 6280 ******************************************************** * TST ***************************************************************/ inline void h6280_device::tst(UINT8 imm, UINT8 tmp) { P = (P & ~(_fN|_fV|_fT|_fZ)) | ((tmp&0x80) ? _fN:0) | ((tmp&0x40) ? _fV:0) | ((tmp&imm) ? 0:_fZ); } /* 6280 ******************************************************** * TXA Transfer index X to accumulator ***************************************************************/ inline void h6280_device::txa() { clear_t(); A = X; set_nz(A); } /* 6280 ******************************************************** * TXS Transfer index X to stack LSB * no flags changed (sic!) ***************************************************************/ inline void h6280_device::txs() { clear_t(); S = X; } /* 6280 ******************************************************** * TYA Transfer index Y to accumulator ***************************************************************/ inline void h6280_device::tya() { clear_t(); A = Y; set_nz(A); } /* 6280 ******************************************************** * CSH Set CPU in high speed mode ***************************************************************/ inline void h6280_device::csh() { m_clocks_per_cycle = 1; } /* 6280 ******************************************************** * CSL Set CPU in low speed mode ***************************************************************/ inline void h6280_device::csl() { m_clocks_per_cycle = 4; } #define OP(prefix,opcode) void h6280_device::prefix##_##opcode() /***************************************************************************** ***************************************************************************** * * Hu6280 opcodes * ***************************************************************************** * op cycles opc ***********************/ OP(op,00) { h6280_cycles(8); brk(); } // 8 BRK OP(op,20) { h6280_cycles(7); ea_abs(); jsr(); } // 7 JSR ABS OP(op,40) { h6280_cycles(7); rti(); } // 7 RTI OP(op,60) { h6280_cycles(7); rts(); } // 7 RTS OP(op,80) { bra(1); } // 4 BRA REL OP(op,a0) { h6280_cycles(2); ldy(rd_imm()); } // 2 LDY IMM OP(op,c0) { h6280_cycles(2); cpy(rd_imm()); } // 2 CPY IMM OP(op,e0) { h6280_cycles(2); cpx(rd_imm()); } // 2 CPX IMM OP(op,10) { bpl(); } // 2/4 BPL REL OP(op,30) { bmi(); } // 2/4 BMI REL OP(op,50) { bvc(); } // 2/4 BVC REL OP(op,70) { bvs(); } // 2/4 BVS REL OP(op,90) { bcc(); } // 2/4 BCC REL OP(op,b0) { bcs(); } // 2/4 BCS REL OP(op,d0) { bne(); } // 2/4 BNE REL OP(op,f0) { beq(); } // 2/4 BEQ REL OP(op,01) { h6280_cycles(7); ora(rd_idx()); } // 7 ORA IDX OP(op,21) { h6280_cycles(7); and_a(rd_idx()); } // 7 AND IDX OP(op,41) { h6280_cycles(7); eor(rd_idx()); } // 7 EOR IDX OP(op,61) { h6280_cycles(7); adc(rd_idx()); } // 7 ADC IDX OP(op,81) { h6280_cycles(7); wr_idx(sta()); } // 7 STA IDX OP(op,a1) { h6280_cycles(7); lda(rd_idx()); } // 7 LDA IDX OP(op,c1) { h6280_cycles(7); cmp(rd_idx()); } // 7 CMP IDX OP(op,e1) { h6280_cycles(7); sbc(rd_idx()); } // 7 SBC IDX OP(op,11) { h6280_cycles(7); ora(rd_idy()); } // 7 ORA IDY OP(op,31) { h6280_cycles(7); and_a(rd_idy()); } // 7 AND IDY OP(op,51) { h6280_cycles(7); eor(rd_idy()); } // 7 EOR IDY OP(op,71) { h6280_cycles(7); adc(rd_idy()); } // 7 ADC AZP OP(op,91) { h6280_cycles(7); wr_idy(sta()); } // 7 STA IDY OP(op,b1) { h6280_cycles(7); lda(rd_idy()); } // 7 LDA IDY OP(op,d1) { h6280_cycles(7); cmp(rd_idy()); } // 7 CMP IDY OP(op,f1) { h6280_cycles(7); sbc(rd_idy()); } // 7 SBC IDY OP(op,02) { h6280_cycles(3); sxy(); } // 3 SXY OP(op,22) { h6280_cycles(3); sax(); } // 3 SAX OP(op,42) { h6280_cycles(3); say(); } // 3 SAY OP(op,62) { h6280_cycles(2); cla(); } // 2 CLA OP(op,82) { h6280_cycles(2); clx(); } // 2 CLX OP(op,a2) { h6280_cycles(2); ldx(rd_imm()); } // 2 LDX IMM OP(op,c2) { h6280_cycles(2); cly(); } // 2 CLY OP(op,e2) { h6280_cycles(2); nop(); } // 2 NOP OP(op,12) { h6280_cycles(7); ora(rd_zpi()); } // 7 ORA ZPI OP(op,32) { h6280_cycles(7); and_a(rd_zpi()); } // 7 AND ZPI OP(op,52) { h6280_cycles(7); eor(rd_zpi()); } // 7 EOR ZPI OP(op,72) { h6280_cycles(7); adc(rd_zpi()); } // 7 ADC ZPI OP(op,92) { h6280_cycles(7); wr_zpi(sta()); } // 7 STA ZPI OP(op,b2) { h6280_cycles(7); lda(rd_zpi()); } // 7 LDA ZPI OP(op,d2) { h6280_cycles(7); cmp(rd_zpi()); } // 7 CMP ZPI OP(op,f2) { h6280_cycles(7); sbc(rd_zpi()); } // 7 SBC ZPI OP(op,03) { h6280_cycles(5); st0(rd_imm()); } // 4 + 1 penalty cycle ST0 IMM OP(op,23) { h6280_cycles(5); st2(rd_imm()); } // 4 + 1 penalty cycle ST2 IMM OP(op,43) { h6280_cycles(4); tma(rd_imm()); } // 4 TMA OP(op,63) { h6280_cycles(4); nop(); } // 2 NOP OP(op,83) { h6280_cycles(7); int imm = rd_imm(); tst(imm, rd_zpg()); } // 7 TST IMM,ZPG OP(op,a3) { h6280_cycles(7); int imm = rd_imm(); tst(imm, rd_zpx()); } // 7 TST IMM,ZPX OP(op,c3) { tdd(); } // 6*l+17 TDD XFER OP(op,e3) { tia(); } // 6*l+17 TIA XFER OP(op,13) { h6280_cycles(5); st1(rd_imm()); } // 4 + 1 penalty cycle ST1 OP(op,33) { h6280_cycles(2); nop(); } // 2 NOP OP(op,53) { h6280_cycles(5); tam(rd_imm()); } // 5 TAM IMM OP(op,73) { tii(); } // 6*l+17 TII XFER OP(op,93) { h6280_cycles(8); int imm = rd_imm(); tst(imm, rd_abs()); } // 8 TST IMM,ABS OP(op,b3) { h6280_cycles(8); int imm = rd_imm(); tst(imm, rd_abx()); } // 8 TST IMM,ABX OP(op,d3) { tin(); } // 6*l+17 TIN XFER OP(op,f3) { tai(); } // 6*l+17 TAI XFER OP(op,04) { h6280_cycles(6); wb_eaz(tsb(rd_zpg())); } // 6 TSB ZPG OP(op,24) { h6280_cycles(4); bit(rd_zpg()); } // 4 BIT ZPG OP(op,44) { bsr(); } // 8 BSR REL OP(op,64) { h6280_cycles(4); wr_zpg(stz()); } // 4 STZ ZPG OP(op,84) { h6280_cycles(4); wr_zpg(sty()); } // 4 STY ZPG OP(op,a4) { h6280_cycles(4); ldy(rd_zpg()); } // 4 LDY ZPG OP(op,c4) { h6280_cycles(4); cpy(rd_zpg()); } // 4 CPY ZPG OP(op,e4) { h6280_cycles(4); cpx(rd_zpg()); } // 4 CPX ZPG OP(op,14) { h6280_cycles(6); wb_eaz(trb(rd_zpg())); } // 6 TRB ZPG OP(op,34) { h6280_cycles(4); bit(rd_zpx()); } // 4 BIT ZPX OP(op,54) { h6280_cycles(3); csl(); } // 3 CSL OP(op,74) { h6280_cycles(4); wr_zpx(stz()); } // 4 STZ ZPX OP(op,94) { h6280_cycles(4); wr_zpx(sty()); } // 4 STY ZPX OP(op,b4) { h6280_cycles(4); ldy(rd_zpx()); } // 4 LDY ZPX OP(op,d4) { h6280_cycles(3); csh(); } // 3 CSH OP(op,f4) { h6280_cycles(2); set(); } // 2 SET OP(op,05) { h6280_cycles(4); ora(rd_zpg()); } // 4 ORA ZPG OP(op,25) { h6280_cycles(4); and_a(rd_zpg()); } // 4 AND ZPG OP(op,45) { h6280_cycles(4); eor(rd_zpg()); } // 4 EOR ZPG OP(op,65) { h6280_cycles(4); adc(rd_zpg()); } // 4 ADC ZPG OP(op,85) { h6280_cycles(4); wr_zpg(sta()); } // 4 STA ZPG OP(op,a5) { h6280_cycles(4); lda(rd_zpg()); } // 4 LDA ZPG OP(op,c5) { h6280_cycles(4); cmp(rd_zpg()); } // 4 CMP ZPG OP(op,e5) { h6280_cycles(4); sbc(rd_zpg()); } // 4 SBC ZPG OP(op,15) { h6280_cycles(4); ora(rd_zpx()); } // 4 ORA ZPX OP(op,35) { h6280_cycles(4); and_a(rd_zpx()); } // 4 AND ZPX OP(op,55) { h6280_cycles(4); eor(rd_zpx()); } // 4 EOR ZPX OP(op,75) { h6280_cycles(4); adc(rd_zpx()); } // 4 ADC ZPX OP(op,95) { h6280_cycles(4); wr_zpx(sta()); } // 4 STA ZPX OP(op,b5) { h6280_cycles(4); lda(rd_zpx()); } // 4 LDA ZPX OP(op,d5) { h6280_cycles(4); cmp(rd_zpx()); } // 4 CMP ZPX OP(op,f5) { h6280_cycles(4); sbc(rd_zpx()); } // 4 SBC ZPX OP(op,06) { h6280_cycles(6); wb_eaz(asl(rd_zpg())); } // 6 ASL ZPG OP(op,26) { h6280_cycles(6); wb_eaz(rol(rd_zpg())); } // 6 ROL ZPG OP(op,46) { h6280_cycles(6); wb_eaz(lsr(rd_zpg())); } // 6 LSR ZPG OP(op,66) { h6280_cycles(6); wb_eaz(ror(rd_zpg())); } // 6 ROR ZPG OP(op,86) { h6280_cycles(4); wr_zpg(stx()); } // 4 STX ZPG OP(op,a6) { h6280_cycles(4); ldx(rd_zpg()); } // 4 LDX ZPG OP(op,c6) { h6280_cycles(6); wb_eaz(dec(rd_zpg())); } // 6 DEC ZPG OP(op,e6) { h6280_cycles(6); wb_eaz(inc(rd_zpg())); } // 6 INC ZPG OP(op,16) { h6280_cycles(6); wb_eaz(asl(rd_zpx())); } // 6 ASL ZPX OP(op,36) { h6280_cycles(6); wb_eaz(rol(rd_zpx())); } // 6 ROL ZPX OP(op,56) { h6280_cycles(6); wb_eaz(lsr(rd_zpx())); } // 6 LSR ZPX OP(op,76) { h6280_cycles(6); wb_eaz(ror(rd_zpx())); } // 6 ROR ZPX OP(op,96) { h6280_cycles(4); wr_zpy(stx()); } // 4 STX ZPY OP(op,b6) { h6280_cycles(4); ldx(rd_zpy()); } // 4 LDX ZPY OP(op,d6) { h6280_cycles(6); wb_eaz(dec(rd_zpx())); } // 6 DEC ZPX OP(op,f6) { h6280_cycles(6); wb_eaz(inc(rd_zpx())); } // 6 INC ZPX OP(op,07) { h6280_cycles(7); wb_eaz(rmb(0, rd_zpg())); } // 7 RMB0 ZPG OP(op,27) { h6280_cycles(7); wb_eaz(rmb(2, rd_zpg())); } // 7 RMB2 ZPG OP(op,47) { h6280_cycles(7); wb_eaz(rmb(4, rd_zpg())); } // 7 RMB4 ZPG OP(op,67) { h6280_cycles(7); wb_eaz(rmb(6, rd_zpg())); } // 7 RMB6 ZPG OP(op,87) { h6280_cycles(7); wb_eaz(smb(0, rd_zpg())); } // 7 SMB0 ZPG OP(op,a7) { h6280_cycles(7); wb_eaz(smb(2, rd_zpg())); } // 7 SMB2 ZPG OP(op,c7) { h6280_cycles(7); wb_eaz(smb(4, rd_zpg())); } // 7 SMB4 ZPG OP(op,e7) { h6280_cycles(7); wb_eaz(smb(6, rd_zpg())); } // 7 SMB6 ZPG OP(op,17) { h6280_cycles(7); wb_eaz(rmb(1, rd_zpg())); } // 7 RMB1 ZPG OP(op,37) { h6280_cycles(7); wb_eaz(rmb(3, rd_zpg())); } // 7 RMB3 ZPG OP(op,57) { h6280_cycles(7); wb_eaz(rmb(5, rd_zpg())); } // 7 RMB5 ZPG OP(op,77) { h6280_cycles(7); wb_eaz(rmb(7, rd_zpg())); } // 7 RMB7 ZPG OP(op,97) { h6280_cycles(7); wb_eaz(smb(1, rd_zpg())); } // 7 SMB1 ZPG OP(op,b7) { h6280_cycles(7); wb_eaz(smb(3, rd_zpg())); } // 7 SMB3 ZPG OP(op,d7) { h6280_cycles(7); wb_eaz(smb(5, rd_zpg())); } // 7 SMB5 ZPG OP(op,f7) { h6280_cycles(7); wb_eaz(smb(7, rd_zpg())); } // 7 SMB7 ZPG OP(op,08) { h6280_cycles(3); php(); } // 3 PHP OP(op,28) { h6280_cycles(4); plp(); } // 4 PLP OP(op,48) { h6280_cycles(3); pha(); } // 3 PHA OP(op,68) { h6280_cycles(4); pla(); } // 4 PLA OP(op,88) { h6280_cycles(2); dey(); } // 2 DEY OP(op,a8) { h6280_cycles(2); tay(); } // 2 TAY OP(op,c8) { h6280_cycles(2); iny(); } // 2 INY OP(op,e8) { h6280_cycles(2); inx(); } // 2 INX OP(op,18) { h6280_cycles(2); clc(); } // 2 CLC OP(op,38) { h6280_cycles(2); sec(); } // 2 SEC OP(op,58) { h6280_cycles(2); cli(); } // 2 CLI OP(op,78) { h6280_cycles(2); sei(); } // 2 SEI OP(op,98) { h6280_cycles(2); tya(); } // 2 TYA OP(op,b8) { h6280_cycles(2); clv(); } // 2 CLV OP(op,d8) { h6280_cycles(2); cld(); } // 2 CLD OP(op,f8) { h6280_cycles(2); sed(); } // 2 SED OP(op,09) { h6280_cycles(2); ora(rd_imm()); } // 2 ORA IMM OP(op,29) { h6280_cycles(2); and_a(rd_imm()); } // 2 AND IMM OP(op,49) { h6280_cycles(2); eor(rd_imm()); } // 2 EOR IMM OP(op,69) { h6280_cycles(2); adc(rd_imm()); } // 2 ADC IMM OP(op,89) { h6280_cycles(2); bit(rd_imm()); } // 2 BIT IMM OP(op,a9) { h6280_cycles(2); lda(rd_imm()); } // 2 LDA IMM OP(op,c9) { h6280_cycles(2); cmp(rd_imm()); } // 2 CMP IMM OP(op,e9) { h6280_cycles(2); sbc(rd_imm()); } // 2 SBC IMM OP(op,19) { h6280_cycles(5); ora(rd_aby()); } // 5 ORA ABY OP(op,39) { h6280_cycles(5); and_a(rd_aby()); } // 5 AND ABY OP(op,59) { h6280_cycles(5); eor(rd_aby()); } // 5 EOR ABY OP(op,79) { h6280_cycles(5); adc(rd_aby()); } // 5 ADC ABY OP(op,99) { h6280_cycles(5); wr_aby(sta()); } // 5 STA ABY OP(op,b9) { h6280_cycles(5); lda(rd_aby()); } // 5 LDA ABY OP(op,d9) { h6280_cycles(5); cmp(rd_aby()); } // 5 CMP ABY OP(op,f9) { h6280_cycles(5); sbc(rd_aby()); } // 5 SBC ABY OP(op,0a) { h6280_cycles(2); A = asl(A); } // 2 ASL A OP(op,2a) { h6280_cycles(2); A = rol(A); } // 2 ROL A OP(op,4a) { h6280_cycles(2); A = lsr(A); } // 2 LSR A OP(op,6a) { h6280_cycles(2); A = ror(A); } // 2 ROR A OP(op,8a) { h6280_cycles(2); txa(); } // 2 TXA OP(op,aa) { h6280_cycles(2); tax(); } // 2 TAX OP(op,ca) { h6280_cycles(2); dex(); } // 2 DEX OP(op,ea) { h6280_cycles(2); nop(); } // 2 NOP OP(op,1a) { h6280_cycles(2); A = inc(A); } // 2 INC A OP(op,3a) { h6280_cycles(2); A = dec(A); } // 2 DEC A OP(op,5a) { h6280_cycles(3); phy(); } // 3 PHY OP(op,7a) { h6280_cycles(4); ply(); } // 4 PLY OP(op,9a) { h6280_cycles(2); txs(); } // 2 TXS OP(op,ba) { h6280_cycles(2); tsx(); } // 2 TSX OP(op,da) { h6280_cycles(3); phx(); } // 3 PHX OP(op,fa) { h6280_cycles(4); plx(); } // 4 PLX OP(op,0b) { h6280_cycles(2); nop(); } // 2 NOP OP(op,2b) { h6280_cycles(2); nop(); } // 2 NOP OP(op,4b) { h6280_cycles(2); nop(); } // 2 NOP OP(op,6b) { h6280_cycles(2); nop(); } // 2 NOP OP(op,8b) { h6280_cycles(2); nop(); } // 2 NOP OP(op,ab) { h6280_cycles(2); nop(); } // 2 NOP OP(op,cb) { h6280_cycles(2); nop(); } // 2 NOP OP(op,eb) { h6280_cycles(2); nop(); } // 2 NOP OP(op,1b) { h6280_cycles(2); nop(); } // 2 NOP OP(op,3b) { h6280_cycles(2); nop(); } // 2 NOP OP(op,5b) { h6280_cycles(2); nop(); } // 2 NOP OP(op,7b) { h6280_cycles(2); nop(); } // 2 NOP OP(op,9b) { h6280_cycles(2); nop(); } // 2 NOP OP(op,bb) { h6280_cycles(2); nop(); } // 2 NOP OP(op,db) { h6280_cycles(2); nop(); } // 2 NOP OP(op,fb) { h6280_cycles(2); nop(); } // 2 NOP OP(op,0c) { h6280_cycles(7); wb_ea(tsb(rd_abs())); } // 7 TSB ABS OP(op,2c) { h6280_cycles(5); bit(rd_abs()); } // 5 BIT ABS OP(op,4c) { h6280_cycles(4); ea_abs(); jmp(); } // 4 JMP ABS OP(op,6c) { h6280_cycles(7); ea_ind(); jmp(); } // 7 JMP IND OP(op,8c) { h6280_cycles(5); wr_abs(sty()); } // 5 STY ABS OP(op,ac) { h6280_cycles(5); ldy(rd_abs()); } // 5 LDY ABS OP(op,cc) { h6280_cycles(5); cpy(rd_abs()); } // 5 CPY ABS OP(op,ec) { h6280_cycles(5); cpx(rd_abs()); } // 5 CPX ABS OP(op,1c) { h6280_cycles(7); wb_ea(trb(rd_abs())); } // 7 TRB ABS OP(op,3c) { h6280_cycles(5); bit(rd_abx()); } // 5 BIT ABX OP(op,5c) { h6280_cycles(2); nop(); } // 2 NOP OP(op,7c) { h6280_cycles(7); ea_iax(); jmp(); } // 7 JMP IAX OP(op,9c) { h6280_cycles(5); wr_abs(stz()); } // 5 STZ ABS OP(op,bc) { h6280_cycles(5); ldy(rd_abx()); } // 5 LDY ABX OP(op,dc) { h6280_cycles(2); nop(); } // 2 NOP OP(op,fc) { h6280_cycles(2); nop(); } // 2 NOP OP(op,0d) { h6280_cycles(5); ora(rd_abs()); } // 5 ORA ABS OP(op,2d) { h6280_cycles(5); and_a(rd_abs()); } // 5 AND ABS OP(op,4d) { h6280_cycles(5); eor(rd_abs()); } // 5 EOR ABS OP(op,6d) { h6280_cycles(5); adc(rd_abs()); } // 5 ADC ABS OP(op,8d) { h6280_cycles(5); wr_abs(sta()); } // 5 STA ABS OP(op,ad) { h6280_cycles(5); lda(rd_abs()); } // 5 LDA ABS OP(op,cd) { h6280_cycles(5); cmp(rd_abs()); } // 5 CMP ABS OP(op,ed) { h6280_cycles(5); sbc(rd_abs()); } // 5 SBC ABS OP(op,1d) { h6280_cycles(5); ora(rd_abx()); } // 5 ORA ABX OP(op,3d) { h6280_cycles(5); and_a(rd_abx()); } // 5 AND ABX OP(op,5d) { h6280_cycles(5); eor(rd_abx()); } // 5 EOR ABX OP(op,7d) { h6280_cycles(5); adc(rd_abx()); } // 5 ADC ABX OP(op,9d) { h6280_cycles(5); wr_abx(sta()); } // 5 STA ABX OP(op,bd) { h6280_cycles(5); lda(rd_abx()); } // 5 LDA ABX OP(op,dd) { h6280_cycles(5); cmp(rd_abx()); } // 5 CMP ABX OP(op,fd) { h6280_cycles(5); sbc(rd_abx()); } // 5 SBC ABX OP(op,0e) { h6280_cycles(7); wb_ea(asl(rd_abs())); } // 7 ASL ABS OP(op,2e) { h6280_cycles(7); wb_ea(rol(rd_abs())); } // 7 ROL ABS OP(op,4e) { h6280_cycles(7); wb_ea(lsr(rd_abs())); } // 7 LSR ABS OP(op,6e) { h6280_cycles(7); wb_ea(ror(rd_abs())); } // 7 ROR ABS OP(op,8e) { h6280_cycles(5); wr_abs(stx()); } // 5 STX ABS OP(op,ae) { h6280_cycles(5); ldx(rd_abs()); } // 5 LDX ABS OP(op,ce) { h6280_cycles(7); wb_ea(dec(rd_abs())); } // 7 DEC ABS OP(op,ee) { h6280_cycles(7); wb_ea(inc(rd_abs())); } // 7 INC ABS OP(op,1e) { h6280_cycles(7); wb_ea(asl(rd_abx())); } // 7 ASL ABX OP(op,3e) { h6280_cycles(7); wb_ea(rol(rd_abx())); } // 7 ROL ABX OP(op,5e) { h6280_cycles(7); wb_ea(lsr(rd_abx())); } // 7 LSR ABX OP(op,7e) { h6280_cycles(7); wb_ea(ror(rd_abx())); } // 7 ROR ABX OP(op,9e) { h6280_cycles(5); wr_abx(stz()); } // 5 STZ ABX OP(op,be) { h6280_cycles(5); ldx(rd_aby()); } // 5 LDX ABY OP(op,de) { h6280_cycles(7); wb_ea(dec(rd_abx())); } // 7 DEC ABX OP(op,fe) { h6280_cycles(7); wb_ea(inc(rd_abx())); } // 7 INC ABX OP(op,0f) { h6280_cycles(4); bbr(0, rd_zpg()); } // 6/8 BBR0 ZPG,REL OP(op,2f) { h6280_cycles(4); bbr(2, rd_zpg()); } // 6/8 BBR2 ZPG,REL OP(op,4f) { h6280_cycles(4); bbr(4, rd_zpg()); } // 6/8 BBR4 ZPG,REL OP(op,6f) { h6280_cycles(4); bbr(6, rd_zpg()); } // 6/8 BBR6 ZPG,REL OP(op,8f) { h6280_cycles(4); bbs(0, rd_zpg()); } // 6/8 BBS0 ZPG,REL OP(op,af) { h6280_cycles(4); bbs(2, rd_zpg()); } // 6/8 BBS2 ZPG,REL OP(op,cf) { h6280_cycles(4); bbs(4, rd_zpg()); } // 6/8 BBS4 ZPG,REL OP(op,ef) { h6280_cycles(4); bbs(6, rd_zpg()); } // 6/8 BBS6 ZPG,REL OP(op,1f) { h6280_cycles(4); bbr(1, rd_zpg()); } // 6/8 BBR1 ZPG,REL OP(op,3f) { h6280_cycles(4); bbr(3, rd_zpg()); } // 6/8 BBR3 ZPG,REL OP(op,5f) { h6280_cycles(4); bbr(5, rd_zpg()); } // 6/8 BBR5 ZPG,REL OP(op,7f) { h6280_cycles(4); bbr(7, rd_zpg()); } // 6/8 BBR7 ZPG,REL OP(op,9f) { h6280_cycles(4); bbs(1, rd_zpg()); } // 6/8 BBS1 ZPG,REL OP(op,bf) { h6280_cycles(4); bbs(3, rd_zpg()); } // 6/8 BBS3 ZPG,REL OP(op,df) { h6280_cycles(4); bbs(5, rd_zpg()); } // 6/8 BBS5 ZPG,REL OP(op,ff) { h6280_cycles(4); bbs(7, rd_zpg()); } // 6/8 BBS7 ZPG,REL //------------------------------------------------- // state_string_export - export state as a string // for the debugger //------------------------------------------------- void h6280_device::state_string_export(const device_state_entry &entry, astring &string) { switch (entry.index()) { case STATE_GENFLAGS: string.printf("%c%c%c%c%c%c%c%c", (m_p & 0x80) ? 'N':'.', (m_p & 0x40) ? 'V':'.', (m_p & 0x20) ? 'R':'.', (m_p & 0x10) ? 'B':'.', (m_p & 0x08) ? 'D':'.', (m_p & 0x04) ? 'I':'.', (m_p & 0x02) ? 'Z':'.', (m_p & 0x01) ? 'C':'.'); break; } } //------------------------------------------------- // disasm_min_opcode_bytes - return the length // of the shortest instruction, in bytes //------------------------------------------------- UINT32 h6280_device::disasm_min_opcode_bytes() const { return 1; } //------------------------------------------------- // disasm_max_opcode_bytes - return the length // of the longest instruction, in bytes //------------------------------------------------- UINT32 h6280_device::disasm_max_opcode_bytes() const { return 7; } //------------------------------------------------- // disasm_disassemble - call the disassembly // helper function //------------------------------------------------- offs_t h6280_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) { extern CPU_DISASSEMBLE( h6280 ); return CPU_DISASSEMBLE_NAME(h6280)(this, buffer, pc, oprom, opram, options); } //------------------------------------------------- // execute_min_cycles - return minimum number of // cycles it takes for one instruction to execute //------------------------------------------------- UINT32 h6280_device::execute_min_cycles() const { return 2; } //------------------------------------------------- // execute_max_cycles - return maximum number of // cycles it takes for one instruction to execute //------------------------------------------------- UINT32 h6280_device::execute_max_cycles() const { return 17 + 6*65536; } //------------------------------------------------- // execute_input_lines - return the number of // input/interrupt lines //------------------------------------------------- UINT32 h6280_device::execute_input_lines() const { return 4; } //------------------------------------------------- // execute_set_input - act on a changed input/ // interrupt line //------------------------------------------------- void h6280_device::execute_set_input(int inputnum, int state) { switch(inputnum) { case H6280_IRQ1_STATE: case 0: set_irq_line(0, state); break; case H6280_IRQ2_STATE: case 1: set_irq_line(1, state); break; case H6280_IRQT_STATE: case 2: set_irq_line(2, state); break; case H6280_NMI_STATE: case INPUT_LINE_NMI: set_irq_line(INPUT_LINE_NMI, state); break; } } /*************************************************************** * program_read8 read memory ***************************************************************/ UINT8 h6280_device::program_read8(offs_t addr) { check_vdc_vce_penalty(addr); return m_program->read_byte(translated(addr)); } /*************************************************************** * program_write8 write memory ***************************************************************/ void h6280_device::program_write8(offs_t addr, UINT8 data) { check_vdc_vce_penalty(addr); m_program->write_byte(translated(addr), data); } /*************************************************************** * program_read8z read memory - zero page ***************************************************************/ UINT8 h6280_device::program_read8z(offs_t addr) { return m_program->read_byte((m_mmr[1] << 13) | (addr & 0x1fff)); } /*************************************************************** * program_write8z write memory - zero page ***************************************************************/ void h6280_device::program_write8z(offs_t addr, UINT8 data) { m_program->write_byte((m_mmr[1] << 13) | (addr & 0x1fff), data); } /*************************************************************** * program_read16 read word from memory ***************************************************************/ UINT16 h6280_device::program_read16(offs_t addr) { return m_program->read_byte(translated(addr)) | (m_program->read_byte(translated(addr + 1)) << 8); } /*************************************************************** * program_read16z read a word from a zero page address ***************************************************************/ UINT16 h6280_device::program_read16z(offs_t addr) { if ((addr & 0xff) == 0xff) { return m_program->read_byte((m_mmr[1] << 13) | (addr & 0x1fff)) | (m_program->read_byte((m_mmr[1] << 13) | ((addr - 0xff) & 0x1fff)) << 8); } else { return m_program->read_byte((m_mmr[1] << 13) | (addr & 0x1fff)) | (m_program->read_byte((m_mmr[1] << 13) | ((addr + 1) & 0x1fff)) << 8); } } /*************************************************************** * push a register onto the stack ***************************************************************/ void h6280_device::push(UINT8 value) { m_program->write_byte((m_mmr[1] << 13) | m_sp.d, value); S--; } /*************************************************************** * pull a register from the stack ***************************************************************/ void h6280_device::pull(UINT8 &value) { S++; value = m_program->read_byte((m_mmr[1] << 13) | m_sp.d); } /*************************************************************** * read_opcode read an opcode ***************************************************************/ UINT8 h6280_device::read_opcode() { return m_direct->read_decrypted_byte(translated(PCW)); } /*************************************************************** * read_opcode_arg read an opcode argument ***************************************************************/ UINT8 h6280_device::read_opcode_arg() { return m_direct->read_raw_byte(translated(PCW)); } //------------------------------------------------- // execute_run - execute a timeslice's worth of // opcodes //------------------------------------------------- void h6280_device::execute_run() { int in; if (m_irq_pending == 2) { m_irq_pending--; } /* Execute instructions */ do { m_ppc = m_pc; debugger_instruction_hook(this, PCW); /* Execute 1 instruction */ in = read_opcode(); PCW++; (this->*m_opcode[in])(); if (m_irq_pending) { if (m_irq_pending == 1) { if (!(P & _fI)) { m_irq_pending--; check_and_take_irq_lines(); } } else { m_irq_pending--; } } /* Check internal timer */ if (m_timer_status) { if (m_timer_value<=0) { if (!m_irq_pending) { m_irq_pending = 1; } while (m_timer_value <= 0) { m_timer_value += m_timer_load; } set_irq_line(2, ASSERT_LINE); } } } while (m_icount > 0); } //************************************************************************** // IRQ HANDLING //************************************************************************** void h6280_device::set_irq_line(int irqline, int state) { if (irqline == INPUT_LINE_NMI) { if (state != ASSERT_LINE) return; m_nmi_state = state; check_irq_lines(); } else if (irqline < 3) { /* If the state has not changed, just return */ if (m_irq_state[irqline] == state) return; m_irq_state[irqline] = state; check_irq_lines(); } } //************************************************************************** // REGISTER HANDLING //************************************************************************** READ8_MEMBER( h6280_device::irq_status_r ) { int status; switch (offset & 3) { default: return m_io_buffer; case 3: { status = 0; if (m_irq_state[1] != CLEAR_LINE) status |= 1; /* IRQ 2 */ if (m_irq_state[0] != CLEAR_LINE) status |= 2; /* IRQ 1 */ if (m_irq_state[2] != CLEAR_LINE) status |= 4; /* TIMER */ return status | (m_io_buffer & (~H6280_IRQ_MASK)); } case 2: return m_irq_mask | (m_io_buffer & (~H6280_IRQ_MASK)); } } WRITE8_MEMBER( h6280_device::irq_status_w ) { m_io_buffer = data; switch (offset & 3) { default: m_io_buffer = data; break; case 2: /* Write irq mask */ m_irq_mask = data & 0x7; check_irq_lines(); break; case 3: /* Timer irq ack */ set_irq_line(2, CLEAR_LINE); break; } } READ8_MEMBER( h6280_device::timer_r ) { /* only returns countdown */ return ((m_timer_value >> 10) & 0x7F) | (m_io_buffer & 0x80); } WRITE8_MEMBER( h6280_device::timer_w ) { m_io_buffer = data; switch (offset & 1) { case 0: /* Counter preload */ m_timer_load = m_timer_value = ((data & 127) + 1) * 1024; return; case 1: /* Counter enable */ if (data & 1) {/* stop -> start causes reload */ if(m_timer_status == 0) m_timer_value = m_timer_load; } m_timer_status = data & 1; return; } } bool h6280_device::memory_translate(address_spacenum spacenum, int intention, offs_t &address) { if (spacenum == AS_PROGRAM) address = translated(address); return TRUE; } UINT8 h6280_device::io_get_buffer() { return m_io_buffer; } void h6280_device::io_set_buffer(UINT8 data) { m_io_buffer = data; }