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
24 changes: 14 additions & 10 deletions src/api/optimize.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,16 +321,20 @@ def visit_LET(self, node):
lvalue = node.children[0]
if self.O_LEVEL > 1 and not lvalue.accessed:
warning_not_used(lvalue.lineno, lvalue.name, fname=lvalue.filename)
block = symbols.BLOCK(
*[
symbols.CALL(x.entry, x.args, x.lineno, lvalue.filename)
for x in self.filter_inorder(
node.children[1],
lambda x: x.token == "FUNCCALL",
lambda x: x.token != "FUNCTION",
)
]
)
nodes = [
symbols.CALL(x.entry, x.args, x.lineno, lvalue.filename) if x.token == "FUNCCALL" else x
for x in self.filter_inorder(
node.children[1],
lambda x: x.token in ("FUNCCALL", "BUILTIN"),
lambda x: x.token != "FUNCTION",
)
if x.token == "FUNCCALL" or getattr(x, "fname") in {"IN", "RND", "USR"}
]
for node_ in nodes:
if node_.token == "BUILTIN":
node_.discard_result = True

block = symbols.BLOCK(*nodes)
yield block
else:
yield (yield self.generic_visit(node))
Expand Down
2 changes: 2 additions & 0 deletions src/arch/z80/visitor/translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ def visit_BUILTIN(self, node):
att = f"visit_{node.fname}"
if hasattr(bvisitor, att):
yield getattr(bvisitor, att)(node)
if node.discard_result:
self.ic_fparam(node.type_, optemps.new_t())
return

raise InvalidBuiltinFunctionError(node.fname)
Expand Down
3 changes: 2 additions & 1 deletion src/symbols/builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@


class SymbolBUILTIN(Symbol):
"""Defines an BUILTIN function e.g. INKEY$(), RND() or LEN"""
"""Defines a BUILTIN function e.g. INKEY$(), RND() or LEN"""

def __init__(self, lineno, fname, type_=None, *operands):
assert isinstance(lineno, int)
Expand All @@ -22,6 +22,7 @@ def __init__(self, lineno, fname, type_=None, *operands):
self.lineno = lineno
self.fname = fname
self.type_ = type_
self.discard_result = False # Whether to discard the return value of the function

@property
def type_(self):
Expand Down
38 changes: 38 additions & 0 deletions tests/functional/arch/zx48k/opt2_in_opt.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
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
.core.ZXBASIC_USER_DATA_END:
.core.__MAIN_PROGRAM__:
ld bc, 0
in a, (c)
ld hl, 0
ld b, h
ld c, l
.core.__END_PROGRAM:
di
ld hl, (.core.__CALL_BACK__)
ld sp, hl
exx
pop hl
pop iy
pop ix
exx
ei
ret
;; --- end of user code ---
END
3 changes: 3 additions & 0 deletions tests/functional/arch/zx48k/opt2_in_opt.bas
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
REM USR 0 must be compiled despite c being optimized
LET c = IN 0

