bugfixes, test_misc2, checkpc options
authornotaz <notasas@gmail.com>
Thu, 5 Jul 2007 20:25:06 +0000 (20:25 +0000)
committernotaz <notasas@gmail.com>
Thu, 5 Jul 2007 20:25:06 +0000 (20:25 +0000)
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@181 be3aeb3a-fb24-0410-a615-afba39da0efa

cpu/Cyclone/Cyclone.txt
cpu/Cyclone/Ea.cpp
cpu/Cyclone/OpArith.cpp
cpu/Cyclone/OpBranch.cpp
cpu/Cyclone/OpLogic.cpp
cpu/Cyclone/OpMove.cpp
cpu/Cyclone/config.h
cpu/Cyclone/tests/test_misc2_gen.c [new file with mode: 0644]

index 6e4749d..4858b18 100644 (file)
@@ -14,11 +14,11 @@ ___________________________________________________________________________
   Cyclone 68000 (c) Copyright 2004 Dave.   Free for non-commercial use\r
 \r
   Homepage: http://www.finalburn.com/\r
-  Dave's e-mail: dev(atsymbol)finalburn.com\r
+  Dave's e-mail: emudave(atsymbol)googlemail.com\r
   Replace (atsymbol) with @\r
 \r
-  Additional coding and bugfixes done by notaz, 2005, 2006\r
-  Homepage: http://mif.vu.lt/~grig2790/Cyclone/\r
+  Additional coding and bugfixes done by notaz, 2005-2007\r
+  Homepage: http://mif.vu.lt/~grig2790/Cyclone/ , http://notaz.gp2x.de\r
   e-mail: notasas(atsymbol)gmail.com\r
 ___________________________________________________________________________\r
 \r
@@ -35,6 +35,17 @@ Flags are mapped onto ARM flags whenever possible, which speeds up the processin
 \r
 What's New\r
 ----------\r
+v0.0087 notaz\r
+  - Reduced amount of code in opcode handlers by ~23% by doing the following:\r
+    - Removed duplicate opcode handlers\r
+    - Optimized code to use less ARM instructions\r
+    - Merged some duplicate handler endings\r
+  + Cyclone now does better job avoiding pipeline interlocks.\r
+  + Replaced incorrect handler of DBT with proper one.\r
+  + Fixed "MOVEA (An)+ An" behaviour.\r
+  + Fixed flags for ROXR and LSR. Hopefully got them right now.\r
+  + Additional functionality added for MAME and other ports (see config.h).\r
+\r
 v0.0086 notaz\r
   + Cyclone now can be customized to better suit your project, see config.h .\r
   + Added an option to compress the jumptable at compile-time. Must call CycloneInit()\r
index 8b103c9..35f0048 100644 (file)
@@ -98,11 +98,12 @@ static int EaCalcReg(int r,int ea,int mask,int forceor,int shift,int noshift=0)
   for (i=mask|0x8000; (i&1)==0; i>>=1) low++; // Find out how high up the EA mask is\r
   mask&=0xf<<low; // This is the max we can do\r
 \r
-  if (ea>=8) needor=1; // Need to OR to access A0-7\r
-\r
-  if (((mask&g_op)>>low)&8) needor=0; // Ah - no we don't actually need to or, since the bit is high in r8\r
-\r
-  if (forceor) needor=1; // Special case for 0x30-0x38 EAs ;)\r
+  if (ea>=8)\r
+  {\r
+    needor=1; // Need to OR to access A0-7\r
+    if ((g_op>>low)&8) { needor=0; mask|=8<<low; } // Ah - no we don't actually need to or, since the bit is high in r8\r
+    if (forceor) needor=1; // Special case for 0x30-0x38 EAs ;)\r
+  }\r
 \r
   ot("  and r%d,r8,#0x%.4x\n",r,mask);\r
   if (needor) ot("  orr r%d,r%d,#0x%x ;@ A0-7\n",r,r,8<<low);\r
