1 // license:BSD-3-Clause
2 // copyright-holders:R. Belmont, Karl Stenerud
3 /* ======================================================================== */
4 /* =============================== COPYRIGHT ============================== */
5 /* ======================================================================== */
6 /*
7
8 Sony/Nintendo SPC700 CPU Emulator
9
10 The SPC700 is 6502-based at heart but contains a lot of the extended
11 opcodes of the Mitsubishi 770 and 7700 series 65xxx-based MCUs, plus
12 a few special twists borrowed from the 68000.
13
14 It was designed by Sony's Ken Kutaragi, later the "father of the PlayStation".
15
16 Original emulation by Anthony Kruize and Lee Hammerton.
17 Substantially revised by R. Belmont.
18
19 Thanks to Anonymous, TRAC, Brad Martin, anomie, Blargg, and everyone
20 else on ZSNES Technical for probing the darker corners of the SNES
21 with test programs so we have a chance at getting things accurate.
22
23 MESS Bugzilla bugs:
24 - 804 ADC sets carry too late (FIXED)
25 - 805 ADDW/SUBW set V wrongly (FIXED)
26 - 806 BRK should modify PSW (FIXED)
27 - 807 DAA/DAS problem (FIXED)
28
29
30 */
31 /* ======================================================================== */
32 /* ================================= NOTES ================================ */
33 /* ======================================================================== */
34 /*
35
36 snes mapped ports: f0-ff
37 Address Function Register R/W When Reset Remarks
38
39 00F0H (test) --- ------ Installed in sound-CPU
40 00F1H Control W Control = "00-000"
41 00F2H Register Add. R/W Indeterminate Installed in DSP
42 00F3H Register Data R/W Indeterminate Installed in DSP
43 00F4H Port-0 R/W Port0r = "00" Installed in sound-CPU
44 Port0w = "00"
45 00F5H Port-1 R/W Port1r = "00" Installed in sound-CPU
46 Port1w = "00"
47 00F6H Port-2 R/W Port2r = "00" Installed in sound-CPU
48 Port2w = "00"
49 00F7H Port-3 R/W Port3r = "00" Installed in sound-CPU
50 Port3w = "00"
51 00F8H ------ --- ---------- -------------------
52 00F9H ------ --- ---------- -------------------
53 00FAH Timer-0 W Indeterminate Installed in sound-CPU
54 00FBH Timer-1 W Indeterminate Installed in sound-CPU
55 00FCH Timer-2 W Indeterminate Installed in sound-CPU
56 00FDH Counter-0 W Indeterminate Installed in sound-CPU
57 00FEH Counter-1 W Indeterminate Installed in sound-CPU
58 00FFH Counter-2 W Indeterminate Installed in sound-CPU
59
60 */
61 /* ======================================================================== */
62 /* ================================ INCLUDES ============================== */
63 /* ======================================================================== */
64
65 #include "emu.h"
66 #include "spc700.h"
67
68 #include "debugger.h"
69
70 #include <climits>
71
72
73 /* ======================================================================== */
74 /* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */
75 /* ======================================================================== */
76
77 #undef int8
78
79 /* Allow for architectures that don't have 8-bit sizes */
80 #if UCHAR_MAX == 0xff
81 #define int8 char
82 #define MAKE_INT_8(A) (int8)((A)&0xff)
83 #else
84 #define int8 int
MAKE_INT_8(int A)85 static inline int MAKE_INT_8(int A) {return (A & 0x80) ? A | ~0xff : A & 0xff;}
86 #endif /* UCHAR_MAX == 0xff */
87
88 #define MAKE_UINT_8(A) ((A)&0xff)
89 #define MAKE_UINT_16(A) ((A)&0xffff)
90
91 /* ======================================================================== */
92 /* ============================ GENERAL DEFINES =========================== */
93 /* ======================================================================== */
94
95 /* Bits */
96 #define BIT_0 0x01
97 #define BIT_1 0x02
98 #define BIT_2 0x04
99 #define BIT_3 0x08
100 #define BIT_4 0x10
101 #define BIT_5 0x20
102 #define BIT_6 0x40
103 #define BIT_7 0x80
104 #define BIT_8 0x100
105
106 /* Flag positions in Processor Status Register */
107 #define FLAGPOS_N BIT_7 /* Negative */
108 #define FLAGPOS_V BIT_6 /* Overflow */
109 #define FLAGPOS_P BIT_5 /* Direct Page Selector */
110 #define FLAGPOS_B BIT_4 /* Break */
111 #define FLAGPOS_H BIT_3 /* Half-carry */
112 #define FLAGPOS_I BIT_2 /* Interrupt */
113 #define FLAGPOS_Z BIT_1 /* Zero */
114 #define FLAGPOS_C BIT_0 /* Carry */
115
116 #define NFLAG_SET FLAGPOS_N
117 #define VFLAG_SET BIT_7
118 #define PFLAG_SET BIT_8
119 #define BFLAG_SET FLAGPOS_B
120 #define HFLAG_SET BIT_3
121 #define IFLAG_SET FLAGPOS_I
122 #define ZFLAG_SET 0
123 #define CFLAG_SET BIT_8
124 #define NZFLAG_CLEAR 1
125 #define VFLAG_CLEAR 0
126 #define PFLAG_CLEAR 0
127 #define BFLAG_CLEAR 0
128 #define HFLAG_CLEAR 0
129 #define IFLAG_CLEAR 0
130 #define CFLAG_CLEAR 0
131
132 #define NMI_SET 1
133 #define NMI_CLEAR 0
134 #define IRQ_SET IFLAG_CLEAR
135 #define IRQ_CLEAR IFLAG_SET
136
137 #define STACK_PAGE 0x100 /* Stack Page Offset */
138
139 #define VECTOR_RST 0xfffe /* Reset */
140 #define VECTOR_BRK 0xffde /* Break Instruction */
141 #define VECTOR_IRQ 0xfffc /* IRQ ??? what is real vector? */
142 #define VECTOR_NMI 0xfffa /* NMI ??? what is real vector? */
143
144 #define REG_A m_a /* Accumulator */
145 #define REG_X m_x /* Index X Register */
146 #define REG_Y m_y /* Index Y Register */
147 #define REG_S m_s /* Stack Pointer */
148 #define REG_PC m_pc /* Program Counter */
149 #define REG_PPC m_ppc /* Previous Program Counter */
150 #define REG_P m_p /* Processor Status Register */
151 #define FLAG_NZ m_flag_n = m_flag_z /* Negative Flag and inverted Zero flag */
152 #define FLAG_N m_flag_n /* Negative flag */
153 #define FLAG_Z m_flag_z /* Inverted Zero flag */
154 #define FLAG_V m_flag_v /* Overflow Flag */
155 #define FLAG_P m_flag_p /* Direct Page Flag */
156 #define FLAG_B m_flag_b /* BRK Instruction Flag */
157 #define FLAG_H m_flag_h /* Decimal Mode Flag */
158 #define FLAG_I m_flag_i /* Interrupt Mask Flag */
159 #define FLAG_C m_flag_c /* Carry Flag */
160 #define LINE_IRQ m_line_irq /* Status of the IRQ line */
161 #define LINE_NMI m_line_nmi /* Status of the NMI line */
162 #define REG_IR m_ir /* Instruction Register */
163 #define CLOCKS m_ICount /* Clock cycles remaining */
164 #define CPU_STOPPED m_stopped /* Stopped status */
165
166 #define SRC m_source /* Source Operand */
167 #define DST m_destination /* Destination Operand */
168 #define TMP1 m_temp1 /* temporary result 1 */
169 #define TMP2 m_temp2 /* temporary result 2 */
170 #define TMP3 m_temp3 /* temporary result 3 */
171
172 #define STOP_LEVEL_STOP 1
173 #define STOP_LEVEL_SLEEP 2
174
175
176 /* ======================================================================== */
177 /* ============================ GENERAL MACROS ============================ */
178 /* ======================================================================== */
179
180 /* Condition code tests */
181 #define COND_CC() (!(FLAG_C&0x100)) /* Carry Clear */
182 #define COND_CS() (FLAG_C&0x100) /* Carry Set */
183 #define COND_EQ() (!FLAG_Z) /* Equal */
184 #define COND_NE() (FLAG_Z) /* Not Equal */
185 #define COND_MI() (FLAG_N&0x80) /* Minus */
186 #define COND_PL() (!(FLAG_N&0x80)) /* Plus */
187 #define COND_VC() (!(FLAG_V&0x80)) /* Overflow Clear */
188 #define COND_VS() (FLAG_V&0x80) /* Overflow Set */
189
190 /* Set Overflow flag in math operations */
191 #define VFLAG_ADD_8(S, D, R) ((S^R) & (D^R))
192 #define VFLAG_ADD_16(S, D, R) (((S^R) & (D^R))>>8)
193 #define VFLAG_SUB_8(S, D, R) ((S^D) & (R^D))
194 #define VFLAG_SUB_16(S, D, R) (((S^D) & (R^D))>>8)
195
196 #define CFLAG_1() ((FLAG_C>>8)&1)
197 #define CFLAG_AS_NOT_1() (!(FLAG_C&CFLAG_SET))
198
199 #define NZFLAG_16(A) (((A)&0x7f) | (((A)>>1)&0x40) | (((A)>>8)&0xff))
200 #define CFLAG_16(A) ((A)>>8)
201
202
203 /* ======================================================================== */
204 /* ================================= MAME ================================= */
205 /* ======================================================================== */
206
207 #define spc700_read_8(addr) m_program->read_byte(addr)
208 #define spc700_write_8(addr,data) m_program->write_byte(addr,data)
209
210 #define spc700_read_8_direct(A) spc700_read_8(A)
211 #define spc700_write_8_direct(A, V) spc700_write_8(A, V)
212 //#define spc700_read_instruction(A) memory_decrypted_read_byte(m_program,A)
213 //#define spc700_read_8_immediate(A) memory_raw_read_byte(m_program,A)
214 #define spc700_read_instruction(A) m_program->read_byte(A)
215 #define spc700_read_8_immediate(A) m_program->read_byte(A)
216 #define spc700_jumping(A)
217 #define spc700_branching(A)
218
219
220
221 DEFINE_DEVICE_TYPE(SPC700, spc700_device, "spc700", "Sony SPC700")
222
223
spc700_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)224 spc700_device::spc700_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
225 : spc700_device(mconfig, SPC700, tag, owner, clock)
226 {
227 }
228
spc700_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock,address_map_constructor internal_map)229 spc700_device::spc700_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal_map)
230 : cpu_device(mconfig, type, tag, owner, clock)
231 , m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0, internal_map)
232 , m_a(0)
233 , m_x(0)
234 , m_y(0)
235 , m_s(0)
236 , m_pc(0)
237 , m_ppc(0)
238 , m_debugger_temp(0)
239 {
240 }
241
memory_space_config() const242 device_memory_interface::space_config_vector spc700_device::memory_space_config() const
243 {
244 return space_config_vector {
245 std::make_pair(AS_PROGRAM, &m_program_config)
246 };
247 }
248
249
250 /* ======================================================================== */
251 /* ============================ UTILITY MACROS ============================ */
252 /* ======================================================================== */
253
254 /* Use up clock cycles */
255 #define CLK_DIVIDER 2
256 #define CLK(A) CLOCKS -= ((A)*(CLK_DIVIDER))
257 #define CLK_ALL() CLOCKS = 0
258
259
read_8_normal(uint32_t address)260 uint32_t spc700_device::read_8_normal(uint32_t address)
261 {
262 address = MAKE_UINT_16(address);
263 return spc700_read_8(address);
264 }
265
read_8_immediate(uint32_t address)266 uint32_t spc700_device::read_8_immediate(uint32_t address)
267 {
268 address = MAKE_UINT_16(address);
269 return spc700_read_8_immediate(address);
270 }
271
read_8_instruction(uint32_t address)272 uint32_t spc700_device::read_8_instruction(uint32_t address)
273 {
274 address = MAKE_UINT_16(address);
275 return spc700_read_instruction(address);
276 }
277
read_8_direct(uint32_t address)278 uint32_t spc700_device::read_8_direct(uint32_t address)
279 {
280 address = MAKE_UINT_8(address) | FLAG_P;
281 return spc700_read_8_direct(address);
282 }
283
write_8_normal(uint32_t address,uint32_t value)284 void spc700_device::write_8_normal(uint32_t address, uint32_t value)
285 {
286 address = MAKE_UINT_16(address);
287 value = MAKE_UINT_8(value);
288 spc700_write_8(address, value);
289 }
290
write_8_direct(uint32_t address,uint32_t value)291 void spc700_device::write_8_direct(uint32_t address, uint32_t value)
292 {
293 address = MAKE_UINT_8(address) | FLAG_P;
294 value = MAKE_UINT_8(value);
295 spc700_write_8_direct(address, value);
296 }
297
298
read_16_normal(uint32_t address)299 uint32_t spc700_device::read_16_normal(uint32_t address)
300 {
301 return read_8_normal(address) | (read_8_normal(address+1)<<8);
302 }
303
read_16_immediate(uint32_t address)304 uint32_t spc700_device::read_16_immediate(uint32_t address)
305 {
306 return read_8_immediate(address) | (read_8_immediate(address+1)<<8);
307 }
308
read_16_direct(uint32_t address)309 uint32_t spc700_device::read_16_direct(uint32_t address)
310 {
311 return read_8_direct(address) | (read_8_direct(address+1)<<8);
312 }
313
write_16_direct(uint32_t address,uint32_t value)314 void spc700_device::write_16_direct(uint32_t address, uint32_t value)
315 {
316 write_8_direct(address, value);
317 write_8_direct(address+1, value>>8);
318 }
319
320 /* Low level memory access macros */
321 #define read_8_NORM(A) read_8_normal(A)
322 #define read_8_IMM(A) read_8_immediate(A)
323 #define read_8_ABS(A) read_8_normal(A)
324 #define read_8_ABX(A) read_8_normal(A)
325 #define read_8_ABY(A) read_8_normal(A)
326 #define read_8_AXI(A) read_8_normal(A)
327 #define read_8_DP(A) read_8_direct(A)
328 #define read_8_DPX(A) read_8_direct(A)
329 #define read_8_DPY(A) read_8_direct(A)
330 #define read_8_DPI(A) read_8_normal(A)
331 #define read_8_DXI(A) read_8_normal(A)
332 #define read_8_DIY(A) read_8_normal(A)
333 #define read_8_STK(A) read_8_normal(A)
334 #define read_8_XI(A) read_8_direct(A)
335 #define read_8_XII(A) read_8_direct(A)
336 #define read_8_YI(A) read_8_direct(A)
337
338
339 #define read_16_NORM(A) read_16_normal(A)
340 #define read_16_IMM(A) read_16_immediate(A)
341 #define read_16_ABS(A) read_16_absolute(A)
342 #define read_16_ABX(A) read_16_normal(A)
343 #define read_16_DP(A) read_16_direct(A)
344 #define read_16_DPX(A) read_16_direct(A)
345 #define read_16_DPY(A) read_16_direct(A)
346 #define read_16_DPI(A) read_16_normal(A)
347 #define read_16_VEC(A) read_16_normal(A)
348 #define read_16_XI(A) read_16_direct(A)
349 #define read_16_XII(A) read_16_direct(A)
350 #define read_16_YI(A) read_16_direct(A)
351
352 #define write_8_NORM(A, V) write_8_normal(A, V)
353 #define write_8_IMM(A, V) write_8_normal(A, V)
354 #define write_8_ABS(A, V) write_8_normal(A, V)
355 #define write_8_ABX(A, V) write_8_normal(A, V)
356 #define write_8_ABY(A, V) write_8_normal(A, V)
357 #define write_8_AXI(A, V) write_8_normal(A, V)
358 #define write_8_DP(A, V) write_8_direct(A, V)
359 #define write_8_DPX(A, V) write_8_direct(A, V)
360 #define write_8_DPY(A, V) write_8_direct(A, V)
361 #define write_8_DPI(A, V) write_8_normal(A, V)
362 #define write_8_DXI(A, V) write_8_normal(A, V)
363 #define write_8_DIY(A, V) write_8_normal(A, V)
364 #define write_8_STK(A, V) write_8_normal(A, V)
365 #define write_8_XI(A, V) write_8_direct(A, V)
366 #define write_8_XII(A, V) write_8_direct(A, V)
367 #define write_8_YI(A, V) write_8_direct(A, V)
368
369 #define write_16_NORM(A, V) write_16_normal(A, V)
370 #define write_16_ABS(A, V) write_16_normal(A, V)
371 #define write_16_ABX(A, V) write_16_normal(A, V)
372 #define write_16_ABY(A, V) write_16_normal(A, V)
373 #define write_16_AXI(A, V) write_16_normal(A, V)
374 #define write_16_DP(A, V) write_16_direct(A, V)
375 #define write_16_DPX(A, V) write_16_direct(A, V)
376 #define write_16_DPY(A, V) write_16_direct(A, V)
377 #define write_16_DPI(A, V) write_16_normal(A, V)
378 #define write_16_DXI(A, V) write_16_normal(A, V)
379 #define write_16_DIY(A, V) write_16_normal(A, V)
380 #define write_16_STK(A, V) write_16_normal(A, V)
381 #define write_16_XI(A, V) write_16_direct(A, V)
382 #define write_16_XII(A, V) write_16_direct(A, V)
383 #define write_16_YI(A, V) write_16_direct(A, V)
384
385
386 #define OPER_8_IMM() read_8_IMM(EA_IMM())
387 #define OPER_8_ABS() read_8_ABS(EA_ABS())
388 #define OPER_8_ABX() read_8_ABX(EA_ABX())
389 #define OPER_8_ABY() read_8_ABY(EA_ABY())
390 #define OPER_8_AXI() read_8_IND(EA_IND())
391 #define OPER_8_DP() read_8_DP(EA_DP())
392 #define OPER_8_DPX() read_8_DPX(EA_DPX())
393 #define OPER_8_DPY() read_8_DPY(EA_DPY())
394 #define OPER_8_DPI() read_8_DPI(EA_DPI())
395 #define OPER_8_DXI() read_8_DXI(EA_DXI())
396 #define OPER_8_DIY() read_8_DIY(EA_DIY())
397 #define OPER_8_XI() read_8_XI(EA_XI())
398 #define OPER_8_XII() read_8_XI(EA_XII())
399 #define OPER_8_YI() read_8_YI(EA_YI())
400
401 #define OPER_16_IMM() read_16_IMM(EA_IMM16())
402 #define OPER_16_ABS() read_16_ABS(EA_ABS())
403 #define OPER_16_ABX() read_16_ABX(EA_ABX())
404 #define OPER_16_ABY() read_16_ABY(EA_ABY())
405 #define OPER_16_AXI() read_16_IND(EA_IND())
406 #define OPER_16_DP() read_16_DP(EA_DP())
407 #define OPER_16_DPX() read_16_DPX(EA_DPX())
408 #define OPER_16_DPY() read_16_DPY(EA_DPY())
409 #define OPER_16_DPI() read_16_DPI(EA_DXI())
410 #define OPER_16_DXI() read_16_DXI(EA_DXI())
411 #define OPER_16_DIY() read_16_DIY(EA_DIY())
412 #define OPER_16_XI() read_16_XI(EA_XI())
413 #define OPER_16_XII() read_16_XI(EA_XII())
414 #define OPER_16_YI() read_16_YI(EA_YI())
415
416 /* Effective Address Calculations */
EA_IMM()417 uint32_t spc700_device::EA_IMM() {return REG_PC++;}
EA_IMM16()418 uint32_t spc700_device::EA_IMM16() {REG_PC += 2; return REG_PC-2;}
EA_ABS()419 uint32_t spc700_device::EA_ABS() {return OPER_16_IMM();}
EA_ABX()420 uint32_t spc700_device::EA_ABX() {return EA_ABS() + REG_X;}
EA_ABY()421 uint32_t spc700_device::EA_ABY() {return EA_ABS() + REG_Y;}
EA_AXI()422 uint32_t spc700_device::EA_AXI() {return OPER_16_ABX();}
EA_DP()423 uint32_t spc700_device::EA_DP() {return OPER_8_IMM();}
EA_DPX()424 uint32_t spc700_device::EA_DPX() {return (EA_DP() + REG_X)&0xff;}
EA_DPY()425 uint32_t spc700_device::EA_DPY() {return (EA_DP() + REG_Y)&0xff;}
EA_DXI()426 uint32_t spc700_device::EA_DXI() {return OPER_16_DPX();}
EA_DIY()427 uint32_t spc700_device::EA_DIY() {uint32_t addr = OPER_16_DP(); return addr + REG_Y;}
EA_XI()428 uint32_t spc700_device::EA_XI() {return REG_X;}
EA_XII()429 uint32_t spc700_device::EA_XII() {uint32_t val = REG_X;REG_X = MAKE_UINT_8(REG_X+1);return val;}
EA_YI()430 uint32_t spc700_device::EA_YI() {return REG_Y;}
431
432
433
434 /* Change the Program Counter */
JUMP(uint32_t address)435 void spc700_device::JUMP(uint32_t address)
436 {
437 REG_PC = address;
438 spc700_jumping(REG_PC);
439 }
440
BRANCH(uint32_t offset)441 void spc700_device::BRANCH(uint32_t offset)
442 {
443 REG_PC = MAKE_UINT_16(REG_PC + MAKE_INT_8(offset));
444 spc700_branching(REG_PC);
445 }
446
447
448 #define GET_REG_YA() (REG_A | (REG_Y<<8))
449
SET_REG_YA(uint32_t value)450 void spc700_device::SET_REG_YA(uint32_t value)
451 {
452 REG_A = MAKE_UINT_8(value);
453 REG_Y = MAKE_UINT_8(value>>8);
454 }
455
456 /* Get the Processor Status Register */
457 #define GET_REG_P() \
458 ((FLAG_N & 0x80) | \
459 ((FLAG_V & 0x80) >> 1) | \
460 (FLAG_P>>3) | \
461 FLAG_B | \
462 (FLAG_H& HFLAG_SET) | \
463 FLAG_I | \
464 ((!FLAG_Z) << 1) | \
465 CFLAG_1())
466
467 /* Set the Process Status Register */
SET_REG_P(uint32_t value)468 void spc700_device::SET_REG_P(uint32_t value)
469 {
470 FLAG_N = (value & 0x80);
471 FLAG_Z = !(value & 2);
472 FLAG_V = value<<1;
473 FLAG_P = (value & FLAGPOS_P) << 3;
474 FLAG_B = value & FLAGPOS_B;
475 FLAG_H = value & HFLAG_SET;
476 FLAG_C = value << 8;
477 SET_FLAG_I(value);
478 }
479
480 /* Push/Pull data to/from the stack */
PUSH_8(uint32_t value)481 void spc700_device::PUSH_8(uint32_t value)
482 {
483 write_8_STK(REG_S+STACK_PAGE, value);
484 REG_S = MAKE_UINT_8(REG_S - 1);
485 }
486
PULL_8()487 uint32_t spc700_device::PULL_8()
488 {
489 REG_S = MAKE_UINT_8(REG_S + 1);
490 return read_8_STK(REG_S+STACK_PAGE);
491 }
492
PUSH_16(uint32_t value)493 void spc700_device::PUSH_16(uint32_t value)
494 {
495 PUSH_8(value>>8);
496 PUSH_8(value);
497 }
498
PULL_16()499 uint32_t spc700_device::PULL_16()
500 {
501 uint32_t value = PULL_8();
502 return value | (PULL_8()<<8);
503 }
504
CHECK_IRQ()505 void spc700_device::CHECK_IRQ()
506 {
507 if(FLAG_I & LINE_IRQ)
508 SERVICE_IRQ();
509 }
510
SERVICE_IRQ()511 void spc700_device::SERVICE_IRQ()
512 {
513 fatalerror("spc700: SERVICE_IRQ() not implemented yet!\n");
514 }
515
516
SET_FLAG_I(uint32_t value)517 void spc700_device::SET_FLAG_I(uint32_t value)
518 {
519 FLAG_I = value & IFLAG_SET;
520 #if !SPC700_OPTIMIZE_SNES
521 CHECK_IRQ();
522 #endif
523 }
524
525 /* ======================================================================== */
526 /* =========================== OPERATION MACROS =========================== */
527 /* ======================================================================== */
528
529 #define SUBOP_ADC(A, B) \
530 m_spc_int16 = (A) + (B) + CFLAG_1(); \
531 TMP1 = ((A) & 0x0f) + (CFLAG_1()); \
532 FLAG_C = (m_spc_int16 > 0xff) ? CFLAG_SET : 0; \
533 FLAG_V = (~((A) ^ (B))) & (((A) ^ m_spc_int16) & 0x80); \
534 FLAG_H = (((m_spc_int16 & 0x0f) - TMP1) & 0x10) >> 1; \
535 FLAG_NZ = (uint8_t)m_spc_int16
536
537
538 /* Add With Carry */
539 #define OP_ADC(BCLK, MODE) \
540 CLK(BCLK); \
541 SRC = OPER_8_##MODE(); \
542 SUBOP_ADC(SRC, REG_A); \
543 REG_A = (uint8_t)m_spc_int16;
544
545
546 /* Add With Carry to memory */
547 #define OP_ADCM(BCLK, SMODE, DMODE) \
548 CLK(BCLK); \
549 SRC = OPER_8_##SMODE(); \
550 DST = EA_##DMODE(); \
551 SUBOP_ADC(SRC, read_8_##DMODE(DST)); \
552 write_8_##DMODE(DST, (uint8_t)m_spc_int16)
553
554 /* Add word */
555 #define OP_ADDW(BCLK) \
556 CLK(BCLK); \
557 SRC = OPER_16_DP(); \
558 DST = GET_REG_YA(); \
559 TMP1 = ((SRC) & 0xff) + ((DST) & 0xff); \
560 TMP2 = (TMP1 > 0xff) ? 1 : 0; \
561 TMP3 = ((SRC) >> 8) + ((DST) >> 8) + TMP2; \
562 m_spc_int16 = ((TMP1 & 0xff) + (TMP3 << 8)) & 0xffff; \
563 FLAG_C = (TMP3 > 0xff) ? CFLAG_SET : 0; \
564 FLAG_H = ((unsigned) ((((DST) >> 8) & 0x0F) + \
565 (((SRC) >> 8) & 0x0F) + TMP2)) > 0x0F ? HFLAG_SET : 0; \
566 FLAG_V = (~((DST) ^ (SRC)) & ((SRC) ^ (uint16_t) m_spc_int16) & 0x8000) ? VFLAG_SET : 0; \
567 FLAG_Z = (m_spc_int16 != 0); \
568 FLAG_N = (m_spc_int16>>8); \
569 SET_REG_YA(m_spc_int16);
570
571 /* Logical AND with accumulator */
572 #define OP_AND(BCLK, MODE) \
573 CLK(BCLK); \
574 FLAG_NZ = REG_A &= OPER_8_##MODE()
575
576 /* Logical AND operand */
577 #define OP_ANDM(BCLK, SMODE, DMODE) \
578 CLK(BCLK); \
579 FLAG_NZ = OPER_8_##SMODE(); \
580 DST = EA_##DMODE(); \
581 FLAG_NZ &= read_8_##DMODE(DST); \
582 write_8_##DMODE(DST, FLAG_NZ)
583
584 /* Logical AND bit to C */
585 #define OP_AND1(BCLK) \
586 CLK(BCLK); \
587 DST = EA_IMM16(); \
588 if(FLAG_C & CFLAG_SET) \
589 { \
590 DST = read_16_IMM(DST); \
591 SRC = 1 << (DST >> 13); \
592 DST &= 0x1fff; \
593 if(!(read_8_NORM(DST) & SRC)) \
594 FLAG_C = CFLAG_CLEAR; \
595 }
596
597 /* AND negated bit to C */
598 #define OP_ANDN1(BCLK) \
599 CLK(BCLK); \
600 DST = EA_IMM16(); \
601 if(FLAG_C & CFLAG_SET) \
602 { \
603 DST = read_16_IMM(DST); \
604 SRC = 1 << (DST >> 13); \
605 DST &= 0x1fff; \
606 if(read_8_NORM(DST) & SRC) \
607 FLAG_C = CFLAG_CLEAR; \
608 }
609
610 /* Arithmetic Shift Left accumulator */
611 #define OP_ASL(BCLK) \
612 CLK(BCLK); \
613 FLAG_C = REG_A << 1; \
614 FLAG_NZ = REG_A = MAKE_UINT_8(FLAG_C)
615
616 /* Arithmetic Shift Left operand */
617 #define OP_ASLM(BCLK, MODE) \
618 CLK(BCLK); \
619 DST = EA_##MODE(); \
620 FLAG_C = read_8_##MODE(DST) << 1; \
621 FLAG_NZ = MAKE_UINT_8(FLAG_C); \
622 write_8_##MODE(DST, FLAG_NZ)
623
624 /* Branch if Bit Reset */
625 #define OP_BBC(BCLK, BIT) \
626 CLK(BCLK); \
627 SRC = OPER_8_DP(); \
628 DST = OPER_8_IMM(); \
629 if(!(SRC & BIT)) \
630 { \
631 CLK(2); \
632 BRANCH(DST); \
633 }
634
635 /* Branch if Bit Set */
636 #define OP_BBS(BCLK, BIT) \
637 CLK(BCLK); \
638 SRC = OPER_8_DP(); \
639 DST = OPER_8_IMM(); \
640 if(SRC & BIT) \
641 { \
642 CLK(2); \
643 BRANCH(DST); \
644 }
645
646 /* Branch on Condition Code */
647 #define OP_BCC(BCLK, COND) \
648 CLK(BCLK); \
649 DST = OPER_8_IMM(); \
650 if(COND) \
651 { \
652 CLK(2); \
653 BRANCH(DST); \
654 }
655
656 /* Branch Unconditional */
657 /* speed up busy loops */
658 #define OP_BRA(BCLK) \
659 CLK(BCLK); \
660 BRANCH(OPER_8_IMM()); \
661 if(REG_PC == REG_PPC) \
662 CLK_ALL()
663
664 /* Cause a Break interrupt */
665 #define OP_BRK(BCLK) \
666 CLK(BCLK); \
667 PUSH_16(REG_PC); \
668 PUSH_8(GET_REG_P()); \
669 FLAG_B |= FLAGPOS_B; \
670 FLAG_I = IFLAG_CLEAR; \
671 JUMP(read_16_VEC(VECTOR_BRK))
672
673 /* Call subroutine */
674 #define OP_CALL(BCLK) \
675 CLK(BCLK); \
676 DST = EA_ABS(); \
677 PUSH_16(REG_PC); \
678 JUMP(DST)
679
680 /* Compare accumulator and branch if not equal */
681 #define OP_CBNE(BCLK, MODE) \
682 CLK(BCLK); \
683 SRC = OPER_8_##MODE(); \
684 DST = EA_IMM(); \
685 if(SRC != REG_A) \
686 { \
687 CLK(2); \
688 BRANCH(read_8_IMM(DST)); \
689 }
690
691 /* Clear Carry flag */
692 #define OP_CLRC(BCLK) \
693 CLK(BCLK); \
694 FLAG_C = CFLAG_CLEAR
695
696 /* Clear Memory Bit */
697 #define OP_CLR(BCLK, BIT) \
698 CLK(BCLK); \
699 DST = EA_DP(); \
700 SRC = read_8_DP(DST) & ~BIT; \
701 write_8_DP(DST, SRC)
702
703 /* Clear Overflow flag (also clears half-carry) */
704 #define OP_CLRV(BCLK) \
705 CLK(BCLK); \
706 FLAG_V = VFLAG_CLEAR; \
707 FLAG_H = 0;
708
709 /* Clear the Page flag */
710 #define OP_CLRP(BCLK) \
711 CLK(BCLK); \
712 FLAG_P = PFLAG_CLEAR
713
714 /* Compare operand to register */
715 #define OP_CMPR(BCLK, REG, MODE) \
716 CLK(BCLK); \
717 SRC = OPER_8_##MODE(); \
718 m_spc_int16 = (short)REG - (short)SRC; \
719 FLAG_C = (m_spc_int16 >= 0) ? CFLAG_SET : 0; \
720 FLAG_NZ = MAKE_UINT_8(m_spc_int16);
721
722 /* Compare memory */
723 #define OP_CMPM(BCLK, SMODE, DMODE) \
724 CLK(BCLK); \
725 SRC = OPER_8_##SMODE(); \
726 m_spc_int16 = (short)OPER_8_##DMODE() - (short)SRC; \
727 FLAG_C = (m_spc_int16 >= 0) ? CFLAG_SET : 0; \
728 FLAG_NZ = MAKE_UINT_8(m_spc_int16);
729
730 /* Compare word */
731 #define OP_CMPW(BCLK, MODE) \
732 CLK(BCLK); \
733 SRC = OPER_16_##MODE(); \
734 m_spc_int32 = (int)GET_REG_YA() - (int)SRC; \
735 FLAG_C = (m_spc_int32 >= 0) ? CFLAG_SET : 0; \
736 FLAG_NZ = NZFLAG_16(m_spc_int32);
737
738 /* Decimal adjust for addition */
739 #define OP_DAA(BCLK) \
740 CLK(BCLK); \
741 SRC = REG_A; \
742 if (((SRC & 0x0f) > 9) || (FLAG_H & HFLAG_SET)) \
743 { \
744 REG_A += 6; \
745 if (REG_A < 6) \
746 { \
747 FLAG_C = CFLAG_SET; \
748 } \
749 } \
750 if ((SRC > 0x99) || (FLAG_C & CFLAG_SET)) \
751 { \
752 REG_A += 0x60; \
753 FLAG_C = CFLAG_SET; \
754 } \
755 FLAG_NZ = REG_A = MAKE_UINT_8(REG_A);
756
757 /* Decimal adjust for subtraction */
758 #define OP_DAS(BCLK) \
759 CLK(BCLK); \
760 SRC = REG_A; \
761 if (!(FLAG_H & HFLAG_SET) || ((SRC & 0xf) > 9)) \
762 { \
763 REG_A -= 6; \
764 } \
765 if (!(FLAG_C & CFLAG_SET) || (SRC > 0x99)) \
766 { \
767 REG_A -= 0x60; \
768 FLAG_C = 0; \
769 } \
770 FLAG_NZ = REG_A = MAKE_UINT_8(REG_A)
771
772 /* Decrement register and branch if not zero */
773 /* speed up busy loops */
774 #define OP_DBNZR(BCLK) \
775 CLK(BCLK); \
776 REG_Y = MAKE_UINT_8(REG_Y - 1); \
777 DST = EA_IMM(); \
778 if(REG_Y != 0) \
779 { \
780 CLK(2); \
781 BRANCH(read_8_IMM(DST)); \
782 }
783
784 /* Decrement operand and branch if not zero */
785 /* Speed up busy loops but do reads/writes for compatibility */
786 #define OP_DBNZM(BCLK) \
787 CLK(BCLK); \
788 DST = EA_DP(); \
789 SRC = MAKE_UINT_8(read_8_DP(DST) - 1); \
790 write_8_DP(DST, SRC); \
791 DST = EA_IMM(); \
792 if(SRC != 0) \
793 { \
794 CLK(2); \
795 BRANCH(read_8_IMM(DST)); \
796 }
797
798 /* Decrement register */
799 #define OP_DECR(BCLK, REG) \
800 CLK(BCLK); \
801 FLAG_NZ = REG = MAKE_UINT_8(REG - 1)
802
803 /* Decrement operand */
804 #define OP_DECM(BCLK, MODE) \
805 CLK(BCLK); \
806 DST = EA_##MODE(); \
807 FLAG_NZ = MAKE_UINT_8(read_8_##MODE(DST) - 1); \
808 write_8_##MODE(DST, FLAG_NZ)
809
810 /* Decrement word */
811 #define OP_DECW(BCLK) \
812 CLK(BCLK); \
813 DST = EA_DP(); \
814 FLAG_NZ = MAKE_UINT_16(read_16_DP(DST) - 1); \
815 write_16_DP(DST, FLAG_Z); \
816 FLAG_NZ = NZFLAG_16(FLAG_Z)
817
818 /* Disable interrupts */
819 #define OP_DI(BCLK) \
820 CLK(BCLK); \
821 FLAG_I = IFLAG_CLEAR
822
823 /* Divide - should be almost exactly how the hardware works */
824 #define OP_DIV(BCLK) \
825 CLK(BCLK); \
826 TMP1 = SRC = GET_REG_YA(); \
827 TMP2 = (REG_X << 9); \
828 FLAG_H = 0; \
829 if ((REG_Y & 0xf) >= (REG_X & 0xf)) FLAG_H = HFLAG_SET; \
830 for (TMP3 = 0; TMP3 < 9; TMP3++) \
831 { \
832 TMP1 <<= 1; \
833 if (TMP1 & 0x20000) TMP1 = (TMP1 & 0x1ffff) | 1; \
834 if (TMP1 >= TMP2) TMP1 ^= 1; \
835 if (TMP1 & 1) TMP1 = ((TMP1 - TMP2) & 0x1ffff); \
836 } \
837 FLAG_V = (TMP1 & 0x100) ? VFLAG_SET : 0; \
838 SET_REG_YA((((TMP1 >> 9) & 0xff) << 8) + (TMP1 & 0xff)); \
839 FLAG_NZ = MAKE_UINT_8(GET_REG_YA());
840
841 /* Enable interrupts */
842 #define OP_EI(BCLK) \
843 CLK(BCLK); \
844 FLAG_I = IFLAG_SET
845
846 /* Exclusive Or operand to accumulator */
847 #define OP_EOR(BCLK, MODE) \
848 CLK(BCLK); \
849 FLAG_NZ = REG_A ^= OPER_8_##MODE()
850
851 /* Logical EOR operand */
852 #define OP_EORM(BCLK, SMODE, DMODE) \
853 CLK(BCLK); \
854 FLAG_NZ = OPER_8_##SMODE(); \
855 DST = EA_##DMODE(); \
856 FLAG_NZ ^= read_8_##DMODE(DST); \
857 write_8_##DMODE(DST, FLAG_NZ)
858
859 /* Exclusive OR bit to C */
860 #define OP_EOR1(BCLK) \
861 CLK(BCLK); \
862 DST = OPER_16_IMM(); \
863 SRC = 1 << (DST >> 13); \
864 DST &= 0x1fff; \
865 if(read_8_NORM(DST) & SRC) \
866 FLAG_C = ~FLAG_C
867
868 /* Increment register */
869 #define OP_INCR(BCLK, REG) \
870 CLK(BCLK); \
871 FLAG_NZ = REG = MAKE_UINT_8(REG + 1)
872
873 /* Increment operand */
874 #define OP_INCM(BCLK, MODE) \
875 CLK(BCLK); \
876 DST = EA_##MODE(); \
877 FLAG_NZ = MAKE_UINT_8(read_8_##MODE(DST) + 1); \
878 write_8_##MODE(DST, FLAG_NZ)
879
880 /* Increment word */
881 #define OP_INCW(BCLK) \
882 CLK(BCLK); \
883 DST = EA_DP(); \
884 FLAG_NZ = MAKE_UINT_16(read_16_DP(DST) + 1); \
885 write_16_DP(DST, FLAG_Z); \
886 FLAG_NZ = NZFLAG_16(FLAG_Z)
887
888 /* Jump */
889 /* If we're in a busy loop, eat all clock cycles */
890 #define OP_JMP(BCLK, MODE) \
891 CLK(BCLK); \
892 JUMP(EA_##MODE()); \
893 if(REG_PC == REG_PPC) \
894 CLK_ALL()
895
896 /* Jump to Subroutine */
897 #define OP_JSR(BCLK, MODE) \
898 CLK(BCLK); \
899 PUSH_16(REG_PC); \
900 JUMP(EA_##MODE())
901
902 /* Logical Shift Right accumulator */
903 #define OP_LSR(BCLK) \
904 CLK(BCLK); \
905 FLAG_C = REG_A << 8; \
906 FLAG_NZ = REG_A >>= 1
907
908 /* Logical Shift Right operand */
909 #define OP_LSRM(BCLK, MODE) \
910 CLK(BCLK); \
911 DST = EA_##MODE(); \
912 FLAG_NZ = read_8_##MODE(DST); \
913 FLAG_C = FLAG_N << 8; \
914 FLAG_NZ >>= 1; \
915 write_8_##MODE(DST, FLAG_NZ)
916
917 /* Move from register to register */
918 #define OP_MOVRR(BCLK, SREG, DREG) \
919 CLK(BCLK); \
920 FLAG_NZ = DREG = SREG
921
922 /* Move from register to memory */
923 #define OP_MOVRM(BCLK, SREG, DMODE) \
924 CLK(BCLK); \
925 write_8_##DMODE(EA_##DMODE(), SREG)
926
927 /* Move from memory to register */
928 #define OP_MOVMR(BCLK, SMODE, DREG) \
929 CLK(BCLK); \
930 FLAG_NZ = DREG = OPER_8_##SMODE()
931
932 /* Move from memory to memory */
933 #define OP_MOVMM(BCLK, SMODE, DMODE) \
934 CLK(BCLK); \
935 SRC = OPER_8_##SMODE(); \
936 DST = EA_##DMODE(); \
937 write_8_##DMODE(DST, SRC)
938
939 /* Move word register to memory */
940 #define OP_MOVWRM(BCLK) \
941 CLK(BCLK); \
942 write_16_DP(EA_DP(), GET_REG_YA())
943
944 /* Move word memory to register */
945 #define OP_MOVWMR(BCLK) \
946 CLK(BCLK); \
947 FLAG_NZ = OPER_16_DP(); \
948 SET_REG_YA(FLAG_Z); \
949 FLAG_NZ = NZFLAG_16(FLAG_Z)
950
951 /* Move from Stack pointer to X */
952 #define OP_MOVSX(BCLK) \
953 CLK(BCLK); \
954 FLAG_NZ = REG_X = REG_S
955
956 /* Move from X to Stack pointer */
957 #define OP_MOVXS(BCLK) \
958 CLK(BCLK); \
959 REG_S = REG_X
960
961 /* Move bit from memory to C */
962 #define OP_MOV1C(BCLK) \
963 CLK(BCLK); \
964 DST = OPER_16_IMM(); \
965 SRC = 1 << (DST >> 13); \
966 DST &= 0x1fff; \
967 FLAG_C = ((read_8_NORM(DST) & SRC) != 0) << 8
968
969 /* Move bit from C to memory */
970 #define OP_MOV1M(BCLK) \
971 CLK(BCLK); \
972 DST = OPER_16_IMM(); \
973 SRC = 1 << (DST >> 13); \
974 DST &= 0x1fff; \
975 if(FLAG_C & CFLAG_SET) \
976 write_8_NORM(DST, read_8_NORM(DST) | SRC); \
977 else \
978 write_8_NORM(DST, read_8_NORM(DST) & ~SRC)
979
980
981 /* Multiply A and Y and store result in YA */
982 #define OP_MUL(BCLK) \
983 CLK(BCLK); \
984 SRC = REG_Y * REG_A; \
985 REG_A = MAKE_UINT_8(SRC); \
986 FLAG_NZ = REG_Y = SRC >> 8;
987
988 /* No Operation */
989 #define OP_NOP(BCLK) \
990 CLK(BCLK)
991
992 /* Invert the C flag */
993 #define OP_NOTC(BCLK) \
994 CLK(BCLK); \
995 FLAG_C = ~FLAG_C
996
997 /* NOT bit */
998 #define OP_NOT1(BCLK) \
999 CLK(BCLK); \
1000 DST = OPER_16_IMM(); \
1001 SRC = 1 << (DST >> 13); \
1002 DST &= 0x1fff; \
1003 write_8_NORM(DST, read_8_NORM(DST) ^ SRC)
1004
1005 /* Logical OR operand to accumulator */
1006 #define OP_OR(BCLK, MODE) \
1007 CLK(BCLK); \
1008 FLAG_NZ = REG_A |= OPER_8_##MODE()
1009
1010 /* Logical OR operand */
1011 #define OP_ORM(BCLK, SMODE, DMODE) \
1012 CLK(BCLK); \
1013 FLAG_NZ = OPER_8_##SMODE(); \
1014 DST = EA_##DMODE(); \
1015 FLAG_NZ |= read_8_##DMODE(DST); \
1016 write_8_##DMODE(DST, FLAG_NZ)
1017
1018 /* Logical OR bit to C */
1019 #define OP_OR1(BCLK) \
1020 CLK(BCLK); \
1021 DST = EA_IMM16(); \
1022 if(!(FLAG_C & CFLAG_SET)) \
1023 { \
1024 DST = read_16_IMM(DST); \
1025 SRC = 1 << (DST >> 13); \
1026 DST &= 0x1fff; \
1027 if(read_8_NORM(DST) & SRC) \
1028 FLAG_C = CFLAG_SET; \
1029 }
1030
1031 /* OR negated bit to C */
1032 #define OP_ORN1(BCLK) \
1033 CLK(BCLK); \
1034 DST = EA_IMM16(); \
1035 if(!(FLAG_C & CFLAG_SET)) \
1036 { \
1037 DST = read_16_IMM(DST); \
1038 SRC = 1 << (DST >> 13); \
1039 DST &= 0x1fff; \
1040 if(!(read_8_NORM(DST) & SRC)) \
1041 FLAG_C = CFLAG_SET; \
1042 }
1043
1044 /* UPage Call */
1045 #define OP_PCALL(BCLK) \
1046 CLK(BCLK); \
1047 DST = EA_DP(); \
1048 PUSH_16(REG_PC); \
1049 JUMP(0xff00 | DST)
1050
1051 /* Push a register to the stack */
1052 #define OP_PUSH(BCLK, REG) \
1053 CLK(BCLK); \
1054 PUSH_8(REG)
1055
1056 /* Push the Processor Status Register to the stack */
1057 #define OP_PHP(BCLK) \
1058 CLK(BCLK); \
1059 PUSH_8(GET_REG_P())
1060
1061 /* Pull a register from the stack */
1062 #define OP_PULL(BCLK, REG) \
1063 CLK(BCLK); \
1064 REG = PULL_8()
1065
1066 /* Pull the Processor Status Register from the stack */
1067 #define OP_PLP(BCLK) \
1068 CLK(BCLK); \
1069 SET_REG_P(PULL_8())
1070
1071 /* Return from Subroutine */
1072 #define OP_RET(BCLK) \
1073 CLK(BCLK); \
1074 JUMP(PULL_16())
1075
1076 /* Return from Interrupt */
1077 #define OP_RETI(BCLK) \
1078 CLK(BCLK); \
1079 SET_REG_P(PULL_8()); \
1080 JUMP(PULL_16())
1081
1082 /* Rotate Left the accumulator */
1083 #define OP_ROL(BCLK) \
1084 CLK(BCLK); \
1085 FLAG_C = (REG_A<<1) | CFLAG_1(); \
1086 FLAG_NZ = REG_A = MAKE_UINT_8(FLAG_C)
1087
1088 /* Rotate Left an operand */
1089 #define OP_ROLM(BCLK, MODE) \
1090 CLK(BCLK); \
1091 DST = EA_##MODE(); \
1092 FLAG_C = (read_8_##MODE(DST)<<1) | CFLAG_1(); \
1093 FLAG_NZ = MAKE_UINT_8(FLAG_C); \
1094 write_8_##MODE(DST, FLAG_NZ)
1095
1096 /* Rotate Right the accumulator */
1097 #define OP_ROR(BCLK) \
1098 CLK(BCLK); \
1099 REG_A |= FLAG_C & 0x100; \
1100 FLAG_C = REG_A << 8; \
1101 FLAG_NZ = REG_A >>= 1
1102
1103 /* Rotate Right an operand */
1104 #define OP_RORM(BCLK, MODE) \
1105 CLK(BCLK); \
1106 DST = EA_##MODE(); \
1107 FLAG_NZ = read_8_##MODE(DST) | (FLAG_C & 0x100); \
1108 FLAG_C = FLAG_N << 8; \
1109 FLAG_NZ >>= 1; \
1110 write_8_##MODE(DST, FLAG_NZ)
1111
1112 /* Subtract with Carry */
1113 #define OP_SBC(BCLK, MODE) \
1114 CLK(BCLK); \
1115 SRC = OPER_8_##MODE(); \
1116 TMP2 = REG_A - SRC - (CFLAG_1() ^ 1); \
1117 SUBOP_ADC(REG_A, ~SRC); \
1118 FLAG_C = (TMP2 <= 0xff) ? CFLAG_SET : 0; \
1119 REG_A = (uint8_t)m_spc_int16;
1120
1121 /* Subtract With Carry to memory */
1122 #define OP_SBCM(BCLK, SMODE, DMODE) \
1123 CLK(BCLK); \
1124 SRC = OPER_8_##SMODE(); \
1125 DST = EA_##DMODE(); \
1126 TMP3 = read_8_##DMODE(DST); \
1127 TMP2 = TMP3 - SRC - (CFLAG_1() ^ 1); \
1128 SUBOP_ADC(~SRC, TMP3); \
1129 FLAG_C = (TMP2 <= 0xff) ? CFLAG_SET : 0; \
1130 write_8_##DMODE(DST, (uint8_t)m_spc_int16)
1131
1132 /* Set Carry flag */
1133 #define OP_SETC(BCLK) \
1134 CLK(BCLK); \
1135 FLAG_C = CFLAG_SET
1136
1137 /* Set Page flag */
1138 #define OP_SETP(BCLK) \
1139 CLK(BCLK); \
1140 FLAG_P = PFLAG_SET
1141
1142 /* Set Memory Bit */
1143 #define OP_SET(BCLK, BIT) \
1144 CLK(BCLK); \
1145 DST = EA_DP(); \
1146 SRC = read_8_DP(DST) | BIT; \
1147 write_8_DP(DST, SRC)
1148
1149 /* Put the CPU to sleep */
1150 #define OP_SLEEP(BCLK) \
1151 CLK(BCLK); \
1152 CPU_STOPPED |= STOP_LEVEL_SLEEP; \
1153 CLK_ALL()
1154
1155 /* Stop the CPU */
1156 #define OP_STOP(BCLK) \
1157 CLK(BCLK); \
1158 CPU_STOPPED |= STOP_LEVEL_STOP; \
1159 CLK_ALL()
1160
1161 /* Subtract word */
1162 #define OP_SUBW(BCLK) \
1163 CLK(BCLK); \
1164 SRC = OPER_16_DP(); \
1165 DST = GET_REG_YA(); \
1166 TMP1 = ((DST) & 0xff) - ((SRC) & 0xff); \
1167 TMP2 = (TMP1 > 0xff) ? 1 : 0; \
1168 TMP3 = ((DST) >> 8) - ((SRC) >> 8) - TMP2; \
1169 m_spc_int16 = ((TMP1 & 0xff) + (TMP3 << 8)) & 0xffff; \
1170 FLAG_C = (TMP3 <= 0xff) ? CFLAG_SET : 0; \
1171 FLAG_H = ((unsigned) ((((DST) >> 8) & 0x0F) - \
1172 (((SRC) >> 8) & 0x0F) - TMP2)) > 0x0F ? 0: HFLAG_SET; \
1173 FLAG_V = (((DST) ^ (SRC)) & ((DST) ^ (uint16_t) m_spc_int16) & 0x8000) ? VFLAG_SET : 0; \
1174 FLAG_Z = (m_spc_int16 != 0); \
1175 FLAG_N = (m_spc_int16>>8); \
1176 SET_REG_YA(m_spc_int16);
1177
1178 /* Table Call */
1179 #define OP_TCALL(BCLK, NUM) \
1180 CLK(BCLK); \
1181 PUSH_16(REG_PC); \
1182 JUMP(read_16_NORM(0xffc0 + ((15-NUM)<<1)))
1183
1184 /* Test and Clear Bits */
1185 #define OP_TCLR1(BCLK, MODE) \
1186 CLK(BCLK); \
1187 DST = EA_##MODE(); \
1188 FLAG_NZ = read_8_##MODE(DST); \
1189 m_spc_int16 = (short)REG_A - (short)(read_8_##MODE(DST)); \
1190 write_8_##MODE(DST, FLAG_NZ & ~REG_A); \
1191 FLAG_NZ = MAKE_UINT_8(m_spc_int16);
1192
1193 /* Test and Set Bits */
1194 #define OP_TSET1(BCLK, MODE) \
1195 CLK(BCLK); \
1196 DST = EA_##MODE(); \
1197 FLAG_NZ = read_8_##MODE(DST); \
1198 m_spc_int16 = (short)REG_A - (short)(read_8_##MODE(DST)); \
1199 write_8_##MODE(DST, FLAG_NZ | REG_A); \
1200 FLAG_NZ = MAKE_UINT_8(m_spc_int16);
1201
1202 /* Exchange high and low nybbles of accumulator */
1203 #define OP_XCN(BCLK) \
1204 CLK(BCLK); \
1205 FLAG_NZ = REG_A = MAKE_UINT_8((REG_A<<4) | (REG_A>>4))
1206
1207 #define OP_ILLEGAL(BCLK) \
1208 CLK(BCLK)
1209
1210
1211 /* ======================================================================== */
1212 /* ================================= API ================================== */
1213 /* ======================================================================== */
1214
device_start()1215 void spc700_device::device_start()
1216 {
1217 m_program = &space(AS_PROGRAM);
1218
1219 save_item(NAME(m_a));
1220 save_item(NAME(m_x));
1221 save_item(NAME(m_y));
1222 save_item(NAME(m_s));
1223 save_item(NAME(m_pc));
1224 save_item(NAME(m_ppc));
1225 save_item(NAME(m_flag_n));
1226 save_item(NAME(m_flag_z));
1227 save_item(NAME(m_flag_v));
1228 save_item(NAME(m_flag_p));
1229 save_item(NAME(m_flag_b));
1230 save_item(NAME(m_flag_h));
1231 save_item(NAME(m_flag_i));
1232 save_item(NAME(m_flag_c));
1233 save_item(NAME(m_line_irq));
1234 save_item(NAME(m_line_nmi));
1235 save_item(NAME(m_line_rst));
1236 save_item(NAME(m_ir));
1237 save_item(NAME(m_stopped));
1238 save_item(NAME(m_ICount));
1239 save_item(NAME(m_source));
1240 save_item(NAME(m_destination));
1241 save_item(NAME(m_temp1));
1242 save_item(NAME(m_temp2));
1243 save_item(NAME(m_temp3));
1244 save_item(NAME(m_spc_int16));
1245 save_item(NAME(m_spc_int32));
1246
1247 // Register state for debugger
1248 state_add( SPC700_PC, "PC", m_pc ).formatstr("%04X");
1249 state_add( SPC700_S, "S", m_s ).formatstr("%02X");
1250 state_add( SPC700_P, "P", m_debugger_temp ).callimport().callexport().formatstr("%02X");
1251 state_add( SPC700_A, "A", m_a ).formatstr("%02X");
1252 state_add( SPC700_X, "X", m_x ).formatstr("%02X");
1253 state_add( SPC700_Y, "Y", m_y ).formatstr("%02X");
1254
1255 state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%04X").noshow();
1256 state_add(STATE_GENPCBASE, "CURPC", m_ppc).formatstr("%04X").noshow();
1257 state_add(STATE_GENSP, "GENSP", m_debugger_temp).mask(0x1ff).callexport().formatstr("%04X").noshow();
1258 state_add(STATE_GENFLAGS, "GENFLAGS", m_debugger_temp).formatstr("%8s").noshow();
1259
1260 set_icountptr(m_ICount);
1261 }
1262
1263
state_string_export(const device_state_entry & entry,std::string & str) const1264 void spc700_device::state_string_export(const device_state_entry &entry, std::string &str) const
1265 {
1266 switch (entry.index())
1267 {
1268 case STATE_GENFLAGS:
1269 str = string_format("%c%c%c%c%c%c%c%c",
1270 (FLAG_N & 0x80) ? 'N':'.',
1271 (FLAG_V & 0x80) ? 'V':'.',
1272 (FLAG_P) ? 'P':'.',
1273 (FLAG_B) ? 'B':'.',
1274 (FLAG_H & HFLAG_SET) ? 'H':'.',
1275 (FLAG_I) ? 'I':'.',
1276 (!FLAG_Z) ? 'Z':'.',
1277 (FLAG_C & 0x100) ? 'C':'.'
1278 );
1279 break;
1280 }
1281 }
1282
1283
state_import(const device_state_entry & entry)1284 void spc700_device::state_import(const device_state_entry &entry)
1285 {
1286 switch (entry.index())
1287 {
1288 case SPC700_P:
1289 SET_REG_P(m_debugger_temp);
1290 break;
1291 }
1292 }
1293
1294
state_export(const device_state_entry & entry)1295 void spc700_device::state_export(const device_state_entry &entry)
1296 {
1297 switch (entry.index())
1298 {
1299 case SPC700_P:
1300 m_debugger_temp = ((FLAG_N & 0x80) |
1301 ((FLAG_V & 0x80) >> 1) |
1302 FLAG_P>>3 |
1303 FLAG_B |
1304 (FLAG_H & HFLAG_SET) |
1305 FLAG_I |
1306 ((!FLAG_Z) << 1) |
1307 ((FLAG_C >> 8)&1));
1308 break;
1309
1310 case STATE_GENSP:
1311 m_debugger_temp = m_s + STACK_PAGE;
1312 break;
1313 }
1314 }
1315
1316
device_reset()1317 void spc700_device::device_reset()
1318 {
1319 CPU_STOPPED = 0;
1320 LINE_IRQ = 0;
1321 LINE_NMI = 0;
1322 REG_S = 0;
1323 FLAG_NZ = NZFLAG_CLEAR;
1324 FLAG_V = VFLAG_CLEAR;
1325 FLAG_P = PFLAG_CLEAR;
1326 FLAG_B = BFLAG_CLEAR;
1327 FLAG_H = HFLAG_CLEAR;
1328 FLAG_I = IFLAG_CLEAR;
1329 FLAG_C = CFLAG_CLEAR;
1330 JUMP(read_16_VEC(VECTOR_RST));
1331 }
1332
1333
execute_set_input(int inptnum,int state)1334 void spc700_device::execute_set_input( int inptnum, int state )
1335 {
1336 if ( inptnum == INPUT_LINE_NMI )
1337 {
1338 /* Assert or clear the NMI line of the CPU */
1339 #if !SPC700_OPTIMIZE_SNES
1340 if(state == CLEAR_LINE)
1341 LINE_NMI = 0;
1342 else if(!LINE_NMI)
1343 {
1344 LINE_NMI = 1;
1345 CLK(7);
1346 PUSH_16(REG_PC);
1347 PUSH_8(GET_REG_P());
1348 JUMP(read_16_VEC(VECTOR_NMI));
1349 }
1350 #endif /* SPC700_OPTIMIZE_SNES */
1351 }
1352 else
1353 {
1354 /* Assert or clear the IRQ line of the CPU */
1355 #if !SPC700_OPTIMIZE_SNES
1356 LINE_IRQ = (state != CLEAR_LINE) ? IRQ_SET : IRQ_CLEAR;
1357 CHECK_IRQ();
1358 #endif /* SPC700_OPTIMIZE_SNES */
1359 }
1360 }
1361
1362 #include "spc700ds.h"
1363
create_disassembler()1364 std::unique_ptr<util::disasm_interface> spc700_device::create_disassembler()
1365 {
1366 return std::make_unique<spc700_disassembler>();
1367 }
1368
1369 //int dump_flag = 0;
1370
1371 /* Execute instructions for <clocks> cycles */
execute_run()1372 void spc700_device::execute_run()
1373 {
1374 if (CPU_STOPPED)
1375 {
1376 CLOCKS = 0;
1377 return;
1378 }
1379 while(CLOCKS > 0)
1380 {
1381 REG_PPC = REG_PC;
1382 debugger_instruction_hook(REG_PC);
1383 REG_PC++;
1384
1385 switch(REG_IR = read_8_immediate(REG_PPC))
1386 {
1387 case 0x00: OP_NOP ( 2 ); break; /* NOP */
1388 case 0x01: OP_TCALL ( 8, 0 ); break; /* TCALL 0 */
1389 case 0x02: OP_SET ( 4, BIT_0 ); break; /* SET 0 */
1390 case 0x03: OP_BBS ( 5, BIT_0 ); break; /* BBS 0 */
1391
1392 case 0x04: OP_OR ( 3, DP ); break; /* ORA dp */
1393 case 0x05: OP_OR ( 4, ABS ); break; /* ORA abs */
1394 case 0x06: OP_OR ( 3, XI ); break; /* ORA xi */
1395 case 0x07: OP_OR ( 6, DXI ); break; /* ORA dxi */
1396
1397 case 0x08: OP_OR ( 2, IMM ); break; /* ORA imm */
1398 case 0x09: OP_ORM ( 6, DP , DP ); break; /* ORM dp dp */
1399 case 0x0a: OP_OR1 ( 5 ); break; /* OR1 bit */
1400 case 0x0b: OP_ASLM ( 4, DP ); break; /* ASL dp */
1401
1402 case 0x0c: OP_ASLM ( 5, ABS ); break; /* ASL abs */
1403 case 0x0d: OP_PHP ( 4 ); break; /* PHP */
1404 case 0x0e: OP_TSET1 ( 6, ABS ); break; /* TSET1 abs */
1405 case 0x0f: OP_BRK ( 8 ); break; /* BRK */
1406
1407 case 0x10: OP_BCC ( 2, COND_PL() ); break; /* BPL */
1408 case 0x11: OP_TCALL ( 8, 1 ); break; /* TCALL 1 */
1409 case 0x12: OP_CLR ( 4, BIT_0 ); break; /* CLR 0 */
1410 case 0x13: OP_BBC ( 5, BIT_0 ); break; /* BBC 0 */
1411
1412 case 0x14: OP_OR ( 4, DPX ); break; /* ORA dpx */
1413 case 0x15: OP_OR ( 5, ABX ); break; /* ORA abx */
1414 case 0x16: OP_OR ( 5, ABY ); break; /* ORA aby */
1415 case 0x17: OP_OR ( 6, DIY ); break; /* ORA diy */
1416
1417 case 0x18: OP_ORM ( 5, IMM, DP ); break; /* ORM dp, imm */
1418 case 0x19: OP_ORM ( 5, YI, XI ); break; /* ORM xi, yi */
1419 case 0x1a: OP_DECW ( 6 ); break; /* DECW di */
1420 case 0x1b: OP_ASLM ( 5, DPX ); break; /* ASL dpx */
1421
1422 case 0x1c: OP_ASL ( 2 ); break; /* ASL a */
1423 case 0x1d: OP_DECR ( 2, REG_X ); break; /* DEC x */
1424 case 0x1e: OP_CMPR ( 4, REG_X, ABS ); break; /* CMP x, abs */
1425 case 0x1f: OP_JMP ( 6, AXI ); break; /* JMP axi */
1426
1427 case 0x20: OP_CLRP ( 2 ); break; /* CLRP */
1428 case 0x21: OP_TCALL ( 8, 2 ); break; /* TCALL 2 */
1429 case 0x22: OP_SET ( 4, BIT_1 ); break; /* SET 1 */
1430 case 0x23: OP_BBS ( 5, BIT_1 ); break; /* BBS 1 */
1431
1432 case 0x24: OP_AND ( 3, DP ); break; /* AND dp */
1433 case 0x25: OP_AND ( 4, ABS ); break; /* AND abs */
1434 case 0x26: OP_AND ( 3, XI ); break; /* AND xi */
1435 case 0x27: OP_AND ( 6, DXI ); break; /* AND dxi */
1436
1437 case 0x28: OP_AND ( 2, IMM ); break; /* AND imm */
1438 case 0x29: OP_ANDM ( 6, DP , DP ); break; /* AND dp, dp */
1439 case 0x2a: OP_ORN1 ( 5 ); break; /* OR1 !bit */
1440 case 0x2b: OP_ROLM ( 4, DP ); break; /* ROL dp */
1441
1442 case 0x2c: OP_ROLM ( 5, ABS ); break; /* ROL abs */
1443 case 0x2d: OP_PUSH ( 4, REG_A ); break; /* PUSH a */
1444 case 0x2e: OP_CBNE ( 5, DP ); break; /* CBNE dp */
1445 case 0x2f: OP_BRA ( 4 ); break; /* BRA */
1446
1447 case 0x30: OP_BCC ( 2, COND_MI() ); break; /* BMI */
1448 case 0x31: OP_TCALL ( 8, 3 ); break; /* TCALL 3 */
1449 case 0x32: OP_CLR ( 4, BIT_1 ); break; /* CLR 1 */
1450 case 0x33: OP_BBC ( 5, BIT_1 ); break; /* BBC 1 */
1451
1452 case 0x34: OP_AND ( 4, DPX ); break; /* AND dpx */
1453 case 0x35: OP_AND ( 5, ABX ); break; /* AND abx */
1454 case 0x36: OP_AND ( 5, ABY ); break; /* AND aby */
1455 case 0x37: OP_AND ( 6, DIY ); break; /* AND diy */
1456
1457 case 0x38: OP_ANDM ( 5, IMM, DP ); break; /* AND dp, imm */
1458 case 0x39: OP_ANDM ( 5, YI , XI ); break; /* AND xi, yi */
1459 case 0x3a: OP_INCW ( 6 ); break; /* INCW di */
1460 case 0x3b: OP_ROLM ( 5, DPX ); break; /* ROL dpx */
1461
1462 case 0x3c: OP_ROL ( 2 ); break; /* ROL acc */
1463 case 0x3d: OP_INCR ( 2, REG_X ); break; /* INC x */
1464 case 0x3e: OP_CMPR ( 3, REG_X, DP ); break; /* CMP x, dp */
1465 case 0x3f: OP_CALL ( 8 ); break; /* CALL abs */
1466
1467 case 0x40: OP_SETP ( 2 ); break; /* RTI */
1468 case 0x41: OP_TCALL ( 8, 4 ); break; /* TCALL 4 */
1469 case 0x42: OP_SET ( 4, BIT_2 ); break; /* SET 2 */
1470 case 0x43: OP_BBS ( 5, BIT_2 ); break; /* BBS 2 */
1471
1472 case 0x44: OP_EOR ( 3, DP ); break; /* EOR dp */
1473 case 0x45: OP_EOR ( 4, ABS ); break; /* EOR abs */
1474 case 0x46: OP_EOR ( 3, XI ); break; /* EOR xi */
1475 case 0x47: OP_EOR ( 6, DXI ); break; /* EOR dxi */
1476
1477 case 0x48: OP_EOR ( 2, IMM ); break; /* EOR imm */
1478 case 0x49: OP_EORM ( 6, DP, DP ); break; /* EOR dp, dp */
1479 case 0x4a: OP_AND1 ( 4 ); break; /* AND1 bit */
1480 case 0x4b: OP_LSRM ( 4, DP ); break; /* LSR dp */
1481
1482 case 0x4c: OP_LSRM ( 5, ABS ); break; /* LSR abs */
1483 case 0x4d: OP_PUSH ( 4, REG_X ); break; /* PUSH x */
1484 case 0x4e: OP_TCLR1 ( 6, ABS ); break; /* TCLR1 abs */
1485 case 0x4f: OP_PCALL ( 6 ); break; /* PCALL */
1486
1487 case 0x50: OP_BCC ( 2, COND_VC() ); break; /* BVC */
1488 case 0x51: OP_TCALL ( 8, 5 ); break; /* TCALL 5 */
1489 case 0x52: OP_CLR ( 4, BIT_2 ); break; /* CLR 2 */
1490 case 0x53: OP_BBC ( 5, BIT_2 ); break; /* BBC 2 */
1491
1492 case 0x54: OP_EOR ( 4, DPX ); break; /* EOR dpx */
1493 case 0x55: OP_EOR ( 5, ABX ); break; /* EOR abx */
1494 case 0x56: OP_EOR ( 5, ABY ); break; /* EOR aby */
1495 case 0x57: OP_EOR ( 6, DIY ); break; /* EOR diy */
1496
1497 case 0x58: OP_EORM ( 5, IMM, DP ); break; /* EOR dp, imm */
1498 case 0x59: OP_EORM ( 5, YI , XI ); break; /* EOR xi, yi */
1499 case 0x5a: OP_CMPW ( 4, DP ); break; /* CMPW dp */
1500 case 0x5b: OP_LSRM ( 5, DPX ); break; /* LSR dpx */
1501
1502 case 0x5c: OP_LSR ( 2 ); break; /* LSR */
1503 case 0x5d: OP_MOVRR ( 2, REG_A, REG_X ); break; /* MOV X, A */
1504 case 0x5e: OP_CMPR ( 4, REG_Y, ABS ); break; /* CMP Y, abs */
1505 case 0x5f: OP_JMP ( 3, ABS ); break; /* JMP abs */
1506
1507 case 0x60: OP_CLRC ( 2 ); break; /* CLRC */
1508 case 0x61: OP_TCALL ( 8, 6 ); break; /* TCALL 6 */
1509 case 0x62: OP_SET ( 4, BIT_3 ); break; /* SET 3 */
1510 case 0x63: OP_BBS ( 5, BIT_3 ); break; /* BBS 3 */
1511
1512 case 0x64: OP_CMPR ( 3, REG_A, DP ); break; /* CMP A, dp */
1513 case 0x65: OP_CMPR ( 4, REG_A, ABS ); break; /* CMP A, abs */
1514 case 0x66: OP_CMPR ( 3, REG_A, XI ); break; /* CMP A, xi */
1515 case 0x67: OP_CMPR ( 6, REG_A, DXI ); break; /* CMP A, dxi */
1516
1517 case 0x68: OP_CMPR ( 2, REG_A, IMM ); break; /* CMP A, imm */
1518 case 0x69: OP_CMPM ( 6, DP, DP ); break; /* CMP dp, dp */
1519 case 0x6a: OP_ANDN1 ( 4 ); break; /* AND1 !bit */
1520 case 0x6b: OP_RORM ( 4, DP ); break; /* ROR dp */
1521
1522 case 0x6c: OP_RORM ( 5, ABS ); break; /* ROR abs */
1523 case 0x6d: OP_PUSH ( 4, REG_Y ); break; /* PUSH Y */
1524 case 0x6e: OP_DBNZM ( 5 ); break; /* DBNZ dp */
1525 case 0x6f: OP_RET ( 5 ); break; /* RET */
1526
1527 case 0x70: OP_BCC ( 2, COND_VS() ); break; /* BVS */
1528 case 0x71: OP_TCALL ( 8, 7 ); break; /* TCALL 7 */
1529 case 0x72: OP_CLR ( 4, BIT_3 ); break; /* CLR 3 */
1530 case 0x73: OP_BBC ( 5, BIT_3 ); break; /* BBC 3 */
1531 case 0x74: OP_CMPR ( 4, REG_A, DPX ); break; /* CMP A, dpx */
1532 case 0x75: OP_CMPR ( 5, REG_A, ABX ); break; /* CMP A, abx */
1533 case 0x76: OP_CMPR ( 5, REG_A, ABY ); break; /* CMP A, aby */
1534 case 0x77: OP_CMPR ( 6, REG_A, DIY ); break; /* CMP A, diy */
1535
1536 case 0x78: OP_CMPM ( 5, IMM, DP ); break; /* CMP dp, imm */
1537 case 0x79: OP_CMPM ( 5, YI, XI ); break; /* CMP xi, yi */
1538 case 0x7a: OP_ADDW ( 5 ); break; /* ADDW di */
1539 case 0x7b: OP_RORM ( 5, DPX ); break; /* ROR dpx */
1540
1541 case 0x7c: OP_ROR ( 2 ); break; /* ROR A */
1542 case 0x7d: OP_MOVRR ( 2, REG_X, REG_A ); break; /* MOV A, X */
1543 case 0x7e: OP_CMPR ( 3, REG_Y, DP ); break; /* CMP Y, dp */
1544 case 0x7f: OP_RETI ( 6 ); break; /* RETI */
1545
1546 case 0x80: OP_SETC ( 2 ); break; /* SETC */
1547 case 0x81: OP_TCALL ( 8, 8 ); break; /* TCALL 8 */
1548 case 0x82: OP_SET ( 4, BIT_4 ); break; /* SET 4 */
1549 case 0x83: OP_BBS ( 5, BIT_4 ); break; /* BBS 4 */
1550
1551 case 0x84: OP_ADC ( 3, DP ); break; /* ADC dp */
1552 case 0x85: OP_ADC ( 4, ABS ); break; /* ADC abs */
1553 case 0x86: OP_ADC ( 3, XI ); break; /* ADC xi */
1554 case 0x87: OP_ADC ( 6, DXI ); break; /* ADC dxi */
1555
1556 case 0x88: OP_ADC ( 2, IMM ); break; /* ADC imm */
1557 case 0x89: OP_ADCM ( 6, DP, DP ); break; /* ADC dp, dp */
1558 case 0x8a: OP_EOR1 ( 5 ); break; /* EOR1 bit */
1559 case 0x8b: OP_DECM ( 4, DP ); break; /* DEC dp */
1560
1561 case 0x8c: OP_DECM ( 5, ABS ); break; /* DEC abs */
1562 case 0x8d: OP_MOVMR ( 2, IMM, REG_Y ); break; /* MOV Y, imm */
1563 case 0x8e: OP_PLP ( 4 ); break; /* POP PSW */
1564 case 0x8f: OP_MOVMM ( 5, IMM, DP ); break; /* MOV dp, imm */
1565
1566 case 0x90: OP_BCC ( 2, COND_CC() ); break; /* BCC */
1567 case 0x91: OP_TCALL ( 8, 9 ); break; /* TCALL 9 */
1568 case 0x92: OP_CLR ( 4, BIT_4 ); break; /* CLR 4 */
1569 case 0x93: OP_BBC ( 5, BIT_4 ); break; /* BBC 4 */
1570
1571 case 0x94: OP_ADC ( 4, DPX ); break; /* ADC dpx */
1572 case 0x95: OP_ADC ( 5, ABX ); break; /* ADC abx */
1573 case 0x96: OP_ADC ( 5, ABY ); break; /* ADC aby */
1574 case 0x97: OP_ADC ( 6, DIY ); break; /* ADC diy */
1575
1576 case 0x98: OP_ADCM ( 5, IMM, DP ); break; /* ADC dp, imm */
1577 case 0x99: OP_ADCM ( 5, YI, XI ); break; /* ADC xi, yi */
1578 case 0x9a: OP_SUBW ( 5 ); break; /* SUBW dp */
1579 case 0x9b: OP_DECM ( 5, DPX ); break; /* DEC dpx */
1580
1581 case 0x9c: OP_DECR ( 2, REG_A ); break; /* DEC A */
1582 case 0x9d: OP_MOVSX ( 2 ); break; /* MOV X, SP */
1583 case 0x9e: OP_DIV (12 ); break; /* DIV YA, X */
1584 case 0x9f: OP_XCN ( 5 ); break; /* XCN A */
1585
1586 case 0xa0: OP_EI ( 3 ); break; /* EI */
1587 case 0xa1: OP_TCALL ( 8, 10 ); break; /* TCALL 10 */
1588 case 0xa2: OP_SET ( 4, BIT_5 ); break; /* SET 5 */
1589 case 0xa3: OP_BBS ( 5, BIT_5 ); break; /* BBS 5 */
1590
1591 case 0xa4: OP_SBC ( 3, DP ); break; /* SBC dp */
1592 case 0xa5: OP_SBC ( 4, ABS ); break; /* SBC abs */
1593 case 0xa6: OP_SBC ( 3, XI ); break; /* SBC xi */
1594 case 0xa7: OP_SBC ( 6, DXI ); break; /* SBC dxi */
1595
1596 case 0xa8: OP_SBC ( 2, IMM ); break; /* SBC imm */
1597 case 0xa9: OP_SBCM ( 6, DP, DP ); break; /* SBC dp, dp */
1598 case 0xaa: OP_MOV1C ( 4 ); break; /* MOV1 bit->C */
1599 case 0xab: OP_INCM ( 4, DP ); break; /* INC dp */
1600
1601 case 0xac: OP_INCM ( 5, ABS ); break; /* INC abs */
1602 case 0xad: OP_CMPR ( 2, REG_Y, IMM ); break; /* CMP Y, imm */
1603 case 0xae: OP_PULL ( 4, REG_A ); break; /* POP A */
1604 case 0xaf: OP_MOVRM ( 4, REG_A, XII ); break; /* MOV xii, A */
1605
1606 case 0xb0: OP_BCC ( 2, COND_CS() ); break; /* BCS */
1607 case 0xb1: OP_TCALL ( 8, 11 ); break; /* TCALL 11 */
1608 case 0xb2: OP_CLR ( 4, BIT_5 ); break; /* CLR 5 */
1609 case 0xb3: OP_BBC ( 5, BIT_5 ); break; /* BBC 5 */
1610
1611 case 0xb4: OP_SBC ( 4, DPX ); break; /* SBC dpx */
1612 case 0xb5: OP_SBC ( 5, ABX ); break; /* SBC abx */
1613 case 0xb6: OP_SBC ( 5, ABY ); break; /* SBC aby */
1614 case 0xb7: OP_SBC ( 6, DIY ); break; /* SBC diy */
1615
1616 case 0xb8: OP_SBCM ( 5, IMM, DP ); break; /* SBC dp, imm */
1617 case 0xb9: OP_SBCM ( 5, YI, XI ); break; /* SBC xi, yi */
1618 case 0xba: OP_MOVWMR( 5 ); break; /* MOVW YA, dp */
1619 case 0xbb: OP_INCM ( 5, DPX ); break; /* INC dpx */
1620
1621 case 0xbc: OP_INCR ( 2, REG_A ); break; /* INC A */
1622 case 0xbd: OP_MOVXS ( 2 ); break; /* MOV SP, X */
1623 case 0xbe: OP_DAS ( 3 ); break; /* DAS A */
1624 case 0xbf: OP_MOVMR ( 4, XII, REG_A ); break; /* MOV A, xii */
1625
1626 case 0xc0: OP_DI ( 3 ); break; /* DI */
1627 case 0xc1: OP_TCALL ( 8, 12 ); break; /* TCALL 12 */
1628 case 0xc2: OP_SET ( 4, BIT_6 ); break; /* SET 6 */
1629 case 0xc3: OP_BBS ( 5, BIT_6 ); break; /* BBS 6 */
1630 case 0xc4: OP_MOVRM ( 4, REG_A, DP ); break; /* MOV dp, A */
1631 case 0xc5: OP_MOVRM ( 5, REG_A, ABS ); break; /* MOV abs, A */
1632 case 0xc6: OP_MOVRM ( 4, REG_A, XI ); break; /* MOV xi, A */
1633 case 0xc7: OP_MOVRM ( 7, REG_A, DXI ); break; /* MOV dxi, A */
1634
1635 case 0xc8: OP_CMPR ( 2, REG_X, IMM ); break; /* CMP X, imm */
1636 case 0xc9: OP_MOVRM ( 5, REG_X, ABS ); break; /* MOV abs, X */
1637 case 0xca: OP_MOV1M ( 6 ); break; /* MOV1 C->bit */
1638 case 0xcb: OP_MOVRM ( 4, REG_Y, DP ); break; /* MOV dp, Y */
1639
1640 case 0xcc: OP_MOVRM ( 5, REG_Y, ABS ); break; /* MOV abs, Y */
1641 case 0xcd: OP_MOVMR ( 2, IMM, REG_X ); break; /* MOV X, imm */
1642 case 0xce: OP_PULL ( 4, REG_X ); break; /* POP X */
1643 case 0xcf: OP_MUL ( 9 ); break; /* MUL YA */
1644
1645 case 0xd0: OP_BCC ( 2, COND_NE() ); break; /* BNE */
1646 case 0xd1: OP_TCALL ( 8, 13 ); break; /* TCALL 13 */
1647 case 0xd2: OP_CLR ( 4, BIT_6 ); break; /* CLR 6 */
1648 case 0xd3: OP_BBC ( 5, BIT_6 ); break; /* BBC 6 */
1649
1650 case 0xd4: OP_MOVRM ( 5, REG_A, DPX ); break; /* MOV dpx, A */
1651 case 0xd5: OP_MOVRM ( 6, REG_A, ABX ); break; /* MOV abx, A */
1652 case 0xd6: OP_MOVRM ( 6, REG_A, ABY ); break; /* MOV aby, A */
1653 case 0xd7: OP_MOVRM ( 7, REG_A, DIY ); break; /* MOV diy, A */
1654
1655 case 0xd8: OP_MOVRM ( 4, REG_X, DP ); break; /* MOV dp, X */
1656 case 0xd9: OP_MOVRM ( 5, REG_X, DPY ); break; /* MOV dpy, X */
1657 case 0xda: OP_MOVWRM( 5 ); break; /* MOVW dp, YA */
1658 case 0xdb: OP_MOVRM ( 5, REG_Y, DPX ); break; /* MOV dpx, Y */
1659
1660 case 0xdc: OP_DECR ( 2, REG_Y ); break; /* DEC Y */
1661 case 0xdd: OP_MOVRR ( 2, REG_Y, REG_A ); break; /* MOV A, Y */
1662 case 0xde: OP_CBNE ( 6, DPX ); break; /* CBNE dpx */
1663 case 0xdf: OP_DAA ( 3 ); break; /* DAA */
1664
1665 case 0xe0: OP_CLRV ( 2 ); break; /* CLRV */
1666 case 0xe1: OP_TCALL ( 8, 14 ); break; /* TCALL 14 */
1667 case 0xe2: OP_SET ( 4, BIT_7 ); break; /* SET 7 */
1668 case 0xe3: OP_BBS ( 5, BIT_7 ); break; /* BBS 7 */
1669
1670 case 0xe4: OP_MOVMR ( 3, DP, REG_A ); break; /* MOV A, dp */
1671 case 0xe5: OP_MOVMR ( 4, ABS, REG_A ); break; /* MOV A, abs */
1672 case 0xe6: OP_MOVMR ( 3, XI, REG_A ); break; /* MOV A, xi */
1673 case 0xe7: OP_MOVMR ( 6, DXI, REG_A ); break; /* MOV A, dxi */
1674
1675 case 0xe8: OP_MOVMR ( 2, IMM, REG_A ); break; /* CMP A, imm */
1676 case 0xe9: OP_MOVMR ( 4, ABS, REG_X ); break; /* MOV X, abs */
1677 case 0xea: OP_NOT1 ( 5 ); break; /* NOT1 */
1678 case 0xeb: OP_MOVMR ( 3, DP, REG_Y ); break; /* MOV Y, dp */
1679
1680 case 0xec: OP_MOVMR ( 4, ABS, REG_Y ); break; /* MOV Y, abs */
1681 case 0xed: OP_NOTC ( 3 ); break; /* NOTC */
1682 case 0xee: OP_PULL ( 4, REG_Y ); break; /* POP Y */
1683 case 0xef: OP_SLEEP ( 1 ); break; /* SLEEP */
1684
1685 case 0xf0: OP_BCC ( 2, COND_EQ() ); break; /* BEQ */
1686 case 0xf1: OP_TCALL ( 8, 15 ); break; /* TCALL1 5 */
1687 case 0xf2: OP_CLR ( 4, BIT_7 ); break; /* CLR 7 */
1688 case 0xf3: OP_BBC ( 5, BIT_7 ); break; /* BBC 7 */
1689
1690 case 0xf4: OP_MOVMR ( 4, DPX, REG_A ); break; /* MOV A, dpx */
1691 case 0xf5: OP_MOVMR ( 5, ABX, REG_A ); break; /* MOV A, abx */
1692 case 0xf6: OP_MOVMR ( 5, ABY, REG_A ); break; /* MOV A, aby */
1693 case 0xf7: OP_MOVMR ( 6, DIY, REG_A ); break; /* MOV A, diy */
1694
1695 case 0xf8: OP_MOVMR ( 3, DP, REG_X ); break; /* MOV X, dp */
1696 case 0xf9: OP_MOVMR ( 4, DPY, REG_X ); break; /* MOV X, dpy */
1697 case 0xfa: OP_MOVMM ( 5, DP, DP ); break; /* MOV dp, dp */
1698 case 0xfb: OP_MOVMR ( 4, DPX, REG_Y ); break; /* MOV Y, DPX */
1699 case 0xfc: OP_INCR ( 2, REG_Y ); break; /* INC Y */
1700 case 0xfd: OP_MOVRR ( 2, REG_A, REG_Y ); break; /* MOV Y, A */
1701 case 0xfe: OP_DBNZR ( 4 ); break; /* DBNZ Y */
1702 case 0xff: OP_STOP ( 1 ); break; /* STOP */
1703 }
1704 }
1705 }
1706
1707 /* ======================================================================== */
1708 /* ============================== END OF FILE ============================= */
1709 /* ======================================================================== */
1710