CHAPTER 22. UNIONS CHAPTER 22. UNIONS
LDR R0, =aF ; "%f"
; convert float type value into double type value (printf() will need it):
FCVTDS D7, S0
; bitwise copy from D7 into R2/R3 pair of registers (for printf()):
FMRRD R2, R3, D7
BL printf
SUBS R4, R4, #1
BNE loc_78
MOV R0, R4
LDMFD SP!, {R4,PC}
aF DCB "%f",0xA,0
We’ll also make a dump in objdump and we’ll see that the FPU instructions have different names than inIDA. Apparently,
IDA and binutils developers used different manuals? Perhaps, it would be good to know both instruction name variants.
Listing 22.4: Optimizing GCC 4.6.3 (objdump)
00000038
38: e92d4008 push {r3, lr}
3c: ebfffffe bl 10
40: ed9f0a05 vldr s0, [pc, #20] ; 5c <float_rand+0x24>
44: e3c034ff bic r3, r0, #-16777216 ; 0xff000000
48: e3c33502 bic r3, r3, #8388608 ; 0x800000
4c: e38335fe orr r3, r3, #1065353216 ; 0x3f800000
50: ee073a90 vmov s15, r3
54: ee370ac0 vsub.f32 s0, s15, s0
58: e8bd8008 pop {r3, pc}
5c: 3f800000 svccc 0x00800000
00000000
0: e92d4010 push {r4, lr}
4: e3a00000 mov r0, #0
8: ebfffffe bl 0
The instructions at 0x5c in float_rand() and at 0x38 in main() are random noise.
22.2 Calculating machine epsilon
The machine epsilon is the smallest possible value theFPUcan work with. The more bits allocated for floating point number,
the smaller the machine epsilon. It is 2 −^23 = 1: 19 e− 07 forfloatand 2 −^52 = 2: 22 e− 16 fordouble.
It’s interesting, how easy it’s to calculate the machine epsilon:
#include <stdio.h>
#include <stdint.h>
union uint_float
{
uint32_t i;
float f;
};
float calculate_machine_epsilon(float start)
{
union uint_float v;