First pass at fixing formatting issues in the ARM emulation code.

Also fixed warnings when compiling on 64-bit compilers.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2214 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2011-03-09 14:21:32 +00:00
parent 4d16be1049
commit bcb8dfbc2b
1 changed files with 660 additions and 599 deletions

View File

@ -49,9 +49,9 @@ Thumbulator::~Thumbulator()
int Thumbulator::run( void ) int Thumbulator::run( void )
{ {
reset(); reset();
while(1) for(;;)
{ {
if(execute()) break; if (execute()) break;
if (instructions > 500000) // way more than would otherwise be possible if (instructions > 500000) // way more than would otherwise be possible
{ {
DISS=1; // dump instructions DISS=1; // dump instructions
@ -61,6 +61,7 @@ int Thumbulator::run( void )
{ {
DISS=0; DISS=0;
DBUG=0; DBUG=0;
// TODO - deal with this condition more elegantly
exit(1); // exit Stella exit(1); // exit Stella
} }
} }
@ -68,136 +69,149 @@ int Thumbulator::run( void )
return 0; return 0;
} }
//------------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Thumbulator::dump_counters ( void ) void Thumbulator::dump_counters ( void )
{ {
printf("\n\n"); cout << endl << endl
printf("instructions %lu\n",instructions); << "instructions " << instructions << endl
printf("fetches %lu\n",fetches); << "fetches " << fetches << endl
printf("reads %lu\n",reads); << "reads " << reads << endl
printf("writes %lu\n",writes); << "writes " << writes << endl
printf("memcycles %lu\n",fetches+reads+writes); << "memcycles " << (fetches+reads+writes) << endl;
} }
//------------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 Thumbulator::fetch16 ( uInt32 addr ) uInt32 Thumbulator::fetch16 ( uInt32 addr )
{ {
uInt32 data; uInt32 data;
fetches++; fetches++;
if(DBUG)
fprintf(stderr,"fetch16(0x%08X)=",addr);
if(DBUG) fprintf(stderr,"fetch16(0x%08X)=",addr);
switch(addr&0xF0000000) switch(addr&0xF0000000)
{ {
case 0x00000000: //ROM case 0x00000000: //ROM
addr&=ROMADDMASK; addr &= ROMADDMASK;
if(addr<0x50)
if(addr<0x50) {
{
fprintf(stderr,"fetch16(0x%08X), abort\n",addr); fprintf(stderr,"fetch16(0x%08X), abort\n",addr);
exit(1); exit(1);
} }
addr>>=1; addr>>=1;
#ifdef __BIG_ENDIAN__ #ifdef __BIG_ENDIAN__
data=((rom[addr]>>8)|(rom[addr]<<8))&0xffff; data=((rom[addr]>>8)|(rom[addr]<<8))&0xffff;
#else #else
data=rom[addr]; data=rom[addr];
#endif #endif
if(DBUG) fprintf(stderr,"0x%04X\n",data); if(DBUG)
fprintf(stderr,"0x%04X\n",data);
return(data); return(data);
case 0x40000000: //RAM case 0x40000000: //RAM
addr&=RAMADDMASK; addr &= RAMADDMASK;
addr>>=1; addr>>=1;
#ifdef __BIG_ENDIAN__ #ifdef __BIG_ENDIAN__
data=((ram[addr]>>8)|(ram[addr]<<8))&0xffff; data=((ram[addr]>>8)|(ram[addr]<<8))&0xffff;
#else #else
data=ram[addr]; data=ram[addr];
#endif #endif
if(DBUG) fprintf(stderr,"0x%04X\n",data); if(DBUG)
fprintf(stderr,"0x%04X\n",data);
return(data); return(data);
} }
fprintf(stderr,"fetch16(0x%08X), abort\n",addr); fprintf(stderr,"fetch16(0x%08X), abort\n",addr);
exit(1); exit(1);
} }
//------------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 Thumbulator::fetch32 ( uInt32 addr ) uInt32 Thumbulator::fetch32 ( uInt32 addr )
{ {
uInt32 data; uInt32 data;
if(DBUG) fprintf(stderr,"fetch32(0x%08X)=",addr); if(DBUG)
fprintf(stderr,"fetch32(0x%08X)=",addr);
switch(addr&0xF0000000) switch(addr&0xF0000000)
{ {
case 0x00000000: //ROM case 0x00000000: //ROM
if(addr<0x50) if(addr<0x50)
{ {
data=read32(addr); data=read32(addr);
if(DBUG) fprintf(stderr,"0x%08X\n",data); if(DBUG)
fprintf(stderr,"0x%08X\n",data);
if(addr==0x00000000) return(data); if(addr==0x00000000) return(data);
if(addr==0x00000004) return(data); if(addr==0x00000004) return(data);
fprintf(stderr,"fetch32(0x%08X), abort\n",addr); fprintf(stderr,"fetch32(0x%08X), abort\n",addr);
exit(1); exit(1);
} }
case 0x40000000: //RAM case 0x40000000: //RAM
data =fetch16(addr+2); data =fetch16(addr+2);
data<<=16; data<<=16;
data|=fetch16(addr+0); data|=fetch16(addr+0);
if(DBUG) fprintf(stderr,"0x%08X\n",data); if(DBUG)
fprintf(stderr,"0x%08X\n",data);
return(data); return(data);
} }
fprintf(stderr,"fetch32(0x%08X), abort\n",addr); fprintf(stderr,"fetch32(0x%08X), abort\n",addr);
exit(1); exit(1);
} }
//------------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Thumbulator::write16 ( uInt32 addr, uInt32 data ) void Thumbulator::write16 ( uInt32 addr, uInt32 data )
{ {
writes++; writes++;
if(DBUG)
fprintf(stderr,"write16(0x%08X,0x%08X)\n",addr,data);
if(DBUG) fprintf(stderr,"write16(0x%08X,0x%08X)\n",addr,data);
switch(addr&0xF0000000) switch(addr&0xF0000000)
{ {
case 0x40000000: //RAM case 0x40000000: //RAM
addr&=RAMADDMASK; addr&=RAMADDMASK;
addr>>=1; addr>>=1;
#ifdef __BIG_ENDIAN__ #ifdef __BIG_ENDIAN__
ram[addr]=(((data&0xFFFF)>>8)|((data&0xffff)<<8))&0xffff; ram[addr]=(((data&0xFFFF)>>8)|((data&0xffff)<<8))&0xffff;
#else #else
ram[addr]=data&0xFFFF; ram[addr]=data&0xFFFF;
#endif #endif
return; return;
} }
fprintf(stderr,"write16(0x%08X,0x%08X), abort\n",addr,data); fprintf(stderr,"write16(0x%08X,0x%08X), abort\n",addr,data);
exit(1); exit(1);
} }
//------------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Thumbulator::write32 ( uInt32 addr, uInt32 data ) void Thumbulator::write32 ( uInt32 addr, uInt32 data )
{ {
if(DBUG) fprintf(stderr,"write32(0x%08X,0x%08X)\n",addr,data); if(DBUG)
fprintf(stderr,"write32(0x%08X,0x%08X)\n",addr,data);
switch(addr&0xF0000000) switch(addr&0xF0000000)
{ {
case 0xF0000000: //halt case 0xF0000000: //halt
dump_counters(); dump_counters();
exit(0); exit(0);
case 0xE0000000: //periph case 0xE0000000: //periph
switch(addr) switch(addr)
{ {
case 0xE0000000: case 0xE0000000:
if(DISS) printf("uart: ["); if(DISS) printf("uart: [");
printf("%c",data&0xFF); printf("%c",data&0xFF);
if(DISS) printf("]\n"); if(DISS) printf("]\n");
fflush(stdout); fflush(stdout);
break; break;
} }
return; return;
case 0xD0000000: //debug case 0xD0000000: //debug
fprintf(stderr,"[0x%08X][0x%08X] 0x%08X\n",read_register(14),addr,data); fprintf(stderr,"[0x%08X][0x%08X] 0x%08X\n",read_register(14),addr,data);
return; return;
case 0x40000000: //RAM case 0x40000000: //RAM
write16(addr+0,(data>> 0)&0xFFFF); write16(addr+0,(data>> 0)&0xFFFF);
write16(addr+2,(data>>16)&0xFFFF); write16(addr+2,(data>>16)&0xFFFF);
@ -207,47 +221,54 @@ fflush(stdout);
exit(1); exit(1);
} }
//----------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 Thumbulator::read16 ( uInt32 addr ) uInt32 Thumbulator::read16 ( uInt32 addr )
{ {
uInt32 data; uInt32 data;
reads++; reads++;
if(DBUG) fprintf(stderr,"read16(0x%08X)=",addr); if(DBUG)
fprintf(stderr,"read16(0x%08X)=",addr);
switch(addr&0xF0000000) switch(addr&0xF0000000)
{ {
case 0x00000000: //ROM case 0x00000000: //ROM
addr&=ROMADDMASK; addr&=ROMADDMASK;
addr>>=1; addr>>=1;
#ifdef __BIG_ENDIAN__ #ifdef __BIG_ENDIAN__
data=((rom[addr]>>8)|(rom[addr]<<8))&0xffff; data=((rom[addr]>>8)|(rom[addr]<<8))&0xffff;
#else #else
data=rom[addr]; data=rom[addr];
#endif #endif
if(DBUG) fprintf(stderr,"0x%04X\n",data); if(DBUG)
fprintf(stderr,"0x%04X\n",data);
return(data); return(data);
case 0x40000000: //RAM case 0x40000000: //RAM
addr&=RAMADDMASK; addr&=RAMADDMASK;
addr>>=1; addr>>=1;
#ifdef __BIG_ENDIAN__ #ifdef __BIG_ENDIAN__
data=((ram[addr]>>8)|(ram[addr]<<8))&0xffff; data=((ram[addr]>>8)|(ram[addr]<<8))&0xffff;
#else #else
data=ram[addr]; data=ram[addr];
#endif #endif
if(DBUG) fprintf(stderr,"0x%04X\n",data); if(DBUG)
fprintf(stderr,"0x%04X\n",data);
return(data); return(data);
} }
fprintf(stderr,"read16(0x%08X), abort\n",addr); fprintf(stderr,"read16(0x%08X), abort\n",addr);
exit(1); exit(1);
} }
//------------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 Thumbulator::read32 ( uInt32 addr ) uInt32 Thumbulator::read32 ( uInt32 addr )
{ {
uInt32 data; uInt32 data;
if(DBUG) fprintf(stderr,"read32(0x%08X)=",addr); if(DBUG)
fprintf(stderr,"read32(0x%08X)=",addr);
switch(addr&0xF0000000) switch(addr&0xF0000000)
{ {
case 0x00000000: //ROM case 0x00000000: //ROM
@ -255,44 +276,51 @@ if(DBUG) fprintf(stderr,"read32(0x%08X)=",addr);
data =read16(addr+2); data =read16(addr+2);
data<<=16; data<<=16;
data|=read16(addr+0); data|=read16(addr+0);
if(DBUG) fprintf(stderr,"0x%08X\n",data); if(DBUG)
fprintf(stderr,"0x%08X\n",data);
return(data); return(data);
} }
fprintf(stderr,"read32(0x%08X), abort\n",addr); fprintf(stderr,"read32(0x%08X), abort\n",addr);
exit(1); exit(1);
} }
//------------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 Thumbulator::read_register ( uInt32 reg ) uInt32 Thumbulator::read_register ( uInt32 reg )
{ {
uInt32 data; uInt32 data;
reg&=0xF; reg&=0xF;
if(DBUG) fprintf(stderr,"read_register(%u)=",reg); if(DBUG)
fprintf(stderr,"read_register(%u)=",reg);
switch(cpsr&0x1F) switch(cpsr&0x1F)
{ {
case MODE_SVC: case MODE_SVC:
switch(reg) switch(reg) // TODO (SA) - does this do anything other than default?
{ {
default: data=reg_sys[reg]; break; default: data=reg_sys[reg]; break;
case 13: case 14: data=reg_svc[reg]; break; case 13: case 14: data=reg_svc[reg]; break;
} }
if(DBUG) fprintf(stderr,"0x%08X\n",data); if(DBUG)
fprintf(stderr,"0x%08X\n",data);
return(data); return(data);
} }
fprintf(stderr,"invalid cpsr mode 0x%08X\n",cpsr); fprintf(stderr,"invalid cpsr mode 0x%08X\n",cpsr);
exit(1); exit(1);
} }
//------------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 Thumbulator::write_register ( uInt32 reg, uInt32 data ) uInt32 Thumbulator::write_register ( uInt32 reg, uInt32 data )
{ {
reg&=0xF; reg&=0xF;
if(DBUG) fprintf(stderr,"write_register(%u,0x%08X)\n",reg,data);
if(DBUG)
fprintf(stderr,"write_register(%u,0x%08X)\n",reg,data);
switch(cpsr&0x1F) switch(cpsr&0x1F)
{ {
case MODE_SVC: case MODE_SVC:
switch(reg) switch(reg) // TODO (SA) - does this do anything other than default?
{ {
default: reg_sys[reg]=data; break; default: reg_sys[reg]=data; break;
case 13: case 14: reg_svc[reg]=data; break; case 13: case 14: reg_svc[reg]=data; break;
@ -303,19 +331,21 @@ if(DBUG) fprintf(stderr,"write_register(%u,0x%08X)\n",reg,data);
exit(1); exit(1);
} }
//------------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Thumbulator::do_zflag ( uInt32 x ) void Thumbulator::do_zflag ( uInt32 x )
{ {
if(x==0) cpsr|=CPSR_Z; else cpsr&=~CPSR_Z; if(x==0) cpsr|=CPSR_Z;
else cpsr&=~CPSR_Z;
} }
//------------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Thumbulator::do_nflag ( uInt32 x ) void Thumbulator::do_nflag ( uInt32 x )
{ {
if(x&0x80000000) cpsr|=CPSR_N; else cpsr&=~CPSR_N; if(x&0x80000000) cpsr|=CPSR_N;
else cpsr&=~CPSR_N;
} }
//------------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Thumbulator::do_cflag ( uInt32 a, uInt32 b, uInt32 c ) void Thumbulator::do_cflag ( uInt32 a, uInt32 b, uInt32 c )
{ {
uInt32 rc; uInt32 rc;
@ -323,61 +353,66 @@ void Thumbulator::do_cflag ( uInt32 a, uInt32 b, uInt32 c )
cpsr&=~CPSR_C; cpsr&=~CPSR_C;
rc=(a&0x7FFFFFFF)+(b&0x7FFFFFFF)+c; //carry in rc=(a&0x7FFFFFFF)+(b&0x7FFFFFFF)+c; //carry in
rc = (rc>>31)+(a>>31)+(b>>31); //carry out rc = (rc>>31)+(a>>31)+(b>>31); //carry out
if(rc&2) cpsr|=CPSR_C; if(rc&2)
cpsr|=CPSR_C;
} }
//------------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Thumbulator::do_sub_vflag ( uInt32 a, uInt32 b, uInt32 c ) void Thumbulator::do_sub_vflag ( uInt32 a, uInt32 b, uInt32 c )
{ {
cpsr&=~CPSR_V; cpsr&=~CPSR_V;
//if the sign bits are different //if the sign bits are different
if((a&0x80000000)^(b&0x80000000)) if((a&0x80000000)^(b&0x80000000))
{ {
//and result matches b //and result matches b
if((b&0x80000000)==(c&0x80000000)) cpsr|=CPSR_V; if((b&0x80000000)==(c&0x80000000))
cpsr|=CPSR_V;
} }
} }
//------------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Thumbulator::do_add_vflag ( uInt32 a, uInt32 b, uInt32 c ) void Thumbulator::do_add_vflag ( uInt32 a, uInt32 b, uInt32 c )
{ {
cpsr&=~CPSR_V; cpsr&=~CPSR_V;
//if sign bits are the same //if sign bits are the same
if((a&0x80000000)==(b&0x80000000)) if((a&0x80000000)==(b&0x80000000))
{ {
//and the result is different //and the result is different
if((b&0x80000000)!=(c&0x80000000)) cpsr|=CPSR_V; if((b&0x80000000)!=(c&0x80000000))
cpsr|=CPSR_V;
} }
} }
//------------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Thumbulator::do_cflag_bit ( uInt32 x ) void Thumbulator::do_cflag_bit ( uInt32 x )
{ {
if(x) cpsr|=CPSR_C; else cpsr&=~CPSR_C; if(x) cpsr|=CPSR_C;
else cpsr&=~CPSR_C;
} }
//------------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Thumbulator::do_vflag_bit ( uInt32 x ) void Thumbulator::do_vflag_bit ( uInt32 x )
{ {
if(x) cpsr|=CPSR_V; else cpsr&=~CPSR_V; if(x) cpsr|=CPSR_V;
else cpsr&=~CPSR_V;
} }
//------------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Thumbulator::execute ( void ) int Thumbulator::execute ( void )
{ {
uInt32 pc; uInt32 pc, sp, inst,
uInt32 sp; ra,rb,rc,
uInt32 inst; rm,rd,rn,rs,
op;
uInt32 ra,rb,rc;
uInt32 rm,rd,rn,rs;
uInt32 op;
pc=read_register(15); pc=read_register(15);
inst=fetch16(pc-2); inst=fetch16(pc-2);
pc+=2; pc+=2;
write_register(15,pc); write_register(15,pc);
if(DISS) fprintf(stderr,"0x%08X: 0x%04X ",(pc-5),inst); if(DISS)
fprintf(stderr,"0x%08X: 0x%04X ",(pc-5),inst);
instructions++; instructions++;
@ -386,11 +421,13 @@ if(DISS) fprintf(stderr,"0x%08X: 0x%04X ",(pc-5),inst);
{ {
rd=(inst>>0)&0x07; rd=(inst>>0)&0x07;
rm=(inst>>3)&0x07; rm=(inst>>3)&0x07;
if(DISS) fprintf(stderr,"adc r%u,r%u\n",rd,rm); if(DISS)
fprintf(stderr,"adc r%u,r%u\n",rd,rm);
ra=read_register(rd); ra=read_register(rd);
rb=read_register(rm); rb=read_register(rm);
rc=ra+rb; rc=ra+rb;
if(cpsr&CPSR_C) rc++; if(cpsr&CPSR_C)
rc++;
write_register(rd,rc); write_register(rd,rc);
do_nflag(rc); do_nflag(rc);
do_zflag(rc); do_zflag(rc);
@ -408,10 +445,11 @@ if(DISS) fprintf(stderr,"adc r%u,r%u\n",rd,rm);
rb=(inst>>6)&0x7; rb=(inst>>6)&0x7;
if(rb) if(rb)
{ {
if(DISS) fprintf(stderr,"adds r%u,r%u,#0x%X\n",rd,rn,rb); if(DISS)
fprintf(stderr,"adds r%u,r%u,#0x%X\n",rd,rn,rb);
ra=read_register(rn); ra=read_register(rn);
rc=ra+rb; rc=ra+rb;
//fprintf(stderr,"0x%08X = 0x%08X + 0x%08X\n",rc,ra,rb); //fprintf(stderr,"0x%08X = 0x%08X + 0x%08X\n",rc,ra,rb);
write_register(rd,rc); write_register(rd,rc);
do_nflag(rc); do_nflag(rc);
do_zflag(rc); do_zflag(rc);
@ -430,7 +468,8 @@ if(DISS) fprintf(stderr,"adds r%u,r%u,#0x%X\n",rd,rn,rb);
{ {
rb=(inst>>0)&0xFF; rb=(inst>>0)&0xFF;
rd=(inst>>8)&0x7; rd=(inst>>8)&0x7;
if(DISS) fprintf(stderr,"adds r%u,#0x%02X\n",rd,rb); if(DISS)
fprintf(stderr,"adds r%u,#0x%02X\n",rd,rb);
ra=read_register(rd); ra=read_register(rd);
rc=ra+rb; rc=ra+rb;
write_register(rd,rc); write_register(rd,rc);
@ -447,7 +486,8 @@ if(DISS) fprintf(stderr,"adds r%u,#0x%02X\n",rd,rb);
rd=(inst>>0)&0x7; rd=(inst>>0)&0x7;
rn=(inst>>3)&0x7; rn=(inst>>3)&0x7;
rm=(inst>>6)&0x7; rm=(inst>>6)&0x7;
if(DISS) fprintf(stderr,"adds r%u,r%u,r%u\n",rd,rn,rm); if(DISS)
fprintf(stderr,"adds r%u,r%u,r%u\n",rd,rn,rm);
ra=read_register(rn); ra=read_register(rn);
rb=read_register(rm); rb=read_register(rm);
rc=ra+rb; rc=ra+rb;
@ -469,11 +509,12 @@ if(DISS) fprintf(stderr,"adds r%u,r%u,r%u\n",rd,rn,rm);
rd=(inst>>0)&0x7; rd=(inst>>0)&0x7;
rd|=(inst>>4)&0x8; rd|=(inst>>4)&0x8;
rm=(inst>>3)&0xF; rm=(inst>>3)&0xF;
if(DISS) fprintf(stderr,"add r%u,r%u\n",rd,rm); if(DISS)
fprintf(stderr,"add r%u,r%u\n",rd,rm);
ra=read_register(rd); ra=read_register(rd);
rb=read_register(rm); rb=read_register(rm);
rc=ra+rb; rc=ra+rb;
//fprintf(stderr,"0x%08X = 0x%08X + 0x%08X\n",rc,ra,rb); //fprintf(stderr,"0x%08X = 0x%08X + 0x%08X\n",rc,ra,rb);
write_register(rd,rc); write_register(rd,rc);
return(0); return(0);
} }
@ -484,7 +525,8 @@ if(DISS) fprintf(stderr,"add r%u,r%u\n",rd,rm);
rb=(inst>>0)&0xFF; rb=(inst>>0)&0xFF;
rd=(inst>>8)&0x7; rd=(inst>>8)&0x7;
rb<<=2; rb<<=2;
if(DISS) fprintf(stderr,"add r%u,PC,#0x%02X\n",rd,rb); if(DISS)
fprintf(stderr,"add r%u,PC,#0x%02X\n",rd,rb);
ra=read_register(15); ra=read_register(15);
rc=(ra&(~3))+rb; rc=(ra&(~3))+rb;
write_register(rd,rc); write_register(rd,rc);
@ -497,7 +539,8 @@ if(DISS) fprintf(stderr,"add r%u,PC,#0x%02X\n",rd,rb);
rb=(inst>>0)&0xFF; rb=(inst>>0)&0xFF;
rd=(inst>>8)&0x7; rd=(inst>>8)&0x7;
rb<<=2; rb<<=2;
if(DISS) fprintf(stderr,"add r%u,SP,#0x%02X\n",rd,rb); if(DISS)
fprintf(stderr,"add r%u,SP,#0x%02X\n",rd,rb);
ra=read_register(13); ra=read_register(13);
rc=ra+rb; rc=ra+rb;
write_register(rd,rc); write_register(rd,rc);
@ -509,7 +552,8 @@ if(DISS) fprintf(stderr,"add r%u,SP,#0x%02X\n",rd,rb);
{ {
rb=(inst>>0)&0x7F; rb=(inst>>0)&0x7F;
rb<<=2; rb<<=2;
if(DISS) fprintf(stderr,"add SP,#0x%02X\n",rb); if(DISS)
fprintf(stderr,"add SP,#0x%02X\n",rb);
ra=read_register(13); ra=read_register(13);
rc=ra+rb; rc=ra+rb;
write_register(13,rc); write_register(13,rc);
@ -521,7 +565,8 @@ if(DISS) fprintf(stderr,"add SP,#0x%02X\n",rb);
{ {
rd=(inst>>0)&0x7; rd=(inst>>0)&0x7;
rm=(inst>>3)&0x7; rm=(inst>>3)&0x7;
if(DISS) fprintf(stderr,"ands r%u,r%u\n",rd,rm); if(DISS)
fprintf(stderr,"ands r%u,r%u\n",rd,rm);
ra=read_register(rd); ra=read_register(rd);
rb=read_register(rm); rb=read_register(rm);
rc=ra&rb; rc=ra&rb;
@ -537,7 +582,8 @@ if(DISS) fprintf(stderr,"ands r%u,r%u\n",rd,rm);
rd=(inst>>0)&0x07; rd=(inst>>0)&0x07;
rm=(inst>>3)&0x07; rm=(inst>>3)&0x07;
rb=(inst>>6)&0x1F; rb=(inst>>6)&0x1F;
if(DISS) fprintf(stderr,"asrs r%u,r%u,#0x%X\n",rd,rm,rb); if(DISS)
fprintf(stderr,"asrs r%u,r%u,#0x%X\n",rd,rm,rb);
rc=read_register(rm); rc=read_register(rm);
if(rb==0) if(rb==0)
{ {
@ -573,7 +619,8 @@ if(DISS) fprintf(stderr,"asrs r%u,r%u,#0x%X\n",rd,rm,rb);
{ {
rd=(inst>>0)&0x07; rd=(inst>>0)&0x07;
rs=(inst>>3)&0x07; rs=(inst>>3)&0x07;
if(DISS) fprintf(stderr,"asrs r%u,r%u\n",rd,rs); if(DISS)
fprintf(stderr,"asrs r%u,r%u\n",rd,rs);
rc=read_register(rd); rc=read_register(rd);
rb=read_register(rs); rb=read_register(rs);
rb&=0xFF; rb&=0xFF;
@ -613,7 +660,8 @@ if(DISS) fprintf(stderr,"asrs r%u,r%u\n",rd,rs);
if((inst&0xF000)==0xD000) if((inst&0xF000)==0xD000)
{ {
rb=(inst>>0)&0xFF; rb=(inst>>0)&0xFF;
if(rb&0x80) rb|=(~0)<<8; if(rb&0x80)
rb|=(~0)<<8;
op=(inst>>8)&0xF; op=(inst>>8)&0xF;
rb<<=1; rb<<=1;
rb+=pc; rb+=pc;
@ -621,7 +669,8 @@ if(DISS) fprintf(stderr,"asrs r%u,r%u\n",rd,rs);
switch(op) switch(op)
{ {
case 0x0: //b eq z set case 0x0: //b eq z set
if(DISS) fprintf(stderr,"beq 0x%08X\n",rb-3); if(DISS)
fprintf(stderr,"beq 0x%08X\n",rb-3);
if(cpsr&CPSR_Z) if(cpsr&CPSR_Z)
{ {
write_register(15,rb); write_register(15,rb);
@ -629,7 +678,8 @@ if(DISS) fprintf(stderr,"beq 0x%08X\n",rb-3);
return(0); return(0);
case 0x1: //b ne z clear case 0x1: //b ne z clear
if(DISS) fprintf(stderr,"bne 0x%08X\n",rb-3); if(DISS)
fprintf(stderr,"bne 0x%08X\n",rb-3);
if(!(cpsr&CPSR_Z)) if(!(cpsr&CPSR_Z))
{ {
write_register(15,rb); write_register(15,rb);
@ -637,7 +687,8 @@ if(DISS) fprintf(stderr,"bne 0x%08X\n",rb-3);
return(0); return(0);
case 0x2: //b cs c set case 0x2: //b cs c set
if(DISS) fprintf(stderr,"bcs 0x%08X\n",rb-3); if(DISS)
fprintf(stderr,"bcs 0x%08X\n",rb-3);
if(cpsr&CPSR_C) if(cpsr&CPSR_C)
{ {
write_register(15,rb); write_register(15,rb);
@ -645,7 +696,8 @@ if(DISS) fprintf(stderr,"bcs 0x%08X\n",rb-3);
return(0); return(0);
case 0x3: //b cc c clear case 0x3: //b cc c clear
if(DISS) fprintf(stderr,"bcc 0x%08X\n",rb-3); if(DISS)
fprintf(stderr,"bcc 0x%08X\n",rb-3);
if(!(cpsr&CPSR_C)) if(!(cpsr&CPSR_C))
{ {
write_register(15,rb); write_register(15,rb);
@ -653,7 +705,8 @@ if(DISS) fprintf(stderr,"bcc 0x%08X\n",rb-3);
return(0); return(0);
case 0x4: //b mi n set case 0x4: //b mi n set
if(DISS) fprintf(stderr,"bmi 0x%08X\n",rb-3); if(DISS)
fprintf(stderr,"bmi 0x%08X\n",rb-3);
if(cpsr&CPSR_N) if(cpsr&CPSR_N)
{ {
write_register(15,rb); write_register(15,rb);
@ -661,16 +714,17 @@ if(DISS) fprintf(stderr,"bmi 0x%08X\n",rb-3);
return(0); return(0);
case 0x5: //b pl n clear case 0x5: //b pl n clear
if(DISS) fprintf(stderr,"bpl 0x%08X\n",rb-3); if(DISS)
fprintf(stderr,"bpl 0x%08X\n",rb-3);
if(!(cpsr&CPSR_N)) if(!(cpsr&CPSR_N))
{ {
write_register(15,rb); write_register(15,rb);
} }
return(0); return(0);
case 0x6: //b vs v set case 0x6: //b vs v set
if(DISS) fprintf(stderr,"bvs 0x%08X\n",rb-3); if(DISS)
fprintf(stderr,"bvs 0x%08X\n",rb-3);
if(cpsr&CPSR_V) if(cpsr&CPSR_V)
{ {
write_register(15,rb); write_register(15,rb);
@ -678,16 +732,17 @@ if(DISS) fprintf(stderr,"bvs 0x%08X\n",rb-3);
return(0); return(0);
case 0x7: //b vc v clear case 0x7: //b vc v clear
if(DISS) fprintf(stderr,"bvc 0x%08X\n",rb-3); if(DISS)
fprintf(stderr,"bvc 0x%08X\n",rb-3);
if(!(cpsr&CPSR_V)) if(!(cpsr&CPSR_V))
{ {
write_register(15,rb); write_register(15,rb);
} }
return(0); return(0);
case 0x8: //b hi c set z clear case 0x8: //b hi c set z clear
if(DISS) fprintf(stderr,"bhi 0x%08X\n",rb-3); if(DISS)
fprintf(stderr,"bhi 0x%08X\n",rb-3);
if((cpsr&CPSR_C)&&(!(cpsr&CPSR_Z))) if((cpsr&CPSR_C)&&(!(cpsr&CPSR_Z)))
{ {
write_register(15,rb); write_register(15,rb);
@ -695,7 +750,8 @@ if(DISS) fprintf(stderr,"bhi 0x%08X\n",rb-3);
return(0); return(0);
case 0x9: //b ls c clear or z set case 0x9: //b ls c clear or z set
if(DISS) fprintf(stderr,"bls 0x%08X\n",rb-3); if(DISS)
fprintf(stderr,"bls 0x%08X\n",rb-3);
if((cpsr&CPSR_Z)||(!(cpsr&CPSR_C))) if((cpsr&CPSR_Z)||(!(cpsr&CPSR_C)))
{ {
write_register(15,rb); write_register(15,rb);
@ -703,7 +759,8 @@ if(DISS) fprintf(stderr,"bls 0x%08X\n",rb-3);
return(0); return(0);
case 0xA: //b ge N == V case 0xA: //b ge N == V
if(DISS) fprintf(stderr,"bge 0x%08X\n",rb-3); if(DISS)
fprintf(stderr,"bge 0x%08X\n",rb-3);
ra=0; ra=0;
if( (cpsr&CPSR_N) && (cpsr&CPSR_V) ) ra++; if( (cpsr&CPSR_N) && (cpsr&CPSR_V) ) ra++;
if((!(cpsr&CPSR_N))&&(!(cpsr&CPSR_V))) ra++; if((!(cpsr&CPSR_N))&&(!(cpsr&CPSR_V))) ra++;
@ -714,7 +771,8 @@ if(DISS) fprintf(stderr,"bge 0x%08X\n",rb-3);
return(0); return(0);
case 0xB: //b lt N != V case 0xB: //b lt N != V
if(DISS) fprintf(stderr,"blt 0x%08X\n",rb-3); if(DISS)
fprintf(stderr,"blt 0x%08X\n",rb-3);
ra=0; ra=0;
if((!(cpsr&CPSR_N))&&(cpsr&CPSR_V)) ra++; if((!(cpsr&CPSR_N))&&(cpsr&CPSR_V)) ra++;
if((!(cpsr&CPSR_V))&&(cpsr&CPSR_N)) ra++; if((!(cpsr&CPSR_V))&&(cpsr&CPSR_N)) ra++;
@ -725,7 +783,8 @@ if(DISS) fprintf(stderr,"blt 0x%08X\n",rb-3);
return(0); return(0);
case 0xC: //b gt Z==0 and N == V case 0xC: //b gt Z==0 and N == V
if(DISS) fprintf(stderr,"bgt 0x%08X\n",rb-3); if(DISS)
fprintf(stderr,"bgt 0x%08X\n",rb-3);
ra=0; ra=0;
if( (cpsr&CPSR_N) && (cpsr&CPSR_V) ) ra++; if( (cpsr&CPSR_N) && (cpsr&CPSR_V) ) ra++;
if((!(cpsr&CPSR_N))&&(!(cpsr&CPSR_V))) ra++; if((!(cpsr&CPSR_N))&&(!(cpsr&CPSR_V))) ra++;
@ -737,7 +796,8 @@ if(DISS) fprintf(stderr,"bgt 0x%08X\n",rb-3);
return(0); return(0);
case 0xD: //b le Z==1 or N != V case 0xD: //b le Z==1 or N != V
if(DISS) fprintf(stderr,"ble 0x%08X\n",rb-3); if(DISS)
fprintf(stderr,"ble 0x%08X\n",rb-3);
ra=0; ra=0;
if((!(cpsr&CPSR_N))&&(cpsr&CPSR_V)) ra++; if((!(cpsr&CPSR_N))&&(cpsr&CPSR_V)) ra++;
if((!(cpsr&CPSR_V))&&(cpsr&CPSR_N)) ra++; if((!(cpsr&CPSR_V))&&(cpsr&CPSR_N)) ra++;
@ -751,6 +811,7 @@ if(DISS) fprintf(stderr,"ble 0x%08X\n",rb-3);
case 0xE: case 0xE:
//undefined instruction //undefined instruction
break; break;
case 0xF: case 0xF:
//swi //swi
break; break;
@ -1884,7 +1945,7 @@ if(DISS) fprintf(stderr,"uxth r%u,r%u\n",rd,rm);
return(1); return(1);
} }
//------------------------------------------------------------------- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Thumbulator::reset ( void ) int Thumbulator::reset ( void )
{ {
//memset(ram,0xFF,sizeof(ram)); //memset(ram,0xFF,sizeof(ram));