index 8280a2b..fe3d40a 100644 (file)
@@ -25,20 +25,21 @@ int OpArith(int op)
 \r
   OpStart(op, sea, tea); Cycles=4;\r
 \r
-  EaCalcReadNoSE((type!=6)?11:-1,0,tea,size,0x003f);\r
+  // imm must be read first\r
   EaCalcReadNoSE(-1,10,sea,size,0);\r
+  EaCalcReadNoSE((type!=6)?11:-1,0,tea,size,0x003f);\r
 \r
   if (size<2) shiftstr=(char *)(size?",asl #16":",asl #24");\r
-  if (size<2) ot("  mov r0,r0,asl %i\n",size?16:24);\r
+  if (size<2) ot("  mov r10,r10,asl #%i\n",size?16:24);\r
 \r
   ot(";@ Do arithmetic:\n");\r
 \r
-  if (type==0) ot("  orr r1,r0,r10%s\n",shiftstr);\r
-  if (type==1) ot("  and r1,r0,r10%s\n",shiftstr);\r
-  if (type==2) ot("  subs r1,r0,r10%s ;@ Defines NZCV\n",shiftstr);\r
-  if (type==3) ot("  adds r1,r0,r10%s ;@ Defines NZCV\n",shiftstr);\r
-  if (type==5) ot("  eor r1,r0,r10%s\n",shiftstr);\r
-  if (type==6) ot("  cmp r0,r10%s ;@ Defines NZCV\n",shiftstr);\r
+  if (type==0) ot("  orr r1,r10,r0%s\n",shiftstr);\r
+  if (type==1) ot("  and r1,r10,r0%s\n",shiftstr);\r
+  if (type==2||type==6)\r
+               ot("  rsbs r1,r10,r0%s ;@ Defines NZCV\n",shiftstr);\r
+  if (type==3) ot("  adds r1,r10,r0%s ;@ Defines NZCV\n",shiftstr);\r
+  if (type==5) ot("  eor r1,r10,r0%s\n",shiftstr);\r
 \r
   if (type<2 || type==5) ot("  adds r1,r1,#0 ;@ Defines NZ, clears CV\n"); // 0,1,5\r
 \r
@@ -384,7 +385,7 @@ int OpAbcd(int op)
     ot(";@ Get src/dest EA vals\n");\r
     EaCalc (0,0x000f, sea,0,1);\r
     EaRead (0,    10, sea,0,0x000f,1);\r
