From 4a82c6281fe73f17da29d8a6d0a73f210a7529a1 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sun, 8 Feb 2026 13:38:46 +0100 Subject: [PATCH 1/2] fix: cast f16 to long or ulong was broken --- src/arch/z80/backend/common.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/arch/z80/backend/common.py b/src/arch/z80/backend/common.py index 436413833..6f25dc8d2 100644 --- a/src/arch/z80/backend/common.py +++ b/src/arch/z80/backend/common.py @@ -385,19 +385,24 @@ def to_long(stype: DataType) -> list[str]: ) return output - if stype in {I8_t, U8_t, F16_t}: # Byte to word + if stype in (I8_t, U8_t): # Byte to word output = to_word(stype) + output.append("ld e, h") + output.append("ld d, h") - if stype != F16_t: # If it's a byte, just copy H to D,E - output.append("ld e, h") - output.append("ld d, h") + elif stype == I16_t: # Signed byte or fixed to word + output.extend( + [ + "ld a, h", + "add a, a", + "sbc a, a", + "ld e, a", + "ld d, a", + ] + ) - elif stype in (I16_t, F16_t): # Signed byte or fixed to word - output.append("ld a, h") - output.append("add a, a") - output.append("sbc a, a") - output.append("ld e, a") - output.append("ld d, a") + elif stype == F16_t: + output.extend(["ex de, hl", "ld de, 0"]) elif stype in (U32_t, I32_t): return [] From 4f362f4dba58a43d74088c736ffb87d5e437b9bc Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sun, 8 Feb 2026 13:48:01 +0100 Subject: [PATCH 2/2] Add tests --- .../arch/zx48k/cast_f16_to_long.asm | 49 +++++++++++++++++++ .../arch/zx48k/cast_f16_to_long.bas | 5 ++ .../arch/zx48k/cast_f16_to_ulong.asm | 49 +++++++++++++++++++ .../arch/zx48k/cast_f16_to_ulong.bas | 5 ++ .../arch/zxnext/cast_f16_to_long.asm | 42 ++++++++++++++++ .../arch/zxnext/cast_f16_to_long.bas | 5 ++ .../arch/zxnext/cast_f16_to_ulong.asm | 42 ++++++++++++++++ .../arch/zxnext/cast_f16_to_ulong.bas | 5 ++ 8 files changed, 202 insertions(+) create mode 100644 tests/functional/arch/zx48k/cast_f16_to_long.asm create mode 100644 tests/functional/arch/zx48k/cast_f16_to_long.bas create mode 100644 tests/functional/arch/zx48k/cast_f16_to_ulong.asm create mode 100644 tests/functional/arch/zx48k/cast_f16_to_ulong.bas create mode 100644 tests/functional/arch/zxnext/cast_f16_to_long.asm create mode 100644 tests/functional/arch/zxnext/cast_f16_to_long.bas create mode 100644 tests/functional/arch/zxnext/cast_f16_to_ulong.asm create mode 100644 tests/functional/arch/zxnext/cast_f16_to_ulong.bas diff --git a/tests/functional/arch/zx48k/cast_f16_to_long.asm b/tests/functional/arch/zx48k/cast_f16_to_long.asm new file mode 100644 index 000000000..547845bad --- /dev/null +++ b/tests/functional/arch/zx48k/cast_f16_to_long.asm @@ -0,0 +1,49 @@ + 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 +_v1: + DEFB 00h + DEFB 80h + DEFB 01h + DEFB 00h +_v2: + DEFB 00, 00, 00, 00 +.core.ZXBASIC_USER_DATA_END: +.core.__MAIN_PROGRAM__: + ld hl, (_v1) + ld de, (_v1 + 2) + ex de, hl + ld de, 0 + ld (_v2), hl + ld (_v2 + 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 --- + END diff --git a/tests/functional/arch/zx48k/cast_f16_to_long.bas b/tests/functional/arch/zx48k/cast_f16_to_long.bas new file mode 100644 index 000000000..b8f1315d7 --- /dev/null +++ b/tests/functional/arch/zx48k/cast_f16_to_long.bas @@ -0,0 +1,5 @@ +DIM v1 As Fixed = 1.5 +DIM v2 As Long + +v2 = v1 + diff --git a/tests/functional/arch/zx48k/cast_f16_to_ulong.asm b/tests/functional/arch/zx48k/cast_f16_to_ulong.asm new file mode 100644 index 000000000..547845bad --- /dev/null +++ b/tests/functional/arch/zx48k/cast_f16_to_ulong.asm @@ -0,0 +1,49 @@ + 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 +_v1: + DEFB 00h + DEFB 80h + DEFB 01h + DEFB 00h +_v2: + DEFB 00, 00, 00, 00 +.core.ZXBASIC_USER_DATA_END: +.core.__MAIN_PROGRAM__: + ld hl, (_v1) + ld de, (_v1 + 2) + ex de, hl + ld de, 0 + ld (_v2), hl + ld (_v2 + 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 --- + END diff --git a/tests/functional/arch/zx48k/cast_f16_to_ulong.bas b/tests/functional/arch/zx48k/cast_f16_to_ulong.bas new file mode 100644 index 000000000..e805c2240 --- /dev/null +++ b/tests/functional/arch/zx48k/cast_f16_to_ulong.bas @@ -0,0 +1,5 @@ +DIM v1 As Fixed = 1.5 +DIM v2 As ULong + +v2 = v1 + diff --git a/tests/functional/arch/zxnext/cast_f16_to_long.asm b/tests/functional/arch/zxnext/cast_f16_to_long.asm new file mode 100644 index 000000000..53c65b0ce --- /dev/null +++ b/tests/functional/arch/zxnext/cast_f16_to_long.asm @@ -0,0 +1,42 @@ + org 32768 +.core.__START_PROGRAM: + di + push iy + ld iy, 0x5C3A ; ZX Spectrum ROM variables address + 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 +_v1: + DEFB 00h + DEFB 80h + DEFB 01h + DEFB 00h +_v2: + DEFB 00, 00, 00, 00 +.core.ZXBASIC_USER_DATA_END: +.core.__MAIN_PROGRAM__: + ld hl, (_v1) + ld de, (_v1 + 2) + ex de, hl + ld de, 0 + ld (_v2), hl + ld (_v2 + 2), de + ld hl, 0 + ld b, h + ld c, l +.core.__END_PROGRAM: + di + ld hl, (.core.__CALL_BACK__) + ld sp, hl + pop iy + ei + ret + ;; --- end of user code --- + END diff --git a/tests/functional/arch/zxnext/cast_f16_to_long.bas b/tests/functional/arch/zxnext/cast_f16_to_long.bas new file mode 100644 index 000000000..b8f1315d7 --- /dev/null +++ b/tests/functional/arch/zxnext/cast_f16_to_long.bas @@ -0,0 +1,5 @@ +DIM v1 As Fixed = 1.5 +DIM v2 As Long + +v2 = v1 + diff --git a/tests/functional/arch/zxnext/cast_f16_to_ulong.asm b/tests/functional/arch/zxnext/cast_f16_to_ulong.asm new file mode 100644 index 000000000..53c65b0ce --- /dev/null +++ b/tests/functional/arch/zxnext/cast_f16_to_ulong.asm @@ -0,0 +1,42 @@ + org 32768 +.core.__START_PROGRAM: + di + push iy + ld iy, 0x5C3A ; ZX Spectrum ROM variables address + 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 +_v1: + DEFB 00h + DEFB 80h + DEFB 01h + DEFB 00h +_v2: + DEFB 00, 00, 00, 00 +.core.ZXBASIC_USER_DATA_END: +.core.__MAIN_PROGRAM__: + ld hl, (_v1) + ld de, (_v1 + 2) + ex de, hl + ld de, 0 + ld (_v2), hl + ld (_v2 + 2), de + ld hl, 0 + ld b, h + ld c, l +.core.__END_PROGRAM: + di + ld hl, (.core.__CALL_BACK__) + ld sp, hl + pop iy + ei + ret + ;; --- end of user code --- + END diff --git a/tests/functional/arch/zxnext/cast_f16_to_ulong.bas b/tests/functional/arch/zxnext/cast_f16_to_ulong.bas new file mode 100644 index 000000000..e805c2240 --- /dev/null +++ b/tests/functional/arch/zxnext/cast_f16_to_ulong.bas @@ -0,0 +1,5 @@ +DIM v1 As Fixed = 1.5 +DIM v2 As ULong + +v2 = v1 +