Case
Standard floating point operations cannot be executed on BREW enabled devices. BREW helper functions must be substituted for floating-point operations.
To make things worst, BREW does not support the float type, only double, and most mathematical functions are not available either.
Cause
When compiling BREW SoftFP operations, the ARM compiler will convert all floating point operations to ARM compiler functions.
These ARM compiler functions will link to other libraries, some of them using static variables. However, BREW does not allow static variables.
And, since BREW applications do not have main() functions, initialization for the standard library will not be done automatically
Goal
The goal is to use standard floating point operations with BREW.
float a = 1.0; float b = 2.0; float c; int i; c = sin(a) + cos(b); i = c * 100.05;
Solution
The ARM compiler will replace floating point operations by the following ARM compiler functions defined in its attached rt_fp.h header file.
/* * Single-precision arithmetic routines. */ extern __softfp float _fadd(float, float); extern __softfp float _fsub(float, float); extern __softfp float _fmul(float, float); extern __softfp float _fdiv(float, float); ...etc.
To use these ARM compiler functions, _fp_init() needs to be called from inside AEEMod_Load() which boots up the application.
/* * Since BREW has no main function, * fplib must be initialized manually with _fp_init() */ extern void _fp_init(void);
After calling the _fp_init() function, several ARM compiler functions can be linked. But BREW is not capable of using all these functions. Specifically, functions with static variables and SWI instructions can not be used in BREW.
<rt_misc.h> /* * The library's signal handling process must be customized for BREW. * __raise(), which traps error signals, cannot be called in BREW. * So the functions that calls it, __rt_raise() is re-targeted. */ void __rt_raise(int /*sig*/, int /*type*/); <errno.h> extern __pure volatile int *__rt_errno_addr(void); <rt_fp.h> /* * This returns a pointer to the FP status word, when it's stored * in memory. */ extern unsigned *__rt_fp_status_addr(void);
There are two ways to replace these incompatible functions, by using C or by using assembler. ( The C method is recommended )
The address of the handset's variable pool must be returned to the two functions above. The method of implementation will change according to the position of the variable pool.
Re-Targeting the __rt_raise Function with C language
In this method, the variable pool is reserved in the AEEApplet structure, and the function is implemented to return that address.
When that function is called, the GETAPPINSTANCE() helper function is called to aquire the address of the AEEApplet structure.
#if defined __arm
#include <rt_misc.h >
#include <errno.h >
#include <rt_fp.h >
#endif
#if defined __arm
#pragma import(__use_no_semihosting_swi)
#endif
typedef struct SoftFPApplet {
AEEApplet aee;
#if defined __arm
signed int volatile _errno;
unsigned int _fpstatus;
#endif
} SoftFPApplet;
#if defined __arm
void __rt_raise(signed int signal, signed int type)
{
return;
}
signed int volatile* __rt_errno_addr(void)
{
SoftFPApplet* ap = (SoftFPApplet*)GETAPPINSTANCE();
return(&ap->_errno);
}
unsigned int* __rt_fp_status_addr(void)
{
SoftFPApplet* ap = (SoftFPApplet*)GETAPPINSTANCE();
return(&ap->_fpstatus);
}
#endif
int AEEClsCreateInstance(AEECLSID ClsId,
IShell * pIShell,IModule * po,void ** ppObj)
{
*ppObj = NULL;
if (ClsId == AEECLSID_SOFTFP) {
if (AEEApplet_New(sizeof(SoftFPApplet),
ClsId, pIShell, po, (IApplet**)ppObj,
(AEEHANDLER)SoftFP_HandleEvent, NULL) == TRUE) {
#if defined __arm
_fp_init();
#endif
// Add your code here .....
return(AEE_SUCCESS);
}
}
return(EFAILED);
}
Re-Targeting the __rt_raise Function By Assembler
In the assembler method, the variable pool uses a particle of the application module itself as the static variable area. The problem with this method is that basic BREW applications are ROPI (Read Only Position Independent). If the application is embedded in the ROM memory, this method will no longer be valid.
This method may not be applicable in some BREW enabled handsets.
AREA ||i.__rt_raise||, CODE, READONLY
EXPORT __rt_raise
__rt_raise
BX lr
AREA ||i.__rt_errno_addr||, CODE, READONLY
EXPORT __rt_errno_addr
__rt_errno_addr
LDR r0, table_errno_addr
ADD r0, pc, r0
BX lr
table_errno_addr
DCD errno_addr - {PC}
AREA ||i.__rt_fp_status_addr||, CODE, READONLY
EXPORT __rt_fp_status_addr
__rt_fp_status_addr
LDR r0, table_status_addr
ADD r0, pc, r0
BX lr
table_status_addr
DCD status_addr - {PC}
AREA ||.constdata||, DATA, READONLY
errno_addr
DCD 0x00000000
status_addr
DCD 0x00000000
END
By implementing these methods,standard floating point operations can be used with BREW.
SophiaFramework comes equipped with standard floating-point operations by default.














