-1

My question is about representing the carry-bit and arithmetic shift right in my ARM thumb simulation function. do I have to create a boolian variable if the op code is the binary bit-value of ADC then i add the boolian variable as 1 and if not then it's SBC? also, how to represent the logic of ASR in my code?

format 4

instructions of format 4 by opcode

case 2:           // format 4
    op = (instr >> 6) & 0xF;
    rd = instr & 7;
    rs = (instr >> 3) & 7;
    if (op == 0)
    {
        cout << " AND " << rd << "," << rs << endl;
        Regs[rd] = Regs[rd] & Regs[rs];
    }
    else if (op == 1)
    {
        cout << " EOR " << rd << "," << rs << endl;
        Regs[rd] = Regs[rd] ^ Regs[rs];
    }
    else if (op == 2)
    {
        cout << " LSL " << rd << "," << rs << endl;
        Regs[rd] = Regs[rd] << Regs[rs];
    }
    else if (op == 3)
    {
        cout << " LSR " << rd << "," << rs << endl;
        Regs[rd] = Regs[rd] >> Regs[rs];
    }
    **else if (op == 4)
    {
        cout << " ASR  " << rd << "," << rs << endl;
        Regs[rd] = Regs[rd] >> Regs[rs];
    }**
    **else if (op == 5)
    {
        cout << " ADC " << rd << "," << rs << endl;
        Regs[rd] = Regs[rd] & Regs[rs];
    }
    else if (op == 6)
    {
        cout << " SBC " << rd << "," << rs << endl;
        Regs[rd] = Regs[rd] - Regs[rs];
    }**
    break;
Nisback
  • 11
  • 1
  • 6
  • `op = (instr >> 6) & 3; rd = instr & 0xF;` looks weird compared to the number of bits in the image. – MikeCAT Jul 10 '20 at 13:22
  • edited it. I replaced the mask of rd with op by mistake sorry for that. – Nisback Jul 10 '20 at 13:27
  • 1
    I don't understand your question regarding `ADC` and `SBC`. They're separate opcodes, so there should be no problem telling them apart. As for how to handle the carry, you really should implement the status registers (CPSR, SPSR). I also suggest that you get the _ARM Architecture Reference Manual_ (e.g. document ARM DDI 0100E) which has detailed descriptions of each of these instructions and a lot of other things. – Michael Jul 10 '20 at 14:13
  • 1
    `ASR` is right shift operation in which the highest bit is copied to upper bits instead of filling them with 0. What is the type of `Regs`? – MikeCAT Jul 10 '20 at 14:15
  • You forgot to add in the carry bit on ADC and subtract the borrow from SBC. ARMs shifters have some rules you cant blindly just shift the input amount, you have to read the arm documentation. – old_timer Jul 12 '20 at 05:29
  • the flags are bits not booleans, if you feel the need to use booleans, fine that just adds even more code. – old_timer Jul 12 '20 at 05:31
  • You are writing too much code without following the arm documentation, you will have to come back and revisit a lot of this code. – old_timer Jul 12 '20 at 05:32
  • Looking at your images, you are definitely using the wrong documentation. – old_timer Jul 12 '20 at 05:34
  • Stop writing code. Get the right documentation. Learn about carry, borrow, and signed overflow. Figure out how to compute them, then start writing code again. Use all of the ARM ARMs the original, now known as the armv5 ARM ARM is for a number of things the better one, but the armv6-m and armv7-m help as well. – old_timer Jul 12 '20 at 05:44

1 Answers1

0

I'll just give you some working code to ponder.

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);
    }
halfer
  • 19,824
  • 17
  • 99
  • 186
old_timer
  • 69,149
  • 8
  • 89
  • 168