Skip to content

Commit 5f3540e

Browse files
authored
Merge pull request #1046 from boriel-basic/fix/rounding_consolidation
Fix/rounding consolidation
2 parents 951f53e + f8b2e8f commit 5f3540e

11 files changed

Lines changed: 543 additions & 4 deletions

File tree

src/arch/z80/backend/common.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,18 @@ def to_long(stype: DataType) -> list[str]:
402402
)
403403

404404
elif stype == F16_t:
405-
output.extend(["ex de, hl", "ld de, 0"])
405+
output.extend(
406+
[
407+
"ex de, hl",
408+
"ld de, 0",
409+
# Copies the highest bit (sign) to DE
410+
"ld a, h",
411+
"add a, a",
412+
"sbc a, a",
413+
"ld e, a",
414+
"ld d, a",
415+
]
416+
)
406417

407418
elif stype in (U32_t, I32_t):
408419
return []

src/symbols/typecast.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# See the file CONTRIBUTORS.md for copyright details.
55
# See https://www.gnu.org/licenses/agpl-3.0.html for details.
66
# --------------------------------------------------------------------
7+
import math
78

89
from src.api import check, errmsg
910
from src.api.errmsg import error
@@ -91,7 +92,8 @@ def make_node(cls, new_type: SymbolTYPE, node: Symbol, lineno: int):
9192
elif new_type.is_basic and not TYPE.is_integral(new_type): # not an integer
9293
node.value = float(node.value)
9394
else: # It's an integer
94-
new_val = int(node.value) & ((1 << (8 * new_type.size)) - 1) # Mask it
95+
# ZX Spectrum ROM always truncates to -Infinity, so we do the same using floor()
96+
new_val = math.floor(node.value) & ((1 << (8 * new_type.size)) - 1) # Mask it
9597

9698
if node.value >= 0 and node.value != new_val:
9799
errmsg.warning_conversion_lose_digits(node.lineno)

src/zxbc/zxblex.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
from src.api import global_
1515
from src.api.errmsg import error
1616
from src.ply import lex
17-
18-
from .keywords import KEYWORDS as reserved
17+
from src.zxbc.keywords import KEYWORDS as reserved
1918

