// license:BSD-3-Clause // copyright-holders:Aaron Giles /*** m6800: Portable 6800 class emulator ************************************* m68xx.cpp References: 6809 Simulator V09, By L.C. Benschop, Eindhoven The Netherlands. m6809: Portable 6809 emulator, DS (6809 code in MAME, derived from the 6809 Simulator V09) 6809 Microcomputer Programming & Interfacing with Experiments" by Andrew C. Staugaard, Jr.; Howard W. Sams & Co., Inc. System dependencies: u16 must be 16 bit unsigned int u8 must be 8 bit unsigned int u32 must be more than 16 bits arrays up to 65536 bytes must be supported machine must be twos complement TODO: - verify invalid opcodes for the different CPU types - add 6802 nvram (only in case VCC STANDBY is connected to battery) - cleanups (difficult to do maintenance work right now) - (see m6801.cpp for 6801-specific TODO) *****************************************************************************/ /* Chip RAM NVRAM ROM SCI r15-f ports ----------------------------------------------------------------- MC6800 - - - no no - MC6802 128 32 - no no - MC6802NS 128 - - no no - MC6808 - - - no no - MC6801 128 64 2K yes no 4 MC68701 128 64 2K yes no 4 MC6803 128 64 - yes no 4 MC6803NR - - - yes no 4 MC6801U4 192 32 4K yes yes 4 MC6803U4 192 32 - yes yes 4 MC68120 128(DP) - 2K yes IPC 3 MC68121 128(DP) - - yes IPC 3 HD6801 128 64 2K yes no 4 HD6301V 128 - 4K yes no 4 HD63701V 192 - 4K yes no 4 HD6303R 128 - - yes no 4 HD6301X 192 - 4K yes yes 6 HD6301Y 256 - 16K yes yes 6 HD6303X 192 - - yes yes 6 HD6303Y 256 - - yes yes 6 NSC8105 MS2010-A */ #include "emu.h" #include "m6800.h" #include "6800dasm.h" #define LOG_IRQ (1U << 1) //#define VERBOSE (LOG_IRQ) #include "logmacro.h" #define LOGIRQ(...) LOGMASKED(LOG_IRQ, __VA_ARGS__) #define pPPC m_ppc #define pPC m_pc #define pS m_s #define pX m_x #define pD m_d #define PC m_pc.w.l #define PCD m_pc.d #define S m_s.w.l #define SD m_s.d #define X m_x.w.l #define D m_d.w.l #define A m_d.b.h #define B m_d.b.l #define CC m_cc #define EAD m_ea.d #define EA m_ea.w.l /* memory interface */ /****************************************************************************/ /* Read a byte from given memory location */ /****************************************************************************/ #define RM(Addr) (m_program.read_byte(Addr)) /****************************************************************************/ /* Write a byte to given memory location */ /****************************************************************************/ #define WM(Addr,Value) (m_program.write_byte(Addr,Value)) /****************************************************************************/ /* M6800_RDOP() is identical to M6800_RDMEM() except it is used for reading */ /* opcodes. In case of system with memory mapped I/O, this function can be */ /* used to greatly speed up emulation */ /****************************************************************************/ #define M_RDOP(Addr) (m_copcodes.read_byte(Addr)) /****************************************************************************/ /* M6800_RDOP_ARG() is identical to M6800_RDOP() but it's used for reading */ /* opcode arguments. This difference can be used to support systems that */ /* use different encoding mechanisms for opcodes and opcode arguments */ /****************************************************************************/ #define M_RDOP_ARG(Addr) (m_cprogram.read_byte(Addr)) /* macros to access memory */ #define IMMBYTE(b) b = M_RDOP_ARG(PCD); PC++ #define IMMWORD(w) w.d = (M_RDOP_ARG(PCD)<<8) | M_RDOP_ARG((PCD+1)&0xffff); PC+=2 #define PUSHBYTE(b) WM(SD,b); --S #define PUSHWORD(w) WM(SD,w.b.l); --S; WM(SD,w.b.h); --S #define PULLBYTE(b) S++; b = RM(SD) #define PULLWORD(w) S++; w.d = RM(SD)<<8; S++; w.d |= RM(SD) /* CC masks HI NZVC 7654 3210 */ #define CLR_HNZVC CC&=0xd0 #define CLR_NZV CC&=0xf1 #define CLR_HNZC CC&=0xd2 #define CLR_NZVC CC&=0xf0 #define CLR_Z CC&=0xfb #define CLR_ZC CC&=0xfa #define CLR_C CC&=0xfe /* macros for CC -- CC bits affected should be reset before calling */ #define SET_Z(a) if(!(a))SEZ #define SET_Z8(a) SET_Z(u8(a)) #define SET_Z16(a) SET_Z(u16(a)) #define SET_N8(a) CC|=(((a)&0x80)>>4) #define SET_N16(a) CC|=(((a)&0x8000)>>12) #define SET_H(a,b,r) CC|=((((a)^(b)^(r))&0x10)<<1) #define SET_C8(a) CC|=(((a)&0x100)>>8) #define SET_C16(a) CC|=(((a)&0x10000)>>16) #define SET_V8(a,b,r) CC|=((((a)^(b)^(r)^((r)>>1))&0x80)>>6) #define SET_V16(a,b,r) CC|=((((a)^(b)^(r)^((r)>>1))&0x8000)>>14) const u8 m6800_cpu_device::flags8i[256]= /* increment */ { 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x0a,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08 }; const u8 m6800_cpu_device::flags8d[256]= /* decrement */ { 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08 }; #define SET_FLAGS8I(a) {CC|=flags8i[(a)&0xff];} #define SET_FLAGS8D(a) {CC|=flags8d[(a)&0xff];} /* combos */ #define SET_NZ8(a) {SET_N8(a);SET_Z8(a);} #define SET_NZ16(a) {SET_N16(a);SET_Z16(a);} #define SET_FLAGS8(a,b,r) {SET_N8(r);SET_Z8(r);SET_V8(a,b,r);SET_C8(r);} #define SET_FLAGS16(a,b,r) {SET_N16(r);SET_Z16(r);SET_V16(a,b,r);SET_C16(r);} /* for treating an u8 as a signed s16 */ #define SIGNED(b) (s16(b&0x80?b|0xff00:b)) /* Macros for addressing modes */ #define DIRECT IMMBYTE(EAD) #define IMM8 EA=PC++ #define IMM16 {EA=PC;PC+=2;} #define EXTENDED IMMWORD(m_ea) #define INDEXED {EA=X+(u8)M_RDOP_ARG(PCD);PC++;} /* macros to set status flags */ #if defined(SEC) #undef SEC #endif #define SEC CC|=0x01 #define CLC CC&=0xfe #define SEZ CC|=0x04 #define CLZ CC&=0xfb #define SEN CC|=0x08 #define CLN CC&=0xf7 #define SEV CC|=0x02 #define CLV CC&=0xfd #define SEH CC|=0x20 #define CLH CC&=0xdf #define SEI CC|=0x10 #define CLI CC&=~0x10 /* macros for convenience */ #define DIRBYTE(b) {DIRECT;b=RM(EAD);} #define DIRWORD(w) {DIRECT;w.d=RM16(EAD);} #define EXTBYTE(b) {EXTENDED;b=RM(EAD);} #define EXTWORD(w) {EXTENDED;w.d=RM16(EAD);} #define IDXBYTE(b) {INDEXED;b=RM(EAD);} #define IDXWORD(w) {INDEXED;w.d=RM16(EAD);} /* Macros for branch instructions */ #define BRANCH(f) {IMMBYTE(t);if(f){PC+=SIGNED(t);}} #define NXORV ((CC&0x08)^((CC&0x02)<<2)) #define NXORC ((CC&0x08)^((CC&0x01)<<3)) /* include the opcode functions */ #include "6800ops.hxx" // to prevent the possibility of MAME locking up, don't use 0 cycles here #define XX 4 // illegal opcode unknown cycle count const u8 m6800_cpu_device::cycles_6800[256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ /*0*/ XX, 2,XX,XX,XX,XX, 2, 2, 4, 4, 2, 2, 2, 2, 2, 2, /*1*/ 2, 2,XX,XX,XX,XX, 2, 2,XX, 2,XX, 2,XX,XX,XX,XX, /*2*/ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /*3*/ 4, 4, 4, 4, 4, 4, 4, 4,XX, 5,XX,10,XX,XX, 9,12, /*4*/ 2,XX,XX, 2, 2,XX, 2, 2, 2, 2, 2,XX, 2, 2,XX, 2, /*5*/ 2,XX,XX, 2, 2,XX, 2, 2, 2, 2, 2,XX, 2, 2,XX, 2, /*6*/ 7,XX,XX, 7, 7,XX, 7, 7, 7, 7, 7,XX, 7, 7, 4, 7, /*7*/ 6,XX,XX, 6, 6,XX, 6, 6, 6, 6, 6,XX, 6, 6, 3, 6, /*8*/ 2, 2, 2,XX, 2, 2, 2, 3, 2, 2, 2, 2, 3, 8, 3, 4, /*9*/ 3, 3, 3,XX, 3, 3, 3, 4, 3, 3, 3, 3, 4, 6, 4, 5, /*A*/ 5, 5, 5,XX, 5, 5, 5, 6, 5, 5, 5, 5, 6, 8, 6, 7, /*B*/ 4, 4, 4,XX, 4, 4, 4, 5, 4, 4, 4, 4, 5, 9, 5, 6, /*C*/ 2, 2, 2,XX, 2, 2, 2, 3, 2, 2, 2, 2,XX,XX, 3, 4, /*D*/ 3, 3, 3,XX, 3, 3, 3, 4, 3, 3, 3, 3,XX,XX, 4, 5, /*E*/ 5, 5, 5,XX, 5, 5, 5, 6, 5, 5, 5, 5,XX,XX, 6, 7, /*F*/ 4, 4, 4,XX, 4, 4, 4, 5, 4, 4, 4, 4,XX,XX, 5, 6 }; const u8 m6800_cpu_device::cycles_nsc8105[256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ /*0*/ XX,XX, 2,XX,XX, 2,XX, 2, 4, 2, 4, 2, 2, 2, 2, 2, /*1*/ 2,XX, 2,XX,XX, 2,XX, 2,XX,XX, 2, 2,XX,XX,XX,XX, /*2*/ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /*3*/ 4, 4, 4, 4, 4, 4, 4, 4,XX,XX, 5,10,XX, 9,XX,12, /*4*/ 2, 2, 2,XX, 2, 2, 2, 3, 2, 2, 2, 2, 3, 3, 8, 4, /*5*/ 3, 3, 3,XX, 3, 3, 3, 4, 3, 3, 3, 3, 4, 4, 6, 5, /*6*/ 5, 5, 5,XX, 5, 5, 5, 6, 5, 5, 5, 5, 6, 6, 8, 7, /*7*/ 4, 4, 4,XX, 4, 4, 4, 5, 4, 4, 4, 4, 5, 5, 9, 6, /*8*/ 2,XX,XX, 2, 2, 2,XX, 2, 2, 2, 2,XX, 2,XX, 2, 2, /*9*/ 2,XX,XX, 2, 2, 2,XX, 2, 2, 2, 2,XX, 2,XX, 2, 2, /*A*/ 7,XX,XX, 7, 7, 7,XX, 7, 7, 7, 7,XX, 7, 4, 7, 7, /*B*/ 6,XX, 6, 6, 6, 6,XX, 6, 6, 6, 6, 6, 6, 3, 6, 6, /*C*/ 2, 2, 2,XX, 2, 2, 2, 3, 2, 2, 2, 2,XX, 3,XX, 4, /*D*/ 3, 3, 3,XX, 3, 3, 3, 4, 3, 3, 3, 3,XX, 4,XX, 5, /*E*/ 5, 5, 5,XX, 5, 5, 5, 6, 5, 5, 5, 5, 5, 6,XX, 7, /*F*/ 4, 4, 4,XX, 4, 4, 4, 5, 4, 4, 4, 4, 4, 5,XX, 6 }; #undef XX // /illegal opcode unknown cc const m6800_cpu_device::op_func m6800_cpu_device::m6800_insn[0x100] = { // 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F &m6800_cpu_device::illegl1,&m6800_cpu_device::nop, &m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::tap, &m6800_cpu_device::tpa, // 0 &m6800_cpu_device::inx, &m6800_cpu_device::dex, &m6800_cpu_device::clv, &m6800_cpu_device::sev, &m6800_cpu_device::clc, &m6800_cpu_device::sec, &m6800_cpu_device::cli, &m6800_cpu_device::sei, &m6800_cpu_device::sba, &m6800_cpu_device::cba, &m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::tab, &m6800_cpu_device::tba, // 1 &m6800_cpu_device::illegl1,&m6800_cpu_device::daa, &m6800_cpu_device::illegl1,&m6800_cpu_device::aba, &m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1, &m6800_cpu_device::bra, &m6800_cpu_device::brn, &m6800_cpu_device::bhi, &m6800_cpu_device::bls, &m6800_cpu_device::bcc, &m6800_cpu_device::bcs, &m6800_cpu_device::bne, &m6800_cpu_device::beq, // 2 &m6800_cpu_device::bvc, &m6800_cpu_device::bvs, &m6800_cpu_device::bpl, &m6800_cpu_device::bmi, &m6800_cpu_device::bge, &m6800_cpu_device::blt, &m6800_cpu_device::bgt, &m6800_cpu_device::ble, &m6800_cpu_device::tsx, &m6800_cpu_device::ins, &m6800_cpu_device::pula, &m6800_cpu_device::pulb, &m6800_cpu_device::des, &m6800_cpu_device::txs, &m6800_cpu_device::psha, &m6800_cpu_device::pshb, // 3 &m6800_cpu_device::illegl1,&m6800_cpu_device::rts, &m6800_cpu_device::illegl1,&m6800_cpu_device::rti, &m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::wai, &m6800_cpu_device::swi, &m6800_cpu_device::nega, &m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::coma, &m6800_cpu_device::lsra, &m6800_cpu_device::illegl1,&m6800_cpu_device::rora, &m6800_cpu_device::asra, // 4 &m6800_cpu_device::asla, &m6800_cpu_device::rola, &m6800_cpu_device::deca, &m6800_cpu_device::illegl1,&m6800_cpu_device::inca, &m6800_cpu_device::tsta, &m6800_cpu_device::illegl1,&m6800_cpu_device::clra, &m6800_cpu_device::negb, &m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::comb, &m6800_cpu_device::lsrb, &m6800_cpu_device::illegl1,&m6800_cpu_device::rorb, &m6800_cpu_device::asrb, // 5 &m6800_cpu_device::aslb, &m6800_cpu_device::rolb, &m6800_cpu_device::decb, &m6800_cpu_device::illegl1,&m6800_cpu_device::incb, &m6800_cpu_device::tstb, &m6800_cpu_device::illegl1,&m6800_cpu_device::clrb, &m6800_cpu_device::neg_ix, &m6800_cpu_device::illegl2,&m6800_cpu_device::illegl2,&m6800_cpu_device::com_ix, &m6800_cpu_device::lsr_ix, &m6800_cpu_device::illegl2,&m6800_cpu_device::ror_ix, &m6800_cpu_device::asr_ix, // 6 &m6800_cpu_device::asl_ix, &m6800_cpu_device::rol_ix, &m6800_cpu_device::dec_ix, &m6800_cpu_device::illegl2,&m6800_cpu_device::inc_ix, &m6800_cpu_device::tst_ix, &m6800_cpu_device::jmp_ix, &m6800_cpu_device::clr_ix, &m6800_cpu_device::neg_ex, &m6800_cpu_device::illegl3,&m6800_cpu_device::illegl3,&m6800_cpu_device::com_ex, &m6800_cpu_device::lsr_ex, &m6800_cpu_device::illegl3,&m6800_cpu_device::ror_ex, &m6800_cpu_device::asr_ex, // 7 &m6800_cpu_device::asl_ex, &m6800_cpu_device::rol_ex, &m6800_cpu_device::dec_ex, &m6800_cpu_device::illegl3,&m6800_cpu_device::inc_ex, &m6800_cpu_device::tst_ex, &m6800_cpu_device::jmp_ex, &m6800_cpu_device::clr_ex, &m6800_cpu_device::suba_im,&m6800_cpu_device::cmpa_im,&m6800_cpu_device::sbca_im,&m6800_cpu_device::illegl2,&m6800_cpu_device::anda_im,&m6800_cpu_device::bita_im,&m6800_cpu_device::lda_im, &m6800_cpu_device::sta_im, // 8 &m6800_cpu_device::eora_im,&m6800_cpu_device::adca_im,&m6800_cpu_device::ora_im, &m6800_cpu_device::adda_im,&m6800_cpu_device::cmpx_im,&m6800_cpu_device::bsr, &m6800_cpu_device::lds_im, &m6800_cpu_device::sts_im, &m6800_cpu_device::suba_di,&m6800_cpu_device::cmpa_di,&m6800_cpu_device::sbca_di,&m6800_cpu_device::illegl2,&m6800_cpu_device::anda_di,&m6800_cpu_device::bita_di,&m6800_cpu_device::lda_di, &m6800_cpu_device::sta_di, // 9 &m6800_cpu_device::eora_di,&m6800_cpu_device::adca_di,&m6800_cpu_device::ora_di, &m6800_cpu_device::adda_di,&m6800_cpu_device::cmpx_di,&m6800_cpu_device::jsr_di, &m6800_cpu_device::lds_di, &m6800_cpu_device::sts_di, &m6800_cpu_device::suba_ix,&m6800_cpu_device::cmpa_ix,&m6800_cpu_device::sbca_ix,&m6800_cpu_device::illegl2,&m6800_cpu_device::anda_ix,&m6800_cpu_device::bita_ix,&m6800_cpu_device::lda_ix, &m6800_cpu_device::sta_ix, // A &m6800_cpu_device::eora_ix,&m6800_cpu_device::adca_ix,&m6800_cpu_device::ora_ix, &m6800_cpu_device::adda_ix,&m6800_cpu_device::cmpx_ix,&m6800_cpu_device::jsr_ix, &m6800_cpu_device::lds_ix, &m6800_cpu_device::sts_ix, &m6800_cpu_device::suba_ex,&m6800_cpu_device::cmpa_ex,&m6800_cpu_device::sbca_ex,&m6800_cpu_device::illegl3,&m6800_cpu_device::anda_ex,&m6800_cpu_device::bita_ex,&m6800_cpu_device::lda_ex, &m6800_cpu_device::sta_ex, // B &m6800_cpu_device::eora_ex,&m6800_cpu_device::adca_ex,&m6800_cpu_device::ora_ex, &m6800_cpu_device::adda_ex,&m6800_cpu_device::cmpx_ex,&m6800_cpu_device::jsr_ex, &m6800_cpu_device::lds_ex, &m6800_cpu_device::sts_ex, &m6800_cpu_device::subb_im,&m6800_cpu_device::cmpb_im,&m6800_cpu_device::sbcb_im,&m6800_cpu_device::illegl2,&m6800_cpu_device::andb_im,&m6800_cpu_device::bitb_im,&m6800_cpu_device::ldb_im, &m6800_cpu_device::stb_im, // C &m6800_cpu_device::eorb_im,&m6800_cpu_device::adcb_im,&m6800_cpu_device::orb_im, &m6800_cpu_device::addb_im,&m6800_cpu_device::illegl3,&m6800_cpu_device::illegl3,&m6800_cpu_device::ldx_im, &m6800_cpu_device::stx_im, &m6800_cpu_device::subb_di,&m6800_cpu_device::cmpb_di,&m6800_cpu_device::sbcb_di,&m6800_cpu_device::illegl2,&m6800_cpu_device::andb_di,&m6800_cpu_device::bitb_di,&m6800_cpu_device::ldb_di, &m6800_cpu_device::stb_di, // D &m6800_cpu_device::eorb_di,&m6800_cpu_device::adcb_di,&m6800_cpu_device::orb_di, &m6800_cpu_device::addb_di,&m6800_cpu_device::illegl2,&m6800_cpu_device::illegl2,&m6800_cpu_device::ldx_di, &m6800_cpu_device::stx_di, &m6800_cpu_device::subb_ix,&m6800_cpu_device::cmpb_ix,&m6800_cpu_device::sbcb_ix,&m6800_cpu_device::illegl2,&m6800_cpu_device::andb_ix,&m6800_cpu_device::bitb_ix,&m6800_cpu_device::ldb_ix, &m6800_cpu_device::stb_ix, // E &m6800_cpu_device::eorb_ix,&m6800_cpu_device::adcb_ix,&m6800_cpu_device::orb_ix, &m6800_cpu_device::addb_ix,&m6800_cpu_device::illegl2,&m6800_cpu_device::illegl2,&m6800_cpu_device::ldx_ix, &m6800_cpu_device::stx_ix, &m6800_cpu_device::subb_ex,&m6800_cpu_device::cmpb_ex,&m6800_cpu_device::sbcb_ex,&m6800_cpu_device::illegl3,&m6800_cpu_device::andb_ex,&m6800_cpu_device::bitb_ex,&m6800_cpu_device::ldb_ex, &m6800_cpu_device::stb_ex, // F &m6800_cpu_device::eorb_ex,&m6800_cpu_device::adcb_ex,&m6800_cpu_device::orb_ex, &m6800_cpu_device::addb_ex,&m6800_cpu_device::illegl3,&m6800_cpu_device::illegl3,&m6800_cpu_device::ldx_ex, &m6800_cpu_device::stx_ex }; const m6800_cpu_device::op_func m6800_cpu_device::nsc8105_insn[0x100] = { // 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F &m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::nop, &m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::tap, &m6800_cpu_device::illegl1,&m6800_cpu_device::tpa, // 0 &m6800_cpu_device::inx, &m6800_cpu_device::clv, &m6800_cpu_device::dex, &m6800_cpu_device::sev, &m6800_cpu_device::clc, &m6800_cpu_device::cli, &m6800_cpu_device::sec, &m6800_cpu_device::sei, &m6800_cpu_device::sba, &m6800_cpu_device::illegl1,&m6800_cpu_device::cba, &m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::tab, &m6800_cpu_device::illegl1,&m6800_cpu_device::tba, // 1 &m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::daa, &m6800_cpu_device::aba, &m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1, &m6800_cpu_device::bra, &m6800_cpu_device::bhi, &m6800_cpu_device::brn, &m6800_cpu_device::bls, &m6800_cpu_device::bcc, &m6800_cpu_device::bne, &m6800_cpu_device::bcs, &m6800_cpu_device::beq, // 2 &m6800_cpu_device::bvc, &m6800_cpu_device::bpl, &m6800_cpu_device::bvs, &m6800_cpu_device::bmi, &m6800_cpu_device::bge, &m6800_cpu_device::bgt, &m6800_cpu_device::blt, &m6800_cpu_device::ble, &m6800_cpu_device::tsx, &m6800_cpu_device::pula, &m6800_cpu_device::ins, &m6800_cpu_device::pulb, &m6800_cpu_device::des, &m6800_cpu_device::psha, &m6800_cpu_device::txs, &m6800_cpu_device::pshb, // 3 &m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::rts, &m6800_cpu_device::rti, &m6800_cpu_device::illegl1,&m6800_cpu_device::wai, &m6800_cpu_device::illegl1,&m6800_cpu_device::swi, &m6800_cpu_device::suba_im,&m6800_cpu_device::sbca_im,&m6800_cpu_device::cmpa_im,&m6800_cpu_device::illegl1,&m6800_cpu_device::anda_im,&m6800_cpu_device::lda_im, &m6800_cpu_device::bita_im,&m6800_cpu_device::sta_im, // 4 &m6800_cpu_device::eora_im,&m6800_cpu_device::ora_im, &m6800_cpu_device::adca_im,&m6800_cpu_device::adda_im,&m6800_cpu_device::cmpx_im,&m6800_cpu_device::lds_im, &m6800_cpu_device::bsr, &m6800_cpu_device::sts_im, &m6800_cpu_device::suba_di,&m6800_cpu_device::sbca_di,&m6800_cpu_device::cmpa_di,&m6800_cpu_device::illegl1,&m6800_cpu_device::anda_di,&m6800_cpu_device::lda_di, &m6800_cpu_device::bita_di,&m6800_cpu_device::sta_di, // 5 &m6800_cpu_device::eora_di,&m6800_cpu_device::ora_di, &m6800_cpu_device::adca_di,&m6800_cpu_device::adda_di,&m6800_cpu_device::cmpx_di,&m6800_cpu_device::lds_di, &m6800_cpu_device::jsr_di, &m6800_cpu_device::sts_di, &m6800_cpu_device::suba_ix,&m6800_cpu_device::sbca_ix,&m6800_cpu_device::cmpa_ix,&m6800_cpu_device::illegl1,&m6800_cpu_device::anda_ix,&m6800_cpu_device::lda_ix, &m6800_cpu_device::bita_ix,&m6800_cpu_device::sta_ix, // 6 &m6800_cpu_device::eora_ix,&m6800_cpu_device::ora_ix, &m6800_cpu_device::adca_ix,&m6800_cpu_device::adda_ix,&m6800_cpu_device::cmpx_ix,&m6800_cpu_device::lds_ix, &m6800_cpu_device::jsr_ix, &m6800_cpu_device::sts_ix, &m6800_cpu_device::suba_ex,&m6800_cpu_device::sbca_ex,&m6800_cpu_device::cmpa_ex,&m6800_cpu_device::illegl1,&m6800_cpu_device::anda_ex,&m6800_cpu_device::lda_ex, &m6800_cpu_device::bita_ex,&m6800_cpu_device::sta_ex, // 7 &m6800_cpu_device::eora_ex,&m6800_cpu_device::ora_ex, &m6800_cpu_device::adca_ex,&m6800_cpu_device::adda_ex,&m6800_cpu_device::cmpx_ex,&m6800_cpu_device::lds_ex, &m6800_cpu_device::jsr_ex, &m6800_cpu_device::sts_ex, &m6800_cpu_device::nega, &m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::coma, &m6800_cpu_device::lsra, &m6800_cpu_device::rora, &m6800_cpu_device::illegl1,&m6800_cpu_device::asra, // 8 &m6800_cpu_device::asla, &m6800_cpu_device::deca, &m6800_cpu_device::rola, &m6800_cpu_device::illegl1,&m6800_cpu_device::inca, &m6800_cpu_device::illegl1,&m6800_cpu_device::tsta, &m6800_cpu_device::clra, &m6800_cpu_device::negb, &m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::comb, &m6800_cpu_device::lsrb, &m6800_cpu_device::rorb, &m6800_cpu_device::illegl1,&m6800_cpu_device::asrb, // 9 &m6800_cpu_device::aslb, &m6800_cpu_device::decb, &m6800_cpu_device::rolb, &m6800_cpu_device::illegl1,&m6800_cpu_device::incb, &m6800_cpu_device::illegl1,&m6800_cpu_device::tstb, &m6800_cpu_device::clrb, &m6800_cpu_device::neg_ix, &m6800_cpu_device::illegl1,&m6800_cpu_device::illegl1,&m6800_cpu_device::com_ix, &m6800_cpu_device::lsr_ix, &m6800_cpu_device::ror_ix, &m6800_cpu_device::illegl1,&m6800_cpu_device::asr_ix, // A &m6800_cpu_device::asl_ix, &m6800_cpu_device::dec_ix, &m6800_cpu_device::rol_ix, &m6800_cpu_device::illegl1,&m6800_cpu_device::inc_ix, &m6800_cpu_device::jmp_ix, &m6800_cpu_device::tst_ix, &m6800_cpu_device::clr_ix, &m6800_cpu_device::neg_ex, &m6800_cpu_device::illegl1,&m6800_cpu_device::stx_nsc,&m6800_cpu_device::com_ex, &m6800_cpu_device::lsr_ex, &m6800_cpu_device::ror_ex, &m6800_cpu_device::illegl1,&m6800_cpu_device::asr_ex, // B &m6800_cpu_device::asl_ex, &m6800_cpu_device::dec_ex, &m6800_cpu_device::rol_ex, &m6800_cpu_device::btst_ix,&m6800_cpu_device::inc_ex, &m6800_cpu_device::jmp_ex, &m6800_cpu_device::tst_ex, &m6800_cpu_device::clr_ex, &m6800_cpu_device::subb_im,&m6800_cpu_device::sbcb_im,&m6800_cpu_device::cmpb_im,&m6800_cpu_device::illegl1,&m6800_cpu_device::andb_im,&m6800_cpu_device::ldb_im, &m6800_cpu_device::bitb_im,&m6800_cpu_device::stb_im, // C &m6800_cpu_device::eorb_im,&m6800_cpu_device::orb_im, &m6800_cpu_device::adcb_im,&m6800_cpu_device::addb_im,&m6800_cpu_device::illegl1,&m6800_cpu_device::ldx_im, &m6800_cpu_device::illegl1,&m6800_cpu_device::stx_im, &m6800_cpu_device::subb_di,&m6800_cpu_device::sbcb_di,&m6800_cpu_device::cmpb_di,&m6800_cpu_device::illegl1,&m6800_cpu_device::andb_di,&m6800_cpu_device::ldb_di, &m6800_cpu_device::bitb_di,&m6800_cpu_device::stb_di, // D &m6800_cpu_device::eorb_di,&m6800_cpu_device::orb_di, &m6800_cpu_device::adcb_di,&m6800_cpu_device::addb_di,&m6800_cpu_device::illegl1,&m6800_cpu_device::ldx_di, &m6800_cpu_device::illegl1,&m6800_cpu_device::stx_di, &m6800_cpu_device::subb_ix,&m6800_cpu_device::sbcb_ix,&m6800_cpu_device::cmpb_ix,&m6800_cpu_device::illegl1,&m6800_cpu_device::andb_ix,&m6800_cpu_device::ldb_ix, &m6800_cpu_device::bitb_ix,&m6800_cpu_device::stb_ix, // E &m6800_cpu_device::eorb_ix,&m6800_cpu_device::orb_ix, &m6800_cpu_device::adcb_ix,&m6800_cpu_device::addb_ix,&m6800_cpu_device::adcx_im,&m6800_cpu_device::ldx_ix, &m6800_cpu_device::illegl1,&m6800_cpu_device::stx_ix, &m6800_cpu_device::subb_ex,&m6800_cpu_device::sbcb_ex,&m6800_cpu_device::cmpb_ex,&m6800_cpu_device::illegl1,&m6800_cpu_device::andb_ex,&m6800_cpu_device::ldb_ex, &m6800_cpu_device::bitb_ex,&m6800_cpu_device::stb_ex, // F &m6800_cpu_device::eorb_ex,&m6800_cpu_device::orb_ex, &m6800_cpu_device::adcb_ex,&m6800_cpu_device::addb_ex,&m6800_cpu_device::addx_ex,&m6800_cpu_device::ldx_ex, &m6800_cpu_device::illegl1,&m6800_cpu_device::stx_ex }; DEFINE_DEVICE_TYPE(M6800, m6800_cpu_device, "m6800", "Motorola MC6800") DEFINE_DEVICE_TYPE(M6802, m6802_cpu_device, "m6802", "Motorola MC6802") DEFINE_DEVICE_TYPE(M6808, m6808_cpu_device, "m6808", "Motorola MC6808") DEFINE_DEVICE_TYPE(NSC8105, nsc8105_cpu_device, "nsc8105", "NSC8105") m6800_cpu_device::m6800_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : m6800_cpu_device(mconfig, M6800, tag, owner, clock, m6800_insn, cycles_6800, address_map_constructor()) { } m6800_cpu_device::m6800_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, const op_func *insn, const u8 *cycles, address_map_constructor internal) : cpu_device(mconfig, type, tag, owner, clock) , m_program_config("program", ENDIANNESS_BIG, 8, 16, 0, internal) , m_decrypted_opcodes_config("program", ENDIANNESS_BIG, 8, 16, 0) , m_insn(insn) , m_cycles(cycles) { } m6802_cpu_device::m6802_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : m6802_cpu_device(mconfig, M6802, tag, owner, clock, m6800_insn, cycles_6800) { } m6802_cpu_device::m6802_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, const op_func *insn, const u8 *cycles) : m6800_cpu_device(mconfig, type, tag, owner, clock, insn, cycles, address_map_constructor(FUNC(m6802_cpu_device::ram_map), this)) , m_ram_enable(true) { } void m6802_cpu_device::ram_map(address_map &map) { if (m_ram_enable) map(0x0000, 0x007f).ram(); } m6808_cpu_device::m6808_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : m6802_cpu_device(mconfig, M6808, tag, owner, clock, m6800_insn, cycles_6800) { set_ram_enable(false); } void m6808_cpu_device::device_validity_check(validity_checker &valid) const { if (m_ram_enable) osd_printf_error("MC6808 should not have internal RAM enabled\n"); } nsc8105_cpu_device::nsc8105_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : m6802_cpu_device(mconfig, NSC8105, tag, owner, clock, nsc8105_insn, cycles_nsc8105) { } device_memory_interface::space_config_vector m6800_cpu_device::memory_space_config() const { if (has_configured_map(AS_OPCODES)) return space_config_vector { std::make_pair(AS_PROGRAM, &m_program_config), std::make_pair(AS_OPCODES, &m_decrypted_opcodes_config) }; else return space_config_vector { std::make_pair(AS_PROGRAM, &m_program_config) }; } u32 m6800_cpu_device::RM16(u32 Addr) { u32 result = RM(Addr) << 8; return result | RM((Addr+1) & 0xffff); } void m6800_cpu_device::WM16(u32 Addr, PAIR *p) { WM(Addr, p->b.h); WM((Addr+1) & 0xffff, p->b.l); } /* IRQ enter */ void m6800_cpu_device::enter_interrupt(const char *message, u16 irq_vector) { int cycles_to_eat = 0; LOGIRQ("Take %s interrupt\n", message); if (m_wai_state & M6800_WAI) { cycles_to_eat = 4; m_wai_state &= ~M6800_WAI; } else { PUSHWORD(pPC); PUSHWORD(pX); PUSHBYTE(A); PUSHBYTE(B); PUSHBYTE(CC); cycles_to_eat = 12; } SEI; PCD = RM16(irq_vector); increment_counter(cycles_to_eat); } /* check the IRQ lines for pending interrupts */ void m6800_cpu_device::check_irq_lines() { if (m_nmi_pending) { m_wai_state &= ~M6800_SLP; m_nmi_pending = false; enter_interrupt("NMI", 0xfffc); } else if (check_irq1_enabled()) { /* standard IRQ */ m_wai_state &= ~M6800_SLP; if (!(CC & 0x10)) { standard_irq_callback(M6800_IRQ_LINE, m_pc.w.l); enter_interrupt("IRQ1", 0xfff8); } } else check_irq2(); } bool m6800_cpu_device::check_irq1_enabled() { return m_irq_state[M6800_IRQ_LINE] != CLEAR_LINE; } void m6800_cpu_device::increment_counter(int amount) { m_icount -= amount; } void m6800_cpu_device::eat_cycles() { if (m_icount > 0) increment_counter(m_icount); } void m6800_cpu_device::device_start() { space(AS_PROGRAM).cache(m_cprogram); space(has_space(AS_OPCODES) ? AS_OPCODES : AS_PROGRAM).cache(m_copcodes); space(AS_PROGRAM).specific(m_program); m_ppc.d = 0; m_pc.d = 0; m_s.d = 0; m_x.d = 0; m_d.d = 0; m_cc = 0; m_wai_state = 0; m_nmi_state = 0; m_nmi_pending = 0; std::fill(std::begin(m_irq_state), std::end(m_irq_state), 0); save_item(NAME(m_ppc.w.l)); save_item(NAME(m_pc.w.l)); save_item(NAME(m_s.w.l)); save_item(NAME(m_x.w.l)); save_item(NAME(m_d.w.l)); save_item(NAME(m_cc)); save_item(NAME(m_wai_state)); save_item(NAME(m_nmi_state)); save_item(NAME(m_nmi_pending)); save_item(NAME(m_irq_state)); state_add( M6800_A, "A", m_d.b.h).formatstr("%02X"); state_add( M6800_B, "B", m_d.b.l).formatstr("%02X"); state_add( M6800_PC, "PC", m_pc.w.l).formatstr("%04X"); state_add( M6800_S, "S", m_s.w.l).formatstr("%04X"); state_add( M6800_X, "X", m_x.w.l).formatstr("%04X"); state_add( M6800_CC, "CC", m_cc).formatstr("%02X"); state_add( M6800_WAI_STATE, "WAI", m_wai_state).formatstr("%01X"); state_add( STATE_GENPC, "GENPC", m_pc.w.l).noshow(); state_add( STATE_GENPCBASE, "CURPC", m_pc.w.l).noshow(); state_add( STATE_GENFLAGS, "GENFLAGS", m_cc).formatstr("%8s").noshow(); set_icountptr(m_icount); } void m6800_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const { switch (entry.index()) { case STATE_GENFLAGS: str = string_format("%c%c%c%c%c%c%c%c", m_cc & 0x80 ? '?':'.', m_cc & 0x40 ? '?':'.', m_cc & 0x20 ? 'H':'.', m_cc & 0x10 ? 'I':'.', m_cc & 0x08 ? 'N':'.', m_cc & 0x04 ? 'Z':'.', m_cc & 0x02 ? 'V':'.', m_cc & 0x01 ? 'C':'.'); break; } } void m6800_cpu_device::device_reset() { m_cc = 0xc0; SEI; /* IRQ disabled */ PCD = RM16(0xfffe); m_wai_state = 0; m_nmi_state = 0; m_nmi_pending = 0; } void m6800_cpu_device::execute_set_input(int irqline, int state) { switch (irqline) { case INPUT_LINE_NMI: if (!m_nmi_state && state != CLEAR_LINE) m_nmi_pending = true; m_nmi_state = state; break; default: m_irq_state[irqline] = state; break; } } void m6800_cpu_device::execute_run() { check_irq_lines(); cleanup_counters(); do { if (m_wai_state & (M6800_WAI | M6800_SLP)) { debugger_wait_hook(); eat_cycles(); } else { execute_one(); } } while (m_icount > 0); } void m6800_cpu_device::execute_one() { pPPC = pPC; debugger_instruction_hook(PCD); u8 ireg = M_RDOP(PCD); PC++; (this->*m_insn[ireg])(); increment_counter(m_cycles[ireg]); } std::unique_ptr m6800_cpu_device::create_disassembler() { return std::make_unique(6800); } std::unique_ptr m6802_cpu_device::create_disassembler() { return std::make_unique(6802); } std::unique_ptr m6808_cpu_device::create_disassembler() { return std::make_unique(6808); } std::unique_ptr nsc8105_cpu_device::create_disassembler() { return std::make_unique(8105); }