some optimizations

git-svn-id: file:///home/notaz/opt/svn/PicoDrive@178 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
notaz 2007-06-30 22:24:39 +00:00
parent cfb3dfa0f2
commit b637c56aad
17 changed files with 160 additions and 102 deletions

View file

@ -24,7 +24,7 @@ struct Cyclone
unsigned char irq; // [r7,#0x47] IRQ level unsigned char irq; // [r7,#0x47] IRQ level
unsigned int osp; // [r7,#0x48] Other Stack Pointer (USP/SSP) unsigned int osp; // [r7,#0x48] Other Stack Pointer (USP/SSP)
unsigned int vector; // [r7,#0x4c] IRQ vector (temporary) unsigned int vector; // [r7,#0x4c] IRQ vector (temporary)
unsigned int prev_pc;// [r7,#0x50] set to start address of currently executed opcode (if enabled in config.h) unsigned int prev_pc;// [r7,#0x50] set to start address of currently executed opcode + 2 (if enabled in config.h)
unsigned int unused; // [r7,#0x54] Unused unsigned int unused; // [r7,#0x54] Unused
int stopped; // [r7,#0x58] 1 == processor is in stopped state int stopped; // [r7,#0x58] 1 == processor is in stopped state
int cycles; // [r7,#0x5c] int cycles; // [r7,#0x5c]

View file