-    EaCalcReadNoSE(11,0,dea,0,0x1e00);\r
+    EaCalcReadNoSE(11,0,dea,0,0x0e00);\r
   }\r
   else\r
   {\r
@@ -540,13 +541,11 @@ int OpAritha(int op)
   if(size==2&&(sea<0x10||sea==0x3c)) Cycles+=2;\r
   if(type==1) Cycles=6;\r
 \r
-  // must calculate reg EA first, because of situations like: suba.w (A0)+, A0\r
-  EaCalc (10,0x1e00, dea,2,1);\r
-  EaRead (10,    11, dea,2,0x1e00);\r
-\r
-  EaCalc ( 0,0x003f, sea,size,1);\r
-  EaRead ( 0,     0, sea,size,0x003f,1);\r
+  // to handle suba.w (A0)+, A0 properly, must calc reg EA first\r
+  EaCalcReadNoSE(type!=1?10:-1,11,dea,2,0x0e00);\r
+  EaCalcReadNoSE(-1,0,sea,size,0x003f);\r
 \r
+  if (size<2) ot("  mov r0,r0,asl #%d\n\n",size?16:24);\r
   if (size<2) asr=(char *)(size?",asr #16":",asr #24");\r
 \r
   if (type==0) ot("  sub r11,r11,r0%s\n",asr);\r
@@ -555,7 +554,7 @@ int OpAritha(int op)
   if (type==2) ot("  add r11,r11,r0%s\n",asr);\r
   ot("\n");\r
   \r
-  if (type!=1) EaWrite(10,    11, dea,2,0x0e00,1);\r
+  if (type!=1) EaWrite(10,    11, dea,2,0x0e00);\r
 \r
   OpEnd(sea);\r
 \r
@@ -596,7 +595,7 @@ int OpAddx(int op)
     ot(";@ Get src/dest EA vals\n");\r
     EaCalc (0,0x000f, sea,size,1);\r
     EaRead (0,    11, sea,size,0x000f,1);\r
-    EaCalcReadNoSE(10,0,dea,size,0x1e00);\r
+    EaCalcReadNoSE(10,0,dea,size,0x0e00);\r
   }\r
   else\r
   {\r
@@ -716,11 +715,11 @@ int OpCmpm(int op)
   OpStart(op,sea); Cycles=4;\r
 \r
   ot(";@ Get src operand into r10:\n");\r
-  EaCalc (0,0x1e00, sea,size,1);\r
-  EaRead (0,    10, sea,size,0x000f,1);\r
+  EaCalc (0,0x0007, sea,size,1);\r
+  EaRead (0,    10, sea,size,0x0007,1);\r
 \r
   ot(";@ Get dst operand into r0:\n");\r
-  EaCalcReadNoSE(-1,0,dea,size,0x1e00);\r
+  EaCalcReadNoSE(-1,0,dea,size,0x0e00);\r
 \r
   if (size<2) asl=(char *)(size?",asl #16":",asl #24");\r
 \r
index c24c769..5d132cf 100644 (file)
@@ -158,11 +158,12 @@ int OpUnlk(int op)
 }\r
 \r
 // --------------------- Opcodes 0x4e70+ ---------------------\r
+// 01001110 01110ttt\r
 int Op4E70(int op)\r
 {\r
   int type=0;\r
 \r
-  type=op&7; // 01001110 01110ttt, reset/nop/stop/rte/rtd/rts/trapv/rtr\r
+  type=op&7; // reset/nop/stop/rte/rtd/rts/trapv/rtr\r
 \r
   switch (type)\r
   {\r
@@ -236,7 +237,7 @@ int OpJsr(int op)
   ot(";@ Jump - Get new PC from r0\n");\r
   if (op&0x40)\r
   {\r
-    // Jmp - Get new PC from r0\r
+    // Jmp - Get new PC from r11\r
     ot("  add r0,r11,r10 ;@ Memory Base + New PC\n");\r
     ot("\n");\r
   }\r
@@ -319,14 +320,24 @@ int OpDbra(int op)
 \r
     ot(";@ Check if Dn.w is -1\n");\r
     ot("  cmn r0,#1\n");\r
+\r
+#if USE_CHECKPC_CALLBACK && USE_CHECKPC_DBRA\r
+    ot("  beq DbraMin1\n");\r
     ot("\n");\r
 \r
+    ot(";@ Get Branch offset:\n");\r
+    ot("  ldrsh r0,[r4]\n");\r
+    ot("  add r0,r4,r0 ;@ r4 = New PC\n");\r
+    CheckPc(0);\r
+#else\r
+    ot("\n");\r
     ot(";@ Get Branch offset:\n");\r
     ot("  ldrnesh r0,[r4]\n");\r
     ot("  addeq r4,r4,#2 ;@ Skip branch offset\n");\r
     ot("  subeq r5,r5,#4 ;@ additional cycles\n");\r
     ot("  addne r4,r4,r0 ;@ r4 = New PC\n");\r
     ot("\n");\r
+#endif\r
     Cycles=12-2;\r
     OpEnd();\r
   }\r
@@ -342,6 +353,18 @@ int OpDbra(int op)
     OpEnd();\r
   }\r
 \r
