1 /***********************************************************************************
2   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3 
4   (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5                              Jerremy Koot (jkoot@snes9x.com)
6 
7   (c) Copyright 2002 - 2004  Matthew Kendora
8 
9   (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10 
11   (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12 
13   (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14 
15   (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16                              Kris Bleakley (codeviolation@hotmail.com)
17 
18   (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19                              Nach (n-a-c-h@users.sourceforge.net),
20                              zones (kasumitokoduck@yahoo.com)
21 
22   (c) Copyright 2006 - 2007  nitsuja
23 
24   (c) Copyright 2009 - 2010  BearOso,
25                              OV2
26 
27 
28   BS-X C emulator code
29   (c) Copyright 2005 - 2006  Dreamer Nom,
30                              zones
31 
32   C4 x86 assembler and some C emulation code
33   (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
34                              Nach,
35                              zsKnight (zsknight@zsnes.com)
36 
37   C4 C++ code
38   (c) Copyright 2003 - 2006  Brad Jorsch,
39                              Nach
40 
41   DSP-1 emulator code
42   (c) Copyright 1998 - 2006  _Demo_,
43                              Andreas Naive (andreasnaive@gmail.com),
44                              Gary Henderson,
45                              Ivar (ivar@snes9x.com),
46                              John Weidman,
47                              Kris Bleakley,
48                              Matthew Kendora,
49                              Nach,
50                              neviksti (neviksti@hotmail.com)
51 
52   DSP-2 emulator code
53   (c) Copyright 2003         John Weidman,
54                              Kris Bleakley,
55                              Lord Nightmare (lord_nightmare@users.sourceforge.net),
56                              Matthew Kendora,
57                              neviksti
58 
59   DSP-3 emulator code
60   (c) Copyright 2003 - 2006  John Weidman,
61                              Kris Bleakley,
62                              Lancer,
63                              z80 gaiden
64 
65   DSP-4 emulator code
66   (c) Copyright 2004 - 2006  Dreamer Nom,
67                              John Weidman,
68                              Kris Bleakley,
69                              Nach,
70                              z80 gaiden
71 
72   OBC1 emulator code
73   (c) Copyright 2001 - 2004  zsKnight,
74                              pagefault (pagefault@zsnes.com),
75                              Kris Bleakley
76                              Ported from x86 assembler to C by sanmaiwashi
77 
78   SPC7110 and RTC C++ emulator code used in 1.39-1.51
79   (c) Copyright 2002         Matthew Kendora with research by
80                              zsKnight,
81                              John Weidman,
82                              Dark Force
83 
84   SPC7110 and RTC C++ emulator code used in 1.52+
85   (c) Copyright 2009         byuu,
86                              neviksti
87 
88   S-DD1 C emulator code
89   (c) Copyright 2003         Brad Jorsch with research by
90                              Andreas Naive,
91                              John Weidman
92 
93   S-RTC C emulator code
94   (c) Copyright 2001 - 2006  byuu,
95                              John Weidman
96 
97   ST010 C++ emulator code
98   (c) Copyright 2003         Feather,
99                              John Weidman,
100                              Kris Bleakley,
101                              Matthew Kendora
102 
103   Super FX x86 assembler emulator code
104   (c) Copyright 1998 - 2003  _Demo_,
105                              pagefault,
106                              zsKnight
107 
108   Super FX C emulator code
109   (c) Copyright 1997 - 1999  Ivar,
110                              Gary Henderson,
111                              John Weidman
112 
113   Sound emulator code used in 1.5-1.51
114   (c) Copyright 1998 - 2003  Brad Martin
115   (c) Copyright 1998 - 2006  Charles Bilyue'
116 
117   Sound emulator code used in 1.52+
118   (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
119 
120   SH assembler code partly based on x86 assembler code
121   (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
122 
123   2xSaI filter
124   (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
125 
126   HQ2x, HQ3x, HQ4x filters
127   (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
128 
129   NTSC filter
130   (c) Copyright 2006 - 2007  Shay Green
131 
132   GTK+ GUI code
133   (c) Copyright 2004 - 2010  BearOso
134 
135   Win32 GUI code
136   (c) Copyright 2003 - 2006  blip,
137                              funkyass,
138                              Matthew Kendora,
139                              Nach,
140                              nitsuja
141   (c) Copyright 2009 - 2010  OV2
142 
143   Mac OS GUI code
144   (c) Copyright 1998 - 2001  John Stiles
145   (c) Copyright 2001 - 2010  zones
146 
147   (c) Copyright 2010 - 2016 Daniel De Matteis. (UNDER NO CIRCUMSTANCE
148   WILL COMMERCIAL RIGHTS EVER BE APPROPRIATED TO ANY PARTY)
149 
150   Specific ports contains the works of other authors. See headers in
151   individual files.
152 
153 
154   Snes9x homepage: http://www.snes9x.com/
155 
156   Permission to use, copy, modify and/or distribute Snes9x in both binary
157   and source form, for non-commercial purposes, is hereby granted without
158   fee, providing that this license information and copyright notice appear
159   with all copies and any derived work.
160 
161   This software is provided 'as-is', without any express or implied
162   warranty. In no event shall the authors be held liable for any damages
163   arising from the use of this software or it's derivatives.
164 
165   Snes9x is freeware for PERSONAL USE only. Commercial users should
166   seek permission of the copyright holders first. Commercial use includes,
167   but is not limited to, charging money for Snes9x or software derived from
168   Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
169   using Snes9x as a promotion for your commercial product.
170 
171   The copyright holders request that bug fixes and improvements to the code
172   should be forwarded to them so everyone can benefit from the modifications
173   in future versions.
174 
175   Super NES and Super Nintendo Entertainment System are trademarks of
176   Nintendo Co., Limited and its subsidiary companies.
177  ***********************************************************************************/
178 
179 
180 #ifndef _CPUMACRO_H_
181 #define _CPUMACRO_H_
182 
183 #define rOP8(OP, ADDR, WRAP, FUNC) \
184 static void Op##OP (void) \
185 { \
186 	uint8	val = OpenBus = S9xGetByte(ADDR(READ)); \
187 	FUNC##8(val); \
188 }
189 
190 #define rOP16(OP, ADDR, WRAP, FUNC) \
191 static void Op##OP (void) \
192 { \
193 	uint16	val = S9xGetWord(ADDR(READ), WRAP); \
194 	OpenBus = (uint8) (val >> 8); \
195 	FUNC(val); \
196 }
197 
198 #define rOPC(OP, COND, ADDR, WRAP, FUNC) \
199 static void Op##OP (void) \
200 { \
201 	if (Check##COND()) \
202 	{ \
203 		uint8	val = OpenBus = S9xGetByte(ADDR(READ)); \
204 		FUNC##8(val); \
205 	} \
206 	else \
207 	{ \
208 		uint16	val = S9xGetWord(ADDR(READ), WRAP); \
209 		OpenBus = (uint8) (val >> 8); \
210 		FUNC##16(val); \
211 	} \
212 }
213 
214 #define rOPM(OP, ADDR, WRAP, FUNC) \
215 rOPC(OP, Memory, ADDR, WRAP, FUNC)
216 
217 #define rOPX(OP, ADDR, WRAP, FUNC) \
218 rOPC(OP, Index, ADDR, WRAP, FUNC)
219 
220 #define wOP8(OP, ADDR, WRAP, FUNC) \
221 static void Op##OP (void) \
222 { \
223 	FUNC##8(ADDR(WRITE)); \
224 }
225 
226 #define wOP16(OP, ADDR, WRAP, FUNC) \
227 static void Op##OP (void) \
228 { \
229 	FUNC##16(ADDR(WRITE), WRAP); \
230 }
231 
232 #define wOPC(OP, COND, ADDR, WRAP, FUNC) \
233 static void Op##OP (void) \
234 { \
235 	if (Check##COND()) \
236 		FUNC##8(ADDR(WRITE)); \
237 	else \
238 		FUNC##16(ADDR(WRITE), WRAP); \
239 }
240 
241 #define wOPM(OP, ADDR, WRAP, FUNC) \
242 wOPC(OP, Memory, ADDR, WRAP, FUNC)
243 
244 #define wOPX(OP, ADDR, WRAP, FUNC) \
245 wOPC(OP, Index, ADDR, WRAP, FUNC)
246 
247 #define mOP8(OP, ADDR, WRAP, FUNC) \
248 static void Op##OP (void) \
249 { \
250 	FUNC##8(ADDR(MODIFY)); \
251 }
252 
253 #define mOP16(OP, ADDR, WRAP, FUNC) \
254 static void Op##OP (void) \
255 { \
256 	FUNC##16(ADDR(MODIFY), WRAP); \
257 }
258 
259 #define mOPC(OP, COND, ADDR, WRAP, FUNC) \
260 static void Op##OP (void) \
261 { \
262 	if (Check##COND()) \
263 		FUNC##8(ADDR(MODIFY)); \
264 	else \
265 		FUNC##16(ADDR(MODIFY), WRAP); \
266 }
267 
268 #define mOPM(OP, ADDR, WRAP, FUNC) \
269 mOPC(OP, Memory, ADDR, WRAP, FUNC)
270 
271 #define bOP(OP, REL, COND, CHK, E) \
272 static void Op##OP (void) \
273 { \
274 	pair	newPC; \
275 	newPC.W = REL(JUMP); \
276 	if (COND) \
277 	{ \
278 		AddCycles(ONE_CYCLE); \
279 		if (E && Registers.PCh != newPC.B.h) \
280 			AddCycles(ONE_CYCLE); \
281 		if ((Registers.PCw & ~MEMMAP_MASK) != (newPC.W & ~MEMMAP_MASK)) \
282 			S9xSetPCBase(ICPU.ShiftedPB + newPC.W); \
283 		else \
284 			Registers.PCw = newPC.W; \
285 	} \
286 }
287 
288 
289 #define SetZN16(Work16) \
290 	ICPU._Zero = Work16 != 0; \
291 	ICPU._Negative = (uint8) (Work16 >> 8);
292 
293 #define SetZN8(Work8) \
294 	ICPU._Zero = Work8; \
295 	ICPU._Negative = Work8;
296 
ADC16(uint16 Work16)297 static INLINE void ADC16(uint16 Work16)
298 {
299 	if (CheckDecimal())
300 	{
301 		uint16 Ans16;
302 		uint16	A1 = Registers.A.W & 0x000F;
303 		uint16	A2 = Registers.A.W & 0x00F0;
304 		uint16	A3 = Registers.A.W & 0x0F00;
305 		uint32	A4 = Registers.A.W & 0xF000;
306 		uint16	W1 = Work16 & 0x000F;
307 		uint16	W2 = Work16 & 0x00F0;
308 		uint16	W3 = Work16 & 0x0F00;
309 		uint16	W4 = Work16 & 0xF000;
310 
311 		A1 += W1 + CheckCarry();
312 		if (A1 > 0x0009)
313 		{
314 			A1 -= 0x000A;
315 			A1 &= 0x000F;
316 			A2 += 0x0010;
317 		}
318 
319 		A2 += W2;
320 		if (A2 > 0x0090)
321 		{
322 			A2 -= 0x00A0;
323 			A2 &= 0x00F0;
324 			A3 += 0x0100;
325 		}
326 
327 		A3 += W3;
328 		if (A3 > 0x0900)
329 		{
330 			A3 -= 0x0A00;
331 			A3 &= 0x0F00;
332 			A4 += 0x1000;
333 		}
334 
335 		A4 += W4;
336 		if (A4 > 0x9000)
337 		{
338 			A4 -= 0xA000;
339 			A4 &= 0xF000;
340 			SetCarry();
341 		}
342 		else
343 			ClearCarry();
344 
345 		Ans16 = A4 | A3 | A2 | A1;
346 
347 		if (~(Registers.A.W ^ Work16) & (Work16 ^ Ans16) & 0x8000)
348 			SetOverflow();
349 		else
350 			ClearOverflow();
351 
352 		Registers.A.W = Ans16;
353 	}
354 	else
355 	{
356 		uint32	Ans32 = Registers.A.W + Work16 + CheckCarry();
357 
358 		ICPU._Carry = Ans32 >= 0x10000;
359 
360 		if (~(Registers.A.W ^ Work16) & (Work16 ^ (uint16) Ans32) & 0x8000)
361 			SetOverflow();
362 		else
363 			ClearOverflow();
364 
365 		Registers.A.W = (uint16) Ans32;
366 	}
367 	SetZN16(Registers.A.W);
368 }
369 
ADC8(uint8 Work8)370 static INLINE void ADC8(uint8 Work8)
371 {
372 	if (CheckDecimal())
373 	{
374 		uint8 A1, W1, W2, Ans8;
375 		uint16 A2;
376 
377 		A1 = Registers.A.W & 0x0F;
378 		A2 = Registers.A.W & 0xF0;
379 		W1 = Work8 & 0x0F;
380 		W2 = Work8 & 0xF0;
381 
382 		A1 += W1 + CheckCarry();
383 		if (A1 > 0x09)
384 		{
385 			A1 -= 0x0A;
386 			A1 &= 0x0F;
387 			A2 += 0x10;
388 		}
389 
390 		A2 += W2;
391 		if (A2 > 0x90)
392 		{
393 			A2 -= 0xA0;
394 			A2 &= 0xF0;
395 			SetCarry();
396 		}
397 		else
398 			ClearCarry();
399 
400 		Ans8 = A2 | A1;
401 
402 		if (~(Registers.AL ^ Work8) & (Work8 ^ Ans8) & 0x80)
403 			SetOverflow();
404 		else
405 			ClearOverflow();
406 
407 		Registers.AL = Ans8;
408 	}
409 	else
410 	{
411 		uint16	Ans16 = Registers.AL + Work8 + CheckCarry();
412 
413 		ICPU._Carry = Ans16 >= 0x100;
414 
415 		if (~(Registers.AL ^ Work8) & (Work8 ^ (uint8) Ans16) & 0x80)
416 			SetOverflow();
417 		else
418 			ClearOverflow();
419 
420 		Registers.AL = (uint8) Ans16;
421 	}
422 	SetZN8(Registers.AL);
423 }
424 
AND16(uint16 Work16)425 static INLINE void AND16(uint16 Work16)
426 {
427 	Registers.A.W &= Work16;
428 	SetZN16(Registers.A.W);
429 }
430 
AND8(uint8 Work8)431 static INLINE void AND8(uint8 Work8)
432 {
433 	Registers.AL &= Work8;
434 	SetZN8(Registers.AL);
435 }
436 
ASL16(uint32 OpAddress,uint32 w)437 static INLINE void ASL16 (uint32 OpAddress, uint32 w)
438 {
439 	uint16	Work16 = S9xGetWord(OpAddress, w);
440 	ICPU._Carry = (Work16 & 0x8000) != 0;
441 	Work16 <<= 1;
442 	AddCycles(ONE_CYCLE);
443 	S9xSetWord_Write1(Work16, OpAddress, w);
444 	OpenBus = Work16 & 0xff;
445 	SetZN16(Work16);
446 }
447 
ASL8(uint32 OpAddress)448 static INLINE void ASL8 (uint32 OpAddress)
449 {
450 	uint8	Work8 = S9xGetByte(OpAddress);
451 	ICPU._Carry = (Work8 & 0x80) != 0;
452 	Work8 <<= 1;
453 	AddCycles(ONE_CYCLE);
454 	S9xSetByte(Work8, OpAddress);
455 	OpenBus = Work8;
456 	SetZN8(Work8);
457 }
458 
BIT16(uint16 Work16)459 static INLINE void BIT16(uint16 Work16)
460 {
461 	ICPU._Overflow = (Work16 & 0x4000) != 0;
462 	ICPU._Negative = (uint8) (Work16 >> 8);
463 	ICPU._Zero = (Work16 & Registers.A.W) != 0;
464 }
465 
BIT8(uint8 Work8)466 static INLINE void BIT8(uint8 Work8)
467 {
468 	ICPU._Overflow = (Work8 & 0x40) != 0;
469 	ICPU._Negative = Work8;
470 	ICPU._Zero = Work8 & Registers.AL;
471 }
472 
CMP16(uint16 val)473 static INLINE void CMP16(uint16 val)
474 {
475 	int16 Int16;
476 	int32 Int32;
477 
478 	Int32 = (int32) Registers.A.W - (int32) val;
479 	ICPU._Carry = Int32 >= 0;
480 	Int16 = Int32;
481 	SetZN16(Int16);
482 }
483 
CMP8(uint8 val)484 static INLINE void CMP8(uint8 val)
485 {
486 	int16 Int16;
487 	uint8 Int8;
488 
489 	Int16 = (int16) Registers.AL - (int16) val;
490 	ICPU._Carry = Int16 >= 0;
491 	Int8 = Int16;
492 	SetZN8(Int8);
493 }
494 
CPX16(uint16 val)495 static INLINE void CPX16(uint16 val)
496 {
497 	int32 Int32;
498 	uint16 Int16;
499 
500 	Int32 = (int32) Registers.X.W - (int32) val;
501 	ICPU._Carry = Int32 >= 0;
502 	Int16 = Int32;
503 	SetZN16(Int16);
504 }
505 
CPX8(uint8 val)506 static INLINE void CPX8(uint8 val)
507 {
508 	int16 Int16;
509 	uint8 Int8;
510 
511 	Int16 = (int16) Registers.XL - (int16) val;
512 	ICPU._Carry = Int16 >= 0;
513 	Int8 = Int16;
514 	SetZN8(Int8);
515 }
516 
CPY16(uint16 val)517 static INLINE void CPY16(uint16 val)
518 {
519 	int32 Int32;
520 	uint16 Int16;
521 
522 	Int32 = (int32) Registers.Y.W - (int32) val;
523 	ICPU._Carry = Int32 >= 0;
524 	Int16 = Int32;
525 	SetZN16(Int16);
526 }
527 
CPY8(uint8 val)528 static INLINE void CPY8(uint8 val)
529 {
530 	int16 Int16;
531 	uint8 Int8;
532 
533 	Int16 = (int16) Registers.YL - (int16) val;
534 	ICPU._Carry = Int16 >= 0;
535 	Int8 = Int16;
536 	SetZN8(Int8);
537 }
538 
DEC16(uint32 OpAddress,uint32 w)539 static INLINE void DEC16 (uint32 OpAddress, uint32 w)
540 {
541 	uint16 Work16;
542 
543 	Work16 = S9xGetWord(OpAddress, w) - 1;
544 	AddCycles(ONE_CYCLE);
545 	S9xSetWord_Write1(Work16, OpAddress, w);
546 	OpenBus = Work16 & 0xff;
547 	SetZN16(Work16);
548 }
549 
DEC8(uint32 OpAddress)550 static INLINE void DEC8 (uint32 OpAddress)
551 {
552 	uint8	Work8 = S9xGetByte(OpAddress) - 1;
553 	AddCycles(ONE_CYCLE);
554 	S9xSetByte(Work8, OpAddress);
555 	OpenBus = Work8;
556 	SetZN8(Work8);
557 }
558 
EOR16(uint16 val)559 static INLINE void EOR16(uint16 val)
560 {
561 	Registers.A.W ^= val;
562 	SetZN16(Registers.A.W);
563 }
564 
EOR8(uint8 val)565 static INLINE void EOR8(uint8 val)
566 {
567 	Registers.AL ^= val;
568 	SetZN8(Registers.AL);
569 }
570 
INC16(uint32 OpAddress,uint32 w)571 static INLINE void INC16 (uint32 OpAddress, uint32 w)
572 {
573 	uint16	Work16 = S9xGetWord(OpAddress, w) + 1;
574 	AddCycles(ONE_CYCLE);
575 	S9xSetWord_Write1(Work16, OpAddress, w);
576 	OpenBus = Work16 & 0xff;
577 	SetZN16(Work16);
578 }
579 
INC8(uint32 OpAddress)580 static INLINE void INC8 (uint32 OpAddress)
581 {
582 	uint8	Work8 = S9xGetByte(OpAddress) + 1;
583 	AddCycles(ONE_CYCLE);
584 	S9xSetByte(Work8, OpAddress);
585 	OpenBus = Work8;
586 	SetZN8(Work8);
587 }
588 
LDA16(uint16 val)589 static INLINE void LDA16(uint16 val)
590 {
591 	Registers.A.W = val;
592 	SetZN16(Registers.A.W);
593 }
594 
LDA8(uint8 val)595 static INLINE void LDA8(uint8 val)
596 {
597 	Registers.AL = val;
598 	SetZN8(Registers.AL);
599 }
600 
LDX16(uint16 val)601 static INLINE void LDX16(uint16 val)
602 {
603 	Registers.X.W = val;
604 	SetZN16(Registers.X.W);
605 }
606 
LDX8(uint8 val)607 static INLINE void LDX8(uint8 val)
608 {
609 	Registers.XL = val;
610 	SetZN8(Registers.XL);
611 }
612 
LDY16(uint16 val)613 static INLINE void LDY16(uint16 val)
614 {
615 	Registers.Y.W = val;
616 	SetZN16(Registers.Y.W);
617 }
618 
LDY8(uint8 val)619 static INLINE void LDY8(uint8 val)
620 {
621 	Registers.YL = val;
622 	SetZN8(Registers.YL);
623 }
624 
LSR16(uint32 OpAddress,uint32 w)625 static INLINE void LSR16 (uint32 OpAddress, uint32 w)
626 {
627 	uint16	Work16 = S9xGetWord(OpAddress, w);
628 	ICPU._Carry = Work16 & 1;
629 	Work16 >>= 1;
630 	AddCycles(ONE_CYCLE);
631 	S9xSetWord_Write1(Work16, OpAddress, w);
632 	OpenBus = Work16 & 0xff;
633 	SetZN16(Work16);
634 }
635 
LSR8(uint32 OpAddress)636 static INLINE void LSR8 (uint32 OpAddress)
637 {
638 	uint8	Work8 = S9xGetByte(OpAddress);
639 	ICPU._Carry = Work8 & 1;
640 	Work8 >>= 1;
641 	AddCycles(ONE_CYCLE);
642 	S9xSetByte(Work8, OpAddress);
643 	OpenBus = Work8;
644 	SetZN8(Work8);
645 }
646 
ORA16(uint16 val)647 static INLINE void ORA16(uint16 val)
648 {
649 	Registers.A.W |= val;
650 	SetZN16(Registers.A.W);
651 }
652 
ORA8(uint8 val)653 static INLINE void ORA8(uint8 val)
654 {
655 	Registers.AL |= val;
656 	SetZN8(Registers.AL);
657 }
658 
ROL16(uint32 OpAddress,uint32 w)659 static INLINE void ROL16 (uint32 OpAddress, uint32 w)
660 {
661 	uint32	Work32 = (((uint32) S9xGetWord(OpAddress, w)) << 1) | CheckCarry();
662 	ICPU._Carry = Work32 >= 0x10000;
663 	AddCycles(ONE_CYCLE);
664 	S9xSetWord_Write1((uint16) Work32, OpAddress, w);
665 	OpenBus = Work32 & 0xff;
666 	SetZN16((uint16) Work32);
667 }
668 
ROL8(uint32 OpAddress)669 static INLINE void ROL8 (uint32 OpAddress)
670 {
671 	uint16	Work16 = (((uint16) S9xGetByte(OpAddress)) << 1) | CheckCarry();
672 	ICPU._Carry = Work16 >= 0x100;
673 	AddCycles(ONE_CYCLE);
674 	S9xSetByte((uint8) Work16, OpAddress);
675 	OpenBus = Work16 & 0xff;
676 	SetZN8((uint8) Work16);
677 }
678 
ROR16(uint32 OpAddress,uint32 w)679 static INLINE void ROR16 (uint32 OpAddress, uint32 w)
680 {
681 	uint32	Work32 = ((uint32) S9xGetWord(OpAddress, w)) | (((uint32) CheckCarry()) << 16);
682 	ICPU._Carry = Work32 & 1;
683 	Work32 >>= 1;
684 	AddCycles(ONE_CYCLE);
685 	S9xSetWord_Write1((uint16) Work32, OpAddress, w);
686 	OpenBus = Work32 & 0xff;
687 	SetZN16((uint16) Work32);
688 }
689 
ROR8(uint32 OpAddress)690 static INLINE void ROR8 (uint32 OpAddress)
691 {
692 	uint16	Work16 = ((uint16) S9xGetByte(OpAddress)) | (((uint16) CheckCarry()) << 8);
693 	ICPU._Carry = Work16 & 1;
694 	Work16 >>= 1;
695 	AddCycles(ONE_CYCLE);
696 	S9xSetByte((uint8) Work16, OpAddress);
697 	OpenBus = Work16 & 0xff;
698 	SetZN8((uint8) Work16);
699 }
700 
SBC16(uint16 Work16)701 static INLINE void SBC16(uint16 Work16)
702 {
703 	if (CheckDecimal())
704 	{
705 		uint16 Ans16;
706 		uint16	A1 = Registers.A.W & 0x000F;
707 		uint16	A2 = Registers.A.W & 0x00F0;
708 		uint16	A3 = Registers.A.W & 0x0F00;
709 		uint32	A4 = Registers.A.W & 0xF000;
710 		uint16	W1 = Work16 & 0x000F;
711 		uint16	W2 = Work16 & 0x00F0;
712 		uint16	W3 = Work16 & 0x0F00;
713 		uint16	W4 = Work16 & 0xF000;
714 
715 		A1 -= W1 + !CheckCarry();
716 		A2 -= W2;
717 		A3 -= W3;
718 		A4 -= W4;
719 
720 		if (A1 > 0x000F)
721 		{
722 			A1 += 0x000A;
723 			A1 &= 0x000F;
724 			A2 -= 0x0010;
725 		}
726 
727 		if (A2 > 0x00F0)
728 		{
729 			A2 += 0x00A0;
730 			A2 &= 0x00F0;
731 			A3 -= 0x0100;
732 		}
733 
734 		if (A3 > 0x0F00)
735 		{
736 			A3 += 0x0A00;
737 			A3 &= 0x0F00;
738 			A4 -= 0x1000;
739 		}
740 
741 		if (A4 > 0xF000)
742 		{
743 			A4 += 0xA000;
744 			A4 &= 0xF000;
745 			ClearCarry();
746 		}
747 		else
748 			SetCarry();
749 
750 		Ans16 = A4 | A3 | A2 | A1;
751 
752 		if ((Registers.A.W ^ Work16) & (Registers.A.W ^ Ans16) & 0x8000)
753 			SetOverflow();
754 		else
755 			ClearOverflow();
756 
757 		Registers.A.W = Ans16;
758 	}
759 	else
760 	{
761 		int32	Int32 = (int32) Registers.A.W - (int32) Work16 + (int32) CheckCarry() - 1;
762 
763 		ICPU._Carry = Int32 >= 0;
764 
765 		if ((Registers.A.W ^ Work16) & (Registers.A.W ^ (uint16) Int32) & 0x8000)
766 			SetOverflow();
767 		else
768 			ClearOverflow();
769 
770 		Registers.A.W = (uint16) Int32;
771 	}
772 	SetZN16(Registers.A.W);
773 }
774 
SBC8(uint8 Work8)775 static INLINE void SBC8(uint8 Work8)
776 {
777 	if (CheckDecimal())
778 	{
779 		uint8 A1, W1, W2, Ans8;
780 		uint16 A2;
781 
782 		A1 = Registers.A.W & 0x0F;
783 		A2 = Registers.A.W & 0xF0;
784 		W1 = Work8 & 0x0F;
785 		W2 = Work8 & 0xF0;
786 
787 		A1 -= W1 + !CheckCarry();
788 		A2 -= W2;
789 
790 		if (A1 > 0x0F)
791 		{
792 			A1 += 0x0A;
793 			A1 &= 0x0F;
794 			A2 -= 0x10;
795 		}
796 
797 		if (A2 > 0xF0)
798 		{
799 			A2 += 0xA0;
800 			A2 &= 0xF0;
801 			ClearCarry();
802 		}
803 		else
804 			SetCarry();
805 
806 		Ans8 = A2 | A1;
807 
808 		if ((Registers.AL ^ Work8) & (Registers.AL ^ Ans8) & 0x80)
809 			SetOverflow();
810 		else
811 			ClearOverflow();
812 
813 		Registers.AL = Ans8;
814 	}
815 	else
816 	{
817 		int16	Int16 = (int16) Registers.AL - (int16) Work8 + (int16) CheckCarry() - 1;
818 
819 		ICPU._Carry = Int16 >= 0;
820 
821 		if ((Registers.AL ^ Work8) & (Registers.AL ^ (uint8) Int16) & 0x80)
822 			SetOverflow();
823 		else
824 			ClearOverflow();
825 
826 		Registers.AL = (uint8) Int16;
827 	}
828 	SetZN8(Registers.AL);
829 }
830 
STA16(uint32 OpAddress,uint32 w)831 static INLINE void STA16 (uint32 OpAddress, uint32 w)
832 {
833 	S9xSetWord_Write0(Registers.A.W, OpAddress, w);
834 	OpenBus = Registers.AH;
835 }
836 
STA8(uint32 OpAddress)837 static INLINE void STA8 (uint32 OpAddress)
838 {
839 	S9xSetByte(Registers.AL, OpAddress);
840 	OpenBus = Registers.AL;
841 }
842 
STX16(uint32 OpAddress,uint32 w)843 static INLINE void STX16 (uint32 OpAddress, uint32 w)
844 {
845 	S9xSetWord_Write0(Registers.X.W, OpAddress, w);
846 	OpenBus = Registers.XH;
847 }
848 
STX8(uint32 OpAddress)849 static INLINE void STX8 (uint32 OpAddress)
850 {
851 	S9xSetByte(Registers.XL, OpAddress);
852 	OpenBus = Registers.XL;
853 }
854 
STY16(uint32 OpAddress,uint32 w)855 static INLINE void STY16 (uint32 OpAddress, uint32 w)
856 {
857 	S9xSetWord_Write0(Registers.Y.W, OpAddress, w);
858 	OpenBus = Registers.YH;
859 }
860 
STY8(uint32 OpAddress)861 static INLINE void STY8 (uint32 OpAddress)
862 {
863 	S9xSetByte(Registers.YL, OpAddress);
864 	OpenBus = Registers.YL;
865 }
866 
STZ16(uint32 OpAddress,uint32 w)867 static INLINE void STZ16 (uint32 OpAddress, uint32 w)
868 {
869 	S9xSetWord_Write0(0, OpAddress, w);
870 	OpenBus = 0;
871 }
872 
STZ8(uint32 OpAddress)873 static INLINE void STZ8 (uint32 OpAddress)
874 {
875 	S9xSetByte(0, OpAddress);
876 	OpenBus = 0;
877 }
878 
TSB16(uint32 OpAddress,uint32 w)879 static INLINE void TSB16 (uint32 OpAddress, uint32 w)
880 {
881 	uint16 Work16;
882 
883 	Work16 = S9xGetWord(OpAddress, w);
884 	ICPU._Zero = (Work16 & Registers.A.W) != 0;
885 	Work16 |= Registers.A.W;
886 	AddCycles(ONE_CYCLE);
887 	S9xSetWord_Write1(Work16, OpAddress, w);
888 	OpenBus = Work16 & 0xff;
889 }
890 
TSB8(uint32 OpAddress)891 static INLINE void TSB8 (uint32 OpAddress)
892 {
893 	uint8 Work8;
894 
895 	Work8 = S9xGetByte(OpAddress);
896 	ICPU._Zero = Work8 & Registers.AL;
897 	Work8 |= Registers.AL;
898 	AddCycles(ONE_CYCLE);
899 	S9xSetByte(Work8, OpAddress);
900 	OpenBus = Work8;
901 }
902 
TRB16(uint32 OpAddress,uint32 w)903 static INLINE void TRB16 (uint32 OpAddress, uint32 w)
904 {
905 	uint16 Work16;
906 
907 	Work16 = S9xGetWord(OpAddress, w);
908 	ICPU._Zero = (Work16 & Registers.A.W) != 0;
909 	Work16 &= ~Registers.A.W;
910 	AddCycles(ONE_CYCLE);
911 	S9xSetWord_Write1(Work16, OpAddress, w);
912 	OpenBus = Work16 & 0xff;
913 }
914 
TRB8(uint32 OpAddress)915 static INLINE void TRB8 (uint32 OpAddress)
916 {
917 	uint8 Work8;
918 
919 	Work8 = S9xGetByte(OpAddress);
920 	ICPU._Zero = Work8 & Registers.AL;
921 	Work8 &= ~Registers.AL;
922 	AddCycles(ONE_CYCLE);
923 	S9xSetByte(Work8, OpAddress);
924 	OpenBus = Work8;
925 }
926 
927 #endif
928