Search code examples
assemblybinarynormalizationtwos-complementfixed-point

Normalizing a two complement number


I am working on some Tensilica processor and I don't understand the normalization process.

NSA - Normalized Shift Amount

Usage:
    NSA at, as

NSA calculates the left shift amount that will normalize the twos complement contents of address register as and writes this amount (in the range 0 to 31) to address register at.

If as contains 0 or -1, NSA returns 31. Using SSL and SLL to shift as left by the NSA result yields the smallest value for which bits 31 and 30 differ unless as contains 0.

enter image description here

So basically NSA calculate a shift amount value (0...31) and writes to at register.

The question is how it calculates, what does it means normalizing the two complement value from as?

This is not a floating point instruction. In as can be a signed value on 32 bits (31 + sign)

Thanks for clarifications,

EDIT: Should be like this (thanks to Peter Cordes)

0x00000004 4                         _______  number
                                    |       
0    0    0    0    0    0    0    1| 
0000 0000 0000 0000 0000 0000 0000 0100
<--------------------------------> |
              NSA = 28 bits        |________  sign 


0x00000003 3                          ______  number
                                     |      
0    0    0    0    0    0    0    1 | 
0000 0000 0000 0000 0000 0000 0000 0011
<---------------------------------->|
              NSA = 29 bits         |_______  sign 


0x00000002 2                          ______  number
                                     |      
0    0    0    0    0    0    0    1 | 
0000 0000 0000 0000 0000 0000 0000 0010
<---------------------------------->|
              NSA = 29 bits         |_______  sign 


0x00000001 1                           _____  number
                                      |     
0    0    0    0    0    0    0    1  | 
0000 0000 0000 0000 0000 0000 0000 0001
<----------------------------------->|
              NSA = 30 bits          |______  sign 



0xFFFFFFFF 0    NSA = 31
0xFFFFFFFF -1   NSA = 31


0xFFFFFFFE -2                          _____  number
                                      |     
F    F    F    F    F    F    F    E  | 
1111 1111 1111 1111 1111 1111 1111 1110
<----------------------------------->|
              NSA = 30 bits          |______  sign 



0xFFFFFFFD -3                         ______  number    
                                     |      
F    F    F    F    F    F    F    D | 
1111 1111 1111 1111 1111 1111 1111 1101
<---------------------------------->|
              NSA = 29 bits         |_______  sign  



0xFFFFFFFC -4                         ______  number    
                                     |      
F    F    F    F    F    F    F    C | 
1111 1111 1111 1111 1111 1111 1111 1100
<---------------------------------->|
              NSA = 29 bits         |_______  sign      


0xFFFFFFFB -5                        _______  number    
                                    |       
F    F    F    F    F    F    F    B| 
1111 1111 1111 1111 1111 1111 1111 1011
<--------------------------------> |
              NSA = 28 bits        |________  sign                    

Solution

  • Sounds like a count leading zeros instruction, except it counts how many leading bits all have the same value, and produces a result of that - 1.

    Or to put it anotherw way, it counts how many bits below the sign bit have the same value as the sign bit. (And thus are not part of the significant digits of the input.) The pseudocode expresses this bit-scan as a binary search, but the internal implementation could be anything.


    Left shifting by that amount will "normalize" the value to use the full range of -2^31 .. 2^31-1, without overflowing. So the result of x << NSA(x) will be in one of the 2 ranges -2^31 .. -(2^30+1) or 2^30 .. 2^31-1. (As the docs say, left-shifting by that amount results in a value where the sign bit differs from the bit below. Except for inputs of 0 or -1 being a special case.)

    Presumably the normal use case is to use the same normalization shift value for multiple input values?