Engineer-to-Engineer Notea

EE-185

Technical notes on using Analog Devices DSPs, processors and development tools
Visit our Web resources http://www.analog.com/ee-notes and http://www.analog.com/processors or
e-mail processor.support@analog.com or processor.tools.support@analog.com for technical support.

Fast Floating-Point Arithmetic Emulation on Blackfin® Processors
Contributed by Central Apps

Introduction
Processors optimized for digital signal
processing are divided into two broad categories:
fixed-point and floating-point. In general, thecutting-edge fixed-point families tend to be fast,
low power, and low cost, while floating-point
processors offer high precision and wide
dynamic range in hardware.
While the Blackfin® processor architecture wasdesigned for native fixed-point computations, it
can achieve clock speeds that are high enough toemulate floating-point operations in software.
This gives the system designer a choice between
hardware efficiency of floating-point processors
and the low cost and power of Blackfin processor
fixed-point devices. Depending on whether fullstandard conformance or speed is the goal,
floating-point emulation on a fixed-point
processor might use the IEEE-754 standard or afast floating-point (non-IEEE-compliant) format.

Rev 4 – August 23, 2007

representing short and long fast floating-point
data types. C-callable assembly source code isincluded for the following operations: addition,
subtraction, multiplication and conversion
between fixed-point, IEEE-754 floating-point,
and the fast floating-point formats.

Overview
In fixed-point number representation, the radix
point is always at the same location. While thisconvention simplifies numeric operations andconserves memory, it places a limit themagnitude and precision. In situations that
require a large range of numbers or highresolution, a changeable radix point is desirable.

To reduce computational complexity, it issometimes advantageous to use a more relaxedand faster floating-point format. A significant
cycle savings can often be achieved in this way.

Very large and very small numbers can be
represented in floating-point format. Floatingpoint format is basically scientific notation; afloating-point number consists of a mantissa (orfraction) and an exponent. In the IEEE-754
standard, a floating-point number is stored in a
32-bit word, with a 23-bit mantissa, an 8-bit
exponent, and a 1-bit sign. In the fast floatingpoint two-word format described in thisdocument, the exponent is a 16-bit signed
integer, while the mantissa is either a 16- or a 32bit signed fraction (depending on whether the
short of the long fast floating-point data type isused).

This document shows how to emulate fast
floating-point arithmetic on the Blackfin
processor. A two-word format is employed forNormalization is an important feature of floatingpoint representation. A floating-point number isnormalized if it contains no redundant sign bits

On the Blackfin processor platform, IEEE-754
floating-point functions are available as librarycalls from both C/C++ and assembly language.
These libraries emulate floating-point processing
using fixed-point logic.

Copyright 2007, Analog Devices, Inc. All rights reserved. Analog Devices assumes no responsibility for customer product design or the use or application ofcustomers’ products or for any infringements of patents or rights of others which may result from Analog Devices assistance. All trademarks and logos are propertyof their respective holders. Information furnished by Analog Devices applications and development tools engineers is believed to be accurate and reliable, however
no responsibility is assumed by Analog Devices regarding technical accuracy and topicality of the content provided in Analog Devices Engineer-to-Engineer Notes.

ain the mantissa; that is, all bits are significant.
Normalization provides the highest precision for
the number of bits available. It also simplifies thecomparison of magnitudes because the number
with the greater exponent has the greater
magnitude; it is only necessary to compare themantissas if the exponents are equal. All routinespresented in this document assume normalized
input and produce normalized results.

There are two Blackfin processor instructions
used in fixed-point to fast floating-point
conversion. The first instruction, signbits,
returns the number of sign bits in a number (i.e.
the exponent). The second, ashift, is used tonormalize the mantissa.

L

Assembly code for both the short version(fastfloat16) and the long version (fastfloat32) isshown below.

There are some differences in arithmetic
flags between the ADSP-BF535
Blackfin processor and the rest of theBlackfin processors. All of the assembly
code in this document was written forthe
non-ADSP-BF535
Blackfinprocessors.

Converting Between Fixed-Point
and Fast Floating-Point Formats