+#if USE_CHECKPC_CALLBACK && USE_CHECKPC_DBRA\r
+  if (op==0x51c8)\r
+  {\r
+    ot(";@ Dn.w is -1:\n");\r
+    ot("DbraMin1%s\n", ms?"":":");\r
+    ot("  add r4,r4,#2 ;@ Skip branch offset\n");\r
+    ot("\n");\r
+    Cycles=12+2;\r
+    OpEnd();\r
+  }\r
+#endif\r
+\r
   return 0;\r
 }\r
 \r
@@ -349,7 +372,7 @@ int OpDbra(int op)
 // Emit a Branch opcode 0110cccc nn  (cccc=condition)\r
 int OpBranch(int op)\r
 {\r
-  int size=0,use=0;\r
+  int size=0,use=0,checkpc=0;\r
   int offset=0;\r
   int cc=0;\r
   char *asr_r11="";\r
@@ -426,28 +449,26 @@ int OpBranch(int op)
     MemHandler(1,2);\r
     ot("\n");\r
     Cycles=18; // always 18\r
-    if (offset==0 || offset==-1)\r
-    {\r
-      ot(";@ Branch is quite far, so may be a good idea to check Memory Base+pc\n");\r
-      ot("  add r0,r4,r11%s ;@ r4 = New PC\n",asr_r11);\r
-      CheckPc(0);\r
-    }\r
-    else\r
-      ot("  add r4,r4,r11%s ;@ r4 = New PC\n",asr_r11);\r
+  }\r
+\r
+#if USE_CHECKPC_CALLBACK && USE_CHECKPC_OFFSETBITS_8\r
+  if (offset!=0 && offset!=-1) checkpc=1;\r
+#endif\r
+#if USE_CHECKPC_CALLBACK && USE_CHECKPC_OFFSETBITS_16\r
+  if (offset==0)  checkpc=1;\r
+#endif\r
+#if USE_CHECKPC_CALLBACK\r
+  if (offset==-1) checkpc=1;\r
+#endif\r
+  if (checkpc)\r
+  {\r
+    ot("  add r0,r4,r11%s ;@ r4 = New PC\n",asr_r11);\r
+    CheckPc(0);\r
   }\r
   else\r
   {\r
-    if (offset==0 || offset==-1)\r
-    {\r
-      ot("  add r0,r4,r11%s ;@ r4 = New PC\n",asr_r11);\r
-      ot(";@ Branch is quite far, so may be a good idea to check Memory Base+pc\n");\r
-      CheckPc(0);\r
-    }\r
-    else\r
-    {\r
-      ot("  add r4,r4,r11%s ;@ r4 = New PC\n",asr_r11);\r
-      ot("\n");\r
-    }\r
+    ot("  add r4,r4,r11%s ;@ r4 = New PC\n",asr_r11);\r
+    ot("\n");\r
   }\r
 \r
   OpEnd(size?0x10:0);\r
@@ -456,7 +477,7 @@ int OpBranch(int op)
   if (cc>=2&&(op&0xff00)==0x6200)\r
   {\r
     ot("BccDontBranch%i%s\n", 8<<size, ms?"":":");\r
-    if (size) ot("  add r4,r4,#%d\n",8<<size);\r
+    if (size) ot("  add r4,r4,#%d\n",1<<size);\r
     Cycles+=(size==1) ? 2 : -2; // Branch not taken\r
     OpEnd(0);\r
   }\r
index 3389a8e..7623704 100644 (file)
@@ -409,13 +409,6 @@ static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)
     if (type==0) ot("  movs r0,r0,%s %s\n",dir?"asl":"asr",pct);\r
     if (type==1) ot("  movs r0,r0,%s %s\n",dir?"lsl":"lsr",pct);\r
 \r
