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
4 changes: 3 additions & 1 deletion src/arch/z80/visitor/function_translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ def visit_FUNCTION(self, node):
if local_var.class_ == CLASS.array and local_var.scope == SCOPE.local:
lbound_label = local_var.mangled + ".__LBOUND__"
ubound_label = local_var.mangled + ".__UBOUND__"
lbound_needed = not local_var.is_zero_based and local_var.is_dynamically_accessed
lbound_needed = not local_var.is_zero_based and (
local_var.is_dynamically_accessed or local_var.lbound_used
)

bound_ptrs = [lbound_label if lbound_needed else "0", "0"]
if local_var.ubound_used:
Expand Down
2 changes: 1 addition & 1 deletion src/arch/z80/visitor/var_translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def visit_ARRAYDECL(self, node):
ubound_label = entry.mangled + ".__UBOUND__"
bound_ptrs = ["0", "0"] # NULL by default

if not entry.is_zero_based and entry.is_dynamically_accessed:
if not entry.is_zero_based and (entry.is_dynamically_accessed or entry.lbound_used):
bound_ptrs[0] = lbound_label

if entry.ubound_used or OPTIONS.array_check:
Expand Down
13 changes: 10 additions & 3 deletions src/symbols/call.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# --------------------------------------------------------------------

from collections.abc import Iterable
from typing import Optional
from typing import Self

