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
\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
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
\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
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
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
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
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
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
}\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
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
\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
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
// 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
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
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
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
// 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
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
\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
\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
}\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
}\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
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
// 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
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
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
\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
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
* 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
--- /dev/null
+#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;
+}
+