Skip to content

Commit 77932c4

Browse files
committed
lltod now raises FE_INEXACT. Removed utod/itod for now
1 parent 8529ceb commit 77932c4

File tree

3 files changed

+133
-75
lines changed

3 files changed

+133
-75
lines changed

src/crt/ltod.src

Lines changed: 47 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -49,54 +49,71 @@ __lltod_common:
4949
push hl
5050
push bc
5151
ld b, a
52-
ld c, 1
52+
ld c, a
53+
xor a, a
5354
.shift_loop:
54-
jr nc, .no_carry
55-
inc c
56-
.no_carry:
55+
adc a, 0
5756
srl h
5857
rr l
5958
djnz .shift_loop
60-
; test round bit
59+
; round upwards to even if (round && (guard || sticky))
6160
jr nc, .no_round
62-
; test sticky bits
63-
dec c
61+
; we must ensure that FE_INEXACT is raised since rounding has occured
62+
or a, a ; test sticky bits
6463
jr nz, .round_up
65-
; test guard bit
66-
bit 0, l
67-
jr nc, .no_round
64+
inc a ; ld a, 1
65+
and a, l ; test guard bit
66+
jr nc, .no_round_inexact
6867
.round_up:
6968
inc b ; round up after shifting
7069
.no_round:
70+
adc a, a ; test sticky and round bits
71+
jr z, .result_is_exact
72+
.no_round_inexact:
73+
ld hl, ___fe_cur_env
74+
set 5, (hl) ; FE_INEXACT
75+
.result_is_exact:
76+
7177
ld h, b
78+
ld a, c
79+
ld l, c
7280
pop bc
7381

74-
ld l, a
7582
ex (sp), hl ; (SP) = shift
7683
call __llshru
7784
ex (sp), hl ; (SP) = shifted HL, H = rounding, L = shift
7885
add a, 51
7986

8087
dec h
81-
push af
82-
; exponent = ($400 + (base2_logarithm - 1)) << 4
83-
; BC = $4EEM
84-
ld l, a
85-
ld h, $04
86-
; clear the implicit mantissa bit
87-
res 4, c ; 52 % 8 == 4
88-
add hl, hl
89-
add hl, hl
90-
add hl, hl
91-
add hl, hl
92-
ld a, l
93-
or a, c
88+
jr nz, __int_to_f64_shl.no_rounding
89+
90+
dec a ; compensate for the implicit mantissa bit
91+
; BC/exponent = [$434*, $43E*]
92+
add a, a
93+
add a, a
94+
add a, a
95+
add a, a
96+
add a, c
9497
ld c, a
95-
ld b, h
96-
pop af
9798
pop hl ; restore shifted HL
98-
call z, __lladd_1 ; round up to even
99+
ld b, $43
100+
if 0
101+
; inlined __lladd_1
102+
inc hl
103+
add hl, de
104+
or a, a
105+
sbc hl, de
106+
jr nz, __int_to_f64_shl.finish
107+
inc de
108+
sbc hl, de
109+
add hl, de
110+
jr nz, __int_to_f64_shl.finish
111+
inc bc
99112
jr __int_to_f64_shl.finish
113+
else
114+
call __lladd_1 ; round up to even
115+
jr __int_to_f64_shl.finish
116+
end if
100117

101118
;-------------------------------------------------------------------------------
102119

@@ -116,31 +133,6 @@ __int_to_f64_zero_or_one:
116133
sbc hl, hl
117134
jr __int_to_f64_shl.finish
118135

119-
;-------------------------------------------------------------------------------
120-
121-
section .text
122-
123-
public __itod
124-
; (long double)int
125-
__itod:
126-
push hl
127-
add hl, hl ; extract signbit
128-
sbc hl, hl ; set Z flag
129-
ld e, l ; sign extend UHL to E:UHL
130-
pop hl
131-
jq __ltod
132-
133-
;-------------------------------------------------------------------------------
134-
135-
section .text
136-
137-
public __utod
138-
; (long double)unsigned int
139-
__utod:
140-
ld e, 0
141-
142-
require __ultod
143-
144136
;-------------------------------------------------------------------------------
145137

146138
section .text
@@ -160,16 +152,6 @@ __ultod:
160152
; (long double)long
161153
__ltod:
162154
bit 7, e
163-
164-
require __ltod.hijack_itod
165-
166-
;-------------------------------------------------------------------------------
167-
168-
section .text
169-
170-
private __ltod.hijack_itod
171-
__ltod.hijack_itod:
172-
173155
push af
174156
call nz, __lneg ; abs(E:UHL)
175157

@@ -211,17 +193,18 @@ __int_to_f64_shl:
211193
ld a, 51
212194
sub a, l
213195

196+
.no_rounding:
214197
; exponent = ($400 + (base2_logarithm - 1)) << 4
215198
; BC = $4EEM
216199
ld l, a
217200
ld h, $04
218201
; clear the implicit mantissa bit
219-
res 4, c ; 52 % 8 == 4
220202
add hl, hl
221203
add hl, hl
222204
add hl, hl
223205
add hl, hl
224206
ld a, l
207+
res 4, c ; 52 % 8 == 4
225208
or a, c
226209
ld c, a
227210
ld b, h
@@ -234,11 +217,11 @@ __int_to_f64_shl:
234217

235218
;-------------------------------------------------------------------------------
236219