Listing 3 Fixed-point to short fast floating-point(fastfloat16) conversion/**************************************
fastfloat16 fract16_to_ff16(fract16);------------------

Short and Long Fast FloatingPoint Data Types
The code routines in this document use the twoword format for two different data types. The
short data type (fastfloat16) provides one 16-bit
word for the exponent and one 16-bit word forthe fraction. The long data type (fastfloat32)
provides one 16-bit word for the exponent andone 32-bit word for the fraction. The fastfloat32
data type is more computationally intensive, but
provides greater precision than the fastfloat16
data type. Signed twos-complement notation isassumed for both the fraction and the exponent.
Listing 1 Format of the fastfloat16 data typetypedef struct {short exp;
fract16 frac;Input parameters (compiler convention):
R0.L = fract16
Output parameters (compiler
convention):
R0.L = ff16.exp
R0.H = ff16.frac-----------------**************************************/_fract16_to_ff16:.global _fract16_to_ff16;
r1.l = signbits r0.l; // get the numberof sign bits
r2 = -r1 (v);r2.h = ashift r0.l by r1.l; //normalize the mantissa
r0 = r2;
rts;_fract16_to_ff16.end:} fastfloat16;
Listing 2 Format of the fastfloat32 data typetypedef struct {short exp;
fract32 frac;} fastfloat32;

Fast Floating-Point Arithmetic Emulation on Blackfin® Processors (EE-185)

Page 2 of 9

aListing 4 Fixed-point to long fast floating-point(fastfloat32) conversion

Listing 5 Short fast floating-point (fastfloat16) to fixedpoint conversion/**************************************
fastfloat32 fract32_to_ff32(fract32);/**************************************
fract16 ff16_to_fract16(fastfloat16);------------------------------------

Input parameters (compiler convention):

Input parameters (compiler convention):

R0 = fract32

R0.L = ff16.exp

Output parameters (compiler
convention):

R0.H = ff16.frac

R0.L = ff32.exp

Output parameters (compiler
convention):

R1 = ff32.frac

R0.L = fract16------------------------------------**************************************/**************************************/_fract32_to_ff32:_ff16_to_fract16:.global _fract32_to_ff32;.global _ff16_to_fract16;

r1.l = signbits r0; // get the numberof sign bits

r0.h = ashift r0.h by r0.l; // shift
the binary pointr2 = -r1 (v);r0 >>= 16;

r1 = ashift r0 by r1.l; // normalize
the mantissa

rts;_ff16_to_fract16.end:

r0 = r2;
rts;_fract32_to_ff32.end:

Converting two-word fast floating-point numbers
to fixed-point format is made simple by using theashift instruction.
Assembly code for both the short version(fastfloat16) and the long version (fastfloat32) isshown below.

Listing 6 Long fast floating-point (fastfloat32) to fixedpoint conversion/**************************************
fract32 ff32_to_fract32(fastfloat32);-----------------Input parameters (compiler convention):
R0.L = ff32.exp
R1 = ff32.frac
Output parameters (compiler
convention):
R0 = fract32-----------------**************************************/_ff32_to_fract32:.global _ff32_to_fract32;
r0 = ashift r1 by r0.l; // shift thebinary point
rts;_ff32_to_fract32.end:

Fast Floating-Point Arithmetic Emulation on Blackfin® Processors (EE-185)

Page 3 of 9aConverting Between Fast
Floating-Point and IEEE
Floating-Point Formats

5. Treat overflows by scaling back the input
parameters, if necessary.

The basic approach to converting from the IEEE
floating-point format to the fast floating-point
format begins with extracting the mantissa,
exponent, and sign bit ranges from the IEEE
floating-point word. The exponent needs to beunbiased before setting the fast floating-point
exponent word. The mantissa is used with thesign bit to create a twos-complement signed
fraction, which completes the fast floating-point
two-word format.

Assembly code for both the short version(fastfloat16) and the long version (fastfloat32) isshown below.

Reversing these steps converts a fast floatingpoint number into IEEE floating-point format.
It is outside the scope of this document toprovide more detail about the IEEE-754 floatingpoint format. The attached compressed package
contains sample C code to perform theconversions.

L

The
compressedpackagethataccompanies this document contains
sample routines that convert between thefast floating-point and the IEEE floatingpoint numbers. Note that they do nottreat any special IEEE defined values
like NaN, +∞, or -∞.

6. Normalize the result.

L