-    if (dir==0 && size<2)\r
-    {\r
-      ot(";@ restore after right shift:\n");\r
-      ot("  mov r0,r0,lsl #%d\n",32-(8<<size));\r
-      ot("\n");\r
-    }\r
-\r
     OpGetFlags(0,0);\r
     if (usereg) { // store X only if count is not 0\r
       ot("  cmp %s,#0 ;@ shifting by 0?\n",pct);\r
@@ -425,6 +418,16 @@ static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)
       // count will never be 0 if we use immediate\r
       ot("  str r9,[r7,#0x4c] ;@ Save X bit\n");\r
     }\r
+    ot("\n");\r
+\r
+    if (dir==0 && size<2)\r
+    {\r
+      ot(";@ restore after right shift:\n");\r
+      ot("  movs r0,r0,lsl #%d\n",32-(8<<size));\r
+      if (type)\r
+        ot("  orrmi r9,r9,#0x80000000 ;@ Potentially missed N flag\n");\r
+      ot("\n");\r
+    }\r
 \r
     if (type==0 && dir) {\r
       ot(";@ calculate V flag (set if sign bit changes at anytime):\n");\r
@@ -433,9 +436,8 @@ static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)
       ot("  cmpne r3,r1,asr %s\n", pct);\r
       ot("  biceq r9,r9,#0x10000000\n");\r
       ot("  orrne r9,r9,#0x10000000\n");\r
+      ot("\n");\r
     }\r
-\r
-    ot("\n");\r
   }\r
 \r
   // --------------------------------------\r
@@ -467,12 +469,20 @@ static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)
 \r
     if (usereg)\r
     {\r
-      ot(";@ Reduce r2 until <0:\n");\r
-      ot("Reduce_%.4x%s\n",op,ms?"":":");\r
-      ot("  subs r2,r2,#%d\n",wide+1);\r
-      ot("  bpl Reduce_%.4x\n",op);\r
-      ot("  adds r2,r2,#%d ;@ Now r2=0-%d\n",wide+1,wide);\r
-      ot("  beq norotx%.4x\n",op);\r
+      if (size==2)\r
+      {\r
+        ot("  subs r2,r2,#33\n");\r
+        ot("  addmis r2,r2,#33 ;@ Now r2=0-%d\n",wide);\r
+      }\r
+      else\r
+      {\r
+        ot(";@ Reduce r2 until <0:\n");\r
+        ot("Reduce_%.4x%s\n",op,ms?"":":");\r
+        ot("  subs r2,r2,#%d\n",wide+1);\r
+        ot("  bpl Reduce_%.4x\n",op);\r
+        ot("  adds r2,r2,#%d ;@ Now r2=0-%d\n",wide+1,wide);\r
+      }\r
+      ot("  beq norotx_%.4x\n",op);\r
       ot("\n");\r
     }\r
 \r
@@ -488,30 +498,26 @@ static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)
 \r
     if (shift) ot("  mov r0,r0,lsr #%d ;@ Shift down\n",shift);\r
 \r
-    ot(";@ Rotate bits:\n");\r
-    ot("  mov r3,r0,lsr r2 ;@ Get right part\n");\r
-    ot("  rsbs r2,r2,#%d ;@ should also clear ARM V\n",wide+1);\r
-    ot("  movs r0,r0,lsl r2 ;@ Get left part\n");\r
-    ot("  orr r0,r3,r0 ;@ r0=Rotated value\n");\r
-\r
-    ot(";@ Insert X bit into r2-1:\n");\r
+    ot("\n");\r
+    ot(";@ First get X bit (middle):\n");\r
     ot("  ldr r3,[r7,#0x4c]\n");\r
-    ot("  sub r2,r2,#1\n");\r
+    ot("  rsb r1,r2,#%d\n",wide);\r
     ot("  and r3,r3,#0x20000000\n");\r
     ot("  mov r3,r3,lsr #29\n");\r
