Skip to content

Commit e02a2fa

Browse files
committed
implemented logbf in asm and optimized ilogbf and copysignl
1 parent 5c31b2f commit e02a2fa

File tree

6 files changed

+141
-26
lines changed

6 files changed

+141
-26
lines changed

src/libc/copysignl.src

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
_copysignl:
77
ld hl, 19 ; upper 8 bits of y
88
add hl, sp
9-
rl (hl) ; extract the signbit of y
9+
ld a, (hl) ; extract the signbit of y
10+
rlca
1011
pop iy, hl, de, bc
1112
push bc, de, hl
1213
rl b ; clear the signbit of x, signbit of y is in the LSB

src/libc/ilogbf.src

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,48 +13,40 @@ _ilogbf:
1313
dec hl
1414
dec hl
1515
dec hl
16-
ld de, (hl)
17-
sbc hl, hl
18-
ex de, hl
19-
; DE is zero
16+
ld hl, (hl)
2017
add hl, hl
21-
2218
adc a, a
2319
jr z, .maybe_subnormal
2420
inc a
25-
scf
2621
jr z, .inf_nan
27-
rr e ; E = 128 or float32_bias + 1
22+
sub a, 128 ; float32_bias + 1
2823
sbc hl, hl
2924
ld l, a
30-
sbc hl, de
3125
ret
3226

3327
.maybe_subnormal:
34-
; DE is zero, Carry unknown
3528
add hl, de
29+
or a, a
3630
sbc hl, de
3731
jr z, .ret_zero
3832
call __ictlz
39-
ex de, hl
40-
; DE was zero, so HL is now zero
41-
dec hl
4233
cpl
4334
add a, 130
35+
sbc hl, hl
4436
ld l, a
4537
ret
4638

47-
.ret_zero:
4839
.inf_nan:
49-
ld hl, $800000 ; FP_ILOGB0
50-
sbc hl, de ; FP_ILOGBNAN or INT_MAX when carry is set
51-
ex de, hl
52-
; DE was zero, so HL is now zero
53-
ld l, 4 ; EDOM
40+
scf
41+
.ret_zero:
42+
ld hl, 4 ; EDOM
5443
ld (_errno), hl
5544
ld hl, ___fe_cur_env
5645
set 4, (hl) ; FE_INVALID
57-
ex de, hl
46+
ld hl, $800000 ; FP_ILOGB0
47+
ret nc
48+
; FP_ILOGBNAN or INT_MAX when carry is set
49+
dec hl
5850
ret
5951

6052
extern _errno

src/libc/logb.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#include <fenv.h>
22
#include <math.h>
33

