This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Using C and reading CPU Register (Carry-Flag) via assembler

Hi smart guys out there,

I am using µVision with TIs eval-kit LM3S9B92. I use µVisions C-Compiler.

I learned that it is not possible to read the CPU-Registers with C and I have to use asembler for that.

I have no idea of asembler and actually I don't work with it in future and I hope I never have to again :-) ...but right now I need to know the status of the carrybit.

So all I am asking is for a piece of code that gets me the status of bit 29 in the register 17 :) and how to implement that in my project.

I hope this doesn't sound sassy ;-) - at least it isn't meant that way.

Thank you so much.

Parents
  • A little clue:

    int32u __asm processor_in_user_mode(void)
    {
            STMDB   R13!, {R1}
    
            MRS     R0, CPSR
            AND     R0, R0, #0x1F   // the lowest 5 bits of CPSR respresent the processor mode
            MOV             R1, #0x10               // user mode = 0x10
            CMP             R0, R1
            BEQ             not_interrupt_context
    
            LDMIA   R13!, {R1} // restore the file name and the line number.
    
            MOV             R0,     #0x0 // indicate called while not in user mode
    
            BX              LR
    
    not_interrupt_context
    
            // restore original values of R1
            LDMIA   R13!, {R1}
    
            MOV             R0,     #0x1 // indicate called while in user mode
    
            BX              LR
    }
    

    Assuming you are working with an ARM7 core, you are interested in CRSR. What is that according to the user manual...?

Reply
  • A little clue:

    int32u __asm processor_in_user_mode(void)
    {
            STMDB   R13!, {R1}
    
            MRS     R0, CPSR
            AND     R0, R0, #0x1F   // the lowest 5 bits of CPSR respresent the processor mode
            MOV             R1, #0x10               // user mode = 0x10
            CMP             R0, R1
            BEQ             not_interrupt_context
    
            LDMIA   R13!, {R1} // restore the file name and the line number.
    
            MOV             R0,     #0x0 // indicate called while not in user mode
    
            BX              LR
    
    not_interrupt_context
    
            // restore original values of R1
            LDMIA   R13!, {R1}
    
            MOV             R0,     #0x1 // indicate called while in user mode
    
            BX              LR
    }
    

    Assuming you are working with an ARM7 core, you are interested in CRSR. What is that according to the user manual...?

Children
  • For the sake of completeness -

    STMDB   R13!, {R1}
    


    and

    LDMDB   R13!, {R1}
    

    above can be discarded.

  • you are interested in CRSR -> you are interested in CPSR

  • Hey Tamir,
    thanks for your fast reply.

    I am working on an ARM Cortex-M3. CPSR was unknown to the compiler, but APSR wasn't :)
    Anyways, I placed your code (with CPSR changed to APSR) in a new .c file and it compiled without grumping :]

    For evaluation I tried that:

    int
    main(void)
    {
            unsigned long dummy;
            unsigned long a=1000;
            unsigned long b=10000;
    
            dummy = a - b;  //Carry-bit should be set
            UARTprintf("\n: %d \n", processor_in_user_mode);
            dummy = b - a;//Carry-bit shouldn't be set
            UARTprintf("\n: %d \n", processor_in_user_mode);
    

    but both times it prints out '489' which is:

    111101001

    so nothing changed. But register 17 bit 31 is according to the datasheet the carry bit, which should have changed here...
    I also tried PSR instead of APSR: no change

    By the way: CPSR is printed bold in code, PSR or APSR isn't.

  • Hi Susan

    Couple of options:

    Use this standardized CMSIS function portable between popular toolchains

    __get_APSR(void)
    

    Or use MDK/RVCT specific named register variables

    uint32_t apsr __asm("APSR");
    
    if (apsr & APSR_C)
       // do this
    else
       // do that
    

    Hope this helps
    Marcus

  • Note that you can manage quite well without ever knowing the content of the carry bit.

    if (b >= a) {
        b -= a;
        // no borrow
    } else {
        b -= a;
        // handle borrow
    }
    
    unsigned a,b,c;
    c = a+b;
    if (c < a || c < b) {
        // addition overflow
    }
    

  • Marcus, I tried yours, too.

    __get_APSR(void)

    Do I need a special header or include file for this?
    Cause µVision tells me:

    undefined symbol __get_APSR();

    identifier "APSR_C" is undefined, respectively (when trying the other one)

  • __get_APSR() is defined in CMSIS, so yes, you do need to include a header file, namely core_cmFunc.h.

    The identifier APSR_C was just a made up example, perhaps defined as macro, to demonstrate that you need to compare with a numeric value. BTW, CMSIS also defines a structure APSR_Type so that you could perhaps write something like:

    if ((APSR_Type)apsr.b.C)
      // do this
    else
      // do that
    


    But as others have said already: For your purposes, this is completely unnecessary.

    Best regards
    Marcus