mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00
bugfixes, test_misc2, checkpc options
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@181 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
parent
85a36a57a8
commit
03c5768cb5
8 changed files with 267 additions and 103 deletions
|
@ -14,11 +14,11 @@ ___________________________________________________________________________
|
|||
Cyclone 68000 (c) Copyright 2004 Dave. Free for non-commercial use
|
||||
|
||||
Homepage: http://www.finalburn.com/
|
||||
Dave's e-mail: dev(atsymbol)finalburn.com
|
||||
Dave's e-mail: emudave(atsymbol)googlemail.com
|
||||
Replace (atsymbol) with @
|
||||
|
||||
Additional coding and bugfixes done by notaz, 2005, 2006
|
||||
Homepage: http://mif.vu.lt/~grig2790/Cyclone/
|
||||
Additional coding and bugfixes done by notaz, 2005-2007
|
||||
Homepage: http://mif.vu.lt/~grig2790/Cyclone/ , http://notaz.gp2x.de
|
||||
e-mail: notasas(atsymbol)gmail.com
|
||||
___________________________________________________________________________
|
||||
|
||||
|
@ -35,6 +35,17 @@ Flags are mapped onto ARM flags whenever possible, which speeds up the processin
|
|||
|
||||
What's New
|
||||
----------
|
||||
v0.0087 notaz
|
||||
- Reduced amount of code in opcode handlers by ~23% by doing the following:
|
||||
- Removed duplicate opcode handlers
|
||||
- Optimized code to use less ARM instructions
|
||||
- Merged some duplicate handler endings
|
||||
+ Cyclone now does better job avoiding pipeline interlocks.
|
||||
+ Replaced incorrect handler of DBT with proper one.
|
||||
+ Fixed "MOVEA (An)+ An" behaviour.
|
||||
+ Fixed flags for ROXR and LSR. Hopefully got them right now.
|
||||
+ Additional functionality added for MAME and other ports (see config.h).
|
||||
|
||||
v0.0086 notaz
|
||||
+ Cyclone now can be customized to better suit your project, see config.h .
|
||||
+ Added an option to compress the jumptable at compile-time. Must call CycloneInit()
|
||||
|
|
|
@ -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
|
||||
mask&=0xf<<low; // This is the max we can do
|
||||
|
||||
if (ea>=8) needor=1; // Need to OR to access A0-7
|
||||
|
||||
if (((mask&g_op)>>low)&8) needor=0; // Ah - no we don't actually need to or, since the bit is high in r8
|
||||
|
||||
if (forceor) needor=1; // Special case for 0x30-0x38 EAs ;)
|
||||
if (ea>=8)
|
||||
{
|
||||
needor=1; // Need to OR to access A0-7
|
||||
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
|
||||
if (forceor) needor=1; // Special case for 0x30-0x38 EAs ;)
|
||||
}
|
||||
|
||||
ot(" and r%d,r8,#0x%.4x\n",r,mask);
|
||||
if (needor) ot(" orr r%d,r%d,#0x%x ;@ A0-7\n",r,r,8<<low);
|
||||
|
|
|
@ -25,20 +25,21 @@ int OpArith(int op)
|
|||
|
||||
OpStart(op, sea, tea); Cycles=4;
|
||||
|
||||
EaCalcReadNoSE((type!=6)?11:-1,0,tea,size,0x003f);
|
||||
// imm must be read first
|
||||
EaCalcReadNoSE(-1,10,sea,size,0);
|
||||
EaCalcReadNoSE((type!=6)?11:-1,0,tea,size,0x003f);
|
||||
|
||||
if (size<2) shiftstr=(char *)(size?",asl #16":",asl #24");
|
||||
if (size<2) ot(" mov r0,r0,asl %i\n",size?16:24);
|
||||
if (size<2) ot(" mov r10,r10,asl #%i\n",size?16:24);
|
||||
|
||||
ot(";@ Do arithmetic:\n");
|
||||
|
||||
if (type==0) ot(" orr r1,r0,r10%s\n",shiftstr);
|
||||
if (type==1) ot(" and r1,r0,r10%s\n",shiftstr);
|
||||
if (type==2) ot(" subs r1,r0,r10%s ;@ Defines NZCV\n",shiftstr);
|
||||
if (type==3) ot(" adds r1,r0,r10%s ;@ Defines NZCV\n",shiftstr);
|
||||
if (type==5) ot(" eor r1,r0,r10%s\n",shiftstr);
|
||||
if (type==6) ot(" cmp r0,r10%s ;@ Defines NZCV\n",shiftstr);
|
||||
if (type==0) ot(" orr r1,r10,r0%s\n",shiftstr);
|
||||
if (type==1) ot(" and r1,r10,r0%s\n",shiftstr);
|
||||
if (type==2||type==6)
|
||||
ot(" rsbs r1,r10,r0%s ;@ Defines NZCV\n",shiftstr);
|
||||
if (type==3) ot(" adds r1,r10,r0%s ;@ Defines NZCV\n",shiftstr);
|
||||
if (type==5) ot(" eor r1,r10,r0%s\n",shiftstr);
|
||||
|
||||
if (type<2 || type==5) ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n"); // 0,1,5
|
||||
|
||||
|
@ -384,7 +385,7 @@ int OpAbcd(int op)
|
|||
ot(";@ Get src/dest EA vals\n");
|
||||
EaCalc (0,0x000f, sea,0,1);
|
||||
EaRead (0, 10, sea,0,0x000f,1);
|
||||
EaCalcReadNoSE(11,0,dea,0,0x1e00);
|
||||
EaCalcReadNoSE(11,0,dea,0,0x0e00);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -540,13 +541,11 @@ int OpAritha(int op)
|
|||
if(size==2&&(sea<0x10||sea==0x3c)) Cycles+=2;
|
||||
if(type==1) Cycles=6;
|
||||
|
||||
// must calculate reg EA first, because of situations like: suba.w (A0)+, A0
|
||||
EaCalc (10,0x1e00, dea,2,1);
|
||||
EaRead (10, 11, dea,2,0x1e00);
|
||||
|
||||
EaCalc ( 0,0x003f, sea,size,1);
|
||||
EaRead ( 0, 0, sea,size,0x003f,1);
|
||||
// to handle suba.w (A0)+, A0 properly, must calc reg EA first
|
||||
EaCalcReadNoSE(type!=1?10:-1,11,dea,2,0x0e00);
|
||||
EaCalcReadNoSE(-1,0,sea,size,0x003f);
|
||||
|
||||
if (size<2) ot(" mov r0,r0,asl #%d\n\n",size?16:24);
|
||||
if (size<2) asr=(char *)(size?",asr #16":",asr #24");
|
||||
|
||||
if (type==0) ot(" sub r11,r11,r0%s\n",asr);
|
||||
|
@ -555,7 +554,7 @@ int OpAritha(int op)
|
|||
if (type==2) ot(" add r11,r11,r0%s\n",asr);
|
||||
ot("\n");
|
||||
|
||||
if (type!=1) EaWrite(10, 11, dea,2,0x0e00,1);
|
||||
if (type!=1) EaWrite(10, 11, dea,2,0x0e00);
|
||||
|
||||
OpEnd(sea);
|
||||
|
||||
|
@ -596,7 +595,7 @@ int OpAddx(int op)
|
|||
ot(";@ Get src/dest EA vals\n");
|
||||
EaCalc (0,0x000f, sea,size,1);
|
||||
EaRead (0, 11, sea,size,0x000f,1);
|
||||
EaCalcReadNoSE(10,0,dea,size,0x1e00);
|
||||
EaCalcReadNoSE(10,0,dea,size,0x0e00);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -716,11 +715,11 @@ int OpCmpm(int op)
|
|||
OpStart(op,sea); Cycles=4;
|
||||
|
||||
ot(";@ Get src operand into r10:\n");
|
||||
EaCalc (0,0x1e00, sea,size,1);
|
||||
EaRead (0, 10, sea,size,0x000f,1);
|
||||
EaCalc (0,0x0007, sea,size,1);
|
||||
EaRead (0, 10, sea,size,0x0007,1);
|
||||
|
||||
ot(";@ Get dst operand into r0:\n");
|
||||
EaCalcReadNoSE(-1,0,dea,size,0x1e00);
|
||||
EaCalcReadNoSE(-1,0,dea,size,0x0e00);
|
||||
|
||||
if (size<2) asl=(char *)(size?",asl #16":",asl #24");
|
||||
|
||||
|
|
|
@ -158,11 +158,12 @@ int OpUnlk(int op)
|
|||
}
|
||||
|
||||
// --------------------- Opcodes 0x4e70+ ---------------------
|
||||
// 01001110 01110ttt
|
||||
int Op4E70(int op)
|
||||
{
|
||||
int type=0;
|
||||
|
||||
type=op&7; // 01001110 01110ttt, reset/nop/stop/rte/rtd/rts/trapv/rtr
|
||||
type=op&7; // reset/nop/stop/rte/rtd/rts/trapv/rtr
|
||||
|
||||
switch (type)
|
||||
{
|
||||
|
@ -236,7 +237,7 @@ int OpJsr(int op)
|
|||
ot(";@ Jump - Get new PC from r0\n");
|
||||
if (op&0x40)
|
||||
{
|
||||
// Jmp - Get new PC from r0
|
||||
// Jmp - Get new PC from r11
|
||||
ot(" add r0,r11,r10 ;@ Memory Base + New PC\n");
|
||||
ot("\n");
|
||||
}
|
||||
|
@ -319,14 +320,24 @@ int OpDbra(int op)
|
|||
|
||||
ot(";@ Check if Dn.w is -1\n");
|
||||
ot(" cmn r0,#1\n");
|
||||
|
||||
#if USE_CHECKPC_CALLBACK && USE_CHECKPC_DBRA
|
||||
ot(" beq DbraMin1\n");
|
||||
ot("\n");
|
||||
|
||||
ot(";@ Get Branch offset:\n");
|
||||
ot(" ldrsh r0,[r4]\n");
|
||||
ot(" add r0,r4,r0 ;@ r4 = New PC\n");
|
||||
CheckPc(0);
|
||||
#else
|
||||
ot("\n");
|
||||
ot(";@ Get Branch offset:\n");
|
||||
ot(" ldrnesh r0,[r4]\n");
|
||||
ot(" addeq r4,r4,#2 ;@ Skip branch offset\n");
|
||||
ot(" subeq r5,r5,#4 ;@ additional cycles\n");
|
||||
ot(" addne r4,r4,r0 ;@ r4 = New PC\n");
|
||||
ot("\n");
|
||||
#endif
|
||||
Cycles=12-2;
|
||||
OpEnd();
|
||||
}
|
||||
|
@ -342,6 +353,18 @@ int OpDbra(int op)
|
|||
OpEnd();
|
||||
}
|
||||
|
||||
#if USE_CHECKPC_CALLBACK && USE_CHECKPC_DBRA
|
||||
if (op==0x51c8)
|
||||
{
|
||||
ot(";@ Dn.w is -1:\n");
|
||||
ot("DbraMin1%s\n", ms?"":":");
|
||||
ot(" add r4,r4,#2 ;@ Skip branch offset\n");
|
||||
ot("\n");
|
||||
Cycles=12+2;
|
||||
OpEnd();
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -349,7 +372,7 @@ int OpDbra(int op)
|
|||
// Emit a Branch opcode 0110cccc nn (cccc=condition)
|
||||
int OpBranch(int op)
|
||||
{
|
||||
int size=0,use=0;
|
||||
int size=0,use=0,checkpc=0;
|
||||
int offset=0;
|
||||
int cc=0;
|
||||
char *asr_r11="";
|
||||
|
@ -426,28 +449,26 @@ int OpBranch(int op)
|
|||
MemHandler(1,2);
|
||||
ot("\n");
|
||||
Cycles=18; // always 18
|
||||
if (offset==0 || offset==-1)
|
||||
{
|
||||
ot(";@ Branch is quite far, so may be a good idea to check Memory Base+pc\n");
|
||||
ot(" add r0,r4,r11%s ;@ r4 = New PC\n",asr_r11);
|
||||
CheckPc(0);
|
||||
}
|
||||
else
|
||||
ot(" add r4,r4,r11%s ;@ r4 = New PC\n",asr_r11);
|
||||
}
|
||||
|
||||
#if USE_CHECKPC_CALLBACK && USE_CHECKPC_OFFSETBITS_8
|
||||
if (offset!=0 && offset!=-1) checkpc=1;
|
||||
#endif
|
||||
#if USE_CHECKPC_CALLBACK && USE_CHECKPC_OFFSETBITS_16
|
||||
if (offset==0) checkpc=1;
|
||||
#endif
|
||||
#if USE_CHECKPC_CALLBACK
|
||||
if (offset==-1) checkpc=1;
|
||||
#endif
|
||||
if (checkpc)
|
||||
{
|
||||
ot(" add r0,r4,r11%s ;@ r4 = New PC\n",asr_r11);
|
||||
CheckPc(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (offset==0 || offset==-1)
|
||||
{
|
||||
ot(" add r0,r4,r11%s ;@ r4 = New PC\n",asr_r11);
|
||||
ot(";@ Branch is quite far, so may be a good idea to check Memory Base+pc\n");
|
||||
CheckPc(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ot(" add r4,r4,r11%s ;@ r4 = New PC\n",asr_r11);
|
||||
ot("\n");
|
||||
}
|
||||
ot(" add r4,r4,r11%s ;@ r4 = New PC\n",asr_r11);
|
||||
ot("\n");
|
||||
}
|
||||
|
||||
OpEnd(size?0x10:0);
|
||||
|
@ -456,7 +477,7 @@ int OpBranch(int op)
|
|||
if (cc>=2&&(op&0xff00)==0x6200)
|
||||
{
|
||||
ot("BccDontBranch%i%s\n", 8<<size, ms?"":":");
|
||||
if (size) ot(" add r4,r4,#%d\n",8<<size);
|
||||
if (size) ot(" add r4,r4,#%d\n",1<<size);
|
||||
Cycles+=(size==1) ? 2 : -2; // Branch not taken
|
||||
OpEnd(0);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
if (type==1) ot(" movs r0,r0,%s %s\n",dir?"lsl":"lsr",pct);
|
||||
|
||||
if (dir==0 && size<2)
|
||||
{
|
||||
ot(";@ restore after right shift:\n");
|
||||
ot(" mov r0,r0,lsl #%d\n",32-(8<<size));
|
||||
ot("\n");
|
||||
}
|
||||
|
||||
OpGetFlags(0,0);
|
||||
if (usereg) { // store X only if count is not 0
|
||||
ot(" cmp %s,#0 ;@ shifting by 0?\n",pct);
|
||||
|
@ -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
|
||||
ot(" str r9,[r7,#0x4c] ;@ Save X bit\n");
|
||||
}
|
||||
ot("\n");
|
||||
|
||||
if (dir==0 && size<2)
|
||||
{
|
||||
ot(";@ restore after right shift:\n");
|
||||
ot(" movs r0,r0,lsl #%d\n",32-(8<<size));
|
||||
if (type)
|
||||
ot(" orrmi r9,r9,#0x80000000 ;@ Potentially missed N flag\n");
|
||||
ot("\n");
|
||||
}
|
||||
|
||||
if (type==0 && dir) {
|
||||
ot(";@ calculate V flag (set if sign bit changes at anytime):\n");
|
||||
|
@ -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);
|
||||
ot(" biceq r9,r9,#0x10000000\n");
|
||||
ot(" orrne r9,r9,#0x10000000\n");
|
||||
ot("\n");
|
||||
}
|
||||
|
||||
ot("\n");
|
||||
}
|
||||
|
||||
// --------------------------------------
|
||||
|
@ -467,12 +469,20 @@ static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)
|
|||
|
||||
if (usereg)
|
||||
{
|
||||
ot(";@ Reduce r2 until <0:\n");
|
||||
ot("Reduce_%.4x%s\n",op,ms?"":":");
|
||||
ot(" subs r2,r2,#%d\n",wide+1);
|
||||
ot(" bpl Reduce_%.4x\n",op);
|
||||
ot(" adds r2,r2,#%d ;@ Now r2=0-%d\n",wide+1,wide);
|
||||
ot(" beq norotx%.4x\n",op);
|
||||
if (size==2)
|
||||
{
|
||||
ot(" subs r2,r2,#33\n");
|
||||
ot(" addmis r2,r2,#33 ;@ Now r2=0-%d\n",wide);
|
||||
}
|
||||
else
|
||||
{
|
||||
ot(";@ Reduce r2 until <0:\n");
|
||||
ot("Reduce_%.4x%s\n",op,ms?"":":");
|
||||
ot(" subs r2,r2,#%d\n",wide+1);
|
||||
ot(" bpl Reduce_%.4x\n",op);
|
||||
ot(" adds r2,r2,#%d ;@ Now r2=0-%d\n",wide+1,wide);
|
||||
}
|
||||
ot(" beq norotx_%.4x\n",op);
|
||||
ot("\n");
|
||||
}
|
||||
|
||||
|
@ -488,30 +498,26 @@ static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)
|
|||
|
||||
if (shift) ot(" mov r0,r0,lsr #%d ;@ Shift down\n",shift);
|
||||
|
||||
ot(";@ Rotate bits:\n");
|
||||
ot(" mov r3,r0,lsr r2 ;@ Get right part\n");
|
||||
ot(" rsbs r2,r2,#%d ;@ should also clear ARM V\n",wide+1);
|
||||
ot(" movs r0,r0,lsl r2 ;@ Get left part\n");
|
||||
ot(" orr r0,r3,r0 ;@ r0=Rotated value\n");
|
||||
|
||||
ot(";@ Insert X bit into r2-1:\n");
|
||||
ot("\n");
|
||||
ot(";@ First get X bit (middle):\n");
|
||||
ot(" ldr r3,[r7,#0x4c]\n");
|
||||
ot(" sub r2,r2,#1\n");
|
||||
ot(" rsb r1,r2,#%d\n",wide);
|
||||
ot(" and r3,r3,#0x20000000\n");
|
||||
ot(" mov r3,r3,lsr #29\n");
|
||||
ot(" orr r0,r0,r3,lsl r2\n");
|
||||
ot(" mov r3,r3,lsl r1\n");
|
||||
|
||||
ot(";@ Rotate bits:\n");
|
||||
ot(" orr r3,r3,r0,lsr r2 ;@ Orr right part\n");
|
||||
ot(" rsbs r2,r2,#%d ;@ should also clear ARM V\n",wide+1);
|
||||
ot(" orrs r0,r3,r0,lsl r2 ;@ Orr left part, set flags\n");
|
||||
ot("\n");
|
||||
|
||||
if (shift) ot(" movs r0,r0,lsl #%d ;@ Shift up and get correct NC flags\n",shift);
|
||||
OpGetFlags(0,!usereg);
|
||||
if (!shift) {
|
||||
ot(" tst r0,r0\n");
|
||||
ot(" bicne r9,r9,#0x40000000 ;@ make sure we didn't mess Z\n");
|
||||
}
|
||||
if (usereg) { // store X only if count is not 0
|
||||
ot(" str r9,[r7,#0x4c] ;@ if not 0, Save X bit\n");
|
||||
ot(" b nozerox%.4x\n",op);
|
||||
ot("norotx%.4x%s\n",op,ms?"":":");
|
||||
ot("norotx_%.4x%s\n",op,ms?"":":");
|
||||
ot(" ldr r2,[r7,#0x4c]\n");
|
||||
ot(" adds r0,r0,#0 ;@ Defines NZ, clears CV\n");
|
||||
OpGetFlags(0,0);
|
||||
|
@ -536,9 +542,10 @@ static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)
|
|||
}
|
||||
|
||||
ot(";@ Rotate register:\n");
|
||||
if (!dir) ot(" adds r0,r0,#0 ;@ first clear V and C\n"); // ARM does not clear C if rot count is 0
|
||||
if (count<0)
|
||||
{
|
||||
if (dir) ot(" rsbs %s,%s,#32\n",pct,pct);
|
||||
if (dir) ot(" rsb %s,%s,#32\n",pct,pct);
|
||||
ot(" movs r0,r0,ror %s\n",pct);
|
||||
}
|
||||
else
|
||||
|
@ -549,9 +556,9 @@ static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)
|
|||
}
|
||||
|
||||
OpGetFlags(0,0);
|
||||
if (!dir) ot(" bic r9,r9,#0x10000000 ;@ make suve V is clear\n");
|
||||
if (dir)
|
||||
{
|
||||
ot(" bic r9,r9,#0x30000000 ;@ clear CV\n");
|
||||
ot(";@ Get carry bit from bit 0:\n");
|
||||
if (usereg)
|
||||
{
|
||||
|
@ -561,14 +568,6 @@ static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)
|
|||
else
|
||||
ot(" tst r0,#1\n");
|
||||
ot(" orrne r9,r9,#0x20000000\n");
|
||||
ot(" biceq r9,r9,#0x20000000\n");
|
||||
}
|
||||
else if (usereg)
|
||||
{
|
||||
// if we rotate something by 0, ARM doesn't clear C
|
||||
// so we need to detect that
|
||||
ot(" cmp %s,#0\n",pct);
|
||||
ot(" biceq r9,r9,#0x20000000\n");
|
||||
}
|
||||
ot("\n");
|
||||
|
||||
|
@ -599,7 +598,7 @@ int OpAsr(int op)
|
|||
// Use the same opcode for target registers:
|
||||
use=op&~0x0007;
|
||||
|
||||
// As long as count is not 8, use the same opcode for all shift counts::
|
||||
// As long as count is not 8, use the same opcode for all shift counts:
|
||||
if (usereg==0 && count!=8 && !(count==1&&type==2)) { use|=0x0e00; count=-1; }
|
||||
if (usereg) { use&=~0x0e00; count=-1; } // Use same opcode for all Dn
|
||||
|
||||
|
|
|
@ -133,18 +133,18 @@ int OpMove(int op)
|
|||
if (movea) size=2; // movea always expands to 32-bits
|
||||
|
||||
#if SPLIT_MOVEL_PD
|
||||
EaCalc (10,0x1e00,tea,size,0,0);
|
||||
EaCalc (10,0x0e00,tea,size,0,0);
|
||||
if ((tea&0x38)==0x20 && size==2) { // -(An)
|
||||
ot(" mov r11,r1\n");
|
||||
ot(" add r0,r10,#2\n");
|
||||
EaWrite(0, 1,tea,1,0x1e00,0,0);
|
||||
EaWrite(10, 11,tea,1,0x1e00,1);
|
||||
EaWrite(0, 1,tea,1,0x0e00,0,0);
|
||||
EaWrite(10, 11,tea,1,0x0e00,1);
|
||||
} else {
|
||||
EaWrite(0, 1,tea,size,0x1e00,0,0);
|
||||
EaWrite(0, 1,tea,size,0x0e00,0,0);
|
||||
}
|
||||
#else
|
||||
EaCalc (0,0x1e00,tea,size,0,0);
|
||||
EaWrite(0, 1,tea,size,0x1e00,0,0);
|
||||
EaCalc (0,0x0e00,tea,size,0,0);
|
||||
EaWrite(0, 1,tea,size,0x0e00,0,0);
|
||||
#endif
|
||||
|
||||
#if CYCLONE_FOR_GENESIS && !MEMHANDLERS_CHANGE_CYCLES
|
||||
|
@ -178,8 +178,8 @@ int OpLea(int op)
|
|||
OpStart(op,sea,tea);
|
||||
|
||||
EaCalc (1,0x003f,sea,0); // Lea
|
||||
EaCalc (0,0x1e00,tea,2);
|
||||
EaWrite(0, 1,tea,2,0x1e00);
|
||||
EaCalc (0,0x0e00,tea,2);
|
||||
EaWrite(0, 1,tea,2,0x0e00);
|
||||
|
||||
Cycles=Ea_add_ns(g_lea_cycle_table,sea);
|
||||
|
||||
|
@ -513,7 +513,7 @@ int OpMovep(int op)
|
|||
|
||||
// Get EA
|
||||
ea = (op&0x0007)|0x28;
|
||||
rea= op&0x0e00;
|
||||
rea= (op&0x0e00)>>9;
|
||||
dir = (op>>7)&1;
|
||||
|
||||
// Find size extension
|
||||
|
@ -522,7 +522,7 @@ int OpMovep(int op)
|
|||
OpStart(op,ea);
|
||||
|
||||
if(dir) { // reg to mem
|
||||
EaCalcReadNoSE(-1,11,rea,size,0x1e00);
|
||||
EaCalcReadNoSE(-1,11,rea,size,0x0e00);
|
||||
|
||||
EaCalc(10,0x000f,ea,size);
|
||||
if(size==2) { // if operand is long
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
* Warning: if you enable this, you MUST call CycloneInit() before calling
|
||||
* CycloneRun(), or else it will crash.
|
||||
*/
|
||||
#define COMPRESS_JUMPTABLE 1
|
||||
#define COMPRESS_JUMPTABLE 0
|
||||
|
||||
/*
|
||||
* Address mask for memory hadlers. The bits set will be masked out of address
|
||||
|
@ -107,10 +107,23 @@
|
|||
*/
|
||||
#define USE_CHECKPC_CALLBACK 1
|
||||
|
||||
/*
|
||||
* This determines if checkpc() should be called after jumps when 8 and 16 bit
|
||||
* displacement values were used.
|
||||
*/
|
||||
#define USE_CHECKPC_OFFSETBITS_16 1
|
||||
#define USE_CHECKPC_OFFSETBITS_8 0
|
||||
|
||||
/*
|
||||
* Call checkpc() after DBcc jumps (which use 16bit displacement). Cyclone prior to
|
||||
* 0.0087 never did that.
|
||||
*/
|
||||
#define USE_CHECKPC_DBRA 0
|
||||
|
||||
/*
|
||||
* When this option is enabled Cyclone will do two word writes instead of one
|
||||
* long write when handling MOVE.L with pre-decrementing destination, as described in
|
||||
* Bart Trzynadlowski's doc (http://www.trzy.org/files/68knotes.txt).
|
||||
* Enable this if you are emulating a 16 bit system.
|
||||
*/
|
||||
#define SPLIT_MOVEL_PD 1
|
||||
#define SPLIT_MOVEL_PD 0
|
||||
|
|
120
cpu/Cyclone/tests/test_misc2_gen.c
Normal file
120
cpu/Cyclone/tests/test_misc2_gen.c
Normal file
|
@ -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;
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue