Я просто дам вам для размышления рабочий код.
void do_cflag ( unsigned int a, unsigned int b, unsigned int c )
{
unsigned int rc;
cpsr&=~CPSR_C;
rc=(a&0x7FFFFFFF)+(b&0x7FFFFFFF)+c; //carry in
rc = (rc>>31)+(a>>31)+(b>>31); //carry out
if(rc&2) cpsr|=CPSR_C;
}
void do_cflag_bit ( unsigned int x )
{
if(x) cpsr|=CPSR_C; else cpsr&=~CPSR_C;
}
...
//SUB(1)
if((inst&0xFE00)==0x1E00)
{
rd=(inst>>0)&7;
rn=(inst>>3)&7;
rb=(inst>>6)&7;
if(DISS) fprintf(stderr,"subs r%u,r%u,#0x%X\n",rd,rn,rb);
ra=read_register(rn);
rc=ra-rb;
write_register(rd,rc);
do_nflag(rc);
do_zflag(rc);
do_cflag(ra,~rb,1);
do_vflag(ra,~rb,1);
return(0);
}
//SBC
if((inst&0xFFC0)==0x4180)
{
rd=(inst>>0)&0x7;
rm=(inst>>3)&0x7;
if(DISS) fprintf(stderr,"sbc r%u,r%u\n",rd,rm);
ra=read_register(rd);
rb=read_register(rm);
rc=ra-rb;
if(!(cpsr&CPSR_C)) rc--;
write_register(rd,rc);
do_nflag(rc);
do_zflag(rc);
if(cpsr&CPSR_C)
{
do_cflag(ra,~rb,1);
do_vflag(ra,~rb,1);
}
else
{
do_cflag(ra,~rb,0);
do_vflag(ra,~rb,0);
}
return(0);
}
//ADC
if((inst&0xFFC0)==0x4140)
{
rd=(inst>>0)&0x07;
rm=(inst>>3)&0x07;
if(DISS) fprintf(stderr,"adc r%u,r%u\n",rd,rm);
ra=read_register(rd);
rb=read_register(rm);
rc=ra+rb;
if(cpsr&CPSR_C) rc++;
write_register(rd,rc);
do_nflag(rc);
do_zflag(rc);
if(cpsr&CPSR_C) { do_cflag(ra,rb,1); do_vflag(ra,rb,1); }
else { do_cflag(ra,rb,0); do_vflag(ra,rb,0); }
return(0);
}
//ADD(3) three registers
if((inst&0xFE00)==0x1800)
{
rd=(inst>>0)&0x7;
rn=(inst>>3)&0x7;
rm=(inst>>6)&0x7;
if(DISS) fprintf(stderr,"adds r%u,r%u,r%u\n",rd,rn,rm);
ra=read_register(rn);
rb=read_register(rm);
rc=ra+rb;
write_register(rd,rc);
do_nflag(rc);
do_zflag(rc);
do_cflag(ra,rb,0);
do_vflag(ra,rb,0);
return(0);
}
//ASR(2) two register
if((inst&0xFFC0)==0x4100)
{
rd=(inst>>0)&0x07;
rs=(inst>>3)&0x07;
if(DISS) fprintf(stderr,"asrs r%u,r%u\n",rd,rs);
rc=read_register(rd);
rb=read_register(rs);
rb&=0xFF;
if(rb==0)
{
}
else if(rb<32)
{
do_cflag_bit(rc&(1<<(rb-1)));
ra=rc&0x80000000;
rc>>=rb;
if(ra) //asr, sign is shifted in
{
rc|=(~0)<<(32-rb);
}
}
else
{
if(rc&0x80000000)
{
do_cflag_bit(1);
rc=(~0);
}
else
{
do_cflag_bit(0);
rc=0;
}
}
write_register(rd,rc);
do_nflag(rc);
do_zflag(rc);
return(0);
}