1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
static inline real_t DESCALE(int val, int shift)
{
    int out;
    asm volatile(
        /* clear flags */
        "tst lr, #256\n\t"
        /* If shift is negative, this will set Z, if positive it will set C
           according to the highest bit shifted out */
        "movs %[out], %[val], lsr %[shift]\n\t"
        /* Invert shift */
        "rsb %[shift], %[shift], #0\n\t"
        /* Add the rounding bit */
        "adc %[out], %[out], #0\n\t"
        /* If shift is negative, the initial movs produced a zero result, and
           this moveq will now write val << -shift to out */
        "moveq %[out], %[val], lsl %[shift]"
        : [out]   "=&r" (out),
          [shift] "+r" (shift)
        : [val] "r" (val)
    );
    return out;
}