-    ot("  orr r0,r0,r3,lsl r2\n");\r
+    ot("  mov r3,r3,lsl r1\n");\r
+\r
+    ot(";@ Rotate bits:\n");\r
+    ot("  orr r3,r3,r0,lsr r2 ;@ Orr right part\n");\r
+    ot("  rsbs r2,r2,#%d ;@ should also clear ARM V\n",wide+1);\r
+    ot("  orrs r0,r3,r0,lsl r2 ;@ Orr left part, set flags\n");\r
     ot("\n");\r
 \r
     if (shift) ot("  movs r0,r0,lsl #%d ;@ Shift up and get correct NC flags\n",shift);\r
     OpGetFlags(0,!usereg);\r
-    if (!shift) {\r
-      ot("  tst r0,r0\n");\r
-      ot("  bicne r9,r9,#0x40000000 ;@ make sure we didn't mess Z\n");\r
-    }\r
     if (usereg) { // store X only if count is not 0\r
       ot("  str r9,[r7,#0x4c] ;@ if not 0, Save X bit\n");\r
       ot("  b nozerox%.4x\n",op);\r
-      ot("norotx%.4x%s\n",op,ms?"":":");\r
+      ot("norotx_%.4x%s\n",op,ms?"":":");\r
       ot("  ldr r2,[r7,#0x4c]\n");\r
       ot("  adds r0,r0,#0 ;@ Defines NZ, clears CV\n");\r
       OpGetFlags(0,0);\r
@@ -536,9 +542,10 @@ static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)
     }\r
 \r
     ot(";@ Rotate register:\n");\r
+    if (!dir) ot("  adds r0,r0,#0 ;@ first clear V and C\n"); // ARM does not clear C if rot count is 0\r
     if (count<0)\r
     {\r
-      if (dir) ot("  rsbs %s,%s,#32\n",pct,pct);\r
+      if (dir) ot("  rsb %s,%s,#32\n",pct,pct);\r
       ot("  movs r0,r0,ror %s\n",pct);\r
     }\r
     else\r
@@ -549,9 +556,9 @@ static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)
     }\r
 \r
     OpGetFlags(0,0);\r
-    if (!dir) ot("  bic r9,r9,#0x10000000 ;@ make suve V is clear\n");\r
     if (dir)\r
     {\r
+      ot("  bic r9,r9,#0x30000000 ;@ clear CV\n");\r
       ot(";@ Get carry bit from bit 0:\n");\r
       if (usereg)\r
       {\r
@@ -561,14 +568,6 @@ static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)
       else\r
         ot("  tst r0,#1\n");\r
       ot("  orrne r9,r9,#0x20000000\n");\r
-      ot("  biceq r9,r9,#0x20000000\n");\r
-    }\r
-    else if (usereg)\r
-    {\r
-      // if we rotate something by 0, ARM doesn't clear C\r
-      // so we need to detect that\r
-      ot("  cmp %s,#0\n",pct);\r
-      ot("  biceq r9,r9,#0x20000000\n");\r
     }\r
     ot("\n");\r
 \r
@@ -599,7 +598,7 @@ int OpAsr(int op)
   // Use the same opcode for target registers:\r
   use=op&~0x0007;\r
 \r
-  // As long as count is not 8, use the same opcode for all shift counts::\r
+  // As long as count is not 8, use the same opcode for all shift counts:\r
   if (usereg==0 && count!=8 && !(count==1&&type==2)) { use|=0x0e00; count=-1; }\r
   if (usereg) { use&=~0x0e00; count=-1; } // Use same opcode for all Dn\r
 \r
index c0e436c..1d7165b 100644 (file)
@@ -133,18 +133,18 @@ int OpMove(int op)
   if (movea) size=2; // movea always expands to 32-bits\r
 \r
 #if SPLIT_MOVEL_PD\r