4+
#if 0
5+
6+
/* logbf.src */
7+
48
float logbf(float x) {
59
if (isfinite(x)) {
610
if (iszero(x)) {
@@ -15,6 +19,8 @@ float logbf(float x) {
1519

1620
double logb(double) __attribute__((alias("logbf")));
1721

22+
#endif
23+
1824
long double logbl(long double x) {
1925
if (isfinite(x)) {
2026
if (iszero(x)) {

src/libc/logbf.src

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
assume adl=1
2+
3+
section .text
4+
5+
public _logbf, _logb
6+
7+
; float logbf(float)
8+
_logb:
9+
_logbf:
10+
ld hl, 6
11+
ld bc, -3
12+
add hl, sp
13+
ld a, (hl)
14+
add hl, bc
15+
ld c, b ; ld bc, -1
16+
ld hl, (hl)
17+
add hl, hl
18+
adc a, a
19+
jr z, .maybe_subnormal
20+
inc a
21+
jr z, .inf_nan
22+
sub a, 128 ; float32_bias + 1
23+
jr c, .negative_exponent
24+
inc bc ; ld bc, 0
25+
.negative_exponent:
26+
.int_to_float:
27+
; exponent is [-149, 127]
28+
ld c, a
29+
ld a, b ; sign extend
30+
call __ltof
31+
push bc
32+
pop hl
33+
ld e, a
34+
ret
35+
36+
.inf_nan:
37+
; return fabsf(x)
38+
pop bc
39+
ex (sp), hl
40+
push bc
41+
ld e, $7F
42+
ret
43+
44+
.ret_zero:
45+
; HL is zero here
46+
ld l, 4 ; EDOM
47+
ld (_errno), hl
48+
; FE_DIVBYZERO
49+
ld hl, ___fe_cur_env
50+
set 6, (hl)
51+
; -HUGE_VALF
52+
ld hl, $800000
53+
ld e, b ; ld e, $FF
54+
ret
55+
56+
.maybe_subnormal:
57+
add hl, bc
58+
inc hl ; restore HL
59+
jr nc, .ret_zero
60+
call __ictlz
61+
cpl
62+
add a, 130
63+
jr .int_to_float
64+
65+
extern __ltof
66+
extern __ictlz
67+
extern ___fe_cur_env
68+
extern _errno

test/floating_point/float32_ilogb/src/main.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
#include <stddef.h>
33
#include <stdint.h>
44
#include <stdio.h>
5+
#include <string.h>
56
#include <math.h>
7+
#include <fenv.h>
68
#include <assert.h>
79
#include <ti/screen.h>
810
#include <ti/getcsc.h>
@@ -13,6 +15,24 @@
1315

1416
#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
1517

18+
#if 0
19+
#define test_printf printf
20+
#else
21+
#define test_printf(...)
22+
#endif
23+
24+
float truth_logbf(float x) {
25+
if (isfinite(x)) {
26+
if (iszero(x)) {
27+
feraiseexcept(FE_DIVBYZERO);
28+
return -HUGE_VALF;
29+
}
30+
return (float)ilogbf(x);
31+
}
32+
// infinity and NaN
33+
return fabsf(x);
34+
}
35+
1636
size_t run_test(void) {
1737
typedef float input_t;
1838
typedef int output_t;
@@ -24,9 +44,13 @@ size_t run_test(void) {
2444
for (size_t i = 0; i < length; i++) {
2545
int result = ilogbf(input[i]);
2646
if (result != output[i]) {
27-
#if 0
28-
printf("%3zu: %08lX\n\t%d != %d\n", i, input[i], result, output[i]);
29-
#endif
47+
test_printf("%3zu: %08lX\n%d != %d\n", i, input[i], result, output[i]);
48+
return i;
49+
}
50+
float f_truth = truth_logbf(input[i]);
51+
float f_guess = logbf(input[i]);
52+
if (memcmp(&f_guess, &f_truth, sizeof(float)) != 0) {
53+
test_printf("%3zu: %08lX %d\n%08lX != %08lX\n", i, input[i], output[i], f_guess, f_truth);
3054
return i;
3155
}
3256
}

test/floating_point/float64_ilogb/src/main.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
#include <stddef.h>
33
#include <stdint.h>
44
#include <stdio.h>
5+
#include <string.h>
56
#include <math.h>
7+
#include <fenv.h>
68
#include <assert.h>
79
#include <ti/screen.h>
810
#include <ti/getcsc.h>
@@ -13,6 +15,24 @@
1315

1416
#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
1517

18+
#if 0
19+
#define test_printf printf
20+
#else
21+
#define test_printf(...)
22+
#endif
23+
24+
long double truth_logbl(long double x) {
25+
if (isfinite(x)) {
26+
if (iszero(x)) {
27+
feraiseexcept(FE_DIVBYZERO);
28+
return -HUGE_VALL;
29+
}
30+
return (long double)ilogbl(x);
31+
}
32+
// infinity and NaN
33+
return fabsl(x);
34+
}
35+
1636
size_t run_test(void) {
1737
typedef long double input_t;
1838
typedef int output_t;
@@ -24,9 +44,13 @@ size_t run_test(void) {
2444
for (size_t i = 0; i < length; i++) {
2545
int result = ilogbl(input[i]);
2646
if (result != output[i]) {
27-
#if 0
28-
printf("%4zu: %016llX\n %d != %d\n", i, input[i], result, output[i]);
29-
#endif
47+
test_printf("%4zu: %016llX\n%d != %d\n", i, input[i], result, output[i]);
48+
return i;
49+
}
50+
long double f_truth = truth_logbl(input[i]);
51+
long double f_guess = logbl(input[i]);
52+
if (memcmp(&f_guess, &f_truth, sizeof(long double)) != 0) {
53+
test_printf("%4zu:\n%016llX %d\n%016llX !=\n%016llX\n", i, input[i], output[i], f_guess, f_truth);
3054
return i;
3155
}
3256
}

0 commit comments

Comments
 (0)