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