1

The ARM Cortex-M4F processor has an instruction that will load an immediate constant into a floating-point register, as in:

      VMOV    S0,+6.75

However, the value of the constant is restricted and must be equal to a value that can be expressed as +/-m x 2-n, where m is an integer in the range 16-31 and n is an integer in the range 0-7. E.g., the above instruction works because you can get 6.75 with m=27 and n=2.

I'd really like to find an algorithm that determines whether or not a particular real number can be represented this way, and if so, gives the corresponding values of m and n.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Dan Lewis
  • 93
  • 8
  • 1
    FWIW, I don't know the answer, but I _can_ deduce that there must exist a straightforward way, because it's precisely what assemblers have to do when they encode such an instruction in the first place. To save a bit of trouble, [here's an assembler](https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gas/config/tc-arm.c;h=061aaa8222d03f6e52953ae3fdcd1e047d7bbee3;hb=HEAD#l4995) - whatever voodoo that's doing would appear to involve having the number as a regular IEEE754 float to start with, which means you might have to start by figuring out whether it can be represented as one of those. – Notlikethat Nov 03 '16 at 23:45
  • If you have the C math library available frexp could be a way to start – dmuir Nov 04 '16 at 08:52

4 Answers4

1

If you like, you can do this by converting to a regular single-precision float, and then examining its bits. All numbers representable by your formula are also representable as floats, but only some floats are representable by your formula.

For any number representable by your formula, the exponent is guaranteed to be between -3 (16*2^-7) and +4 (16*2^0) inclusive and the mantissa is guaranteed to have zeros in all but the top four bits after the decimal. So the byte contained in bits 23-30 inclusive must have a value between 124 and 131 inclusive and bits 0-18 inclusive must be zero. To determine n, subtract the exponent byte from 131; to determine m, use bits 19-22 inclusive and add 16.

Note that this all assumes you know that the number can be stored as a float in the first place.

Sneftel
  • 40,271
  • 12
  • 71
  • 104
1

It's only 8*16*2 = 256 values, so an easy way is to use a hash table. In Python:

D = set()

for m in range(16,32):
    for n in range(8):
        x = m*2.0**-n
        D.add(x)
        D.add(-x)

def iscortexable(x):
    return x in D

Gives

>>> iscortexable(6.75)
True
>>> iscortexable(8.75)
False

A more principled way would be using frexp

from math import frexp

def iscortexable(x):
    if x == 0:
        return False
    m, e = frexp(x)  # 0.5 <= m < 1
    m = m*32         # 16  <= m < 32
    n = -(e - 5)
    return m.is_integer() and 0 <= n <= 7
Simon Byrne
  • 7,694
  • 1
  • 26
  • 50
0

Actually I didnt test it but it looks pretty easy. Take the number multiply it by 1, 2, 4, 8, etc, up to 0x80. Does it result in a whole number/integer between 16 and 31? in this case 6.75 *4 = 27. so m is 27 n is 2. 2.8750 * 8 = 23 so m is 23, n is 3.

float vut; //value under test
float f;
unsigned int nn;
int n;
unsigned int m;

for(nn=0x01;nn<=0x80;nn<<=1)
{
   f=vut*n;
   if(is_an_integer_no_fraction(f))
   {
       m=f;
       if((m>=16)&&(m<=31))
       {
           n=nn;
           n=-n; 
           //FOUND m and n
           break;
       }
   }
}
if(nn>=0x80)
{
    //NOPE doesnt work
}
else
{
    //YEP found m and n
}
ChrisF
  • 134,786
  • 31
  • 255
  • 325
old_timer
  • 69,149
  • 8
  • 89
  • 168
0

Thanks to all of you for your great suggestions. In retrospect, I should probably have provided a bit more context. I teach a course on assembly language programming to college sophomores and use the Cortex-M4F as the target platform. I was trying to find a simple way for them to know when a VMOV immediate was possible. I finally realized (with some embarresment) that there were so few combinations of m and n that the best solution was to just print out all the combinations in the form of a handout. :-)

Thanks again!

Dan –

Dan Lewis
  • 93
  • 8