For the fastfloat16 arithmetic operations(add, subtract, divide), the following
parameter passing conventions are used.
These are the default conventions usedby the Blackfin processor compiler.
Calling Parametersr0.h = Fraction of x (=Fx)
r0.l = Exponent of x (=Ex)
r1.h = Fraction of y (=Fy)
r1.l = Exponent of y (=Ey)
Return Values
r0.h = Fraction of z (=Fz)
r0.l = Exponent of z (=Ez)

Listing 7 Short fast floating-point (fastfloat16) addition/**************************************
fastfloat16
add_ff16(fastfloat16,fastfloat16);**************************************/

Floating-Point Addition_add_ff16:

The algorithm for adding two numbers in twoword fast floating-point format is as follows:.global _add_ff16;

1. Determine which number has the larger
exponent. Let’s call this number X (= Ex, Fx)
and the other number Y (= Ey, Fy).

cc = an; // negative result?

r2.l = r0.l - r1.l (ns); // is Ex > Ey?
r2.l = r2.l << 11 (s); // guarantee
shift range [-16,15]
r2.l = r2.l >>> 11;

2. Set the exponent of the result to Ex.

if !cc jump _add_ff16_1; // no, shift y

3. Shift Fy right by the difference between Ex
and Ey, to align the radix points of Fx and Fy.

r0.h = ashift r0.h by r2.l; // yes,shift x4. Add Fx and Fy to produce the fraction of theresult.

jump _add_ff16_2;

Fast Floating-Point Arithmetic Emulation on Blackfin® Processors (EE-185)

Page 4 of 9

a_add_ff16_1:
r2 = -r2 (v);r1.h = ashift r1.h by r2.l; // shift
the y value
a0 = 0;a0.l = r0.l; // you can't do r1.h =r2.hL

For the fastfloat32 arithmetic operations(add, subtract, divide), the following
parameter passing conventions are used.
These are the default conventions usedby the Blackfin processor compiler.

r1.l = a0 (iu); // so use a0.x as anintermediate storage place

Calling Parameters_add_ff16_2:

r1 = Fraction of x (=Fx)

r2.l = r0.h + r1.h (ns); // add
fractional partsr0.l = Exponent of x (=Ex)

cc = v; // was there an overflow?
if cc jump _add_ff16_3;

r3 = [FP+20] = Fraction of y(=Fy)// normalize

r2.l = Exponent of y (=Ey)

r0.l = signbits r2.l; // get the numberof sign bits

Return Values

r0.h = ashift r2.l by r0.l; //normalize the mantissa
r0.l = r1.l - r0.l (ns); // adjust theexponent

r1 = Fraction of z (=Fz)
r0.l = Exponent of z (=Ez)
Listing 8 Long fast floating-point (fastfloat32) additionrts;// overflow condition for mantissa
addition_add_ff16_3:
r0.h = r0.h >>> 1; // shift themantissas down
r1.h = r1.h >>> 1;
r0.h = r0.h + r1.h (ns); // add
fractional partsr2.l = 1;/**************************************
fastfloat32 add_ff32(fastfloat32,
fastfloat32);**************************************/#define FF32_PROLOGUE() link 0; r3 =[fp+20]; [--sp]=r4; [--sp]=r5#define FF32_EPILOGUE() r5=[sp++];r4=[sp++]; unlink.global _add_ff32;

r0.l = r1.l + r2.l (ns); // adjust theexponent_add_ff32:

rts;

FF32_PROLOGUE();_add_ff16.end:

r4.l = r0.l - r2.l (ns); // is Ex > Ey?
cc = an; // negative result?
r4.l = r4.l << 10 (s); // guarantee
shift range [-32,31]
r4.l = r4.l >>> 10;
if !cc jump _add_ff32_1; // no, shiftFyr1 = ashift r1 by r4.l; // yes, shift
Fx
jump _add_ff32_2;

Fast Floating-Point Arithmetic Emulation on Blackfin® Processors (EE-185)

Page 5 of 9

a_add_ff32_1:

2. Set the exponent of the result to Ex.

r4 = -r4 (v);

3. Shift Fy right by the difference between Ex
and Ey, to align the radix points of Fx and Fy.

r3 = ashift r3 by r4.l; // shift Fy
r2 = r0;_add_ff32_2:
r4 = r1 + r3 (ns); // add fractionalparts
cc = v; // was there an overflow?
if cc jump _add_ff32_3;

