summaryrefslogtreecommitdiff
path: root/src/spc700/spcgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/spc700/spcgen.c')
-rw-r--r--src/spc700/spcgen.c2164
1 files changed, 2164 insertions, 0 deletions
diff --git a/src/spc700/spcgen.c b/src/spc700/spcgen.c
new file mode 100644
index 0000000..5a15bd7
--- /dev/null
+++ b/src/spc700/spcgen.c
@@ -0,0 +1,2164 @@
+// notaz's SPC700 Emulator
+// (c) Copyright 2006 notaz, All rights reserved.
+//
+// Added some modifications by Bitrider 2010-2011.
+//
+// this is a rewrite of spc700.cpp in ARM asm, inspired by other asm CPU cores like
+// Cyclone and DrZ80. It is meant to be used in Snes9x emulator ports for ARM platforms.
+//
+// notes:
+// "Shutdown" mechanism is not supported, so undefine SPC700_SHUTDOWN in your port.h
+// code branches backwards over start of memory are not supported
+// (never seen any game doing that)
+//
+// license:
+// the code is released under Snes9x license. It would be nice if the word "notaz"
+// would appear somewhere in your documentation or your program's "about" screen
+// if you use this :)
+
+/*
+ * Permission to use, copy, modify and distribute Snes9x in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Snes9x is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Snes9x or software derived from Snes9x.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so everyone can benefit from the modifications
+ * in future versions.
+ *
+ * Super NES and Super Nintendo Entertainment System are trademarks of
+ * Nintendo Co., Limited and its subsidiary companies.
+ */
+
+int one_apu_cycle[] = {13, 14, 15, 21};
+int current_cycles;
+
+
+// settings
+#define VERSION "0.12"
+#define APU_EXECUTING_OFF 124
+//#define SPC_DEBUG
+
+
+// includes
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+// timings
+int S9xAPUCycles [256] =
+{
+ /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, */
+ /* 00 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 6, 8,
+ /* 10 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 4, 6,
+ /* 20 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 5, 4,
+ /* 30 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 3, 8,
+ /* 40 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 6, 6,
+ /* 50 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 4, 5, 2, 2, 4, 3,
+ /* 60 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 5, 5,
+ /* 70 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 6,
+ /* 80 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 2, 4, 5,
+ /* 90 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2,12, 5,
+ /* a0 */ 3, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 2, 4, 4,
+ /* b0 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 4,
+ /* c0 */ 3, 8, 4, 5, 4, 5, 4, 7, 2, 5, 6, 4, 5, 2, 4, 9,
+ /* d0 */ 2, 8, 4, 5, 5, 6, 6, 7, 4, 5, 4, 5, 2, 2, 6, 3,
+ /* e0 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 4, 5, 3, 4, 3, 4, 3,
+ /* f0 */ 2, 8, 4, 5, 4, 5, 5, 6, 3, 4, 5, 4, 2, 2, 4, 3
+};
+
+
+// stuff
+static FILE *AsmFile=NULL;
+static int opcode=0; // 0-0xff
+static int ibuffer = 0;
+static char buff[1024];
+
+
+void ot(char *format, ...)
+{
+ va_list valist=NULL;
+ int i, len;
+
+ // notaz: stop me from leaving newlines in the middle of format string
+ // and generating bad code
+ for(i=0, len=strlen(format); i < len && format[i] != '\n'; i++);
+ if(i < len-1 && format[len-1] != '\n') printf("\nWARNING: possible improper newline placement:\n%s\n", format);
+
+ va_start(valist,format);
+ if (AsmFile) vfprintf(AsmFile,format,valist);
+ va_end(valist);
+}
+
+// ot buffered
+void otb(char *format, ...)
+{
+ va_list valist=NULL;
+ int i, len;
+
+ // notaz: stop me from leaving newlines in the middle of format string
+ // and generating bad code
+ for(i=0, len=strlen(format); i < len && format[i] != '\n'; i++);
+ if(i < len-1 && format[len-1] != '\n') printf(buff, "\nWARNING: possible improper newline placement:\n%s\n", format);
+
+ va_start(valist,format);
+ if (AsmFile) vsprintf(buff,format,valist);
+ ibuffer = 1;
+ va_end(valist);
+}
+
+void flush_buffer() {
+ if (ibuffer != 0) {
+ ot(buff);
+ ibuffer = 0;
+ }
+}
+
+// trashes: r0, r1, r2
+// return: r0
+// exit at label "2"
+static void GetAPUDSP() {
+ ot("GetAPUDSP: \n");
+ ot(" ldrb r1, [spc_ram, #0xf2] \n");
+ // r1 = IAPU.RAM [0xf2]
+
+ ot(" mov r0, #0\n");
+ ot(" and r2, r1, #0X0f \n");
+ // switch (reg & 0xf) {
+ ot(" cmp r2, #0x08\n");
+ ot(" bxeq lr\n"); // APU_ENVX = 8
+ // r1 = IAPU.RAM [0xf2] & 0x7f;
+
+ ot(" cmp r2, #0x09\n");
+ // return APU.DSP [reg];
+ ot(" ldrne r2, .APU_DSP\n");
+ ot(" and r1, r1, #0X7f \n"); // r1 = IAPU.RAM[0xf2] & 0x7f
+ ot(" ldrneb r0, [r2, r1] \n");
+ ot(" bxne lr \n");
+
+ // APU_OUTX = 9
+ // if (SoundData.channels [reg >> 4].state == SOUND_SILENT) return 0;
+ // return ((SoundData.channels [reg >> 4].sample >> 8) | (SoundData.channels [reg >> 4].sample & 0x
+ ot(" ldr r2, .SOUNDDATA_CHANNELS\n");
+ ot(" mov r1, r1, lsr #4 \n");
+ //ot(" add r1, r2, r1, asl #8\n");
+ //ot(" ldr r0, [r1, #0x0] \n"); // r0 = SoundData.channels[reg >> 4].state
+ ot(" ldr r0, [r2, r1, asl #8] \n");
+ ot(" add r1, r2, r1, asl #8\n");
+ ot(" cmp r0, #0 \n"); // SOUND_SILENT = 0
+ ot(" ldrneh r1, [r1, #0x48] \n"); // r1 = SoundData.channels[reg >> 4].sample
+ ot(" bxeq lr \n");
+
+ ot(" and r0, r1, #0xff\n");
+ ot(" orr r0, r0, r1, lsr #8\n");
+ ot(" bx lr \n");
+
+ ot(".APU_DSP:\n");
+ ot(" .long APU + 0x0b\n"); // &APU.DSP
+ ot(".SOUNDDATA_CHANNELS:\n");
+ ot(" .long SoundData + 0x30\n"); // &SoundData.channels[0]
+}
+
+
+// bitrider
+// macros
+static void GetByte() {
+ ot(" mov r1, r0\n");
+
+ ot(" ldrb r0, [spc_ram, r1] \n");
+
+ ot(" cmp r1, #0x0ff\n");
+ ot(" bhi 1f \n");
+
+ ot(" cmp r1, #0xf3 \n");
+ ot(" addeq lr, pc, #12 \n"); // lr = &ExitPoint
+ ot(" beq GetAPUDSP \n");
+
+ ot(" cmp r1, #0xfd \n");
+ ot(" movhs r2, #0 \n");
+ ot(" strhsb r2, [spc_ram, r1] \n");
+ ot("1:\n");
+
+
+}
+
+// trashes: r0, r1, r14
+static void GetByteZ() {
+ ot(" mov r1, r0\n");
+
+ ot(" cmp r1, #0xf3 \n");
+ ot(" addeq lr, pc, #20 \n"); // lr = &ExitPoint
+ ot(" beq GetAPUDSP \n");
+
+ ot(" ldr r14, [context, #iapu_directpage]\n");
+ ot(" cmp r1, #0xfd \n");
+ ot(" ldrb r0, [r14, r1] \n");
+ ot(" movhs r2, #0 \n");
+ ot(" strhsb r2, [r14, r1] \n");
+}
+
+static void SetByte(int restore) {
+ // Still should check for ShowRom
+ ot(" add r2, r1, #40 \n");
+ ot(" tst r2, #0x10000 \n");
+ ot(" bne 1f \n");
+
+ ot(" bic r2, r1, #0x0f\n");
+ ot(" cmp r2, #0xf0\n");
+ ot(" strneb r0, [spc_ram, r1] \n");
+ ot(" bne 3f\n");
+
+ ot(" add lr, pc, #20\n");
+
+ ot(" cmp r1, #0xf1 \n");
+ ot(" beq S9xSetAPUControl \n");
+
+ ot(" cmp r1, #0xf3 \n"); // pc + 4
+ ot(" beq S9xSetAPUDSP \n"); // pc + 8
+ ot(" b S9xAPUSetByteFFtoF0 \n"); // pc + 12
+
+ ot("1: \n");
+ ot(" bl S9xAPUSetByteFFC0 \n");
+ ot(" ldr spc_ram, [context, #iapu_ram] \n");
+ ot("3: \n");
+
+}
+
+static void SetByteZ(int restore) {
+ ot(" ldr r2, [context, #iapu_directpage] \n");
+ ot(" cmp r2, spc_ram \n");
+ ot(" bne 2f \n");
+
+ ot(" cmp r1, #0xf0 \n");
+ ot(" blo 2f \n");
+
+ ot(" cmp r1, #0xfe \n");
+ ot(" bhs 1f \n");
+
+ if (restore) ot(" add lr, pc, #16\n");
+ else ot(" add lr, pc, #20\n");
+
+ ot(" cmp r1, #0xf1 \n");
+ ot(" beq S9xSetAPUControl \n");
+
+ ot(" cmp r1, #0xf3 \n"); // pc + 4
+ ot(" beq S9xSetAPUDSP \n"); // pc + 8
+ ot(" b S9xAPUSetByteFFtoF0 \n"); // pc + 12
+ //ot("6: \n"); // pc + 16
+ if (restore) {
+ ot(" ldr spc_ram, [context, #iapu_ram] \n");
+ ot(" b 1f \n");
+ }
+ ot("2: \n");
+ ot(" strb r0, [r2, r1] \n");
+ ot("1: \n");
+}
+
+
+// r0-2: Temporary registers
+// r3 : current opcode or temp
+// r4 : Cycles remaining
+// r5 : Pointer to IAPU structure
+// r6 : Pointer to Opcode Jump table
+// r7 : Current PC
+// r8 : YA
+// r9 : P (nzzzzzzz ........ ........ NODBHIZC; nzzzzzzz - NZ flag in use (for a little speedup)
+
+// r10 : X
+// r11 : S
+// r14 : temp
+// lr : RAM pointer
+
+static void PrintFramework()
+{
+
+
+#ifndef SPC_DEBUG
+ ot(" .extern IAPU\n");
+#else
+ ot(" .extern IAPU2\n");
+#endif
+ ot(" .extern CPU @ for STOP and SLEEP\n");
+ ot(" .extern S9xAPUGetByte\n");
+ ot(" .extern S9xAPUSetByte\n");
+ ot(" .extern S9xAPUGetByteZ\n");
+ ot(" .extern S9xAPUSetByteZ\n\n");
+
+ // bitrider
+ ot(" .extern S9xGetAPUDSP\n");
+ ot(" .extern S9xSetAPUDSP\n");
+ ot(" .extern S9xSetAPUControl\n");
+ ot(" .extern S9xAPUSetByteFFC0\n");
+ ot(" .extern S9xAPUSetByteFFtoF0\n");
+
+ ot(" .global spc700_execute @ int cycles\n");
+ //ot(" .global Spc700JumpTab\n\n");
+ for (current_cycles=0; current_cycles < (sizeof(one_apu_cycle) / sizeof(int)); current_cycles++)
+ ot(" .global Spc700JumpTab_%i\n", one_apu_cycle[current_cycles]);
+ ot("\n");
+
+
+ ot(" opcode .req r3\n");
+ ot(" cycles .req r4\n");
+ ot(" context .req r5\n");
+ ot(" opcodes .req r6\n");
+ ot(" spc_pc .req r7\n");
+ ot(" spc_ya .req r8\n");
+ ot(" spc_p .req r9\n");
+ ot(" spc_x .req r10\n");
+ ot(" spc_s .req r11\n");
+ ot(" spc_ram .req r12\n\n");
+
+ ot(" .equ iapu_directpage, 0x00\n");
+ ot(" .equ iapu_ram, 0x44\n");
+ ot(" .equ iapu_extraram, 0x48\n");
+ ot(" .equ iapu_allregs_load, 0x30\n");
+ ot(" .equ iapu_allregs_save, 0x34\n\n");
+
+ ot(" .equ flag_c, 0x01\n");
+ ot(" .equ flag_z, 0x02\n");
+ ot(" .equ flag_i, 0x04\n");
+ ot(" .equ flag_h, 0x08\n");
+ ot(" .equ flag_b, 0x10\n");
+ ot(" .equ flag_d, 0x20\n");
+ ot(" .equ flag_o, 0x40\n");
+ ot(" .equ flag_n, 0x80\n\n");
+
+ ot(" .equ cpu_apu_executing, %i \n\n", APU_EXECUTING_OFF);
+ // tmp
+// ot(" .equ iapu_carry, 0x24\n");
+// ot(" .equ iapu_overflow, 0x26\n\n");
+
+ ot("@ --------------------------- Framework --------------------------\n");
+ ot(" .align 4\n");
+ ot("spc700_execute: @ int cycles\n");
+
+ ot(" stmfd sp!,{r4-r11,lr}\n");
+
+#ifndef SPC_DEBUG
+ ot(" ldr context,=IAPU @ Pointer to SIAPU struct\n");
+#else
+ ot(" ldr context,=IAPU2 @ Pointer to SIAPU struct\n");
+#endif
+ ot(" mov cycles,r0 @ Cycles\n");
+ ot(" add r0,context,#iapu_allregs_load\n");
+ ot(" ldmia r0,{opcodes,spc_pc,spc_ya,spc_p,spc_x,spc_ram}\n");
+
+ ot(" ldrb opcode,[spc_pc],#1 @ Fetch first opcode\n");
+ ot(" mov spc_s,spc_x,lsr #8\n");
+ ot(" and spc_x,spc_x,#0xff\n");
+ ot("\n");
+
+ ot(" ldr pc,[opcodes,opcode,lsl #2] @ Jump to opcode handler\n");
+ ot("\n\n");
+
+
+ ot("@ We come back here after execution\n");
+ ot("spc700End:\n");
+ ot(" orr spc_x,spc_x,spc_s,lsl #8\n");
+ ot(" add r0,context,#iapu_allregs_save\n");
+ ot(" stmia r0,{spc_pc,spc_ya,spc_p,spc_x}\n");
+ ot(" mov r0,cycles\n");
+ ot(" ldmfd sp!,{r4-r11,pc}\n");
+ ot("\n");
+
+ ot(" .ltorg\n");
+ ot("\n");
+
+ GetAPUDSP();
+}
+
+
+// ---------------------------------------------------------------------------
+
+// Trashes r0-r3
+static void MemHandler(int set, int z, int save)
+{
+ //if(set) ot(" bl S9xAPUSetByte%s\n", z ? "Z" : "");
+ //else ot(" bl S9xAPUGetByte%s\n", z ? "Z" : "");
+
+ //if(set) ot(" asm_S9xAPUSetByte%s\n", z ? "Z" : "");
+ //else ot(" asm_S9xAPUGetByte%s\n", z ? "Z" : "");
+ if(set) {
+ if (z) SetByteZ(save);
+ else SetByte(save);
+ } else {
+ if (z) GetByteZ();
+ else GetByte();
+ }
+
+ //if(save) ot(" ldr spc_ram,[context,#iapu_ram]\n");
+}
+
+// pushes reg, trashes r1
+static void Push(char *reg)
+{
+ ot(" add r1,spc_ram,spc_s\n");
+ ot(" strb %s,[r1,#0x100]\n", reg);
+ ot(" sub spc_s,spc_s,#1\n");
+}
+
+// pushes r0, trashes r0,r1
+static void PushW()
+{
+ ot(" add r1,spc_ram,spc_s\n");
+ ot(" sub spc_s,spc_s,#2\n");
+ ot(" strb r0,[r1,#0xff]\n");
+ ot(" mov r0,r0,lsr #8\n");
+ ot(" strb r0,[r1,#0x100]\n");
+}
+
+// pops to reg
+static void Pop(char *reg)
+{
+ ot(" add %s,spc_ram,spc_s\n", reg);
+ ot(" ldrb %s,[%s,#(0x100 + 1)]\n", reg, reg);
+ ot(" add spc_s,spc_s,#1\n");
+}
+
+// pops to r0, trashes r1
+static void PopW()
+{
+ ot(" add r1,spc_ram,spc_s\n");
+ ot(" ldrb r0,[r1,#(0xff + 2)]\n");
+ ot(" ldrb r1,[r1,#(0x100 + 2)]\n");
+ ot(" add spc_s,spc_s,#2\n");
+ ot(" orr r0,r0,r1,lsl #8\n");
+}
+
+// // rr <- absolute, trashes r14
+// rr <- absolute
+
+static void AbsoluteAdd(int r, char *rAdd)
+{
+ ot(" ldrb r%i,[spc_pc],#1\n", r);
+ ot(" ldrb r14,[spc_pc],#1\n");
+ if (rAdd) ot(" add r%i,r%i,%s\n", r, r, rAdd);
+ ot(" add r%i,r%i,r14,lsl #8\n", r, r);
+}
+
+// // rr <- absolute, trashes r14
+// rr <- absolute
+static void Absolute(int r)
+{
+ //ot(" ldrb r%i,[spc_pc],#1\n", r);
+ //ot(" ldrb r14,[spc_pc],#1\n");
+ //ot(" orr r%i,r%i,r14,lsl #8\n", r, r);
+ AbsoluteAdd(r, NULL);
+}
+
+
+// rr <- absoluteX, trashes r14
+static void AbsoluteX(int r)
+{
+ //Absolute(r);
+ //ot(" ldrb r%i,[spc_pc],#1\n", r);
+ //ot(" ldrb r14,[spc_pc],#1\n");
+ //ot(" add r%i,r%i,spc_x\n", r, r);
+ //ot(" add r%i,r%i,r14,lsl #8\n", r, r);
+ AbsoluteAdd(r, "spc_x");
+}
+
+// r0 <- absoluteY, trashes r1
+static void AbsoluteY(int r)
+{
+ //Absolute(r);
+ //ot(" ldrb r%i,[spc_pc],#1\n", r);
+ //ot(" ldrb r14,[spc_pc],#1\n");
+ //ot(" add r%i,r%i,spc_ya,lsr #8\n", r, r);
+ //ot(" add r%i,r%i,r14,lsl #8\n", r, r);
+ AbsoluteAdd(r, "spc_ya, lsr #8");
+}
+
+// rr <- IndirectIndexedY, trashes r14
+static void IndirectIndexedY(int r)
+{
+ ot(" ldrb r%i,[spc_pc],#1\n", r);
+ ot(" ldr r14,[context,#iapu_directpage]\n");
+ ot(" ldrb r%i,[r14,r%i]!\n", r, r);
+ ot(" ldrb r14,[r14,#1]\n");
+ //ot(" orr r%i,r%i,r14,lsl #8\n", r, r);
+ ot(" add r%i,r%i,spc_ya,lsr #8\n", r, r);
+ ot(" add r%i,r%i,r14,lsl #8\n", r, r);
+}
+
+// rr <- address, trashes r14
+static void IndexedXIndirect(int r)
+{
+ ot(" ldrb r%i,[spc_pc],#1\n", r);
+ ot(" ldr r14,[context,#iapu_directpage]\n"); // again, interlocks are bad
+ ot(" add r%i,r%i,spc_x\n", r, r);
+ ot(" and r%i,r%i,#0xff\n", r, r);
+ ot(" ldrb r%i,[r14,r%i]!\n", r, r);
+ ot(" ldrb r14,[r14,#1]\n");
+ ot(" orr r%i,r%i,r14,lsl #8\n", r, r);
+}
+
+// sets ZN for reg in *reg, not suitable for Y
+static void SetZN8(char *reg)
+{
+ ot(" and spc_p,spc_p,#0xff\n");
+ ot(" orr spc_p,spc_p,%s,lsl #24\n", reg);
+}
+
+// sets ZN for reg in *reg
+static void SetZN16(char *reg)
+{
+ ot(" and spc_p,spc_p,#0xff\n");
+ ot(" orr spc_p,spc_p,%s,lsl #16\n", reg);
+ ot(" tst %s,#0xff\n", reg);
+ ot(" orrne spc_p,spc_p,#0x01000000\n");
+}
+
+// does ROL on r0, sets flags
+static void Rol()
+{
+ ot(" mov r0,r0,lsl #1\n");
+ ot(" tst spc_p,#flag_c\n");
+ ot(" orrne r0,r0,#1\n");
+ ot(" tst r0,#0x100\n");
+ ot(" orrne spc_p,spc_p,#flag_c\n");
+ ot(" biceq spc_p,spc_p,#flag_c\n");
+ SetZN8("r0");
+}
+
+// does ROR on r0, sets flags
+static void Ror()
+{
+ ot(" tst spc_p,#flag_c\n");
+ ot(" orrne r0,r0,#0x100\n");
+ ot(" movs r0,r0,lsr #1\n");
+ ot(" orrcs spc_p,spc_p,#flag_c\n");
+ ot(" biccc spc_p,spc_p,#flag_c\n");
+ SetZN8("r0");
+}
+
+// does ASL on r0, sets flags but doesn't cut the shifted bits
+static void Asl()
+{
+ ot(" tst r0,#0x80\n");
+ ot(" orrne spc_p,spc_p,#flag_c\n");
+ ot(" biceq spc_p,spc_p,#flag_c\n");
+ ot(" mov r0,r0,lsl #1\n");
+ SetZN8("r0");
+}
+
+// does LSR on r0, sets flags
+static void Lsr()
+{
+ ot(" tst r0,#0x01\n");
+ ot(" orrne spc_p,spc_p,#flag_c\n");
+ ot(" biceq spc_p,spc_p,#flag_c\n");
+ ot(" mov r0,r0,lsr #1\n");
+ SetZN8("r0");
+}
+
+// CMP rr0,rr1; trashes r14
+static void Cmp(char *r0, char *r1, int and_r0)
+{
+ char *lop = r0;
+
+ if(and_r0) { ot(" and r14,%s,#0xff\n", r0); lop = "r14"; }
+ ot(" subs r14,%s,%s\n", lop, r1);
+ //ot(" orrge spc_p,spc_p,#flag_c\n");
+ //ot(" biclt spc_p,spc_p,#flag_c\n");
+ ot(" orrcs spc_p,spc_p,#flag_c\n");
+ ot(" biccc spc_p,spc_p,#flag_c\n");
+ SetZN8("r14");
+}
+
+// ADC rr0,rr1 -> rr0, trashes r2,r14, does not mask to byte
+static void Adc(char *r0, char *r1)
+{
+ ot(" eor r2,%s,%s\n", r0, r1); // r3=(a) ^ (b)
+ ot(" movs r14, spc_p, lsr #1\n");
+ ot(" adc %s, %s, %s\n", r0, r0, r1);
+ //ot(" add %s,%s,%s\n", r0, r0, r1);
+ //ot(" tst spc_p,#flag_c\n");
+ //ot(" addne %s,%s,#1\n", r0, r0);
+ ot(" movs r14,%s,lsr #8\n", r0);
+ ot(" orrne spc_p,spc_p,#flag_c\n");
+ ot(" biceq spc_p,spc_p,#flag_c\n");
+ ot(" eor r14,%s,%s\n", r0, r1); // r14=(b) ^ Work16
+ ot(" bic r14,r14,r2\n"); // ((b) ^ Work16) & ~((a) ^ (b))
+ ot(" tst r14,#0x80\n");
+ ot(" orrne spc_p,spc_p,#flag_o\n");
+ ot(" biceq spc_p,spc_p,#flag_o\n");
+ ot(" eor r14,r2,%s\n", r0);
+ ot(" tst r14,#0x10\n");
+ ot(" orrne spc_p,spc_p,#flag_h\n");
+ ot(" biceq spc_p,spc_p,#flag_h\n");
+}
+
+// SBC rr0,rr1 -> rr0, trashes r2,r3,r14, does not mask to byte
+static void Sbc(char *r0, char *r1)
+{
+ ot(" movs r14,spc_p,lsr #1\n");
+ ot(" sbcs r2,%s,%s\n", r0, r1);
+ ot(" orrge spc_p,spc_p,#flag_c\n");
+ ot(" biclt spc_p,spc_p,#flag_c\n");
+ ot(" eor r14,%s,r2\n", r0); // r14=(a) ^ Int16
+ ot(" eor r3,%s,%s\n", r0, r1); // r3=(a) ^ (b)
+ ot(" and r14,r14,r3\n"); // ((a) ^ Work16) & ((a) ^ (b))
+ ot(" tst r14,#0x80\n");
+ ot(" orrne spc_p,spc_p,#flag_o\n");
+ ot(" biceq spc_p,spc_p,#flag_o\n");
+ ot(" eor r14,r3,r2\n");
+ ot(" tst r14,#0x10\n");
+ ot(" orreq spc_p,spc_p,#flag_h\n");
+ ot(" bicne spc_p,spc_p,#flag_h\n");
+ ot(" mov %s,r2\n", r0);
+}
+
+
+//
+static void TCall()
+{
+ ot(" sub r0,spc_pc,spc_ram\n");
+ PushW();
+ ot(" ldr r0,[context,#iapu_extraram]\n");
+ ot(" ldrh r0,[r0,#0x%x]\n", (15-(opcode>>4))<<1);
+ ot(" add spc_pc,spc_ram,r0\n");
+}
+
+//
+static void SetClr1()
+{
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ ot(" %s r0,r0,#0x%02x\n", opcode & 0x10 ? "bic" : "orr", 1<<(opcode>>5));
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+}
+
+//
+static void BssBbc()
+{
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 1);
+ ot(" tst r0,#0x%02x\n", 1<<(opcode>>5));
+ ot(" add%s spc_pc,spc_pc,#1\n", opcode & 0x10 ? "ne" : "eq");
+ ot(" ldr%ssb r0,[spc_pc],#1\n", opcode & 0x10 ? "eq" : "ne");
+ ot(" sub%s cycles,cycles,#%i\n",opcode & 0x10 ? "eq" : "ne", one_apu_cycle[current_cycles]*2);
+ ot(" add%s spc_pc,spc_pc,r0\n", opcode & 0x10 ? "eq" : "ne");
+}
+
+//
+static void Membit()
+{
+ ot(" ldrb r0,[spc_pc], #1\n");
+ ot(" ldrb r3,[spc_pc], #1\n");
+ //ot(" orr spc_x,spc_x,r1,lsl #(29-5)
+ ot(" add r3,r0,r3,lsl #8\n"); //@ store membit where it can survive memhandler call\n"); // saving bit 12 ?
+ //ot(" mov r1,r1,lsr #5\n");
+ //ot(" mov r0,r0,lsl #19\n");
+ //ot(" mov r0,r0,lsr #19\n");
+ //if((opcode >> 4) >= 0xC) ot(" mov r3, r0\n"); //ot(" stmfd sp!,{r0}\n"); // membit
+ ot(" bic r0, r3, #0xe000\n"); // Clear bits 15, 14 & 13 => r0 = r0 & 0x1fff
+ MemHandler(0, 0, 0);
+ //ot(" mov r1,spc_x,lsr #29\n");
+ //ot(" and spc_x,spc_x,#0xff\n");
+ ot(" mov r1, r3, lsr #13\n"); // membit = bits[15:13] of memory address
+ if((opcode >> 4) < 0xC) {
+ ot(" mov r0,r0,lsr r1\n");
+ ot(" tst r0,#1\n");
+ switch(opcode >> 4) {
+ case 0x0: ot(" orrne spc_p,spc_p,#flag_c\n"); break; // OR1 C,membit
+ case 0x2: ot(" orreq spc_p,spc_p,#flag_c\n"); break; // OR1 C,not membit
+ case 0x4: ot(" biceq spc_p,spc_p,#flag_c\n"); break; // AND1 C,membit
+ case 0x6: ot(" bicne spc_p,spc_p,#flag_c\n"); break; // AND1 C, not membit
+ case 0x8: ot(" eorne spc_p,spc_p,#flag_c\n"); break; // EOR1 C, membit
+ case 0xA: ot(" orrne spc_p,spc_p,#flag_c\n"); // MOV1 C,membit
+ ot(" biceq spc_p,spc_p,#flag_c\n"); break;
+ }
+ } else {
+ ot(" mov r2,#1\n");
+ ot(" mov r2,r2,lsl r1\n");
+ if((opcode >> 4) == 0xC) { // MOV1 membit,C
+ ot(" tst spc_p,#flag_c\n");
+ ot(" orrne r0,r0,r2\n");
+ ot(" biceq r0,r0,r2\n");
+ } else { // NOT1 membit
+ ot(" eor r0,r0,r2\n");
+ }
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" bic r1, r3, #0xe000\n"); // Clear bits 15, 14 & 13 => r0 = r0 & 0x1fff
+ MemHandler(1, 0, 0);
+ }
+ //ot(" ldr spc_ram,[context,#iapu_ram] @ restore what memhandler(s) messed up\n");
+}
+
+//
+static void CBranch()
+{
+ int tests[] = { 0x80000000, 0x40, 0x01, 0xff000000 }; // NOCZ
+ char *eq = "eq";
+ char *ne = "ne";
+
+ if((opcode>>6) == 3) { // zero test inverts everything
+ eq = "ne";
+ ne = "eq";
+ }
+
+ ot(" tst spc_p,#0x%08X\n", tests[opcode>>6]);
+ ot(" add%s spc_pc,spc_pc,#1\n", opcode & 0x20 ? eq : ne);
+/*
+ ot(" b%s Apu%02X\n", opcode & 0x20 ? eq : ne, opcode);
+ ot(" sub r0,spc_pc,spc_ram\n");
+ ot(" ldrsb r1,[spc_pc],#1\n");
+ ot(" add r0,r0,r1\n");
+ ot(" mov r0,r0,lsl #16\n");
+ ot(" add spc_pc,spc_ram,r0,lsr #16\n");
+*/
+ ot(" ldr%ssb r0,[spc_pc],#1\n", opcode & 0x20 ? ne : eq);
+
+ ot(" sub%s cycles,cycles,#%i\n", opcode & 0x20 ? ne : eq, one_apu_cycle[current_cycles]*2);
+ ot(" add%s spc_pc,spc_pc,r0\n", opcode & 0x20 ? ne : eq);
+// ot("Apu%02X:\n", opcode);
+}
+
+// NeededOperation spc_ya,r0 -> spc_ya
+static void ArithOpToA()
+{
+ // special A pre-processing
+ if((opcode>>5) == 4 || (opcode>>5) == 5) {
+ ot(" and r1,spc_ya,#0xff00\n");
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ }
+
+ switch(opcode>>5) {
+ case 0: ot(" orr spc_ya,spc_ya,r0\n"); break; // OR
+ case 1: ot(" orr r0,r0,#0xff00\n");
+ ot(" and spc_ya,spc_ya,r0\n"); break; // AND
+ case 2: ot(" eor spc_ya,spc_ya,r0\n"); break; // EOR
+ case 3: Cmp("spc_ya", "r0", 1); break; // CMP
+ case 4: Adc("spc_ya", "r0"); break; // ADC
+ case 5: Sbc("spc_ya", "r0"); break; // SBC
+ case 6: printf("MOV (reversed)!?\n"); break; // MOV (reversed)
+ case 7: ot(" and spc_ya,spc_ya,#0xff00\n");
+ ot(" orr spc_ya,spc_ya,r0\n"); break; // MOV
+ }
+
+ if((opcode>>5) != 3) SetZN8("spc_ya"); // only if not Cmp
+
+ // special A post-processing
+ if((opcode>>5) == 4 || (opcode>>5) == 5) {
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ ot(" orr spc_ya,spc_ya,r1\n");
+ }
+}
+
+//
+static void ArithmeticToA()
+{
+ switch(opcode&0x1f) {
+ case 0x04: // OP A,dp
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 1);
+ ArithOpToA();
+ break;
+
+ case 0x05: // OP A,abs
+ Absolute(0);
+ MemHandler(0, 0, 1);
+ ArithOpToA();
+ break;
+
+ case 0x06: // OP A,(X)
+ ot(" mov r0,spc_x\n");
+ MemHandler(0, 1, 1);
+ ArithOpToA();
+ break;
+
+ case 0x07: // OP A,(dp+X)
+ IndexedXIndirect(0);
+ MemHandler(0, 0, 1);
+ ArithOpToA();
+ break;
+
+ case 0x08: // OP A,#00
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ArithOpToA();
+ break;
+
+ case 0x14: // OP A,dp+X
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" add r0,r0,spc_x\n");
+ MemHandler(0, 1, 1);
+ ArithOpToA();
+ break;
+
+ case 0x15: // OP A,abs+X
+ AbsoluteX(0);
+ MemHandler(0, 0, 1);
+ ArithOpToA();
+ break;
+
+ case 0x16: // OP A,abs+Y
+ AbsoluteY(0);
+ MemHandler(0, 0, 1);
+ ArithOpToA();
+ break;
+
+ case 0x17: // OP A,(dp)+Y
+ IndirectIndexedY(0);
+ MemHandler(0, 0, 1);
+ ArithOpToA();
+ break;
+
+ default:
+ printf("Op %02X - arithmetic??\n", opcode);
+ }
+}
+
+void printOpcodes(int apu_cycles) {
+ for(opcode = 0; opcode < 0x100; opcode++) {
+ printf("%02X", opcode);
+
+ ot("\n\n");
+ //tmp_prologue();
+ ot("Apu%02X_%i:\n", opcode, apu_cycles);
+
+ if((opcode & 0x1f) == 0x10) CBranch(); // BXX
+ if((opcode & 0x0f) == 0x01) TCall(); // TCALL X
+ if((opcode & 0x0f) == 0x02) SetClr1(); // SET1/CLR1 direct page bit X
+ if((opcode & 0x0f) == 0x03) BssBbc(); // BBS/BBC direct page bit X
+ if((opcode & 0x1f) == 0x0A) Membit(); // membit ops
+ if((opcode & 0x0f) >= 0x04 && (opcode & 0x0f) <= 0x08 && (opcode & 0x1f) != 0x18 && (opcode >> 5) != 6)
+ ArithmeticToA();
+
+
+ switch(opcode) {
+ case 0x00: // NOP
+ break;
+
+ case 0x3F: // CALL absolute
+ Absolute(2);
+ ot(" sub r0,spc_pc,spc_ram\n");
+ PushW();
+ ot(" add spc_pc,spc_ram,r2\n");
+ break;
+
+ case 0x4F: // PCALL $XX
+ ot(" ldrb r2,[spc_pc],#1\n");
+ ot(" sub r0,spc_pc,spc_ram\n");
+ PushW();
+ ot(" add spc_pc,spc_ram,r2\n");
+ ot(" add spc_pc,spc_pc,#0xff00\n");
+ break;
+
+ case 0x09: // OR dp(dest),dp(src)
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 0);
+ //ot(" orr spc_x,spc_x,r0,lsl #24 @ save from harm\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ ot(" orr r0, r0, r3\n");
+ //ot(" orr r0,r0,spc_x,lsr #24\n");
+ //ot(" and spc_x,spc_x,#0xff\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x18: // OR dp,#00
+ ot(" ldrb r0,[spc_pc,#1]\n");
+ MemHandler(0, 1, 0);
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" orr r0,r0,r1\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x19: // OR (X),(Y)
+ ot(" mov r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ //ot(" orr spc_x,spc_x,r0,lsl #24\n");
+ ot(" mov r3, r0\n");
+ ot(" mov r0,spc_ya,lsr #8\n");
+ MemHandler(0, 1, 0);
+ ot(" orr r0, r3, r0\n");
+ //ot(" orr r0,r0,spc_x,lsr #24\n");
+ //ot(" and spc_x,spc_x,#0xff\n");
+ SetZN8("r0");
+ ot(" mov r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x0B: // ASL dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ Asl();
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x0C: // ASL abs
+ Absolute(0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ MemHandler(0, 0, 0);
+ Asl();
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" mov r1, r3\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0x1B: // ASL dp+X
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" add r0,r0,spc_x\n");
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ MemHandler(0, 1, 0);
+ Asl();
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" mov r1, r3\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x1C: // ASL A
+ ot(" tst spc_ya,#0x80\n");
+ ot(" orrne spc_p,spc_p,#flag_c\n");
+ ot(" biceq spc_p,spc_p,#flag_c\n");
+ ot(" and r0,spc_ya,#0x7f\n");
+ ot(" and spc_ya,spc_ya,#0xff00\n");
+ ot(" orr spc_ya,spc_ya,r0,lsl #1\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0x0D: // PUSH PSW
+ ot(" mov r0,spc_p,lsr #24\n");
+ ot(" and r1,r0,#0x80\n");
+ ot(" tst r0,r0\n");
+ ot(" orreq r1,r1,#flag_z\n");
+ ot(" and spc_p,spc_p,#0x7d @ clear N & Z\n");
+ ot(" orr spc_p,spc_p,r1\n");
+ Push("spc_p");
+ otb(" orr spc_p,spc_p,r0,lsl #24\n");
+ break;
+
+ case 0x2D: // PUSH A
+ Push("spc_ya");
+ break;
+
+ case 0x4D: // PUSH X
+ Push("spc_x");
+ break;
+
+ case 0x6D: // PUSH Y
+ ot(" mov r0,spc_ya,lsr #8\n");
+ Push("r0");
+ break;
+
+ case 0x8E: // POP PSW
+ Pop("spc_p");
+ ot(" and r0,spc_p,#(flag_z|flag_n)\n");
+ ot(" eor r0,r0,#flag_z\n");
+ ot(" orr spc_p,spc_p,r0,lsl #24\n");
+ ot(" tst spc_p,#flag_d\n");
+ ot(" addne r0,spc_ram,#0x100\n");
+ ot(" moveq r0,spc_ram\n");
+ otb(" str r0,[context,#iapu_directpage]\n");
+ break;
+
+ case 0xAE: // POP A
+ Pop("r0");
+ ot(" and spc_ya,spc_ya,#0xff00\n");
+ otb(" orr spc_ya,spc_ya,r0\n");
+ break;
+
+ case 0xCE: // POP X
+ Pop("spc_x");
+ break;
+
+ case 0xEE: // POP X
+ Pop("r0");
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ otb(" orr spc_ya,spc_ya,r0,lsl #8\n");
+ break;
+
+ case 0x0E: // TSET1 abs
+ Absolute(0);
+ ot(" mov r3, r0\n");
+ //ot(" orr spc_x,spc_x,r0,lsl #16 @ save from memhandler\n");
+ MemHandler(0, 0, 0);
+ ot(" and r2,r0,spc_ya\n");
+ SetZN8("r2");
+ ot(" orr r0,r0,spc_ya\n");
+ ot(" mov r1, r3\n");
+ //ot(" mov r1,spc_x,lsr #16\n");
+ //ot(" and spc_x,spc_x,#0xff\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0x4E: // TCLR1 abs
+ Absolute(0);
+ ot(" mov r3, r0\n");
+ //ot(" orr spc_x,spc_x,r0,lsl #16 @ save from memhandler\n");
+ MemHandler(0, 0, 0);
+ ot(" and r2,r0,spc_ya\n");
+ SetZN8("r2");
+ ot(" bic r0,r0,spc_ya\n");
+ ot(" mov r1, r3\n");
+ //ot(" mov r1,spc_x,lsr #16\n");
+ //ot(" and spc_x,spc_x,#0xff\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0x0F: // BRK
+ ot(" sub r0,spc_pc,spc_ram\n");
+ PushW();
+ ot(" mov r0,spc_p,lsr #24\n");
+ ot(" and r1,r0,#0x80\n");
+ ot(" tst r0,r0\n");
+ ot(" orrne r1,r1,#flag_z\n");
+ ot(" and spc_p,spc_p,#0x7d @ clear N & Z\n");
+ ot(" orr spc_p,spc_p,r1\n");
+ Push("spc_p");
+ ot(" orr spc_p,spc_p,#flag_b\n");
+ ot(" bic spc_p,spc_p,#flag_i\n");
+ ot(" ldr r0,[context,#iapu_extraram]\n");
+ ot(" ldrh r0,[r0,#0x20]\n");
+ ot(" add spc_pc,spc_ram,r0\n");
+ break;
+
+ case 0xEF: // SLEEP
+ case 0xFF: // STOP: this is to be compatible with yoyofr's code
+ //ot(" ldr r0,=CPU\n");
+ ot(" ldr r0, 5001f\n", apu_cycles);
+ ot(" mov r1,#0\n");
+ //otb(" strb r1,[r0,#122]\n");
+ otb(" str r1,[r0,#cpu_apu_executing]\n");
+ //tmp_epilogue();
+ ot(" subs cycles,cycles,#%i\n", S9xAPUCycles[opcode] * one_apu_cycle[current_cycles]);
+ ot(" ldrgeb opcode,[spc_pc],#1\n");
+ flush_buffer();
+ ot(" ldrge pc,[opcodes,opcode,lsl #2]\n");
+ ot(" b spc700End\n");
+ // don't let code flow until here
+ ot("5001:\n", apu_cycles);
+ ot(" .long CPU \n");
+ break;
+
+ case 0x2F: // BRA
+ ot(" ldrsb r0,[spc_pc],#1\n");
+ ot(" add spc_pc,spc_pc,r0\n");
+ break;
+
+ case 0x80: // SETC
+ otb(" orr spc_p,spc_p,#flag_c\n");
+ break;
+
+ case 0xED: // NOTC
+ otb(" eor spc_p,spc_p,#flag_c\n");
+ break;
+
+ case 0x40: // SETP
+ ot(" orr spc_p,spc_p,#flag_d\n");
+ ot(" add r0,spc_ram,#0x100\n");
+ otb(" str r0,[context,#iapu_directpage]\n");
+ break;
+
+ case 0x1A: // DECW dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc]\n");
+ ot(" add r0,r0,#1\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" orr r1,r3,r0,lsl #8\n");
+ ot(" sub r0,r1,#1\n");
+ SetZN16("r0");
+ ot(" stmfd sp!,{r0}\n");
+ ot(" ldrb r1,[spc_pc]\n");
+ MemHandler(1, 1, 0);
+ ot(" ldmfd sp!,{r0}\n");
+ ot(" mov r0,r0,lsr #8\n");
+ ot(" ldrb r1,[spc_pc],#1\n");
+
+ ot(" add r1,r1,#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x5A: // CMPW YA,dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" add r0,r0,#1\n");
+ MemHandler(0, 1, 1);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" orr r1,r3,r0,lsl #8\n");
+ ot(" subs r0,spc_ya,r1\n");
+ ot(" orrge spc_p,spc_p,#flag_c\n");
+ ot(" biclt spc_p,spc_p,#flag_c\n");
+ SetZN16("r0");
+ break;
+
+ case 0x3A: // INCW dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc]\n");
+ ot(" add r0,r0,#1\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" orr r1,r3,r0,lsl #8\n");
+ ot(" add r0,r1,#1\n");
+ SetZN16("r0");
+ ot(" stmfd sp!,{r0}\n");
+ ot(" ldrb r1,[spc_pc]\n");
+ MemHandler(1, 1, 0);
+ ot(" ldmfd sp!,{r0}\n");
+ ot(" mov r0,r0,lsr #8\n");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" add r1,r1,#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x7A: // ADDW YA,dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" add r0,r0,#1\n");
+ MemHandler(0, 1, 1);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" orr r1,r3,r0,lsl #8\n");
+ ot(" add r0,spc_ya,r1\n");
+ ot(" movs r2,r0,lsr #16\n");
+ ot(" orrne spc_p,spc_p,#flag_c\n");
+ ot(" biceq spc_p,spc_p,#flag_c\n");
+ ot(" bic r2,r0,#0x00ff0000\n");
+ ot(" eor r3,r1,r2\n"); // Work16 ^ (uint16) Work32
+ ot(" eor r14,spc_ya,r1\n");
+ ot(" mvn r14,r14\n"); // ~(pIAPU->YA.W ^ Work16)
+ ot(" and r14,r14,r3\n");
+ ot(" tst r14,#0x8000\n");
+ ot(" orrne spc_p,spc_p,#flag_o\n");
+ ot(" biceq spc_p,spc_p,#flag_o\n");
+ ot(" eor r14,r3,spc_ya\n");
+ ot(" tst r14,#0x10\n");
+ ot(" orrne spc_p,spc_p,#flag_h\n");
+ ot(" biceq spc_p,spc_p,#flag_h\n");
+ ot(" mov spc_ya,r2\n");
+ SetZN16("spc_ya");
+
+ break;
+
+ case 0x9A: // SUBW YA,dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" add r0,r0,#1\n");
+ MemHandler(0, 1, 1);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" orr r1,r3,r0,lsl #8\n");
+ ot(" subs r0,spc_ya,r1\n");
+ ot(" orrge spc_p,spc_p,#flag_c\n");
+ ot(" biclt spc_p,spc_p,#flag_c\n");
+ ot(" mov r2,r0,lsl #16\n");
+ ot(" mov r2,r2,lsr #16\n"); // r2=(uint16) Int32
+ ot(" eor r3,spc_ya,r2\n"); // r3=pIAPU->YA.W ^ (uint16) Int32
+ ot(" eor r14,spc_ya,r1\n");
+ ot(" and r14,r14,r3\n");
+ ot(" tst r14,#0x8000\n");
+ ot(" orrne spc_p,spc_p,#flag_o\n");
+ ot(" biceq spc_p,spc_p,#flag_o\n");
+ ot(" eor r14,r3,r1\n");
+ ot(" tst r14,#0x10\n");
+ ot(" bicne spc_p,spc_p,#flag_h\n");
+ ot(" orreq spc_p,spc_p,#flag_h\n");
+ ot(" mov spc_ya,r2\n");
+ SetZN16("spc_ya");
+ break;
+
+ case 0xBA: // MOVW YA,dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ ot(" ldrb r1, [spc_pc],#1\n");
+ ot(" mov spc_ya, r0\n"); // avoiding inter-locks
+ ot(" add r0, r1, #1\n");
+ MemHandler(0, 1, 1);
+ ot(" orr spc_ya,spc_ya,r0,lsl #8\n");
+ SetZN16("spc_ya");
+ break;
+
+ case 0xDA: // MOVW dp,YA
+ ot(" ldrb r1,[spc_pc]\n");
+ ot(" mov r0,spc_ya\n");
+ MemHandler(1, 1, 0);
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" mov r0,spc_ya,lsr #8\n"); // avoiding inter-locks
+ ot(" add r1,r1,#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x69: // CMP dp(dest), dp(src)
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 0);
+ ot(" orr spc_x,spc_x,r0,lsl #24\n");
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 1);
+ ot(" mov r1,spc_x,lsr #24\n");
+ Cmp("r0", "r1", 0);
+ otb(" and spc_x,spc_x,#0xff\n");
+ break;
+
+ case 0x78: // CMP dp,#00
+ ot(" ldrb r0,[spc_pc,#1]\n");
+ MemHandler(0, 1, 1);
+ ot(" ldrb r1,[spc_pc],#2\n");
+ Cmp("r0", "r1", 0);
+ break;
+
+ case 0x79: // CMP (X),(Y)
+ ot(" mov r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ ot(" orr spc_x,spc_x,r0,lsl #24\n");
+ ot(" mov r0,spc_ya,lsr #8\n");
+ MemHandler(0, 1, 1);
+ ot(" mov r1,spc_x,lsr #24\n");
+ Cmp("r1", "r0", 0);
+ otb(" and spc_x,spc_x,#0xff\n");
+ break;
+
+ case 0x1E: // CMP X,abs
+ Absolute(0);
+ MemHandler(0, 0, 1);
+ Cmp("spc_x", "r0", 0);
+ break;
+
+ case 0x3E: // CMP X,dp
+ ot(" ldrb r0,[spc_pc],#1\n");
+
+ MemHandler(0, 1, 1);
+ Cmp("spc_x", "r0", 0);
+ break;
+
+ case 0xC8: // CMP X,#00
+ ot(" ldrb r0,[spc_pc],#1\n");
+ Cmp("spc_x", "r0", 0);
+ break;
+
+ case 0x5E: // CMP Y,abs
+ Absolute(0);
+ MemHandler(0, 0, 1);
+ ot(" mov r1,spc_ya,lsr #8\n");
+ Cmp("r1", "r0", 0);
+ break;
+
+ case 0x7E: // CMP Y,dp
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 1);
+ ot(" mov r1,spc_ya,lsr #8\n");
+ Cmp("r1", "r0", 0);
+ break;
+
+ case 0xAD: // CMP Y,#00
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" mov r1,spc_ya,lsr #8\n");
+ Cmp("r1", "r0", 0);
+ break;
+
+ case 0x1F: // JMP (abs+X)
+ AbsoluteX(0);
+ ot(" sub sp,sp,#8\n");
+ ot(" str r0,[sp,#4]\n");
+ MemHandler(0, 0, 0);
+ ot(" str r0,[sp]\n");
+ ot(" ldr r0,[sp,#4]\n");
+ ot(" add r0,r0,#1\n");
+ MemHandler(0, 0, 1);
+ ot(" ldr r1,[sp],#8\n");
+ ot(" orr r0,r1,r0,lsl #8\n");
+ ot(" add spc_pc,spc_ram,r0\n");
+ break;
+
+ case 0x5F: // JMP abs
+ //Absolute(0);
+ //ot(" add spc_pc,spc_ram,r0\n");
+ ot(" ldrb r0, [spc_pc], #1\n");
+ ot(" ldrb r14, [spc_pc], #1\n");
+ ot(" add spc_pc, r0, spc_ram\n");
+ ot(" add spc_pc, spc_pc, r14, lsl #8\n");
+ break;
+
+ case 0x20: // CLRP
+ ot(" bic spc_p,spc_p,#flag_d\n");
+ otb(" str spc_ram,[context,#iapu_directpage]\n");
+ break;
+
+ case 0x60: // CLRC
+ otb(" bic spc_p,spc_p,#flag_c\n");
+ break;
+
+ case 0xE0: // CLRV
+ otb(" bic spc_p,spc_p,#(flag_o|flag_h)\n");
+ break;
+
+ case 0x29: // AND dp(dest), dp(src)
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" and r0,r0,r3\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x38: // AND dp,#00
+ ot(" ldrb r0,[spc_pc,#1]\n");
+ MemHandler(0, 1, 0);
+ ot(" ldrb r1,[spc_pc],#2\n");
+ ot(" and r0,r0,r1\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc,#-1]\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x39: // AND (X),(Y)
+ ot(" mov r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" mov r0,spc_ya,lsr #8\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" and r0,r0,r3\n");
+ SetZN8("r0");
+ ot(" mov r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x2B: // ROL dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ Rol();
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x2C: // ROL abs
+ Absolute(0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ MemHandler(0, 0, 0);
+ Rol();
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" mov r1, r3\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0x3B: // ROL dp+X
+ ot(" ldrb r0,[spc_pc]\n");
+ ot(" add r0,r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ Rol();
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" add r1,r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x3C: // ROL A
+ ot(" and r0,spc_ya,#0xff\n");
+ Rol();
+ ot(" and r0,r0,#0xff\n");
+ ot(" mov spc_ya,spc_ya,lsr #8\n");
+ otb(" orr spc_ya,r0,spc_ya,lsl #8\n");
+ break;
+
+ case 0x2E: // CBNE dp,rel
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 1);
+ ot(" and r1,spc_ya,#0xff\n");
+ ot(" cmp r0,r1\n");
+ ot(" addeq spc_pc,spc_pc,#1\n");
+ ot(" ldrnesb r0,[spc_pc],#1\n");
+ ot(" subne cycles,cycles,#%i\n", one_apu_cycle[current_cycles]*2);
+ ot(" addne spc_pc,spc_pc,r0\n");
+ break;
+
+ case 0xDE: // CBNE dp+X,rel
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" add r0,r0,spc_x\n");
+ MemHandler(0, 1, 1);
+ ot(" and r1,spc_ya,#0xff\n");
+ ot(" cmp r0,r1\n");
+ ot(" addeq spc_pc,spc_pc,#1\n");
+ ot(" ldrnesb r0,[spc_pc],#1\n");
+ ot(" addne spc_pc,spc_pc,r0\n");
+ ot(" subne cycles,cycles,#%i\n", one_apu_cycle[current_cycles]*2);
+ break;
+
+ case 0x3D: // INC X
+ ot(" add spc_x,spc_x,#1\n");
+ ot(" and spc_x,spc_x,#0xff\n");
+ SetZN8("spc_x");
+ break;
+
+ case 0xFC: // INC Y
+ ot(" mov r0,spc_ya,lsr #8\n");
+ ot(" add r0,r0,#1\n");
+ ot(" and r0,r0,#0xff\n");
+ SetZN8("r0");
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ otb(" orr spc_ya,spc_ya,r0,lsl #8\n");
+ break;
+
+ case 0x1D: // DEC X
+ ot(" sub spc_x,spc_x,#1\n");
+ ot(" and spc_x,spc_x,#0xff\n");
+ SetZN8("spc_x");
+ break;
+
+ case 0xDC: // DEC Y
+ ot(" mov r0,spc_ya,lsr #8\n");
+ ot(" sub r0,r0,#1\n");
+ ot(" and r0,r0,#0xff\n");
+ SetZN8("r0");
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ otb(" orr spc_ya,spc_ya,r0,lsl #8\n");
+ break;
+
+ case 0xAB: // INC dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ ot(" add r0,r0,#1\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xAC: // INC abs
+ Absolute(0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ MemHandler(0, 0, 0);
+ ot(" add r0,r0,#1\n");
+ SetZN8("r0");
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" mov r1, r3\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0xBB: // INC dp+X
+ ot(" ldrb r0,[spc_pc]\n");
+ ot(" add r0,r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ ot(" add r0,r0,#1\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" add r1,r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xBC: // INC A
+ ot(" and r0,spc_ya,#0xff\n");
+ ot(" add r0,r0,#1\n");
+ SetZN8("r0");
+ ot(" and r0,r0,#0xff\n");
+ ot(" mov spc_ya,spc_ya,lsr #8\n");
+ otb(" orr spc_ya,r0,spc_ya,lsl #8\n");
+ break;
+
+ case 0x8B: // DEC dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ ot(" sub r0,r0,#1\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x8C: // DEC abs
+ Absolute(0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ MemHandler(0, 0, 0);
+ ot(" sub r0,r0,#1\n");
+ SetZN8("r0");
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" mov r1, r3\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0x9B: // DEC dp+X
+ ot(" ldrb r0,[spc_pc]\n");
+ ot(" add r0,r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ ot(" sub r0,r0,#1\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+
+ ot(" add r1,r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x9C: // DEC A
+ ot(" and r0,spc_ya,#0xff\n");
+ ot(" sub r0,r0,#1\n");
+ SetZN8("r0");
+ ot(" and r0,r0,#0xff\n");
+ ot(" mov spc_ya,spc_ya,lsr #8\n");
+ otb(" orr spc_ya,r0,spc_ya,lsl #8\n");
+ break;
+
+ case 0x49: // EOR dp(dest), dp(src)
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" eor r0,r0,r3\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x58: // EOR dp,#00
+ ot(" ldrb r0,[spc_pc,#1]\n");
+ MemHandler(0, 1, 0);
+ ot(" ldrb r1,[spc_pc],#2\n");
+ ot(" eor r0,r0,r1\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc,#-1]\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x59: // EOR (X),(Y)
+ ot(" mov r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" mov r0,spc_ya,lsr #8\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" eor r0,r0,r3\n");
+ SetZN8("r0");
+ ot(" mov r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x4B: // LSR dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ Lsr();
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x4C: // LSR abs
+ Absolute(0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ MemHandler(0, 0, 0);
+ Lsr();
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" mov r1, r3\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0x5B: // LSR dp+X
+ ot(" ldrb r0,[spc_pc]\n");
+ ot(" add r0,r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ Lsr();
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" add r1,r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x5C: // LSR A
+ ot(" and r0,spc_ya,#0xff\n");
+ Lsr();
+ ot(" mov spc_ya,spc_ya,lsr #8\n");
+ otb(" orr spc_ya,r0,spc_ya,lsl #8\n");
+ break;
+
+ case 0x7D: // MOV A,X
+ ot(" and spc_ya,spc_ya,#0xff00\n");
+ ot(" orr spc_ya,spc_ya,spc_x\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0xDD: // MOV A,Y
+ ot(" and spc_ya,spc_ya,#0xff00\n");
+ ot(" orr spc_ya,spc_ya,spc_ya,lsr #8\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0x5D: // MOV X,A
+ ot(" and spc_x,spc_ya,#0xff\n");
+ SetZN8("spc_x");
+ break;
+
+ case 0xFD: // MOV Y,A
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ ot(" orr spc_ya,spc_ya,spc_ya,lsl #8\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0x9D: // MOV X,SP
+ ot(" mov spc_x,spc_s\n");
+ SetZN8("spc_x");
+ break;
+
+ case 0xBD: // SP,X
+ otb(" mov spc_s,spc_x\n");
+ break;
+
+ case 0x6B: // ROR dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ Ror();
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x6C: // ROR abs
+ Absolute(0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ MemHandler(0, 0, 0);
+ Ror();
+ ot(" mov r1, r3\n");
+ //ot(" ldmfd sp!,{r1}\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0x7B: // ROR dp+X
+ ot(" ldrb r0,[spc_pc]\n");
+ ot(" add r0,r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ Ror();
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" add r1,r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x7C: // ROR A
+ ot(" and r0,spc_ya,#0xff\n");
+ Ror();
+ ot(" mov spc_ya,spc_ya,lsr #8\n");
+ otb(" orr spc_ya,r0,spc_ya,lsl #8\n");
+ break;
+
+ case 0x6E: // DBNZ dp,rel
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" sub r0,r0,#1\n");
+ ot(" tst r0,r0\n");
+ ot(" addeq spc_pc,spc_pc,#1\n");
+ ot(" ldrnesb r2,[spc_pc],#1\n");
+ ot(" addne spc_pc,spc_pc,r2\n");
+ ot(" subne cycles,cycles,#%i\n", one_apu_cycle[current_cycles]*2);
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xFE: // DBNZ Y,rel
+ ot(" sub spc_ya,spc_ya,#0x100\n");
+ ot(" mov spc_ya,spc_ya,lsl #16\n");
+ ot(" mov spc_ya,spc_ya,lsr #16\n");
+ ot(" movs r0,spc_ya,lsr #8\n");
+ ot(" addeq spc_pc,spc_pc,#1\n");
+ ot(" ldrnesb r0,[spc_pc],#1\n");
+ ot(" addne spc_pc,spc_pc,r0\n");
+ ot(" subne cycles,cycles,#%i\n", one_apu_cycle[current_cycles]*2);
+ break;
+
+ case 0x6F: // RET
+ PopW();
+ ot(" add spc_pc,spc_ram,r0\n");
+ break;
+
+ case 0x7F: // RETI
+ Pop("spc_p");
+ ot(" and r0,spc_p,#(flag_z|flag_n)\n");
+ ot(" eor r0,r0,#flag_z\n");
+ ot(" orr spc_p,spc_p,r0,lsl #24\n");
+ ot(" tst spc_p,#flag_d\n");
+ ot(" addne r0,spc_ram,#0x100\n");
+ ot(" moveq r0,spc_ram\n");
+ ot(" str r0,[context,#iapu_directpage]\n");
+ PopW();
+ ot(" add spc_pc,spc_ram,r0\n");
+ break;
+
+ case 0x89: // ADC dp(dest), dp(src)
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ //ot(" mov r1, r3\n");
+ Adc("r0", "r3");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x98: // ADC dp,#00
+ ot(" ldrb r0,[spc_pc,#1]\n");
+ MemHandler(0, 1, 0);
+ ot(" ldrb r1,[spc_pc],#2\n");
+ Adc("r0", "r1");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc,#-1]\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x99: // ADC (X),(Y)
+ ot(" mov r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" mov r0,spc_ya,lsr #8\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ //ot(" mov r1, r3\n");
+ Adc("r0", "r3");
+ SetZN8("r0");
+ ot(" mov r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x8D: // MOV Y,#00 //-REVISAR
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ ot(" orr spc_ya,spc_ya,r0,lsl #8\n");
+ SetZN8("r0");
+ break;
+
+ case 0x8F: // MOV dp,#00 //-REVISAR
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x9E: // DIV YA,X
+ ot(" tst spc_x,spc_x @ div by 0?\n");
+ ot(" orreq spc_ya,spc_ya,#0xff00\n");
+ ot(" orreq spc_ya,spc_ya,#0x00ff\n");
+ ot(" orreq spc_p,spc_p,#flag_o\n");
+ ot(" beq 1002f\n");
+ ot(" bic spc_p,spc_p,#flag_o\n");
+
+ // division algo from Cyclone (result in r3, remainder instead of divident)
+ ot("@ Divide spc_ya by spc_x\n");
+ ot(" mov r3,#0\n");
+ ot(" mov r1,spc_x\n");
+ ot("\n");
+
+ //
+ /*ot("@ Shift up divisor till it's just less than numerator\n");
+ ot("divshift:\n");
+ ot(" cmp r1,spc_ya,lsr #1\n");
+ ot(" movls r1,r1,lsl #1\n");
+ ot(" bcc divshift\n");
+ ot("\n");*/
+
+ //optimised version of code provided by William Blair
+ ot("@ Shift up divisor till it's just less than numerator\n");
+ ot("cmp spc_ya,r1,lsl #8\n");
+ ot("movge r1,r1,lsl #8\n");
+ ot("cmp spc_ya,r1,lsl #4\n");
+ ot("movge r1,r1,lsl #4\n");
+ ot("cmp spc_ya,r1,lsl #2\n");
+ ot("movge r1,r1,lsl #2\n");
+ ot("cmp spc_ya,r1,lsl #1\n");
+ ot("movge r1,r1,lsl #1\n");
+
+ ot("1001:\n");
+ ot(" cmp spc_ya,r1\n");
+ ot(" adc r3,r3,r3 ;@ Double r3 and add 1 if carry set\n");
+ ot(" subcs spc_ya,spc_ya,r1\n");
+ ot(" teq r1,spc_x\n");
+ ot(" movne r1,r1,lsr #1\n");
+ ot(" bne 1001b\n");
+ ot("\n");
+
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ ot(" and r3,r3,#0xff\n");
+ ot(" orr spc_ya,r3,spc_ya,lsl #8\n");
+
+ ot("1002:\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0x9F: // XCN A
+ ot(" and r0,spc_ya,#0xff\n");
+ ot(" mov r1,r0,lsl #28\n");
+ ot(" orr r0,r1,r0,lsl #20\n");
+ ot(" and spc_ya,spc_ya,#0xff00\n");
+ ot(" orr spc_ya,spc_ya,r0,lsr #24\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0xA9: // SBC dp(dest), dp(src)
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ //ot(" mov r1, r3\n");
+ Sbc("r0", "r3");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xB8: // SBC dp,#00
+ ot(" ldrb r0,[spc_pc,#1]\n");
+ MemHandler(0, 1, 0);
+ ot(" ldrb r1,[spc_pc],#2\n");
+ Sbc("r0", "r1");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc,#-1]\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xB9: // SBC (X),(Y)
+ ot(" mov r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" mov r0,spc_ya,lsr #8\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ //ot(" mov r1, r3\n");
+ Sbc("r0", "r3");
+ SetZN8("r0");
+ ot(" mov r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xAF: // MOV (X)+, A
+ ot(" mov r0,spc_ya\n");
+ ot(" mov r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ ot(" add spc_x,spc_x,#1\n");
+ otb(" and spc_x,spc_x,#0xff\n");
+ break;
+
+ case 0xBE: // DAS
+ ot(" and r0,spc_ya,#0xff\n");
+ ot(" and r1,spc_ya,#0x0f\n");
+ ot(" cmp r1,#9\n");
+ ot(" subhi r0,r0,#6\n");
+ ot(" tstls spc_p,#flag_h\n");
+ ot(" subeq r0,r0,#6\n");
+ ot(" cmp r0,#0x9f\n");
+ ot(" bhi 2001f\n");
+ ot(" tst spc_p,#flag_c\n");
+ ot(" beq 2001f\n");
+ ot(" orr spc_p,spc_p,#flag_c\n");
+ ot(" b 2002f\n");
+ ot("2001:\n"); // tens
+ ot(" sub r0,r0,#0x60\n");
+ ot(" bic spc_p,spc_p,#flag_c\n");
+
+ ot("2002:\n"); // end
+ ot(" and spc_ya,spc_ya,#0xff00\n");
+ ot(" orr spc_ya,spc_ya,r0\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0xBF: // MOV A,(X)+
+ ot(" mov r0,spc_x\n");
+ MemHandler(0, 1, 1);
+ ot(" and spc_ya,spc_ya,#0xff00\n");
+ ot(" orr spc_ya,spc_ya,r0\n");
+ ot(" add spc_x,spc_x,#1\n");
+ ot(" and spc_x,spc_x,#0xff\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0xC0: // DI
+ otb(" bic spc_p,spc_p,#flag_i\n");
+ break;
+
+ case 0xA0: // EI
+ otb(" orr spc_p,spc_p,#flag_i\n");
+ break;
+
+ case 0xC4: // MOV dp,A
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" mov r0,spc_ya\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xC5: // MOV abs,A
+ Absolute(1);
+ ot(" mov r0,spc_ya\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0xC6: // MOV (X),A
+ ot(" mov r0,spc_ya\n");
+ ot(" mov r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xC7: // MOV (dp+X),A
+ IndexedXIndirect(1);
+ ot(" mov r0,spc_ya\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0xC9: // MOV abs,X
+ Absolute(1);
+ ot(" mov r0,spc_x\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0xCB: // MOV dp,Y
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" mov r0,spc_ya,lsr #8\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xCC: // MOV abs,Y
+
+ Absolute(1);
+ ot(" mov r0,spc_ya,lsr #8\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0xCD: // MOV X,#00
+ ot(" ldrb spc_x,[spc_pc],#1\n");
+ SetZN8("spc_x");
+ break;
+
+ case 0xCF: // MUL YA
+ ot(" mov r0,spc_ya,lsr #8\n");
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ ot(" mul spc_ya,r0,spc_ya\n");
+ SetZN16("spc_ya");
+ break;
+
+ case 0xD4: // MOV dp+X, A
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" mov r0,spc_ya\n");
+ ot(" add r1,r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xD5: // MOV abs+X,A
+ AbsoluteX(1);
+ ot(" mov r0,spc_ya\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0xD6: // MOV abs+Y,A
+ AbsoluteY(1);
+ ot(" mov r0,spc_ya\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0xD7: // MOV (dp)+Y,A
+ IndirectIndexedY(1);
+ ot(" mov r0,spc_ya\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0xD8: // MOV dp,X
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" mov r0,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xD9: // MOV dp+Y,X
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" mov r0,spc_x\n");
+ ot(" add r1,r1,spc_ya,lsr #8\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xDB: // MOV dp+X,Y
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" mov r0,spc_ya,lsr #8\n");
+ ot(" add r1,r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xDF: // DAA
+ ot(" and r0,spc_ya,#0xff\n");
+ ot(" and r1,spc_ya,#0x0f\n");
+ ot(" cmp r1,#9\n");
+ ot(" addhi r0,r0,#6\n");
+ ot(" bls 3001f\n");
+ ot(" cmphi r0,#0xf0\n");
+ ot(" orrhi spc_p,spc_p,#flag_c\n");
+ ot(" b 3002f\n");
+ ot("3001:\n"); // testHc
+ ot(" tst spc_p,#flag_h\n");
+ ot(" addne r0,r0,#6\n");
+ ot(" beq 3002f\n");
+ ot(" cmp r0,#0xf0\n");
+ ot(" orrhi spc_p,spc_p,#flag_c\n");
+ ot("3002:\n"); // test2
+ ot(" tst spc_p,#flag_c\n");
+ ot(" addne r0,r0,#0x60\n");
+ ot(" bne 3003f\n");
+ ot(" cmp r0,#0x9f\n");
+ ot(" addhi r0,r0,#0x60\n");
+ ot(" orrhi spc_p,spc_p,#flag_c\n");
+ ot(" bicls spc_p,spc_p,#flag_c\n");
+ ot("3003:\n"); // end
+ ot(" and spc_ya,spc_ya,#0xff00\n");
+ ot(" orr spc_ya,spc_ya,r0\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0xE9: // MOV X, abs
+ Absolute(0);
+ MemHandler(0, 0, 1);
+ ot(" mov spc_x,r0\n");
+ SetZN8("spc_x");
+ break;
+
+ case 0xEB: // MOV Y,dp
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 1);
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ ot(" orr spc_ya,spc_ya,r0,lsl #8\n");
+ SetZN8("r0");
+ break;
+
+ case 0xEC: // MOV Y,abs
+ Absolute(0);
+ MemHandler(0, 0, 1);
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ ot(" orr spc_ya,spc_ya,r0,lsl #8\n");
+ SetZN8("r0");
+ break;
+
+ case 0xF8: // MOV X,dp
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 1);
+ ot(" mov spc_x,r0\n");
+ SetZN8("spc_x");
+ break;
+
+ case 0xF9: // MOV X,dp+Y
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" add r0,r0,spc_ya,lsr #8\n");
+ MemHandler(0, 1, 1);
+ ot(" mov spc_x,r0\n");
+ SetZN8("spc_x");
+ break;
+
+ case 0xFA: // MOV dp(dest),dp(src)
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 0);
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xFB: // MOV Y,dp+X
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" add r0,r0,spc_x\n");
+ MemHandler(0, 1, 1);
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ ot(" orr spc_ya,spc_ya,r0,lsl #8\n");
+ SetZN8("r0");
+ break;
+ }
+
+ //tmp_epilogue();
+ ot(" subs cycles,cycles,#%i\n", S9xAPUCycles[opcode] * one_apu_cycle[current_cycles]);
+ ot(" ldrgeb opcode,[spc_pc],#1\n");
+ flush_buffer();
+ ot(" ldrge pc,[opcodes,opcode,lsl #2]\n");
+ ot(" b spc700End\n");
+
+ printf("\b\b");
+ }
+
+
+ ot("\n\n");
+
+}
+
+
+void printJumpTable(int apu_cycles) {
+ int i;
+ ot("@ -------------------------- Jump Table %i --------------------------\n", apu_cycles);
+ ot("Spc700JumpTab_%i:\n", apu_cycles);
+
+ for (i=0; i < 0x100; i++)
+ {
+ if ((i&7)==0) ot(" .long ");
+
+ ot("Apu%02X_%i", i, apu_cycles);
+
+ if ((i&7)==7) ot(" @ %02x\n",i-7);
+ else if (i+1 < 0x100) ot(", ");
+ }
+
+}
+
+int main()
+{
+ printf("\n notaz's SPC700 Emulator v%s - Core Creator\n\n", VERSION);
+
+ // Open the assembly file
+ AsmFile=fopen("spc700a.s", "wt"); if (AsmFile==NULL) return 1;
+
+ ot("@ notaz's SPC700 Emulator v%s - Assembler Output\n\n", VERSION);
+ ot("@ (c) Copyright 2006 notaz, All rights reserved.\n\n");
+ ot("@ Modified by bitrider 2010 - 2011\n\n");
+ ot("@ this is a rewrite of spc700.cpp in ARM asm, inspired by other asm CPU cores like\n");
+ ot("@ Cyclone and DrZ80. It is meant to be used in Snes9x emulator ports for ARM platforms.\n\n");
+ ot("@ the code is released under Snes9x license. See spcgen.c or any other source file\n@ from Snes9x source tree.\n\n\n");
+
+ PrintFramework();
+
+ ot(" .align 4\n");
+
+ for (current_cycles=0; current_cycles < (sizeof(one_apu_cycle) / sizeof(int)); current_cycles++) {
+ printOpcodes(one_apu_cycle[current_cycles]);
+ printJumpTable(one_apu_cycle[current_cycles]);
+ }
+
+
+ fclose(AsmFile); AsmFile=NULL;
+
+ printf("Assembling...\n");
+ // Assemble the file
+ //system("as -marmv4t -mthumb-interwork -o spc700a.o spc700a.S");
+ printf("Done!\n\n");
+
+ return 0;
+}