-  EaCalc (10,0x1e00,tea,size,0,0);\r
+  EaCalc (10,0x0e00,tea,size,0,0);\r
   if ((tea&0x38)==0x20 && size==2) { // -(An)\r
     ot("  mov r11,r1\n");\r
     ot("  add r0,r10,#2\n");\r
-    EaWrite(0,     1,tea,1,0x1e00,0,0);\r
-    EaWrite(10,   11,tea,1,0x1e00,1);\r
+    EaWrite(0,     1,tea,1,0x0e00,0,0);\r
+    EaWrite(10,   11,tea,1,0x0e00,1);\r
   } else {\r
-    EaWrite(0,     1,tea,size,0x1e00,0,0);\r
+    EaWrite(0,     1,tea,size,0x0e00,0,0);\r
   }\r
 #else\r
-  EaCalc (0,0x1e00,tea,size,0,0);\r
-  EaWrite(0,     1,tea,size,0x1e00,0,0);\r
+  EaCalc (0,0x0e00,tea,size,0,0);\r
+  EaWrite(0,     1,tea,size,0x0e00,0,0);\r
 #endif\r
 \r
 #if CYCLONE_FOR_GENESIS && !MEMHANDLERS_CHANGE_CYCLES\r
@@ -178,8 +178,8 @@ int OpLea(int op)
   OpStart(op,sea,tea);\r
 \r
   EaCalc (1,0x003f,sea,0); // Lea\r
-  EaCalc (0,0x1e00,tea,2);\r
-  EaWrite(0,     1,tea,2,0x1e00);\r
+  EaCalc (0,0x0e00,tea,2);\r
+  EaWrite(0,     1,tea,2,0x0e00);\r
 \r
   Cycles=Ea_add_ns(g_lea_cycle_table,sea);\r
 \r
@@ -513,7 +513,7 @@ int OpMovep(int op)
 \r
   // Get EA\r
   ea = (op&0x0007)|0x28;\r
-  rea=  op&0x0e00;\r
+  rea= (op&0x0e00)>>9;\r
   dir = (op>>7)&1;\r
 \r
   // Find size extension\r
