Skip to content

Commit 06ba6a5

Browse files
committed
Fix address of arrayaccess
Should be optimized only for global arrays. For local and parameters it works in different way. Test updated.
1 parent 3556798 commit 06ba6a5

9 files changed

Lines changed: 458 additions & 29 deletions

File tree

api/optimize.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import api.errmsg
77
from api.errmsg import warning
88
import api.check as chk
9-
from api.constants import TYPE
9+
from api.constants import TYPE, SCOPE
1010
import api.global_ as gl
1111
import symbols
1212
import types
@@ -85,14 +85,14 @@ def visit_ADDRESS(self, node):
8585
if node.operand.token != 'ARRAYACCESS':
8686
if not chk.is_dynamic(node.operand):
8787
node = symbols.CONST(node, node.lineno)
88-
elif node.operand.offset is not None: # A constant access. Calculate offset
89-
node = symbols.BINARY.make_node('PLUS',
90-
symbols.UNARY('ADDRESS', node.operand.entry, node.lineno,
91-
type_=self.TYPE(gl.PTR_TYPE)),
92-
symbols.NUMBER(node.operand.offset, lineno=node.operand.lineno,
93-
type_=self.TYPE(gl.PTR_TYPE)),
94-
lineno=node.lineno, func=lambda x, y: x + y
95-
)
88+
elif node.operand.offset is not None: # A constant access
89+
if node.operand.scope == SCOPE.global_: # Calculate offset if global variable
90+
node = symbols.BINARY.make_node(
91+
'PLUS',
92+
symbols.UNARY('ADDRESS', node.operand.entry, node.lineno, type_=self.TYPE(gl.PTR_TYPE)),
93+
symbols.NUMBER(node.operand.offset, lineno=node.operand.lineno, type_=self.TYPE(gl.PTR_TYPE)),
94+
lineno=node.lineno, func=lambda x, y: x + y
95+
)
9696
yield node
9797

9898
def visit_BINARY(self, node):

arch/zx48k/translator.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,16 +1145,16 @@ def visit_BNOT(self, node):
11451145
self.ic_bnot(node.operand.type_, node.t, node.operand.t)
11461146

