0

I am trying to get the math routines from Compiler RT working with a GCC toolchain for the ARM Cortex M3/M4F processors (armv7m and armv7em with fpu).

I have everything compiling (with minimal changes) except two lines of code (msr CPSR_f, ip and msr CPSR_f, #APSR_C) in the functions below

#define APSR_Z (1 << 30)
#define APSR_C (1 << 29)

DEFINE_COMPILERRT_FUNCTION(__aeabi_cfcmple)
    // Per the RTABI, this function must preserve r0-r11.
    // Save lr in the same instruction for compactness
    push {r0-r3, lr}

    bl __aeabi_fcmplt
    cmp r0, #1
    IT(eq)
    moveq ip, #0
    beq 1f

    ldm sp, {r0-r3}
    bl __aeabi_fcmpeq
    cmp r0, #1
    IT(eq)
    moveq ip, #(APSR_C | APSR_Z)
    IT(ne)
    movne ip, #(APSR_C)

1:
    msr CPSR_f, ip
    pop {r0-r3}
    POP_PC()
END_COMPILERRT_FUNCTION(__aeabi_cfcmple)

And the other function:

DEFINE_COMPILERRT_FUNCTION(__aeabi_cfcmpeq)
    push {r0-r3, lr}
    bl __aeabi_cfcmpeq_check_nan
    cmp r0, #1
    pop {r0-r3, lr}

    // NaN has been ruled out, so __aeabi_cfcmple can't trap
    bne __aeabi_cfcmple

    msr CPSR_f, #APSR_C
    JMP(lr)
END_COMPILERRT_FUNCTION(__aeabi_cfcmpeq)

The CPSR_f notation is not available on the armv7m instruction set. How do I convert msr CPSR_f, ip and msr CPSR_f, #APSR_C to armv7m code (should be the same for armv7em)?

artless noise
  • 21,212
  • 6
  • 68
  • 105
TylerG
  • 13
  • 2

1 Answers1

0

You need to use the MOV APSR, Rm instruction. The Cortex-M processors basically don't have a CPSR, and the APSR register acts as its replacement as far as the condition codes go.

The first function is easy to fix, since it uses a register as the source operand. Just replace msr CPSR_f, ip with msr APSR_nzcvq, ip. The second function would require going through a register. Assuming the IP register can be clobbered just like it is in the first function you can use:

mov ip, #APSR_C
msr APSR_nzcvq, ip
Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
  • How do I handle the CPSR_f portion? The _f means that it only affects the top 8 bits (I think). So I would need to read APSR, clear the top 8 bits, then write it back. Is 3 instructions the fastest and only way to do that? – TylerG Apr 24 '16 at 03:59
  • The `_f` part means it only affects the condition flags bits, which is all that APSR is used for. The other parts of the CPSR are in other registers or don't exist. You don't need to anything other than what I described. – Ross Ridge Apr 24 '16 at 04:01
  • I am trying this out. I think I need `msr APSR, ip` rather than `mov APSR, ip` but then I get a "writing to APSR without specifying a bitmask is deprecated" error. So I tried `msr APSR_nzcvq, ip` and that compiled OK. Does that look right? – TylerG Apr 24 '16 at 05:25
  • @TylerG Yah, fixed my mistake Didn't know you needed the `_nzcvq`, the documentation I was looking at didn't mention it. – Ross Ridge Apr 24 '16 at 05:47