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.
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...?
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 }
...but right now I need to know the status of the carrybit.
That's most probably an incorrect belief.
Note that even if you find a method for reading the carry flag, there's absolutely no guarantee that by the time that method actually accesses it the carry still contains the same state you were looking for. Compiled C code owns that flag --- it'll do with it whatever it wants, up to and including using it for some other purpose in the meantime.
In a nutshell, when you think you need the carry flag (or the content of any general-purpose register) from inside a C program, you're still thinking in assembler. And that will not work.
That is very probably an incorrect belief.
So, instead, why don't you tell us what you're actually trying to achieve here?
www.catb.org/.../smart-questions.html
Point taken - didn't know that C works that way (owning the carry bit). Would it work, if the prior calculation was in assembler, too? 'Cause I thought that the codepart written in assembler will be transcoded to machinecode in a coherent way...won't it?
I wanted to avoid the method Per suggested, because I was just curious if it is possible to avoid it. That was my single goal: Curiosity :-) . Stupid, I guess.
Now I will just do it the standard way without using assembler.
Thanks a lot for your help!
Marcus, I tried yours, too.
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
The ARM compiler is "smart" enough that it merges the assembler instructions with the instructions generated from the C code. Then it performs a number of optimization steps.
So inlined assembler need not survive unmodified to the finaly binary.
If you want to implement a large-number library while using the carry flag, then you should implement the evaluations fully in assembler.
Note that a comparison "if (a >= b)" is very fast on the ARM processor, and the optimizer will recognize that it's the same variables in the comparison as in the actual subtraction. So no extra memory accesses. Just a comparison. And the optimizer might even note that the comparison and the subtraction are basically the same thing, and the code is still interested in a subtraction.
When programming in C - do stay with C. Do not try to fool the optimizer by taking short cuts. When you are not happy with C, because of special needs: write full functions in assembler.
That's the whole point of any high-level language (HLL) - you delegate responsibility for the low-level detail to the compiler.
Indeed!
See: http://www.keil.com/forum/17856/
Thanks a lot guys, I will stay with C :-]