Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/arch/z80/backend/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,18 @@ def to_long(stype: DataType) -> list[str]:
)

elif stype == F16_t:
output.extend(["ex de, hl", "ld de, 0"])
output.extend(
[
"ex de, hl",
"ld de, 0",
# Copies the highest bit (sign) to DE
"ld a, h",
"add a, a",
"sbc a, a",
"ld e, a",
"ld d, a",
]
)

elif stype in (U32_t, I32_t):
return []
Expand Down
4 changes: 3 additions & 1 deletion src/symbols/typecast.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# See the file CONTRIBUTORS.md for copyright details.
# See https://www.gnu.org/licenses/agpl-3.0.html for details.
# --------------------------------------------------------------------
import math

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

if node.value >= 0 and node.value != new_val:
errmsg.warning_conversion_lose_digits(node.lineno)
Expand Down
3 changes: 1 addition & 2 deletions src/zxbc/zxblex.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
from src.api import global_
from src.api.errmsg import error
from src.ply import lex

from .keywords import KEYWORDS as reserved
from src.zxbc.keywords import KEYWORDS as reserved

ASM = "" # Set to asm block when commenting
ASMLINENO = 0 # Line of ASM INLINE beginning
Expand Down
232 changes: 232 additions & 0 deletions tests/functional/arch/zx48k/cast_const_to_int.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
org 32768
.core.__START_PROGRAM:
di
push ix
push iy
exx
push hl
exx
ld (.core.__CALL_BACK__), sp
ei
jp .core.__MAIN_PROGRAM__
.core.__CALL_BACK__:
DEFW 0
.core.ZXBASIC_USER_DATA:
; Defines USER DATA Length in bytes
.core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA
.core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN
.core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA
_var_neg:
DEFB 00h
DEFB 80h
DEFB 0FEh
DEFB 0FFh
_var:
DEFB 00h
DEFB 80h
DEFB 01h
DEFB 00h
_var_neg_fl:
DEFB 81h
DEFB 0C0h
DEFB 00h
DEFB 00h
DEFB 00h
_r_int:
DEFB 00, 00
_r_long:
DEFB 00, 00, 00, 00
_r_ulong:
DEFB 00, 00, 00, 00
.core.ZXBASIC_USER_DATA_END:
.core.__MAIN_PROGRAM__:
ld hl, (_var_neg)
ld de, (_var_neg + 2)
ex de, hl
ld (_r_int), hl
ld hl, 65534
ld (_r_int), hl
ld hl, (_var_neg)
ld de, (_var_neg + 2)
ex de, hl
ld de, 0
ld a, h
add a, a
sbc a, a
ld e, a
ld d, a
ld (_r_long), hl
ld (_r_long + 2), de
ld hl, (_var_neg)
ld de, (_var_neg + 2)
ex de, hl
ld de, 0
ld a, h
add a, a
sbc a, a
ld e, a
ld d, a
ld (_r_ulong), hl
ld (_r_ulong + 2), de
ld hl, (_var)
ld de, (_var + 2)
ex de, hl
ld (_r_int), hl
ld hl, 1
ld (_r_int), hl
ld hl, (_var)
ld de, (_var + 2)
ex de, hl
ld de, 0
ld a, h
add a, a
sbc a, a
ld e, a
ld d, a
ld (_r_long), hl
ld (_r_long + 2), de
ld hl, (_var)
ld de, (_var + 2)
ex de, hl
ld de, 0
ld a, h
add a, a
sbc a, a
ld e, a
ld d, a
ld (_r_ulong), hl
ld (_r_ulong + 2), de
ld a, (_var_neg_fl)
ld de, (_var_neg_fl + 1)
ld bc, (_var_neg_fl + 3)
call .core.__FTOU32REG
ld (_r_int), hl
ld hl, 65534
ld (_r_int), hl
ld a, (_var_neg_fl)
ld de, (_var_neg_fl + 1)
ld bc, (_var_neg_fl + 3)
call .core.__FTOU32REG
ld (_r_long), hl
ld (_r_long + 2), de
ld a, (_var_neg_fl)
ld de, (_var_neg_fl + 1)
ld bc, (_var_neg_fl + 3)
call .core.__FTOU32REG
ld (_r_ulong), hl
ld (_r_ulong + 2), de
ld hl, 0
ld b, h
ld c, l
.core.__END_PROGRAM:
di
ld hl, (.core.__CALL_BACK__)
ld sp, hl
exx
pop hl
exx
pop iy
pop ix
ei
ret
;; --- end of user code ---
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm"
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg32.asm"
push namespace core
__ABS32:
bit 7, d
ret z
__NEG32: ; Negates DEHL (Two's complement)
ld a, l
cpl
ld l, a
ld a, h
cpl
ld h, a
ld a, e
cpl
ld e, a
ld a, d
cpl
ld d, a
inc l
ret nz
inc h
ret nz
inc de
ret
pop namespace
#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm"
push namespace core
__FTOU32REG: ; Converts a Float to (un)signed 32 bit integer (NOTE: It's ALWAYS 32 bit signed)
; Input FP number in A EDCB (A exponent, EDCB mantissa)
; Output: DEHL 32 bit number (signed)
PROC
LOCAL __IS_FLOAT
LOCAL __NEGATE
or a
jr nz, __IS_FLOAT
; Here if it is a ZX ROM Integer
ld h, c
ld l, d
ld d, e
ret
__IS_FLOAT: ; Jumps here if it is a true floating point number
ld h, e
push hl ; Stores it for later (Contains Sign in H)
push de
push bc
exx
pop de ; Loads mantissa into C'B' E'D'
pop bc ;
set 7, c ; Highest mantissa bit is always 1
exx
ld hl, 0 ; DEHL = 0
ld d, h
ld e, l
;ld a, c ; Get exponent
sub 128 ; Exponent -= 128
jr z, __FTOU32REG_END ; If it was <= 128, we are done (Integers must be > 128)
jr c, __FTOU32REG_END ; It was decimal (0.xxx). We are done (return 0)
ld b, a ; Loop counter = exponent - 128
__FTOU32REG_LOOP:
exx ; Shift C'B' E'D' << 1, output bit stays in Carry
sla d
rl e
rl b
rl c
exx ; Shift DEHL << 1, inserting the carry on the right
rl l
rl h
rl e
rl d
djnz __FTOU32REG_LOOP
__FTOU32REG_END:
pop af ; Take the sign bit
or a ; Sets SGN bit to 1 if negative
jp m, __NEGATE ; Negates DEHL
ret
__NEGATE:
exx
ld a, d
or e
or b
or c
exx
jr z, __END
inc l
jr nz, __END
inc h
jr nz, __END
inc de
LOCAL __END
__END:
jp __NEG32
ENDP
__FTOU8: ; Converts float in C ED LH to Unsigned byte in A
call __FTOU32REG
ld a, l
ret
pop namespace
#line 92 "arch/zx48k/cast_const_to_int.bas"
END
25 changes: 25 additions & 0 deletions tests/functional/arch/zx48k/cast_const_to_int.bas
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
dim var_neg as fixed = -1.5
const const_neg as fixed = -1.5
dim var as Fixed = 1.5
const const_ as fixed = 1.5
dim var_neg_fl as Float = -1.5
const const_neg_fl as Float = -1.5

DIM r_int as Integer
DIM r_long as Long
DIM r_ulong as ULong

LET r_int = cast(integer, var_neg)
LET r_int = cast(integer, const_neg)
LET r_long = cast(long, var_neg)
LET r_ulong = cast(ulong, var_neg)

LET r_int = cast(integer, var)
LET r_int = cast(integer, const_)
LET r_long = cast(long, var)
LET r_ulong = cast(ulong, var)

LET r_int = cast(integer, var_neg_fl)
LET r_int = cast(integer, const_neg_fl)
LET r_long = cast(long, var_neg_fl)
LET r_ulong = cast(ulong, var_neg_fl)
5 changes: 5 additions & 0 deletions tests/functional/arch/zx48k/cast_f16_to_long.asm
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ _v2:
ld de, (_v1 + 2)
ex de, hl
ld de, 0
ld a, h
add a, a
sbc a, a
ld e, a
ld d, a
ld (_v2), hl
ld (_v2 + 2), de
ld hl, 0
Expand Down
5 changes: 5 additions & 0 deletions tests/functional/arch/zx48k/cast_f16_to_ulong.asm
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ _v2:
ld de, (_v1 + 2)
ex de, hl
ld de, 0
ld a, h
add a, a
sbc a, a
ld e, a
ld d, a
ld (_v2), hl
ld (_v2 + 2), de
ld hl, 0
Expand Down
Loading