127 changes: 127 additions & 0 deletions tests/functional/arch/zx48k/opt2_rnd_opt.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
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
.core.ZXBASIC_USER_DATA_END:
.core.__MAIN_PROGRAM__:
call .core.RND
ld hl, 0
ld b, h
ld c, l
.core.__END_PROGRAM:
di
ld hl, (.core.__CALL_BACK__)
ld sp, hl
exx
pop hl
pop iy
pop ix
exx
ei
ret
;; --- end of user code ---
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/random.asm"
; RANDOM functions
push namespace core
RANDOMIZE:
; Randomize with 32 bit seed in DE HL
; if SEED = 0, calls ROM to take frames as seed
PROC
LOCAL TAKE_FRAMES
LOCAL FRAMES
ld a, h
or l
or d
or e
jr z, TAKE_FRAMES
ld (RANDOM_SEED_LOW), hl
ld (RANDOM_SEED_HIGH), de
ret
TAKE_FRAMES:
; Takes the seed from frames
ld hl, (FRAMES)
ld (RANDOM_SEED_LOW), hl
ld hl, (FRAMES + 2)
ld (RANDOM_SEED_HIGH), hl
ret
FRAMES EQU 23672
ENDP
RANDOM_SEED_HIGH EQU RAND+1 ; RANDOM seed, 16 higher bits
RANDOM_SEED_LOW EQU 23670 ; RANDOM seed, 16 lower bits
RAND:
PROC
ld de,0C0DEh ; yw -> zt
ld hl,(RANDOM_SEED_LOW) ; xz -> yw
ld (RANDOM_SEED_LOW),de ; x = y, z = w
ld a,e ; w = w ^ ( w << 3 )
add a,a
add a,a
add a,a
xor e
ld e,a
ld a,h ; t = x ^ (x << 1)
add a,a
xor h
ld d,a
rra ; t = t ^ (t >> 1) ^ w
xor d
xor e
ld d,l ; y = z
ld e,a ; w = t
ld (RANDOM_SEED_HIGH),de
ret
ENDP
RND:
; Returns a FLOATING point integer
; using RAND as a mantissa
PROC
LOCAL RND_LOOP
call RAND
; BC = HL since ZX BASIC uses ED CB A registers for FP
ld b, h
ld c, l
ld a, e
or d
or c
or b
ret z ; Returns 0 if BC=DE=0
; We already have a random 32 bit mantissa in ED CB
; From 0001h to FFFFh
ld l, 81h ; Exponent
; At this point we have [0 .. 1) FP number;
; Now we must shift mantissa left until highest bit goes into carry
ld a, e ; Use A register for rotating E faster (using RLA instead of RL E)
RND_LOOP:
dec l
sla b
rl c
rl d
rla
jp nc, RND_LOOP
; Now undo last mantissa left-shift once
ccf ; Clears carry to insert a 0 bit back into mantissa -> positive FP number
rra
rr d
rr c
rr b
ld e, a ; E must have the highest byte
ld a, l ; exponent in A
ret
ENDP
pop namespace
#line 18 "arch/zx48k/opt2_rnd_opt.bas"
END
3 changes: 3 additions & 0 deletions tests/functional/arch/zx48k/opt2_rnd_opt.bas
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
REM USR 0 must be compiled despite c being optimized
LET c = RND

73 changes: 73 additions & 0 deletions tests/functional/arch/zx48k/opt2_usr_opt.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
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
.core.ZXBASIC_USER_DATA_END:
.core.__MAIN_PROGRAM__:
ld hl, 0
call .core.USR
ld hl, 0
ld b, h
ld c, l
.core.__END_PROGRAM:
di
ld hl, (.core.__CALL_BACK__)
ld sp, hl
exx
pop hl
pop iy
pop ix
exx
ei
ret
;; --- end of user code ---
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/usr.asm"
; Emulates the USR Sinclair BASIC function
; Result value returns in BC
; We use HL for returning values, su we must
; copy BC into HL before returning
;
; The incoming parameter is HL (Address to JUMP)
;
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm"
push namespace core
JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A
add a, a
JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE
ld e, a
ld d, 0
JUMP_HL_PLUS_DE: ; Does JP (HL + DE)
add hl, de
ld e, (hl)
inc hl
ld d, (hl)
ex de, hl
CALL_HL:
jp (hl)
pop namespace
#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/usr.asm"
push namespace core
USR:
push ix ; must preserve IX
call CALL_HL
pop ix
ld h, b
ld l, c
ret
pop namespace
#line 19 "arch/zx48k/opt2_usr_opt.bas"
END
3 changes: 3 additions & 0 deletions tests/functional/arch/zx48k/opt2_usr_opt.bas
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
REM USR 0 must be compiled despite c being optimized
LET c = USR 0