1 // license:BSD-3-Clause
2 // copyright-holders:Bryan McPhail
3 /*****************************************************************************
4 
5     h6280.c - Portable HuC6280 emulator
6 
7     Copyright Bryan McPhail, mish@tendril.co.uk
8 
9     This source code is based (with permission!) on the 6502 emulator by
10     Juergen Buchmueller.  It is released as part of the MAME emulator project.
11     Let me know if you intend to use this code in any other project.
12 
13 
14     NOTICE:
15 
16     This code is around 99% complete!  Several things are unimplemented,
17     some due to lack of time, some due to lack of documentation, mainly
18     due to lack of programs using these features.
19 
20     csh, csl opcodes are not supported.
21 
22     I am unsure if flag B is set upon execution of rti.
23 
24     Cycle counts should be quite accurate.
25 
26 
27     Changelog, version 1.02:
28         JMP + indirect X (0x7c) opcode fixed.
29         SMB + RMB opcodes fixed in disassembler.
30         change_pc function calls removed.
31         TSB & TRB now set flags properly.
32         BIT opcode altered.
33 
34     Changelog, version 1.03:
35         Swapped IRQ mask for IRQ1 & IRQ2 (thanks Yasuhiro)
36 
37     Changelog, version 1.04, 28/9/99-22/10/99:
38         Adjusted RTI (thanks Karl)
39         TST opcodes fixed in disassembler (missing break statements in a case!).
40         TST behaviour fixed.
41         SMB/RMB/BBS/BBR fixed in disassembler.
42 
43     Changelog, version 1.05, 8/12/99-16/12/99:
44         Added CAB's timer implementation (note: irq ack & timer reload are changed).
45         Fixed STA IDX.
46         Fixed B flag setting on BRK.
47         Assumed CSH & CSL to take 2 cycles each.
48 
49         Todo:  Performance could be improved by precalculating timer fire position.
50 
51     Changelog, version 1.06, 4/5/00 - last opcode bug found?
52         JMP indirect was doing a EAL++; instead of EAD++; - Obviously causing
53         a corrupt read when L = 0xff!  This fixes Bloody Wolf and Trio The Punch!
54 
55     Changelog, version 1.07, 3/9/00:
56         Changed timer to be single shot - fixes Crude Buster music in level 1.
57 
58     Changelog, version 1.08, 8/11/05: (Charles MacDonald)
59 
60         Changed timer implementation, no longer single shot and reading the
61         timer registers returns the count only. Fixes the following:
62         - Mesopotamia: Music tempo & in-game timer
63         - Dragon Saber: DDA effects
64         - Magical Chase: Music tempo and speed regulation
65         - Cadash: Allows the first level to start
66         - Turrican: Allows the game to start
67 
68         Changed PLX and PLY to set NZ flags. Fixes:
69         - Afterburner: Graphics unpacking
70         - Aoi Blink: Collision detection with background
71 
72         Fixed the decimal version of ADC/SBC to *not* update the V flag,
73         only the binary ones do.
74 
75         Fixed B flag handling so it is always set outside of an interrupt;
76         even after being set by PLP and RTI.
77 
78         Fixed P state after reset to set I and B, leaving T, D cleared and
79         NVZC randomized (cleared in this case).
80 
81         Fixed interrupt processing order (Timer has highest priority followed
82         by IRQ1 and finally IRQ2).
83 
84     Changelog, version 1.09, 1/07/06: (Rob Bohms)
85 
86         Added emulation of the T flag, fixes PCE Ankuku Densetsu title screen
87 
88     Changelog, version 1.10, 5/09/07: (Wilbert Pol)
89 
90         - Taking of interrupts is delayed to respect a pending instruction already
91           in the instruction pipeline; fixes After Burner.
92         - Added 1 cycle for decimal mode ADC and SBC instructions.
93         - Changed cycle counts for CSH and CSL instructions to 3.
94         - Added T flag support to the SBC instruction.
95         - Fixed ADC T flag to set the Z flag based on the value read.
96         - Added 3 cycle penalty to ADC, AND, EOR, ORA, and SBC instructions
97           when the T flag is set.
98         - Fixed cycle count and support for 65536 byte blocks for the TAI, TDD,
99           TIA, TII, and TIN instructions.
100         - Fixed RDWORD macro in the disassembler.
101         - Fixed setting of N and V flags in the TST instructions.
102         - Removed unneeded debug_mmr code.
103         - Fixed TSB and TRB instructions.
104         - Added 1 delay when accessing the VDC or VCE areas.
105         - Implemented low and high speed cpu modes.
106 
107     Changelog, version 1.11, 18/09/07: (Wilbert Pol)
108 
109         - Improvements to the handling of taking of delayed interrupts.
110 
111 ******************************************************************************/
112 
113 #include "emu.h"
114 #include "h6280.h"
115 #include "6280dasm.h"
116 #include "debugger.h"
117 
118 /* 6280 flags */
119 enum
120 {
121 	_fC = 0x01,
122 	_fZ = 0x02,
123 	_fI = 0x04,
124 	_fD = 0x08,
125 	_fB = 0x10,
126 	_fT = 0x20,
127 	_fV = 0x40,
128 	_fN = 0x80
129 };
130 
131 /* some shortcuts for improved readability */
132 #define A   m_a
133 #define X   m_x
134 #define Y   m_y
135 #define P   m_p
136 #define S   m_sp.b.l
137 
138 #define EAL m_ea.b.l
139 #define EAH m_ea.b.h
140 #define EAW m_ea.w.l
141 #define EAD m_ea.d
142 
143 #define ZPL m_zp.b.l
144 #define ZPH m_zp.b.h
145 #define ZPW m_zp.w.l
146 #define ZPD m_zp.d
147 
148 #define PCL m_pc.b.l
149 #define PCH m_pc.b.h
150 #define PCW m_pc.w.l
151 #define PCD m_pc.d
152 
internal_map(address_map & map)153 void h6280_device::internal_map(address_map &map)
154 {
155 	map(0x1fe800, 0x1fe80f).mirror(0x3f0).rw(FUNC(h6280_device::io_buffer_r), FUNC(h6280_device::psg_w));
156 	map(0x1fec00, 0x1fec01).mirror(0x3fe).rw(FUNC(h6280_device::timer_r), FUNC(h6280_device::timer_w));
157 	map(0x1ff000, 0x1ff000).mirror(0x3ff).rw(FUNC(h6280_device::port_r), FUNC(h6280_device::port_w));
158 	map(0x1ff400, 0x1ff403).mirror(0x3fc).rw(FUNC(h6280_device::irq_status_r), FUNC(h6280_device::irq_status_w));
159 }
160 
161 //**************************************************************************
162 //  DEVICE INTERFACE
163 //**************************************************************************
164 
165 DEFINE_DEVICE_TYPE(H6280, h6280_device, "h6280", "Hudson Soft HuC6280")
166 
167 //-------------------------------------------------
168 //  h6280_device - constructor
169 //-------------------------------------------------
170 
h6280_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)171 h6280_device::h6280_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
172 	: cpu_device(mconfig, H6280, tag, owner, clock)
173 	, device_mixer_interface(mconfig, *this, 2)
174 	, m_program_config("program", ENDIANNESS_LITTLE, 8, 21, 0, 16, 0, address_map_constructor(FUNC(h6280_device::internal_map), this))
175 	, m_io_config("io", ENDIANNESS_LITTLE, 8, 2)
176 	, m_port_in_cb(*this)
177 	, m_port_out_cb(*this)
178 	, m_psg(*this, "psg")
179 	, m_timer_scale(1)
180 {
181 	// build the opcode table
182 	for (int op = 0; op < 256; op++)
183 		m_opcode[op] = s_opcodetable[op];
184 }
185 
memory_space_config() const186 device_memory_interface::space_config_vector h6280_device::memory_space_config() const
187 {
188 	return space_config_vector {
189 		std::make_pair(AS_PROGRAM, &m_program_config),
190 		std::make_pair(AS_IO,      &m_io_config)
191 	};
192 }
193 
194 const h6280_device::ophandler h6280_device::s_opcodetable[256] =
195 {
196 	&h6280_device::op_00, &h6280_device::op_01, &h6280_device::op_02, &h6280_device::op_03, &h6280_device::op_04, &h6280_device::op_05, &h6280_device::op_06, &h6280_device::op_07,
197 	&h6280_device::op_08, &h6280_device::op_09, &h6280_device::op_0a, &h6280_device::op_0b, &h6280_device::op_0c, &h6280_device::op_0d, &h6280_device::op_0e, &h6280_device::op_0f,
198 	&h6280_device::op_10, &h6280_device::op_11, &h6280_device::op_12, &h6280_device::op_13, &h6280_device::op_14, &h6280_device::op_15, &h6280_device::op_16, &h6280_device::op_17,
199 	&h6280_device::op_18, &h6280_device::op_19, &h6280_device::op_1a, &h6280_device::op_1b, &h6280_device::op_1c, &h6280_device::op_1d, &h6280_device::op_1e, &h6280_device::op_1f,
200 	&h6280_device::op_20, &h6280_device::op_21, &h6280_device::op_22, &h6280_device::op_23, &h6280_device::op_24, &h6280_device::op_25, &h6280_device::op_26, &h6280_device::op_27,
201 	&h6280_device::op_28, &h6280_device::op_29, &h6280_device::op_2a, &h6280_device::op_2b, &h6280_device::op_2c, &h6280_device::op_2d, &h6280_device::op_2e, &h6280_device::op_2f,
202 	&h6280_device::op_30, &h6280_device::op_31, &h6280_device::op_32, &h6280_device::op_33, &h6280_device::op_34, &h6280_device::op_35, &h6280_device::op_36, &h6280_device::op_37,
203 	&h6280_device::op_38, &h6280_device::op_39, &h6280_device::op_3a, &h6280_device::op_3b, &h6280_device::op_3c, &h6280_device::op_3d, &h6280_device::op_3e, &h6280_device::op_3f,
204 	&h6280_device::op_40, &h6280_device::op_41, &h6280_device::op_42, &h6280_device::op_43, &h6280_device::op_44, &h6280_device::op_45, &h6280_device::op_46, &h6280_device::op_47,
205 	&h6280_device::op_48, &h6280_device::op_49, &h6280_device::op_4a, &h6280_device::op_4b, &h6280_device::op_4c, &h6280_device::op_4d, &h6280_device::op_4e, &h6280_device::op_4f,
206 	&h6280_device::op_50, &h6280_device::op_51, &h6280_device::op_52, &h6280_device::op_53, &h6280_device::op_54, &h6280_device::op_55, &h6280_device::op_56, &h6280_device::op_57,
207 	&h6280_device::op_58, &h6280_device::op_59, &h6280_device::op_5a, &h6280_device::op_5b, &h6280_device::op_5c, &h6280_device::op_5d, &h6280_device::op_5e, &h6280_device::op_5f,
208 	&h6280_device::op_60, &h6280_device::op_61, &h6280_device::op_62, &h6280_device::op_63, &h6280_device::op_64, &h6280_device::op_65, &h6280_device::op_66, &h6280_device::op_67,
209 	&h6280_device::op_68, &h6280_device::op_69, &h6280_device::op_6a, &h6280_device::op_6b, &h6280_device::op_6c, &h6280_device::op_6d, &h6280_device::op_6e, &h6280_device::op_6f,
210 	&h6280_device::op_70, &h6280_device::op_71, &h6280_device::op_72, &h6280_device::op_73, &h6280_device::op_74, &h6280_device::op_75, &h6280_device::op_76, &h6280_device::op_77,
211 	&h6280_device::op_78, &h6280_device::op_79, &h6280_device::op_7a, &h6280_device::op_7b, &h6280_device::op_7c, &h6280_device::op_7d, &h6280_device::op_7e, &h6280_device::op_7f,
212 	&h6280_device::op_80, &h6280_device::op_81, &h6280_device::op_82, &h6280_device::op_83, &h6280_device::op_84, &h6280_device::op_85, &h6280_device::op_86, &h6280_device::op_87,
213 	&h6280_device::op_88, &h6280_device::op_89, &h6280_device::op_8a, &h6280_device::op_8b, &h6280_device::op_8c, &h6280_device::op_8d, &h6280_device::op_8e, &h6280_device::op_8f,
214 	&h6280_device::op_90, &h6280_device::op_91, &h6280_device::op_92, &h6280_device::op_93, &h6280_device::op_94, &h6280_device::op_95, &h6280_device::op_96, &h6280_device::op_97,
215 	&h6280_device::op_98, &h6280_device::op_99, &h6280_device::op_9a, &h6280_device::op_9b, &h6280_device::op_9c, &h6280_device::op_9d, &h6280_device::op_9e, &h6280_device::op_9f,
216 	&h6280_device::op_a0, &h6280_device::op_a1, &h6280_device::op_a2, &h6280_device::op_a3, &h6280_device::op_a4, &h6280_device::op_a5, &h6280_device::op_a6, &h6280_device::op_a7,
217 	&h6280_device::op_a8, &h6280_device::op_a9, &h6280_device::op_aa, &h6280_device::op_ab, &h6280_device::op_ac, &h6280_device::op_ad, &h6280_device::op_ae, &h6280_device::op_af,
218 	&h6280_device::op_b0, &h6280_device::op_b1, &h6280_device::op_b2, &h6280_device::op_b3, &h6280_device::op_b4, &h6280_device::op_b5, &h6280_device::op_b6, &h6280_device::op_b7,
219 	&h6280_device::op_b8, &h6280_device::op_b9, &h6280_device::op_ba, &h6280_device::op_bb, &h6280_device::op_bc, &h6280_device::op_bd, &h6280_device::op_be, &h6280_device::op_bf,
220 	&h6280_device::op_c0, &h6280_device::op_c1, &h6280_device::op_c2, &h6280_device::op_c3, &h6280_device::op_c4, &h6280_device::op_c5, &h6280_device::op_c6, &h6280_device::op_c7,
221 	&h6280_device::op_c8, &h6280_device::op_c9, &h6280_device::op_ca, &h6280_device::op_cb, &h6280_device::op_cc, &h6280_device::op_cd, &h6280_device::op_ce, &h6280_device::op_cf,
222 	&h6280_device::op_d0, &h6280_device::op_d1, &h6280_device::op_d2, &h6280_device::op_d3, &h6280_device::op_d4, &h6280_device::op_d5, &h6280_device::op_d6, &h6280_device::op_d7,
223 	&h6280_device::op_d8, &h6280_device::op_d9, &h6280_device::op_da, &h6280_device::op_db, &h6280_device::op_dc, &h6280_device::op_dd, &h6280_device::op_de, &h6280_device::op_df,
224 	&h6280_device::op_e0, &h6280_device::op_e1, &h6280_device::op_e2, &h6280_device::op_e3, &h6280_device::op_e4, &h6280_device::op_e5, &h6280_device::op_e6, &h6280_device::op_e7,
225 	&h6280_device::op_e8, &h6280_device::op_e9, &h6280_device::op_ea, &h6280_device::op_eb, &h6280_device::op_ec, &h6280_device::op_ed, &h6280_device::op_ee, &h6280_device::op_ef,
226 	&h6280_device::op_f0, &h6280_device::op_f1, &h6280_device::op_f2, &h6280_device::op_f3, &h6280_device::op_f4, &h6280_device::op_f5, &h6280_device::op_f6, &h6280_device::op_f7,
227 	&h6280_device::op_f8, &h6280_device::op_f9, &h6280_device::op_fa, &h6280_device::op_fb, &h6280_device::op_fc, &h6280_device::op_fd, &h6280_device::op_fe, &h6280_device::op_ff
228 };
229 
230 //-------------------------------------------------
231 //  device_add_mconfig - add machine configuration
232 //-------------------------------------------------
device_add_mconfig(machine_config & config)233 void h6280_device::device_add_mconfig(machine_config &config)
234 {
235 	C6280(config, m_psg, DERIVED_CLOCK(1,2));
236 	m_psg->add_route(0, *this, 1.0, AUTO_ALLOC_INPUT, 0);
237 	m_psg->add_route(1, *this, 1.0, AUTO_ALLOC_INPUT, 1);
238 }
239 
device_start()240 void h6280_device::device_start()
241 {
242 	m_port_in_cb.resolve();
243 	m_port_out_cb.resolve_safe();
244 
245 	// register our state for the debugger
246 	state_add(STATE_GENPC,      "GENPC",        m_pc.w.l).noshow();
247 	state_add(STATE_GENPCBASE,  "CURPC",        m_pc.w.l).noshow();
248 	state_add(STATE_GENFLAGS,   "GENFLAGS",     m_p).callimport().callexport().formatstr("%8s").noshow();
249 	state_add(H6280_PC,         "PC",           m_pc.d).mask(0xffff);
250 	state_add(H6280_S,          "S",            m_sp.b.l).mask(0xff);
251 	state_add(H6280_P,          "P",            m_p).mask(0xff);
252 	state_add(H6280_A,          "A",            m_a).mask(0xff);
253 	state_add(H6280_X,          "X",            m_x).mask(0xff);
254 	state_add(H6280_Y,          "Y",            m_y).mask(0xff);
255 	state_add(H6280_IRQ_MASK,   "IM",           m_irq_mask).mask(0xff);
256 	state_add(H6280_TIMER_STATE,"TMR",          m_timer_status).mask(0xff);
257 	state_add(H6280_NMI_STATE,  "NMI",          m_nmi_state).mask(0xf);
258 	state_add(H6280_IRQ1_STATE, "IRQ1",        m_irq_state[0]).mask(0xf);
259 	state_add(H6280_IRQ2_STATE, "IRQ2",        m_irq_state[1]).mask(0xf);
260 	state_add(H6280_IRQT_STATE, "IRQT",        m_irq_state[2]).mask(0xf);
261 	for (int i = 0; i < 8; i++)
262 		state_add(H6280_MPR0 + i, util::string_format("MPR%d", i).c_str(), m_mmr[i]).mask(0xff);
263 
264 	save_item(NAME(m_ppc.w.l));
265 	save_item(NAME(m_pc.w.l));
266 	save_item(NAME(m_sp.w.l));
267 	save_item(NAME(m_zp.w.l));
268 	save_item(NAME(m_ea.w.l));
269 	save_item(NAME(m_a));
270 	save_item(NAME(m_x));
271 	save_item(NAME(m_y));
272 	save_item(NAME(m_p));
273 	save_item(NAME(m_mmr));
274 	save_item(NAME(m_irq_mask));
275 	save_item(NAME(m_timer_status));
276 	save_item(NAME(m_timer_ack));
277 	save_item(NAME(m_clocks_per_cycle));
278 	save_item(NAME(m_timer_value));
279 	save_item(NAME(m_timer_load));
280 	save_item(NAME(m_nmi_state));
281 	save_item(NAME(m_irq_state[0]));
282 	save_item(NAME(m_irq_state[1]));
283 	save_item(NAME(m_irq_state[2]));
284 	save_item(NAME(m_irq_pending));
285 
286 #if H6280_LAZY_FLAGS
287 	save_item(NAME(m_nz));
288 #endif
289 	save_item(NAME(m_io_buffer));
290 
291 	// set our instruction counter
292 	set_icountptr(m_icount);
293 	m_icount = 0;
294 
295 	/* clear pending interrupts */
296 	for (auto & elem : m_irq_state)
297 	{
298 		elem = CLEAR_LINE;
299 	}
300 	m_nmi_state = CLEAR_LINE;
301 }
302 
device_reset()303 void h6280_device::device_reset()
304 {
305 	/* wipe out the h6280 structure */
306 	m_ppc.d = 0;
307 	m_pc.d = 0;
308 	m_zp.d = 0;
309 	m_ea.d = 0;
310 	m_a = 0;
311 	m_x = 0;
312 	m_y = 0;
313 	m_p = 0;
314 	memset(m_mmr, 0, sizeof(uint8_t) * 8);
315 	m_irq_mask = 0;
316 	m_timer_ack = 0;
317 	m_timer_value = 0;
318 #if H6280_LAZY_FLAGS
319 	m_nz = 0;
320 #endif
321 	m_io_buffer = 0;
322 
323 	space(AS_PROGRAM).cache(m_cache);
324 	space(AS_PROGRAM).specific(m_program);
325 	space(AS_IO).specific(m_io);
326 
327 	/* set I and B flags */
328 	P = _fI | _fB;
329 
330 	/* stack starts at 0x01ff */
331 	m_sp.d = 0x1ff;
332 
333 	/* read the reset vector into PC */
334 	PCL = program_read8(H6280_RESET_VEC);
335 	PCH = program_read8(H6280_RESET_VEC + 1);
336 
337 	/* CPU starts in low speed mode */
338 	m_clocks_per_cycle = 4;
339 
340 	/* timer off by default */
341 	m_timer_status = 0;
342 	m_timer_load = 128 * 1024 * m_timer_scale;
343 
344 	m_irq_pending = 0;
345 }
346 
device_stop()347 void h6280_device::device_stop()
348 {
349 	/* nothing */
350 }
351 
352 
translated(uint16_t addr)353 inline uint32_t h6280_device::translated(uint16_t addr)
354 {
355 	return ((m_mmr[((addr) >> 13) & 7] << 13) | ((addr) & 0x1fff));
356 }
357 
h6280_cycles(int cyc)358 inline void h6280_device::h6280_cycles(int cyc)
359 {
360 	m_icount -= ((cyc) * m_clocks_per_cycle);
361 	m_timer_value -= ((cyc) * m_clocks_per_cycle);
362 }
363 
364 #if H6280_LAZY_FLAGS
365 
366 #define NZ  m_NZ
set_nz(uint8_t n)367 inline void h6280_device::set_nz(uint8_t n)
368 {
369 	P &= ~_fT;
370 	NZ = ((n & _fN) << 8) | n;
371 }
372 
373 #else
374 
set_nz(uint8_t n)375 inline void h6280_device::set_nz(uint8_t n)
376 {
377 	P = (P & ~(_fN|_fT|_fZ)) |
378 		(n & _fN) |
379 		((n == 0) ? _fZ : 0);
380 }
381 
382 #endif
383 
clear_t()384 inline void h6280_device::clear_t()
385 {
386 	P &= ~_fT;
387 }
388 
do_interrupt(uint16_t vector)389 inline void h6280_device::do_interrupt(uint16_t vector)
390 {
391 	h6280_cycles(7);    /* 7 cycles for an int */
392 	push(PCH);
393 	push(PCL);
394 	compose_p(0, _fB);
395 	push(P);
396 	P = (P & ~_fD) | _fI;   /* knock out D and set I flag */
397 	PCL = program_read8(vector);
398 	PCH = program_read8(vector + 1);
399 }
400 
check_and_take_irq_lines()401 inline void h6280_device::check_and_take_irq_lines()
402 {
403 	if ( m_nmi_state != CLEAR_LINE ) {
404 		m_nmi_state = CLEAR_LINE;
405 		do_interrupt(H6280_NMI_VEC);
406 	}
407 	else if( !(P & _fI) )
408 	{
409 		if ( m_irq_state[2] != CLEAR_LINE &&
410 				!(m_irq_mask & 0x4) )
411 		{
412 			do_interrupt(H6280_TIMER_VEC);
413 		} else
414 		if ( m_irq_state[0] != CLEAR_LINE &&
415 				!(m_irq_mask & 0x2) )
416 		{
417 			do_interrupt(H6280_IRQ1_VEC);
418 			standard_irq_callback(0);
419 		} else
420 		if ( m_irq_state[1] != CLEAR_LINE &&
421 				!(m_irq_mask & 0x1) )
422 		{
423 			do_interrupt(H6280_IRQ2_VEC);
424 			standard_irq_callback(1);
425 		}
426 	}
427 }
428 
check_irq_lines()429 inline void h6280_device::check_irq_lines()
430 {
431 	if (!m_irq_pending)
432 		m_irq_pending = 2;
433 }
434 
435 /***************************************************************
436  *  CHECK_VDC_VCE_PENALTY
437  * The CPU inserts 1 clock delay when accessing the VDC or VCE
438  * area.
439  ***************************************************************/
check_vdc_vce_penalty(uint16_t addr)440 inline void h6280_device::check_vdc_vce_penalty(uint16_t addr)
441 {
442 	if ( ( translated(addr) & 0x1FF800 ) == 0x1FE000 ) {
443 		h6280_cycles(1);
444 	}
445 }
446 
447 /***************************************************************
448  *  BRA  branch relative
449  ***************************************************************/
bra(bool cond)450 inline void h6280_device::bra(bool cond)
451 {
452 	clear_t();
453 	if (cond)
454 	{
455 		h6280_cycles(4);
456 		uint8_t tmp = read_opcode_arg();
457 		PCW++;
458 		EAW = PCW + (signed char)tmp;
459 		PCD = EAD;
460 	}
461 	else
462 	{
463 		PCW++;
464 		h6280_cycles(2);
465 	}
466 }
467 
468 /***************************************************************
469  *
470  * Helper macros to build the effective address
471  *
472  ***************************************************************/
473 
474 /***************************************************************
475  *  EA = zero page address
476  ***************************************************************/
ea_zpg()477 inline void h6280_device::ea_zpg()
478 {
479 	ZPL = read_opcode_arg();
480 	PCW++;
481 	EAD = ZPD;
482 }
483 
484 /***************************************************************
485  *  EA = zero page address - T flag
486  ***************************************************************/
ea_tflg()487 inline void h6280_device::ea_tflg()
488 {
489 	ZPL = X;
490 	EAD = ZPD;
491 }
492 
493 /***************************************************************
494  *  EA = zero page address + X
495  ***************************************************************/
ea_zpx()496 inline void h6280_device::ea_zpx()
497 {
498 	ZPL = read_opcode_arg() + X;
499 	PCW++;
500 	EAD = ZPD;
501 }
502 
503 /***************************************************************
504  *  EA = zero page address + Y
505  ***************************************************************/
ea_zpy()506 inline void h6280_device::ea_zpy()
507 {
508 	ZPL = read_opcode_arg() + Y;
509 	PCW++;
510 	EAD = ZPD;
511 }
512 
513 /***************************************************************
514  *  EA = absolute address
515  ***************************************************************/
ea_abs()516 inline void h6280_device::ea_abs()
517 {
518 	EAL = read_opcode_arg();
519 	PCW++;
520 	EAH = read_opcode_arg();
521 	PCW++;
522 }
523 
524 /***************************************************************
525  *  EA = absolute address + X
526  ***************************************************************/
ea_abx()527 inline void h6280_device::ea_abx()
528 {
529 	ea_abs();
530 	EAW += X;
531 }
532 
533 /***************************************************************
534  *  EA = absolute address + Y
535  ***************************************************************/
ea_aby()536 inline void h6280_device::ea_aby()
537 {
538 	ea_abs();
539 	EAW += Y;
540 }
541 
542 /***************************************************************
543  *  EA = zero page indirect (65c02 pre indexed w/o X)
544  ***************************************************************/
ea_zpi()545 inline void h6280_device::ea_zpi()
546 {
547 	ZPL = read_opcode_arg();
548 	PCW++;
549 	EAD = program_read16z(ZPD);
550 }
551 
552 /***************************************************************
553  *  EA = zero page + X indirect (pre indexed)
554  ***************************************************************/
ea_idx()555 inline void h6280_device::ea_idx()
556 {
557 	ZPL = read_opcode_arg() + X;
558 	PCW++;
559 	EAD = program_read16z(ZPD);
560 }
561 
562 /***************************************************************
563  *  EA = zero page indirect + Y (post indexed)
564  ***************************************************************/
ea_idy()565 inline void h6280_device::ea_idy()
566 {
567 	ZPL = read_opcode_arg();
568 	PCW++;
569 	EAD = program_read16z(ZPD);
570 	EAW += Y;
571 }
572 
573 /***************************************************************
574  *  EA = indirect (only used by JMP)
575  ***************************************************************/
ea_ind()576 inline void h6280_device::ea_ind()
577 {
578 	ea_abs();
579 	uint8_t tmp = program_read8(EAD);
580 	EAD++;
581 	EAH = program_read8(EAD);
582 	EAL = tmp;
583 }
584 
585 /***************************************************************
586  *  EA = indirect plus x (only used by JMP)
587  ***************************************************************/
ea_iax()588 inline void h6280_device::ea_iax()
589 {
590 	ea_abs();
591 	EAD+=X;
592 	uint8_t tmp = program_read8(EAD);
593 	EAD++;
594 	EAH = program_read8(EAD);
595 	EAL = tmp;
596 }
597 
rd_imm()598 inline uint8_t h6280_device::rd_imm()
599 {
600 	uint8_t tmp = read_opcode_arg();
601 	PCW++;
602 	return tmp;
603 }
604 
rd_zpg()605 inline uint8_t h6280_device::rd_zpg()
606 {
607 	ea_zpg();
608 	return program_read8z(EAD);
609 }
610 
rd_zpx()611 inline uint8_t h6280_device::rd_zpx()
612 {
613 	ea_zpx();
614 	return program_read8z(EAD);
615 }
616 
rd_zpy()617 inline uint8_t h6280_device::rd_zpy()
618 {
619 	ea_zpy();
620 	return program_read8z(EAD);
621 }
622 
rd_abs()623 inline uint8_t h6280_device::rd_abs()
624 {
625 	ea_abs();
626 	return program_read8(EAD);
627 }
628 
rd_abx()629 inline uint8_t h6280_device::rd_abx()
630 {
631 	ea_abx();
632 	return program_read8(EAD);
633 }
634 
rd_aby()635 inline uint8_t h6280_device::rd_aby()
636 {
637 	ea_aby();
638 	return program_read8(EAD);
639 }
640 
rd_zpi()641 inline uint8_t h6280_device::rd_zpi()
642 {
643 	ea_zpi();
644 	return program_read8(EAD);
645 }
646 
rd_idx()647 inline uint8_t h6280_device::rd_idx()
648 {
649 	ea_idx();
650 	return program_read8(EAD);
651 }
652 
rd_idy()653 inline uint8_t h6280_device::rd_idy()
654 {
655 	ea_idy();
656 	return program_read8(EAD);
657 }
658 
rd_tfl()659 inline uint8_t h6280_device::rd_tfl()
660 {
661 	ea_tflg();
662 	return program_read8z(EAD);
663 }
664 
wr_zpg(uint8_t tmp)665 inline void h6280_device::wr_zpg(uint8_t tmp)
666 {
667 	ea_zpg();
668 	wb_eaz(tmp);
669 }
670 
wr_zpx(uint8_t tmp)671 inline void h6280_device::wr_zpx(uint8_t tmp)
672 {
673 	ea_zpx();
674 	wb_eaz(tmp);
675 }
676 
wr_zpy(uint8_t tmp)677 inline void h6280_device::wr_zpy(uint8_t tmp)
678 {
679 	ea_zpy();
680 	wb_eaz(tmp);
681 }
682 
wr_abs(uint8_t tmp)683 inline void h6280_device::wr_abs(uint8_t tmp)
684 {
685 	ea_abs();
686 	wb_ea(tmp);
687 }
688 
wr_abx(uint8_t tmp)689 inline void h6280_device::wr_abx(uint8_t tmp)
690 {
691 	ea_abx();
692 	wb_ea(tmp);
693 }
694 
wr_aby(uint8_t tmp)695 inline void h6280_device::wr_aby(uint8_t tmp)
696 {
697 	ea_aby();
698 	wb_ea(tmp);
699 }
700 
wr_zpi(uint8_t tmp)701 inline void h6280_device::wr_zpi(uint8_t tmp)
702 {
703 	ea_zpi();
704 	wb_ea(tmp);
705 }
706 
wr_idx(uint8_t tmp)707 inline void h6280_device::wr_idx(uint8_t tmp)
708 {
709 	ea_idx();
710 	wb_ea(tmp);
711 }
712 
wr_idy(uint8_t tmp)713 inline void h6280_device::wr_idy(uint8_t tmp)
714 {
715 	ea_idy();
716 	wb_ea(tmp);
717 }
718 
wb_ea(uint8_t tmp)719 inline void h6280_device::wb_ea(uint8_t tmp)
720 {
721 	program_write8(EAD, tmp);
722 }
723 
wb_eaz(uint8_t tmp)724 inline void h6280_device::wb_eaz(uint8_t tmp)
725 {
726 	program_write8z(EAD, tmp);
727 }
728 
729 /***************************************************************
730  *
731  * Macros to emulate the 6280 opcodes
732  *
733  ***************************************************************/
734 
735 /***************************************************************
736  * compose the real flag register by
737  * including N and Z and set any
738  * SET and clear any CLR bits also
739  ***************************************************************/
740 #if H6280_LAZY_FLAGS
741 
compose_p(uint8_t SET,uint8_t CLR)742 inline void h6280_device::compose_p(uint8_t SET, uint8_t CLR)
743 {
744 	P = (P & ~(_fN | _fZ | CLR)) |
745 		(NZ >> 8) |
746 		((NZ & 0xff) ? 0 : _fZ) |
747 		SET;
748 }
749 
750 #else
751 
compose_p(uint8_t SET,uint8_t CLR)752 inline void h6280_device::compose_p(uint8_t SET, uint8_t CLR)
753 {
754 	P = (P & ~CLR) | SET;
755 }
756 
757 #endif
758 
759 /* 6280 ********************************************************
760  *  ADC Add with carry
761  ***************************************************************/
tadc(uint8_t tmp)762 inline void h6280_device::tadc(uint8_t tmp)
763 {
764 	clear_t();
765 	int tflagtemp = rd_tfl();
766 	if (P & _fD)
767 	{
768 		int c = (P & _fC);
769 		int lo = (tflagtemp & 0x0f) + (tmp & 0x0f) + c;
770 		int hi = (tflagtemp & 0xf0) + (tmp & 0xf0);
771 		P &= ~_fC;
772 		if (lo > 0x09)
773 		{
774 			hi += 0x10;
775 			lo += 0x06;
776 		}
777 		if (hi > 0x90)
778 			hi += 0x60;
779 		if (hi & 0xff00)
780 			P |= _fC;
781 		tflagtemp = (lo & 0x0f) + (hi & 0xf0);
782 		h6280_cycles(1);
783 	}
784 	else
785 	{
786 		int c = (P & _fC);
787 		int sum = tflagtemp + tmp + c;
788 		P &= ~(_fV | _fC);
789 		if (~(tflagtemp^tmp) & (tflagtemp^sum) & _fN)
790 			P |= _fV;
791 		if (sum & 0xff00)
792 			P |= _fC;
793 		tflagtemp = (uint8_t) sum;
794 	}
795 	set_nz(tflagtemp);
796 	wb_eaz(tflagtemp);
797 	h6280_cycles(3);
798 }
799 
800 
adc(uint8_t tmp)801 inline void h6280_device::adc(uint8_t tmp)
802 {
803 	if(P & _fT)
804 		tadc(tmp);
805 	else {
806 		if (P & _fD)
807 		{
808 			int c = (P & _fC);
809 			int lo = (A & 0x0f) + (tmp & 0x0f) + c;
810 			int hi = (A & 0xf0) + (tmp & 0xf0);
811 			P &= ~_fC;
812 			if (lo > 0x09)
813 			{
814 				hi += 0x10;
815 				lo += 0x06;
816 			}
817 			if (hi > 0x90)
818 				hi += 0x60;
819 			if (hi & 0xff00)
820 				P |= _fC;
821 			A = (lo & 0x0f) + (hi & 0xf0);
822 			h6280_cycles(1);
823 		}
824 		else
825 		{
826 			int c = (P & _fC);
827 			int sum = A + tmp + c;
828 			P &= ~(_fV | _fC);
829 			if (~(A^tmp) & (A^sum) & _fN)
830 				P |= _fV;
831 			if (sum & 0xff00)
832 				P |= _fC;
833 			A = (uint8_t) sum;
834 		}
835 		set_nz(A);
836 	}
837 }
838 
839 /* 6280 ********************************************************
840  *  AND Logical and
841  ***************************************************************/
tand(uint8_t tmp)842 inline void h6280_device::tand(uint8_t tmp)
843 {
844 	clear_t();
845 	int tflagtemp = rd_tfl();
846 	tflagtemp = (uint8_t)(tflagtemp & tmp);
847 	wb_eaz(tflagtemp);
848 	set_nz(tflagtemp);
849 	h6280_cycles(3);
850 }
851 
and_a(uint8_t tmp)852 inline void h6280_device::and_a(uint8_t tmp)
853 {
854 	if(P & _fT)
855 		tand(tmp);
856 	else {
857 		A = (uint8_t)(A & tmp);
858 		set_nz(A);
859 	}
860 }
861 
862 /* 6280 ********************************************************
863  *  ASL Arithmetic shift left
864  ***************************************************************/
asl(uint8_t tmp)865 inline uint8_t h6280_device::asl(uint8_t tmp)
866 {
867 	clear_t();
868 	P = (P & ~_fC) | ((tmp >> 7) & _fC);
869 	tmp = (uint8_t)(tmp << 1);
870 	set_nz(tmp);
871 	return tmp;
872 }
873 
874 /* 6280 ********************************************************
875  *  BBR Branch if bit is reset
876  ***************************************************************/
bbr(int bit,uint8_t tmp)877 inline void h6280_device::bbr(int bit, uint8_t tmp)
878 {
879 	bra(!(tmp & (1<<bit)));
880 }
881 
882 /* 6280 ********************************************************
883  *  BBS Branch if bit is set
884  ***************************************************************/
bbs(int bit,uint8_t tmp)885 inline void h6280_device::bbs(int bit, uint8_t tmp)
886 {
887 	bra(tmp & (1<<bit));
888 }
889 
890 /* 6280 ********************************************************
891  *  BCC Branch if carry clear
892  ***************************************************************/
bcc()893 inline void h6280_device::bcc()
894 {
895 	bra(!(P & _fC));
896 }
897 
898 /* 6280 ********************************************************
899  *  BCS Branch if carry set
900  ***************************************************************/
bcs()901 inline void h6280_device::bcs()
902 {
903 	bra(P & _fC);
904 }
905 
906 /* 6280 ********************************************************
907  *  BEQ Branch if equal
908  ***************************************************************/
beq()909 inline void h6280_device::beq()
910 {
911 #if H6280_LAZY_FLAGS
912 	bra(!(NZ & 0xff));
913 #else
914 	bra(P & _fZ);
915 #endif
916 }
917 
918 /* 6280 ********************************************************
919  *  BIT Bit test
920  ***************************************************************/
bit(uint8_t tmp)921 inline void h6280_device::bit(uint8_t tmp)
922 {
923 	P = (P & ~(_fN|_fV|_fT|_fZ))
924 		| ((tmp&0x80) ? _fN:0)
925 		| ((tmp&0x40) ? _fV:0)
926 		| ((tmp&A)  ? 0:_fZ);
927 }
928 
929 /* 6280 ********************************************************
930  *  BMI Branch if minus
931  ***************************************************************/
bmi()932 inline void h6280_device::bmi()
933 {
934 #if H6280_LAZY_FLAGS
935 	bra(NZ & 0x8000);
936 #else
937 	bra(P & _fN);
938 #endif
939 }
940 
941 /* 6280 ********************************************************
942  *  BNE Branch if not equal
943  ***************************************************************/
bne()944 inline void h6280_device::bne()
945 {
946 #if H6280_LAZY_FLAGS
947 	bra(NZ & 0xff);
948 #else
949 	bra(!(P & _fZ));
950 #endif
951 }
952 
953 /* 6280 ********************************************************
954  *  BPL Branch if plus
955  ***************************************************************/
bpl()956 inline void h6280_device::bpl()
957 {
958 #if H6280_LAZY_FLAGS
959 	bra(!(NZ & 0x8000));
960 #else
961 	bra(!(P & _fN));
962 #endif
963 }
964 
965 /* 6280 ********************************************************
966  *  BRK Break
967  *  increment PC, push PC hi, PC lo, flags (with B bit set),
968  *  set I flag, reset D flag and jump via IRQ vector
969  ***************************************************************/
brk()970 inline void h6280_device::brk()
971 {
972 	logerror("BRK %04x\n",PCW);
973 	clear_t();
974 	PCW++;
975 	push(PCH);
976 	push(PCL);
977 	push(P);
978 	P = (P & ~_fD) | _fI;
979 	PCL = program_read8(H6280_IRQ2_VEC);
980 	PCH = program_read8(H6280_IRQ2_VEC+1);
981 }
982 
983 /* 6280 ********************************************************
984  *  BSR Branch to subroutine
985  ***************************************************************/
bsr()986 inline void h6280_device::bsr()
987 {
988 	push(PCH);
989 	push(PCL);
990 	h6280_cycles(4); /* 4 cycles here, 4 in BRA */
991 	bra(1);
992 }
993 
994 /* 6280 ********************************************************
995  *  BVC Branch if overflow clear
996  ***************************************************************/
bvc()997 inline void h6280_device::bvc()
998 {
999 	bra(!(P & _fV));
1000 }
1001 
1002 /* 6280 ********************************************************
1003  *  BVS Branch if overflow set
1004  ***************************************************************/
bvs()1005 inline void h6280_device::bvs()
1006 {
1007 	bra(P & _fV);
1008 }
1009 
1010 /* 6280 ********************************************************
1011  *  CLA Clear accumulator
1012  ***************************************************************/
cla()1013 inline void h6280_device::cla()
1014 {
1015 	clear_t();
1016 	A = 0;
1017 }
1018 
1019 /* 6280 ********************************************************
1020  *  CLC Clear carry flag
1021  ***************************************************************/
clc()1022 inline void h6280_device::clc()
1023 {
1024 	clear_t();
1025 	P &= ~_fC;
1026 }
1027 
1028 /* 6280 ********************************************************
1029  *  CLD Clear decimal flag
1030  ***************************************************************/
cld()1031 inline void h6280_device::cld()
1032 {
1033 	clear_t();
1034 	P &= ~_fD;
1035 }
1036 
1037 /* 6280 ********************************************************
1038  *  CLI Clear interrupt flag
1039  ***************************************************************/
cli()1040 inline void h6280_device::cli()
1041 {
1042 	clear_t();
1043 	if( P & _fI )
1044 	{
1045 		P &= ~_fI;
1046 		check_irq_lines();
1047 	}
1048 }
1049 
1050 
1051 /* 6280 ********************************************************
1052  *  CLV Clear overflow flag
1053  ***************************************************************/
clv()1054 inline void h6280_device::clv()
1055 {
1056 	clear_t();
1057 	P &= ~_fV;
1058 }
1059 
1060 /* 6280 ********************************************************
1061  *  CLX Clear index X
1062  ***************************************************************/
clx()1063 inline void h6280_device::clx()
1064 {
1065 	clear_t();
1066 	X = 0;
1067 }
1068 
1069 /* 6280 ********************************************************
1070  *  CLY Clear index Y
1071  ***************************************************************/
cly()1072 inline void h6280_device::cly()
1073 {
1074 	clear_t();
1075 	Y = 0;
1076 }
1077 
1078 /* 6280 ********************************************************
1079  *  CMP Compare accumulator
1080  ***************************************************************/
cmp(uint8_t tmp)1081 inline void h6280_device::cmp(uint8_t tmp)
1082 {
1083 	clear_t();
1084 	P &= ~_fC;
1085 	if (A >= tmp)
1086 		P |= _fC;
1087 	set_nz((uint8_t)(A - tmp));
1088 }
1089 
1090 /* 6280 ********************************************************
1091  *  CPX Compare index X
1092  ***************************************************************/
cpx(uint8_t tmp)1093 inline void h6280_device::cpx(uint8_t tmp)
1094 {
1095 	clear_t();
1096 	P &= ~_fC;
1097 	if (X >= tmp)
1098 		P |= _fC;
1099 	set_nz((uint8_t)(X - tmp));
1100 }
1101 
1102 /* 6280 ********************************************************
1103  *  CPY Compare index Y
1104  ***************************************************************/
cpy(uint8_t tmp)1105 inline void h6280_device::cpy(uint8_t tmp)
1106 {
1107 	clear_t();
1108 	P &= ~_fC;
1109 	if (Y >= tmp)
1110 		P |= _fC;
1111 	set_nz((uint8_t)(Y - tmp));
1112 }
1113 
1114 /* 6280 ********************************************************
1115  *  DEC Decrement memory
1116  ***************************************************************/
dec(uint8_t tmp)1117 inline uint8_t h6280_device::dec(uint8_t tmp)
1118 {
1119 	clear_t();
1120 	tmp = (uint8_t)(tmp-1);
1121 	set_nz(tmp);
1122 	return tmp;
1123 }
1124 
1125 /* 6280 ********************************************************
1126  *  DEX Decrement index X
1127  ***************************************************************/
dex()1128 inline void h6280_device::dex()
1129 {
1130 	clear_t();
1131 	X = (uint8_t)(X - 1);
1132 	set_nz(X);
1133 }
1134 
1135 /* 6280 ********************************************************
1136  *  DEY Decrement index Y
1137  ***************************************************************/
dey()1138 inline void h6280_device::dey()
1139 {
1140 	clear_t();
1141 	Y = (uint8_t)(Y - 1);
1142 	set_nz(Y);
1143 }
1144 
1145 /* 6280 ********************************************************
1146  *  EOR Logical exclusive or
1147  ***************************************************************/
teor(uint8_t tmp)1148 inline void h6280_device::teor(uint8_t tmp)
1149 {
1150 	clear_t();
1151 	int tflagtemp = rd_tfl();
1152 	tflagtemp = (uint8_t)(tflagtemp ^ tmp);
1153 	wb_eaz(tflagtemp);
1154 	set_nz(tflagtemp);
1155 	h6280_cycles(3);
1156 }
1157 
eor(uint8_t tmp)1158 inline void h6280_device::eor(uint8_t tmp)
1159 {
1160 	if(P & _fT)
1161 		teor(tmp);
1162 	else {
1163 		A = (uint8_t)(A ^ tmp);
1164 		set_nz(A);
1165 	}
1166 }
1167 
1168 /* 6280 ********************************************************
1169  *  INC Increment memory
1170  ***************************************************************/
inc(uint8_t tmp)1171 inline uint8_t h6280_device::inc(uint8_t tmp)
1172 {
1173 	clear_t();
1174 	tmp = (uint8_t)(tmp+1);
1175 	set_nz(tmp);
1176 	return tmp;
1177 }
1178 
1179 /* 6280 ********************************************************
1180  *  INX Increment index X
1181  ***************************************************************/
inx()1182 inline void h6280_device::inx()
1183 {
1184 	clear_t();
1185 	X = (uint8_t)(X + 1);
1186 	set_nz(X);
1187 }
1188 
1189 /* 6280 ********************************************************
1190  *  INY Increment index Y
1191  ***************************************************************/
iny()1192 inline void h6280_device::iny()
1193 {
1194 	clear_t();
1195 	Y = (uint8_t)(Y + 1);
1196 	set_nz(Y);
1197 }
1198 
1199 /* 6280 ********************************************************
1200  *  JMP Jump to address
1201  *  set PC to the effective address
1202  ***************************************************************/
jmp()1203 inline void h6280_device::jmp()
1204 {
1205 	clear_t();
1206 	PCD = EAD;
1207 }
1208 
1209 /* 6280 ********************************************************
1210  *  JSR Jump to subroutine
1211  *  decrement PC (sic!) push PC hi, push PC lo and set
1212  *  PC to the effective address
1213  ***************************************************************/
jsr()1214 inline void h6280_device::jsr()
1215 {
1216 	clear_t();
1217 	PCW--;
1218 	push(PCH);
1219 	push(PCL);
1220 	PCD = EAD;
1221 }
1222 
1223 /* 6280 ********************************************************
1224  *  LDA Load accumulator
1225  ***************************************************************/
lda(uint8_t tmp)1226 inline void h6280_device::lda(uint8_t tmp)
1227 {
1228 	clear_t();
1229 	A = (uint8_t)tmp;
1230 	set_nz(A);
1231 }
1232 
1233 /* 6280 ********************************************************
1234  *  LDX Load index X
1235  ***************************************************************/
ldx(uint8_t tmp)1236 inline void h6280_device::ldx(uint8_t tmp)
1237 {
1238 	clear_t();
1239 	X = (uint8_t)tmp;
1240 	set_nz(X);
1241 }
1242 
1243 /* 6280 ********************************************************
1244  *  LDY Load index Y
1245  ***************************************************************/
ldy(uint8_t tmp)1246 inline void h6280_device::ldy(uint8_t tmp)
1247 {
1248 	clear_t();
1249 	Y = (uint8_t)tmp;
1250 	set_nz(Y);
1251 }
1252 
1253 /* 6280 ********************************************************
1254  *  LSR Logic shift right
1255  *  0 -> [7][6][5][4][3][2][1][0] -> C
1256  ***************************************************************/
lsr(uint8_t tmp)1257 inline uint8_t h6280_device::lsr(uint8_t tmp)
1258 {
1259 	clear_t();
1260 	P = (P & ~_fC) | (tmp & _fC);
1261 	tmp = (uint8_t)tmp >> 1;
1262 	set_nz(tmp);
1263 	return tmp;
1264 }
1265 
1266 /* 6280 ********************************************************
1267  *  NOP No operation
1268  ***************************************************************/
nop()1269 inline void h6280_device::nop()
1270 {
1271 	clear_t();
1272 }
1273 
1274 /* 6280 ********************************************************
1275  *  ORA Logical inclusive or
1276  ***************************************************************/
1277 
tora(uint8_t tmp)1278 inline void h6280_device::tora(uint8_t tmp)
1279 {
1280 	clear_t();
1281 	int tflagtemp = rd_tfl();
1282 	tflagtemp = (uint8_t)(tflagtemp | tmp);
1283 	wb_eaz(tflagtemp);
1284 	set_nz(tflagtemp);
1285 	h6280_cycles(3);
1286 }
1287 
ora(uint8_t tmp)1288 inline void h6280_device::ora(uint8_t tmp)
1289 {
1290 	if(P & _fT)
1291 		tora(tmp);
1292 	else {
1293 		A = (uint8_t)(A | tmp);
1294 		set_nz(A);
1295 	}
1296 }
1297 
1298 /* 6280 ********************************************************
1299  *  PHA Push accumulator
1300  ***************************************************************/
pha()1301 inline void h6280_device::pha()
1302 {
1303 	clear_t();
1304 	push(A);
1305 }
1306 
1307 /* 6280 ********************************************************
1308  *  PHP Push processor status (flags)
1309  ***************************************************************/
php()1310 inline void h6280_device::php()
1311 {
1312 	clear_t();
1313 	compose_p(0,0);
1314 	push(P);
1315 }
1316 
1317 /* 6280 ********************************************************
1318  *  PHX Push index X
1319  ***************************************************************/
phx()1320 inline void h6280_device::phx()
1321 {
1322 	clear_t();
1323 	push(X);
1324 }
1325 
1326 /* 6280 ********************************************************
1327  *  PHY Push index Y
1328  ***************************************************************/
phy()1329 inline void h6280_device::phy()
1330 {
1331 	clear_t();
1332 	push(Y);
1333 }
1334 
1335 /* 6280 ********************************************************
1336  *  PLA Pull accumulator
1337  ***************************************************************/
pla()1338 inline void h6280_device::pla()
1339 {
1340 	clear_t();
1341 	pull(A);
1342 	set_nz(A);
1343 }
1344 
1345 /* 6280 ********************************************************
1346  *  PLP Pull processor status (flags)
1347  ***************************************************************/
plp()1348 inline void h6280_device::plp()
1349 {
1350 #if H6280_LAZY_FLAGS
1351 	pull(P);
1352 	P |= _fB;
1353 	NZ = ((P & _fN) << 8) |
1354 			((P & _fZ) ^ _fZ);
1355 	check_irq_lines();
1356 #else
1357 	pull(P);
1358 	P |= _fB;
1359 	check_irq_lines();
1360 #endif
1361 }
1362 
1363 /* 6280 ********************************************************
1364  *  PLX Pull index X
1365  ***************************************************************/
plx()1366 inline void h6280_device::plx()
1367 {
1368 	clear_t();
1369 	pull(X);
1370 	set_nz(X);
1371 }
1372 
1373 /* 6280 ********************************************************
1374  *  PLY Pull index Y
1375  ***************************************************************/
ply()1376 inline void h6280_device::ply()
1377 {
1378 	clear_t();
1379 	pull(Y);
1380 	set_nz(Y);
1381 }
1382 
1383 /* 6280 ********************************************************
1384  *  RMB Reset memory bit
1385  ***************************************************************/
rmb(int bit,uint8_t tmp)1386 inline uint8_t h6280_device::rmb(int bit, uint8_t tmp)
1387 {
1388 	clear_t();
1389 	tmp &= ~(1<<bit);
1390 	return tmp;
1391 }
1392 
1393 /* 6280 ********************************************************
1394  *  ROL Rotate left
1395  *  new C <- [7][6][5][4][3][2][1][0] <- C
1396  ***************************************************************/
rol(uint8_t tmp)1397 inline uint8_t h6280_device::rol(uint8_t tmp)
1398 {
1399 	clear_t();
1400 	int tmp9 = (tmp << 1) | (P & _fC);
1401 	P = (P & ~_fC) | ((tmp9 >> 8) & _fC);
1402 	tmp = (uint8_t)tmp9;
1403 	set_nz(tmp);
1404 	return tmp;
1405 }
1406 
1407 /* 6280 ********************************************************
1408  *  ROR Rotate right
1409  *  C -> [7][6][5][4][3][2][1][0] -> new C
1410  ***************************************************************/
ror(uint8_t tmp)1411 inline uint8_t h6280_device::ror(uint8_t tmp)
1412 {
1413 	clear_t();
1414 	int tmp9 = tmp | (P & _fC) << 8;
1415 	P = (P & ~_fC) | (tmp & _fC);
1416 	tmp = (uint8_t)(tmp9 >> 1);
1417 	set_nz(tmp);
1418 	return tmp;
1419 }
1420 
1421 /* 6280 ********************************************************
1422  *  RTI Return from interrupt
1423  *  pull flags, pull PC lo, pull PC hi and increment PC
1424  ***************************************************************/
rti()1425 inline void h6280_device::rti()
1426 {
1427 #if H6280_LAZY_FLAGS
1428 	pull(P);
1429 	P |= _fB;
1430 	NZ = ((P & _fN) << 8) |
1431 			((P & _fZ) ^ _fZ);
1432 	pull(PCL);
1433 	pull(PCH);
1434 	check_irq_lines();
1435 #else
1436 	pull(P);
1437 	P |= _fB;
1438 	pull(PCL);
1439 	pull(PCH);
1440 	check_irq_lines();
1441 #endif
1442 }
1443 
1444 /* 6280 ********************************************************
1445  *  RTS Return from subroutine
1446  *  pull PC lo, PC hi and increment PC
1447  ***************************************************************/
rts()1448 inline void h6280_device::rts()
1449 {
1450 	clear_t();
1451 	pull(PCL);
1452 	pull(PCH);
1453 	PCW++;
1454 }
1455 
1456 /* 6280 ********************************************************
1457  *  SAX Swap accumulator and index X
1458  ***************************************************************/
sax()1459 inline void h6280_device::sax()
1460 {
1461 	clear_t();
1462 	uint8_t tmp = X;
1463 	X = A;
1464 	A = tmp;
1465 }
1466 
1467 /* 6280 ********************************************************
1468  *  SAY Swap accumulator and index Y
1469  ***************************************************************/
say()1470 inline void h6280_device::say()
1471 {
1472 	clear_t();
1473 	uint8_t tmp = Y;
1474 	Y = A;
1475 	A = tmp;
1476 }
1477 
1478 /* 6280 ********************************************************
1479  *  SBC Subtract with carry
1480  ***************************************************************/
tsbc(uint8_t tmp)1481 inline void h6280_device::tsbc(uint8_t tmp)
1482 {
1483 	clear_t();
1484 	int tflagtemp = rd_tfl();
1485 	if (P & _fD)
1486 	{
1487 		int c = (P & _fC) ^ _fC;
1488 		int sum = tflagtemp - tmp -c;
1489 		int lo = (tflagtemp & 0x0f) - (tmp & 0x0f) - c;
1490 		int hi = (tflagtemp & 0xf0) - (tmp & 0xf0);
1491 		P &= ~_fC;
1492 		if (lo & 0xf0)
1493 			lo -= 6;
1494 		if (lo & 0x80)
1495 			hi -= 0x10;
1496 		if (hi & 0x0f00)
1497 			hi -= 0x60;
1498 		if ((sum & 0xff00) == 0)
1499 			P |= _fC;
1500 		tflagtemp = (lo & 0x0f) + (hi & 0xf0);
1501 		h6280_cycles(1);
1502 	}
1503 	else
1504 	{
1505 		int c = (P & _fC) ^ _fC;
1506 		int sum = tflagtemp - tmp - c;
1507 		P &= ~(_fV | _fC);
1508 		if ((tflagtemp^tmp) & (tflagtemp^sum) & _fN)
1509 			P |= _fV;
1510 		if ((sum & 0xff00) == 0)
1511 			P |= _fC;
1512 		tflagtemp = (uint8_t) sum;
1513 	}
1514 	set_nz(tflagtemp);
1515 	wb_eaz(tflagtemp);
1516 	h6280_cycles(3);
1517 }
1518 
sbc(uint8_t tmp)1519 inline void h6280_device::sbc(uint8_t tmp)
1520 {
1521 	if(P & _fT)
1522 		tsbc(tmp);
1523 	else {
1524 		if (P & _fD)
1525 		{
1526 			int c = (P & _fC) ^ _fC;
1527 			int sum = A - tmp - c;
1528 			int lo = (A & 0x0f) - (tmp & 0x0f) - c;
1529 			int hi = (A & 0xf0) - (tmp & 0xf0);
1530 			P &= ~_fC;
1531 			if (lo & 0xf0)
1532 				lo -= 6;
1533 			if (lo & 0x80)
1534 				hi -= 0x10;
1535 			if (hi & 0x0f00)
1536 				hi -= 0x60;
1537 			if ((sum & 0xff00) == 0)
1538 				P |= _fC;
1539 			A = (lo & 0x0f) + (hi & 0xf0);
1540 			h6280_cycles(1);
1541 		}
1542 		else
1543 		{
1544 			int c = (P & _fC) ^ _fC;
1545 			int sum = A - tmp - c;
1546 			P &= ~(_fV | _fC);
1547 			if ((A^tmp) & (A^sum) & _fN)
1548 				P |= _fV;
1549 			if ((sum & 0xff00) == 0)
1550 				P |= _fC;
1551 			A = (uint8_t) sum;
1552 		}
1553 		set_nz(A);
1554 	}
1555 }
1556 
1557 /* 6280 ********************************************************
1558  *  SEC Set carry flag
1559  ***************************************************************/
sec()1560 inline void h6280_device::sec()
1561 {
1562 	clear_t();
1563 	P |= _fC;
1564 }
1565 
1566 /* 6280 ********************************************************
1567  *  SED Set decimal flag
1568  ***************************************************************/
sed()1569 inline void h6280_device::sed()
1570 {
1571 	clear_t();
1572 	P |= _fD;
1573 }
1574 
1575 /* 6280 ********************************************************
1576  *  SEI Set interrupt flag
1577  ***************************************************************/
sei()1578 inline void h6280_device::sei()
1579 {
1580 	clear_t();
1581 	P |= _fI;
1582 }
1583 
1584 /* 6280 ********************************************************
1585  *  SET Set t flag
1586  ***************************************************************/
set()1587 inline void h6280_device::set()
1588 {
1589 	P |= _fT;
1590 }
1591 
1592 /* 6280 ********************************************************
1593  *  SMB Set memory bit
1594  ***************************************************************/
smb(int bit,uint8_t tmp)1595 inline uint8_t h6280_device::smb(int bit, uint8_t tmp)
1596 {
1597 	clear_t();
1598 	tmp |= (1<<bit);
1599 	return tmp;
1600 }
1601 
1602 /* 6280 ********************************************************
1603  *  ST0 Store at hardware address 0
1604  ***************************************************************/
st0(uint8_t tmp)1605 inline void h6280_device::st0(uint8_t tmp)
1606 {
1607 	clear_t();
1608 	m_io.write_byte(0x0000,tmp);
1609 }
1610 
1611 /* 6280 ********************************************************
1612  *  ST1 Store at hardware address 2
1613  ***************************************************************/
st1(uint8_t tmp)1614 inline void h6280_device::st1(uint8_t tmp)
1615 {
1616 	clear_t();
1617 	m_io.write_byte(0x0002,tmp);
1618 }
1619 
1620 /* 6280 ********************************************************
1621  *  ST2 Store at hardware address 3
1622  ***************************************************************/
st2(uint8_t tmp)1623 inline void h6280_device::st2(uint8_t tmp)
1624 {
1625 	clear_t();
1626 	m_io.write_byte(0x0003,tmp);
1627 }
1628 
1629 /* 6280 ********************************************************
1630  *  STA Store accumulator
1631  ***************************************************************/
sta()1632 inline uint8_t h6280_device::sta()
1633 {
1634 	clear_t();
1635 	return A;
1636 }
1637 
1638 /* 6280 ********************************************************
1639  *  STX Store index X
1640  ***************************************************************/
stx()1641 inline uint8_t h6280_device::stx()
1642 {
1643 	clear_t();
1644 	return X;
1645 }
1646 
1647 /* 6280 ********************************************************
1648  *  STY Store index Y
1649  ***************************************************************/
sty()1650 inline uint8_t h6280_device::sty()
1651 {
1652 	clear_t();
1653 	return Y;
1654 }
1655 
1656 /* 6280 ********************************************************
1657  * STZ  Store zero
1658  ***************************************************************/
stz()1659 inline uint8_t h6280_device::stz()
1660 {
1661 	clear_t();
1662 	return 0;
1663 }
1664 
1665 /* H6280 *******************************************************
1666  *  SXY Swap index X and index Y
1667  ***************************************************************/
sxy()1668 inline void h6280_device::sxy()
1669 {
1670 	clear_t();
1671 	uint8_t tmp = X;
1672 	X = Y;
1673 	Y = tmp;
1674 }
1675 
1676 /* H6280 *******************************************************
1677  *  TAI Transfer Alternate Increment
1678  ***************************************************************/
tai()1679 inline void h6280_device::tai()
1680 {
1681 	clear_t();
1682 	int from = program_read16(PCW);
1683 	int to = program_read16(PCW + 2);
1684 	int length = program_read16(PCW + 4);
1685 	PCW += 6;
1686 	int alternate = 0;
1687 	if (!length) length = 0x10000;
1688 	h6280_cycles( ((6 * length) + 17) );
1689 	while ((length--) != 0)
1690 	{
1691 		program_write8(to, program_read8(from + alternate));
1692 		to++;
1693 		alternate ^= 1;
1694 	}
1695 }
1696 
1697 /* H6280 *******************************************************
1698  *  TAM Transfer accumulator to memory mapper register(s)
1699  ***************************************************************/
tam(uint8_t tmp)1700 inline void h6280_device::tam(uint8_t tmp)
1701 {
1702 	clear_t();
1703 	if (tmp&0x01) m_mmr[0] = A;
1704 	if (tmp&0x02) m_mmr[1] = A;
1705 	if (tmp&0x04) m_mmr[2] = A;
1706 	if (tmp&0x08) m_mmr[3] = A;
1707 	if (tmp&0x10) m_mmr[4] = A;
1708 	if (tmp&0x20) m_mmr[5] = A;
1709 	if (tmp&0x40) m_mmr[6] = A;
1710 	if (tmp&0x80) m_mmr[7] = A;
1711 }
1712 
1713 /* 6280 ********************************************************
1714  *  TAX Transfer accumulator to index X
1715  ***************************************************************/
tax()1716 inline void h6280_device::tax()
1717 {
1718 	clear_t();
1719 	X = A;
1720 	set_nz(X);
1721 }
1722 
1723 /* 6280 ********************************************************
1724  *  TAY Transfer accumulator to index Y
1725  ***************************************************************/
tay()1726 inline void h6280_device::tay()
1727 {
1728 	clear_t();
1729 	Y = A;
1730 	set_nz(Y);
1731 }
1732 
1733 /* 6280 ********************************************************
1734  *  TDD Transfer Decrement Decrement
1735  ***************************************************************/
tdd()1736 inline void h6280_device::tdd()
1737 {
1738 	clear_t();
1739 	int from = program_read16(PCW);
1740 	int to = program_read16(PCW + 2);
1741 	int length = program_read16(PCW + 4);
1742 	PCW+=6;
1743 	if (!length) length = 0x10000;
1744 	h6280_cycles( ((6 * length) + 17) );
1745 	while ((length--) != 0) {
1746 		program_write8(to, program_read8(from));
1747 		to--;
1748 		from--;
1749 	}
1750 }
1751 
1752 /* 6280 ********************************************************
1753  *  TIA Transfer Increment Alternate
1754  ***************************************************************/
tia()1755 inline void h6280_device::tia()
1756 {
1757 	clear_t();
1758 	int from = program_read16(PCW);
1759 	int to  = program_read16(PCW + 2);
1760 	int length = program_read16(PCW + 4);
1761 	PCW+=6;
1762 	int alternate=0;
1763 	if (!length) length = 0x10000;
1764 	h6280_cycles( ((6 * length) + 17) );
1765 	while ((length--) != 0) {
1766 		program_write8(to + alternate, program_read8(from));
1767 		from++;
1768 		alternate ^= 1;
1769 	}
1770 }
1771 
1772 /* 6280 ********************************************************
1773  *  TII Transfer Increment Increment
1774  ***************************************************************/
tii()1775 inline void h6280_device::tii()
1776 {
1777 	clear_t();
1778 	int from = program_read16(PCW);
1779 	int to = program_read16(PCW + 2);
1780 	int length = program_read16(PCW + 4);
1781 	PCW += 6;
1782 	if (!length) length = 0x10000;
1783 	h6280_cycles( ((6 * length) + 17) );
1784 	while ((length--) != 0) {
1785 		program_write8(to, program_read8(from));
1786 		to++;
1787 		from++;
1788 	}
1789 }
1790 
1791 /* 6280 ********************************************************
1792  *  TIN Transfer block, source increments every loop
1793  ***************************************************************/
tin()1794 inline void h6280_device::tin()
1795 {
1796 	clear_t();
1797 	int from = program_read16(PCW);
1798 	int to = program_read16(PCW + 2);
1799 	int length = program_read16(PCW + 4);
1800 	PCW+=6;
1801 	if (!length) length = 0x10000;
1802 	h6280_cycles( ((6 * length) + 17) );
1803 	while ((length--) != 0) {
1804 		program_write8(to, program_read8(from));
1805 		from++;
1806 	}
1807 }
1808 
1809 /* 6280 ********************************************************
1810  *  TMA Transfer memory mapper register(s) to accumulator
1811  *  the highest bit set in tmp is the one that counts
1812  ***************************************************************/
tma(uint8_t tmp)1813 inline void h6280_device::tma(uint8_t tmp)
1814 {
1815 	clear_t();
1816 	if (tmp&0x01) A = m_mmr[0];
1817 	if (tmp&0x02) A = m_mmr[1];
1818 	if (tmp&0x04) A = m_mmr[2];
1819 	if (tmp&0x08) A = m_mmr[3];
1820 	if (tmp&0x10) A = m_mmr[4];
1821 	if (tmp&0x20) A = m_mmr[5];
1822 	if (tmp&0x40) A = m_mmr[6];
1823 	if (tmp&0x80) A = m_mmr[7];
1824 }
1825 
1826 /* 6280 ********************************************************
1827  * TRB  Test and reset bits
1828  ***************************************************************/
trb(uint8_t tmp)1829 inline uint8_t h6280_device::trb(uint8_t tmp)
1830 {
1831 	clear_t();
1832 	P = (P & ~(_fN|_fV|_fT|_fZ))
1833 		| ((tmp&0x80) ? _fN:0)
1834 		| ((tmp&0x40) ? _fV:0)
1835 		| ((tmp&~A)  ? 0:_fZ);
1836 	tmp &= ~A;
1837 	return tmp;
1838 }
1839 
1840 /* 6280 ********************************************************
1841  * TSB  Test and set bits
1842  ***************************************************************/
tsb(uint8_t tmp)1843 inline uint8_t h6280_device::tsb(uint8_t tmp)
1844 {
1845 	clear_t();
1846 	P = (P & ~(_fN|_fV|_fT|_fZ))
1847 		| ((tmp&0x80) ? _fN:0)
1848 		| ((tmp&0x40) ? _fV:0)
1849 		| ((tmp|A)  ? 0:_fZ);
1850 	tmp |= A;
1851 	return tmp;
1852 }
1853 
1854 /* 6280 ********************************************************
1855  *  TSX Transfer stack LSB to index X
1856  ***************************************************************/
tsx()1857 inline void h6280_device::tsx()
1858 {
1859 	clear_t();
1860 	X = S;
1861 	set_nz(X);
1862 }
1863 
1864 /* 6280 ********************************************************
1865  *  TST
1866  ***************************************************************/
tst(uint8_t imm,uint8_t tmp)1867 inline void h6280_device::tst(uint8_t imm, uint8_t tmp)
1868 {
1869 	P = (P & ~(_fN|_fV|_fT|_fZ))
1870 		| ((tmp&0x80) ? _fN:0)
1871 		| ((tmp&0x40) ? _fV:0)
1872 		| ((tmp&imm)  ? 0:_fZ);
1873 }
1874 
1875 /* 6280 ********************************************************
1876  *  TXA Transfer index X to accumulator
1877  ***************************************************************/
txa()1878 inline void h6280_device::txa()
1879 {
1880 	clear_t();
1881 	A = X;
1882 	set_nz(A);
1883 }
1884 
1885 /* 6280 ********************************************************
1886  *  TXS Transfer index X to stack LSB
1887  *  no flags changed (sic!)
1888  ***************************************************************/
txs()1889 inline void h6280_device::txs()
1890 {
1891 	clear_t();
1892 	S = X;
1893 }
1894 
1895 /* 6280 ********************************************************
1896  *  TYA Transfer index Y to accumulator
1897  ***************************************************************/
tya()1898 inline void h6280_device::tya()
1899 {
1900 	clear_t();
1901 	A = Y;
1902 	set_nz(A);
1903 }
1904 
1905 /* 6280 ********************************************************
1906  * CSH Set CPU in high speed mode
1907  ***************************************************************/
csh()1908 inline void h6280_device::csh()
1909 {
1910 	m_clocks_per_cycle = 1;
1911 }
1912 
1913 /* 6280 ********************************************************
1914  * CSL Set CPU in low speed mode
1915  ***************************************************************/
csl()1916 inline void h6280_device::csl()
1917 {
1918 	m_clocks_per_cycle = 4;
1919 }
1920 
1921 
1922 #define OP(prefix,opcode)  void h6280_device::prefix##_##opcode()
1923 
1924 /*****************************************************************************
1925  *****************************************************************************
1926  *
1927  *   Hu6280 opcodes
1928  *
1929  *****************************************************************************
1930  *    op    cycles           opc                       ***********************/
1931 OP(op,00) { h6280_cycles(8); brk();                    } // 8 BRK
1932 OP(op,20) { h6280_cycles(7); ea_abs(); jsr();          } // 7 JSR  ABS
1933 OP(op,40) { h6280_cycles(7); rti();                    } // 7 RTI
1934 OP(op,60) { h6280_cycles(7); rts();                    } // 7 RTS
1935 OP(op,80) {                  bra(1);                   } // 4 BRA  REL
OP(op,a0)1936 OP(op,a0) { h6280_cycles(2); ldy(rd_imm());            } // 2 LDY  IMM
OP(op,c0)1937 OP(op,c0) { h6280_cycles(2); cpy(rd_imm());            } // 2 CPY  IMM
OP(op,e0)1938 OP(op,e0) { h6280_cycles(2); cpx(rd_imm());            } // 2 CPX  IMM
1939 
1940 OP(op,10) {                  bpl();                    } // 2/4 BPL  REL
1941 OP(op,30) {                  bmi();                    } // 2/4 BMI  REL
1942 OP(op,50) {                  bvc();                    } // 2/4 BVC  REL
1943 OP(op,70) {                  bvs();                    } // 2/4 BVS  REL
1944 OP(op,90) {                  bcc();                    } // 2/4 BCC  REL
OP(op,b0)1945 OP(op,b0) {                  bcs();                    } // 2/4 BCS  REL
OP(op,d0)1946 OP(op,d0) {                  bne();                    } // 2/4 BNE  REL
OP(op,f0)1947 OP(op,f0) {                  beq();                    } // 2/4 BEQ  REL
1948 
1949 OP(op,01) { h6280_cycles(7); ora(rd_idx());            } // 7 ORA  IDX
1950 OP(op,21) { h6280_cycles(7); and_a(rd_idx());          } // 7 AND  IDX
1951 OP(op,41) { h6280_cycles(7); eor(rd_idx());            } // 7 EOR  IDX
1952 OP(op,61) { h6280_cycles(7); adc(rd_idx());            } // 7 ADC  IDX
1953 OP(op,81) { h6280_cycles(7); wr_idx(sta());            } // 7 STA  IDX
OP(op,a1)1954 OP(op,a1) { h6280_cycles(7); lda(rd_idx());            } // 7 LDA  IDX
OP(op,c1)1955 OP(op,c1) { h6280_cycles(7); cmp(rd_idx());            } // 7 CMP  IDX
OP(op,e1)1956 OP(op,e1) { h6280_cycles(7); sbc(rd_idx());            } // 7 SBC  IDX
1957 
1958 OP(op,11) { h6280_cycles(7); ora(rd_idy());            } // 7 ORA  IDY
1959 OP(op,31) { h6280_cycles(7); and_a(rd_idy());          } // 7 AND  IDY
1960 OP(op,51) { h6280_cycles(7); eor(rd_idy());            } // 7 EOR  IDY
1961 OP(op,71) { h6280_cycles(7); adc(rd_idy());            } // 7 ADC  AZP
1962 OP(op,91) { h6280_cycles(7); wr_idy(sta());            } // 7 STA  IDY
OP(op,b1)1963 OP(op,b1) { h6280_cycles(7); lda(rd_idy());            } // 7 LDA  IDY
OP(op,d1)1964 OP(op,d1) { h6280_cycles(7); cmp(rd_idy());            } // 7 CMP  IDY
OP(op,f1)1965 OP(op,f1) { h6280_cycles(7); sbc(rd_idy());            } // 7 SBC  IDY
1966 
1967 OP(op,02) { h6280_cycles(3); sxy();                    } // 3 SXY
1968 OP(op,22) { h6280_cycles(3); sax();                    } // 3 SAX
1969 OP(op,42) { h6280_cycles(3); say();                    } // 3 SAY
1970 OP(op,62) { h6280_cycles(2); cla();                    } // 2 CLA
1971 OP(op,82) { h6280_cycles(2); clx();                    } // 2 CLX
OP(op,a2)1972 OP(op,a2) { h6280_cycles(2); ldx(rd_imm());            } // 2 LDX  IMM
OP(op,c2)1973 OP(op,c2) { h6280_cycles(2); cly();                    } // 2 CLY
OP(op,e2)1974 OP(op,e2) { h6280_cycles(2); nop();                    } // 2 NOP
1975 
1976 OP(op,12) { h6280_cycles(7); ora(rd_zpi());            } // 7 ORA  ZPI
1977 OP(op,32) { h6280_cycles(7); and_a(rd_zpi());          } // 7 AND  ZPI
1978 OP(op,52) { h6280_cycles(7); eor(rd_zpi());            } // 7 EOR  ZPI
1979 OP(op,72) { h6280_cycles(7); adc(rd_zpi());            } // 7 ADC  ZPI
1980 OP(op,92) { h6280_cycles(7); wr_zpi(sta());            } // 7 STA  ZPI
OP(op,b2)1981 OP(op,b2) { h6280_cycles(7); lda(rd_zpi());            } // 7 LDA  ZPI
OP(op,d2)1982 OP(op,d2) { h6280_cycles(7); cmp(rd_zpi());            } // 7 CMP  ZPI
OP(op,f2)1983 OP(op,f2) { h6280_cycles(7); sbc(rd_zpi());            } // 7 SBC  ZPI
1984 
1985 OP(op,03) { h6280_cycles(5); st0(rd_imm());            } // 4 + 1 penalty cycle ST0  IMM
1986 OP(op,23) { h6280_cycles(5); st2(rd_imm());            } // 4 + 1 penalty cycle ST2  IMM
1987 OP(op,43) { h6280_cycles(4); tma(rd_imm());            } // 4 TMA
1988 OP(op,63) { h6280_cycles(4); nop();                    } // 2 NOP
1989 OP(op,83) { h6280_cycles(7); int imm = rd_imm(); tst(imm, rd_zpg()); } // 7 TST  IMM,ZPG
OP(op,a3)1990 OP(op,a3) { h6280_cycles(7); int imm = rd_imm(); tst(imm, rd_zpx()); } // 7 TST  IMM,ZPX
OP(op,c3)1991 OP(op,c3) {                  tdd();                    } // 6*l+17 TDD  XFER
OP(op,e3)1992 OP(op,e3) {                  tia();                    } // 6*l+17 TIA  XFER
1993 
1994 OP(op,13) { h6280_cycles(5); st1(rd_imm());            } // 4 + 1 penalty cycle ST1
1995 OP(op,33) { h6280_cycles(2); nop();                    } // 2 NOP
1996 OP(op,53) { h6280_cycles(5); tam(rd_imm());            } // 5 TAM  IMM
1997 OP(op,73) {                  tii();                    } // 6*l+17 TII  XFER
1998 OP(op,93) { h6280_cycles(8); int imm = rd_imm(); tst(imm, rd_abs()); } // 8 TST  IMM,ABS
OP(op,b3)1999 OP(op,b3) { h6280_cycles(8); int imm = rd_imm(); tst(imm, rd_abx()); } // 8 TST  IMM,ABX
OP(op,d3)2000 OP(op,d3) {                  tin();                    } // 6*l+17 TIN  XFER
OP(op,f3)2001 OP(op,f3) {                  tai();                    } // 6*l+17 TAI  XFER
2002 
2003 OP(op,04) { h6280_cycles(6); wb_eaz(tsb(rd_zpg()));    } // 6 TSB  ZPG
2004 OP(op,24) { h6280_cycles(4); bit(rd_zpg());            } // 4 BIT  ZPG
2005 OP(op,44) {                  bsr();                    } // 8 BSR  REL
2006 OP(op,64) { h6280_cycles(4); wr_zpg(stz());            } // 4 STZ  ZPG
2007 OP(op,84) { h6280_cycles(4); wr_zpg(sty());            } // 4 STY  ZPG
OP(op,a4)2008 OP(op,a4) { h6280_cycles(4); ldy(rd_zpg());            } // 4 LDY  ZPG
OP(op,c4)2009 OP(op,c4) { h6280_cycles(4); cpy(rd_zpg());            } // 4 CPY  ZPG
OP(op,e4)2010 OP(op,e4) { h6280_cycles(4); cpx(rd_zpg());            } // 4 CPX  ZPG
2011 
2012 OP(op,14) { h6280_cycles(6); wb_eaz(trb(rd_zpg()));    } // 6 TRB  ZPG
2013 OP(op,34) { h6280_cycles(4); bit(rd_zpx());            } // 4 BIT  ZPX
2014 OP(op,54) { h6280_cycles(3); csl();                    } // 3 CSL
2015 OP(op,74) { h6280_cycles(4); wr_zpx(stz());            } // 4 STZ  ZPX
2016 OP(op,94) { h6280_cycles(4); wr_zpx(sty());            } // 4 STY  ZPX
OP(op,b4)2017 OP(op,b4) { h6280_cycles(4); ldy(rd_zpx());            } // 4 LDY  ZPX
OP(op,d4)2018 OP(op,d4) { h6280_cycles(3); csh();                    } // 3 CSH
OP(op,f4)2019 OP(op,f4) { h6280_cycles(2); set();                    } // 2 SET
2020 
2021 OP(op,05) { h6280_cycles(4); ora(rd_zpg());            } // 4 ORA  ZPG
2022 OP(op,25) { h6280_cycles(4); and_a(rd_zpg());          } // 4 AND  ZPG
2023 OP(op,45) { h6280_cycles(4); eor(rd_zpg());            } // 4 EOR  ZPG
2024 OP(op,65) { h6280_cycles(4); adc(rd_zpg());            } // 4 ADC  ZPG
2025 OP(op,85) { h6280_cycles(4); wr_zpg(sta());            } // 4 STA  ZPG
OP(op,a5)2026 OP(op,a5) { h6280_cycles(4); lda(rd_zpg());            } // 4 LDA  ZPG
OP(op,c5)2027 OP(op,c5) { h6280_cycles(4); cmp(rd_zpg());            } // 4 CMP  ZPG
OP(op,e5)2028 OP(op,e5) { h6280_cycles(4); sbc(rd_zpg());            } // 4 SBC  ZPG
2029 
2030 OP(op,15) { h6280_cycles(4); ora(rd_zpx());            } // 4 ORA  ZPX
2031 OP(op,35) { h6280_cycles(4); and_a(rd_zpx());          } // 4 AND  ZPX
2032 OP(op,55) { h6280_cycles(4); eor(rd_zpx());            } // 4 EOR  ZPX
2033 OP(op,75) { h6280_cycles(4); adc(rd_zpx());            } // 4 ADC  ZPX
2034 OP(op,95) { h6280_cycles(4); wr_zpx(sta());            } // 4 STA  ZPX
OP(op,b5)2035 OP(op,b5) { h6280_cycles(4); lda(rd_zpx());            } // 4 LDA  ZPX
OP(op,d5)2036 OP(op,d5) { h6280_cycles(4); cmp(rd_zpx());            } // 4 CMP  ZPX
OP(op,f5)2037 OP(op,f5) { h6280_cycles(4); sbc(rd_zpx());            } // 4 SBC  ZPX
2038 
2039 OP(op,06) { h6280_cycles(6); wb_eaz(asl(rd_zpg()));    } // 6 ASL  ZPG
2040 OP(op,26) { h6280_cycles(6); wb_eaz(rol(rd_zpg()));    } // 6 ROL  ZPG
2041 OP(op,46) { h6280_cycles(6); wb_eaz(lsr(rd_zpg()));    } // 6 LSR  ZPG
2042 OP(op,66) { h6280_cycles(6); wb_eaz(ror(rd_zpg()));    } // 6 ROR  ZPG
2043 OP(op,86) { h6280_cycles(4); wr_zpg(stx());            } // 4 STX  ZPG
OP(op,a6)2044 OP(op,a6) { h6280_cycles(4); ldx(rd_zpg());            } // 4 LDX  ZPG
OP(op,c6)2045 OP(op,c6) { h6280_cycles(6); wb_eaz(dec(rd_zpg()));    } // 6 DEC  ZPG
OP(op,e6)2046 OP(op,e6) { h6280_cycles(6); wb_eaz(inc(rd_zpg()));    } // 6 INC  ZPG
2047 
2048 OP(op,16) { h6280_cycles(6); wb_eaz(asl(rd_zpx()));    } // 6 ASL  ZPX
2049 OP(op,36) { h6280_cycles(6); wb_eaz(rol(rd_zpx()));    } // 6 ROL  ZPX
2050 OP(op,56) { h6280_cycles(6); wb_eaz(lsr(rd_zpx()));    } // 6 LSR  ZPX
2051 OP(op,76) { h6280_cycles(6); wb_eaz(ror(rd_zpx()));    } // 6 ROR  ZPX
2052 OP(op,96) { h6280_cycles(4); wr_zpy(stx());            } // 4 STX  ZPY
OP(op,b6)2053 OP(op,b6) { h6280_cycles(4); ldx(rd_zpy());            } // 4 LDX  ZPY
OP(op,d6)2054 OP(op,d6) { h6280_cycles(6); wb_eaz(dec(rd_zpx()));    } // 6 DEC  ZPX
OP(op,f6)2055 OP(op,f6) { h6280_cycles(6); wb_eaz(inc(rd_zpx()));    } // 6 INC  ZPX
2056 
2057 OP(op,07) { h6280_cycles(7); wb_eaz(rmb(0, rd_zpg())); } // 7 RMB0 ZPG
2058 OP(op,27) { h6280_cycles(7); wb_eaz(rmb(2, rd_zpg())); } // 7 RMB2 ZPG
2059 OP(op,47) { h6280_cycles(7); wb_eaz(rmb(4, rd_zpg())); } // 7 RMB4 ZPG
2060 OP(op,67) { h6280_cycles(7); wb_eaz(rmb(6, rd_zpg())); } // 7 RMB6 ZPG
2061 OP(op,87) { h6280_cycles(7); wb_eaz(smb(0, rd_zpg())); } // 7 SMB0 ZPG
OP(op,a7)2062 OP(op,a7) { h6280_cycles(7); wb_eaz(smb(2, rd_zpg())); } // 7 SMB2 ZPG
OP(op,c7)2063 OP(op,c7) { h6280_cycles(7); wb_eaz(smb(4, rd_zpg())); } // 7 SMB4 ZPG
OP(op,e7)2064 OP(op,e7) { h6280_cycles(7); wb_eaz(smb(6, rd_zpg())); } // 7 SMB6 ZPG
2065 
2066 OP(op,17) { h6280_cycles(7); wb_eaz(rmb(1, rd_zpg())); } // 7 RMB1 ZPG
2067 OP(op,37) { h6280_cycles(7); wb_eaz(rmb(3, rd_zpg())); } // 7 RMB3 ZPG
2068 OP(op,57) { h6280_cycles(7); wb_eaz(rmb(5, rd_zpg())); } // 7 RMB5 ZPG
2069 OP(op,77) { h6280_cycles(7); wb_eaz(rmb(7, rd_zpg())); } // 7 RMB7 ZPG
2070 OP(op,97) { h6280_cycles(7); wb_eaz(smb(1, rd_zpg())); } // 7 SMB1 ZPG
OP(op,b7)2071 OP(op,b7) { h6280_cycles(7); wb_eaz(smb(3, rd_zpg())); } // 7 SMB3 ZPG
OP(op,d7)2072 OP(op,d7) { h6280_cycles(7); wb_eaz(smb(5, rd_zpg())); } // 7 SMB5 ZPG
OP(op,f7)2073 OP(op,f7) { h6280_cycles(7); wb_eaz(smb(7, rd_zpg())); } // 7 SMB7 ZPG
2074 
2075 OP(op,08) { h6280_cycles(3); php();                    } // 3 PHP
2076 OP(op,28) { h6280_cycles(4); plp();                    } // 4 PLP
2077 OP(op,48) { h6280_cycles(3); pha();                    } // 3 PHA
2078 OP(op,68) { h6280_cycles(4); pla();                    } // 4 PLA
2079 OP(op,88) { h6280_cycles(2); dey();                    } // 2 DEY
OP(op,a8)2080 OP(op,a8) { h6280_cycles(2); tay();                    } // 2 TAY
OP(op,c8)2081 OP(op,c8) { h6280_cycles(2); iny();                    } // 2 INY
OP(op,e8)2082 OP(op,e8) { h6280_cycles(2); inx();                    } // 2 INX
2083 
2084 OP(op,18) { h6280_cycles(2); clc();                    } // 2 CLC
2085 OP(op,38) { h6280_cycles(2); sec();                    } // 2 SEC
2086 OP(op,58) { h6280_cycles(2); cli();                    } // 2 CLI
2087 OP(op,78) { h6280_cycles(2); sei();                    } // 2 SEI
2088 OP(op,98) { h6280_cycles(2); tya();                    } // 2 TYA
OP(op,b8)2089 OP(op,b8) { h6280_cycles(2); clv();                    } // 2 CLV
OP(op,d8)2090 OP(op,d8) { h6280_cycles(2); cld();                    } // 2 CLD
OP(op,f8)2091 OP(op,f8) { h6280_cycles(2); sed();                    } // 2 SED
2092 
2093 OP(op,09) { h6280_cycles(2); ora(rd_imm());            } // 2 ORA  IMM
2094 OP(op,29) { h6280_cycles(2); and_a(rd_imm());          } // 2 AND  IMM
2095 OP(op,49) { h6280_cycles(2); eor(rd_imm());            } // 2 EOR  IMM
2096 OP(op,69) { h6280_cycles(2); adc(rd_imm());            } // 2 ADC  IMM
2097 OP(op,89) { h6280_cycles(2); bit(rd_imm());            } // 2 BIT  IMM
OP(op,a9)2098 OP(op,a9) { h6280_cycles(2); lda(rd_imm());            } // 2 LDA  IMM
OP(op,c9)2099 OP(op,c9) { h6280_cycles(2); cmp(rd_imm());            } // 2 CMP  IMM
OP(op,e9)2100 OP(op,e9) { h6280_cycles(2); sbc(rd_imm());            } // 2 SBC  IMM
2101 
2102 OP(op,19) { h6280_cycles(5); ora(rd_aby());            } // 5 ORA  ABY
2103 OP(op,39) { h6280_cycles(5); and_a(rd_aby());          } // 5 AND  ABY
2104 OP(op,59) { h6280_cycles(5); eor(rd_aby());            } // 5 EOR  ABY
2105 OP(op,79) { h6280_cycles(5); adc(rd_aby());            } // 5 ADC  ABY
2106 OP(op,99) { h6280_cycles(5); wr_aby(sta());            } // 5 STA  ABY
OP(op,b9)2107 OP(op,b9) { h6280_cycles(5); lda(rd_aby());            } // 5 LDA  ABY
OP(op,d9)2108 OP(op,d9) { h6280_cycles(5); cmp(rd_aby());            } // 5 CMP  ABY
OP(op,f9)2109 OP(op,f9) { h6280_cycles(5); sbc(rd_aby());            } // 5 SBC  ABY
2110 
2111 OP(op,0a) { h6280_cycles(2); A = asl(A);               } // 2 ASL  A
2112 OP(op,2a) { h6280_cycles(2); A = rol(A);               } // 2 ROL  A
2113 OP(op,4a) { h6280_cycles(2); A = lsr(A);               } // 2 LSR  A
2114 OP(op,6a) { h6280_cycles(2); A = ror(A);               } // 2 ROR  A
2115 OP(op,8a) { h6280_cycles(2); txa();                    } // 2 TXA
OP(op,aa)2116 OP(op,aa) { h6280_cycles(2); tax();                    } // 2 TAX
OP(op,ca)2117 OP(op,ca) { h6280_cycles(2); dex();                    } // 2 DEX
OP(op,ea)2118 OP(op,ea) { h6280_cycles(2); nop();                    } // 2 NOP
2119 
2120 OP(op,1a) { h6280_cycles(2); A = inc(A);               } // 2 INC  A
2121 OP(op,3a) { h6280_cycles(2); A = dec(A);               } // 2 DEC  A
2122 OP(op,5a) { h6280_cycles(3); phy();                    } // 3 PHY
2123 OP(op,7a) { h6280_cycles(4); ply();                    } // 4 PLY
2124 OP(op,9a) { h6280_cycles(2); txs();                    } // 2 TXS
OP(op,ba)2125 OP(op,ba) { h6280_cycles(2); tsx();                    } // 2 TSX
OP(op,da)2126 OP(op,da) { h6280_cycles(3); phx();                    } // 3 PHX
OP(op,fa)2127 OP(op,fa) { h6280_cycles(4); plx();                    } // 4 PLX
2128 
2129 OP(op,0b) { h6280_cycles(2); nop();                    } // 2 NOP
2130 OP(op,2b) { h6280_cycles(2); nop();                    } // 2 NOP
2131 OP(op,4b) { h6280_cycles(2); nop();                    } // 2 NOP
2132 OP(op,6b) { h6280_cycles(2); nop();                    } // 2 NOP
2133 OP(op,8b) { h6280_cycles(2); nop();                    } // 2 NOP
OP(op,ab)2134 OP(op,ab) { h6280_cycles(2); nop();                    } // 2 NOP
OP(op,cb)2135 OP(op,cb) { h6280_cycles(2); nop();                    } // 2 NOP
OP(op,eb)2136 OP(op,eb) { h6280_cycles(2); nop();                    } // 2 NOP
2137 
2138 OP(op,1b) { h6280_cycles(2); nop();                    } // 2 NOP
2139 OP(op,3b) { h6280_cycles(2); nop();                    } // 2 NOP
2140 OP(op,5b) { h6280_cycles(2); nop();                    } // 2 NOP
2141 OP(op,7b) { h6280_cycles(2); nop();                    } // 2 NOP
2142 OP(op,9b) { h6280_cycles(2); nop();                    } // 2 NOP
OP(op,bb)2143 OP(op,bb) { h6280_cycles(2); nop();                    } // 2 NOP
OP(op,db)2144 OP(op,db) { h6280_cycles(2); nop();                    } // 2 NOP
OP(op,fb)2145 OP(op,fb) { h6280_cycles(2); nop();                    } // 2 NOP
2146 
2147 OP(op,0c) { h6280_cycles(7); wb_ea(tsb(rd_abs()));     } // 7 TSB  ABS
2148 OP(op,2c) { h6280_cycles(5); bit(rd_abs());            } // 5 BIT  ABS
2149 OP(op,4c) { h6280_cycles(4); ea_abs(); jmp();          } // 4 JMP  ABS
2150 OP(op,6c) { h6280_cycles(7); ea_ind(); jmp();          } // 7 JMP  IND
2151 OP(op,8c) { h6280_cycles(5); wr_abs(sty());            } // 5 STY  ABS
OP(op,ac)2152 OP(op,ac) { h6280_cycles(5); ldy(rd_abs());            } // 5 LDY  ABS
OP(op,cc)2153 OP(op,cc) { h6280_cycles(5); cpy(rd_abs());            } // 5 CPY  ABS
OP(op,ec)2154 OP(op,ec) { h6280_cycles(5); cpx(rd_abs());            } // 5 CPX  ABS
2155 
2156 OP(op,1c) { h6280_cycles(7); wb_ea(trb(rd_abs()));     } // 7 TRB  ABS
2157 OP(op,3c) { h6280_cycles(5); bit(rd_abx());            } // 5 BIT  ABX
2158 OP(op,5c) { h6280_cycles(2); nop();                    } // 2 NOP
2159 OP(op,7c) { h6280_cycles(7); ea_iax(); jmp();          } // 7 JMP  IAX
2160 OP(op,9c) { h6280_cycles(5); wr_abs(stz());            } // 5 STZ  ABS
OP(op,bc)2161 OP(op,bc) { h6280_cycles(5); ldy(rd_abx());            } // 5 LDY  ABX
OP(op,dc)2162 OP(op,dc) { h6280_cycles(2); nop();                    } // 2 NOP
OP(op,fc)2163 OP(op,fc) { h6280_cycles(2); nop();                    } // 2 NOP
2164 
2165 OP(op,0d) { h6280_cycles(5); ora(rd_abs());            } // 5 ORA  ABS
2166 OP(op,2d) { h6280_cycles(5); and_a(rd_abs());          } // 5 AND  ABS
2167 OP(op,4d) { h6280_cycles(5); eor(rd_abs());            } // 5 EOR  ABS
2168 OP(op,6d) { h6280_cycles(5); adc(rd_abs());            } // 5 ADC  ABS
2169 OP(op,8d) { h6280_cycles(5); wr_abs(sta());            } // 5 STA  ABS
OP(op,ad)2170 OP(op,ad) { h6280_cycles(5); lda(rd_abs());            } // 5 LDA  ABS
OP(op,cd)2171 OP(op,cd) { h6280_cycles(5); cmp(rd_abs());            } // 5 CMP  ABS
OP(op,ed)2172 OP(op,ed) { h6280_cycles(5); sbc(rd_abs());            } // 5 SBC  ABS
2173 
2174 OP(op,1d) { h6280_cycles(5); ora(rd_abx());            } // 5 ORA  ABX
2175 OP(op,3d) { h6280_cycles(5); and_a(rd_abx());          } // 5 AND  ABX
2176 OP(op,5d) { h6280_cycles(5); eor(rd_abx());            } // 5 EOR  ABX
2177 OP(op,7d) { h6280_cycles(5); adc(rd_abx());            } // 5 ADC  ABX
2178 OP(op,9d) { h6280_cycles(5); wr_abx(sta());            } // 5 STA  ABX
OP(op,bd)2179 OP(op,bd) { h6280_cycles(5); lda(rd_abx());            } // 5 LDA  ABX
OP(op,dd)2180 OP(op,dd) { h6280_cycles(5); cmp(rd_abx());            } // 5 CMP  ABX
OP(op,fd)2181 OP(op,fd) { h6280_cycles(5); sbc(rd_abx());            } // 5 SBC  ABX
2182 
2183 OP(op,0e) { h6280_cycles(7); wb_ea(asl(rd_abs()));     } // 7 ASL  ABS
2184 OP(op,2e) { h6280_cycles(7); wb_ea(rol(rd_abs()));     } // 7 ROL  ABS
2185 OP(op,4e) { h6280_cycles(7); wb_ea(lsr(rd_abs()));     } // 7 LSR  ABS
2186 OP(op,6e) { h6280_cycles(7); wb_ea(ror(rd_abs()));     } // 7 ROR  ABS
2187 OP(op,8e) { h6280_cycles(5); wr_abs(stx());            } // 5 STX  ABS
OP(op,ae)2188 OP(op,ae) { h6280_cycles(5); ldx(rd_abs());            } // 5 LDX  ABS
OP(op,ce)2189 OP(op,ce) { h6280_cycles(7); wb_ea(dec(rd_abs()));     } // 7 DEC  ABS
OP(op,ee)2190 OP(op,ee) { h6280_cycles(7); wb_ea(inc(rd_abs()));     } // 7 INC  ABS
2191 
2192 OP(op,1e) { h6280_cycles(7); wb_ea(asl(rd_abx()));     } // 7 ASL  ABX
2193 OP(op,3e) { h6280_cycles(7); wb_ea(rol(rd_abx()));     } // 7 ROL  ABX
2194 OP(op,5e) { h6280_cycles(7); wb_ea(lsr(rd_abx()));     } // 7 LSR  ABX
2195 OP(op,7e) { h6280_cycles(7); wb_ea(ror(rd_abx()));     } // 7 ROR  ABX
2196 OP(op,9e) { h6280_cycles(5); wr_abx(stz());            } // 5 STZ  ABX
OP(op,be)2197 OP(op,be) { h6280_cycles(5); ldx(rd_aby());            } // 5 LDX  ABY
OP(op,de)2198 OP(op,de) { h6280_cycles(7); wb_ea(dec(rd_abx()));     } // 7 DEC  ABX
OP(op,fe)2199 OP(op,fe) { h6280_cycles(7); wb_ea(inc(rd_abx()));     } // 7 INC  ABX
2200 
2201 OP(op,0f) { h6280_cycles(4); bbr(0, rd_zpg());         } // 6/8 BBR0 ZPG,REL
2202 OP(op,2f) { h6280_cycles(4); bbr(2, rd_zpg());         } // 6/8 BBR2 ZPG,REL
2203 OP(op,4f) { h6280_cycles(4); bbr(4, rd_zpg());         } // 6/8 BBR4 ZPG,REL
2204 OP(op,6f) { h6280_cycles(4); bbr(6, rd_zpg());         } // 6/8 BBR6 ZPG,REL
2205 OP(op,8f) { h6280_cycles(4); bbs(0, rd_zpg());         } // 6/8 BBS0 ZPG,REL
OP(op,af)2206 OP(op,af) { h6280_cycles(4); bbs(2, rd_zpg());         } // 6/8 BBS2 ZPG,REL
OP(op,cf)2207 OP(op,cf) { h6280_cycles(4); bbs(4, rd_zpg());         } // 6/8 BBS4 ZPG,REL
OP(op,ef)2208 OP(op,ef) { h6280_cycles(4); bbs(6, rd_zpg());         } // 6/8 BBS6 ZPG,REL
2209 
2210 OP(op,1f) { h6280_cycles(4); bbr(1, rd_zpg());         } // 6/8 BBR1 ZPG,REL
2211 OP(op,3f) { h6280_cycles(4); bbr(3, rd_zpg());         } // 6/8 BBR3 ZPG,REL
2212 OP(op,5f) { h6280_cycles(4); bbr(5, rd_zpg());         } // 6/8 BBR5 ZPG,REL
2213 OP(op,7f) { h6280_cycles(4); bbr(7, rd_zpg());         } // 6/8 BBR7 ZPG,REL
2214 OP(op,9f) { h6280_cycles(4); bbs(1, rd_zpg());         } // 6/8 BBS1 ZPG,REL
OP(op,bf)2215 OP(op,bf) { h6280_cycles(4); bbs(3, rd_zpg());         } // 6/8 BBS3 ZPG,REL
OP(op,df)2216 OP(op,df) { h6280_cycles(4); bbs(5, rd_zpg());         } // 6/8 BBS5 ZPG,REL
OP(op,ff)2217 OP(op,ff) { h6280_cycles(4); bbs(7, rd_zpg());         } // 6/8 BBS7 ZPG,REL
2218 
2219 //-------------------------------------------------
2220 //  state_string_export - export state as a string
2221 //  for the debugger
2222 //-------------------------------------------------
2223 
state_string_export(const device_state_entry & entry,std::string & str) const2224 void h6280_device::state_string_export(const device_state_entry &entry, std::string &str) const
2225 {
2226 	switch (entry.index())
2227 	{
2228 		case STATE_GENFLAGS:
2229 			str = string_format("%c%c%c%c%c%c%c%c",
2230 				(m_p & 0x80) ? 'N':'.',
2231 				(m_p & 0x40) ? 'V':'.',
2232 				(m_p & 0x20) ? 'R':'.',
2233 				(m_p & 0x10) ? 'B':'.',
2234 				(m_p & 0x08) ? 'D':'.',
2235 				(m_p & 0x04) ? 'I':'.',
2236 				(m_p & 0x02) ? 'Z':'.',
2237 				(m_p & 0x01) ? 'C':'.');
2238 			break;
2239 	}
2240 }
2241 
2242 
2243 //-------------------------------------------------
2244 //  disassemble - call the disassembly
2245 //  helper function
2246 //-------------------------------------------------
2247 
create_disassembler()2248 std::unique_ptr<util::disasm_interface> h6280_device::create_disassembler()
2249 {
2250 	return std::make_unique<h6280_disassembler>();
2251 }
2252 
2253 
2254 //-------------------------------------------------
2255 //  execute_min_cycles - return minimum number of
2256 //  cycles it takes for one instruction to execute
2257 //-------------------------------------------------
2258 
execute_min_cycles() const2259 uint32_t h6280_device::execute_min_cycles() const noexcept
2260 {
2261 	return 2;
2262 }
2263 
2264 
2265 //-------------------------------------------------
2266 //  execute_max_cycles - return maximum number of
2267 //  cycles it takes for one instruction to execute
2268 //-------------------------------------------------
2269 
execute_max_cycles() const2270 uint32_t h6280_device::execute_max_cycles() const noexcept
2271 {
2272 	return 17 + 6*65536;
2273 }
2274 
2275 
2276 //-------------------------------------------------
2277 //  execute_input_lines - return the number of
2278 //  input/interrupt lines
2279 //-------------------------------------------------
2280 
execute_input_lines() const2281 uint32_t h6280_device::execute_input_lines() const noexcept
2282 {
2283 	return 4;
2284 }
2285 
2286 
2287 //-------------------------------------------------
2288 //  execute_input_edge_triggered - return true if
2289 //  the input line has an asynchronous edge trigger
2290 //-------------------------------------------------
2291 
execute_input_edge_triggered(int inputnum) const2292 bool h6280_device::execute_input_edge_triggered(int inputnum) const noexcept
2293 {
2294 	return inputnum == H6280_NMI_STATE;
2295 }
2296 
2297 
2298 //-------------------------------------------------
2299 //  execute_set_input - act on a changed input/
2300 //  interrupt line
2301 //-------------------------------------------------
2302 
execute_set_input(int inputnum,int state)2303 void h6280_device::execute_set_input(int inputnum, int state)
2304 {
2305 	switch(inputnum)
2306 	{
2307 		case H6280_IRQ1_STATE:
2308 		case 0:
2309 			set_irq_line(0, state);
2310 			break;
2311 		case H6280_IRQ2_STATE:
2312 		case 1:
2313 			set_irq_line(1, state);
2314 			break;
2315 		case H6280_IRQT_STATE:
2316 		case 2:
2317 			set_irq_line(2, state);
2318 			break;
2319 		case H6280_NMI_STATE:
2320 		case INPUT_LINE_NMI:
2321 			set_irq_line(INPUT_LINE_NMI, state);
2322 			break;
2323 	}
2324 }
2325 
2326 /***************************************************************
2327  *  program_read8       read memory
2328  ***************************************************************/
program_read8(offs_t addr)2329 uint8_t h6280_device::program_read8(offs_t addr)
2330 {
2331 	check_vdc_vce_penalty(addr);
2332 	return m_program.read_byte(translated(addr));
2333 }
2334 
2335 /***************************************************************
2336  *  program_write8      write memory
2337  ***************************************************************/
program_write8(offs_t addr,uint8_t data)2338 void h6280_device::program_write8(offs_t addr, uint8_t data)
2339 {
2340 	check_vdc_vce_penalty(addr);
2341 	m_program.write_byte(translated(addr), data);
2342 }
2343 
2344 /***************************************************************
2345  *  program_read8z      read memory - zero page
2346  ***************************************************************/
program_read8z(offs_t addr)2347 uint8_t h6280_device::program_read8z(offs_t addr)
2348 {
2349 	return m_program.read_byte((m_mmr[1] << 13) | (addr & 0x1fff));
2350 }
2351 
2352 /***************************************************************
2353  *  program_write8z     write memory - zero page
2354  ***************************************************************/
program_write8z(offs_t addr,uint8_t data)2355 void h6280_device::program_write8z(offs_t addr, uint8_t data)
2356 {
2357 	m_program.write_byte((m_mmr[1] << 13) | (addr & 0x1fff), data);
2358 }
2359 
2360 /***************************************************************
2361  *  program_read16      read word from memory
2362  ***************************************************************/
program_read16(offs_t addr)2363 uint16_t h6280_device::program_read16(offs_t addr)
2364 {
2365 	return m_program.read_byte(translated(addr)) |
2366 			(m_program.read_byte(translated(addr + 1)) << 8);
2367 }
2368 
2369 /***************************************************************
2370  *  program_read16z     read a word from a zero page address
2371  ***************************************************************/
program_read16z(offs_t addr)2372 uint16_t h6280_device::program_read16z(offs_t addr)
2373 {
2374 	if ((addr & 0xff) == 0xff)
2375 	{
2376 		return m_program.read_byte((m_mmr[1] << 13) | (addr & 0x1fff)) |
2377 				(m_program.read_byte((m_mmr[1] << 13) | ((addr - 0xff) & 0x1fff)) << 8);
2378 	}
2379 	else
2380 	{
2381 		return m_program.read_byte((m_mmr[1] << 13) | (addr & 0x1fff)) |
2382 				(m_program.read_byte((m_mmr[1] << 13) | ((addr + 1) & 0x1fff)) << 8);
2383 	}
2384 }
2385 
2386 /***************************************************************
2387  * push a register onto the stack
2388  ***************************************************************/
push(uint8_t value)2389 void h6280_device::push(uint8_t value)
2390 {
2391 	m_program.write_byte((m_mmr[1] << 13) | m_sp.d, value);
2392 	S--;
2393 }
2394 
2395 /***************************************************************
2396  * pull a register from the stack
2397  ***************************************************************/
pull(uint8_t & value)2398 void h6280_device::pull(uint8_t &value)
2399 {
2400 	S++;
2401 	value = m_program.read_byte((m_mmr[1] << 13) | m_sp.d);
2402 }
2403 
2404 /***************************************************************
2405  *  read_opcode     read an opcode
2406  ***************************************************************/
read_opcode()2407 uint8_t h6280_device::read_opcode()
2408 {
2409 	return m_cache.read_byte(translated(PCW));
2410 }
2411 
2412 /***************************************************************
2413  *  read_opcode_arg read an opcode argument
2414  ***************************************************************/
read_opcode_arg()2415 uint8_t h6280_device::read_opcode_arg()
2416 {
2417 	return m_cache.read_byte(translated(PCW));
2418 }
2419 
2420 
2421 //-------------------------------------------------
2422 //  execute_run - execute a timeslice's worth of
2423 //  opcodes
2424 //-------------------------------------------------
2425 
execute_run()2426 void h6280_device::execute_run()
2427 {
2428 	int in;
2429 
2430 	if (m_irq_pending == 2)
2431 	{
2432 		m_irq_pending--;
2433 	}
2434 
2435 	/* Execute instructions */
2436 	do
2437 	{
2438 		m_ppc = m_pc;
2439 
2440 		debugger_instruction_hook(PCW);
2441 
2442 		/* Execute 1 instruction */
2443 		in = read_opcode();
2444 		PCW++;
2445 		(this->*m_opcode[in])();
2446 
2447 		if (m_irq_pending)
2448 		{
2449 			if (m_irq_pending == 1)
2450 			{
2451 				if (!(P & _fI))
2452 				{
2453 					m_irq_pending--;
2454 					check_and_take_irq_lines();
2455 				}
2456 			}
2457 			else
2458 			{
2459 				m_irq_pending--;
2460 			}
2461 		}
2462 
2463 		/* Check internal timer */
2464 		if (m_timer_status)
2465 		{
2466 			if (m_timer_value<=0)
2467 			{
2468 				if (!m_irq_pending)
2469 				{
2470 					m_irq_pending = 1;
2471 				}
2472 				while (m_timer_value <= 0)
2473 				{
2474 					m_timer_value += m_timer_load;
2475 				}
2476 				set_irq_line(2, ASSERT_LINE);
2477 			}
2478 		}
2479 	} while (m_icount > 0);
2480 }
2481 
2482 
2483 //**************************************************************************
2484 //  IRQ HANDLING
2485 //**************************************************************************
2486 
set_irq_line(int irqline,int state)2487 void h6280_device::set_irq_line(int irqline, int state)
2488 {
2489 	if (irqline == INPUT_LINE_NMI)
2490 	{
2491 		if (state != ASSERT_LINE)
2492 			return;
2493 		m_nmi_state = state;
2494 		check_irq_lines();
2495 	}
2496 	else if (irqline < 3)
2497 	{
2498 		/* If the state has not changed, just return */
2499 		if (m_irq_state[irqline] == state)
2500 			return;
2501 
2502 		m_irq_state[irqline] = state;
2503 
2504 		check_irq_lines();
2505 	}
2506 }
2507 
2508 
2509 //**************************************************************************
2510 //  REGISTER HANDLING
2511 //**************************************************************************
2512 
irq_status_r(offs_t offset)2513 uint8_t h6280_device::irq_status_r(offs_t offset)
2514 {
2515 	int status;
2516 
2517 	switch (offset & 3)
2518 	{
2519 	default:
2520 		return m_io_buffer;
2521 	case 3:
2522 		{
2523 			status = 0;
2524 			if (m_irq_state[1] != CLEAR_LINE)
2525 				status |= 1; /* IRQ 2 */
2526 			if (m_irq_state[0] != CLEAR_LINE)
2527 				status |= 2; /* IRQ 1 */
2528 			if (m_irq_state[2] != CLEAR_LINE)
2529 				status |= 4; /* TIMER */
2530 			return status | (m_io_buffer & (~H6280_IRQ_MASK));
2531 		}
2532 	case 2:
2533 		return m_irq_mask | (m_io_buffer & (~H6280_IRQ_MASK));
2534 	}
2535 }
2536 
irq_status_w(offs_t offset,uint8_t data)2537 void h6280_device::irq_status_w(offs_t offset, uint8_t data)
2538 {
2539 	m_io_buffer = data;
2540 	switch (offset & 3)
2541 	{
2542 		default:
2543 			m_io_buffer = data;
2544 			break;
2545 
2546 		case 2: /* Write irq mask */
2547 			m_irq_mask = data & 0x7;
2548 			check_irq_lines();
2549 			break;
2550 
2551 		case 3: /* Timer irq ack */
2552 			set_irq_line(2, CLEAR_LINE);
2553 			break;
2554 	}
2555 }
2556 
timer_r()2557 uint8_t h6280_device::timer_r()
2558 {
2559 	/* only returns countdown */
2560 	return ((m_timer_value >> 10) & 0x7F) | (m_io_buffer & 0x80);
2561 }
2562 
timer_w(offs_t offset,uint8_t data)2563 void h6280_device::timer_w(offs_t offset, uint8_t data)
2564 {
2565 	m_io_buffer = data;
2566 	switch (offset & 1)
2567 	{
2568 		case 0: /* Counter preload */
2569 			// matches HW behaviour, value is latched only with 0->1 counter enable transition
2570 			m_timer_load = ((data & 127) + 1) * 1024 * m_timer_scale;
2571 			return;
2572 
2573 		case 1: /* Counter enable */
2574 			if (data & 1)
2575 			{/* stop -> start causes reload */
2576 				if(m_timer_status == 0)
2577 					m_timer_value = m_timer_load;
2578 			}
2579 			m_timer_status = data & 1;
2580 			return;
2581 	}
2582 }
2583 
port_r()2584 uint8_t h6280_device::port_r()
2585 {
2586 	if (!m_port_in_cb.isnull())
2587 		return m_port_in_cb();
2588 	else
2589 		return m_io_buffer;
2590 }
2591 
port_w(uint8_t data)2592 void h6280_device::port_w(uint8_t data)
2593 {
2594 	m_io_buffer = data;
2595 
2596 	m_port_out_cb(data);
2597 }
2598 
io_buffer_r()2599 uint8_t h6280_device::io_buffer_r()
2600 {
2601 	return m_io_buffer;
2602 }
2603 
psg_w(offs_t offset,uint8_t data)2604 void h6280_device::psg_w(offs_t offset, uint8_t data)
2605 {
2606 	m_io_buffer = data;
2607 	m_psg->c6280_w(offset, data);
2608 }
2609 
memory_translate(int spacenum,int intention,offs_t & address)2610 bool h6280_device::memory_translate(int spacenum, int intention, offs_t &address)
2611 {
2612 	if (spacenum == AS_PROGRAM)
2613 		address = translated(address);
2614 
2615 	return true;
2616 }
2617 
io_get_buffer()2618 uint8_t h6280_device::io_get_buffer()
2619 {
2620 	return m_io_buffer;
2621 }
2622 
io_set_buffer(uint8_t data)2623 void h6280_device::io_set_buffer(uint8_t data)
2624 {
2625 	m_io_buffer = data;
2626 }
2627