1// license:BSD-3-Clause
2// copyright-holders:Nathan Woods
3NMI:
4	m_nmi_asserted = false;
5	m_cc |= CC_E;
6	set_regop16(m_s);
7	m_temp.w = entire_state_registers();
8	%PUSH_REGISTERS;
9	m_cc |= CC_I | CC_F;
10	set_ea(VECTOR_NMI);
11	eat(1);
12	standard_irq_callback(INPUT_LINE_NMI);
13	goto INTERRUPT_VECTOR;
14
15FIRQ:
16	if (firq_saves_entire_state())
17	{
18		m_cc |= CC_E;
19		m_temp.w = entire_state_registers();
20	}
21	else
22	{
23		m_cc &= ~CC_E;
24		m_temp.w = partial_state_registers();
25	}
26	set_regop16(m_s);
27	%PUSH_REGISTERS;
28	m_cc |= CC_I | CC_F;
29	set_ea(VECTOR_FIRQ);
30	eat(1);
31	standard_irq_callback(M6809_FIRQ_LINE);
32	goto INTERRUPT_VECTOR;
33
34IRQ:
35	m_cc |= CC_E;
36	set_regop16(m_s);
37	m_temp.w = entire_state_registers();
38	%PUSH_REGISTERS;
39	m_cc |= CC_I;
40	set_ea(VECTOR_IRQ);
41	eat(1);
42	standard_irq_callback(M6809_IRQ_LINE);
43	goto INTERRUPT_VECTOR;
44
45INTERRUPT_VECTOR:
46	@eat(4);
47	@m_pc.b.h = read_operand(0);	// Not sure if this is cycle exact
48	@m_pc.b.l = read_operand(1);	// Not sure if this is cycle exact
49	return;
50
51NEG8:
52	@m_temp.b.l = read_operand();
53	m_temp.b.l = set_flags(CC_NZVC, (uint8_t)0, m_temp.b.l, -m_temp.b.l);
54	@eat(hd6309_native_mode() ? 0 : 1);
55	@write_operand(m_temp.b.l);
56	return;
57
58COM8:
59	@m_temp.b.l = read_operand();
60	m_cc &= ~CC_V;
61	m_cc |= CC_C;
62	m_temp.b.l = set_flags(CC_NZ, (uint8_t) ~m_temp.b.l);
63	@eat(hd6309_native_mode() ? 0 : 1);
64	@write_operand(m_temp.b.l);
65	return;
66
67LSR8:
68	@m_temp.b.l = read_operand();
69	m_cc &= ~CC_C;
70	m_cc |= (m_temp.b.l & 1) ? CC_C : 0;
71	m_temp.b.l = set_flags<uint8_t>(CC_NZ, m_temp.b.l >> 1);
72	@eat(hd6309_native_mode() ? 0 : 1);
73	@write_operand(m_temp.b.l);
74	return;
75
76ROR8:
77	@m_temp.b.l = read_operand();
78	m_temp.b.l = set_flags<uint8_t>(CC_NZ, rotate_right(m_temp.b.l));
79	@eat(hd6309_native_mode() ? 0 : 1);
80	@write_operand(m_temp.b.l);
81	return;
82
83ASR8:
84	@m_temp.b.l = read_operand();
85	m_cc &= ~CC_C;
86	m_cc |= (m_temp.b.l & 1) ? CC_C : 0;
87	m_temp.b.l = set_flags<uint8_t>(CC_NZ, ((int8_t) m_temp.b.l) >> 1);
88	@eat(hd6309_native_mode() ? 0 : 1);
89	@write_operand(m_temp.b.l);
90	return;
91
92ASL8:
93	@m_temp.b.l = read_operand();
94	m_temp.b.l = set_flags<uint8_t>(CC_NZVC, m_temp.b.l, m_temp.b.l, m_temp.b.l << 1);
95	@eat(hd6309_native_mode() ? 0 : 1);
96	@write_operand(m_temp.b.l);
97	return;
98
99ROL8:
100	@m_temp.b.l = read_operand();
101	m_temp.b.l = set_flags<uint8_t>(CC_NZV, m_temp.b.l, m_temp.b.l, rotate_left(m_temp.b.l));
102	@eat(hd6309_native_mode() ? 0 : 1);
103	@write_operand(m_temp.b.l);
104	return;
105
106DEC8:
107	@m_temp.b.l = read_operand();
108	m_temp.b.l = set_flags<uint8_t>(CC_NZV, m_temp.b.l, 1, m_temp.b.l - 1);
109	@eat(hd6309_native_mode() && is_register_addressing_mode() ? 0 : 1);
110	@write_operand(m_temp.b.l);
111	return;
112
113INC8:
114	@m_temp.b.l = read_operand();
115	m_temp.b.l = set_flags<uint8_t>(CC_NZV, m_temp.b.l, 1, m_temp.b.l + 1);
116	@eat(hd6309_native_mode() && is_register_addressing_mode() ? 0 : 1);
117	@write_operand(m_temp.b.l);
118	return;
119
120TST8:
121	@m_temp.b.l = read_operand();
122	set_flags(CC_NZV, m_temp.b.l);
123	eat(hd6309_native_mode() ? 0 : 1);
124	eat(is_register_addressing_mode() ? 0 : 1);
125	return;
126
127JMP:
128	m_pc.w = m_ea.w;
129	return;
130
131CLR8:
132	@read_operand();
133	m_cc &= ~CC_NZVC;
134	m_cc |= CC_Z;
135	@eat(hd6309_native_mode() && is_register_addressing_mode() ? 0 : 1);
136	@write_operand(0);
137	return;
138
139NEG16:
140	m_temp.b.h = read_operand(0);
141	m_temp.b.l = read_operand(1);
142	m_temp.w = set_flags(CC_NZVC, (uint16_t)0, m_temp.w, -m_temp.w);
143	eat(hd6309_native_mode() ? 0 : 1);
144	write_operand(0, m_temp.b.h);
145	write_operand(1, m_temp.b.l);
146	return;
147
148LSR16:
149	@m_temp.b.h = read_operand(0);
150	@m_temp.b.l = read_operand(1);
151	m_cc &= ~CC_C;
152	m_cc |= (m_temp.w & 1) ? CC_C : 0;
153	m_temp.w = set_flags<uint16_t>(CC_NZ, m_temp.w >> 1);
154	@eat(hd6309_native_mode() ? 0 : 1);
155	@write_operand(0, m_temp.b.h);
156	write_operand(1, m_temp.b.l);
157	return;
158
159ROR16:
160	@m_temp.b.h = read_operand(0);
161	@m_temp.b.l = read_operand(1);
162	m_temp.w = set_flags<uint16_t>(CC_NZ, rotate_right(m_temp.w));
163	@eat(hd6309_native_mode() ? 0 : 1);
164	@write_operand(0, m_temp.b.h);
165	write_operand(1, m_temp.b.l);
166	return;
167
168ASR16:
169	@m_temp.b.h = read_operand(0);
170	@m_temp.b.l = read_operand(1);
171	m_cc &= ~CC_C;
172	m_cc |= (m_temp.w & 1) ? CC_C : 0;
173	m_temp.w = set_flags<uint16_t>(CC_NZ, ((int16_t) m_temp.w) >> 1);
174	@eat(hd6309_native_mode() ? 0 : 1);
175	@write_operand(0, m_temp.b.h);
176	write_operand(1, m_temp.b.l);
177	return;
178
179ASL16:
180	@m_temp.b.h = read_operand(0);
181	@m_temp.b.l = read_operand(1);
182	m_temp.w = set_flags<uint16_t>(CC_NZVC, m_temp.w, m_temp.w, m_temp.w << 1);
183	@eat(hd6309_native_mode() ? 0 : 1);
184	@write_operand(0, m_temp.b.h);
185	write_operand(1, m_temp.b.l);
186	return;
187
188ROL16:
189	@m_temp.b.h = read_operand(0);
190	@m_temp.b.l = read_operand(1);
191	m_temp.w = set_flags<uint16_t>(CC_NZV, rotate_left(m_temp.w));
192	@eat(hd6309_native_mode() ? 0 : 1);
193	@write_operand(0, m_temp.b.h);
194	write_operand(1, m_temp.b.l);
195	return;
196
197DEC16:
198	m_temp.b.h = read_operand(0);
199	m_temp.b.l = read_operand(1);
200	m_temp.w = set_flags<uint16_t>(CC_NZVC, m_temp.w, 1, m_temp.w - 1);
201	eat(hd6309_native_mode() ? 0 : 1);
202	write_operand(0, m_temp.b.h);
203	write_operand(1, m_temp.b.l);
204	return;
205
206INC16:
207	m_temp.b.h = read_operand(0);
208	m_temp.b.l = read_operand(1);
209	m_temp.w = set_flags<uint16_t>(CC_NZVC, m_temp.w, 1, m_temp.w + 1);
210	eat(hd6309_native_mode() ? 0 : 1);
211	write_operand(0, m_temp.b.h);
212	write_operand(1, m_temp.b.l);
213	return;
214
215TST16:
216	m_temp.b.h = read_operand(0);
217	m_temp.b.l = read_operand(1);
218	set_flags(CC_NZV, m_temp.w);
219	eat(hd6309_native_mode() ? 0 : 1);
220	eat(is_register_addressing_mode() ? 0 : 1);
221	return;
222
223CLR16:
224	eat(hd6309_native_mode() ? 0 : 1);
225	m_cc &= ~CC_NZVC;
226	m_cc |= CC_Z;
227	write_operand(0, 0x00);
228	write_operand(1, 0x00);
229	return;
230
231SUB8:
232	m_temp.b.l = read_operand();
233	regop8() = set_flags(CC_NZVC, regop8(), m_temp.b.l, regop8() - m_temp.b.l);
234	return;
235
236CMP8:
237	m_temp.b.l = read_operand();
238	set_flags(CC_NZVC, regop8(), m_temp.b.l, regop8() - m_temp.b.l);
239	return;
240
241SBC8:
242	m_temp.b.l = read_operand();
243	regop8() = set_flags(CC_NZVC, regop8(), m_temp.b.l, regop8() - m_temp.b.l - (m_cc & CC_C ? 1 : 0));
244	return;
245
246AND8:
247	m_cc &= ~CC_V;
248	regop8() = set_flags(CC_NZ, (uint8_t)0, regop8(), regop8() & read_operand());
249	return;
250
251BIT8:
252	m_cc &= ~CC_V;
253	set_flags(CC_NZ, (uint8_t)0, regop8(), regop8() & read_operand());
254	return;
255
256EOR8:
257	m_cc &= ~CC_V;
258	regop8() = set_flags(CC_NZ, (uint8_t)0, regop8(), regop8() ^ read_operand());
259	return;
260
261ADC8:
262	m_temp.b.l = read_operand();
263	regop8() = set_flags(add8_sets_h() ? CC_HNZVC : CC_NZVC, regop8(), m_temp.b.l, regop8() + m_temp.b.l + (m_cc & CC_C ? 1 : 0));
264	return;
265
266OR8:
267	m_cc &= ~CC_V;
268	regop8() = set_flags(CC_NZ, (uint8_t)0, regop8(), regop8() | read_operand());
269	return;
270
271ADD8:
272	m_temp.b.l = read_operand();
273	regop8() = set_flags(add8_sets_h() ? CC_HNZVC : CC_NZVC, regop8(), m_temp.b.l, regop8() + m_temp.b.l);
274	return;
275
276ADD16:
277	@m_temp.b.h = read_operand(0);
278	@m_temp.b.l = read_operand(1);
279	regop16().w = set_flags(CC_NZVC, regop16().w, m_temp.w, regop16().w + m_temp.w);
280	eat(hd6309_native_mode() ? 0 : 1);
281	return;
282
283SUB16:
284	@m_temp.b.h = read_operand(0);
285	@m_temp.b.l = read_operand(1);
286	regop16().w = set_flags(CC_NZVC, regop16().w, m_temp.w, regop16().w - m_temp.w);
287	eat(hd6309_native_mode() ? 0 : 1);
288	return;
289
290CMP16:
291	@m_temp.b.h = read_operand(0);
292	@m_temp.b.l = read_operand(1);
293	set_flags(CC_NZVC, regop16().w, m_temp.w, regop16().w - m_temp.w);
294	eat(hd6309_native_mode() ? 0 : 1);
295	return;
296
297LD8:
298	regop8() = read_operand();
299	set_flags(CC_NZV, regop8());
300	return;
301
302LD16:
303	@regop16().b.h = read_operand(0);
304	@regop16().b.l = read_operand(1);
305	set_flags(CC_NZV, regop16().w);
306	if (&regop16() == &m_s)
307		m_lds_encountered = true;
308	return;
309
310ST8:
311	write_ea(set_flags(CC_NZV, regop8()));
312	return;
313
314ST16:
315	@write_operand(0, regop16().b.h);
316	@write_operand(1, regop16().b.l);
317	set_flags(CC_NZV, regop16().w);
318	return;
319
320NOP:
321	eat(hd6309_native_mode() ? 0 : 1);
322	return;
323
324SYNC:
325	// SYNC stops processing instructions until an interrupt request happens.
326	// This doesn't require the corresponding interrupt to be enabled: if it
327	// is disabled, execution continues with the next instruction.
328	eat(3);
329
330	while(!m_nmi_asserted && !m_firq_line && !m_irq_line)
331	{
332		// massaging the PC this way makes the debugger's behavior more
333		// intuitive
334		m_pc.w--;
335
336		@eat_remaining();
337
338		// unmassage...
339		m_pc.w++;
340	}
341	return;
342
343DAA:
344	daa();
345	eat(hd6309_native_mode() ? 0 : 1);
346	return;
347
348ORCC:
349	m_cc |= read_operand();
350	eat(hd6309_native_mode() ? 0 : 1);
351	return;
352
353ANDCC:
354	m_cc &= read_operand();
355	eat(1);
356	return;
357
358SEX:
359	m_q.r.d = set_flags<uint16_t>(CC_NZ, (int8_t) m_q.r.b);
360	eat(hd6309_native_mode() ? 0 : 1);
361	return;
362
363BRANCH:
364	@m_temp.b.l = read_opcode_arg();
365	eat(1);
366	if (branch_taken())
367	{
368		m_pc.w += (int8_t) m_temp.b.l;
369	}
370	return;
371
372LBRANCH:
373	@m_temp.b.h = read_opcode_arg();
374	@m_temp.b.l = read_opcode_arg();
375	eat(1);
376	if (branch_taken())
377	{
378		m_pc.w += m_temp.w;
379		eat(hd6309_native_mode() ? 0 : 1);
380	}
381	return;
382
383BSR:
384	@m_temp.b.l = read_opcode_arg();
385	m_ea.w = m_pc.w + (int8_t) m_temp.b.l;
386	@eat(hd6309_native_mode() ? 2 : 3);
387	goto GOTO_SUBROUTINE;
388
389LBSR:
390	@m_temp.b.h = read_opcode_arg();
391	@m_temp.b.l = read_opcode_arg();
392	m_ea.w = m_pc.w + (int16_t) m_temp.w;
393	@eat(hd6309_native_mode() ? 2 : 4);
394	goto GOTO_SUBROUTINE;
395
396JSR:
397	@eat(2);
398	goto GOTO_SUBROUTINE;
399
400GOTO_SUBROUTINE:
401	@write_memory(--m_s.w, m_pc.b.l);
402	@write_memory(--m_s.w, m_pc.b.h);
403	m_pc.w = m_ea.w;
404	return;
405
406RTS:
407	m_temp.w = 0x80;	// RTS is equivalent to "PULS PC"
408	eat(hd6309_native_mode() ? 0 : 1);
409	set_regop16(m_s);
410	goto PULL_REGISTERS;
411
412ABX:
413	m_x.w += m_q.r.b;
414	eat(hd6309_native_mode() ? 0 : 2);
415	return;
416
417MUL:
418	mul();
419	eat(hd6309_native_mode() ? 9 : 10);
420	return;
421
422RTI:
423	set_regop16(m_s);
424	m_temp.w = 0x01;	// PULS CC
425	%PULL_REGISTERS;
426	m_temp.w = ((m_cc & CC_E) ? entire_state_registers() : partial_state_registers()) & ~0x01;
427	goto PULL_REGISTERS;
428
429CWAI:
430	@m_cc &= read_opcode_arg();
431	@eat(2);
432
433	m_cc |= CC_E;
434	set_regop16(m_s);
435	m_temp.w = entire_state_registers();
436	%PUSH_REGISTERS;
437
438	while((m_ea.w = get_pending_interrupt()) == 0)
439	{
440		// massaging the PC this way makes the debugger's behavior more
441		// intuitive
442		m_pc.w -= 2;
443
444		@eat_remaining();
445
446		// unmassage...
447		m_pc.w += 2;
448	}
449
450	if (m_nmi_asserted)
451		m_nmi_asserted = false;
452
453	set_ea(m_ea.w);	// need to do this to set the addressing mode
454	m_cc |= CC_I | (m_ea.w != VECTOR_IRQ ? CC_F : 0);
455
456	// invoke standard interrupt callback for MAME core
457	switch (m_ea.w)
458	{
459		case VECTOR_NMI:	standard_irq_callback(INPUT_LINE_NMI); break;
460		case VECTOR_FIRQ:	standard_irq_callback(M6809_FIRQ_LINE); break;
461		case VECTOR_IRQ:	standard_irq_callback(M6809_IRQ_LINE); break;
462		default:			break;
463	}
464
465	goto INTERRUPT_VECTOR;
466
467LEA_xy:
468	regop16().w = set_flags(CC_Z, m_ea.w);
469	eat(1);
470	return;
471
472LEA_us:
473	if (&regop16() == &m_s)
474		m_lds_encountered = true;
475	regop16().w = m_ea.w;
476	eat(1);
477	return;
478
479PSHS:
480	@m_temp.w = read_opcode_arg();
481	@eat(hd6309_native_mode() ? 2 : 3);
482	set_regop16(m_s);
483	goto PUSH_REGISTERS;
484
485PULS:
486	@m_temp.w = read_opcode_arg();
487	@eat(hd6309_native_mode() ? 1 : 2);
488	set_regop16(m_s);
489	goto PULL_REGISTERS;
490
491PSHU:
492	@m_temp.w = read_opcode_arg();
493	@eat(hd6309_native_mode() ? 2 : 3);
494	set_regop16(m_u);
495	goto PUSH_REGISTERS;
496
497PULU:
498	@m_temp.w = read_opcode_arg();
499	@eat(hd6309_native_mode() ? 1 : 2);
500	set_regop16(m_u);
501	goto PULL_REGISTERS;
502
503SWI:
504	// doesn't use SOFTWARE_INTERRUPT label because SWI will
505	// inhibit IRQ/FIRQ
506	set_ea(VECTOR_SWI);
507	standard_irq_callback(M6809_SWI);
508	m_cc |= CC_E;
509	set_regop16(m_s);
510	m_temp.w = entire_state_registers();
511	%PUSH_REGISTERS;
512	m_cc |= CC_I | CC_F;
513	goto INTERRUPT_VECTOR;
514
515SWI2:
516	set_ea(VECTOR_SWI2);
517	standard_irq_callback(M6809_SWI);
518	goto SOFTWARE_INTERRUPT;
519
520SWI3:
521	set_ea(VECTOR_SWI3);
522	standard_irq_callback(M6809_SWI);
523	goto SOFTWARE_INTERRUPT;
524
525SOFTWARE_INTERRUPT:
526	// used for SWI2/SWI3 and illegal/div0 on 6309
527	m_cc |= CC_E;
528	set_regop16(m_s);
529	m_temp.w = entire_state_registers();
530	%PUSH_REGISTERS;
531	goto INTERRUPT_VECTOR;
532
533DIRECT:
534	@set_ea(((uint16_t)m_dp << 8) | read_opcode_arg());
535	@eat(hd6309_native_mode() ? 0 : 1);
536	return;
537
538EXTENDED:
539	@set_ea_h(read_opcode_arg());
540	@set_ea_l(read_opcode_arg());
541	@eat(hd6309_native_mode() ? 0 : 1);
542	return;
543