6ae415d48b
In EM, fef splits a float into exponent and fraction. The old C code, given an infinite float, got stuck in an infinite loop. The new assembly code doesn't loop; it extracts the IEEE exponent.
59 lines
1.5 KiB
ArmAsm
59 lines
1.5 KiB
ArmAsm
#include "powerpc.h"
|
|
|
|
.sect .text
|
|
|
|
! Split a double-precision float into fraction and exponent, like
|
|
! frexp(3) in C. On entry:
|
|
! r3 = float, high word (bits 0..31)
|
|
! r4 = float, low word (bits 32..63)
|
|
! Yields:
|
|
! r3 = fraction, high word (bits 0..31)
|
|
! r4 = fraction, low word (bits 32..63)
|
|
! r5 = exponent
|
|
! Kills: cr0 f0 f1 r6 r7
|
|
|
|
.define .fef8
|
|
.fef8:
|
|
! IEEE double-precision format:
|
|
! sign exponent fraction
|
|
! 0 1..11 12..63
|
|
rlwinm r6, r3, 12, 21, 31 ! r6 = IEEE exponent
|
|
addis r7, r0, 0x7ff0 ! r7 = exponent mask
|
|
addi r5, r6, -1022 ! r5 = true exponent
|
|
cmpi cr0, 0, r6, 2047
|
|
bclr IFTRUE, EQ, 0 ! return if infinity or NaN
|
|
cmpi cr0, 0, r6, 0
|
|
bc IFFALSE, EQ, 1f ! jump if normalized number
|
|
|
|
! Got denormalized number or zero, probably zero.
|
|
rlwinm r6, r3, 0, 12, 31
|
|
addi r5, r0, 0 ! r5 = true exponent = 0
|
|
or. r6, r6, r4 ! r6 = high|low fraction
|
|
bclr IFTRUE, EQ, 0 ! return if zero
|
|
|
|
! Got denormalized number, not zero.
|
|
stwu r4, -4(sp)
|
|
stwu r3, -4(sp)
|
|
li32 r6, _2_64
|
|
lfd f0, 0(sp)
|
|
lfd f1, 0(r6)
|
|
fmul f0, f0, f1 ! multiply it by 2**64
|
|
stfd f0, 0(sp)
|
|
lwz r3, 0(sp)
|
|
lwz r4, 4(sp)
|
|
rlwinm r6, r3, 12, 21, 31 ! r6 = IEEE exponent
|
|
addi sp, sp, 8
|
|
addi r5, r6, -1022 - 64 ! r5 = true exponent
|
|
1:
|
|
! Put fraction in [0.5, 1) or (-1, -0.5] by setting its
|
|
! exponent to true 0, IEEE 1022.
|
|
andc r3, r3, r7 ! clear old exponent
|
|
oris r3, r3, 1022 << 4 ! set new exponent
|
|
bclr ALWAYS, 0, 0
|
|
|
|
.sect .rom
|
|
_2_64:
|
|
! (double) 2**64
|
|
.data4 0x43f00000
|
|
.data4 0x00000000
|