Skip to content

Commit a2fa632

Browse files
committed
feat: add mul8 for zxnext
1 parent 3fe7f8e commit a2fa632

9 files changed

Lines changed: 251 additions & 2 deletions

File tree

src/arch/zx48k/backend/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
from src.api.config import OPTIONS
44
from src.arch.z80 import backend
55

6-
from src.arch.z80.backend import *
6+
from src.arch.z80.backend import tmp_label, _fpop, HI16, INITS, LO16, LABEL_COUNTER, MEMORY, MEMINITS
7+
from src.arch.z80.backend import QUADS, REQUIRES, TMP_COUNTER, TMP_STORAGES
8+
from src.arch.z80.backend import emit, emit_end, emit_start
9+
710

811
__all__ = [
912
"tmp_label",

src/arch/zxnext/backend/_8bit.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# -*- coding: utf-8 -*-
2+
3+
4+
from typing import List
5+
6+
from src.arch.z80.backend import Quad
7+
from src.arch.z80.backend._8bit import _8bit_oper, int8
8+
from src.arch.z80.backend.common import _int_ops
9+
10+
11+
def _mul8(ins: Quad) -> List[str]:
12+
"""Multiplies 2 las values from the stack.
13+
14+
Optimizations:
15+
* If any of the ops is ZERO,
16+
then do A = 0 ==> XOR A, cause A * 0 = 0 * A = 0
17+
18+
* If any ot the ops is ONE, do NOTHING
19+
A * 1 = 1 * A = A
20+
"""
21+
22+
op1, op2 = tuple(ins.quad[2:])
23+
if _int_ops(op1, op2) is not None:
24+
op1, op2 = _int_ops(op1, op2)
25+
26+
output = _8bit_oper(op1)
27+
28+
if op2 == 0:
29+
output.append("xor a")
30+
output.append("push af")
31+
return output
32+
33+
if op2 == 1: # A * 1 = 1 * A = A
34+
output.append("push af")
35+
return output
36+
37+
if op2 == 2: # A * 2 == A SLA 1
38+
output.append("add a, a")
39+
output.append("push af")
40+
return output
41+
42+
if op2 == 4: # A * 4 == A SLA 2
43+
output.append("add a, a")
44+
output.append("add a, a")
45+
output.append("push af")
46+
return output
47+
48+
output.append("ld h, %i" % int8(op2))
49+
else:
50+
if op2[0] == "_": # stack optimization
51+
op1, op2 = op2, op1
52+
53+
output = _8bit_oper(op1, op2)
54+
55+
output.append("ld d, h") # Immediate
56+
output.append("ld e, a")
57+
output.append("mul d, e")
58+
output.append("ld a, e")
59+
output.append("push af")
60+
return output

src/arch/zxnext/backend/__init__.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,14 @@
22

33
from src.api.config import OPTIONS
44
from src.arch.z80 import backend
5+
from src.arch.z80.backend import ICInfo
6+
7+
from src.arch.zxnext.backend._8bit import _mul8
8+
9+
from src.arch.z80.backend import tmp_label, _fpop, HI16, INITS, LO16, LABEL_COUNTER, MEMORY, MEMINITS
10+
from src.arch.z80.backend import QUADS, REQUIRES, TMP_COUNTER, TMP_STORAGES
11+
from src.arch.z80.backend import emit, emit_end, emit_start
512

6-
from src.arch.z80.backend import *
713

814
__all__ = [
915
"tmp_label",
@@ -28,6 +34,10 @@
2834
OPTIONS.zxnext = True
2935

3036

37+
# Override z80 generic implementation with ZX Next ones
38+
QUADS.update({"muli8": ICInfo(3, _mul8), "mulu8": ICInfo(3, _mul8)})
39+
40+
3141
def init():
3242
# ZXNext asm enabled by default for this arch
3343
OPTIONS.zxnext = True

tests/functional/zxnext/muli8.asm

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
org 32768
2+
.core.__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 (.core.__CALL_BACK__), hl
12+
ei
13+
jp .core.__MAIN_PROGRAM__
14+
.core.__CALL_BACK__:
15+
DEFW 0
16+
.core.ZXBASIC_USER_DATA:
17+
; Defines USER DATA Length in bytes
18+
.core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA
19+
.core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN
20+
.core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA
21+
_a:
22+
DEFB 00
23+
.core.ZXBASIC_USER_DATA_END:
24+
.core.__MAIN_PROGRAM__:
25+
ld a, (_a)
26+
ld h, 3
27+
ld d, h
28+
ld e, a
29+
mul d, e
30+
ld a, e
31+
ld (_a), a
32+
ld hl, 0
33+
ld b, h
34+
ld c, l
35+
.core.__END_PROGRAM:
36+
di
37+
ld hl, (.core.__CALL_BACK__)
38+
ld sp, hl
39+
exx
40+
pop hl
41+
exx
42+
pop iy
43+
pop ix
44+
ei
45+
ret
46+
;; --- end of user code ---
47+
END

tests/functional/zxnext/muli8.bas

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
DIM a as Byte
2+
3+
LET a = a * 3

tests/functional/zxnext/mulu16.asm

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
org 32768
2+
.core.__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 (.core.__CALL_BACK__), hl
12+
ei
13+
jp .core.__MAIN_PROGRAM__
14+
.core.__CALL_BACK__:
15+
DEFW 0
16+
.core.ZXBASIC_USER_DATA:
17+
; Defines USER DATA Length in bytes
18+
.core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA
19+
.core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN
20+
.core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA
21+
_a:
22+
DEFB 00, 00
23+
.core.ZXBASIC_USER_DATA_END:
24+
.core.__MAIN_PROGRAM__:
25+
ld hl, (_a)
26+
ld de, 3
27+
call .core.__MUL16_FAST
28+
ld (_a), hl
29+
ld hl, 0
30+
ld b, h
31+
ld c, l
32+
.core.__END_PROGRAM:
33+
di
34+
ld hl, (.core.__CALL_BACK__)
35+
ld sp, hl
36+
exx
37+
pop hl
38+
exx
39+
pop iy
40+
pop ix
41+
ei
42+
ret
43+
;; --- end of user code ---
44+
#line 1 "/zxbasic/src/arch/zxnext/library-asm/mul16.asm"
45+
push namespace core
46+
__MUL16: ; Mutiplies HL with the last value stored into de stack
47+
; Works for both signed and unsigned
48+
PROC
49+
ex de, hl
50+
pop hl ; Return address
51+
ex (sp), hl ; CALLEE caller convention
52+
__MUL16_FAST:
53+
ld a,d ; a = xh
54+
ld d,h ; d = yh
55+
ld h,a ; h = xh
56+
ld c,e ; c = xl
57+
ld b,l ; b = yl
58+
mul d,e ; yh * yl
59+
ex de,hl
60+
mul d,e ; xh * yl
61+
add hl,de ; add cross products
62+
ld e,c
63+
ld d,b
64+
mul d,e ; yl * xl
65+
ld a,l ; cross products lsb
66+
add a,d ; add to msb final
67+
ld h,a
68+
ld l,e ; hl = final
69+
ret ; Result in hl (16 lower bits)
70+
ENDP
71+
pop namespace
72+
#line 21 "zxnext/mulu16.bas"
73+
END

tests/functional/zxnext/mulu16.bas

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
DIM a as UInteger
2+
3+
LET a = a * 3

tests/functional/zxnext/mulu8.asm

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
org 32768
2+
.core.__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 (.core.__CALL_BACK__), hl
12+
ei
13+
jp .core.__MAIN_PROGRAM__
14+
.core.__CALL_BACK__:
15+
DEFW 0
16+
.core.ZXBASIC_USER_DATA:
17+
; Defines USER DATA Length in bytes
18+
.core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA
19+
.core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN
20+
.core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA
21+
_a:
22+
DEFB 00
23+
.core.ZXBASIC_USER_DATA_END:
24+
.core.__MAIN_PROGRAM__:
25+
ld a, (_a)
26+
ld h, 3
27+
ld d, h
28+
ld e, a
29+
mul d, e
30+
ld a, e
31+
ld (_a), a
32+
ld hl, 0
33+
ld b, h
34+
ld c, l
35+
.core.__END_PROGRAM:
36+
di
37+
ld hl, (.core.__CALL_BACK__)
38+
ld sp, hl
39+
exx
40+
pop hl
41+
exx
42+
pop iy
43+
pop ix
44+
ei
45+
ret
46+
;; --- end of user code ---
47+
END

tests/functional/zxnext/mulu8.bas

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
DIM a as UByte
2+
3+
LET a = a * 3

0 commit comments

Comments
 (0)