diff --git a/arch/zx48k/translator.py b/arch/zx48k/translator.py index 89f66d940..93e657b93 100644 --- a/arch/zx48k/translator.py +++ b/arch/zx48k/translator.py @@ -238,7 +238,7 @@ def visit_ARRAYLOAD(self, node): if scope == SCOPE.global_: self.ic_aload(node.type_, node.entry.t, node.entry.mangled) elif scope == SCOPE.parameter: - self.ic_paload(node.type_, node.t, node.entry.offset) + self.ic_paload(node.type_, node.t, '*{}'.format(node.entry.offset)) elif scope == SCOPE.local: self.ic_paload(node.type_, node.t, -node.entry.offset) else: diff --git a/symbols/arrayaccess.py b/symbols/arrayaccess.py index d378423a0..e9629a2a7 100644 --- a/symbols/arrayaccess.py +++ b/symbols/arrayaccess.py @@ -116,8 +116,8 @@ def make_node(cls, id_, arglist, lineno): # Checks for array subscript range if the subscript is constant # e.g. A(1) is a constant subscript access + btype = gl.SYMBOL_TABLE.basic_types[gl.BOUND_TYPE] for i, b in zip(arglist, variable.bounds): - btype = gl.SYMBOL_TABLE.basic_types[gl.BOUND_TYPE] lower_bound = NUMBER(b.lower, type_=btype, lineno=lineno) i.value = BINARY.make_node('MINUS', TYPECAST.make_node(btype, i.value, lineno), @@ -127,6 +127,10 @@ def make_node(cls, id_, arglist, lineno): val = i.value.value if val < 0 or val > b.count: warning(lineno, "Array '%s' subscript out of range" % id_) + else: + btype = gl.SYMBOL_TABLE.basic_types[gl.BOUND_TYPE] + for arg in arglist: + arg.value = TYPECAST.make_node(btype, arg.value, arg.value.lineno) # Returns the variable entry and the node return cls(variable, arglist, lineno) diff --git a/tests/functional/pararray8.asm b/tests/functional/pararray8.asm new file mode 100644 index 000000000..d189cec19 --- /dev/null +++ b/tests/functional/pararray8.asm @@ -0,0 +1,246 @@ + org 32768 +__START_PROGRAM: + di + push ix + push iy + exx + push hl + exx + ld hl, 0 + add hl, sp + ld (__CALL_BACK__), hl + ei + ld hl, _a + push hl + call _max + ld (_maximum), a + ld hl, 0 + ld b, h + ld c, l +__END_PROGRAM: + di + ld hl, (__CALL_BACK__) + ld sp, hl + exx + pop hl + exx + pop iy + pop ix + ei + ret +__CALL_BACK__: + DEFW 0 +_max: + push ix + ld ix, 0 + add ix, sp + ld hl, 0 + push hl + ld hl, 0 + push hl + push ix + pop hl + ld de, 4 + add hl, de + call __ARRAY_PTR + ld a, (hl) + ld (ix-1), a + ld (ix-2), 1 + jp __LABEL0 +__LABEL3: + ld a, (ix-1) + push af + ld a, (ix-2) + ld l, a + ld h, 0 + push hl + push ix + pop hl + ld de, 4 + add hl, de + call __ARRAY_PTR + pop af + cp (hl) + jp nc, __LABEL6 + ld a, (ix-2) + ld l, a + ld h, 0 + push hl + push ix + pop hl + ld de, 4 + add hl, de + call __ARRAY_PTR + ld a, (hl) + ld (ix-1), a +__LABEL6: +__LABEL4: + inc (ix-2) +__LABEL0: + ld a, (ix-2) + push af + ld a, 5 + pop hl + cp h + jp nc, __LABEL3 +__LABEL2: + ld a, (ix-1) +_max__leave: + ld sp, ix + pop ix + exx + pop hl + ex (sp), hl + exx + ret +#line 1 "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 "mul16.asm" +__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 +#line 20 "array.asm" +#line 24 "/zxbasic/library-asm/array.asm" +__ARRAY_PTR: ;; computes an array offset from a pointer + ld c, (hl) + inc hl + ld h, (hl) + ld l, c +__ARRAY: + PROC + LOCAL LOOP + LOCAL ARRAY_END + LOCAL RET_ADDRESS ; Stores return address + LOCAL TMP_ARR_PTR ; Stores pointer temporarily + ld e, (hl) + inc hl + ld d, (hl) + inc hl + ld (TMP_ARR_PTR), hl + ex de, hl + ex (sp), hl ; Return address in HL, array address in the stack + ld (RET_ADDRESS + 1), hl ; Stores it for later + exx + pop hl ; Will use H'L' as the pointer + ld c, (hl) ; Loads Number of dimensions from (hl) + inc hl + ld b, (hl) + inc hl ; Ready + exx + ld hl, 0 ; HL = Offset "accumulator" +LOOP: +#line 62 "/zxbasic/library-asm/array.asm" + pop bc ; Get next index (Ai) from the stack +#line 72 "/zxbasic/library-asm/array.asm" + add hl, bc ; 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 + ld e, (hl) ; Loads next dimension into D'E' + inc hl + ld d, (hl) + inc hl + push de + dec bc ; Decrements loop counter + exx + pop de ; DE = Max bound Number (i-th dimension) + call __FNMUL + jp LOOP +ARRAY_END: + ld a, (hl) + exx +#line 101 "/zxbasic/library-asm/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 111 "/zxbasic/library-asm/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 +RET_ADDRESS: + jp 0 + ;; Performs a faster multiply for little 16bit numbs + LOCAL __FNMUL, __FNMUL2 +__FNMUL: + 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 +__FNMUL2: + add hl, de + djnz __FNMUL2 + ret +TMP_ARR_PTR: + DW 0 ; temporary storage for pointer to tables + ENDP +#line 85 "pararray8.bas" +ZXBASIC_USER_DATA: +_maximum: + DEFB 00 +_a: + DEFW __LABEL7 +_a.__DATA__.__PTR__: + DEFW _a.__DATA__ +_a.__DATA__: + DEFB 04h + DEFB 03h + DEFB 01h + DEFB 05h + DEFB 07h + DEFB 08h +__LABEL7: + DEFW 0000h + DEFB 01h +; Defines DATA END --> HEAP size is 0 +ZXBASIC_USER_DATA_END: + ; Defines USER DATA Length in bytes +ZXBASIC_USER_DATA_LEN EQU ZXBASIC_USER_DATA_END - ZXBASIC_USER_DATA + END diff --git a/tests/functional/pararray8.bas b/tests/functional/pararray8.bas new file mode 100644 index 000000000..9d5bf8d76 --- /dev/null +++ b/tests/functional/pararray8.bas @@ -0,0 +1,13 @@ + +Function max(a() as Ubyte) as Ubyte + DIM max as UByte + max = a(0) + for i = 1 to 5 + if max < a(i) then max = a(i) + next + return max +End Function + +DIM a(5) as Ubyte = {4, 3, 1, 5, 7, 8} +maximum = max(a) +