@ -123,7 +123,7 @@ static int EaCalcReg(int r,int ea,int mask,int forceor,int shift,int noshift=0)
// EaCalc - ARM Register 'a' = Effective Address // EaCalc - ARM Register 'a' = Effective Address
// Trashes r0,r2 and r3 // Trashes r0,r2 and r3
// size values 0, 1, 2 ~ byte, word, long // size values 0, 1, 2 ~ byte, word, long
int EaCalc(int a,int mask,int ea,int size,int top) int EaCalc(int a,int mask,int ea,int size,int top,int sign_extend)
{ {
char text[32]=""; char text[32]="";
int func=0; int func=0;
@ -134,7 +134,7 @@ int EaCalc(int a,int mask,int ea,int size,int top)
if (ea<0x10) if (ea<0x10)
{ {
int noshift=0; int noshift=0;
if (size>=2||(size==0&&top)) noshift=1; // Saves one opcode if (size>=2||(size==0&&(top||!sign_extend))) noshift=1; // Saves one opcode
ot(";@ EaCalc : Get register index into r%d:\n",a); ot(";@ EaCalc : Get register index into r%d:\n",a);
@ -180,8 +180,8 @@ int EaCalc(int a,int mask,int ea,int size,int top)
if (ea<0x30) // ($nn,An) (di) if (ea<0x30) // ($nn,An) (di)
{ {
EaCalcReg(2,8,mask,0,0);
ot(" ldrsh r0,[r4],#2 ;@ Fetch offset\n"); pc_dirty=1; ot(" ldrsh r0,[r4],#2 ;@ Fetch offset\n"); pc_dirty=1;
EaCalcReg(2,8,mask,0,0);
ot(" ldr r2,[r7,r2,lsl #2]\n"); ot(" ldr r2,[r7,r2,lsl #2]\n");
ot(" add r%d,r0,r2 ;@ Add on offset\n",a); ot(" add r%d,r0,r2 ;@ Add on offset\n",a);
Cycles+=size<2 ? 8:12; // Extra cycles Cycles+=size<2 ? 8:12; // Extra cycles
@ -277,9 +277,10 @@ int EaCalc(int a,int mask,int ea,int size,int top)
// 'a' and 'v' can be anything but 0 is generally best (for both) // 'a' and 'v' can be anything but 0 is generally best (for both)
// If (ea<0x10) nothing is trashed, else r0-r3 is trashed // If (ea<0x10) nothing is trashed, else r0-r3 is trashed
// If 'top' is given, the ARM register v shifted to the top, e.g. 0xc000 -> 0xc0000000 // If 'top' is given, the ARM register v shifted to the top, e.g. 0xc000 -> 0xc0000000
// Otherwise the ARM register v is sign extended, e.g. 0xc000 -> 0xffffc000 // If top is 0 and sign_extend is not, then ARM register v is sign extended,
// e.g. 0xc000 -> 0xffffc000 (else it may or may not be sign extended)
int EaRead(int a,int v,int ea,int size,int mask,int top) int EaRead(int a,int v,int ea,int size,int mask,int top,int sign_extend)
{ {
char text[32]=""; char text[32]="";
int shift=0; int shift=0;
@ -291,7 +292,7 @@ int EaRead(int a,int v,int ea,int size,int mask,int top)
if (ea<0x10) if (ea<0x10)
{ {
int lsl=0,low=0,i; int lsl=0,low=0,i;
if (size>=2||(size==0&&top)) { if (size>=2||(size==0&&(top||!sign_extend))) {
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
@ -316,18 +317,35 @@ int EaRead(int a,int v,int ea,int size,int mask,int top)
if (top) asl=shift; if (top) asl=shift;
if (v!=a || asl) ot(" mov r%d,r%d,asl #%d\n",v,a,asl); if (asl) ot(" mov r%d,r%d,asl #%d\n",v,a,asl);
else if (v!=a) ot(" mov r%d,r%d\n",v,a);
ot("\n"); return 0; ot("\n"); return 0;
} }
if (ea>=0x3a && ea<=0x3b) MemHandler(2,size,a); // Fetch if (ea>=0x3a && ea<=0x3b) MemHandler(2,size,a); // Fetch
else MemHandler(0,size,a); // Read else MemHandler(0,size,a); // Read
if (v!=0 || shift) { if (sign_extend)
if (shift) ot(" mov r%d,r0,asl #%d\n",v,shift); {
else ot(" mov r%d,r0\n",v); int d_reg=0;
if (shift) {
ot(" mov r%d,r%d,asl #%d\n",v,d_reg,shift);
d_reg=v;
}
if (!top && shift) {
ot(" mov r%d,r%d,asr #%d\n",v,d_reg,shift);
d_reg=v;
}
if (d_reg != v)
ot(" mov r%d,r%d\n",v,d_reg);
}
else
{
if (top && shift)
ot(" mov r%d,r0,asl #%d\n",v,shift);
else if (v!=0)
ot(" mov r%d,r0\n",v);
} }
if (top==0 && shift) ot(" mov r%d,r%d,asr #%d\n",v,v,shift);
ot("\n"); return 0; ot("\n"); return 0;
} }
@ -352,7 +370,7 @@ int EaCanRead(int ea,int size)
// Write effective address (ARM Register 'a') with ARM register 'v' // Write effective address (ARM Register 'a') with ARM register 'v'
// Trashes r0-r3,r12,lr; 'a' can be 0 or 2+, 'v' can be 1 or higher // Trashes r0-r3,r12,lr; 'a' can be 0 or 2+, 'v' can be 1 or higher
// If a==0 and v==1 it's faster though. // If a==0 and v==1 it's faster though.
int EaWrite(int a,int v,int ea,int size,int mask,int top) int EaWrite(int a,int v,int ea,int size,int mask,int top,int sign_extend_ea)
{ {
char text[32]=""; char text[32]="";
int shift=0; int shift=0;
@ -366,7 +384,7 @@ int EaWrite(int a,int v,int ea,int size,int mask,int top)
if (ea<0x10) if (ea<0x10)
{ {
int lsl=0,low=0,i; int lsl=0,low=0,i;
if (size>=2||(size==0&&top)) { if (size>=2||(size==0&&(top||!sign_extend_ea))) {
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
@ -386,7 +404,8 @@ int EaWrite(int a,int v,int ea,int size,int mask,int top)
if (ea==0x3c) { ot("Error! Write EA=0x%x\n\n",ea); return 1; } if (ea==0x3c) { ot("Error! Write EA=0x%x\n\n",ea); return 1; }
if (v!=1 || shift) ot(" mov r1,r%d,asr #%d\n",v,shift); if (shift) ot(" mov r1,r%d,asr #%d\n",v,shift);
else if (v!=1) ot(" mov r1,r%d\n",v);
MemHandler(1,size,a); // Call write handler MemHandler(1,size,a); // Call write handler

View file

@ -10,6 +10,7 @@ char *Narm[4]={ "b", "h","",""}; // Normal ARM Extensions for operand sizes 0,1,
char *Sarm[4]={"sb","sh","",""}; // Sign-extend ARM Extensions for operand sizes 0,1,2 char *Sarm[4]={"sb","sh","",""}; // Sign-extend ARM Extensions for operand sizes 0,1,2
int Cycles; // Current cycles for opcode int Cycles; // Current cycles for opcode
int pc_dirty; // something changed PC during processing int pc_dirty; // something changed PC during processing
static int arm_op_count;
void ot(const char *format, ...) void ot(const char *format, ...)
@ -22,6 +23,9 @@ void ot(const char *format, ...)
for(i=0, len=strlen(format); i < len && format[i] != '\n'; i++); for(i=0, len=strlen(format); i < len && format[i] != '\n'; i++);
if(i < len-1 && format[len-1] != '\n') printf("\nWARNING: possible improper newline placement:\n%s\n", format); if(i < len-1 && format[len-1] != '\n') printf("\nWARNING: possible improper newline placement:\n%s\n", format);
if (format[0] == ' ' && format[1] == ' ' && format[2] != ' ' && format[2] != '.')
arm_op_count++;
va_start(valist,format); va_start(valist,format);
if (AsmFile) vfprintf(AsmFile,format,valist); if (AsmFile) vfprintf(AsmFile,format,valist);
va_end(valist); va_end(valist);
@ -441,7 +445,7 @@ int MemHandler(int type,int size,int addrreg)
static void PrintOpcodes() static void PrintOpcodes()
{ {
int op=0; int op=0;
printf("Creating Opcodes: ["); printf("Creating Opcodes: [");
ot(";@ ---------------------------- Opcodes ---------------------------\n"); ot(";@ ---------------------------- Opcodes ---------------------------\n");
@ -713,7 +717,9 @@ static int CycloneMake()
ot("\n"); ot("\n");
PrintFramework(); PrintFramework();
arm_op_count = 0;
PrintOpcodes(); PrintOpcodes();
printf("~%i ARM instructions used for opcode handlers\n", arm_op_count);
PrintJumpTable(); PrintJumpTable();
if (ms) ot(" END\n"); if (ms) ot(" END\n");

View file

@ -33,8 +33,7 @@ void OpStart(int op, int sea, int tea)
#if (MEMHANDLERS_NEED_PREV_PC || MEMHANDLERS_NEED_CYCLES) #if (MEMHANDLERS_NEED_PREV_PC || MEMHANDLERS_NEED_CYCLES)
if ((sea >= 0x10 && sea != 0x3c) || (tea >= 0x10 && tea != 0x3c)) { if ((sea >= 0x10 && sea != 0x3c) || (tea >= 0x10 && tea != 0x3c)) {
#if MEMHANDLERS_NEED_PREV_PC #if MEMHANDLERS_NEED_PREV_PC
ot(" sub r0,r4,#2\n"); ot(" str r4,[r7,#0x50] ;@ Save prev PC + 2\n");
ot(" str r0,[r7,#0x50] ;@ Save prev PC\n");
#endif #endif
#if MEMHANDLERS_NEED_CYCLES #if MEMHANDLERS_NEED_CYCLES
ot(" str r5,[r7,#0x5c] ;@ Save Cycles\n"); ot(" str r5,[r7,#0x5c] ;@ Save Cycles\n");

View file

@ -8,6 +8,7 @@ int OpArith(int op)
int type=0,size=0; int type=0,size=0;
int sea=0,tea=0; int sea=0,tea=0;
int use=0; int use=0;
char *shiftstr="";
// Get source and target EA // Get source and target EA
type=(op>>9)&7; if (type==4 || type>=7) return 1; type=(op>>9)&7; if (type==4 || type>=7) return 1;
@ -26,17 +27,20 @@ int OpArith(int op)
EaCalc(10,0x0000, sea,size,1); EaCalc(10,0x0000, sea,size,1);
EaCalc(11,0x003f, tea,size,1); EaCalc(11,0x003f, tea,size,1);
EaRead(10, 10, sea,size,0,1); EaRead(10, 10, sea,size,0,0,0);
EaRead(11, 0, tea,size,0x003f,1); EaRead(11, 0, tea,size,0x003f,1);
if (size==0) shiftstr=",asl #24";
else if (size==1) shiftstr=",asl #16";
ot(";@ Do arithmetic:\n"); ot(";@ Do arithmetic:\n");
if (type==0) ot(" orr r1,r0,r10\n"); if (type==0) ot(" orr r1,r0,r10%s\n",shiftstr);
if (type==1) ot(" and r1,r0,r10\n"); if (type==1) ot(" and r1,r0,r10%s\n",shiftstr);
if (type==2) ot(" subs r1,r0,r10 ;@ Defines NZCV\n"); if (type==2) ot(" subs r1,r0,r10%s ;@ Defines NZCV\n",shiftstr);
if (type==3) ot(" adds r1,r0,r10 ;@ Defines NZCV\n"); if (type==3) ot(" adds r1,r0,r10%s ;@ Defines NZCV\n",shiftstr);
if (type==5) ot(" eor r1,r0,r10\n"); if (type==5) ot(" eor r1,r0,r10%s\n",shiftstr);
if (type==6) ot(" cmp r0,r10 ;@ Defines NZCV\n"); if (type==6) ot(" cmp r0,r10%s ;@ Defines NZCV\n",shiftstr);
if (type<2 || type==5) ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n"); // 0,1,5 if (type<2 || type==5) ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n"); // 0,1,5
@ -523,19 +527,20 @@ int OpAritha(int op)
if(type==1) Cycles=6; if(type==1) Cycles=6;
// must calculate reg EA first, because of situations like: suba.w (A0)+, A0
EaCalc (10,0x0e00, dea,2,1);
EaRead (10, 11, dea,2,0x0e00);
EaCalc ( 0,0x003f, sea,size); EaCalc ( 0,0x003f, sea,size);
EaRead ( 0, 10, sea,size,0x003f); EaRead ( 0, 0, sea,size,0x003f);
EaCalc ( 0,0x0e00, dea,2,1); if (type==0) ot(" sub r11,r11,r0\n");
EaRead ( 0, 1, dea,2,0x0e00); if (type==1) ot(" cmp r11,r0 ;@ Defines NZCV\n");
if (type==0) ot(" sub r1,r1,r10\n");
if (type==1) ot(" cmp r1,r10 ;@ Defines NZCV\n");
if (type==1) OpGetFlags(1,0); // Get Cmp flags if (type==1) OpGetFlags(1,0); // Get Cmp flags
if (type==2) ot(" add r1,r1,r10\n"); if (type==2) ot(" add r11,r11,r0\n");
ot("\n"); ot("\n");
if (type!=1) EaWrite( 0, 1, dea,2,0x0e00,1); if (type!=1) EaWrite(10, 11, dea,2,0x0e00,1);
OpEnd(sea); OpEnd(sea);

View file

@ -36,15 +36,19 @@ int OpBtstReg(int op)
if(size>=2) Cycles+=2; if(size>=2) Cycles+=2;
} }
EaCalc (0,0x0e00,sea,0); EaCalc (10,0x0e00,sea,0,0,0);
EaRead (0, 0,sea,0,0x0e00); EaRead (10, 10,sea,0,0x0e00,0,0);
EaCalc ( 0,0x003f,tea,size,0,0);
if (type>0)
ot(" mov r11,r0\n");
EaRead ( 0, 0,tea,size,0x003f,0,0);
if (tea>=0x10) if (tea>=0x10)
ot(" and r10,r0,#7 ;@ mem - do mod 8\n"); ot(" and r10,r10,#7 ;@ mem - do mod 8\n"); // size always 0
else ot(" and r10,r0,#31 ;@ reg - do mod 32\n"); else ot(" and r10,r10,#31 ;@ reg - do mod 32\n"); // size always 2
ot("\n"); ot("\n");
EaCalc(11,0x003f,tea,size);
EaRead(11, 0,tea,size,0x003f);
ot(" mov r1,#1\n"); ot(" mov r1,#1\n");
ot(" tst r0,r1,lsl r10 ;@ Do arithmetic\n"); ot(" tst r0,r1,lsl r10 ;@ Do arithmetic\n");
ot(" bicne r9,r9,#0x40000000\n"); ot(" bicne r9,r9,#0x40000000\n");
@ -57,7 +61,7 @@ int OpBtstReg(int op)
if (type==2) ot(" bic r1,r0,r1,lsl r10 ;@ Clear bit\n"); if (type==2) ot(" bic r1,r0,r1,lsl r10 ;@ Clear bit\n");
if (type==3) ot(" orr r1,r0,r1,lsl r10 ;@ Set bit\n"); if (type==3) ot(" orr r1,r0,r1,lsl r10 ;@ Set bit\n");
ot("\n"); ot("\n");
EaWrite(11, 1,tea,size,0x003f); EaWrite(11, 1,tea,size,0x003f,0,0);
} }
OpEnd(tea); OpEnd(tea);
@ -90,14 +94,14 @@ int OpBtstImm(int op)
OpStart(op,sea,tea); OpStart(op,sea,tea);
ot(" mov r10,#1\n");
ot("\n"); ot("\n");
EaCalc ( 0,0x0000,sea,0); EaCalc ( 0,0x0000,sea,0,0,0);
EaRead ( 0, 0,sea,0,0); EaRead ( 0, 0,sea,0,0,0,0);
ot(" mov r10,#1\n");
ot(" bic r9,r9,#0x40000000 ;@ Blank Z flag\n"); ot(" bic r9,r9,#0x40000000 ;@ Blank Z flag\n");
if (tea>=0x10) if (tea>=0x10)
ot(" and r0,r0,#7 ;@ mem - do mod 8\n"); ot(" and r0,r0,#7 ;@ mem - do mod 8\n"); // size always 0
else ot(" and r0,r0,#0x1F ;@ reg - do mod 32\n"); else ot(" and r0,r0,#0x1F ;@ reg - do mod 32\n"); // size always 2
ot(" mov r10,r10,lsl r0 ;@ Make bit mask\n"); ot(" mov r10,r10,lsl r0 ;@ Make bit mask\n");
ot("\n"); ot("\n");
@ -108,8 +112,8 @@ int OpBtstImm(int op)
if(size>=2) Cycles+=2; if(size>=2) Cycles+=2;
} }
EaCalc (11,0x003f,tea,size); EaCalc (11,0x003f,tea,size,0,0);
EaRead (11, 0,tea,size,0x003f); EaRead (11, 0,tea,size,0x003f,0,0);
ot(" tst r0,r10 ;@ Do arithmetic\n"); ot(" tst r0,r10 ;@ Do arithmetic\n");
ot(" orreq r9,r9,#0x40000000 ;@ Get Z flag\n"); ot(" orreq r9,r9,#0x40000000 ;@ Get Z flag\n");
ot("\n"); ot("\n");
@ -120,7 +124,7 @@ int OpBtstImm(int op)
if (type==2) ot(" bic r1,r0,r10 ;@ Clear bit\n"); if (type==2) ot(" bic r1,r0,r10 ;@ Clear bit\n");
if (type==3) ot(" orr r1,r0,r10 ;@ Set bit\n"); if (type==3) ot(" orr r1,r0,r10 ;@ Set bit\n");
ot("\n"); ot("\n");
EaWrite(11, 1,tea,size,0x003f); EaWrite(11, 1,tea,size,0x003f,0,0);
} }
OpEnd(sea,tea); OpEnd(sea,tea);
@ -156,16 +160,16 @@ int OpNeg(int op)
#endif #endif
} }
EaCalc (10,0x003f,ea,size); EaCalc (10,0x003f,ea,size,0,0);
if (type!=1) EaRead (10,0,ea,size,0x003f); // Don't need to read for 'clr' if (type!=1) EaRead (10,0,ea,size,0x003f,0,0); // Don't need to read for 'clr' (or do we, for dummy read?)
if (type==1) ot("\n"); if (type==1) ot("\n");
if (type==0) if (type==0)
{ {
ot(";@ Negx:\n"); ot(";@ Negx:\n");
GetXBit(1); GetXBit(1);
if(size!=2) ot(" mov r0,r0,lsl #%i\n",size?16:24); if(size!=2) ot(" mov r0,r0,asl #%i\n",size?16:24);
ot(" rscs r1,r0,#0 ;@ do arithmetic\n"); ot(" rscs r1,r0,#0 ;@ do arithmetic\n");
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);
@ -188,7 +192,7 @@ int OpNeg(int op)
if (type==2) if (type==2)
{ {
ot(";@ Neg:\n"); ot(";@ Neg:\n");
if(size!=2) ot(" mov r0,r0,lsl #%i\n",size?16:24); if(size!=2) ot(" mov r0,r0,asl #%i\n",size?16:24);
ot(" rsbs r1,r0,#0\n"); ot(" rsbs r1,r0,#0\n");
OpGetFlags(1,1); OpGetFlags(1,1);
if(size!=2) ot(" mov r1,r1,asr #%i\n",size?16:24); if(size!=2) ot(" mov r1,r1,asr #%i\n",size?16:24);
@ -198,13 +202,18 @@ int OpNeg(int op)
if (type==3) if (type==3)
{ {
ot(";@ Not:\n"); ot(";@ Not:\n");
ot(" mvn r1,r0\n"); if(size!=2) {
ot(" mov r0,r0,asl #%i\n",size?16:24);
ot(" mvn r1,r0,asr #%i\n",size?16:24);
}
else
ot(" mvn r1,r0\n");
ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n"); ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");
OpGetFlags(0,0); OpGetFlags(0,0);
ot("\n"); ot("\n");
} }
EaWrite(10, 1,ea,size,0x003f); EaWrite(10, 1,ea,size,0x003f,0,0);
OpEnd(ea); OpEnd(ea);
@ -284,8 +293,8 @@ int OpExt(int op)
OpStart(op); Cycles=4; OpStart(op); Cycles=4;
EaCalc (10,0x0007,ea,size+1); EaCalc (10,0x0007,ea,size+1,0,0);
EaRead (10, 0,ea,size+1,0x0007); EaRead (10, 0,ea,size+1,0x0007,0,0);
ot(" mov r0,r0,asl #%d\n",shift); ot(" mov r0,r0,asl #%d\n",shift);
ot(" adds r0,r0,#0 ;@ Defines NZ, clears CV\n"); ot(" adds r0,r0,#0 ;@ Defines NZ, clears CV\n");
@ -293,7 +302,7 @@ int OpExt(int op)
ot(" mov r1,r0,asr #%d\n",shift); ot(" mov r1,r0,asr #%d\n",shift);
ot("\n"); ot("\n");
EaWrite(10, 1,ea,size+1,0x0007); EaWrite(10, 1,ea,size+1,0x0007,0,0);
OpEnd(); OpEnd();
return 0; return 0;
@ -325,22 +334,39 @@ int OpSet(int op)
OpStart(op,ea); Cycles=8; OpStart(op,ea); Cycles=8;
if (ea<8) Cycles=4; if (ea<8) Cycles=4;
ot(" mov r1,#0\n"); if (cc)
ot(" mov r1,#0\n");
if (cc!=1) switch (cc)
{ {
ot(";@ Is the condition true?\n"); case 0: // T
if ((cc&~1)==2) ot(" eor r9,r9,#0x20000000 ;@ Invert carry for hi/ls\n"); ot(" mvn r1,#0\n");
ot(" msr cpsr_flg,r9 ;@ ARM flags = 68000 flags\n"); if (ea<8) Cycles+=2;
if ((cc&~1)==2) ot(" eor r9,r9,#0x20000000 ;@ Invert carry for hi/ls\n"); break;
ot(" mvn%s r1,r1\n",cond[cc]); case 1: // F
break;
case 2: // hi
ot(" ands r0,r9,#0x60000000 ;@ hi: !C && !Z\n");
ot(" mvneq r1,r1\n");
if (ea<8) ot(" subeq r5,r5,#2 ;@ Extra cycles\n");
break;
case 3: // ls
ot(" tst r9,#0x60000000 ;@ ls: C || Z\n");
ot(" mvnne r1,r1\n");
if (ea<8) ot(" subne r5,r5,#2 ;@ Extra cycles\n");
break;
default:
ot(";@ Is the condition true?\n");
ot(" msr cpsr_flg,r9 ;@ ARM flags = 68000 flags\n");
ot(" mvn%s r1,r1\n",cond[cc]);
if (ea<8) ot(" sub%s r5,r5,#2 ;@ Extra cycles\n",cond[cc]);
break;
} }
if (cc!=1 && ea<8) ot(" sub%s r5,r5,#2 ;@ Extra cycles\n",cond[cc]);
ot("\n"); ot("\n");
EaCalc (0,0x003f, ea,size); EaCalc (0,0x003f, ea,size,0,0);
EaWrite(0, 1, ea,size,0x003f); EaWrite(0, 1, ea,size,0x003f,0,0);
OpEnd(ea); OpEnd(ea);
return 0; return 0;

View file

@ -130,19 +130,19 @@ int OpMove(int op)
if (movea) size=2; // movea always expands to 32-bits if (movea) size=2; // movea always expands to 32-bits
EaCalc (0,0x0e00,tea,size); EaCalc (0,0x0e00,tea,size,0,0);
#if SPLIT_MOVEL_PD #if SPLIT_MOVEL_PD
if ((tea&0x38)==0x20 && size==2) { // -(An) if ((tea&0x38)==0x20 && size==2) { // -(An)
ot(" mov r10,r0\n"); ot(" mov r10,r0\n");
ot(" mov r11,r1\n"); ot(" mov r11,r1\n");
ot(" add r0,r0,#2\n"); ot(" add r0,r0,#2\n");
EaWrite(0, 1,tea,1,0x0e00); EaWrite(0, 1,tea,1,0x0e00,0,0);
EaWrite(10, 11,tea,1,0x0e00,1); EaWrite(10, 11,tea,1,0x0e00,1);
} else { } else {
EaWrite(0, 1,tea,size,0x0e00); EaWrite(0, 1,tea,size,0x0e00,0,0);
} }
#else #else
EaWrite(0, 1,tea,size,0x0e00); EaWrite(0, 1,tea,size,0x0e00,0,0);
#endif #endif
#if CYCLONE_FOR_GENESIS && !MEMHANDLERS_CHANGE_CYCLES #if CYCLONE_FOR_GENESIS && !MEMHANDLERS_CHANGE_CYCLES
@ -224,14 +224,14 @@ int OpMoveSr(int op)
if (type==0 || type==1) if (type==0 || type==1)
{ {
OpFlagsToReg(type==0); OpFlagsToReg(type==0);
EaCalc (0,0x003f,ea,size); EaCalc (0,0x003f,ea,size,0,0);
EaWrite(0, 1,ea,size,0x003f); EaWrite(0, 1,ea,size,0x003f,0,0);
} }
if (type==2 || type==3) if (type==2 || type==3)
{ {
EaCalc(0,0x003f,ea,size); EaCalc(0,0x003f,ea,size,0,0);
EaRead(0, 0,ea,size,0x003f); EaRead(0, 0,ea,size,0x003f,0,0);
OpRegToFlags(type==3); OpRegToFlags(type==3);
if (type==3) { if (type==3) {
SuperChange(op); SuperChange(op);
@ -264,8 +264,8 @@ int OpArithSr(int op)
if (size) SuperCheck(op); if (size) SuperCheck(op);
EaCalc(0,0x003f,ea,size); EaCalc(10,0x003f,ea,size);
EaRead(0, 10,ea,size,0x003f); EaRead(10, 10,ea,size,0x003f);
OpFlagsToReg(size); OpFlagsToReg(size);
if (type==0) ot(" orr r0,r1,r10\n"); if (type==0) ot(" orr r0,r1,r10\n");
@ -341,57 +341,58 @@ int OpMovem(int op)
OpStart(op,ea); OpStart(op,ea);
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");
ot("\n");
ot(";@ Get the address into r9:\n");
EaCalc(9,0x003f,cea,size);
ot(";@ r10=Register Index*4:\n"); ot(";@ r10=Register Index*4:\n");
if (decr) ot(" mov r10,#0x3c ;@ order reversed for -(An)\n"); if (decr) ot(" mov r10,#0x40 ;@ order reversed for -(An)\n");
else ot(" mov r10,#0\n"); else ot(" mov r10,#-4\n");
ot("\n"); ot("\n");
ot("MoreReg%.4x%s\n",op, ms?"":":"); ot(";@ Get the address into r6:\n");
EaCalc(6,0x003f,cea,size);
ot(" tst r11,#1\n"); ot("\n");
ot(" beq SkipReg%.4x\n",op); ot(" tst r11,r11\n"); // sanity check
ot(" beq NoRegs%.4x\n",op);
ot("\n");
ot("Movemloop%.4x%s\n",op, ms?"":":");
ot(" add r10,r10,#%d ;@ r10=Next Register\n",decr?-4:4);
ot(" movs r11,r11,lsr #1\n");
ot(" bcc Movemloop%.4x\n",op);
ot("\n"); ot("\n");
if (decr) ot(" sub r9,r9,#%d ;@ Pre-decrement address\n",1<<size); if (decr) ot(" sub r6,r6,#%d ;@ Pre-decrement address\n",1<<size);
if (dir) if (dir)
{ {
ot(" ;@ Copy memory to register:\n",1<<size); ot(" ;@ Copy memory to register:\n",1<<size);
EaRead (9,0,ea,size,0x003f); EaRead (6,0,ea,size,0x003f);
ot(" str r0,[r7,r10] ;@ Save value into Dn/An\n"); ot(" str r0,[r7,r10] ;@ Save value into Dn/An\n");
} }
else else
{ {
ot(" ;@ Copy register to memory:\n",1<<size); ot(" ;@ Copy register to memory:\n",1<<size);
ot(" ldr r1,[r7,r10] ;@ Load value from Dn/An\n"); ot(" ldr r1,[r7,r10] ;@ Load value from Dn/An\n");
EaWrite(9,1,ea,size,0x003f); EaWrite(6,1,ea,size,0x003f);
} }
if (decr==0) ot(" add r9,r9,#%d ;@ Post-increment address\n",1<<size); if (decr==0) ot(" add r6,r6,#%d ;@ Post-increment address\n",1<<size);
ot(" sub r5,r5,#%d ;@ Take some cycles\n",2<<size); ot(" sub r5,r5,#%d ;@ Take some cycles\n",2<<size);
ot("\n"); ot(" tst r11,r11\n");
ot("SkipReg%.4x%s\n",op, ms?"":":"); ot(" bne Movemloop%.4x\n",op);
ot(" movs r11,r11,lsr #1;@ Shift mask:\n");
ot(" add r10,r10,#%d ;@ r10=Next Register\n",decr?-4:4);
ot(" bne MoreReg%.4x\n",op);
ot("\n"); ot("\n");
if (change) if (change)
{ {
ot(";@ Write back address:\n"); ot(";@ Write back address:\n");
EaCalc (0,0x0007,8|(ea&7),2); EaCalc (0,0x0007,8|(ea&7),2);
EaWrite(0, 9,8|(ea&7),2,0x0007); EaWrite(0, 6,8|(ea&7),2,0x0007);
} }
ot(" ldmia sp!,{r9} ;@ Pop r9\n"); ot("NoRegs%.4x%s\n",op, ms?"":":");
ot(" ldr r6,=CycloneJumpTab ;@ restore Opcode Jump table\n");
ot("\n"); ot("\n");
if(dir) { // er if(dir) { // er
@ -405,6 +406,8 @@ int OpMovem(int op)
Cycles+=Ea_add_ns(g_movem_cycle_table,ea); Cycles+=Ea_add_ns(g_movem_cycle_table,ea);
OpEnd(ea); OpEnd(ea);
ot("\n");
ltorg();
return 0; return 0;
} }

View file

@ -16,10 +16,10 @@ extern int g_lea_cycle_table[];
extern int g_pea_cycle_table[]; extern int g_pea_cycle_table[];
extern int g_movem_cycle_table[]; extern int g_movem_cycle_table[];
int Ea_add_ns(int *tab, int ea); // add nonstandard EA cycles int Ea_add_ns(int *tab, int ea); // add nonstandard EA cycles
int EaCalc(int a,int mask,int ea,int size,int top=0); int EaCalc(int a,int mask,int ea,int size,int top=0,int sign_extend=1); // 6
int EaRead(int a,int v,int ea,int size,int mask,int top=0); int EaRead(int a,int v,int ea,int size,int mask,int top=0,int sign_extend=1); // 7
int EaCanRead(int ea,int size); int EaCanRead(int ea,int size);
int EaWrite(int a,int v,int ea,int size,int mask,int top=0); int EaWrite(int a,int v,int ea,int size,int mask,int top=0,int sign_extend_ea=1);
int EaCanWrite(int ea); int EaCanWrite(int ea);
int EaAn(int ea); int EaAn(int ea);

View file

@ -45,7 +45,7 @@
* MEMHANDLERS_NEED_PC updates .pc context field with PC value effective at the time * MEMHANDLERS_NEED_PC updates .pc context field with PC value effective at the time
* when memhandler was called (opcode address + unknown amount). * when memhandler was called (opcode address + unknown amount).
* MEMHANDLERS_NEED_PREV_PC updates .prev_pc context field to currently executed * MEMHANDLERS_NEED_PREV_PC updates .prev_pc context field to currently executed
* opcode address. * opcode address + 2.
* Note that .pc and .prev_pc values are always real pointers to memory, so you must * Note that .pc and .prev_pc values are always real pointers to memory, so you must
* subtract .membase to get M68k PC value. * subtract .membase to get M68k PC value.
* Warning: updating PC in memhandlers is dangerous, as Cyclone may internally * Warning: updating PC in memhandlers is dangerous, as Cyclone may internally

Binary file not shown.

BIN
cpu/Cyclone/tests/test_abcd.bin Executable file

Binary file not shown.

BIN
cpu/Cyclone/tests/test_cmpm.bin Executable file

Binary file not shown.

BIN
cpu/Cyclone/tests/test_div.bin Executable file

Binary file not shown.

BIN
cpu/Cyclone/tests/test_misc.bin Executable file

Binary file not shown.

BIN
cpu/Cyclone/tests/test_negx.bin Executable file

Binary file not shown.

BIN
cpu/Cyclone/tests/test_rol.bin Executable file

Binary file not shown.

BIN
cpu/Cyclone/tests/test_shift.bin Executable file

Binary file not shown.