Skip to content

Commit 74d1f12

Browse files
committed
implemented logbf in asm and optimized ilogbf and copysignl
1 parent 529c558 commit 74d1f12

File tree

6 files changed

+179
-40
lines changed

6 files changed

+179
-40
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/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

src/libc/logb.c renamed to src/libc/logbl.c

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,11 @@
1+
#include <errno.h>
12
#include <fenv.h>
23
#include <math.h>
34

4-
float logbf(float x) {
5-
if (isfinite(x)) {
6-
if (iszero(x)) {
7-
feraiseexcept(FE_DIVBYZERO);
8-
return -HUGE_VALF;
9-
}
10-
return (float)ilogbf(x);
11-
}
12-
// infinity and NaN
13-
return fabsf(x);
14-
}
15-
16-
double logb(double) __attribute__((alias("logbf")));
17-
185
long double logbl(long double x) {
196
if (isfinite(x)) {
207
if (iszero(x)) {
8+
errno = EDOM;
219
feraiseexcept(FE_DIVBYZERO);
2210
return -HUGE_VALL;
2311
}

test/floating_point/float32_ilogb/src/main.c

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
#include <stddef.h>
33
#include <stdint.h>
44
#include <stdio.h>
5+
#include <string.h>
56
#include <math.h>
7+
#include <errno.h>
8+
#include <fenv.h>
69
#include <assert.h>
710
#include <ti/screen.h>
811
#include <ti/getcsc.h>
@@ -13,6 +16,25 @@
1316

1417
#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
1518

19+
#if 0
20+
#define test_printf printf
21+
#else
22+
#define test_printf(...)
23+
#endif
24+
25+
float truth_logbf(float x) {
26+
if (isfinite(x)) {
27+
if (iszero(x)) {
28+
errno = EDOM;
29+
feraiseexcept(FE_DIVBYZERO);
30+
return -HUGE_VALF;
31+
}
32+
return (float)ilogbf(x);
33+
}
34+
// infinity and NaN
35+
return fabsf(x);
36+
}
37+
1638
size_t run_test(void) {
1739
typedef float input_t;
1840
typedef int output_t;
@@ -24,9 +46,32 @@ size_t run_test(void) {
2446
for (size_t i = 0; i < length; i++) {
2547
int result = ilogbf(input[i]);
2648
if (result != output[i]) {
27-
#if 0
28-
printf("%3zu: %08lX\n\t%d != %d\n", i, input[i], result, output[i]);
29-
#endif
49+
test_printf("%3zu: %08lX\n%d != %d\n", i, input[i], result, output[i]);
50+
return i;
51+
}
52+
53+
errno = 0;
54+
feclearexcept(FE_ALL_EXCEPT);
55+
float f_truth = truth_logbf(input[i]);
56+
unsigned char fe_truth = __fe_cur_env;
57+
int errno_truth = errno;
58+
59+
errno = 0;
60+
feclearexcept(FE_ALL_EXCEPT);
61+
float f_guess = logbf(input[i]);
62+
unsigned char fe_guess = __fe_cur_env;
63+
int errno_guess = errno;
64+
65+
if (memcmp(&f_guess, &f_truth, sizeof(float)) != 0) {
66+
test_printf("%3zu: %08lX %d\n%08lX != %08lX\n", i, input[i], output[i], f_guess, f_truth);
67+
return i;
68+
}
69+
if (fe_guess != fe_truth) {
70+
fputs("fenv fail\n", stdout);
71+
return i;
72+
}
73+
if (errno_guess != errno_truth) {
74+
fputs("errno fail\n", stdout);
3075
return i;
3176
}
3277
}

test/floating_point/float64_ilogb/src/main.c

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
#include <stddef.h>
33
#include <stdint.h>
44
#include <stdio.h>
5+
#include <string.h>
56
#include <math.h>
7+
#include <errno.h>
8+
#include <fenv.h>
69
#include <assert.h>
710
#include <ti/screen.h>
811
#include <ti/getcsc.h>
@@ -13,6 +16,25 @@
1316

1417
#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
1518

19+
#if 0
20+
#define test_printf printf
21+
#else
22+
#define test_printf(...)
23+
#endif
24+
25+
long double truth_logbl(long double x) {
26+
if (isfinite(x)) {
27+
if (iszero(x)) {
28+
errno = EDOM;
29+
feraiseexcept(FE_DIVBYZERO);
30+
return -HUGE_VALL;
31+
}
32+
return (long double)ilogbl(x);
33+
}
34+
// infinity and NaN
35+
return fabsl(x);
36+
}
37+
1638
size_t run_test(void) {
1739
typedef long double input_t;
1840
typedef int output_t;
@@ -24,9 +46,32 @@ size_t run_test(void) {
2446
for (size_t i = 0; i < length; i++) {
2547
int result = ilogbl(input[i]);
2648
if (result != output[i]) {
27-
#if 0
28-
printf("%4zu: %016llX\n %d != %d\n", i, input[i], result, output[i]);
29-
#endif
49+
test_printf("%4zu: %016llX\n%d != %d\n", i, input[i], result, output[i]);
50+
return i;
51+
}
52+
53+
errno = 0;
54+
feclearexcept(FE_ALL_EXCEPT);
55+
long double f_truth = truth_logbl(input[i]);
56+
unsigned char fe_truth = __fe_cur_env;
57+
int errno_truth = errno;
58+
59+
errno = 0;
60+
feclearexcept(FE_ALL_EXCEPT);
61+
long double f_guess = logbl(input[i]);
62+
unsigned char fe_guess = __fe_cur_env;
63+
int errno_guess = errno;
64+
65+
if (memcmp(&f_guess, &f_truth, sizeof(long double)) != 0) {
66+
test_printf("%4zu:\n%016llX %d\n%016llX !=\n%016llX\n", i, input[i], output[i], f_guess, f_truth);
67+
return i;
68+
}
69+
if (fe_guess != fe_truth) {
70+
fputs("fenv fail\n", stdout);
71+
return i;
72+
}
73+
if (errno_guess != errno_truth) {
74+
fputs("errno fail\n", stdout);
3075
return i;
3176
}
3277
}

0 commit comments

Comments
 (0)