import src.api.global_ as gl
from src.api import check, errmsg
Expand Down Expand Up @@ -46,6 +46,13 @@ def __init__(self, entry: SymbolID, arglist: Iterable[SymbolARGUMENT], lineno: i
for arg, param in zip(arglist, ref.params): # Sets dependency graph for each argument -> parameter
if arg.value is not None:
arg.value.add_required_symbol(param)
if (
isinstance(arg.value, SymbolID)
and arg.value.class_ == CLASS.array
and param.class_ == CLASS.array
and param.ref.is_dynamically_accessed is True
):
arg.value.ref.is_dynamically_accessed = True

@property
def entry(self):
Expand Down Expand Up @@ -80,7 +87,7 @@ def type_(self):
return self.entry.type_

@classmethod
def make_node(cls, id_: str, params, lineno: int, filename: str) -> Optional["SymbolCALL"]:
def make_node(cls, id_: str, params, lineno: int, filename: str) -> Self | None:
"""This will return an AST node for a function/procedure call."""
assert isinstance(params, SymbolARGLIST)
entry = gl.SYMBOL_TABLE.access_func(id_, lineno)
Expand All @@ -94,7 +101,7 @@ def make_node(cls, id_: str, params, lineno: int, filename: str) -> Optional["Sy

if entry.declared and not entry.forwarded:
check.check_call_arguments(lineno, id_, params, filename)
else: # All functions goes to global scope by default
else: # All functions go to global scope by default
if entry.token != "FUNCTION":
entry = entry.to_function(lineno)
gl.SYMBOL_TABLE.move_to_global_scope(id_)
Expand Down
237 changes: 237 additions & 0 deletions tests/functional/arch/zx48k/array13.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
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
_array:
DEFW .LABEL.__LABEL0
_array.__DATA__.__PTR__:
DEFW _array.__DATA__
DEFW _array.__LBOUND__
DEFW 0
_array.__DATA__:
DEFB 00h
DEFB 00h
.LABEL.__LABEL0:
DEFW 0000h
DEFB 01h
_array.__LBOUND__:
DEFW 0001h
.core.ZXBASIC_USER_DATA_END:
.core.__MAIN_PROGRAM__:
ld hl, _array
push hl
call _test
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
_test:
push ix
ld ix, 0
add ix, sp
ld hl, 0
push hl
ld l, (ix-2)
ld h, (ix-1)
push hl
push ix
pop hl
ld de, 4
add hl, de
call .core.__ARRAY_PTR
ld a, (hl)
ld (0), a
_test__leave:
ld sp, ix
pop ix
exx
pop hl
ex (sp), hl
exx
ret
;; --- end of user code ---
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/array/array.asm"
; vim: ts=4:et:sw=4:
; Copyleft (K) by Jose M. Rodriguez de la Rosa
; (a.k.a. Boriel)
; http://www.boriel.com
; -------------------------------------------------------------------
; Simple array Index routine
; Number of total indexes dimensions - 1 at beginning of memory
; HL = Start of array memory (First two bytes contains N-1 dimensions)
; Dimension values on the stack, (top of the stack, highest dimension)
; E.g. A(2, 4) -> PUSH <4>; PUSH <2>
; For any array of N dimension A(aN-1, ..., a1, a0)
; and dimensions D[bN-1, ..., b1, b0], the offset is calculated as
; O = [a0 + b0 * (a1 + b1 * (a2 + ... bN-2(aN-1)))]
; What I will do here is to calculate the following sequence:
; ((aN-1 * bN-2) + aN-2) * bN-3 + ...
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/fmul16.asm"
;; Performs a faster multiply for little 16bit numbs
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mul16.asm"
push namespace core
__MUL16: ; Mutiplies HL with the last value stored into de stack
; Works for both signed and unsigned
PROC
LOCAL __MUL16LOOP
LOCAL __MUL16NOADD
ex de, hl
pop hl ; Return address
ex (sp), hl ; CALLEE caller convention
__MUL16_FAST:
ld b, 16
ld a, h
ld c, l
ld hl, 0
__MUL16LOOP:
add hl, hl ; hl << 1
sla c
rla ; a,c << 1
jp nc, __MUL16NOADD
add hl, de
__MUL16NOADD:
djnz __MUL16LOOP
ret ; Result in hl (16 lower bits)
ENDP
pop namespace
#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/arith/fmul16.asm"
push namespace core
__FMUL16:
xor a
or h
jp nz, __MUL16_FAST
or l
ret z
cp 33
jp nc, __MUL16_FAST
ld b, l
ld l, h ; HL = 0
1:
add hl, de
djnz 1b
ret
pop namespace
#line 20 "/zxbasic/src/lib/arch/zx48k/runtime/array/array.asm"
#line 24 "/zxbasic/src/lib/arch/zx48k/runtime/array/array.asm"
push namespace core
__ARRAY_PTR: ;; computes an array offset from a pointer
ld c, (hl)
inc hl
ld h, (hl)
ld l, c ;; HL <-- [HL]
__ARRAY:
PROC
LOCAL LOOP
LOCAL ARRAY_END
LOCAL TMP_ARR_PTR ; Ptr to Array DATA region. Stored temporarily
LOCAL LBOUND_PTR, UBOUND_PTR ; LBound and UBound PTR indexes
LOCAL RET_ADDR ; Contains the return address popped from the stack
LBOUND_PTR EQU 23698 ; Uses MEMBOT as a temporary variable
UBOUND_PTR EQU LBOUND_PTR + 2 ; Next 2 bytes for UBOUND PTR
RET_ADDR EQU UBOUND_PTR + 2 ; Next 2 bytes for RET_ADDR
TMP_ARR_PTR EQU RET_ADDR + 2 ; Next 2 bytes for TMP_ARR_PTR
ld e, (hl)
inc hl
ld d, (hl)
inc hl ; DE <-- PTR to Dim sizes table
ld (TMP_ARR_PTR), hl ; HL = Array __DATA__.__PTR__
inc hl
inc hl
ld c, (hl)
inc hl
ld b, (hl) ; BC <-- Array __LBOUND__ PTR
ld (LBOUND_PTR), bc ; Store it for later
#line 66 "/zxbasic/src/lib/arch/zx48k/runtime/array/array.asm"
ex de, hl ; HL <-- PTR to Dim sizes table, DE <-- dummy
ex (sp), hl ; Return address in HL, PTR Dim sizes table onto Stack
ld (RET_ADDR), hl ; Stores it for later
exx
pop hl ; Will use H'L' as the pointer to Dim sizes table
ld c, (hl) ; Loads Number of dimensions from (hl)
inc hl
ld b, (hl)
inc hl ; Ready
exx
ld hl, 0 ; HL = Element Offset "accumulator"
LOOP:
ex de, hl ; DE = Element Offset
ld hl, (LBOUND_PTR)
ld a, h
or l
ld b, h
ld c, l
jr z, 1f
ld c, (hl)
inc hl
ld b, (hl)
inc hl
ld (LBOUND_PTR), hl
1:
pop hl ; Get next index (Ai) from the stack
sbc hl, bc ; Subtract LBOUND
#line 116 "/zxbasic/src/lib/arch/zx48k/runtime/array/array.asm"
add hl, de ; Adds current index
exx ; Checks if B'C' = 0
ld a, b ; Which means we must exit (last element is not multiplied by anything)
or c
jr z, ARRAY_END ; if B'Ci == 0 we are done
dec bc ; Decrements loop counter
ld e, (hl) ; Loads next dimension size into D'E'
inc hl
ld d, (hl)
inc hl
push de
exx
pop de ; DE = Max bound Number (i-th dimension)
call __FMUL16 ; HL <= HL * DE mod 65536
jp LOOP
ARRAY_END:
ld a, (hl)
exx
#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/array/array.asm"
LOCAL ARRAY_SIZE_LOOP
ex de, hl
ld hl, 0
ld b, a
ARRAY_SIZE_LOOP:
add hl, de
djnz ARRAY_SIZE_LOOP
#line 156 "/zxbasic/src/lib/arch/zx48k/runtime/array/array.asm"
ex de, hl
ld hl, (TMP_ARR_PTR)
ld a, (hl)
inc hl
ld h, (hl)
ld l, a
add hl, de ; Adds element start
ld de, (RET_ADDR)
push de
ret
ENDP
pop namespace
#line 44 "arch/zx48k/array13.bas"
END
9 changes: 9 additions & 0 deletions tests/functional/arch/zx48k/array13.bas
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
SUB test(arr() As UByte)
DIM i As UInteger
POKE 0, arr(i)
END SUB

DIM array(1 TO 2) As UByte

test array

5 changes: 4 additions & 1 deletion tests/functional/arch/zx48k/bound02.asm
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ _a:
DEFW .LABEL.__LABEL0
_a.__DATA__.__PTR__:
DEFW _a.__DATA__
DEFW 0
DEFW _a.__LBOUND__
DEFW 0
_a.__DATA__:
DEFB 00h
Expand Down Expand Up @@ -87,6 +87,9 @@ _a.__DATA__:
DEFW 0001h
DEFW 0004h
DEFB 02h
_a.__LBOUND__:
DEFW 0002h
DEFW 0003h
.core.ZXBASIC_USER_DATA_END:
.core.__MAIN_PROGRAM__:
ld a, 1
Expand Down
Loading