}\r
\r
#if (CYCLONE_FOR_GENESIS == 2)\r
-// r12=ptr to tas in table, trashes r0,r1\r
-static void ChangeTAS(int norm)\r
+static const char *tas_ops[] = {\r
+ "Op4ad0", "Op4ad8", "Op4adf",\r
+ "Op4ae0", "Op4ae7", "Op4ae8",\r
+ "Op4af0", "Op4af8", "Op4af9",\r
+};\r
+\r
+// get handler address in r0, OT (offset table) in r2\r
+static void ChangeTASGet(unsigned int i)\r
{\r
- ot(" ldr r0,=Op4ad0%s\n",norm?"_":"");\r
- ot(" mov r1,#8\n");\r
- ot("setrtas_loop%i0%s ;@ 4ad0-4ad7\n",norm,ms?"":":");\r
- ot(" subs r1,r1,#1\n");\r
- ot(" str r0,[r12],#4\n");\r
- ot(" bne setrtas_loop%i0\n",norm);\r
- ot(" ldr r0,=Op4ad8%s\n",norm?"_":"");\r
- ot(" mov r1,#7\n");\r
- ot("setrtas_loop%i1%s ;@ 4ad8-4ade\n",norm,ms?"":":");\r
- ot(" subs r1,r1,#1\n");\r
- ot(" str r0,[r12],#4\n");\r
- ot(" bne setrtas_loop%i1\n",norm);\r
- ot(" ldr r0,=Op4adf%s\n",norm?"_":"");\r
- ot(" str r0,[r12],#4\n");\r
- ot(" ldr r0,=Op4ae0%s\n",norm?"_":"");\r
- ot(" mov r1,#7\n");\r
- ot("setrtas_loop%i2%s ;@ 4ae0-4ae6\n",norm,ms?"":":");\r
- ot(" subs r1,r1,#1\n");\r
- ot(" str r0,[r12],#4\n");\r
- ot(" bne setrtas_loop%i2\n",norm);\r
- ot(" ldr r0,=Op4ae7%s\n",norm?"_":"");\r
- ot(" str r0,[r12],#4\n");\r
- ot(" ldr r0,=Op4ae8%s\n",norm?"_":"");\r
- ot(" mov r1,#8\n");\r
- ot("setrtas_loop%i3%s ;@ 4ae8-4aef\n",norm,ms?"":":");\r
- ot(" subs r1,r1,#1\n");\r
- ot(" str r0,[r12],#4\n");\r
- ot(" bne setrtas_loop%i3\n",norm);\r
- ot(" ldr r0,=Op4af0%s\n",norm?"_":"");\r
- ot(" mov r1,#8\n");\r
- ot("setrtas_loop%i4%s ;@ 4af0-4af7\n",norm,ms?"":":");\r
- ot(" subs r1,r1,#1\n");\r
- ot(" str r0,[r12],#4\n");\r
- ot(" bne setrtas_loop%i4\n",norm);\r
- ot(" ldr r0,=Op4af8%s\n",norm?"_":"");\r
- ot(" str r0,[r12],#4\n");\r
- ot(" ldr r0,=Op4af9%s\n",norm?"_":"");\r
- ot(" str r0,[r12],#4\n");\r
+ if (i >= sizeof(tas_ops) / sizeof(tas_ops[0]))\r
+ abort();\r
+ ot(" ldr r0,[r2,#%d*4] ;@ %s\n",i,tas_ops[i]);\r
+ ot(" add r0,r0,r2\n");\r
}\r
#endif\r
\r
}\r
#endif\r
\r
-void FlushPC(void)\r
+void FlushPC(int force)\r
{\r
#if MEMHANDLERS_NEED_PC\r
- if (pc_dirty)\r
- ot(" str r4,[r7,#0x40] ;@ Save PC\n");\r
-#endif\r
+ force |= pc_dirty;\r
pc_dirty = 0;\r
+#endif\r
+ if (force)\r
+ ot(" str r4,[r7,#0x40] ;@ Save PC\n");\r
}\r
\r
static void PrintFramework()\r
ot(" mov r7,r0 ;@ r7 = Pointer to Cpu Context\n");\r
ot(" ;@ r0-3 = Temporary registers\n");\r
ot(" ldrb r10,[r7,#0x46] ;@ r10 = Flags (NZCV)\n");\r
- ot(" ldr r6,=CycloneJumpTab ;@ r6 = Opcode Jump table\n");\r
+ ot(" ldr r6,[r7,#0x54] ;@ r6 = Opcode Jump table (from reset)\n");\r
ot(" ldr r5,[r7,#0x5c] ;@ r5 = Cycles\n");\r
ot(" ldr r4,[r7,#0x40] ;@ r4 = Current PC + Memory Base\n");\r
ot(" ;@ r8 = Current Opcode\n");\r
ot(" ldr r1,[r7,#0x44] ;@ Get SR high T_S__III and irq level\n");\r
ot(" mov r10,r10,lsl #28;@ r10 = Flags 0xf0000000, cpsr format\n");\r
ot(" ;@ r11 = Source value / Memory Base\n");\r
- ot(" str r6,[r7,#0x54] ;@ make a copy to avoid literal pools\n");\r
ot("\n");\r
#if (CYCLONE_FOR_GENESIS == 2) || EMULATE_TRACE\r
ot(" mov r2,#0\n");\r
ot("\n");\r
ot("\n");\r
\r
- ot("CycloneInit%s\n", ms?"":":");\r
+ ot("CycloneInitJT%s\n", ms?"":":");\r
#if COMPRESS_JUMPTABLE\r
ot(";@ decompress jump table\n");\r
- ot(" ldr r12,=CycloneJumpTab\n");\r
+ ot(" mov r12,r0 ;@ jump table\n");\r
ot(" add r0,r12,#0xe000*4 ;@ ctrl code pointer\n");\r
ot(" ldr r1,[r0,#-4]\n");\r
ot(" tst r1,r1\n");\r
ot(" movne pc,lr ;@ already uncompressed\n");\r
+ ot(" stmfd sp!,{r7,lr}\n");\r
+ ot(" mov r7,r12 ;@ jump table\n");\r
ot(" add r3,r12,#0xa000*4 ;@ handler table pointer, r12=dest\n");\r
ot("unc_loop%s\n", ms?"":":");\r
ot(" ldrh r1,[r0],#2\n");\r
ot(" bgt unc_loop_in\n");\r
ot(" b unc_loop\n");\r
ot("unc_finish%s\n", ms?"":":");\r
- ot(" ldr r12,=CycloneJumpTab\n");\r
ot(" ;@ set a-line and f-line handlers\n");\r
- ot(" add r0,r12,#0xa000*4\n");\r
+ ot(" add r0,r7,#0xa000*4\n");\r
ot(" ldr r1,[r0,#4] ;@ a-line handler\n");\r
ot(" ldr r3,[r0,#8] ;@ f-line handler\n");\r
ot(" mov r2,#0x1000\n");\r
ot(" subs r2,r2,#1\n");\r
ot(" str r1,[r0],#4\n");\r
ot(" bgt unc_fill3\n");\r
- ot(" add r0,r12,#0xf000*4\n");\r
+ ot(" add r0,r7,#0xf000*4\n");\r
ot(" mov r2,#0x1000\n");\r
ot("unc_fill4%s\n", ms?"":":");\r
ot(" subs r2,r2,#1\n");\r
ot(" str r3,[r0],#4\n");\r
ot(" bgt unc_fill4\n");\r
- ot(" bx lr\n");\r
+ ot(" ldmfd sp!,{r7,pc}\n");\r
ltorg();\r
#else\r
ot(";@ fix final jumptable entries\n");\r
- ot(" ldr r12,=CycloneJumpTab\n");\r
- ot(" add r12,r12,#0x10000*4\n");\r
- ot(" ldr r0,[r12,#-3*4]\n");\r
- ot(" str r0,[r12,#-2*4]\n");\r
- ot(" str r0,[r12,#-1*4]\n");\r
+ ot(" add r0,r0,#0x10000*4\n");\r
+ ot(" ldr r1,[r0,#-3*4]\n");\r
+ ot(" str r1,[r0,#-2*4]\n");\r
+ ot(" str r1,[r0,#-1*4]\n");\r
ot(" bx lr\n");\r
#endif\r
ot("\n");\r
\r
// --------------\r
- ot("CycloneReset%s\n", ms?"":":");\r
+ ot("CycloneResetJT%s\n", ms?"":":");\r
ot(" stmfd sp!,{r7,lr}\n");\r
ot(" mov r7,r0\n");\r
+ ot(" str r1,[r7,#0x54] ;@ save CycloneJumpTab avoid literal pools\n");\r
ot(" mov r0,#0\n");\r
ot(" str r0,[r7,#0x58] ;@ state_flags\n");\r
ot(" str r0,[r7,#0x48] ;@ OSP\n");\r
ot(" ldmfd sp!,{r7,pc}\n");\r
ot("\n");\r
\r
+ // --------------\r
+ ot("CycloneSetRealTAS_JT%s\n", ms?"":":");\r
+#if (CYCLONE_FOR_GENESIS == 2)\r
+ ot(" tst r0,r0\n");\r
+ ot(" add r12,r1,#0x4a00*4\n");\r
+ ot(" add r12,r12,#0x00d0*4\n");\r
+ ot(" adr r2,CycloneOT_TAS_\n");\r
+ ot(" addeq r2,r2,#%lu*4\n", sizeof(tas_ops) / sizeof(tas_ops[0]));\r
+\r
+ ChangeTASGet(0);\r
+ ot(" mov r1,#8\n");\r
+ ot("setrtas_loop0%s ;@ 4ad0-4ad7\n",ms?"":":");\r
+ ot(" subs r1,r1,#1\n");\r
+ ot(" str r0,[r12],#4\n");\r
+ ot(" bne setrtas_loop0\n");\r
+\r
+ ChangeTASGet(1);\r
+ ot(" mov r1,#7\n");\r
+ ot("setrtas_loop1%s ;@ 4ad8-4ade\n",ms?"":":");\r
+ ot(" subs r1,r1,#1\n");\r
+ ot(" str r0,[r12],#4\n");\r
+ ot(" bne setrtas_loop1\n");\r
+\r
+ ChangeTASGet(2);\r
+ ot(" str r0,[r12],#4\n");\r
+ ChangeTASGet(3);\r
+ ot(" mov r1,#7\n");\r
+ ot("setrtas_loop2%s ;@ 4ae0-4ae6\n",ms?"":":");\r
+ ot(" subs r1,r1,#1\n");\r
+ ot(" str r0,[r12],#4\n");\r
+ ot(" bne setrtas_loop2\n");\r
+\r
+ ChangeTASGet(4);\r
+ ot(" str r0,[r12],#4\n");\r
+ ChangeTASGet(5);\r
+ ot(" mov r1,#8\n");\r
+ ot("setrtas_loop3%s ;@ 4ae8-4aef\n",ms?"":":");\r
+ ot(" subs r1,r1,#1\n");\r
+ ot(" str r0,[r12],#4\n");\r
+ ot(" bne setrtas_loop3\n");\r
+\r
+ ChangeTASGet(6);\r
+ ot(" mov r1,#8\n");\r
+ ot("setrtas_loop4%s ;@ 4af0-4af7\n",ms?"":":");\r
+ ot(" subs r1,r1,#1\n");\r
+ ot(" str r0,[r12],#4\n");\r
+ ot(" bne setrtas_loop4\n");\r
+\r
+ ChangeTASGet(7);\r
+ ot(" str r0,[r12],#4\n");\r
+ ChangeTASGet(8);\r
+ ot(" str r0,[r12],#4\n");\r
+#endif\r
+ ot(" bx lr\n");\r
+ ot("\n");\r
+\r
+ // --------------\r
+ // offset table to avoid .text relocations (forbidden by Android and iOS)\r
+#if (CYCLONE_FOR_GENESIS == 2)\r
+ ot("CycloneOT_TAS_%s\n", ms?"":":"); // working TAS (no MD bug)\r
+ for (size_t i = 0; i < sizeof(tas_ops) / sizeof(tas_ops[0]); i++)\r
+ ot(" %s %s_-CycloneOT_TAS_\n", ms?"dcd":".long", tas_ops[i]);\r
+ ot("CycloneOT_TAS%s\n", ms?"":":"); // broken TAS\r
+ for (size_t i = 0; i < sizeof(tas_ops) / sizeof(tas_ops[0]); i++)\r
+ ot(" %s %s-CycloneOT_TAS\n", ms?"dcd":".long", tas_ops[i]);\r
+ ot("\n");\r
+#endif\r
+\r
// --------------\r
// 68k: XNZVC, ARM: NZCV\r
ot("CycloneSetSr%s\n", ms?"":":");\r
ot("\n");\r
ot("\n");\r
\r
- // --------------\r
- ot("CycloneSetRealTAS%s\n", ms?"":":");\r
-#if (CYCLONE_FOR_GENESIS == 2)\r
- ot(" ldr r12,=CycloneJumpTab\n");\r
- ot(" tst r0,r0\n");\r
- ot(" add r12,r12,#0x4a00*4\n");\r
- ot(" add r12,r12,#0x00d0*4\n");\r
- ot(" beq setrtas_off\n");\r
- ChangeTAS(1);\r
- ot(" bx lr\n");\r
- ot("setrtas_off%s\n",ms?"":":");\r
- ChangeTAS(0);\r
- ot(" bx lr\n");\r
- ltorg();\r
-#else\r
- ot(" bx lr\n");\r
-#endif\r
- ot("\n");\r
-\r
// --------------\r
ot(";@ DoInterrupt - r0=IRQ level\n");\r
ot("CycloneDoInterruptGoBack%s\n", ms?"":":");\r
for(i=0xf000; i<0x10000; i++) CyJump[i] = -3; // f-line emulation\r
\r
ot(ms?" area |.text|, code\n":" .text\n .align 4\n\n");\r
- ot(" %s CycloneInit\n",globl);\r
- ot(" %s CycloneReset\n",globl);\r
+ ot(" %s CycloneInitJT\n",globl);\r
+ ot(" %s CycloneResetJT\n",globl);\r
ot(" %s CycloneRun\n",globl);\r
ot(" %s CycloneSetSr\n",globl);\r
ot(" %s CycloneGetSr\n",globl);\r
ot(" %s CycloneUnpack\n",globl);\r
ot(" %s CycloneVer\n",globl);\r
#if (CYCLONE_FOR_GENESIS == 2)\r
- ot(" %s CycloneSetRealTAS\n",globl);\r
+ ot(" %s CycloneSetRealTAS_JT\n",globl);\r
ot(" %s CycloneDoInterrupt\n",globl);\r
ot(" %s CycloneDoTrace\n",globl);\r
ot(" %s CycloneJumpTab\n",globl);\r