+\r
+ // 4. Resume execution.\r
+#if EMULATE_ADDRESS_ERRORS_JUMP\r
+ ot(" tst r4,#1\n");\r
+ ot(" bne ExceptionAddressError_r_prg_r4\n");\r
+#endif\r
+ ot(" ldr r6,[r7,#0x54]\n");\r
+ ot(" bx r11 ;@ Return\n");\r
+ ot("\n");\r
+\r
+ // --------------\r
+#if EMULATE_ADDRESS_ERRORS_JUMP || EMULATE_ADDRESS_ERRORS_IO\r
+ // first some wrappers: I see no point inlining this code,\r
+ // as it will be executed in really rare cases.\r
+ AddressErrorWrapper('r', "data", 0x11);\r
+ AddressErrorWrapper('r', "prg", 0x12);\r
+ AddressErrorWrapper('w', "data", 0x01);\r
+ // there are no program writes\r
+ // cpu space is only for bus errors?\r
+ ot("ExceptionAddressError_r_prg_r4%s\n", ms?"":":");\r
+ ot(" ldr r1,[r7,#0x44]\n");\r
+ ot(" ldr r3,[r7,#0x60] ;@ Get Memory base\n");\r
+ ot(" mov r6,#0x12\n");\r
+ ot(" sub r11,r4,r3\n");\r
+ ot(" tst r1,#0x20\n");\r
+ ot(" orrne r6,r6,#4\n");\r
+ ot("\n");\r
+\r
+ ot("ExceptionAddressError%s\n", ms?"":":");\r
+ ot(";@ r6 - info word (without instruction/not bit), r11 - faulting address\n");\r
+\r
+ // 1. Make a temporary copy of the status register and set the status register for exception processing.\r
+ ot(" ldrb r0,[r7,#0x44] ;@ Get old SR high\n");\r
+ ot(" ldr r2,[r7,#0x58] ;@ state flags\n");\r
+ ot(" and r3,r0,#0x27 ;@ clear trace and unused flags\n");\r
+ ot(" orr r3,r3,#0x20 ;@ set supervisor mode\n");\r
+ ot(" strb r3,[r7,#0x44] ;@ Put new SR high\n");\r
+ ot(" bic r2,r2,#3 ;@ clear stopped and trace states\n");\r
+ ot(" tst r2,#4\n");\r
+ ot(" orrne r6,r6,#8 ;@ complete info word\n");\r
+ ot(" orr r2,r2,#4 ;@ set activity bit: 'not processing instruction'\n");\r
+#if EMULATE_HALT\r
+ ot(" tst r2,#8\n");\r
+ ot(" orrne r2,r2,#0x10 ;@ HALT\n");\r
+ ot(" orr r2,r2,#8 ;@ processing address error\n");\r
+ ot(" str r2,[r7,#0x58]\n");\r
+ ot(" movne r5,#0\n");\r
+ ot(" bne CycloneEndNoBack ;@ bye bye\n");\r
+#else\r
+ ot(" str r2,[r7,#0x58]\n");\r
+#endif\r
+ ot(" and r10,r10,#0xf0000000\n");\r
+ ot(" orr r10,r10,r0,lsl #4 ;@ some preparations for SR push\n");\r
+ ot("\n");\r
+\r
+ // 3. Save the current processor context + additional information.\r
+ ot(" ldr r0,[r7,#0x3c] ;@ Get A7\n");\r
+ ot(" tst r10,#0x200\n");\r
+ ot(";@ get our SP:\n");\r
+ ot(" ldreq r2,[r7,#0x48] ;@ ...or OSP as our stack pointer\n");\r
+ ot(" streq r0,[r7,#0x48]\n");\r
+ ot(" moveq r0,r2\n");\r
+ // PC\r
+ ot(";@ Push old PC onto stack\n");\r
+ ot(" ldr r1,[r7,#0x60] ;@ Get Memory base\n");\r
+ ot(" sub r0,r0,#4 ;@ Predecremented A7\n");\r
+ ot(" sub r1,r4,r1 ;@ r1 = Old PC\n");\r
+ ot(" str r0,[r7,#0x3c] ;@ Save A7\n");\r
+ MemHandler(1,2,0,EMULATE_HALT);\r
+ // SR\r
+ ot(";@ Push old SR:\n");\r
+ ot(" ldr r0,[r7,#0x4c] ;@ X bit\n");\r
+ ot(" mov r1,r10,ror #28 ;@ ____NZCV\n");\r
+ ot(" eor r2,r1,r1,ror #1 ;@ Bit 0=C^V\n");\r
+ ot(" tst r2,#1 ;@ 1 if C!=V\n");\r
+ ot(" eorne r1,r1,#3 ;@ ____NZVC\n");\r
+ ot(" and r0,r0,#0x20000000\n");\r
+ ot(" orr r1,r1,r0,lsr #25 ;@ ___XNZVC\n");\r
+ ot(" ldr r0,[r7,#0x3c] ;@ A7\n");\r
+ ot(" and r10,r10,#0xf0000000\n");\r
+ ot(" sub r0,r0,#2 ;@ Predecrement A7\n");\r
+ ot(" str r0,[r7,#0x3c] ;@ Save A7\n");\r
+ MemHandler(1,1,0,0);\r
+ // IR (instruction register)\r
+ ot(";@ Push IR:\n");\r
+ ot(" ldr r0,[r7,#0x3c] ;@ A7\n");\r
+ ot(" mov r1,r8\n");\r
+ ot(" sub r0,r0,#2 ;@ Predecrement A7\n");\r
+ ot(" str r0,[r7,#0x3c] ;@ Save A7\n");\r
+ MemHandler(1,1,0,0);\r
+ // access address\r
+ ot(";@ Push address:\n");\r
+ ot(" ldr r0,[r7,#0x3c] ;@ A7\n");\r
+ ot(" mov r1,r11\n");\r
+ ot(" sub r0,r0,#4 ;@ Predecrement A7\n");\r
+ ot(" str r0,[r7,#0x3c] ;@ Save A7\n");\r
+ MemHandler(1,2,0,0);\r
+ // information word\r
+ ot(";@ Push info word:\n");\r
+ ot(" ldr r0,[r7,#0x3c] ;@ A7\n");\r
+ ot(" mov r1,r6\n");\r
+ ot(" sub r0,r0,#2 ;@ Predecrement A7\n");\r
+ ot(" str r0,[r7,#0x3c] ;@ Save A7\n");\r
+ MemHandler(1,1,0,0);\r
+ ot("\n");\r
+\r
+ // 2. Obtain the exception vector\r
+ ot(";@ Read Exception Vector:\n");\r
+ ot(" mov r0,#0x0c\n");\r
+ MemHandler(0,2,0,0);\r
+ ot(" ldr r3,[r7,#0x60] ;@ Get Memory base\n");\r
+#if USE_CHECKPC_CALLBACK\r
+ ot(" add lr,pc,#4\n");\r
+ ot(" add r0,r0,r3 ;@ r0 = Memory Base + New PC\n");\r
+ #ifdef MEMHANDLERS_DIRECT_PREFIX\r
+ ot(" bl %scheckpc ;@ Call checkpc()\n", MEMHANDLERS_DIRECT_PREFIX);\r
+ #else\r
+ ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n");\r
+ #endif\r
+ ot(" mov r4,r0\n");\r
+#else\r
+ ot(" add r4,r0,r3 ;@ r4 = Memory Base + New PC\n");\r
+#endif\r
+ ot("\n");\r
+\r
+#if EMULATE_ADDRESS_ERRORS_JUMP && EMULATE_HALT\r
+ ot(" tst r4,#1\n");\r
+ ot(" bne ExceptionAddressError_r_prg_r4\n");\r
+#else\r
+ ot(" bic r4,r4,#1\n");\r
+#endif\r
+\r
+ // 4. Resume execution.\r
+ ot(" ldr r6,[r7,#0x54]\n");\r
+ ot(" ldrh r8,[r4],#2 ;@ Fetch next opcode\n");\r
+ ot(" subs r5,r5,#50 ;@ Subtract cycles\n");\r
+ ot(" ldrge pc,[r6,r8,asl #2] ;@ Jump to opcode handler\n");\r
+ ot(" b CycloneEnd\n");\r
+ ot("\n");\r
+#endif\r
+\r
+ // --------------\r
+#if EMULATE_TRACE\r
+ // expects srh and irq level in r1, next opcode already fetched to r8\r
+ ot("CycloneDoTraceWithChecks%s\n", ms?"":":");\r
+ ot(" ldr r0,[r7,#0x58]\n");\r
+ ot(" cmp r5,#0\n");\r
+ ot(" orr r0,r0,#2 ;@ go to trace mode\n");\r
+ ot(" str r0,[r7,#0x58]\n");\r
+ ot(" blt CycloneEnd\n"); // should take care of situation where we come here when already tracing\r
+ ot(";@ CheckInterrupt:\n");\r
+ ot(" movs r0,r1,lsr #24 ;@ Get IRQ level\n");\r
+ ot(" beq CycloneDoTrace\n");\r
+ ot(" cmp r0,#6 ;@ irq>6 ?\n");\r
+ ot(" andle r1,r1,#7 ;@ Get interrupt mask\n");\r
+ ot(" cmple r0,r1 ;@ irq<=6: Is irq<=mask ?\n");\r
+ ot(" bgt CycloneDoInterruptGoBack\n");\r
+ ot("\n");\r
+\r
+ // expects next opcode to be already fetched to r8\r
+ ot("CycloneDoTrace%s\n", ms?"":":");\r
+ ot(" str r5,[r7,#0x9c] ;@ save cycles\n");\r
+ ot(" ldr r1,[r7,#0x98]\n");\r
+ ot(" mov r5,#0\n");\r
+ ot(" str r1,[r7,#0xa0]\n");\r
+ ot(" adr r0,TraceEnd\n");\r
+ ot(" str r0,[r7,#0x98] ;@ store TraceEnd as CycloneEnd hadler\n");\r
+ ot(" ldr pc,[r6,r8,asl #2] ;@ Jump to opcode handler\n");\r
+ ot("\n");\r
+\r
+ ot("TraceEnd%s\n", ms?"":":");\r
+ ot(" ldr r2,[r7,#0x58]\n");\r
+ ot(" ldr r0,[r7,#0x9c] ;@ restore cycles\n");\r
+ ot(" ldr r1,[r7,#0xa0] ;@ old CycloneEnd handler\n");\r
+ ot(" mov r10,r10,lsl #28\n");\r
+ ot(" add r5,r0,r5\n");\r
+ ot(" str r1,[r7,#0x98]\n");\r
+ ot(";@ still tracing?\n"); // exception might have happend\r
+ ot(" tst r2,#2\n");\r
+ ot(" beq TraceDisabled\n");\r
+ ot(";@ trace exception\n");\r
+#if EMULATE_ADDRESS_ERRORS_JUMP || EMULATE_ADDRESS_ERRORS_IO\r
+ ot(" ldr r1,[r7,#0x58]\n");\r
+ ot(" mov r0,#9\n");\r
+ ot(" orr r1,r1,#4 ;@ set activity bit: 'not processing instruction'\n");\r
+ ot(" str r1,[r7,#0x58]\n");\r
+#else\r
+ ot(" mov r0,#9\n");\r
+#endif\r
+ ot(" bl Exception\n");\r
+ ot(" ldrh r8,[r4],#2 ;@ Fetch next opcode\n");\r
+ ot(" subs r5,r5,#34 ;@ Subtract cycles\n");\r
+ ot(" ldrge pc,[r6,r8,asl #2] ;@ Jump to opcode handler\n");\r
+ ot(" b CycloneEnd\n");\r
+ ot("\n");\r
+ ot("TraceDisabled%s\n", ms?"":":");\r
+ ot(" ldrh r8,[r4],#2 ;@ Fetch next opcode\n");\r
+ ot(" cmp r5,#0\n");\r
+ ot(" ldrge pc,[r6,r8,asl #2] ;@ Jump to opcode handler\n");\r
+ ot(" b CycloneEnd\n");\r
+ ot("\n");\r
+#endif\r