4. Subtract the fraction of the subtrahend fromthe fraction of the minuend to produce thefraction of the result.
5. Treat overflows by scaling back the input
parameters, if necessary.
6. Normalize the result.

// normalize
r0.l = signbits r4; // get the numberof sign bits
r1 = ashift r4 by r0.l; // normalize
the mantissa
r0.l = r2.l - r0.l (ns); // adjust theexponent
FF32_EPILOGUE();
rts;

Assembly code for both the short version(fastfloat16) and the long version (fastfloat32) isshown below.
Listing 9 Short fast floating-point (fastfloat16)
subtraction/**************************************
fastfloat16 sub_ff16(fastfloat16,
fastfloat16);**************************************/// overflow condition for mantissa
addition_add_ff32_3:
r1 = r1 >>> 1;
r3 = r3 >>> 1;
r1 = r1 + r3 (ns); // add fractionalparts.global _sub_ff16;_sub_ff16:
r2.l = r0.l - r1.l (ns); // is Ex > Ey?
cc = an; // negative result?
r2.l = r2.l << 11 (s); // guarantee
shift range [-16,15]
r2.l = r2.l >>> 11;

r4.l = 1;

if !cc jump _sub_ff16_1;
shift y// no,

r0.l = r2.l + r4.l (ns); // adjust theexponent

r0.h = ashift r0.h by r2.l; // yes,shift xFF32_EPILOGUE();jump _sub_ff16_2;

rts;_add_ff32.end:_sub_ff16_1:
r2 = -r2 (v);r1.h = ashift r1.h by r2.l; // shift y

Floating-Point Subtraction
The algorithm for subtracting one number fromanother in two-word fast floating-point format is
as follows:
1. Determine which number has the larger
exponent. Let’s call this number X (= Ex, Fx)
and the other number Y (= Ey, Fy).

a0 = 0;a0.l = r0.l; // you can't do r1.h =r2.hr1.l = a0 (iu); // so use a0.x as anintermediate storage place_sub_ff16_2:

Fast Floating-Point Arithmetic Emulation on Blackfin® Processors (EE-185)

Page 6 of 9ar2.l = r0.h - r1.h (ns); // subtract
fractionsr4.l = r4.l << 10 (s); // guarantee
shift range [-32,31]

cc = v; // was there an overflow?

r4.l = r4.l >>> 10;

if cc jump _sub_ff16_3;

if !cc jump _sub_ff32_1;
shift Fy// no,// normalize

r1 = ashift r1 by r4.l; // yes, shift
Fxr0.l = signbits r2.l; // get the numberof sign bits

jump _sub_ff32_2;

r0.h = ashift r2.l by r0.l; //normalize mantissa
r0.l = r1.l - r0.l (ns); // adjust
exponent
rts;_sub_ff32_1:
r4 = -r4 (v);r3 = ashift r3 by r4.l; // shift Fy
r2 = r0;// overflow condition for mantissa
subtraction_sub_ff32_2:_sub_ff16_3:

r4 = r1 - r3 (ns); // subtract
fractionsr0.h = r0.h >>> 1; // shift themantissas down

cc = v; // was there an overflow?

r1.h = r1.h >>> 1;

if cc jump _sub_ff32_3;

r0.h = r0.h - r1.h (ns); // subtract
fractions// normalize

r2.l = 1;
r0.l = r1.l + r2.l (ns); // adjust theexponent
rts;

r0.l = signbits r4; // get the numberof sign bits
r1 = ashift r4 by r0.l; // normalize
the mantissa_sub_ff16.end:

r0.l = r2.l - r0.l (ns); // adjust theexponent

Listing 10 Long fast floating-point (fastfloat32)
subtraction

FF32_EPILOGUE();rts;/**************************************
fastfloat32 sub_ff32(fastfloat32,
fastfloat32);// overflow condition for mantissa
subtraction**************************************/_sub_ff32_3:#define FF32_PROLOGUE() link 0; r3 =[fp+20]; [--sp]=r4; [--sp]=r5

r1 = r1 >>> 1;
r3 = r3 >>> 1;#define FF32_EPILOGUE() r5=[sp++];r4=[sp++]; unlink