11471147
def visit_ADDRESS(self, node):
1148-
scope = node.children[0].scope
1149-
if node.children[0].token == 'ARRAYACCESS':
1150-
yield node.children[0]
1148+
scope = node.operand.scope
1149+
if node.operand.token == 'ARRAYACCESS':
1150+
yield node.operand
11511151
# Address of an array element.
11521152
if scope == SCOPE.global_:
1153-
self.ic_aaddr(node.t, node.children[0].entry.mangled)
1153+
self.ic_aaddr(node.t, node.operand.entry.mangled)
11541154
elif scope == SCOPE.parameter:
1155-
self.ic_paaddr(node.t, node.children[0].entry.offset)
1155+
self.ic_paaddr(node.t, '*{}'.format(node.operand.entry.offset))
11561156
elif scope == SCOPE.local:
1157-
self.ic_paaddr(node.t, -node.children[0].entry.offset)
1157+
self.ic_paaddr(node.t, -node.operand.entry.offset)
11581158
else: # It's a scalar variable
11591159
if scope == SCOPE.global_:
11601160
self.ic_load(node.type_, node.t, '#' + node.operand.t)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
org 32768
2+
__START_PROGRAM:
3+
di
4+
push ix
5+
push iy
6+
exx
7+
push hl
8+
exx
9+
ld hl, 0
10+
add hl, sp
11+
ld (__CALL_BACK__), hl
12+
ei
13+
ld hl, _aglobal.__DATA__
14+
ld de, 4
15+
add hl, de
16+
push hl
17+
ld a, 99
18+
pop hl
19+
ld (hl), a
20+
ld hl, 0
21+
ld b, h
22+
ld c, l
23+
__END_PROGRAM:
24+
di
25+
ld hl, (__CALL_BACK__)
26+
ld sp, hl
27+
exx
28+
pop hl
29+
exx
30+
pop iy
31+
pop ix
32+
ei
33+
ret
34+
__CALL_BACK__:
35+
DEFW 0
36+
ZXBASIC_USER_DATA:
37+
_aglobal:
38+
DEFW __LABEL0
39+
_aglobal.__DATA__.__PTR__:
40+
DEFW _aglobal.__DATA__
41+
_aglobal.__DATA__:
42+
DEFB 00h
43+
DEFB 01h
44+
DEFB 02h
45+
DEFB 03h
46+
DEFB 04h
47+
DEFB 05h
48+
DEFB 06h
49+
DEFB 07h
50+
DEFB 08h
51+
__LABEL0:
52+
DEFW 0001h
53+
DEFW 0003h
54+
DEFB 01h
55+
; Defines DATA END --> HEAP size is 0
56+
ZXBASIC_USER_DATA_END:
57+
; Defines USER DATA Length in bytes
58+
ZXBASIC_USER_DATA_LEN EQU ZXBASIC_USER_DATA_END - ZXBASIC_USER_DATA
59+
END
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
REM test @arr(x, y) for GLOBAL scope
2+
DIM aglobal(2, 2) as UByte => {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}
3+
POKE @aglobal(1, 1), 99
4+
Lines changed: 156 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ __START_PROGRAM:
1313
ld (__CALL_BACK__), hl
1414
ei
1515
call __MEM_INIT
16+
call _test
1617
ld hl, 0
1718
ld b, h
1819
ld c, l
@@ -36,16 +37,25 @@ _test:
3637
ld hl, 0
3738
push hl
3839
push hl
40+
ld hl, __LABEL1
41+
push hl
3942
ld hl, -4
4043
ld de, __LABEL0
41-
ld bc, 176
42-
call __ALLOC_LOCAL_ARRAY
44+
ld bc, 9
45+
call __ALLOC_INITIALIZED_LOCAL_ARRAY
46+
ld hl, 1
47+
push hl
48+
ld hl, 1
49+
push hl
4350
push ix
4451
pop hl
4552
ld de, -4
4653
add hl, de
47-
ld de, 84
48-
add hl, de
54+
call __ARRAY
55+
push hl
56+
ld a, 99
57+
pop hl
58+
ld (hl), a
4959
_test__leave:
5060
ex af, af'
5161
exx
@@ -57,6 +67,135 @@ _test__leave:
5767
ld sp, ix
5868
pop ix
5969
ret
70+
#line 1 "array.asm"
71+
; vim: ts=4:et:sw=4:
72+
; Copyleft (K) by Jose M. Rodriguez de la Rosa
73+
; (a.k.a. Boriel)
74+
; http://www.boriel.com
75+
; -------------------------------------------------------------------
76+
; Simple array Index routine
77+
; Number of total indexes dimensions - 1 at beginning of memory
78+
; HL = Start of array memory (First two bytes contains N-1 dimensions)
79+
; Dimension values on the stack, (top of the stack, highest dimension)
80+
; E.g. A(2, 4) -> PUSH <4>; PUSH <2>
81+
; For any array of N dimension A(aN-1, ..., a1, a0)
82+
; and dimensions D[bN-1, ..., b1, b0], the offset is calculated as
83+
; O = [a0 + b0 * (a1 + b1 * (a2 + ... bN-2(aN-1)))]
84+
; What I will do here is to calculate the following sequence:
85+
; ((aN-1 * bN-2) + aN-2) * bN-3 + ...
86+
#line 1 "mul16.asm"
87+
__MUL16: ; Mutiplies HL with the last value stored into de stack
88+
; Works for both signed and unsigned
89+
PROC
90+
LOCAL __MUL16LOOP
91+
LOCAL __MUL16NOADD
92+
ex de, hl
93+
pop hl ; Return address
94+
ex (sp), hl ; CALLEE caller convention
95+
__MUL16_FAST:
96+
ld b, 16
97+
ld a, h
98+
ld c, l
99+
ld hl, 0
100+
__MUL16LOOP:
101+
add hl, hl ; hl << 1
102+
sla c
103+
rla ; a,c << 1
104+
jp nc, __MUL16NOADD
105+
add hl, de
106+
__MUL16NOADD:
107+
djnz __MUL16LOOP
108+
ret ; Result in hl (16 lower bits)
109+
ENDP
110+
#line 20 "array.asm"
111+
#line 24 "/zxbasic/library-asm/array.asm"
112+
__ARRAY_PTR: ;; computes an array offset from a pointer
113+
ld c, (hl)
114+
inc hl
115+
ld h, (hl)
116+
ld l, c
117+
__ARRAY:
118+
PROC
119+
LOCAL LOOP
120+
LOCAL ARRAY_END
121+
LOCAL RET_ADDRESS ; Stores return address
122+
LOCAL TMP_ARR_PTR ; Stores pointer temporarily
123+
ld e, (hl)
124+
inc hl
125+
ld d, (hl)
126+
inc hl
127+
ld (TMP_ARR_PTR), hl
128+
ex de, hl
129+
ex (sp), hl ; Return address in HL, array address in the stack
130+
ld (RET_ADDRESS + 1), hl ; Stores it for later
131+
exx
132+
pop hl ; Will use H'L' as the pointer
133+
ld c, (hl) ; Loads Number of dimensions from (hl)
134+
inc hl
135+
ld b, (hl)
136+
inc hl ; Ready
137+
exx
138+
ld hl, 0 ; HL = Offset "accumulator"
139+
LOOP:
140+
#line 62 "/zxbasic/library-asm/array.asm"
141+
pop bc ; Get next index (Ai) from the stack
142+
#line 72 "/zxbasic/library-asm/array.asm"
143+
add hl, bc ; Adds current index
144+
exx ; Checks if B'C' = 0
145+
ld a, b ; Which means we must exit (last element is not multiplied by anything)
146+
or c
147+
jr z, ARRAY_END ; if B'Ci == 0 we are done
148+
ld e, (hl) ; Loads next dimension into D'E'
149+
inc hl
150+
ld d, (hl)
151+
inc hl
152+
push de
153+
dec bc ; Decrements loop counter
154+
exx
155+
pop de ; DE = Max bound Number (i-th dimension)
156+
call __FNMUL
157+
jp LOOP
158+
ARRAY_END:
159+
ld a, (hl)
160+
exx
161+
#line 101 "/zxbasic/library-asm/array.asm"
162+
LOCAL ARRAY_SIZE_LOOP
163+
ex de, hl
164+
ld hl, 0
165+
ld b, a
166+
ARRAY_SIZE_LOOP:
167+
add hl, de
168+
djnz ARRAY_SIZE_LOOP
169+
#line 111 "/zxbasic/library-asm/array.asm"
170+
ex de, hl
171+
ld hl, (TMP_ARR_PTR)
172+
ld a, (hl)
173+
inc hl
174+
ld h, (hl)
175+
ld l, a
176+
add hl, de ; Adds element start
177+
RET_ADDRESS:
178+
jp 0
179+
;; Performs a faster multiply for little 16bit numbs
180+
LOCAL __FNMUL, __FNMUL2
181+
__FNMUL:
182+
xor a
183+
or h
184+
jp nz, __MUL16_FAST
185+
or l
186+
ret z
187+
cp 33
188+
jp nc, __MUL16_FAST
189+
ld b, l
190+
ld l, h ; HL = 0
191+
__FNMUL2:
192+
add hl, de
193+
djnz __FNMUL2
194+
ret
195+
TMP_ARR_PTR:
196+
DW 0 ; temporary storage for pointer to tables
197+
ENDP
198+
#line 56 "arr_addr_local.bas"
60199
#line 1 "arrayalloc.asm"
61200
#line 1 "calloc.asm"
62201
; vim: ts=4:et:sw=4:
@@ -451,7 +590,7 @@ __ALLOC_INITIALIZED_LOCAL_ARRAY:
451590
; DE = new data area
452591
ldir
453592
ret
454-
#line 46 "localdim.bas"
593+
#line 57 "arr_addr_local.bas"
455594
#line 1 "free.asm"
456595
; vim: ts=4:et:sw=4:
457596
; Copyleft (K) by Jose M. Rodriguez de la Rosa
@@ -608,14 +747,24 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed
608747
ld (hl), d ; Next saved
609748
ret
610749
ENDP
611-
#line 47 "localdim.bas"
750+
#line 58 "arr_addr_local.bas"
612751
ZXBASIC_USER_DATA:
613752
__LABEL0:
614753
DEFB 01h
615754
DEFB 00h
616-
DEFB 08h
755+
DEFB 03h
756+
DEFB 00h
757+
DEFB 01h
758+
__LABEL1:
617759
DEFB 00h
760+
DEFB 01h
618761
DEFB 02h
762+
DEFB 03h
763+
DEFB 04h
764+
DEFB 05h
765+
DEFB 06h
766+
DEFB 07h
767+
DEFB 08h
619768
ZXBASIC_MEM_HEAP:
620769
; Defines DATA END
621770
ZXBASIC_USER_DATA_END EQU ZXBASIC_MEM_HEAP + ZXBASIC_HEAP_SIZE
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
REM test @arr(x, y) for LOCAL scope
2+
SUB test
3+
DIM alocal(2, 2) as UByte => {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}
4+
POKE @alocal(1, 1), 99
5+
END SUB
6+
test
7+

0 commit comments

Comments
 (0)