2019
ASM = "" # Set to asm block when commenting
2120
ASMLINENO = 0 # Line of ASM INLINE beginning
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
org 32768
2+
.core.__START_PROGRAM:
3+
di
4+
push ix
5+
push iy
6+
exx
7+
push hl
8+
exx
9+
ld (.core.__CALL_BACK__), sp
10+
ei
11+
jp .core.__MAIN_PROGRAM__
12+
.core.__CALL_BACK__:
13+
DEFW 0
14+
.core.ZXBASIC_USER_DATA:
15+
; Defines USER DATA Length in bytes
16+
.core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA
17+
.core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN
18+
.core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA
19+
_var_neg:
20+
DEFB 00h
21+
DEFB 80h
22+
DEFB 0FEh
23+
DEFB 0FFh
24+
_var:
25+
DEFB 00h
26+
DEFB 80h
27+
DEFB 01h
28+
DEFB 00h
29+
_var_neg_fl:
30+
DEFB 81h
31+
DEFB 0C0h
32+
DEFB 00h
33+
DEFB 00h
34+
DEFB 00h
35+
_r_int:
36+
DEFB 00, 00
37+
_r_long:
38+
DEFB 00, 00, 00, 00
39+
_r_ulong:
40+
DEFB 00, 00, 00, 00
41+
.core.ZXBASIC_USER_DATA_END:
42+
.core.__MAIN_PROGRAM__:
43+
ld hl, (_var_neg)
44+
ld de, (_var_neg + 2)
45+
ex de, hl
46+
ld (_r_int), hl
47+
ld hl, 65534
48+
ld (_r_int), hl
49+
ld hl, (_var_neg)
50+
ld de, (_var_neg + 2)
51+
ex de, hl
52+
ld de, 0
53+
ld a, h
54+
add a, a
55+
sbc a, a
56+
ld e, a
57+
ld d, a
58+
ld (_r_long), hl
59+
ld (_r_long + 2), de
60+
ld hl, (_var_neg)
61+
ld de, (_var_neg + 2)
62+
ex de, hl
63+
ld de, 0
64+
ld a, h
65+
add a, a
66+
sbc a, a
67+
ld e, a
68+
ld d, a
69+
ld (_r_ulong), hl
70+
ld (_r_ulong + 2), de
71+
ld hl, (_var)
72+
ld de, (_var + 2)
73+
ex de, hl
74+
ld (_r_int), hl
75+
ld hl, 1
76+
ld (_r_int), hl
77+
ld hl, (_var)
78+
ld de, (_var + 2)
79+
ex de, hl
80+
ld de, 0
81+
ld a, h
82+
add a, a
83+
sbc a, a
84+
ld e, a
85+
ld d, a
86+
ld (_r_long), hl
87+
ld (_r_long + 2), de
88+
ld hl, (_var)
89+
ld de, (_var + 2)
90+
ex de, hl
91+
ld de, 0
92+
ld a, h
93+
add a, a
94+
sbc a, a
95+
ld e, a
96+
ld d, a
97+
ld (_r_ulong), hl
98+
ld (_r_ulong + 2), de
99+
ld a, (_var_neg_fl)
100+
ld de, (_var_neg_fl + 1)
101+
ld bc, (_var_neg_fl + 3)
102+
call .core.__FTOU32REG
103+
ld (_r_int), hl
104+
ld hl, 65534
105+
ld (_r_int), hl
106+
ld a, (_var_neg_fl)
107+
ld de, (_var_neg_fl + 1)
108+
ld bc, (_var_neg_fl + 3)
109+
call .core.__FTOU32REG
110+
ld (_r_long), hl
111+
ld (_r_long + 2), de
112+
ld a, (_var_neg_fl)
113+
ld de, (_var_neg_fl + 1)
114+
ld bc, (_var_neg_fl + 3)
115+
call .core.__FTOU32REG
116+
ld (_r_ulong), hl
117+
ld (_r_ulong + 2), de
118+
ld hl, 0
119+
ld b, h
120+
ld c, l
121+
.core.__END_PROGRAM:
122+
di
123+
ld hl, (.core.__CALL_BACK__)
124+
ld sp, hl
125+
exx
126+
pop hl
127+
exx
128+
pop iy
129+
pop ix
130+
ei
131+
ret
132+
;; --- end of user code ---
133+
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm"
134+
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg32.asm"
135+
push namespace core
136+
__ABS32:
137+
bit 7, d
138+
ret z
139+
__NEG32: ; Negates DEHL (Two's complement)
140+
ld a, l
141+
cpl
142+
ld l, a
143+
ld a, h
144+
cpl
145+
ld h, a
146+
ld a, e
147+
cpl
148+
ld e, a
149+
ld a, d
150+
cpl
151+
ld d, a
152+
inc l
153+
ret nz
154+
inc h
155+
ret nz
156+
inc de
157+
ret
158+
pop namespace
159+
#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm"
160+
push namespace core
161+
__FTOU32REG: ; Converts a Float to (un)signed 32 bit integer (NOTE: It's ALWAYS 32 bit signed)
162+
; Input FP number in A EDCB (A exponent, EDCB mantissa)
163+
; Output: DEHL 32 bit number (signed)
164+
PROC
165+
LOCAL __IS_FLOAT
166+
LOCAL __NEGATE
167+
or a
168+
jr nz, __IS_FLOAT
169+
; Here if it is a ZX ROM Integer
170+
ld h, c
171+
ld l, d
172+
ld d, e
173+
ret
174+
__IS_FLOAT: ; Jumps here if it is a true floating point number
175+
ld h, e
176+
push hl ; Stores it for later (Contains Sign in H)
177+
push de
178+
push bc
179+
exx
180+
pop de ; Loads mantissa into C'B' E'D'
181+
pop bc ;
182+
set 7, c ; Highest mantissa bit is always 1
183+
exx
184+
ld hl, 0 ; DEHL = 0
185+
ld d, h
186+
ld e, l
187+
;ld a, c ; Get exponent
188+
sub 128 ; Exponent -= 128
189+
jr z, __FTOU32REG_END ; If it was <= 128, we are done (Integers must be > 128)
190+
jr c, __FTOU32REG_END ; It was decimal (0.xxx). We are done (return 0)
191+
ld b, a ; Loop counter = exponent - 128
192+
__FTOU32REG_LOOP:
193+
exx ; Shift C'B' E'D' << 1, output bit stays in Carry
194+
sla d
195+
rl e
196+
rl b
197+
rl c
198+
exx ; Shift DEHL << 1, inserting the carry on the right
199+
rl l
200+
rl h
201+
rl e
202+
rl d
203+
djnz __FTOU32REG_LOOP
204+
__FTOU32REG_END:
205+
pop af ; Take the sign bit
206+
or a ; Sets SGN bit to 1 if negative
207+
jp m, __NEGATE ; Negates DEHL
208+
ret
209+
__NEGATE:
210+
exx
211+
ld a, d
212+
or e
213+
or b
214+
or c
215+
exx
216+
jr z, __END
217+
inc l
218+
jr nz, __END
219+
inc h
220+
jr nz, __END
221+
inc de
222+
LOCAL __END
223+
__END:
224+
jp __NEG32
225+
ENDP
226+
__FTOU8: ; Converts float in C ED LH to Unsigned byte in A
227+
call __FTOU32REG
228+
ld a, l
229+
ret
230+
pop namespace
231+
#line 92 "arch/zx48k/cast_const_to_int.bas"
232+
END
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
dim var_neg as fixed = -1.5
2+
const const_neg as fixed = -1.5
3+
dim var as Fixed = 1.5
4+
const const_ as fixed = 1.5
5+
dim var_neg_fl as Float = -1.5
6+
const const_neg_fl as Float = -1.5
7+
8+
DIM r_int as Integer
9+
DIM r_long as Long
10+
DIM r_ulong as ULong
11+
12+
LET r_int = cast(integer, var_neg)
13+
LET r_int = cast(integer, const_neg)
14+
LET r_long = cast(long, var_neg)
15+
LET r_ulong = cast(ulong, var_neg)
16+
17+
LET r_int = cast(integer, var)
18+
LET r_int = cast(integer, const_)
19+
LET r_long = cast(long, var)
20+
LET r_ulong = cast(ulong, var)
21+
22+
LET r_int = cast(integer, var_neg_fl)
23+
LET r_int = cast(integer, const_neg_fl)
24+
LET r_long = cast(long, var_neg_fl)
25+
LET r_ulong = cast(ulong, var_neg_fl)

tests/functional/arch/zx48k/cast_f16_to_long.asm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ _v2:
2929
ld de, (_v1 + 2)
3030
ex de, hl
3131
ld de, 0
32+
ld a, h
33+
add a, a
34+
sbc a, a
35+
ld e, a
36+
ld d, a
3237
ld (_v2), hl
3338
ld (_v2 + 2), de
3439
ld hl, 0

tests/functional/arch/zx48k/cast_f16_to_ulong.asm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ _v2:
2929
ld de, (_v1 + 2)
3030
ex de, hl
3131
ld de, 0
32+
ld a, h
33+
add a, a
34+
sbc a, a
35+
ld e, a
36+
ld d, a
3237
ld (_v2), hl
3338
ld (_v2 + 2), de
3439
ld hl, 0

0 commit comments

Comments
 (0)