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