Skip to content

Commit 2267d17

Browse files
committed
fix: Access to array elem by ref broken
The access byRef to an array element with no constant address was broken because it was being considered constant always.
1 parent e8e68af commit 2267d17

3 files changed

Lines changed: 260 additions & 1 deletion

File tree

src/arch/z80/visitor/translator.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,9 @@ def visit_ARGUMENT(self, node):
245245
return
246246

247247
# Must compute Address of @array(...)
248-
if node.value.scope == SCOPE.global_ and self.O_LEVEL > 1: # Calculate offset if global variable
248+
if (
249+
self.O_LEVEL > 1 and node.value.scope == SCOPE.global_ and node.value.offset
250+
): # Calculate offset if global variable
249251
node.value = SymbolBINARY.make_node(
250252
"PLUS",
251253
symbols.UNARY("ADDRESS", node.value.entry, node.value.lineno, type_=self.TYPE(gl.PTR_TYPE)),
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
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+
_i:
20+
DEFB 03h
21+
DEFB 00h
22+
_myArray:
23+
DEFW .LABEL.__LABEL0
24+
_myArray.__DATA__.__PTR__:
25+
DEFW _myArray.__DATA__
26+
DEFW 0
27+
DEFW 0
28+
_myArray.__DATA__:
29+
DEFB 00h
30+
DEFB 00h
31+
DEFB 00h
32+
DEFB 00h
33+
DEFB 00h
34+
DEFB 00h
35+
.LABEL.__LABEL0:
36+
DEFW 0000h
37+
DEFB 01h
38+
.core.ZXBASIC_USER_DATA_END:
39+
.core.__MAIN_PROGRAM__:
40+
ld hl, (_i)
41+
push hl
42+
ld hl, _myArray
43+
call .core.__ARRAY
44+
push hl
45+
call _plusOne
46+
ld hl, (_i)
47+
push hl
48+
ld hl, _myArray
49+
call .core.__ARRAY
50+
ld a, (hl)
51+
ld (0), a
52+
ld hl, 0
53+
ld b, h
54+
ld c, l
55+
.core.__END_PROGRAM:
56+
di
57+
ld hl, (.core.__CALL_BACK__)
58+
ld sp, hl
59+
exx
60+
pop hl
61+
pop iy
62+
pop ix
63+
exx
64+
ei
65+
ret
66+
_plusOne:
67+
push ix
68+
ld ix, 0
69+
add ix, sp
70+
ld h, (ix+5)
71+
ld l, (ix+4)
72+
ld a, (hl)
73+
inc a
74+
ld h, (ix+5)
75+
ld l, (ix+4)
76+
ld (hl), a
77+
_plusOne__leave:
78+
ld sp, ix
79+
pop ix
80+
exx
81+
pop hl
82+
ex (sp), hl
83+
exx
84+
ret
85+
;; --- end of user code ---
86+
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/array/array.asm"
87+
; vim: ts=4:et:sw=4:
88+
; Copyleft (K) by Jose M. Rodriguez de la Rosa
89+
; (a.k.a. Boriel)
90+
; http://www.boriel.com
91+
; -------------------------------------------------------------------
92+
; Simple array Index routine
93+
; Number of total indexes dimensions - 1 at beginning of memory
94+
; HL = Start of array memory (First two bytes contains N-1 dimensions)
95+
; Dimension values on the stack, (top of the stack, highest dimension)
96+
; E.g. A(2, 4) -> PUSH <4>; PUSH <2>
97+
; For any array of N dimension A(aN-1, ..., a1, a0)
98+
; and dimensions D[bN-1, ..., b1, b0], the offset is calculated as
99+
; O = [a0 + b0 * (a1 + b1 * (a2 + ... bN-2(aN-1)))]
100+
; What I will do here is to calculate the following sequence:
101+
; ((aN-1 * bN-2) + aN-2) * bN-3 + ...
102+
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/fmul16.asm"
103+
;; Performs a faster multiply for little 16bit numbs
104+
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mul16.asm"
105+
push namespace core
106+
__MUL16: ; Mutiplies HL with the last value stored into de stack
107+
; Works for both signed and unsigned
108+
PROC
109+
LOCAL __MUL16LOOP
110+
LOCAL __MUL16NOADD
111+
ex de, hl
112+
pop hl ; Return address
113+
ex (sp), hl ; CALLEE caller convention
114+
__MUL16_FAST:
115+
ld b, 16
116+
ld a, h
117+
ld c, l
118+
ld hl, 0
119+
__MUL16LOOP:
120+
add hl, hl ; hl << 1
121+
sla c
122+
rla ; a,c << 1
123+
jp nc, __MUL16NOADD
124+
add hl, de
125+
__MUL16NOADD:
126+
djnz __MUL16LOOP
127+
ret ; Result in hl (16 lower bits)
128+
ENDP
129+
pop namespace
130+
#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/arith/fmul16.asm"
131+
push namespace core
132+
__FMUL16:
133+
xor a
134+
or h
135+
jp nz, __MUL16_FAST
136+
or l
137+
ret z
138+
cp 33
139+
jp nc, __MUL16_FAST
140+
ld b, l
141+
ld l, h ; HL = 0
142+
1:
143+
add hl, de
144+
djnz 1b
145+
ret
146+
pop namespace
147+
#line 20 "/zxbasic/src/lib/arch/zx48k/runtime/array/array.asm"
148+
#line 24 "/zxbasic/src/lib/arch/zx48k/runtime/array/array.asm"
149+
push namespace core
150+
__ARRAY_PTR: ;; computes an array offset from a pointer
151+
ld c, (hl)
152+
inc hl
153+
ld h, (hl)
154+
ld l, c ;; HL <-- [HL]
155+
__ARRAY:
156+
PROC
157+
LOCAL LOOP
158+
LOCAL ARRAY_END
159+
LOCAL TMP_ARR_PTR ; Ptr to Array DATA region. Stored temporarily
160+
LOCAL LBOUND_PTR, UBOUND_PTR ; LBound and UBound PTR indexes
161+
LOCAL RET_ADDR ; Contains the return address popped from the stack
162+
LBOUND_PTR EQU 23698 ; Uses MEMBOT as a temporary variable
163+
UBOUND_PTR EQU LBOUND_PTR + 2 ; Next 2 bytes for UBOUND PTR
164+
RET_ADDR EQU UBOUND_PTR + 2 ; Next 2 bytes for RET_ADDR
165+
TMP_ARR_PTR EQU RET_ADDR + 2 ; Next 2 bytes for TMP_ARR_PTR
166+
ld e, (hl)
167+
inc hl
168+
ld d, (hl)
169+
inc hl ; DE <-- PTR to Dim sizes table
170+
ld (TMP_ARR_PTR), hl ; HL = Array __DATA__.__PTR__
171+
inc hl
172+
inc hl
173+
ld c, (hl)
174+
inc hl
175+
ld b, (hl) ; BC <-- Array __LBOUND__ PTR
176+
ld (LBOUND_PTR), bc ; Store it for later
177+
#line 66 "/zxbasic/src/lib/arch/zx48k/runtime/array/array.asm"
178+
ex de, hl ; HL <-- PTR to Dim sizes table, DE <-- dummy
179+
ex (sp), hl ; Return address in HL, PTR Dim sizes table onto Stack
180+
ld (RET_ADDR), hl ; Stores it for later
181+
exx
182+
pop hl ; Will use H'L' as the pointer to Dim sizes table
183+
ld c, (hl) ; Loads Number of dimensions from (hl)
184+
inc hl
185+
ld b, (hl)
186+
inc hl ; Ready
187+
exx
188+
ld hl, 0 ; HL = Element Offset "accumulator"
189+
LOOP:
190+
ex de, hl ; DE = Element Offset
191+
ld hl, (LBOUND_PTR)
192+
ld a, h
193+
or l
194+
ld b, h
195+
ld c, l
196+
jr z, 1f
197+
ld c, (hl)
198+
inc hl
199+
ld b, (hl)
200+
inc hl
201+
ld (LBOUND_PTR), hl
202+
1:
203+
pop hl ; Get next index (Ai) from the stack
204+
sbc hl, bc ; Subtract LBOUND
205+
#line 116 "/zxbasic/src/lib/arch/zx48k/runtime/array/array.asm"
206+
add hl, de ; Adds current index
207+
exx ; Checks if B'C' = 0
208+
ld a, b ; Which means we must exit (last element is not multiplied by anything)
209+
or c
210+
jr z, ARRAY_END ; if B'Ci == 0 we are done
211+
dec bc ; Decrements loop counter
212+
ld e, (hl) ; Loads next dimension size into D'E'
213+
inc hl
214+
ld d, (hl)
215+
inc hl
216+
push de
217+
exx
218+
pop de ; DE = Max bound Number (i-th dimension)
219+
call __FMUL16 ; HL <= HL * DE mod 65536
220+
jp LOOP
221+
ARRAY_END:
222+
ld a, (hl)
223+
exx
224+
#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/array/array.asm"
225+
LOCAL ARRAY_SIZE_LOOP
226+
ex de, hl
227+
ld hl, 0
228+
ld b, a
229+
ARRAY_SIZE_LOOP:
230+
add hl, de
231+
djnz ARRAY_SIZE_LOOP
232+
#line 156 "/zxbasic/src/lib/arch/zx48k/runtime/array/array.asm"
233+
ex de, hl
234+
ld hl, (TMP_ARR_PTR)
235+
ld a, (hl)
236+
inc hl
237+
ld h, (hl)
238+
ld l, a
239+
add hl, de ; Adds element start
240+
ld de, (RET_ADDR)
241+
push de
242+
ret
243+
ENDP
244+
pop namespace
245+
#line 48 "arch/zx48k/opt2_arr_elem_by_ref04.bas"
246+
END
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
SUB plusOne(ByRef a As Ubyte)
2+
LET a = a + 1
3+
END SUB
4+
5+
DIM i as UInteger = 3
6+
DIM myArray(5) as Ubyte
7+
8+
plusOne(myArray(i))
9+
POKE 0, myArray(i)
10+
11+

0 commit comments

Comments
 (0)