mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 07:17:45 -04:00
adjustments for MAME
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@164 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
parent
e362c57310
commit
a67855765d
9 changed files with 245 additions and 216 deletions
|
@ -72,17 +72,17 @@ int g_movem_cycle_table[8] =
|
||||||
// add nonstandard EA
|
// add nonstandard EA
|
||||||
int Ea_add_ns(int *tab, int ea)
|
int Ea_add_ns(int *tab, int ea)
|
||||||
{
|
{
|
||||||
if(ea<0x10) return 0;
|
if(ea<0x10) return 0;
|
||||||
if((ea&0x38)==0x10) return tab[0]; // (An) (ai)
|
if((ea&0x38)==0x10) return tab[0]; // (An) (ai)
|
||||||
if(ea<0x28) return 0;
|
if(ea<0x28) return 0;
|
||||||
if(ea<0x30) return tab[1]; // ($nn,An) (di)
|
if(ea<0x30) return tab[1]; // ($nn,An) (di)
|
||||||
if(ea<0x38) return tab[2]; // ($nn,An,Rn) (ix)
|
if(ea<0x38) return tab[2]; // ($nn,An,Rn) (ix)
|
||||||
if(ea==0x38) return tab[3]; // (aw)
|
if(ea==0x38) return tab[3]; // (aw)
|
||||||
if(ea==0x39) return tab[4]; // (al)
|
if(ea==0x39) return tab[4]; // (al)
|
||||||
if(ea==0x3a) return tab[5]; // ($nn,PC) (pcdi)
|
if(ea==0x3a) return tab[5]; // ($nn,PC) (pcdi)
|
||||||
if(ea==0x3b) return tab[6]; // ($nn,pc,Rn) (pcix)
|
if(ea==0x3b) return tab[6]; // ($nn,pc,Rn) (pcix)
|
||||||
if(ea==0x3c) return tab[7]; // #$nnnn (i)
|
if(ea==0x3c) return tab[7]; // #$nnnn (i)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -147,28 +147,28 @@ int EaCalc(int a,int mask,int ea,int size,int top)
|
||||||
if (ea<0x28)
|
if (ea<0x28)
|
||||||
{
|
{
|
||||||
int step=1<<size, strr=a;
|
int step=1<<size, strr=a;
|
||||||
int low=0,lsl,i;
|
int low=0,lsl,i;
|
||||||
|
|
||||||
if ((ea&7)==7 && step<2) step=2; // move.b (a7)+ or -(a7) steps by 2 not 1
|
if ((ea&7)==7 && step<2) step=2; // move.b (a7)+ or -(a7) steps by 2 not 1
|
||||||
|
|
||||||
EaCalcReg(2,ea,mask,0,0,1);
|
EaCalcReg(2,ea,mask,0,0,1);
|
||||||
if(mask)
|
if(mask)
|
||||||
for (i=mask|0x8000; (i&1)==0; i>>=1) low++; // Find out how high up the EA mask is
|
for (i=mask|0x8000; (i&1)==0; i>>=1) low++; // Find out how high up the EA mask is
|
||||||
lsl=2-low; // Having a lsl #x here saves one opcode
|
lsl=2-low; // Having a lsl #x here saves one opcode
|
||||||
if (lsl>=0) ot(" ldr r%d,[r7,r2,lsl #%i]\n",a,lsl);
|
if (lsl>=0) ot(" ldr r%d,[r7,r2,lsl #%i]\n",a,lsl);
|
||||||
else if (lsl<0) ot(" ldr r%d,[r7,r2,lsr #%i]\n",a,-lsl);
|
else if (lsl<0) ot(" ldr r%d,[r7,r2,lsr #%i]\n",a,-lsl);
|
||||||
|
|
||||||
if ((ea&0x38)==0x18) // (An)+
|
if ((ea&0x38)==0x18) // (An)+
|
||||||
{
|
{
|
||||||
ot(" add r3,r%d,#%d ;@ Post-increment An\n",a,step);
|
ot(" add r3,r%d,#%d ;@ Post-increment An\n",a,step);
|
||||||
strr=3;
|
strr=3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ea&0x38)==0x20) // -(An)
|
if ((ea&0x38)==0x20) // -(An)
|
||||||
ot(" sub r%d,r%d,#%d ;@ Pre-decrement An\n",a,a,step);
|
ot(" sub r%d,r%d,#%d ;@ Pre-decrement An\n",a,a,step);
|
||||||
|
|
||||||
if ((ea&0x38)==0x18||(ea&0x38)==0x20)
|
if ((ea&0x38)==0x18||(ea&0x38)==0x20)
|
||||||
{
|
{
|
||||||
if (lsl>=0) ot(" str r%d,[r7,r2,lsl #%i]\n",strr,lsl);
|
if (lsl>=0) ot(" str r%d,[r7,r2,lsl #%i]\n",strr,lsl);
|
||||||
else if (lsl<0) ot(" str r%d,[r7,r2,lsr #%i]\n",strr,-lsl);
|
else if (lsl<0) ot(" str r%d,[r7,r2,lsr #%i]\n",strr,-lsl);
|
||||||
}
|
}
|
||||||
|
@ -292,10 +292,10 @@ int EaRead(int a,int v,int ea,int size,int mask,int top)
|
||||||
{
|
{
|
||||||
int lsl=0,low=0,i;
|
int lsl=0,low=0,i;
|
||||||
if (size>=2||(size==0&&top)) {
|
if (size>=2||(size==0&&top)) {
|
||||||
if(mask)
|
if(mask)
|
||||||
for (i=mask|0x8000; (i&1)==0; i>>=1) low++; // Find out how high up the EA mask is
|
for (i=mask|0x8000; (i&1)==0; i>>=1) low++; // Find out how high up the EA mask is
|
||||||
lsl=2-low; // Having a lsl #2 here saves one opcode
|
lsl=2-low; // Having a lsl #2 here saves one opcode
|
||||||
}
|
}
|
||||||
|
|
||||||
ot(";@ EaRead : Read register[r%d] into r%d:\n",a,v);
|
ot(";@ EaRead : Read register[r%d] into r%d:\n",a,v);
|
||||||
|
|
||||||
|
@ -369,10 +369,10 @@ int EaWrite(int a,int v,int ea,int size,int mask,int top)
|
||||||
{
|
{
|
||||||
int lsl=0,low=0,i;
|
int lsl=0,low=0,i;
|
||||||
if (size>=2||(size==0&&top)) {
|
if (size>=2||(size==0&&top)) {
|
||||||
if(mask)
|
if(mask)
|
||||||
for (i=mask|0x8000; (i&1)==0; i>>=1) low++; // Find out how high up the EA mask is
|
for (i=mask|0x8000; (i&1)==0; i>>=1) low++; // Find out how high up the EA mask is
|
||||||
lsl=2-low; // Having a lsl #x here saves one opcode
|
lsl=2-low; // Having a lsl #x here saves one opcode
|
||||||
}
|
}
|
||||||
|
|
||||||
ot(";@ EaWrite: r%d into register[r%d]:\n",v,a);
|
ot(";@ EaWrite: r%d into register[r%d]:\n",v,a);
|
||||||
if (shift) ot(" mov r%d,r%d,asr #%d\n",v,v,shift);
|
if (shift) ot(" mov r%d,r%d,asr #%d\n",v,v,shift);
|
||||||
|
|
|
@ -216,7 +216,7 @@ static void PrintFramework()
|
||||||
ot(" ldr r1,[r0,#-4]\n");
|
ot(" ldr r1,[r0,#-4]\n");
|
||||||
ot(" tst r1,r1\n");
|
ot(" tst r1,r1\n");
|
||||||
ot(" movne pc,lr ;@ already uncompressed\n");
|
ot(" movne pc,lr ;@ already uncompressed\n");
|
||||||
ot(" add r3,r12,#0xa000*4 ;@ handler table pointer, r12=dest\n");
|
ot(" add r3,r12,#0xa000*4 ;@ handler table pointer, r12=dest\n");
|
||||||
ot("unc_loop%s\n", ms?"":":");
|
ot("unc_loop%s\n", ms?"":":");
|
||||||
ot(" ldrh r1,[r0],#2\n");
|
ot(" ldrh r1,[r0],#2\n");
|
||||||
ot(" and r2,r1,#0xf\n");
|
ot(" and r2,r1,#0xf\n");
|
||||||
|
@ -382,17 +382,23 @@ int MemHandler(int type,int size)
|
||||||
int func=0;
|
int func=0;
|
||||||
func=0x68+type*0xc+(size<<2); // Find correct offset
|
func=0x68+type*0xc+(size<<2); // Find correct offset
|
||||||
|
|
||||||
#if MEMHANDLERS_NEED_PC
|
|
||||||
ot(" str r4,[r7,#0x40] ;@ Save PC\n");
|
|
||||||
#endif
|
|
||||||
#if MEMHANDLERS_NEED_FLAGS
|
#if MEMHANDLERS_NEED_FLAGS
|
||||||
ot(" mov r3,r9,lsr #28\n");
|
ot(" mov r3,r9,lsr #28\n");
|
||||||
ot(" strb r3,[r7,#0x46] ;@ Save Flags (NZCV)\n");
|
ot(" strb r3,[r7,#0x46] ;@ Save Flags (NZCV)\n");
|
||||||
#endif
|
#endif
|
||||||
#if MEMHANDLERS_NEED_CYCLES
|
|
||||||
ot(" str r5,[r7,#0x5c] ;@ Save Cycles\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
#if (MEMHANDLERS_ADDR_MASK & 0xff000000)
|
||||||
|
ot(" bic r0,r0,#0x%08x\n", MEMHANDLERS_ADDR_MASK & 0xff000000);
|
||||||
|
#endif
|
||||||
|
#if (MEMHANDLERS_ADDR_MASK & 0x00ff0000)
|
||||||
|
ot(" bic r0,r0,#0x%08x\n", MEMHANDLERS_ADDR_MASK & 0x00ff0000);
|
||||||
|
#endif
|
||||||
|
#if (MEMHANDLERS_ADDR_MASK & 0x0000ff00)
|
||||||
|
ot(" bic r0,r0,#0x%08x\n", MEMHANDLERS_ADDR_MASK & 0x0000ff00);
|
||||||
|
#endif
|
||||||
|
#if (MEMHANDLERS_ADDR_MASK & 0x000000ff)
|
||||||
|
ot(" bic r0,r0,#0x%08x\n", MEMHANDLERS_ADDR_MASK & 0x000000ff);
|
||||||
|
#endif
|
||||||
ot(" mov lr,pc\n");
|
ot(" mov lr,pc\n");
|
||||||
ot(" ldr pc,[r7,#0x%x] ;@ Call ",func);
|
ot(" ldr pc,[r7,#0x%x] ;@ Call ",func);
|
||||||
|
|
||||||
|
@ -541,84 +547,84 @@ static void PrintJumpTable()
|
||||||
#if COMPRESS_JUMPTABLE
|
#if COMPRESS_JUMPTABLE
|
||||||
int handlers=0,reps=0,*indexes,ip,u,out;
|
int handlers=0,reps=0,*indexes,ip,u,out;
|
||||||
// use some weird compression on the jump table
|
// use some weird compression on the jump table
|
||||||
indexes=(int *)malloc(0x10000*4);
|
indexes=(int *)malloc(0x10000*4);
|
||||||
if(!indexes) { printf("ERROR: out of memory\n"); exit(1); }
|
if(!indexes) { printf("ERROR: out of memory\n"); exit(1); }
|
||||||
len=0x10000;
|
len=0x10000;
|
||||||
|
|
||||||
ot("CycloneJumpTab%s\n", ms?"":":");
|
ot("CycloneJumpTab%s\n", ms?"":":");
|
||||||
if(ms) {
|
if(ms) {
|
||||||
for(i = 0; i < 0xa000/8; i++)
|
for(i = 0; i < 0xa000/8; i++)
|
||||||
ot(" dcd 0,0,0,0,0,0,0,0\n");
|
ot(" dcd 0,0,0,0,0,0,0,0\n");
|
||||||
} else
|
} else
|
||||||
ot(" .rept 0x%x\n .long 0,0,0,0,0,0,0,0\n .endr\n", 0xa000/8);
|
ot(" .rept 0x%x\n .long 0,0,0,0,0,0,0,0\n .endr\n", 0xa000/8);
|
||||||
|
|
||||||
// hanlers live in "a-line" part of the table
|
// hanlers live in "a-line" part of the table
|
||||||
// first output nop,a-line,f-line handlers
|
// first output nop,a-line,f-line handlers
|
||||||
ot(ms?" dcd Op____,Op__al,Op__fl,":" .long Op____,Op__al,Op__fl,");
|
ot(ms?" dcd Op____,Op__al,Op__fl,":" .long Op____,Op__al,Op__fl,");
|
||||||
handlers=3;
|
handlers=3;
|
||||||
|
|
||||||
for(i=0;i<len;i++)
|
for(i=0;i<len;i++)
|
||||||
{
|
{
|
||||||
op=CyJump[i];
|
op=CyJump[i];
|
||||||
|
|
||||||
for(u=i-1; u>=0; u--) if(op == CyJump[u]) break; // already done with this op?
|
for(u=i-1; u>=0; u--) if(op == CyJump[u]) break; // already done with this op?
|
||||||
if(u==-1 && op >= 0) {
|
if(u==-1 && op >= 0) {
|
||||||
ott("Op%.4x",op," ;@ %.4x\n",i,handlers,2);
|
ott("Op%.4x",op," ;@ %.4x\n",i,handlers,2);
|
||||||
indexes[op] = handlers;
|
indexes[op] = handlers;
|
||||||
handlers++;
|
handlers++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if(handlers&7) {
|
|
||||||
fseek(AsmFile, -1, SEEK_CUR); // remove last comma
|
|
||||||
for(i = 8-(handlers&7); i > 0; i--)
|
|
||||||
ot(",000000");
|
|
||||||
ot("\n");
|
|
||||||
}
|
|
||||||
if(ms) {
|
|
||||||
for(i = (0x4000-handlers)/8; i > 0; i--)
|
|
||||||
ot(" dcd 0,0,0,0,0,0,0,0\n");
|
|
||||||
} else {
|
|
||||||
ot(ms?"":" .rept 0x%x\n .long 0,0,0,0,0,0,0,0\n .endr\n", (0x4000-handlers)/8);
|
|
||||||
}
|
|
||||||
printf("total distinct hanlers: %i\n",handlers);
|
|
||||||
// output data
|
|
||||||
for(i=0,ip=0; i < 0xf000; i++, ip++) {
|
|
||||||
op=CyJump[i];
|
|
||||||
if(op == -2) {
|
|
||||||
// it must skip a-line area, because we keep our data there
|
|
||||||
ott("0x%.4x", handlers<<4, "\n",0,ip++,1);
|
|
||||||
ott("0x%.4x", 0x1000, "\n",0,ip,1);
|
|
||||||
i+=0xfff;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for(reps=1; i < 0xf000; i++, reps++) if(op != CyJump[i+1]) break;
|
|
||||||
if(op>=0) out=indexes[op]<<4; else out=0; // unrecognised
|
|
||||||
if(reps <= 0xe || reps==0x10) {
|
|
||||||
if(reps!=0x10) out|=reps; else out|=0xf; // 0xf means 0x10 (0xf appeared to be unused anyway)
|
|
||||||
ott("0x%.4x", out, "\n",0,ip,1);
|
|
||||||
} else {
|
|
||||||
ott("0x%.4x", out, "\n",0,ip++,1);
|
|
||||||
ott("0x%.4x", reps,"\n",0,ip,1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(ip&1) ott("0x%.4x", 0, "\n",0,ip++,1);
|
if(handlers&7) {
|
||||||
if(ip&7) fseek(AsmFile, -1, SEEK_CUR); // remove last comma
|
fseek(AsmFile, -1, SEEK_CUR); // remove last comma
|
||||||
ot("\n");
|
for(i = 8-(handlers&7); i > 0; i--)
|
||||||
if(ip&7) {
|
ot(",000000");
|
||||||
for(i = 8-(ip&7); i > 0; i--)
|
ot("\n");
|
||||||
ot(",0x0000");
|
}
|
||||||
ot("\n");
|
if(ms) {
|
||||||
}
|
for(i = (0x4000-handlers)/8; i > 0; i--)
|
||||||
if(ms) {
|
ot(" dcd 0,0,0,0,0,0,0,0\n");
|
||||||
for(i = (0x2000-ip/2)/8+1; i > 0; i--)
|
} else {
|
||||||
ot(" dcd 0,0,0,0,0,0,0,0\n");
|
ot(ms?"":" .rept 0x%x\n .long 0,0,0,0,0,0,0,0\n .endr\n", (0x4000-handlers)/8);
|
||||||
} else {
|
}
|
||||||
ot(" .rept 0x%x\n .long 0,0,0,0,0,0,0,0\n .endr\n", (0x2000-ip/2)/8+1);
|
printf("total distinct hanlers: %i\n",handlers);
|
||||||
}
|
// output data
|
||||||
ot("\n");
|
for(i=0,ip=0; i < 0xf000; i++, ip++) {
|
||||||
free(indexes);
|
op=CyJump[i];
|
||||||
|
if(op == -2) {
|
||||||
|
// it must skip a-line area, because we keep our data there
|
||||||
|
ott("0x%.4x", handlers<<4, "\n",0,ip++,1);
|
||||||
|
ott("0x%.4x", 0x1000, "\n",0,ip,1);
|
||||||
|
i+=0xfff;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for(reps=1; i < 0xf000; i++, reps++) if(op != CyJump[i+1]) break;
|
||||||
|
if(op>=0) out=indexes[op]<<4; else out=0; // unrecognised
|
||||||
|
if(reps <= 0xe || reps==0x10) {
|
||||||
|
if(reps!=0x10) out|=reps; else out|=0xf; // 0xf means 0x10 (0xf appeared to be unused anyway)
|
||||||
|
ott("0x%.4x", out, "\n",0,ip,1);
|
||||||
|
} else {
|
||||||
|
ott("0x%.4x", out, "\n",0,ip++,1);
|
||||||
|
ott("0x%.4x", reps,"\n",0,ip,1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(ip&1) ott("0x%.4x", 0, "\n",0,ip++,1);
|
||||||
|
if(ip&7) fseek(AsmFile, -1, SEEK_CUR); // remove last comma
|
||||||
|
ot("\n");
|
||||||
|
if(ip&7) {
|
||||||
|
for(i = 8-(ip&7); i > 0; i--)
|
||||||
|
ot(",0x0000");
|
||||||
|
ot("\n");
|
||||||
|
}
|
||||||
|
if(ms) {
|
||||||
|
for(i = (0x2000-ip/2)/8+1; i > 0; i--)
|
||||||
|
ot(" dcd 0,0,0,0,0,0,0,0\n");
|
||||||
|
} else {
|
||||||
|
ot(" .rept 0x%x\n .long 0,0,0,0,0,0,0,0\n .endr\n", (0x2000-ip/2)/8+1);
|
||||||
|
}
|
||||||
|
ot("\n");
|
||||||
|
free(indexes);
|
||||||
#else
|
#else
|
||||||
ot("CycloneJumpTab%s\n", ms?"":":");
|
ot("CycloneJumpTab%s\n", ms?"":":");
|
||||||
len=0xfffe; // Hmmm, armasm 2.50.8684 messes up with a 0x10000 long jump table
|
len=0xfffe; // Hmmm, armasm 2.50.8684 messes up with a 0x10000 long jump table
|
||||||
// notaz: same thing with GNU as 2.9-psion-98r2 (reloc overflow)
|
// notaz: same thing with GNU as 2.9-psion-98r2 (reloc overflow)
|
||||||
// this is due to COFF objects using only 2 bytes for reloc count
|
// this is due to COFF objects using only 2 bytes for reloc count
|
||||||
|
@ -632,7 +638,7 @@ static void PrintJumpTable()
|
||||||
else if(op==-3) ott("Op__fl",0, " ;@ %.4x\n",i-7,i,2);
|
else if(op==-3) ott("Op__fl",0, " ;@ %.4x\n",i-7,i,2);
|
||||||
else ott("Op____",0, " ;@ %.4x\n",i-7,i,2);
|
else ott("Op____",0, " ;@ %.4x\n",i-7,i,2);
|
||||||
}
|
}
|
||||||
if(i&7) fseek(AsmFile, -1, SEEK_CUR); // remove last comma
|
if(i&7) fseek(AsmFile, -1, SEEK_CUR); // remove last comma
|
||||||
|
|
||||||
ot("\n");
|
ot("\n");
|
||||||
ot(";@ notaz: we don't want to crash if we run into those 2 missing opcodes\n");
|
ot(";@ notaz: we don't want to crash if we run into those 2 missing opcodes\n");
|
||||||
|
|
|
@ -25,11 +25,23 @@ void OpUse(int op,int use)
|
||||||
ot(";@ ---------- [%.4x] %s uses Op%.4x ----------\n",op,text,use);
|
ot(";@ ---------- [%.4x] %s uses Op%.4x ----------\n",op,text,use);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpStart(int op)
|
void OpStart(int op, int ea)
|
||||||
{
|
{
|
||||||
Cycles=0;
|
Cycles=0;
|
||||||
OpUse(op,op); // This opcode obviously uses this handler
|
OpUse(op,op); // This opcode obviously uses this handler
|
||||||
ot("Op%.4x%s\n", op, ms?"":":");
|
ot("Op%.4x%s\n", op, ms?"":":");
|
||||||
|
#if (MEMHANDLERS_NEED_PC || MEMHANDLERS_NEED_CYCLES)
|
||||||
|
if (ea >= 0x10) {
|
||||||
|
#if MEMHANDLERS_NEED_PC
|
||||||
|
ot(" sub r0,r4,#2\n");
|
||||||
|
ot(" str r0,[r7,#0x40] ;@ Save PC\n");
|
||||||
|
#endif
|
||||||
|
#if MEMHANDLERS_NEED_CYCLES
|
||||||
|
ot(" str r5,[r7,#0x5c] ;@ Save Cycles\n");
|
||||||
|
#endif
|
||||||
|
ot("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpEnd()
|
void OpEnd()
|
||||||
|
|
|
@ -22,7 +22,7 @@ int OpArith(int op)
|
||||||
use=OpBase(op);
|
use=OpBase(op);
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op); Cycles=4;
|
OpStart(op, sea|tea); Cycles=4;
|
||||||
|
|
||||||
EaCalc(10,0x0000, sea,size,1);
|
EaCalc(10,0x0000, sea,size,1);
|
||||||
EaRead(10, 10, sea,size,0,1);
|
EaRead(10, 10, sea,size,0,1);
|
||||||
|
@ -94,7 +94,7 @@ int OpAddq(int op)
|
||||||
if (num!=8) use|=0x0e00; // If num is not 8, use same handler
|
if (num!=8) use|=0x0e00; // If num is not 8, use same handler
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op);
|
OpStart(op,ea);
|
||||||
Cycles=ea<8?4:8;
|
Cycles=ea<8?4:8;
|
||||||
if(type==0&&size==1) Cycles=ea<0x10?4:8;
|
if(type==0&&size==1) Cycles=ea<0x10?4:8;
|
||||||
if(size>=2) Cycles=ea<0x10?8:12;
|
if(size>=2) Cycles=ea<0x10?8:12;
|
||||||
|
@ -157,7 +157,7 @@ int OpArithReg(int op)
|
||||||
use&=~0x0e00; // Use same opcode for Dn
|
use&=~0x0e00; // Use same opcode for Dn
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op); Cycles=4;
|
OpStart(op,ea); Cycles=4;
|
||||||
|
|
||||||
ot(";@ Get r10=EA r11=EA value\n");
|
ot(";@ Get r10=EA r11=EA value\n");
|
||||||
EaCalc(10,0x003f, ea,size,1);
|
EaCalc(10,0x003f, ea,size,1);
|
||||||
|
@ -190,9 +190,9 @@ int OpArithReg(int op)
|
||||||
if(size>=2) Cycles+=4;
|
if(size>=2) Cycles+=4;
|
||||||
} else {
|
} else {
|
||||||
if(size>=2) {
|
if(size>=2) {
|
||||||
Cycles+=2;
|
Cycles+=2;
|
||||||
if(ea<0x10||ea==0x3c) Cycles+=2;
|
if(ea<0x10||ea==0x3c) Cycles+=2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OpEnd();
|
OpEnd();
|
||||||
|
@ -219,7 +219,7 @@ int OpMul(int op)
|
||||||
use&=~0x0e00; // Use same for all registers
|
use&=~0x0e00; // Use same for all registers
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op);
|
OpStart(op,ea);
|
||||||
if(type) Cycles=54;
|
if(type) Cycles=54;
|
||||||
else Cycles=sign?158:140;
|
else Cycles=sign?158:140;
|
||||||
|
|
||||||
|
@ -249,10 +249,10 @@ int OpMul(int op)
|
||||||
ot("\n");
|
ot("\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ot(" mov r10,r10,lsl #16 ;@ use only 16 bits of divisor\n");
|
ot(" mov r10,r10,lsl #16 ;@ use only 16 bits of divisor\n");
|
||||||
ot(" mov r10,r10,lsr #16\n");
|
ot(" mov r10,r10,lsr #16\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
ot(";@ Divide r2 by r10\n");
|
ot(";@ Divide r2 by r10\n");
|
||||||
ot(" mov r3,#0\n");
|
ot(" mov r3,#0\n");
|
||||||
|
@ -277,7 +277,7 @@ int OpMul(int op)
|
||||||
|
|
||||||
if (sign)
|
if (sign)
|
||||||
{
|
{
|
||||||
// sign correction
|
// sign correction
|
||||||
ot(" and r1,r11,#1\n");
|
ot(" and r1,r11,#1\n");
|
||||||
ot(" teq r1,r11,lsr #1\n");
|
ot(" teq r1,r11,lsr #1\n");
|
||||||
ot(" rsbne r3,r3,#0 ;@ negate if quotient is negative\n");
|
ot(" rsbne r3,r3,#0 ;@ negate if quotient is negative\n");
|
||||||
|
@ -285,19 +285,19 @@ int OpMul(int op)
|
||||||
ot(" rsbne r2,r2,#0 ;@ negate the remainder if divident was negative\n");
|
ot(" rsbne r2,r2,#0 ;@ negate the remainder if divident was negative\n");
|
||||||
ot("\n");
|
ot("\n");
|
||||||
|
|
||||||
// signed overflow check
|
// signed overflow check
|
||||||
ot(" mov r1,r3,asl #16\n");
|
ot(" mov r1,r3,asl #16\n");
|
||||||
ot(" cmp r3,r1,asr #16 ;@ signed overflow?\n");
|
ot(" cmp r3,r1,asr #16 ;@ signed overflow?\n");
|
||||||
ot(" orrne r9,r9,#0x10000000 ;@ set overflow flag\n");
|
ot(" orrne r9,r9,#0x10000000 ;@ set overflow flag\n");
|
||||||
ot(" bne endofop%.4x ;@ overflow!\n",op);
|
ot(" bne endofop%.4x ;@ overflow!\n",op);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// overflow check
|
// overflow check
|
||||||
ot(" movs r1,r3,lsr #16 ;@ check for overflow condition\n");
|
ot(" movs r1,r3,lsr #16 ;@ check for overflow condition\n");
|
||||||
ot(" orrne r9,r9,#0x10000000 ;@ set overflow flag\n");
|
ot(" orrne r9,r9,#0x10000000 ;@ set overflow flag\n");
|
||||||
ot(" bne endofop%.4x ;@ overflow!\n",op);
|
ot(" bne endofop%.4x ;@ overflow!\n",op);
|
||||||
}
|
}
|
||||||
|
|
||||||
ot(" mov r1,r3,lsl #16 ;@ Clip to 16-bits\n");
|
ot(" mov r1,r3,lsl #16 ;@ Clip to 16-bits\n");
|
||||||
ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");
|
ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");
|
||||||
|
@ -370,7 +370,7 @@ int OpAbcd(int op)
|
||||||
if (sea==0x27||dea==0x27) use=op; // ..except -(a7)
|
if (sea==0x27||dea==0x27) use=op; // ..except -(a7)
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op); Cycles=6;
|
OpStart(op,sea|dea); Cycles=6;
|
||||||
|
|
||||||
EaCalc( 0,0x0007, sea,0,1);
|
EaCalc( 0,0x0007, sea,0,1);
|
||||||
EaRead( 0, 10, sea,0,0x0007,1);
|
EaRead( 0, 10, sea,0,0x0007,1);
|
||||||
|
@ -384,7 +384,7 @@ int OpAbcd(int op)
|
||||||
ot(" ldrb r0,[r7,#0x45] ;@ Get X bit\n");
|
ot(" ldrb r0,[r7,#0x45] ;@ Get X bit\n");
|
||||||
ot(" mov r3,#0x00f00000\n");
|
ot(" mov r3,#0x00f00000\n");
|
||||||
ot(" and r2,r3,r1,lsr #4\n");
|
ot(" and r2,r3,r1,lsr #4\n");
|
||||||
ot(" tst r0,#2\n");
|
ot(" tst r0,#2\n");
|
||||||
ot(" and r0,r3,r10,lsr #4\n");
|
ot(" and r0,r3,r10,lsr #4\n");
|
||||||
ot(" add r0,r0,r2\n");
|
ot(" add r0,r0,r2\n");
|
||||||
ot(" addne r0,r0,#0x00100000\n");
|
ot(" addne r0,r0,#0x00100000\n");
|
||||||
|
@ -398,20 +398,20 @@ int OpAbcd(int op)
|
||||||
ot(" mov r2,r10,lsr #28\n");
|
ot(" mov r2,r10,lsr #28\n");
|
||||||
ot(" add r0,r0,r2,lsl #24\n");
|
ot(" add r0,r0,r2,lsl #24\n");
|
||||||
ot(" cmp r0,#0x09900000\n");
|
ot(" cmp r0,#0x09900000\n");
|
||||||
ot(" orrhi r9,r9,#0x20000000 ;@ C\n");
|
ot(" orrhi r9,r9,#0x20000000 ;@ C\n");
|
||||||
ot(" subhi r0,r0,#0x0a000000\n");
|
ot(" subhi r0,r0,#0x0a000000\n");
|
||||||
// ot(" and r3,r9,r0,lsr #3 ;@ Undefined V behavior part II\n");
|
// ot(" and r3,r9,r0,lsr #3 ;@ Undefined V behavior part II\n");
|
||||||
// ot(" orr r9,r9,r3,lsl #4 ;@ V\n");
|
// ot(" orr r9,r9,r3,lsl #4 ;@ V\n");
|
||||||
ot(" movs r0,r0,lsl #4\n");
|
ot(" movs r0,r0,lsl #4\n");
|
||||||
ot(" orrmi r9,r9,#0x90000000 ;@ Undefined N+V behavior\n"); // this is what Musashi really does
|
ot(" orrmi r9,r9,#0x90000000 ;@ Undefined N+V behavior\n"); // this is what Musashi really does
|
||||||
ot(" bicne r9,r9,#0x40000000 ;@ Z flag\n");
|
ot(" bicne r9,r9,#0x40000000 ;@ Z flag\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ot(" ldrb r0,[r7,#0x45] ;@ Get X bit\n");
|
ot(" ldrb r0,[r7,#0x45] ;@ Get X bit\n");
|
||||||
ot(" mov r3,#0x00f00000\n");
|
ot(" mov r3,#0x00f00000\n");
|
||||||
ot(" and r2,r3,r10,lsr #4\n");
|
ot(" and r2,r3,r10,lsr #4\n");
|
||||||
ot(" tst r0,#2\n");
|
ot(" tst r0,#2\n");
|
||||||
ot(" and r0,r3,r1,lsr #4\n");
|
ot(" and r0,r3,r1,lsr #4\n");
|
||||||
ot(" sub r0,r0,r2\n");
|
ot(" sub r0,r0,r2\n");
|
||||||
ot(" subne r0,r0,#0x00100000\n");
|
ot(" subne r0,r0,#0x00100000\n");
|
||||||
|
@ -425,13 +425,13 @@ int OpAbcd(int op)
|
||||||
ot(" mov r2,r10,lsr #28\n");
|
ot(" mov r2,r10,lsr #28\n");
|
||||||
ot(" sub r0,r0,r2,lsl #24\n");
|
ot(" sub r0,r0,r2,lsl #24\n");
|
||||||
ot(" cmp r0,#0x09900000\n");
|
ot(" cmp r0,#0x09900000\n");
|
||||||
ot(" orrhi r9,r9,#0xa0000000 ;@ N and C\n");
|
ot(" orrhi r9,r9,#0xa0000000 ;@ N and C\n");
|
||||||
ot(" addhi r0,r0,#0x0a000000\n");
|
ot(" addhi r0,r0,#0x0a000000\n");
|
||||||
// ot(" and r3,r9,r0,lsr #3 ;@ Undefined V behavior part II\n");
|
// ot(" and r3,r9,r0,lsr #3 ;@ Undefined V behavior part II\n");
|
||||||
// ot(" orr r9,r9,r3,lsl #4 ;@ V\n");
|
// ot(" orr r9,r9,r3,lsl #4 ;@ V\n");
|
||||||
ot(" movs r0,r0,lsl #4\n");
|
ot(" movs r0,r0,lsl #4\n");
|
||||||
// ot(" orrmi r9,r9,#0x80000000 ;@ Undefined N behavior\n");
|
// ot(" orrmi r9,r9,#0x80000000 ;@ Undefined N behavior\n");
|
||||||
ot(" bicne r9,r9,#0x40000000 ;@ Z flag\n");
|
ot(" bicne r9,r9,#0x40000000 ;@ Z flag\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
ot(" mov r2,r9,lsr #28\n");
|
ot(" mov r2,r9,lsr #28\n");
|
||||||
|
@ -456,7 +456,7 @@ int OpNbcd(int op)
|
||||||
use=OpBase(op);
|
use=OpBase(op);
|
||||||
if(op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if(op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op); Cycles=6;
|
OpStart(op,ea); Cycles=6;
|
||||||
if(ea >= 8) Cycles+=2;
|
if(ea >= 8) Cycles+=2;
|
||||||
|
|
||||||
EaCalc(10,0x3f, ea,0,1);
|
EaCalc(10,0x3f, ea,0,1);
|
||||||
|
@ -519,7 +519,7 @@ int OpAritha(int op)
|
||||||
use&=~0x0e00; // Use same opcode for An
|
use&=~0x0e00; // Use same opcode for An
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op); Cycles=(size==2)?6:8;
|
OpStart(op,sea); Cycles=(size==2)?6:8;
|
||||||
if(size==2&&(sea<0x10||sea==0x3c)) Cycles+=2;
|
if(size==2&&(sea<0x10||sea==0x3c)) Cycles+=2;
|
||||||
if(type==1) Cycles=6;
|
if(type==1) Cycles=6;
|
||||||
|
|
||||||
|
@ -566,7 +566,7 @@ int OpAddx(int op)
|
||||||
if (size==0&&(sea==0x27||dea==0x27)) use=op; // ___x.b -(a7)
|
if (size==0&&(sea==0x27||dea==0x27)) use=op; // ___x.b -(a7)
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op); Cycles=4;
|
OpStart(op,sea|dea); Cycles=4;
|
||||||
if(size>=2) Cycles+=4;
|
if(size>=2) Cycles+=4;
|
||||||
if(sea>=0x10) Cycles+=2;
|
if(sea>=0x10) Cycles+=2;
|
||||||
|
|
||||||
|
@ -583,7 +583,7 @@ int OpAddx(int op)
|
||||||
if (type==5 && size<2)
|
if (type==5 && size<2)
|
||||||
{
|
{
|
||||||
ot(";@ Make sure the carry bit will tip the balance:\n");
|
ot(";@ Make sure the carry bit will tip the balance:\n");
|
||||||
ot(" mvn r2,#0\n");
|
ot(" mvn r2,#0\n");
|
||||||
ot(" orr r11,r11,r2,lsr #%i\n",(size==0)?8:16);
|
ot(" orr r11,r11,r2,lsr #%i\n",(size==0)?8:16);
|
||||||
ot("\n");
|
ot("\n");
|
||||||
}
|
}
|
||||||
|
@ -631,7 +631,7 @@ int OpCmpEor(int op)
|
||||||
use&=~0x0e00; // Use 1 handler for register d0-7
|
use&=~0x0e00; // Use 1 handler for register d0-7
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op); Cycles=4;
|
OpStart(op,ea); Cycles=4;
|
||||||
if(eor) {
|
if(eor) {
|
||||||
if(ea>8) Cycles+=4;
|
if(ea>8) Cycles+=4;
|
||||||
if(size>=2) Cycles+=4;
|
if(size>=2) Cycles+=4;
|
||||||
|
@ -678,7 +678,7 @@ int OpCmpm(int op)
|
||||||
if (size==0&&(sea==0x1f||dea==0x1f)) use=op; // ..except (a7)+
|
if (size==0&&(sea==0x1f||dea==0x1f)) use=op; // ..except (a7)+
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op); Cycles=4;
|
OpStart(op,sea); Cycles=4;
|
||||||
|
|
||||||
ot(";@ Get src operand into r10:\n");
|
ot(";@ Get src operand into r10:\n");
|
||||||
EaCalc (0,0x000f, sea,size,1);
|
EaCalc (0,0x000f, sea,size,1);
|
||||||
|
@ -719,7 +719,7 @@ int OpChk(int op)
|
||||||
use&=~0x0e00; // Use 1 handler for register d0-7
|
use&=~0x0e00; // Use 1 handler for register d0-7
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op); Cycles=10;
|
OpStart(op,ea); Cycles=10;
|
||||||
|
|
||||||
ot(";@ Get EA into r10 and value into r0:\n");
|
ot(";@ Get EA into r10 and value into r0:\n");
|
||||||
EaCalc (10,0x003f, ea,size,1);
|
EaCalc (10,0x003f, ea,size,1);
|
||||||
|
|
|
@ -58,7 +58,9 @@ static void PopPc()
|
||||||
MemHandler(0,2);
|
MemHandler(0,2);
|
||||||
ot(" add r4,r0,r10 ;@ r4=Memory Base+PC\n");
|
ot(" add r4,r0,r10 ;@ r4=Memory Base+PC\n");
|
||||||
ot("\n");
|
ot("\n");
|
||||||
|
#if USE_CHECKPC_CALLBACK
|
||||||
CheckPc();
|
CheckPc();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int OpTrap(int op)
|
int OpTrap(int op)
|
||||||
|
@ -68,7 +70,7 @@ int OpTrap(int op)
|
||||||
use=op&~0xf;
|
use=op&~0xf;
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op);
|
OpStart(op,0x10);
|
||||||
ot(" and r0,r8,#0xf ;@ Get trap number\n");
|
ot(" and r0,r8,#0xf ;@ Get trap number\n");
|
||||||
ot(" orr r0,r0,#0x20\n");
|
ot(" orr r0,r0,#0x20\n");
|
||||||
ot(" mov r0,r0,asl #2\n");
|
ot(" mov r0,r0,asl #2\n");
|
||||||
|
@ -90,7 +92,7 @@ int OpLink(int op)
|
||||||
if (reg==7) use=op;
|
if (reg==7) use=op;
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op);
|
OpStart(op,0x10);
|
||||||
|
|
||||||
if(reg!=7) {
|
if(reg!=7) {
|
||||||
ot(";@ Get An\n");
|
ot(";@ Get An\n");
|
||||||
|
@ -132,7 +134,7 @@ int OpUnlk(int op)
|
||||||
use=op&~7;
|
use=op&~7;
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op);
|
OpStart(op,0x10);
|
||||||
|
|
||||||
ot(";@ Get An\n");
|
ot(";@ Get An\n");
|
||||||
EaCalc(10, 7, 8, 2, 1);
|
EaCalc(10, 7, 8, 2, 1);
|
||||||
|
@ -168,27 +170,27 @@ int Op4E70(int op)
|
||||||
OpEnd();
|
OpEnd();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case 3: // rte
|
case 3: // rte
|
||||||
OpStart(op); Cycles=20;
|
OpStart(op,0x10); Cycles=20;
|
||||||
SuperCheck(op);
|
SuperCheck(op);
|
||||||
PopSr(1);
|
PopSr(1);
|
||||||
ot(" ldr r10,[r7,#0x60] ;@ Get Memory base\n");
|
ot(" ldr r10,[r7,#0x60] ;@ Get Memory base\n");
|
||||||
PopPc();
|
PopPc();
|
||||||
SuperChange(op);
|
SuperChange(op);
|
||||||
CheckInterrupt(op);
|
CheckInterrupt(op);
|
||||||
OpEnd();
|
OpEnd();
|
||||||
SuperEnd(op);
|
SuperEnd(op);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case 5: // rts
|
case 5: // rts
|
||||||
OpStart(op); Cycles=16;
|
OpStart(op,0x10); Cycles=16;
|
||||||
ot(" ldr r10,[r7,#0x60] ;@ Get Memory base\n");
|
ot(" ldr r10,[r7,#0x60] ;@ Get Memory base\n");
|
||||||
PopPc();
|
PopPc();
|
||||||
OpEnd();
|
OpEnd();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case 6: // trapv
|
case 6: // trapv
|
||||||
OpStart(op); Cycles=4;
|
OpStart(op,0x10); Cycles=4;
|
||||||
ot(" tst r9,#0x10000000\n");
|
ot(" tst r9,#0x10000000\n");
|
||||||
ot(" subne r5,r5,#%i\n",30);
|
ot(" subne r5,r5,#%i\n",30);
|
||||||
ot(" movne r0,#0x1c ;@ TRAPV exception\n");
|
ot(" movne r0,#0x1c ;@ TRAPV exception\n");
|
||||||
|
@ -197,7 +199,7 @@ int Op4E70(int op)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case 7: // rtr
|
case 7: // rtr
|
||||||
OpStart(op); Cycles=20;
|
OpStart(op,0x10); Cycles=20;
|
||||||
PopSr(0);
|
PopSr(0);
|
||||||
ot(" ldr r10,[r7,#0x60] ;@ Get Memory base\n");
|
ot(" ldr r10,[r7,#0x60] ;@ Get Memory base\n");
|
||||||
PopPc();
|
PopPc();
|
||||||
|
@ -224,7 +226,7 @@ int OpJsr(int op)
|
||||||
use=OpBase(op);
|
use=OpBase(op);
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op);
|
OpStart(op,0x10);
|
||||||
|
|
||||||
ot(" ldr r10,[r7,#0x60] ;@ Get Memory base\n");
|
ot(" ldr r10,[r7,#0x60] ;@ Get Memory base\n");
|
||||||
ot("\n");
|
ot("\n");
|
||||||
|
@ -352,7 +354,7 @@ int OpBranch(int op)
|
||||||
else use=(op&0xff00)+1; // Use same opcode for all 8-bit branches
|
else use=(op&0xff00)+1; // Use same opcode for all 8-bit branches
|
||||||
|
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
OpStart(op);
|
OpStart(op,size?0x10:0);
|
||||||
|
|
||||||
ot(";@ Get Branch offset:\n");
|
ot(";@ Get Branch offset:\n");
|
||||||
if (size)
|
if (size)
|
||||||
|
|
|
@ -27,7 +27,7 @@ int OpBtstReg(int op)
|
||||||
use&=~0x0e00; // Use same handler for all registers
|
use&=~0x0e00; // Use same handler for all registers
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op);
|
OpStart(op,tea);
|
||||||
|
|
||||||
if(type==1||type==3) {
|
if(type==1||type==3) {
|
||||||
Cycles=8;
|
Cycles=8;
|
||||||
|
@ -88,7 +88,7 @@ int OpBtstImm(int op)
|
||||||
use=OpBase(op);
|
use=OpBase(op);
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op);
|
OpStart(op,sea|tea);
|
||||||
|
|
||||||
ot(" mov r10,#1\n");
|
ot(" mov r10,#1\n");
|
||||||
ot("\n");
|
ot("\n");
|
||||||
|
@ -145,7 +145,7 @@ int OpNeg(int op)
|
||||||
use=OpBase(op);
|
use=OpBase(op);
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op); Cycles=size<2?4:6;
|
OpStart(op,ea); Cycles=size<2?4:6;
|
||||||
if(ea >= 0x10) {
|
if(ea >= 0x10) {
|
||||||
Cycles*=2;
|
Cycles*=2;
|
||||||
#ifdef CYCLONE_FOR_GENESIS
|
#ifdef CYCLONE_FOR_GENESIS
|
||||||
|
@ -170,10 +170,10 @@ int OpNeg(int op)
|
||||||
ot(" orr r3,r9,#0xb0000000 ;@ for old Z\n");
|
ot(" orr r3,r9,#0xb0000000 ;@ for old Z\n");
|
||||||
OpGetFlags(1,1,0);
|
OpGetFlags(1,1,0);
|
||||||
if(size!=2) {
|
if(size!=2) {
|
||||||
ot(" movs r1,r1,asr #%i\n",size?16:24);
|
ot(" movs r1,r1,asr #%i\n",size?16:24);
|
||||||
ot(" orreq r9,r9,#0x40000000 ;@ possily missed Z\n");
|
ot(" orreq r9,r9,#0x40000000 ;@ possily missed Z\n");
|
||||||
}
|
}
|
||||||
ot(" andeq r9,r9,r3 ;@ fix Z\n");
|
ot(" andeq r9,r9,r3 ;@ fix Z\n");
|
||||||
ot("\n");
|
ot("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,7 +254,7 @@ int OpTst(int op)
|
||||||
use=OpBase(op);
|
use=OpBase(op);
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op); Cycles=4;
|
OpStart(op,sea); Cycles=4;
|
||||||
|
|
||||||
EaCalc ( 0,0x003f,sea,size,1);
|
EaCalc ( 0,0x003f,sea,size,1);
|
||||||
EaRead ( 0, 0,sea,size,0x003f,1);
|
EaRead ( 0, 0,sea,size,0x003f,1);
|
||||||
|
@ -322,7 +322,7 @@ int OpSet(int op)
|
||||||
use=OpBase(op);
|
use=OpBase(op);
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op); Cycles=8;
|
OpStart(op,ea); Cycles=8;
|
||||||
if (ea<8) Cycles=4;
|
if (ea<8) Cycles=4;
|
||||||
|
|
||||||
ot(" mov r1,#0\n");
|
ot(" mov r1,#0\n");
|
||||||
|
@ -429,9 +429,9 @@ static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)
|
||||||
if(count == 1) {
|
if(count == 1) {
|
||||||
if(dir==0) {
|
if(dir==0) {
|
||||||
if(size!=2) {
|
if(size!=2) {
|
||||||
ot(" orr r0,r0,r0,lsr #%i\n", size?16:24);
|
ot(" orr r0,r0,r0,lsr #%i\n", size?16:24);
|
||||||
ot(" bic r0,r0,#0x%x\n", 1<<(32-wide));
|
ot(" bic r0,r0,#0x%x\n", 1<<(32-wide));
|
||||||
}
|
}
|
||||||
GetXBit(0);
|
GetXBit(0);
|
||||||
ot(" movs r0,r0,rrx\n");
|
ot(" movs r0,r0,rrx\n");
|
||||||
OpGetFlags(0,1);
|
OpGetFlags(0,1);
|
||||||
|
@ -619,7 +619,7 @@ int OpAsrEa(int op)
|
||||||
use=OpBase(op);
|
use=OpBase(op);
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op); Cycles=6; // EmitAsr() will add 2
|
OpStart(op,ea); Cycles=6; // EmitAsr() will add 2
|
||||||
|
|
||||||
EaCalc (10,0x003f,ea,size,1);
|
EaCalc (10,0x003f,ea,size,1);
|
||||||
EaRead (10, 0,ea,size,0x003f,1);
|
EaRead (10, 0,ea,size,0x003f,1);
|
||||||
|
@ -645,7 +645,7 @@ int OpTas(int op, int gen_special)
|
||||||
use=OpBase(op);
|
use=OpBase(op);
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
if (!gen_special) OpStart(op);
|
if (!gen_special) OpStart(op,ea);
|
||||||
else
|
else
|
||||||
ot("Op%.4x_%s\n", op, ms?"":":");
|
ot("Op%.4x_%s\n", op, ms?"":":");
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@ int OpMove(int op)
|
||||||
|
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op); Cycles=4;
|
OpStart(op,sea|tea); Cycles=4;
|
||||||
|
|
||||||
EaCalc(0,0x003f,sea,size);
|
EaCalc(0,0x003f,sea,size);
|
||||||
EaRead(0, 1,sea,size,0x003f);
|
EaRead(0, 1,sea,size,0x003f);
|
||||||
|
@ -173,7 +173,7 @@ int OpLea(int op)
|
||||||
use&=~0x0e00; // Also use 1 handler for target ?0-7
|
use&=~0x0e00; // Also use 1 handler for target ?0-7
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op);
|
OpStart(op,sea|tea);
|
||||||
|
|
||||||
EaCalc (1,0x003f,sea,0); // Lea
|
EaCalc (1,0x003f,sea,0); // Lea
|
||||||
EaCalc (0,0x0e00,tea,2,1);
|
EaCalc (0,0x0e00,tea,2,1);
|
||||||
|
@ -207,7 +207,7 @@ int OpMoveSr(int op)
|
||||||
case 1:
|
case 1:
|
||||||
return 1; // no such op in 68000
|
return 1; // no such op in 68000
|
||||||
|
|
||||||
case 2: case 3:
|
case 2: case 3:
|
||||||
if (EaCanRead(ea,size)==0) return 1; // See if we can do this opcode:
|
if (EaCanRead(ea,size)==0) return 1; // See if we can do this opcode:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -215,7 +215,7 @@ int OpMoveSr(int op)
|
||||||
use=OpBase(op);
|
use=OpBase(op);
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op);
|
OpStart(op,ea);
|
||||||
Cycles=12;
|
Cycles=12;
|
||||||
if (type==0) Cycles=(ea>=8)?8:6;
|
if (type==0) Cycles=(ea>=8)?8:6;
|
||||||
|
|
||||||
|
@ -234,9 +234,9 @@ int OpMoveSr(int op)
|
||||||
EaRead(0, 0,ea,size,0x003f);
|
EaRead(0, 0,ea,size,0x003f);
|
||||||
OpRegToFlags(type==3);
|
OpRegToFlags(type==3);
|
||||||
if (type==3) {
|
if (type==3) {
|
||||||
SuperChange(op);
|
SuperChange(op);
|
||||||
CheckInterrupt(op);
|
CheckInterrupt(op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OpEnd();
|
OpEnd();
|
||||||
|
@ -260,7 +260,7 @@ int OpArithSr(int op)
|
||||||
use=OpBase(op);
|
use=OpBase(op);
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op); Cycles=16;
|
OpStart(op,ea); Cycles=16;
|
||||||
|
|
||||||
if (size) SuperCheck(op);
|
if (size) SuperCheck(op);
|
||||||
|
|
||||||
|
@ -273,7 +273,7 @@ int OpArithSr(int op)
|
||||||
if (type==5) ot(" eor r0,r1,r10\n");
|
if (type==5) ot(" eor r0,r1,r10\n");
|
||||||
OpRegToFlags(size);
|
OpRegToFlags(size);
|
||||||
if (size) {
|
if (size) {
|
||||||
SuperChange(op);
|
SuperChange(op);
|
||||||
CheckInterrupt(op);
|
CheckInterrupt(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ int OpPea(int op)
|
||||||
use=OpBase(op);
|
use=OpBase(op);
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op);
|
OpStart(op,ea);
|
||||||
|
|
||||||
ot(" ldr r10,[r7,#0x3c]\n");
|
ot(" ldr r10,[r7,#0x3c]\n");
|
||||||
EaCalc (1,0x003f, ea,0);
|
EaCalc (1,0x003f, ea,0);
|
||||||
|
@ -339,7 +339,7 @@ int OpMovem(int op)
|
||||||
use=OpBase(op);
|
use=OpBase(op);
|
||||||
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
|
||||||
|
|
||||||
OpStart(op);
|
OpStart(op,ea);
|
||||||
|
|
||||||
ot(" stmdb sp!,{r9} ;@ Push r9\n"); // can't just use r12 or lr here, because memhandlers touch them
|
ot(" stmdb sp!,{r9} ;@ Push r9\n"); // can't just use r12 or lr here, because memhandlers touch them
|
||||||
ot(" ldrh r11,[r4],#2 ;@ r11=register mask\n");
|
ot(" ldrh r11,[r4],#2 ;@ r11=register mask\n");
|
||||||
|
@ -397,7 +397,7 @@ int OpMovem(int op)
|
||||||
if(dir) { // er
|
if(dir) { // er
|
||||||
if (ea==0x3a) Cycles=16; // ($nn,PC)
|
if (ea==0x3a) Cycles=16; // ($nn,PC)
|
||||||
else if (ea==0x3b) Cycles=18; // ($nn,pc,Rn)
|
else if (ea==0x3b) Cycles=18; // ($nn,pc,Rn)
|
||||||
else Cycles=12;
|
else Cycles=12;
|
||||||
} else {
|
} else {
|
||||||
Cycles=8;
|
Cycles=8;
|
||||||
}
|
}
|
||||||
|
@ -519,44 +519,44 @@ int OpMovep(int op)
|
||||||
// Find size extension
|
// Find size extension
|
||||||
if(op&0x0040) size=2;
|
if(op&0x0040) size=2;
|
||||||
|
|
||||||
OpStart(op);
|
OpStart(op,ea);
|
||||||
|
|
||||||
if(dir) { // reg to mem
|
if(dir) { // reg to mem
|
||||||
EaCalc(11,0x0e00,0,size); // reg number -> r11
|
EaCalc(11,0x0e00,0,size); // reg number -> r11
|
||||||
EaRead(11,11,0,size,0x0e00); // regval -> r11
|
EaRead(11,11,0,size,0x0e00); // regval -> r11
|
||||||
EaCalc(10,0x0007,ea,size);
|
EaCalc(10,0x0007,ea,size);
|
||||||
if(size==2) { // if operand is long
|
if(size==2) { // if operand is long
|
||||||
ot(" mov r1,r11,lsr #24 ;@ first byte\n");
|
ot(" mov r1,r11,lsr #24 ;@ first byte\n");
|
||||||
EaWrite(10,1,ea,0,0x0007); // store first byte
|
EaWrite(10,1,ea,0,0x0007); // store first byte
|
||||||
ot(" add r10,r10,#2\n");
|
ot(" add r10,r10,#2\n");
|
||||||
ot(" mov r1,r11,lsr #16 ;@ second byte\n");
|
ot(" mov r1,r11,lsr #16 ;@ second byte\n");
|
||||||
EaWrite(10,1,ea,0,0x0007); // store second byte
|
EaWrite(10,1,ea,0,0x0007); // store second byte
|
||||||
ot(" add r10,r10,#2\n");
|
ot(" add r10,r10,#2\n");
|
||||||
}
|
}
|
||||||
ot(" mov r1,r11,lsr #8 ;@ first or third byte\n");
|
ot(" mov r1,r11,lsr #8 ;@ first or third byte\n");
|
||||||
EaWrite(10,1,ea,0,0x0007);
|
EaWrite(10,1,ea,0,0x0007);
|
||||||
ot(" add r10,r10,#2\n");
|
ot(" add r10,r10,#2\n");
|
||||||
ot(" and r1,r11,#0xff\n");
|
ot(" and r1,r11,#0xff\n");
|
||||||
EaWrite(10,1,ea,0,0x0007);
|
EaWrite(10,1,ea,0,0x0007);
|
||||||
} else { // mem to reg
|
} else { // mem to reg
|
||||||
EaCalc(10,0x0007,ea,size,1);
|
EaCalc(10,0x0007,ea,size,1);
|
||||||
EaRead(10,11,ea,0,0x0007,1); // read first byte
|
EaRead(10,11,ea,0,0x0007,1); // read first byte
|
||||||
ot(" add r10,r10,#2\n");
|
ot(" add r10,r10,#2\n");
|
||||||
EaRead(10,1,ea,0,0x0007,1); // read second byte
|
EaRead(10,1,ea,0,0x0007,1); // read second byte
|
||||||
if(size==2) { // if operand is long
|
if(size==2) { // if operand is long
|
||||||
ot(" orr r11,r11,r1,lsr #8 ;@ second byte\n");
|
ot(" orr r11,r11,r1,lsr #8 ;@ second byte\n");
|
||||||
ot(" add r10,r10,#2\n");
|
ot(" add r10,r10,#2\n");
|
||||||
EaRead(10,1,ea,0,0x0007,1);
|
EaRead(10,1,ea,0,0x0007,1);
|
||||||
ot(" orr r11,r11,r1,lsr #16 ;@ third byte\n");
|
ot(" orr r11,r11,r1,lsr #16 ;@ third byte\n");
|
||||||
ot(" add r10,r10,#2\n");
|
ot(" add r10,r10,#2\n");
|
||||||
EaRead(10,1,ea,0,0x0007,1);
|
EaRead(10,1,ea,0,0x0007,1);
|
||||||
ot(" orr r0,r11,r1,lsr #24 ;@ fourth byte\n");
|
ot(" orr r0,r11,r1,lsr #24 ;@ fourth byte\n");
|
||||||
} else {
|
} else {
|
||||||
ot(" orr r0,r11,r1,lsr #8 ;@ second byte\n");
|
ot(" orr r0,r11,r1,lsr #8 ;@ second byte\n");
|
||||||
}
|
}
|
||||||
// store the result
|
// store the result
|
||||||
EaCalc(11,0x0e00,0,size,1); // reg number -> r11
|
EaCalc(11,0x0e00,0,size,1); // reg number -> r11
|
||||||
EaWrite(11,0,0,size,0x0e00,1);
|
EaWrite(11,0,0,size,0x0e00,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cycles=(size==2)?24:16;
|
Cycles=(size==2)?24:16;
|
||||||
|
@ -580,15 +580,15 @@ int OpStopReset(int op)
|
||||||
SuperChange(op);
|
SuperChange(op);
|
||||||
OpRegToFlags(1);
|
OpRegToFlags(1);
|
||||||
|
|
||||||
ot("\n");
|
ot("\n");
|
||||||
|
|
||||||
ot(" mov r0,#1\n");
|
ot(" mov r0,#1\n");
|
||||||
ot(" str r0,[r7,#0x58] ;@ stopped\n");
|
ot(" str r0,[r7,#0x58] ;@ stopped\n");
|
||||||
ot("\n");
|
ot("\n");
|
||||||
|
|
||||||
ot(" mov r5,#0 ;@ eat cycles\n");
|
ot(" mov r5,#0 ;@ eat cycles\n");
|
||||||
Cycles = 4;
|
Cycles = 4;
|
||||||
ot("\n");
|
ot("\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,7 +37,7 @@ int MemHandler(int type,int size);
|
||||||
// OpAny.cpp
|
// OpAny.cpp
|
||||||
int OpGetFlags(int subtract,int xbit,int sprecialz=0);
|
int OpGetFlags(int subtract,int xbit,int sprecialz=0);
|
||||||
void OpUse(int op,int use);
|
void OpUse(int op,int use);
|
||||||
void OpStart(int op);
|
void OpStart(int op,int ea=0);
|
||||||
void OpEnd();
|
void OpEnd();
|
||||||
int OpBase(int op,int sepa=0);
|
int OpBase(int op,int sepa=0);
|
||||||
void OpAny(int op);
|
void OpAny(int op);
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
* Enable this option if you are going to use Cyclone to emulate Genesis /
|
* Enable this option if you are going to use Cyclone to emulate Genesis /
|
||||||
* Mega Drive system. As VDP chip in these systems had control of the bus,
|
* Mega Drive system. As VDP chip in these systems had control of the bus,
|
||||||
* several instructions were acting differently, for example TAS did'n have
|
* several instructions were acting differently, for example TAS did'n have
|
||||||
* the write-back phase. That will be emulated, if this option is enebled.
|
* the write-back phase. That will be emulated, if this option is enabled.
|
||||||
* This option also alters timing slightly.
|
* This option also alters timing slightly.
|
||||||
*/
|
*/
|
||||||
#define CYCLONE_FOR_GENESIS 1
|
#define CYCLONE_FOR_GENESIS 1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This option compresses Cyclone's jumptable. Because of this the executable
|
* This option compresses Cyclone's jumptable. Because of this the executable
|
||||||
|
@ -29,14 +29,23 @@
|
||||||
*/
|
*/
|
||||||
#define COMPRESS_JUMPTABLE 1
|
#define COMPRESS_JUMPTABLE 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Address mask for memory hadlers. The bits set will be masked out of address
|
||||||
|
* parameter, which is passed to r/w memory handlers.
|
||||||
|
* Using 0xff000000 means that only 24 least significant bits should be used.
|
||||||
|
* Set to 0 if you want to mask unused address bits in the memory handlers yourself.
|
||||||
|
*/
|
||||||
|
#define MEMHANDLERS_ADDR_MASK 0xff000000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cyclone keeps the 4 least significant bits of SR, PC+membase and it's cycle
|
* Cyclone keeps the 4 least significant bits of SR, PC+membase and it's cycle
|
||||||
* count in ARM registers instead of the context for performance reasons. If you for
|
* count in ARM registers instead of the context for performance reasons. If you for
|
||||||
* any reason need to access them in your memory handlers, enable the options below,
|
* any reason need to access them in your memory handlers, enable the options below,
|
||||||
* otherwise disable them to improve performance.
|
* otherwise disable them to improve performance.
|
||||||
* Warning: the PC value will not point to start of instruction (it will be middle or
|
* PC value will point to start of instruction currently executed.
|
||||||
* end), also updating PC is dangerous, as Cyclone may internally increment the PC
|
* Warning: updating PC in memhandlers is dangerous, as Cyclone may internally
|
||||||
* before fetching the next instruction and continue executing at wrong location.
|
* increment the PC before fetching the next instruction and continue executing
|
||||||
|
* at wrong location.
|
||||||
*/
|
*/
|
||||||
#define MEMHANDLERS_NEED_PC 0
|
#define MEMHANDLERS_NEED_PC 0
|
||||||
#define MEMHANDLERS_NEED_FLAGS 0
|
#define MEMHANDLERS_NEED_FLAGS 0
|
||||||
|
@ -70,7 +79,7 @@
|
||||||
* If enabled, UnrecognizedCallback is called if an invalid opcode is
|
* If enabled, UnrecognizedCallback is called if an invalid opcode is
|
||||||
* encountered. All context members are valid and can be changed. The handler
|
* encountered. All context members are valid and can be changed. The handler
|
||||||
* should return zero if you want Cyclone to gererate "Illegal Instruction"
|
* should return zero if you want Cyclone to gererate "Illegal Instruction"
|
||||||
* exception after this, or nonzero if not. In the later case you shuold change
|
* exception after this, or nonzero if not. In the later case you should change
|
||||||
* the PC by yourself, or else Cyclone will keep executing that opcode all over
|
* the PC by yourself, or else Cyclone will keep executing that opcode all over
|
||||||
* again.
|
* again.
|
||||||
* If disabled, "Illegal Instruction" exception is generated and execution is
|
* If disabled, "Illegal Instruction" exception is generated and execution is
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue