0.0088 release
[picodrive.git] / cpu / Cyclone / OpMove.cpp
index 64c0f59..b5dc0ce 100644 (file)
@@ -21,7 +21,7 @@ void OpFlagsToReg(int high)
 \r
 // Convert SR/CRR register in r0 to our flags\r
 // trashes r0,r1\r
-void OpRegToFlags(int high)\r
+void OpRegToFlags(int high, int srh_reg)\r
 {\r
   ot("  eor r1,r0,r0,ror #1 ;@ Bit 0=C^V\n");\r
   ot("  mov r2,r0,lsl #25\n");\r
@@ -32,9 +32,10 @@ void OpRegToFlags(int high)
 \r
   if (high)\r
   {\r
-    ot("  mov r0,r0,ror #8\n");\r
-    ot("  and r0,r0,#0xa7 ;@ only take defined bits\n");\r
-    ot("  strb r0,[r7,#0x44] ;@ Store SR high\n");\r
+    int mask=EMULATE_TRACE?0xa7:0x27;\r
+    ot("  mov r%i,r0,ror #8\n",srh_reg);\r
+    ot("  and r%i,r%i,#0x%02x ;@ only take defined bits\n",srh_reg,srh_reg,mask);\r
+    ot("  strb r%i,[r7,#0x44] ;@ Store SR high\n",srh_reg);\r
   }\r
   ot("\n");\r
 }\r
@@ -44,8 +45,15 @@ void SuperEnd(void)
   ot(";@ ----------\n");\r
   ot(";@ tried execute privileged instruction in user mode\n");\r
   ot("WrongPrivilegeMode%s\n",ms?"":":");\r
+#if EMULATE_ADDRESS_ERRORS_JUMP || EMULATE_ADDRESS_ERRORS_IO\r
+  ot("  ldr r1,[r7,#0x58]\n");\r
   ot("  sub r4,r4,#2 ;@ last opcode wasn't executed - go back\n");\r
-  ot("  mov r0,#0x20 ;@ privilege violation\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("  sub r4,r4,#2 ;@ last opcode wasn't executed - go back\n");\r
+#endif\r
+  ot("  mov r0,#8 ;@ privilege violation\n");\r
   ot("  bl Exception\n");\r
   Cycles=34;\r
   OpEnd(0);\r
@@ -53,13 +61,15 @@ void SuperEnd(void)
 \r
 // does OSP and A7 swapping if needed\r
 // new or old SR (not the one already in [r7,#0x44]) should be passed in r11\r
-// trashes r0,r11\r
-void SuperChange(int op,int load_srh)\r
+// uses srh from srh_reg (loads if < 0), trashes r0,r11\r
+void SuperChange(int op,int srh_reg)\r
 {\r
   ot(";@ A7 <-> OSP?\n");\r
-  if (load_srh)\r
+  if (srh_reg < 0) {\r
     ot("  ldr r0,[r7,#0x44] ;@ Get other SR high\n");\r
-  ot("  eor r0,r0,r11\n");\r
+    srh_reg=0;\r
+  }\r
+  ot("  eor r0,r%i,r11\n",srh_reg);\r
   ot("  tst r0,#0x20\n");\r
   ot("  beq no_sp_swap%.4x\n",op);\r
   ot(" ;@ swap OSP and A7:\n");\r
@@ -122,6 +132,7 @@ int OpMove(int op)
 \r
   if (movea) size=2; // movea always expands to 32-bits\r
 \r
+  eawrite_check_addrerr=1;\r
 #if SPLIT_MOVEL_PD\r
   if ((tea&0x38)==0x20 && size==2) { // -(An)\r
     EaCalc (10,0x0e00,tea,size,0,0);\r
@@ -167,6 +178,7 @@ int OpLea(int op)
 \r
   OpStart(op,sea,tea);\r
 \r
+  eawrite_check_addrerr=1;\r
   EaCalc (1,0x003f,sea,0); // Lea\r
   EaCalc (0,0x0e00,tea,2);\r
   EaWrite(0,     1,tea,2,0x0e00);\r
@@ -214,6 +226,7 @@ int OpMoveSr(int op)
 \r
   if (type==0 || type==1)\r
   {\r
+    eawrite_check_addrerr=1;\r
     OpFlagsToReg(type==0);\r
     EaCalc (0,0x003f,ea,size,0,0);\r
     EaWrite(0,     1,ea,size,0x003f,0,0);\r
@@ -222,13 +235,17 @@ int OpMoveSr(int op)
   if (type==2 || type==3)\r
   {\r
     EaCalcReadNoSE(-1,0,ea,size,0x003f);\r
-    OpRegToFlags(type==3);\r
+    OpRegToFlags(type==3,1);\r
     if (type==3) {\r
-      SuperChange(op,0);\r
+      SuperChange(op,1);\r
+      opend_check_interrupt = 1;\r
+      opend_check_trace = 1;\r
+      OpEnd(ea);\r
+      return 0;\r
     }\r
   }\r
 \r
-  OpEnd(ea,0,0,type==3);\r
+  OpEnd(ea);\r
 \r
   return 0;\r
 }\r
@@ -239,6 +256,7 @@ int OpArithSr(int op)
 {\r
   int type=0,ea=0;\r
   int use=0,size=0;\r
+  int sr_mask=EMULATE_TRACE?0xa7:0x27;\r
 \r
   type=(op>>9)&5; if (type==4) return 1;\r
   size=(op>>6)&1; // ccr or sr?\r
@@ -249,19 +267,53 @@ int OpArithSr(int op)
 \r
   OpStart(op,ea,0,0,size!=0); Cycles=16;\r
 \r
-  EaCalc(10,0x003f,ea,size);\r
-  EaRead(10,    10,ea,size,0x003f);\r
+  EaCalcRead(-1,0,ea,size,0x003f);\r
 \r
-  OpFlagsToReg(size);\r
-  if (type==0) ot("  orr r0,r1,r10\n");\r
-  if (type==1) ot("  and r0,r1,r10\n");\r
-  if (type==5) ot("  eor r0,r1,r10\n");\r
-  OpRegToFlags(size);\r
-  if (size && type!=0) { // we can't enter supervisor mode, nor unmask irqs just by using OR\r
-    SuperChange(op,0);\r
+  ot("  eor r1,r0,r0,ror #1 ;@ Bit 0=C^V\n");\r
+  ot("  tst r1,#1           ;@ 1 if C!=V\n");\r
+  ot("  eorne r0,r0,#3      ;@ ___XNZCV\n");\r
+  ot("  ldr r2,[r7,#0x4c]   ;@ Load old X bit\n");\r
+\r
+  // note: old srh is already in r11 (done by OpStart)\r
+  if (type==0) {\r
+    ot("  orr r9,r9,r0,lsl #28\n");\r
+    ot("  orr r2,r2,r0,lsl #25 ;@ X bit\n");\r
+    if (size!=0) {\r
+      ot("  orr r1,r11,r0,lsr #8\n");\r
+      ot("  and r1,r1,#0x%02x ;@ mask-out unused bits\n",sr_mask);\r
+    }\r
+  }\r
+  if (type==1) {\r
+    ot("  and r9,r9,r0,lsl #28\n");\r
+    ot("  and r2,r2,r0,lsl #25 ;@ X bit\n");\r
+    if (size!=0)\r
+      ot("  and r1,r11,r0,lsr #8\n");\r
+  }\r
+  if (type==5) {\r
+    ot("  eor r9,r9,r0,lsl #28\n");\r
+    ot("  eor r2,r2,r0,lsl #25 ;@ X bit\n");\r
+    if (size!=0) {\r
+      ot("  eor r1,r11,r0,lsr #8\n");\r
+      ot("  and r1,r1,#0x%02x ;@ mask-out unused bits\n",sr_mask);\r
+    }\r
   }\r
 \r
-  OpEnd(ea,0,0,size!=0 && type!=0);\r
+  ot("  str r2,[r7,#0x4c]   ;@ Save X bit\n");\r
+  if (size!=0)\r
+    ot("  strb r1,[r7,#0x44]\n");\r
+  ot("\n");\r
+\r
+  // we can't enter supervisor mode, nor unmask irqs just by using OR\r
+  if (size!=0 && type!=0) {\r
+    SuperChange(op,1);\r
+    ot("\n");\r
+    opend_check_interrupt = 1;\r
+  }\r
+  // also can't set trace bit with AND\r
+  if (size!=0 && type!=1)\r
+    opend_check_trace = 1;\r
+\r
+  OpEnd(ea);\r
 \r
   return 0;\r
 }\r
@@ -338,6 +390,13 @@ int OpMovem(int op)
   ot("  tst r11,r11\n");        // sanity check\r
   ot("  beq NoRegs%.4x\n",op);\r
 \r
+#if EMULATE_ADDRESS_ERRORS_IO\r
+  ot("\n");\r
+  ot("  tst r6,#1 ;@ address error?\n");\r
+  ot("  movne r0,r6\n");\r
+  ot("  bne ExceptionAddressError_%c_data\n",dir?'r':'w');\r
+#endif\r
+\r
   ot("\n");\r
   ot("Movemloop%.4x%s\n",op, ms?"":":");\r
   ot("  add r10,r10,#%d ;@ r10=Next Register\n",decr?-4:4);\r
@@ -350,6 +409,7 @@ int OpMovem(int op)
   if (dir)\r
   {\r
     ot("  ;@ Copy memory to register:\n",1<<size);\r
+    earead_check_addrerr=0; // already checked\r
     EaRead (6,0,ea,size,0x003f);\r
     ot("  str r0,[r7,r10] ;@ Save value into Dn/An\n");\r
   }\r
@@ -391,7 +451,8 @@ int OpMovem(int op)
 \r
   Cycles+=Ea_add_ns(g_movem_cycle_table,ea);\r
 \r
-  OpEnd(ea,0,1);\r
+  opend_op_changes_cycles = 1;\r
+  OpEnd(ea);\r
   ltorg();\r
   ot("\n");\r
 \r
@@ -413,6 +474,7 @@ int OpMoveUsp(int op)
 \r
   if (dir)\r
   {\r
+    eawrite_check_addrerr=1;\r
     ot("  ldr r1,[r7,#0x48] ;@ Get from USP\n\n");\r
     EaCalc (0,0x000f,8,2,1);\r
     EaWrite(0,     1,8,2,0x000f,1);\r
@@ -568,11 +630,12 @@ int OpStopReset(int op)
 \r
     ot("\n");\r
 \r
-    ot("  mov r0,#1\n");\r
-    ot("  str r0,[r7,#0x58] ;@ stopped\n");\r
+    ot("  ldr r0,[r7,#0x58]\n");\r
+    ot("  mov r5,#0 ;@ eat cycles\n");\r
+    ot("  orr r0,r0,#1 ;@ stopped\n");\r
+    ot("  str r0,[r7,#0x58]\n");\r
     ot("\n");\r
 \r
-    ot("  mov r5,#0 ;@ eat cycles\n");\r
     Cycles = 4;\r
     ot("\n");\r
   }\r