1 /*** m6800: Portable 6800 class  emulator *************************************
2 
3     m6800.c
4 
5     References:
6 
7         6809 Simulator V09, By L.C. Benschop, Eidnhoven The Netherlands.
8 
9         m6809: Portable 6809 emulator, DS (6809 code in MAME, derived from
10             the 6809 Simulator V09)
11 
12         6809 Microcomputer Programming & Interfacing with Experiments"
13             by Andrew C. Staugaard, Jr.; Howard W. Sams & Co., Inc.
14 
15     System dependencies:    UINT16 must be 16 bit unsigned int
16                             UINT8 must be 8 bit unsigned int
17                             UINT32 must be more than 16 bits
18                             arrays up to 65536 bytes must be supported
19                             machine must be twos complement
20 
21 History
22 991031  ZV
23     Added NSC-8105 support
24 
25 990319  HJB
26     Fixed wrong LSB/MSB order for push/pull word.
27     Subtract .extra_cycles at the beginning/end of the exectuion loops.
28 
29 990316  HJB
30     Renamed to 6800, since that's the basic CPU.
31     Added different cycle count tables for M6800/2/8, M6801/3 and HD63701.
32 
33 990314  HJB
34     Also added the M6800 subtype.
35 
36 990311  HJB
37     Added _info functions. Now uses static m6808_Regs struct instead
38     of single statics. Changed the 16 bit registers to use the generic
39     PAIR union. Registers defined using macros. Split the core into
40     four execution loops for M6802, M6803, M6808 and HD63701.
41     TST, TSTA and TSTB opcodes reset carry flag.
42 TODO:
43     Verify invalid opcodes for the different CPU types.
44     Add proper credits to _info functions.
45     Integrate m6808_Flags into the registers (multiple m6808 type CPUs?)
46 
47 990301  HJB
48     Modified the interrupt handling. No more pending interrupt checks.
49     WAI opcode saves state, when an interrupt is taken (IRQ or OCI),
50     the state is only saved if not already done by WAI.
51 
52 *****************************************************************************/
53 
54 
55 //#include "debugger.h"
56 #include "burnint.h"
57 #include "m6800.h"
58 #include <stddef.h>
59 
60 #define VERBOSE 0
61 
62 #if VERBOSE
63 #define LOG(x)	logerror x
64 #else
65 #define LOG(x)
66 #endif
67 
68 #define M6800_INLINE		static
69 //#define change_pc(newpc)	m6800.pc.w.l = (newpc)
70 #define M6800_CLEAR_LINE	0
71 
72 #if 0
73 /* CPU subtypes, needed for extra insn after TAP/CLI/SEI */
74 enum {
75 	SUBTYPE_M6800,
76 	SUBTYPE_M6801,
77 	SUBTYPE_M6802,
78 	SUBTYPE_M6803,
79 	SUBTYPE_M6808,
80 	SUBTYPE_HD63701,
81 	SUBTYPE_NSC8105
82 };
83 #endif
84 
85 /* 680x registers */
86 static m6800_Regs m6800;
87 
88 #define m6801   m6800
89 #define m6802   m6800
90 #define m6803	m6800
91 #define m6808	m6800
92 #define hd63701 m6800
93 #define nsc8105 m6800
94 
95 #define	pPPC	m6800.ppc
96 #define pPC 	m6800.pc
97 #define pS		m6800.s
98 #define pX		m6800.x
99 #define pD		m6800.d
100 
101 #define PC		m6800.pc.w.l
102 #define PCD		m6800.pc.d
103 #define S		m6800.s.w.l
104 #define SD		m6800.s.d
105 #define X		m6800.x.w.l
106 #define D		m6800.d.w.l
107 #define A		m6800.d.b.h
108 #define B		m6800.d.b.l
109 #define CC		m6800.cc
110 
111 #define CT		m6800.counter.w.l
112 #define CTH		m6800.counter.w.h
113 #define CTD		m6800.counter.d
114 #define OC		m6800.output_compare.w.l
115 #define OCH		m6800.output_compare.w.h
116 #define OCD		m6800.output_compare.d
117 #define TOH		m6800.timer_over.w.l
118 #define TOD		m6800.timer_over.d
119 
120 //static PAIR ea; 		/* effective address */
121 #define ea		m6800.ea
122 #define EAD		ea.d
123 #define EA		ea.w.l
124 
125 /* public globals */
126 #define m6800_ICount	m6800.m6800_ICount
127 
128 /* point of next timer event */
129 #define timer_next		m6800.timer_next
130 
131 /* DS -- THESE ARE RE-DEFINED IN m6800.h TO RAM, ROM or FUNCTIONS IN cpuintrf.c */
132 #define RM				M6800_RDMEM
133 #define WM				M6800_WRMEM
134 #define M_RDOP			M6800_RDOP
135 #define M_RDOP_ARG		M6800_RDOP_ARG
136 
137 /* macros to access memory */
138 #define IMMBYTE(b)	b = M_RDOP_ARG(PCD); PC++
139 #define IMMWORD(w)	w.d = (M_RDOP_ARG(PCD)<<8) | M_RDOP_ARG((PCD+1)&0xffff); PC+=2
140 
141 #define PUSHBYTE(b) WM(SD,b); --S
142 #define PUSHWORD(w) WM(SD,w.b.l); --S; WM(SD,w.b.h); --S
143 #define PULLBYTE(b) S++; b = RM(SD)
144 #define PULLWORD(w) S++; w.d = RM(SD)<<8; S++; w.d |= RM(SD)
145 
146 #define MODIFIED_tcsr {	\
147 	m6800.irq2 = (m6800.tcsr&(m6800.tcsr<<3))&(TCSR_ICF|TCSR_OCF|TCSR_TOF); \
148 }
149 
150 #define SET_TIMER_EVENT {					\
151 	timer_next = (OCD - CTD < TOD - CTD) ? OCD : TOD;	\
152 }
153 
154 /* cleanup high-word of counters */
155 #define CLEANUP_conters {						\
156 	OCH -= CTH;									\
157 	TOH -= CTH;									\
158 	CTH = 0;									\
159 	SET_TIMER_EVENT;							\
160 }
161 
162 /* when change freerunningcounter or outputcapture */
163 #define MODIFIED_counters {						\
164 	OCH = (OC >= CT) ? CTH : CTH+1;				\
165 	SET_TIMER_EVENT;							\
166 }
167 
168 /* take interrupt */
169 #define TAKE_ICI ENTER_INTERRUPT("M6800#%d take ICI\n",0xfff6)
170 #define TAKE_OCI ENTER_INTERRUPT("M6800#%d take OCI\n",0xfff4)
171 #define TAKE_TOI ENTER_INTERRUPT("M6800#%d take TOI\n",0xfff2)
172 #define TAKE_SCI ENTER_INTERRUPT("M6800#%d take SCI\n",0xfff0)
173 #define TAKE_TRAP ENTER_INTERRUPT("M6800#%d take TRAP\n",0xffee)
174 
175 /* check IRQ2 (internal irq) */
176 #define CHECK_IRQ2 {											\
177 	if(m6800.irq2&(TCSR_ICF|TCSR_OCF|TCSR_TOF))					\
178 	{															\
179 		if(m6800.irq2&TCSR_ICF)									\
180 		{														\
181 			TAKE_ICI;											\
182 		}														\
183 		else if(m6800.irq2&TCSR_OCF)							\
184 		{														\
185 			TAKE_OCI;											\
186 		}														\
187 		else if(m6800.irq2&TCSR_TOF)							\
188 		{														\
189 			TAKE_TOI;											\
190 		}														\
191 	}															\
192 }
193 
194 /* operate one instruction for */
195 #define ONE_MORE_INSN() {		\
196 	UINT8 ireg; 							\
197 	pPPC = pPC; 							\
198 	ireg=M_RDOP(PCD);						\
199 	PC++;									\
200 	(*m6800.insn[ireg])();					\
201 	INCREMENT_COUNTER(m6800.cycles[ireg]);	\
202 }
203 
204 /* check the IRQ lines for pending interrupts */
205 #define CHECK_IRQ_LINES() {										\
206 	{															\
207 		if( m6800.irq_state[M6800_IRQ_LINE] != M6800_CLEAR_LINE )		\
208 		{	/* standard IRQ */									\
209 			if(m6800.wai_state & M6800_SLP)                     \
210 				m6800.wai_state &= ~M6800_SLP;                  \
211 	        if( !(CC & 0x10) ) { 								\
212 			    ENTER_INTERRUPT("M6800#%d take IRQ1\n",0xfff8);	\
213         	    if (m6800.irq_hold[M6800_IRQ_LINE])             \
214 	                m6800_set_irq_line(M6800_IRQ_LINE, 0);      \
215     	    }													\
216     	} else { 												\
217 	        if( !(CC & 0x10) ) { 								\
218 	            CHECK_IRQ2;										\
219 	            if (m6800.irq_hold[M6800_TIN_LINE])             \
220                     m6800_set_irq_line(M6800_TIN_LINE, 0);      \
221 																\
222     	    }													\
223     	}														\
224 	}															\
225 }
226 
227 /* CC masks                       HI NZVC
228                                 7654 3210   */
229 #define CLR_HNZVC	CC&=0xd0
230 #define CLR_NZV 	CC&=0xf1
231 #define CLR_HNZC	CC&=0xd2
232 #define CLR_NZVC	CC&=0xf0
233 #define CLR_Z		CC&=0xfb
234 #define CLR_ZC		CC&=0xfa
235 #define CLR_C		CC&=0xfe
236 
237 /* macros for CC -- CC bits affected should be reset before calling */
238 #define SET_Z(a)		if(!(a))SEZ
239 #define SET_Z8(a)		SET_Z((UINT8)(a))
240 #define SET_Z16(a)		SET_Z((UINT16)(a))
241 #define SET_N8(a)		CC|=(((a)&0x80)>>4)
242 #define SET_N16(a)		CC|=(((a)&0x8000)>>12)
243 #define SET_H(a,b,r)	CC|=((((a)^(b)^(r))&0x10)<<1)
244 #define SET_C8(a)		CC|=(((a)&0x100)>>8)
245 #define SET_C16(a)		CC|=(((a)&0x10000)>>16)
246 #define SET_V8(a,b,r)	CC|=((((a)^(b)^(r)^((r)>>1))&0x80)>>6)
247 #define SET_V16(a,b,r)	CC|=((((a)^(b)^(r)^((r)>>1))&0x8000)>>14)
248 
249 static const UINT8 flags8i[256]=	 /* increment */
250 {
251 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
252 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
253 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
254 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
255 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
256 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
257 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
258 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
259 0x0a,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
260 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
261 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
262 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
263 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
264 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
265 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
266 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08
267 };
268 static const UINT8 flags8d[256]= /* decrement */
269 {
270 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
271 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
272 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
273 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
274 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
275 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
276 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
277 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,
278 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
279 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
280 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
281 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
282 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
283 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
284 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
285 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08
286 };
287 #define SET_FLAGS8I(a)		{CC|=flags8i[(a)&0xff];}
288 #define SET_FLAGS8D(a)		{CC|=flags8d[(a)&0xff];}
289 
290 /* combos */
291 #define SET_NZ8(a)			{SET_N8(a);SET_Z8(a);}
292 #define SET_NZ16(a)			{SET_N16(a);SET_Z16(a);}
293 #define SET_FLAGS8(a,b,r)	{SET_N8(r);SET_Z8(r);SET_V8(a,b,r);SET_C8(r);}
294 #define SET_FLAGS16(a,b,r)	{SET_N16(r);SET_Z16(r);SET_V16(a,b,r);SET_C16(r);}
295 
296 /* for treating an UINT8 as a signed INT16 */
297 #define SIGNED(b) ((INT16)(b&0x80?b|0xff00:b))
298 
299 /* Macros for addressing modes */
300 #define DIRECT IMMBYTE(EAD)
301 #define IMM8 EA=PC++
302 #define IMM16 {EA=PC;PC+=2;}
303 #define EXTENDED IMMWORD(ea)
304 #define INDEXED {EA=X+(UINT8)M_RDOP_ARG(PCD);PC++;}
305 
306 /* macros to set status flags */
307 #if defined(SEC)
308 #undef SEC
309 #endif
310 #define SEC CC|=0x01
311 #define CLC CC&=0xfe
312 #define SEZ CC|=0x04
313 #define CLZ CC&=0xfb
314 #define SEN CC|=0x08
315 #define CLN CC&=0xf7
316 #define SEV CC|=0x02
317 #define CLV CC&=0xfd
318 #define SEH CC|=0x20
319 #define CLH CC&=0xdf
320 #define SEI CC|=0x10
321 #define CLI CC&=~0x10
322 
323 /* mnemonicos for the Timer Control and Status Register bits */
324 #define TCSR_OLVL 0x01
325 #define TCSR_IEDG 0x02
326 #define TCSR_ETOI 0x04
327 #define TCSR_EOCI 0x08
328 #define TCSR_EICI 0x10
329 #define TCSR_TOF  0x20
330 #define TCSR_OCF  0x40
331 #define TCSR_ICF  0x80
332 
333 #define INCREMENT_COUNTER(amount)	\
334 {									\
335 	m6800_ICount -= amount;			\
336 	CTD += amount;					\
337 	if( CTD >= timer_next)			\
338 		check_timer_event();		\
339 }
340 
341 #define EAT_CYCLES													\
342 {																	\
343 	int cycles_to_eat;												\
344 																	\
345 	cycles_to_eat = timer_next - CTD;								\
346 	if( cycles_to_eat > m6800_ICount) cycles_to_eat = m6800_ICount;	\
347 	if (cycles_to_eat > 0)											\
348 	{																\
349 		INCREMENT_COUNTER(cycles_to_eat);							\
350 	}																\
351 }
352 
353 /* macros for convenience */
354 #define DIRBYTE(b) {DIRECT;b=RM(EAD);}
355 #define DIRWORD(w) {DIRECT;w.d=RM16(EAD);}
356 #define EXTBYTE(b) {EXTENDED;b=RM(EAD);}
357 #define EXTWORD(w) {EXTENDED;w.d=RM16(EAD);}
358 
359 #define IDXBYTE(b) {INDEXED;b=RM(EAD);}
360 #define IDXWORD(w) {INDEXED;w.d=RM16(EAD);}
361 
362 /* Macros for branch instructions */
363 #define BRANCH(f) {IMMBYTE(t);if(f){PC+=SIGNED(t);}}
364 #define NXORV  ((CC&0x08)^((CC&0x02)<<2))
365 #define NXORC  ((CC&0x08)^((CC&0x01)<<3))
366 
367 /* Note: we use 99 cycles here for invalid opcodes so that we don't */
368 /* hang in an infinite loop if we hit one */
369 #define XX 5 // invalid opcode unknown cc
370 static const UINT8 cycles_6800[] =
371 {
372 		/* 0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F */
373 	/*0*/ XX, 2,XX,XX,XX,XX, 2, 2, 4, 4, 2, 2, 2, 2, 2, 2,
374 	/*1*/  2, 2,XX,XX,XX,XX, 2, 2,XX, 2,XX, 2,XX,XX,XX,XX,
375 	/*2*/  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
376 	/*3*/  4, 4, 4, 4, 4, 4, 4, 4,XX, 5,XX,10,XX,XX, 9,12,
377 	/*4*/  2,XX,XX, 2, 2,XX, 2, 2, 2, 2, 2,XX, 2, 2,XX, 2,
378 	/*5*/  2,XX,XX, 2, 2,XX, 2, 2, 2, 2, 2,XX, 2, 2,XX, 2,
379 	/*6*/  7,XX,XX, 7, 7,XX, 7, 7, 7, 7, 7,XX, 7, 7, 4, 7,
380 	/*7*/  6,XX,XX, 6, 6,XX, 6, 6, 6, 6, 6,XX, 6, 6, 3, 6,
381 	/*8*/  2, 2, 2,XX, 2, 2, 2, 3, 2, 2, 2, 2, 3, 8, 3, 4,
382 	/*9*/  3, 3, 3,XX, 3, 3, 3, 4, 3, 3, 3, 3, 4, 6, 4, 5,
383 	/*A*/  5, 5, 5,XX, 5, 5, 5, 6, 5, 5, 5, 5, 6, 8, 6, 7,
384 	/*B*/  4, 4, 4,XX, 4, 4, 4, 5, 4, 4, 4, 4, 5, 9, 5, 6,
385 	/*C*/  2, 2, 2,XX, 2, 2, 2, 3, 2, 2, 2, 2,XX,XX, 3, 4,
386 	/*D*/  3, 3, 3,XX, 3, 3, 3, 4, 3, 3, 3, 3,XX,XX, 4, 5,
387 	/*E*/  5, 5, 5,XX, 5, 5, 5, 6, 5, 5, 5, 5,XX,XX, 6, 7,
388 	/*F*/  4, 4, 4,XX, 4, 4, 4, 5, 4, 4, 4, 4,XX,XX, 5, 6
389 };
390 
391 static const UINT8 cycles_6803[] =
392 {
393 		/* 0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F */
394 	/*0*/ XX, 2,XX,XX, 3, 3, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2,
395 	/*1*/  2, 2,XX,XX,XX,XX, 2, 2,XX, 2,XX, 2,XX,XX,XX,XX,
396 	/*2*/  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
397 	/*3*/  3, 3, 4, 4, 3, 3, 3, 3, 5, 5, 3,10, 4,10, 9,12,
398 	/*4*/  2,XX,XX, 2, 2,XX, 2, 2, 2, 2, 2,XX, 2, 2,XX, 2,
399 	/*5*/  2,XX,XX, 2, 2,XX, 2, 2, 2, 2, 2,XX, 2, 2,XX, 2,
400 	/*6*/  6,XX,XX, 6, 6,XX, 6, 6, 6, 6, 6,XX, 6, 6, 3, 6,
401 	/*7*/  6,XX,XX, 6, 6,XX, 6, 6, 6, 6, 6,XX, 6, 6, 3, 6,
402 	/*8*/  2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 4, 6, 3, 3,
403 	/*9*/  3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 4, 4,
404 	/*A*/  4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 5, 5,
405 	/*B*/  4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 5, 5,
406 	/*C*/  2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 3,XX, 3, 3,
407 	/*D*/  3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
408 	/*E*/  4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
409 	/*F*/  4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5
410 };
411 
412 static const UINT8 cycles_63701[] =
413 {
414 		/* 0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F */
415 	/*0*/ XX, 1,XX,XX, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
416 	/*1*/  1, 1,XX,XX,XX,XX, 1, 1, 2, 2, 4, 1,XX,XX,XX,XX,
417 	/*2*/  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
418 	/*3*/  1, 1, 3, 3, 1, 1, 4, 4, 4, 5, 1,10, 5, 7, 9,12,
419 	/*4*/  1,XX,XX, 1, 1,XX, 1, 1, 1, 1, 1,XX, 1, 1,XX, 1,
420 	/*5*/  1,XX,XX, 1, 1,XX, 1, 1, 1, 1, 1,XX, 1, 1,XX, 1,
421 	/*6*/  6, 7, 7, 6, 6, 7, 6, 6, 6, 6, 6, 5, 6, 4, 3, 5,
422 	/*7*/  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 6, 4, 3, 5,
423 	/*8*/  2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 5, 3, 3,
424 	/*9*/  3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 4, 4,
425 	/*A*/  4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
426 	/*B*/  4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 5, 5,
427 	/*C*/  2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3,XX, 3, 3,
428 	/*D*/  3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
429 	/*E*/  4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
430 	/*F*/  4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5
431 };
432 
433 static const UINT8 cycles_nsc8105[] =
434 {
435 		/* 0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F */
436 	/*0*/  5,XX, 2,XX,XX, 2,XX, 2, 4, 2, 4, 2, 2, 2, 2, 2,
437 	/*1*/  2,XX, 2,XX,XX, 2,XX, 2,XX,XX, 2, 2,XX,XX,XX,XX,
438 	/*2*/  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
439 	/*3*/  4, 4, 4, 4, 4, 4, 4, 4,XX,XX, 5,10,XX, 9,XX,12,
440 	/*4*/  2, 2, 2,XX, 2, 2, 2, 3, 2, 2, 2, 2, 3, 3, 8, 4,
441 	/*5*/  3, 3, 3,XX, 3, 3, 3, 4, 3, 3, 3, 3, 4, 4, 6, 5,
442 	/*6*/  5, 5, 5,XX, 5, 5, 5, 6, 5, 5, 5, 5, 6, 6, 8, 7,
443 	/*7*/  4, 4, 4,XX, 4, 4, 4, 5, 4, 4, 4, 4, 5, 5, 9, 6,
444 	/*8*/  2,XX,XX, 2, 2, 2,XX, 2, 2, 2, 2,XX, 2,XX, 2, 2,
445 	/*9*/  2,XX,XX, 2, 2, 2,XX, 2, 2, 2, 2,XX, 2,XX, 2, 2,
446 	/*A*/  7,XX,XX, 7, 7, 7,XX, 7, 7, 7, 7,XX, 7, 4, 7, 7,
447 	/*B*/  6,XX,XX, 6, 6, 6,XX, 6, 6, 6, 6, 5, 6, 3, 6, 6,
448 	/*C*/  2, 2, 2,XX, 2, 2, 2, 3, 2, 2, 2, 2,XX, 3,XX, 4,
449 	/*D*/  3, 3, 3,XX, 3, 3, 3, 4, 3, 3, 3, 3,XX, 4,XX, 5,
450 	/*E*/  5, 5, 5,XX, 5, 5, 5, 6, 5, 5, 5, 5, 5, 6,XX, 7,
451 	/*F*/  4, 4, 4,XX, 4, 4, 4, 5, 4, 4, 4, 4, 4, 5,XX, 6
452 };
453 #undef XX // /invalid opcode unknown cc
454 
RM16(UINT32 Addr)455 M6800_INLINE UINT32 RM16( UINT32 Addr )
456 {
457 	UINT32 result = RM(Addr) << 8;
458 	return result | RM((Addr+1)&0xffff);
459 }
460 
WM16(UINT32 Addr,PAIR * p)461 M6800_INLINE void WM16( UINT32 Addr, PAIR *p )
462 {
463 	WM( Addr, p->b.h );
464 	WM( (Addr+1)&0xffff, p->b.l );
465 }
466 
467 /* IRQ enter */
ENTER_INTERRUPT(const char *,UINT16 irq_vector)468 static void ENTER_INTERRUPT(const char *,UINT16 irq_vector)
469 {
470 //	LOG((message, cpu_getactivecpu()));
471 	if( m6800.wai_state & (M6800_WAI|M6800_SLP) )
472 	{
473 		if( m6800.wai_state & M6800_WAI )
474 			m6800.extra_cycles += 4;
475 		m6800.wai_state &= ~(M6800_WAI|M6800_SLP);
476 	}
477 	else
478 	{
479 		PUSHWORD(pPC);
480 		PUSHWORD(pX);
481 		PUSHBYTE(A);
482 		PUSHBYTE(B);
483 		PUSHBYTE(CC);
484 		m6800.extra_cycles += 12;
485 	}
486 	SEI;
487 	PCD = RM16( irq_vector );
488 }
489 
490 /* check OCI or TOI */
check_timer_event(void)491 static void check_timer_event(void)
492 {
493 	/* OCI */
494 	if( CTD >= OCD)
495 	{
496 		OCH++;	// next IRQ point
497 		m6800.tcsr |= TCSR_OCF;
498 		m6800.pending_tcsr |= TCSR_OCF;
499 		MODIFIED_tcsr;
500 		if ( !(CC & 0x10) && (m6800.tcsr & TCSR_EOCI))
501 			TAKE_OCI;
502 	}
503 	/* TOI */
504 	if( CTD >= TOD)
505 	{
506 		TOH++;	// next IRQ point
507 #if 0
508 		CLEANUP_conters;
509 #endif
510 		m6800.tcsr |= TCSR_TOF;
511 		m6800.pending_tcsr |= TCSR_TOF;
512 		MODIFIED_tcsr;
513 		if ( !(CC & 0x10) && (m6800.tcsr & TCSR_ETOI))
514 			TAKE_TOI;
515 	}
516 	/* set next event */
517 	SET_TIMER_EVENT;
518 }
519 
520 /* include the opcode prototypes and function pointer tables */
521 #include "6800tbl.c"
522 
523 /* include the opcode functions */
524 #include "6800ops.c"
525 
526 /****************************************************************************
527  * Reset registers to their initial values
528  ****************************************************************************/
529 
m6800_init()530 void m6800_init()
531 {
532 //  m6800.subtype   = SUBTYPE_M6800;
533 	m6800.insn = m6800_insn;
534 	m6800.cycles = cycles_6800;
535 //	m6800.irq_callback = irqcallback;
536 //	state_register("m6800", index);
537 }
538 
m6800_reset(void)539 void m6800_reset(void)
540 {
541 	// clear context
542 	memset(&m6800, 0, STRUCT_SIZE_HELPER(m6800_Regs, timer_over));
543 
544 	m6800.cc = 0xc0;
545 	SEI;				/* IRQ disabled */
546 	PCD = RM16( 0xfffe );
547 
548 	m6800.wai_state = 0;
549 	m6800.nmi_state = 0;
550 	m6800.irq_state[M6800_IRQ_LINE] = 0;
551 	m6800.irq_state[M6800_TIN_LINE] = 0;
552 	m6800.ic_eddge = 0;
553 
554 	m6800.port1_ddr = 0x00;
555 	m6800.port2_ddr = 0x00;
556 	/* TODO: on reset port 2 should be read to determine the operating mode (bits 0-2) */
557 	m6800.tcsr = 0x00;
558 	m6800.pending_tcsr = 0x00;
559 	m6800.irq2 = 0;
560 	CTD = 0x0000;
561 	OCD = 0xffff;
562 	TOD = 0xffff;
563 	m6800.ram_ctrl |= 0x40;
564 }
565 
m6800_get_pc()566 int m6800_get_pc()
567 {
568 	return PC;
569 }
570 
571 /****************************************************************************
572  * Shut down CPU emulatio
573  ****************************************************************************/
574 /*
575 static void m6800_exit(void)
576 {
577 
578 }*/
579 
580 /****************************************************************************
581  * Get all registers in given buffer
582  ****************************************************************************/
m6800_get_context(void * dst)583 void m6800_get_context(void *dst)
584 {
585 	if( dst )
586 		*(m6800_Regs*)dst = m6800;
587 }
588 
589 
590 /****************************************************************************
591  * Set all registers to given values
592  ****************************************************************************/
m6800_set_context(void * src)593 void m6800_set_context(void *src)
594 {
595 	if( src )
596 		m6800 = *(m6800_Regs*)src;
597 	//CHANGE_PC();
598 	//CHECK_IRQ_LINES(); /* HJB 990417 */
599 }
600 
601 
m6800_set_irq_line(int irqline,int state)602 void m6800_set_irq_line(int irqline, int state)
603 {
604 	int hold = 0;
605 
606 	if (state == 2) { hold = 1; state = 1; }
607 
608 	if (irqline == M6800_INPUT_LINE_NMI)
609 	{
610 		if (m6800.nmi_state == state) return;
611 		LOG(("M6800#%d set_nmi_line %d \n", cpu_getactivecpu(), state));
612 		m6800.nmi_state = state;
613 		if (state == M6800_CLEAR_LINE) return;
614 
615 		/* NMI */
616 		ENTER_INTERRUPT("M6800#%d take NMI\n",0xfffc);
617 	}
618 	else
619 	{
620 		int eddge;
621 
622 		if (m6800.irq_state[irqline] == state) return;
623 		LOG(("M6800#%d set_irq_line %d,%d\n", cpu_getactivecpu(), irqline, state));
624 		m6800.irq_state[irqline] = state;
625 		m6800.irq_hold[irqline] = hold;
626 
627 		switch(irqline)
628 		{
629 		case M6800_IRQ_LINE:
630 			if (state == M6800_CLEAR_LINE) return;
631 			break;
632 		case M6800_TIN_LINE:
633 			eddge = (state == M6800_CLEAR_LINE ) ? 2 : 0;
634 			if( ((m6800.tcsr&TCSR_IEDG) ^ (state==M6800_CLEAR_LINE ? TCSR_IEDG : 0))==0 )
635 				return;
636 			/* active edge in */
637 			m6800.tcsr |= TCSR_ICF;
638 			m6800.pending_tcsr |= TCSR_ICF;
639 			m6800.input_capture = CT;
640 			MODIFIED_tcsr;
641 			if( !(CC & 0x10) )
642 				CHECK_IRQ2
643 			break;
644 		default:
645 			return;
646 		}
647 		CHECK_IRQ_LINES(); /* HJB 990417 */
648 	}
649 }
650 
m6800_get_segmentcycles()651 int m6800_get_segmentcycles()
652 {
653 	return m6800.segmentcycles - m6800_ICount;
654 }
655 
656 /****************************************************************************
657  * Execute cycles CPU cycles. Return number of cycles really executed
658  ****************************************************************************/
m6800_execute(int cycles)659 int m6800_execute(int cycles)
660 {
661 	UINT8 ireg;
662 
663 	m6800.segmentcycles = cycles;
664 	m6800_ICount = cycles;
665 	CHECK_IRQ_LINES();
666 
667 	CLEANUP_conters;
668 	INCREMENT_COUNTER(m6800.extra_cycles);
669 	m6800.extra_cycles = 0;
670 
671 	do
672 	{
673 		if( m6800.wai_state & (M6800_WAI|M6800_SLP) )
674 		{
675 			EAT_CYCLES;
676 		}
677 		else
678 		{
679 			pPPC = pPC;
680 //			CALL_MAME_DEBUG;
681 			ireg=M_RDOP(PCD);
682 			PC++;
683 			(*m6800.insn[ireg])();
684 			INCREMENT_COUNTER(cycles_6800[ireg]);
685 		}
686 
687 	} while( m6800_ICount>0 );
688 
689 	INCREMENT_COUNTER(m6800.extra_cycles);
690 	m6800.extra_cycles = 0;
691 
692 	cycles = cycles - m6800_ICount;
693 
694 	m6800.segmentcycles = m6800_ICount = 0;
695 
696 	return cycles;
697 }
698 
699 /****************************************************************************
700  * M6801 almost (fully?) equal to the M6803
701  ****************************************************************************/
702 #if (HAS_M6801)
m6801_init()703 void m6801_init()
704 {
705 //  m6800.subtype = SUBTYPE_M6801;
706 	m6800.insn = m6803_insn;
707 	m6800.cycles = cycles_6803;
708 //	m6800.irq_callback = irqcallback;
709 //	state_register("m6801", index);
710 }
711 #endif
712 
713 /****************************************************************************
714  * M6802 almost (fully?) equal to the M6800
715  ****************************************************************************/
716 #if (HAS_M6802)
m6802_init(int index,int clock,const void * config,int (* irqcallback)(int))717 static void m6802_init(int index, int clock, const void *config, int (*irqcallback)(int))
718 {
719 //  m6800.subtype   = SUBTYPE_M6802;
720 	m6800.insn = m6800_insn;
721 	m6800.cycles = cycles_6800;
722 	m6800.irq_callback = irqcallback;
723 	state_register("m6802", index);
724 }
725 #endif
726 
727 /****************************************************************************
728  * M6803 almost (fully?) equal to the M6801
729  ****************************************************************************/
730 #if (HAS_M6803)
m6803_init()731 void m6803_init()
732 {
733 //  m6800.subtype = SUBTYPE_M6803;
734 	m6800.insn = m6803_insn;
735 	m6800.cycles = cycles_6803;
736 //	m6800.irq_callback = irqcallback;
737 //	state_register("m6803", index);
738 }
739 #endif
740 
741 /****************************************************************************
742  * Execute cycles CPU cycles. Return number of cycles really executed
743  ****************************************************************************/
744 #if (HAS_M6803||HAS_M6801)
m6803_execute(int cycles)745 int m6803_execute(int cycles)
746 {
747 	UINT8 ireg;
748 
749 	m6800.segmentcycles = cycles;
750 	m6800_ICount = cycles;
751 
752 	CLEANUP_conters;
753 	INCREMENT_COUNTER(m6803.extra_cycles);
754 	m6803.extra_cycles = 0;
755 
756 	do
757 	{
758 		if( m6803.wai_state & M6800_WAI )
759 		{
760 			EAT_CYCLES;
761 		}
762 		else
763 		{
764 			pPPC = pPC;
765 //			CALL_MAME_DEBUG;
766 			ireg=M_RDOP(PCD);
767 			PC++;
768 			(*m6803.insn[ireg])();
769 			INCREMENT_COUNTER(cycles_6803[ireg]);
770 		}
771 
772 	} while( m6800_ICount>0 );
773 
774 	INCREMENT_COUNTER(m6803.extra_cycles);
775 	m6803.extra_cycles = 0;
776 
777 	cycles = cycles - m6800_ICount;
778 
779 	m6800.segmentcycles = m6800_ICount = 0;
780 
781 	return cycles;
782 }
783 #endif
784 
785 #if (HAS_M6803)
786 
787 //static READ8_HANDLER( m6803_internal_registers_r );
788 //static WRITE8_HANDLER( m6803_internal_registers_w );
789 
790 //static ADDRESS_MAP_START(m6803_mem, ADDRESS_SPACE_PROGRAM, 8)
791 //	AM_RANGE(0x0000, 0x001f) AM_READWRITE(m6803_internal_registers_r, m6803_internal_registers_w)
792 //	AM_RANGE(0x0020, 0x007f) AM_NOP        /* unused */
793 //	AM_RANGE(0x0080, 0x00ff) AM_RAM        /* 6803 internal RAM */
794 //ADDRESS_MAP_END
795 
796 #endif
797 
798 /****************************************************************************
799  * M6808 almost (fully?) equal to the M6800
800  ****************************************************************************/
801 #if (HAS_M6808)
m6808_init(int index,int clock,const void * config,int (* irqcallback)(int))802 static void m6808_init(int index, int clock, const void *config, int (*irqcallback)(int))
803 {
804 //  m6800.subtype = SUBTYPE_M6808;
805 	m6800.insn = m6800_insn;
806 	m6800.cycles = cycles_6800;
807 	m6800.irq_callback = irqcallback;
808 	state_register("m6808", index);
809 }
810 #endif
811 
812 /****************************************************************************
813  * HD63701 similiar to the M6800
814  ****************************************************************************/
815 #if (HAS_HD63701)
hd63701_init()816 void hd63701_init()
817 {
818 //  m6800.subtype = SUBTYPE_HD63701;
819 	m6800.insn = hd63701_insn;
820 	m6800.cycles = cycles_63701;
821 //	m6800.irq_callback = irqcallback;
822 //	state_register("hd63701", index);
823 }
824 /****************************************************************************
825  * Execute cycles CPU cycles. Return number of cycles really executed
826  ****************************************************************************/
hd63701_execute(int cycles)827 int hd63701_execute(int cycles)
828 {
829 	UINT8 ireg;
830 
831 	m6800.segmentcycles = cycles;
832 	m6800_ICount = cycles;
833 
834 	CLEANUP_conters;
835 	INCREMENT_COUNTER(hd63701.extra_cycles);
836 	hd63701.extra_cycles = 0;
837 
838 	do
839 	{
840 		if( hd63701.wai_state & (HD63701_WAI|HD63701_SLP) )
841 		{
842 			EAT_CYCLES;
843 		}
844 		else
845 		{
846 			pPPC = pPC;
847 //			CALL_MAME_DEBUG;
848 			ireg=M_RDOP(PCD);
849 			PC++;
850 			(*hd63701.insn[ireg])();
851 			INCREMENT_COUNTER(cycles_63701[ireg]);
852 		}
853 	} while( m6800_ICount>0 );
854 
855 	INCREMENT_COUNTER(hd63701.extra_cycles);
856 	hd63701.extra_cycles = 0;
857 
858 	cycles = cycles - m6800_ICount;
859 
860 	m6800.segmentcycles = m6800_ICount = 0;
861 
862 	return cycles;
863 }
864 
865 /*
866     if change_pc() direccted these areas ,Call hd63701_trap_pc().
867     'mode' is selected by the sense of p2.0,p2.1,and p2.3 at reset timming.
868     mode 0,1,2,4,6 : $0000-$001f
869     mode 5         : $0000-$001f,$0200-$efff
870     mode 7         : $0000-$001f,$0100-$efff
871 */
hd63701_trap_pc(void)872 void hd63701_trap_pc(void)
873 {
874 	TAKE_TRAP;
875 }
876 
877 //static READ8_HANDLER( m6803_internal_registers_r );
878 //static WRITE8_HANDLER( m6803_internal_registers_w );
879 
880 //READ8_HANDLER( hd63701_internal_registers_r )
881 //{
882 //	return m6803_internal_registers_r(offset);
883 //}
884 
885 //WRITE8_HANDLER( hd63701_internal_registers_w )
886 //{
887 //	m6803_internal_registers_w(offset,data);
888 //}
889 #endif
890 
891 /****************************************************************************
892  * NSC-8105 similiar to the M6800, but the opcodes are scrambled and there
893  * is at least one new opcode ($fc)
894  ****************************************************************************/
895 #if (HAS_NSC8105)
nsc8105_init()896 void nsc8105_init()
897 {
898 //  m6800.subtype = SUBTYPE_NSC8105;
899 	m6800.insn = nsc8105_insn;
900 	m6800.cycles = cycles_nsc8105;
901 	//state_register("nsc8105", index);
902 }
903 /****************************************************************************
904  * Execute cycles CPU cycles. Return number of cycles really executed
905  ****************************************************************************/
nsc8105_execute(int cycles)906 int nsc8105_execute(int cycles)
907 {
908 	UINT8 ireg;
909 
910 	m6800.segmentcycles = cycles;
911 	m6800_ICount = cycles;
912 
913 	CLEANUP_conters;
914 	INCREMENT_COUNTER(nsc8105.extra_cycles);
915 	nsc8105.extra_cycles = 0;
916 
917 	do
918 	{
919 		if( nsc8105.wai_state & NSC8105_WAI )
920 		{
921 			EAT_CYCLES;
922 		}
923 		else
924 		{
925 			pPPC = pPC;
926 			//CALL_MAME_DEBUG;
927 			ireg=M_RDOP(PCD);
928 			PC++;
929 			(*nsc8105.insn[ireg])();
930 			INCREMENT_COUNTER(cycles_nsc8105[ireg]);
931 		}
932 	} while( m6800_ICount>0 );
933 
934 	INCREMENT_COUNTER(nsc8105.extra_cycles);
935 	nsc8105.extra_cycles = 0;
936 
937 	cycles = cycles - m6800_ICount;
938 
939 	m6800.segmentcycles = m6800_ICount = 0;
940 
941 	return cycles;
942 }
943 #endif
944 
945 
946 #if (HAS_M6803||HAS_HD63701)
947 
m6803_internal_registers_r(unsigned short offset)948 unsigned char m6803_internal_registers_r(unsigned short offset)
949 {
950 	switch (offset)
951 	{
952 		case 0x00:
953 			return m6800.port1_ddr;
954 		case 0x01:
955 			return m6800.port2_ddr;
956 		case 0x02:
957 			return (M6800_io_read_byte_8(M6803_PORT1) & (m6800.port1_ddr ^ 0xff))
958 					| (m6800.port1_data & m6800.port1_ddr);
959 		case 0x03:
960 			return (M6800_io_read_byte_8(M6803_PORT2) & (m6800.port2_ddr ^ 0xff))
961 					| (m6800.port2_data & m6800.port2_ddr);
962 		case 0x04:
963 			return m6800.port3_ddr;
964 		case 0x05:
965 			return m6800.port4_ddr;
966 		case 0x06:
967 			return (M6800_io_read_byte_8(M6803_PORT3) & (m6800.port3_ddr ^ 0xff))
968 					| (m6800.port3_data & m6800.port3_ddr);
969 		case 0x07:
970 			return (M6800_io_read_byte_8(M6803_PORT4) & (m6800.port4_ddr ^ 0xff))
971 					| (m6800.port4_data & m6800.port4_ddr);
972 		case 0x08:
973 			m6800.pending_tcsr = 0;
974 //logerror("CPU #%d PC %04x: warning - read TCSR register\n",cpu_getactivecpu(),activecpu_get_pc());
975 			return m6800.tcsr;
976 		case 0x09:
977 			if(!(m6800.pending_tcsr&TCSR_TOF))
978 			{
979 				m6800.tcsr &= ~TCSR_TOF;
980 				MODIFIED_tcsr;
981 			}
982 			return m6800.counter.b.h;
983 		case 0x0a:
984 			return m6800.counter.b.l;
985 		case 0x0b:
986 			if(!(m6800.pending_tcsr&TCSR_OCF))
987 			{
988 				m6800.tcsr &= ~TCSR_OCF;
989 				MODIFIED_tcsr;
990 			}
991 			return m6800.output_compare.b.h;
992 		case 0x0c:
993 			if(!(m6800.pending_tcsr&TCSR_OCF))
994 			{
995 				m6800.tcsr &= ~TCSR_OCF;
996 				MODIFIED_tcsr;
997 			}
998 			return m6800.output_compare.b.l;
999 		case 0x0d:
1000 			if(!(m6800.pending_tcsr&TCSR_ICF))
1001 			{
1002 				m6800.tcsr &= ~TCSR_ICF;
1003 				MODIFIED_tcsr;
1004 			}
1005 			return (m6800.input_capture >> 0) & 0xff;
1006 		case 0x0e:
1007 			return (m6800.input_capture >> 8) & 0xff;
1008 		case 0x0f:
1009 		case 0x10:
1010 		case 0x11:
1011 		case 0x12:
1012 		case 0x13:
1013 //			logerror("CPU #%d PC %04x: warning - read from unsupported internal register %02x\n",cpu_getactivecpu(),activecpu_get_pc(),offset);
1014 			return 0;
1015 		case 0x14:
1016 //			logerror("CPU #%d PC %04x: read RAM control register\n",cpu_getactivecpu(),activecpu_get_pc());
1017 			return m6800.ram_ctrl;
1018 		case 0x15:
1019 		case 0x16:
1020 		case 0x17:
1021 		case 0x18:
1022 		case 0x19:
1023 		case 0x1a:
1024 		case 0x1b:
1025 		case 0x1c:
1026 		case 0x1d:
1027 		case 0x1e:
1028 		case 0x1f:
1029 		default:
1030 //			logerror("CPU #%d PC %04x: warning - read from reserved internal register %02x\n",cpu_getactivecpu(),activecpu_get_pc(),offset);
1031 			return 0;
1032 	}
1033 }
1034 
m6803_internal_registers_w(unsigned short offset,unsigned char data)1035 void m6803_internal_registers_w(unsigned short offset, unsigned char data)
1036 {
1037 	switch (offset)
1038 	{
1039 		case 0x00:
1040 			if (m6800.port1_ddr != data)
1041 			{
1042 				m6800.port1_ddr = data;
1043 				if(m6800.port1_ddr == 0xff)
1044 					M6800_io_write_byte_8(M6803_PORT1,m6800.port1_data);
1045 				else
1046 					M6800_io_write_byte_8(M6803_PORT1,(m6800.port1_data & m6800.port1_ddr)
1047 						| (M6800_io_read_byte_8(M6803_PORT1) & (m6800.port1_ddr ^ 0xff)));
1048 			}
1049 			break;
1050 		case 0x01:
1051 			if (m6800.port2_ddr != data)
1052 			{
1053 				m6800.port2_ddr = data;
1054 				if(m6800.port2_ddr == 0xff)
1055 					M6800_io_write_byte_8(M6803_PORT2,m6800.port2_data);
1056 				else
1057 					M6800_io_write_byte_8(M6803_PORT2,(m6800.port2_data & m6800.port2_ddr)
1058 						| (M6800_io_read_byte_8(M6803_PORT2) & (m6800.port2_ddr ^ 0xff)));
1059 
1060 //				if (m6800.port2_ddr & 2)
1061 //					logerror("CPU #%d PC %04x: warning - port 2 bit 1 set as output (OLVL) - not supported\n",cpu_getactivecpu(),activecpu_get_pc());
1062 			}
1063 			break;
1064 		case 0x02:
1065 			m6800.port1_data = data;
1066 			if(m6800.port1_ddr == 0xff)
1067 				M6800_io_write_byte_8(M6803_PORT1,m6800.port1_data);
1068 			else
1069 				M6800_io_write_byte_8(M6803_PORT1,(m6800.port1_data & m6800.port1_ddr)
1070 					| (M6800_io_read_byte_8(M6803_PORT1) & (m6800.port1_ddr ^ 0xff)));
1071 			break;
1072 		case 0x03:
1073 			m6800.port2_data = data;
1074 			m6800.port2_ddr = data;
1075 			if(m6800.port2_ddr == 0xff)
1076 				M6800_io_write_byte_8(M6803_PORT2,m6800.port2_data);
1077 			else
1078 				M6800_io_write_byte_8(M6803_PORT2,(m6800.port2_data & m6800.port2_ddr)
1079 					| (M6800_io_read_byte_8(M6803_PORT2) & (m6800.port2_ddr ^ 0xff)));
1080 			break;
1081 		case 0x04:
1082 			if (m6800.port3_ddr != data)
1083 			{
1084 				m6800.port3_ddr = data;
1085 				if(m6800.port3_ddr == 0xff)
1086 					M6800_io_write_byte_8(M6803_PORT3,m6800.port3_data);
1087 				else
1088 					M6800_io_write_byte_8(M6803_PORT3,(m6800.port3_data & m6800.port3_ddr)
1089 						| (M6800_io_read_byte_8(M6803_PORT3) & (m6800.port3_ddr ^ 0xff)));
1090 			}
1091 			break;
1092 		case 0x05:
1093 			if (m6800.port4_ddr != data)
1094 			{
1095 				m6800.port4_ddr = data;
1096 				if(m6800.port4_ddr == 0xff)
1097 					M6800_io_write_byte_8(M6803_PORT4,m6800.port4_data);
1098 				else
1099 					M6800_io_write_byte_8(M6803_PORT4,(m6800.port4_data & m6800.port4_ddr)
1100 						| (M6800_io_read_byte_8(M6803_PORT4) & (m6800.port4_ddr ^ 0xff)));
1101 			}
1102 			break;
1103 		case 0x06:
1104 			m6800.port3_data = data;
1105 			if(m6800.port3_ddr == 0xff)
1106 				M6800_io_write_byte_8(M6803_PORT3,m6800.port3_data);
1107 			else
1108 				M6800_io_write_byte_8(M6803_PORT3,(m6800.port3_data & m6800.port3_ddr)
1109 					| (M6800_io_read_byte_8(M6803_PORT3) & (m6800.port3_ddr ^ 0xff)));
1110 			break;
1111 		case 0x07:
1112 			m6800.port4_data = data;
1113 			if(m6800.port4_ddr == 0xff)
1114 				M6800_io_write_byte_8(M6803_PORT4,m6800.port4_data);
1115 			else
1116 				M6800_io_write_byte_8(M6803_PORT4,(m6800.port4_data & m6800.port4_ddr)
1117 					| (M6800_io_read_byte_8(M6803_PORT4) & (m6800.port4_ddr ^ 0xff)));
1118 			break;
1119 		case 0x08:
1120 			m6800.tcsr = data;
1121 			m6800.pending_tcsr &= m6800.tcsr;
1122 			MODIFIED_tcsr;
1123 			if( !(CC & 0x10) )
1124 				CHECK_IRQ2;
1125 //logerror("CPU #%d PC %04x: TCSR = %02x\n",cpu_getactivecpu(),activecpu_get_pc(),data);
1126 			break;
1127 		case 0x09:
1128 			m6800.latch09 = data & 0xff;	/* 6301 only */
1129 			CT  = 0xfff8;
1130 			TOH = CTH;
1131 			MODIFIED_counters;
1132 			break;
1133 		case 0x0a:	/* 6301 only */
1134 			CT = (m6800.latch09 << 8) | (data & 0xff);
1135 			TOH = CTH;
1136 			MODIFIED_counters;
1137 			break;
1138 		case 0x0b:
1139 			if( m6800.output_compare.b.h != data)
1140 			{
1141 				m6800.output_compare.b.h = data;
1142 				MODIFIED_counters;
1143 			}
1144 			break;
1145 		case 0x0c:
1146 			if( m6800.output_compare.b.l != data)
1147 			{
1148 				m6800.output_compare.b.l = data;
1149 				MODIFIED_counters;
1150 			}
1151 			break;
1152 		case 0x0d:
1153 		case 0x0e:
1154 //			logerror("CPU #%d PC %04x: warning - write %02x to read only internal register %02x\n",cpu_getactivecpu(),activecpu_get_pc(),data,offset);
1155 			break;
1156 		case 0x0f:
1157 		case 0x10:
1158 		case 0x11:
1159 		case 0x12:
1160 		case 0x13:
1161 //			logerror("CPU #%d PC %04x: warning - write %02x to unsupported internal register %02x\n",cpu_getactivecpu(),activecpu_get_pc(),data,offset);
1162 			break;
1163 		case 0x14:
1164 //			logerror("CPU #%d PC %04x: write %02x to RAM control register\n",cpu_getactivecpu(),activecpu_get_pc(),data);
1165 			m6800.ram_ctrl = data;
1166 			break;
1167 		case 0x15:
1168 		case 0x16:
1169 		case 0x17:
1170 		case 0x18:
1171 		case 0x19:
1172 		case 0x1a:
1173 		case 0x1b:
1174 		case 0x1c:
1175 		case 0x1d:
1176 		case 0x1e:
1177 		case 0x1f:
1178 		default:
1179 //			logerror("CPU #%d PC %04x: warning - write %02x to reserved internal register %02x\n",cpu_getactivecpu(),activecpu_get_pc(),data,offset);
1180 			break;
1181 	}
1182 }
1183 #endif
1184 
1185 #if 0
1186 /**************************************************************************
1187  * Generic set_info
1188  **************************************************************************/
1189 
1190 static void m6800_set_info(UINT32 state, cpuinfo *info)
1191 {
1192 	switch (state)
1193 	{
1194 		/* --- the following bits of info are set as 64-bit signed integers --- */
1195 		case CPUINFO_INT_INPUT_STATE + M6800_IRQ_LINE:	set_irq_line(M6800_IRQ_LINE, info->i);	break;
1196 		case CPUINFO_INT_INPUT_STATE + M6800_TIN_LINE:	set_irq_line(M6800_TIN_LINE, info->i);	break;
1197 		case CPUINFO_INT_INPUT_STATE + M6800_INPUT_LINE_NMI:	set_irq_line(M6800_INPUT_LINE_NMI, info->i);	break;
1198 
1199 		case CPUINFO_INT_PC:							PC = info->i; CHANGE_PC();				break;
1200 		case CPUINFO_INT_REGISTER + M6800_PC:			m6800.pc.w.l = info->i;					break;
1201 		case CPUINFO_INT_SP:							S = info->i;							break;
1202 		case CPUINFO_INT_REGISTER + M6800_S:			m6800.s.w.l = info->i;					break;
1203 		case CPUINFO_INT_REGISTER + M6800_CC:			m6800.cc = info->i;						break;
1204 		case CPUINFO_INT_REGISTER + M6800_A:			m6800.d.b.h = info->i;					break;
1205 		case CPUINFO_INT_REGISTER + M6800_B:			m6800.d.b.l = info->i;					break;
1206 		case CPUINFO_INT_REGISTER + M6800_X:			m6800.x.w.l = info->i;					break;
1207 	}
1208 }
1209 
1210 
1211 
1212 /**************************************************************************
1213  * Generic get_info
1214  **************************************************************************/
1215 
1216 void m6800_get_info(UINT32 state, cpuinfo *info)
1217 {
1218 	switch (state)
1219 	{
1220 		/* --- the following bits of info are returned as 64-bit signed integers --- */
1221 		case CPUINFO_INT_CONTEXT_SIZE:					info->i = sizeof(m6800);				break;
1222 		case CPUINFO_INT_INPUT_LINES:					info->i = 2;							break;
1223 		case CPUINFO_INT_DEFAULT_IRQ_VECTOR:			info->i = 0;							break;
1224 		case CPUINFO_INT_ENDIANNESS:					info->i = CPU_IS_BE;					break;
1225 		case CPUINFO_INT_CLOCK_DIVIDER:					info->i = 1;							break;
1226 		case CPUINFO_INT_MIN_INSTRUCTION_BYTES:			info->i = 1;							break;
1227 		case CPUINFO_INT_MAX_INSTRUCTION_BYTES:			info->i = 4;							break;
1228 		case CPUINFO_INT_MIN_CYCLES:					info->i = 1;							break;
1229 		case CPUINFO_INT_MAX_CYCLES:					info->i = 12;							break;
1230 
1231 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM:	info->i = 8;					break;
1232 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16;					break;
1233 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0;					break;
1234 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA:	info->i = 0;					break;
1235 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
1236 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
1237 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO:		info->i = 0;					break;
1238 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: 		info->i = 0;					break;
1239 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: 		info->i = 0;					break;
1240 
1241 		case CPUINFO_INT_INPUT_STATE + M6800_IRQ_LINE:	info->i = m6800.irq_state[M6800_IRQ_LINE]; break;
1242 		case CPUINFO_INT_INPUT_STATE + M6800_TIN_LINE:	info->i = m6800.irq_state[M6800_TIN_LINE]; break;
1243 		case CPUINFO_INT_INPUT_STATE + M6800_INPUT_LINE_NMI:	info->i = m6800.nmi_state;				break;
1244 
1245 		case CPUINFO_INT_PREVIOUSPC:					info->i = m6800.ppc.w.l;				break;
1246 
1247 		case CPUINFO_INT_PC:							info->i = PC;							break;
1248 		case CPUINFO_INT_REGISTER + M6800_PC:			info->i = m6800.pc.w.l;					break;
1249 		case CPUINFO_INT_SP:							info->i = S;							break;
1250 		case CPUINFO_INT_REGISTER + M6800_S:			info->i = m6800.s.w.l;					break;
1251 		case CPUINFO_INT_REGISTER + M6800_CC:			info->i = m6800.cc;						break;
1252 		case CPUINFO_INT_REGISTER + M6800_A:			info->i = m6800.d.b.h;					break;
1253 		case CPUINFO_INT_REGISTER + M6800_B:			info->i = m6800.d.b.l;					break;
1254 		case CPUINFO_INT_REGISTER + M6800_X:			info->i = m6800.x.w.l;					break;
1255 		case CPUINFO_INT_REGISTER + M6800_WAI_STATE:	info->i = m6800.wai_state;				break;
1256 
1257 		/* --- the following bits of info are returned as pointers to data or functions --- */
1258 		case CPUINFO_PTR_SET_INFO:						info->setinfo = m6800_set_info;			break;
1259 		case CPUINFO_PTR_GET_CONTEXT:					info->getcontext = m6800_get_context;	break;
1260 		case CPUINFO_PTR_SET_CONTEXT:					info->setcontext = m6800_set_context;	break;
1261 		case CPUINFO_PTR_INIT:							info->init = m6800_init;				break;
1262 		case CPUINFO_PTR_RESET:							info->reset = m6800_reset;				break;
1263 		case CPUINFO_PTR_EXIT:							info->exit = m6800_exit;				break;
1264 		case CPUINFO_PTR_EXECUTE:						info->execute = m6800_execute;			break;
1265 		case CPUINFO_PTR_BURN:							info->burn = NULL;						break;
1266 #ifdef MAME_DEBUG
1267 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = m6800_dasm;			break;
1268 #endif /* MAME_DEBUG */
1269 		case CPUINFO_PTR_INSTRUCTION_COUNTER:			info->icount = &m6800_ICount;			break;
1270 
1271 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1272 		case CPUINFO_STR_NAME:							strcpy(info->s, "M6800");				break;
1273 		case CPUINFO_STR_CORE_FAMILY:					strcpy(info->s, "Motorola 6800");		break;
1274 		case CPUINFO_STR_CORE_VERSION:					strcpy(info->s, "1.1");					break;
1275 		case CPUINFO_STR_CORE_FILE:						strcpy(info->s, __FILE__);				break;
1276 		case CPUINFO_STR_CORE_CREDITS:					strcpy(info->s, "The MAME team.");		break;
1277 
1278 		case CPUINFO_STR_FLAGS:
1279 			sprintf(info->s, "%c%c%c%c%c%c%c%c",
1280 				m6800.cc & 0x80 ? '?':'.',
1281 				m6800.cc & 0x40 ? '?':'.',
1282 				m6800.cc & 0x20 ? 'H':'.',
1283 				m6800.cc & 0x10 ? 'I':'.',
1284 				m6800.cc & 0x08 ? 'N':'.',
1285 				m6800.cc & 0x04 ? 'Z':'.',
1286 				m6800.cc & 0x02 ? 'V':'.',
1287 				m6800.cc & 0x01 ? 'C':'.');
1288 			break;
1289 
1290 		case CPUINFO_STR_REGISTER + M6800_A:			sprintf(info->s, "A:%02X", m6800.d.b.h); break;
1291 		case CPUINFO_STR_REGISTER + M6800_B:			sprintf(info->s, "B:%02X", m6800.d.b.l); break;
1292 		case CPUINFO_STR_REGISTER + M6800_PC:			sprintf(info->s, "PC:%04X", m6800.pc.w.l); break;
1293 		case CPUINFO_STR_REGISTER + M6800_S:			sprintf(info->s, "S:%04X", m6800.s.w.l); break;
1294 		case CPUINFO_STR_REGISTER + M6800_X:			sprintf(info->s, "X:%04X", m6800.x.w.l); break;
1295 		case CPUINFO_STR_REGISTER + M6800_CC:			sprintf(info->s, "CC:%02X", m6800.cc); break;
1296 		case CPUINFO_STR_REGISTER + M6800_WAI_STATE:	sprintf(info->s, "WAI:%X", m6800.wai_state); break;
1297 	}
1298 }
1299 
1300 
1301 #if (HAS_M6801)
1302 /**************************************************************************
1303  * CPU-specific set_info
1304  **************************************************************************/
1305 
1306 void m6801_get_info(UINT32 state, cpuinfo *info)
1307 {
1308 	switch (state)
1309 	{
1310 		/* --- the following bits of info are returned as 64-bit signed integers --- */
1311 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO:		info->i = 8;					break;
1312 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: 		info->i = 9;					break;
1313 
1314 		/* --- the following bits of info are returned as pointers to data or functions --- */
1315 		case CPUINFO_PTR_INIT:							info->init = m6801_init;				break;
1316 		case CPUINFO_PTR_EXECUTE:						info->execute = m6803_execute;			break;
1317 #ifdef MAME_DEBUG
1318 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = m6801_dasm;			break;
1319 #endif /* MAME_DEBUG */
1320 
1321 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1322 		case CPUINFO_STR_NAME:							strcpy(info->s, "M6801");				break;
1323 
1324 		default:										m6800_get_info(state, info);			break;
1325 	}
1326 }
1327 #endif
1328 
1329 
1330 #if (HAS_M6802)
1331 /**************************************************************************
1332  * CPU-specific set_info
1333  **************************************************************************/
1334 
1335 void m6802_get_info(UINT32 state, cpuinfo *info)
1336 {
1337 	switch (state)
1338 	{
1339 		/* --- the following bits of info are returned as pointers to data or functions --- */
1340 		case CPUINFO_PTR_INIT:							info->init = m6802_init;				break;
1341 #ifdef MAME_DEBUG
1342 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = m6802_dasm;			break;
1343 #endif /* MAME_DEBUG */
1344 
1345 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1346 		case CPUINFO_STR_NAME:							strcpy(info->s, "M6802");				break;
1347 
1348 		default:										m6800_get_info(state, info);			break;
1349 	}
1350 }
1351 #endif
1352 
1353 
1354 #if (HAS_M6803)
1355 /**************************************************************************
1356  * CPU-specific set_info
1357  **************************************************************************/
1358 
1359 void m6803_get_info(UINT32 state, cpuinfo *info)
1360 {
1361 	switch (state)
1362 	{
1363 		/* --- the following bits of info are returned as 64-bit signed integers --- */
1364 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO:		info->i = 8;					break;
1365 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: 		info->i = 9;					break;
1366 
1367 		/* --- the following bits of info are returned as pointers to data or functions --- */
1368 		case CPUINFO_PTR_INIT:							info->init = m6803_init;				break;
1369 		case CPUINFO_PTR_EXECUTE:						info->execute = m6803_execute;			break;
1370 #ifdef MAME_DEBUG
1371 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = m6803_dasm;			break;
1372 #endif /* MAME_DEBUG */
1373 
1374 		case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_m6803_mem; break;
1375 
1376 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1377 		case CPUINFO_STR_NAME:							strcpy(info->s, "M6803");				break;
1378 
1379 		default:										m6800_get_info(state, info);			break;
1380 	}
1381 }
1382 #endif
1383 
1384 
1385 #if (HAS_M6808)
1386 /**************************************************************************
1387  * CPU-specific set_info
1388  **************************************************************************/
1389 
1390 void m6808_get_info(UINT32 state, cpuinfo *info)
1391 {
1392 	switch (state)
1393 	{
1394 		/* --- the following bits of info are returned as pointers to data or functions --- */
1395 		case CPUINFO_PTR_INIT:							info->init = m6808_init;				break;
1396 #ifdef MAME_DEBUG
1397 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = m6808_dasm;			break;
1398 #endif /* MAME_DEBUG */
1399 
1400 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1401 		case CPUINFO_STR_NAME:							strcpy(info->s, "M6808");				break;
1402 
1403 		default:										m6800_get_info(state, info);			break;
1404 	}
1405 }
1406 #endif
1407 
1408 
1409 #if (HAS_HD63701)
1410 /**************************************************************************
1411  * CPU-specific set_info
1412  **************************************************************************/
1413 
1414 void hd63701_get_info(UINT32 state, cpuinfo *info)
1415 {
1416 	switch (state)
1417 	{
1418 		/* --- the following bits of info are returned as 64-bit signed integers --- */
1419 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO:		info->i = 8;					break;
1420 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: 		info->i = 9;					break;
1421 
1422 		/* --- the following bits of info are returned as pointers to data or functions --- */
1423 		case CPUINFO_PTR_INIT:							info->init = hd63701_init;				break;
1424 		case CPUINFO_PTR_EXECUTE:						info->execute = hd63701_execute;		break;
1425 #ifdef MAME_DEBUG
1426 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = hd63701_dasm;		break;
1427 #endif /* MAME_DEBUG */
1428 
1429 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1430 		case CPUINFO_STR_NAME:							strcpy(info->s, "HD63701");				break;
1431 
1432 		default:										m6800_get_info(state, info);			break;
1433 	}
1434 }
1435 #endif
1436 
1437 
1438 #if (HAS_NSC8105)
1439 /**************************************************************************
1440  * CPU-specific set_info
1441  **************************************************************************/
1442 
1443 void nsc8105_get_info(UINT32 state, cpuinfo *info)
1444 {
1445 	switch (state)
1446 	{
1447 		/* --- the following bits of info are returned as pointers to data or functions --- */
1448 		case CPUINFO_PTR_INIT:							info->init = nsc8105_init;				break;
1449 		case CPUINFO_PTR_EXECUTE:						info->execute = nsc8105_execute;		break;
1450 #ifdef MAME_DEBUG
1451 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = nsc8105_dasm;		break;
1452 #endif /* MAME_DEBUG */
1453 
1454 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1455 		case CPUINFO_STR_NAME:							strcpy(info->s, "NSC8105");				break;
1456 
1457 		default:										m6800_get_info(state, info);			break;
1458 	}
1459 }
1460 #endif
1461 
1462 #endif
1463