237-
extern __ineg
238220
extern __lneg
239221
extern __lctlz
240222
extern __llctlz
241223
extern __llshl
242224
extern __llshru
243225
extern __llneg
244226
extern __lladd_1
227+
extern ___fe_cur_env

test/floating_point/float64_from_integer/src/crt_wrap.asm

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,20 @@
22

33
section .text
44

5+
public _clear_fe_cur_env
6+
_clear_fe_cur_env:
7+
ld a, (___fe_cur_env)
8+
and a, -125 ; feclearexcept(FE_ALL_EXCEPT)
9+
ld (___fe_cur_env), a
10+
ret
11+
12+
public _get_fe_cur_env
13+
_get_fe_cur_env:
14+
ld a, (___fe_cur_env)
15+
ret
16+
517
public _CRT_utod, _CRT_itod
18+
if 0
619

720
_CRT_utod:
821
ld hl, 3
@@ -16,5 +29,29 @@ _CRT_itod:
1629
ld hl, (hl)
1730
jp __itod
1831

32+
else
33+
34+
_CRT_utod:
35+
ld hl, 3
36+
add hl, sp
37+
ld hl, (hl)
38+
ld e, 0
39+
jp __ultod
40+
41+
_CRT_itod:
42+
ld hl, 3
43+
add hl, sp
44+
ld hl, (hl)
45+
push hl
46+
add hl, hl
47+
sbc hl, hl
48+
ld e, l ; sign extend UHL to E:UHL
49+
pop hl
50+
jp __ltod
51+
end if
52+
1953
extern __utod
2054
extern __itod
55+
extern __ultod
56+
extern __ltod
57+
extern ___fe_cur_env

test/floating_point/float64_from_integer/src/main.c

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <stdint.h>
44
#include <stdio.h>
55
#include <math.h>
6+
#include <fenv.h>
67
#include <assert.h>
78
#include <ti/screen.h>
89
#include <ti/getcsc.h>
@@ -32,13 +33,18 @@ void print_failed(uint64_t input, uint64_t guess, uint64_t truth) {
3233
input, guess, truth
3334
);
3435
}
36+
#define test_printf printf
3537
#else
3638
#define print_failed(...)
39+
#define test_printf(...)
3740
#endif
3841

3942
long double CRT_utod(unsigned int);
4043
long double CRT_itod(signed int);
4144

45+
void clear_fe_cur_env(void);
46+
unsigned char get_fe_cur_env(void);
47+
4248
size_t run_test(const char** failed_func) {
4349
typedef struct { uint32_t u32; uint64_t u64; } input_t;
4450
typedef struct { F64_pun fu32; F64_pun fi32; F64_pun fu64; F64_pun fi64; } output_t;
@@ -82,19 +88,51 @@ size_t run_test(const char** failed_func) {
8288
}
8389
}
8490

85-
result.flt = (long double)((uint64_t)input[i].u64);
86-
if (result.bin != output[i].fu64.bin) {
87-
print_failed((uint64_t)input[i].u64, result.bin, output[i].fu64.bin);
88-
*failed_func = "ulltod";
89-
return i;
91+
{
92+
clear_fe_cur_env();
93+
result.flt = (long double)((uint64_t)input[i].u64);
94+
if (result.bin != output[i].fu64.bin) {
95+
print_failed((uint64_t)input[i].u64, result.bin, output[i].fu64.bin);
96+
*failed_func = "ulltod";
97+
return i;
98+
}
99+
unsigned char fe_env = get_fe_cur_env();
100+
bool rounding_occured = ((uint64_t)output[i].fu64.flt != (uint64_t)input[i].u64);
101+
bool inexact_raised = (fe_env & FE_INEXACT);
102+
if (rounding_occured != inexact_raised) {
103+
test_printf(
104+
"%zu: FE: %02X\nI: %016llX\nO: %016llX\n",
105+
i, fe_env,
106+
input[i].u64, output[i].fu64.bin
107+
);
108+
*failed_func = "ulltod";
109+
fputs("fenv\n", stdout);
110+
return i;
111+
}
90112
}
91113

92-
result.flt = (long double)((int64_t)input[i].u64);
93-
if (result.bin != output[i].fi64.bin) {
94-
print_failed((uint64_t)input[i].u64, result.bin, output[i].fi64.bin);
95-
*failed_func = "lltod";
96-
return i;
97-
}
114+
{
115+
clear_fe_cur_env();
116+
result.flt = (long double)((int64_t)input[i].u64);
117+
if (result.bin != output[i].fi64.bin) {
118+
print_failed((uint64_t)input[i].u64, result.bin, output[i].fi64.bin);
119+
*failed_func = "lltod";
120+
return i;
121+
}
122+
unsigned char fe_env = get_fe_cur_env();
123+
bool rounding_occured = ((int64_t)output[i].fi64.flt != (int64_t)input[i].u64);
124+
bool inexact_raised = (fe_env & FE_INEXACT);
125+
if (rounding_occured != inexact_raised) {
126+
test_printf(
127+
"%zu: FE: %02X\nI: %016llX\nO: %016llX\n",
128+
i, fe_env,
129+
input[i].u64, output[i].fu64.bin
130+
);
131+
*failed_func = "lltod";
132+
fputs("fenv\n", stdout);
133+
return i;
134+
}
135+
}
98136
}
99137

100138
/* passed all */

0 commit comments

Comments
 (0)