r1 = r1 - r3 (ns); // subtract
fractionsr4.l = 1;.global _sub_ff32;

r0.l = r2.l + r4.l (ns); // adjust theexponent_sub_ff32:

FF32_EPILOGUE();

FF32_PROLOGUE();
r4.l = r0.l - r2.l (ns);
> Ey?

rts;
// is Ex_sub_ff32.end:

cc = an; // negative result?
Fast Floating-Point Arithmetic Emulation on Blackfin® Processors (EE-185)

Page 7 of 9

aFloating-Point Multiplication
Multiplication of two numbers in two-word fast
floating-point format is simpler than either
addition or subtraction because there is no needto align the radix points. The algorithm tomultiply two numbers x and y (Ex, Fx and Ey,Fy) is as follows:
1. Add Ex and Ey to produce the exponent of theresult.
2. Multiply Fx by Fy to produce the fraction of
the result.
3. Normalize the result.
Assembly code for both the short version(fastfloat16) and the long version (fastfloat32) isshown below.

#define FF32_PROLOGUE() link 0; r3 =[fp+20]; [--sp]=r4; [--sp]=r5#define FF32_EPILOGUE() r5=[sp++];r4=[sp++]; unlink.global _mult_ff32;_mult_ff32:
FF32_PROLOGUE();r0.l = r0.l + r2.l (ns); // add theexponents// perform 32-bit fractional
multiplication (taken from VisualDSP++
compiler implementation)
r2 = pack(r1.l, r3.l);
cc = r2;
a1 = r1.l * r3.l (fu);Listing 11 Short fast floating-point (fastfloat16)
multiplication

a1 = a1 >> 16;/**************************************
fastfloat16 void mult_ff16(fastfloat16,
fastfloat16);cc &= av0;**************************************/.global _mult_ff16;_mult_ff16:
r3.l = r0.l + r1.l (ns);a1 += r1.h * r3.l (m), a0 = r1.h *r3.h;a1 += r3.h * r1.l (m);a1 = a1 >>> 15;
r1 = (a0 += a1);
r2 = cc;
r1 = r2 + r1;

a0 = r0.h * r1.h;
r2.l = signbits a0; // get the numberof sign bits// normalize

a0 = ashift a0 by r2.l; // normalize
the mantissa

r4.l = signbits r1; // get the numberof sign bitsr0 = a0;r1 = ashift r1 by r4.l; // normalize
the mantissa

r0.l = r3.l - r2.l (ns); // adjust theexponent
rts;_mult_ff16.end:
Listing 12 Long fast floating-point (fastfloat16)
multiplication

r0.l = r0.l - r4.l (ns); // adjust theexponent
FF32_EPILOGUE();
rts;_mult_ff32.end:/**************************************
fastfloat32 void mult_ff32(fastfloat32,
fastfloat32);**************************************/

Summary
The two-word fast floating-point techniquedescribed in this document can greatly improve
floating-point computational efficiency on theFast Floating-Point Arithmetic Emulation on Blackfin® Processors (EE-185)

Page 8 of 9afixed-point Blackfin Processor platform. The
specific operations described above can be usedas standalone routines, or as starting points formore advanced calculations specific to aparticular application. The compressed sourcecode package that accompanies this document
provides a starting for using the fast floatingpoint method in new projects.

References[1] Digital Signal Processing Applications: Using the ADSP-2100 Family (Volume 1). 1992. Analog Devices, Inc.
[2] The Art of Computer Programming: Volume 2 / Seminumerical Algorithms. Knuth, D.E. Second Edition,1969. AddisonWesley Publishing Company.
[3] IEEE Standard for Binary Floating-Point Arithmetic: ANSI/IEEE Std 754-1985. 1985. Institute of Electrical andElectronicsd Engineers.

Document History
Revision

Description

Rev 4 – August 23, 2007
by Tom L.

Corrected the mult_ff32 function; Updated formatting

Rev 3 – May 26, 2003
by Tom L.

Code updated to check for overflow conditions; New test cases added.

Rev 2 – May 12, 2003
by Tom L.

Updated according to new naming conventions

Rev 1 – February 19, 2003
by Tom L.

Initial Release

Fast Floating-Point Arithmetic Emulation on Blackfin® Processors (EE-185)

Page 9 of 9