// 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 #include #include #include // 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; 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; 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; }