Skip to content

Commit f357dee

Browse files
committed
implemented dtol and dtoll in assembly
1 parent 96126e7 commit f357dee

File tree

5 files changed

+605
-548
lines changed

5 files changed

+605
-548
lines changed

src/crt/dtol.src

+8-17
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,17 @@
55
public __dtol
66
public __dtoul
77

8-
; __dtol_c correctly handles all non-UB cases for both
8+
; correctly handles all non-UB cases for both
99
; (long)long double and (unsigned long)long double
1010
__dtol:
1111
__dtoul:
12-
; f64_ret_i32
13-
push af, iy
14-
ld a, b
15-
push bc, de, hl
16-
ld hl, 7
17-
add hl, sp
18-
res 7, (hl) ; fabsl(x)
19-
inc hl
20-
rlca
21-
ld (hl), a ; store the sign of x in the padding byte
22-
call __dtol_c
23-
pop af
24-
ld a, e
12+
push bc
13+
push de
14+
call __dtoll ; same as __dtoull
15+
ld c, e
2516
pop de
26-
ld e, a
27-
pop bc, iy, af
17+
ld e, c
18+
pop bc
2819
ret
2920

30-
extern __dtol_c
21+
extern __dtoll

src/crt/dtoll.src

+69-13
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,77 @@
55
public __dtoll
66
public __dtoull
77

8-
; __dtoll_c correctly handles all non-UB cases for both
8+
; correctly handles all non-UB cases for both
99
; (long long)long double and (unsigned long long)long double
1010
__dtoll:
1111
__dtoull:
12-
; f64_ret_i64
13-
push af, iy
14-
ld a, b
15-
res 7, b ; fabsl(x)
16-
push bc, de, hl
17-
ld hl, 8
18-
add hl, sp
19-
rlca
20-
ld (hl), a ; store the sign of x in the padding byte
21-
call __dtoll_c
22-
pop af, af, af, iy, af
12+
bit 6, b ; set if |x| >= 2.0L
13+
jr z, .zero_or_one
14+
bit 7, b
15+
push af
16+
res 7, b
17+
push hl
18+
; -((Float64_mant_bits + Float64_bias) << 4)
19+
ld hl, $FFC010 ; -16368 ; -$3FF0
20+
21+
; clears the exponent field without touching the mantissa
22+
; sets the LSB of the exponent since x is normalized
23+
ld a, c
24+
or a, l ; or a, $10
25+
and a, $1F
26+
27+
add hl, bc
28+
; HL <<= 4
29+
add hl, hl
30+
add hl, hl
31+
add hl, hl
32+
add hl, hl
33+
34+
ld c, a
35+
ld b, 0
36+
ld a, h
37+
sub a, 52 + 1 ; float64 mantissa bits
38+
jr c, .shift_right
39+
; shift_left
40+
; expon >= 52 or [52, 63]
41+
; A is one less than it should be here to allow for the CPL trick in shift_right
42+
; A is [-1, 10]
43+
cp a, 11 ; only call __llshl if the shift amount is [0, 63]
44+
inc a ; positioning inc a after cp a allows __llshl to be skipped when the shift amount is zero
45+
ld l, a
46+
ex (sp), hl
47+
call c, __llshl
48+
jr .finish
49+
.shift_right:
50+
; expon is [0, 51]
51+
cpl
52+
ld l, a
53+
ex (sp), hl
54+
call __llshru
55+
.finish:
56+
pop af ; reset SP
57+
pop af
58+
.finish_zero_or_one:
59+
jp nz, __llneg
2360
ret
2461

25-
extern __dtoll_c
62+
.zero_or_one:
63+
ld hl, 16
64+
ld d, h
65+
ld e, h
66+
add hl, bc ; adds one to the exponent
67+
bit 6, h ; if |x| was [1, 2)
68+
jr z, .zero
69+
inc de
70+
bit 7, b ; sets NZ if the result should be -1
71+
.zero:
72+
ld c, d
73+
ld b, d
74+
ld h, d
75+
ld l, d
76+
ex.s de, hl
77+
jr .finish_zero_or_one
78+
79+
extern __llneg
80+
extern __llshl
81+
extern __llshru

src/crt/float64_to_int.c

+2
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ static uint64_t f64_to_unsigned(F64_pun val) {
9696
return val.bin;
9797
}
9898

99+
100+
99101
/**
100102
* @brief the exact same routine is used for (long long)long double and
101103
* (unsigned long long)long double. If the input long double is out of range,

0 commit comments

Comments
 (0)