@@ -522,7 +522,7 @@ int OpMovep(int op)
   OpStart(op,ea);\r
   \r
   if(dir) { // reg to mem\r
-    EaCalcReadNoSE(-1,11,rea,size,0x1e00);\r
+    EaCalcReadNoSE(-1,11,rea,size,0x0e00);\r
 \r
     EaCalc(10,0x000f,ea,size);\r
     if(size==2) { // if operand is long\r
index b10ee42..3af4103 100644 (file)
@@ -27,7 +27,7 @@
  * Warning: if you enable this, you MUST call CycloneInit() before calling\r
  * CycloneRun(), or else it will crash.\r
  */\r
-#define COMPRESS_JUMPTABLE        1\r
+#define COMPRESS_JUMPTABLE        0\r
 \r
 /*\r
  * Address mask for memory hadlers. The bits set will be masked out of address\r
  */\r
 #define USE_CHECKPC_CALLBACK      1\r
 \r
+/*\r
+ * This determines if checkpc() should be called after jumps when 8 and 16 bit\r
+ * displacement values were used.\r
+ */\r
+#define USE_CHECKPC_OFFSETBITS_16 1\r
+#define USE_CHECKPC_OFFSETBITS_8  0\r
+\r
+/*\r
+ * Call checkpc() after DBcc jumps (which use 16bit displacement). Cyclone prior to\r
+ * 0.0087 never did that.\r
+ */\r
+#define USE_CHECKPC_DBRA          0\r
+\r
 /*\r
  * When this option is enabled Cyclone will do two word writes instead of one\r
  * long write when handling MOVE.L with pre-decrementing destination, as described in\r
  * Bart Trzynadlowski's doc (http://www.trzy.org/files/68knotes.txt).\r
  * Enable this if you are emulating a 16 bit system.\r
  */\r
-#define SPLIT_MOVEL_PD            1\r
+#define SPLIT_MOVEL_PD            0\r
diff --git a/cpu/Cyclone/tests/test_misc2_gen.c b/cpu/Cyclone/tests/test_misc2_gen.c
new file mode 100644 (file)
index 0000000..8341ea4
--- /dev/null
@@ -0,0 +1,120 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+static FILE *f;
+
+#define bswap16(x) (x=(unsigned short)((x<<8)|(x>>8)))
+#define bswap32(x) (x=((x<<24)|((x<<8)&0xff0000)|((x>>8)&0x00ff00)|((unsigned)x>>24)))
+
+static void write_op(unsigned short op, unsigned short word0, unsigned short word1, unsigned short word2)
+{
+       bswap16(op);
+       bswap16(word0);
+       bswap16(word1);
+       bswap16(word2);
+
+       fwrite(&op,    1, sizeof(op), f);
+       fwrite(&word0, 1, sizeof(word0), f);
+       fwrite(&word1, 1, sizeof(word1), f);
+       fwrite(&word2, 1, sizeof(word2), f);
+}
+
+static void write32(unsigned int a)
+{
+       bswap32(a);
+       fwrite(&a,     1, sizeof(a),  f);
+}
+
+static int op_check(unsigned short op)
+{
+       if ((op&0xf000) == 0x6000) return 0; // Bxx
+       if ((op&0xf0f8) == 0x50c8) return 0; // DBxx
+       if ((op&0xff80) == 0x4e80) return 0; // Jsr
+       if ((op&0xf000) == 0xa000) return 0; // a-line
+       if ((op&0xf000) == 0xf000) return 0; // f-line
+       if ((op&0xfff8)==0x4e70&&op!=0x4e71&&op!=0x4e76) return 0; // reset, rte, rts
+
+       if ((op&0x3f) >= 0x28) op = (op&~0x3f) | (rand() % 0x28);
+       return 1;
+}
+
+static unsigned short safe_rand(void)
+{
+       unsigned short op;
+
+       /* avoid branch opcodes */
+       do
+       {
+               op = rand();
+       }
+       while (!op_check(op));
+
+       return op;
+}
+
+int main()
+{
+       int i, op;
+
+       srand(time(0));
+
+       f = fopen("test_misc2.bin", "wb");
+       if (!f) return 1;
+
+       write32(0x00ff8000); // stack
+       write32(0x300); // IP
+
+       for (i=0x100/4-2; i; i--)
+       {
+               write32(0x200+i*4); // exception vectors
+       }
+
+       for (i=0x100/4; i; i--)
+       {
+               write32(0); // pad
+       }
+
+       for (i=0x100/4; i; i--)
+       {
+               write32(0x4e734e73); // fill with rte instructions
+       }
+
+       for (op = 0; op < 0x10000; op++)
+       {
+               if ((op&0xf000) == 0x6000) // Bxx
+               {
+                       if ((op&0x00ff) == 0)
+                               write_op(op, 6, 0, 0);
+                       else if ((op&0x00ff) == 0xff)
+                               write_op(op, 0, 6, 0);
+               }
+               else if ((op&0xf0f8)==0x50c8) // DBxx
+               {
+                       write_op(op, 6, 0, 0);
+               }
+               else if ((op&0xff80)==0x4e80) // Jsr
+               {
+                       int addr = 0x300 + i*8 + 8;
+                       if ((op&0x3f) == 0x39)
+                               write_op(op, addr >> 16, addr & 0xffff, 0);
+               }
+               else if ((op&0xf000)==0xa000 || (op&0xf000)==0xf000) // a-line, f-line
+               {
+                       if (op != 0xa000 && op != 0xf000) continue;
+               }
+               else if ((op&0xfff8)==0x4e70&&op!=0x4e71&&op!=0x4e76); // rte, rts, stop, reset
+               else
+               {
+                       write_op(op, safe_rand(), safe_rand(), safe_rand());
+               }
+       }
+
+       // jump to the beginning
+       write_op(0x4ef8, 0x300, 0, 0);
+
+       fclose(f);
+       return 0;
+}
+