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
65 changes: 31 additions & 34 deletions src/arch/z80/visitor/translator_inst_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,31 +52,31 @@ def ic_aaddr(self, t1, t2) -> None:
self.emit("aaddr", t1, t2)

def ic_abs(self, type_: TYPE | sym.BASICTYPE, t1, t2) -> None:
self.emit("abs" + self.TSUFFIX(type_), t1, t2)
self.emit(f"abs{self.TSUFFIX(type_)}", t1, t2)

def ic_add(self, type_: TYPE | sym.BASICTYPE, t1, t2, t3) -> None:
self.emit("add" + self.TSUFFIX(type_), t1, t2, t3)
self.emit(f"add{self.TSUFFIX(type_)}", t1, t2, t3)

def ic_aload(self, type_: TYPE | sym.BASICTYPE, t1, mangle: str) -> None:
self.emit("aload" + self.TSUFFIX(type_), t1, mangle)
self.emit(f"aload{self.TSUFFIX(type_)}", t1, mangle)

def ic_and(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit(f"and{self._no_bool(type_)}", t, t1, t2)

def ic_astore(self, type_: TYPE | sym.BASICTYPE, addr: str, t) -> None:
self.emit("astore" + self.TSUFFIX(type_), addr, t)
self.emit(f"astore{self.TSUFFIX(type_)}", addr, t)

def ic_band(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit("band" + self.TSUFFIX(type_), t, t1, t2)
self.emit(f"band{self.TSUFFIX(type_)}", t, t1, t2)

def ic_bnot(self, type_: TYPE | sym.BASICTYPE, t1, t2) -> None:
self.emit("bnot" + self.TSUFFIX(type_), t1, t2)
self.emit(f"bnot{self.TSUFFIX(type_)}", t1, t2)

def ic_bor(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit("bor" + self.TSUFFIX(type_), t, t1, t2)
self.emit(f"bor{self.TSUFFIX(type_)}", t, t1, t2)

def ic_bxor(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit("bxor" + self.TSUFFIX(type_), t, t1, t2)
self.emit(f"bxor{self.TSUFFIX(type_)}", t, t1, t2)

def ic_call(self, label: str, num: int) -> None:
self.emit("call", label, num)
Expand All @@ -91,7 +91,7 @@ def ic_deflabel(self, label: str, t) -> None:
self.emit("deflabel", label, t)

def ic_div(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit("div" + self.TSUFFIX(type_), t, t1, t2)
self.emit(f"div{self.TSUFFIX(type_)}", t, t1, t2)

def ic_end(self, t) -> None:
self.emit("end", t)
Expand All @@ -100,7 +100,7 @@ def ic_enter(self, arg) -> None:
self.emit("enter", arg)

def ic_eq(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit("eq" + self.TSUFFIX(type_), t, t1, t2)
self.emit(f"eq{self.TSUFFIX(type_)}", t, t1, t2)

def ic_exchg(self) -> None:
self.emit("exchg")
Expand All @@ -109,13 +109,13 @@ def ic_fparam(self, type_: TYPE | sym.BASICTYPE, t) -> None:
self.emit(f"fparam{self._no_bool(type_)}", t)

def ic_fpload(self, type_: TYPE | sym.BASICTYPE, t, offset) -> None:
self.emit("fpload" + self.TSUFFIX(type_), t, offset)
self.emit(f"fpload{self.TSUFFIX(type_)}", t, offset)

def ic_ge(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit("ge" + self.TSUFFIX(type_), t, t1, t2)
self.emit(f"ge{self.TSUFFIX(type_)}", t, t1, t2)

def ic_gt(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit("gt" + self.TSUFFIX(type_), t, t1, t2)
self.emit(f"gt{self.TSUFFIX(type_)}", t, t1, t2)

def ic_in(self, t) -> None:
self.emit("in", t)
Expand All @@ -142,7 +142,7 @@ def ic_larrd(self, offset, arg1, size, arg2, bound_ptrs) -> None:
self.emit("larrd", offset, arg1, size, arg2, bound_ptrs)

def ic_le(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit("le" + self.TSUFFIX(type_), t, t1, t2)
self.emit(f"le{self.TSUFFIX(type_)}", t, t1, t2)

def ic_leave(self, convention: str) -> None:
self.emit("leave", convention)
Expand All @@ -151,10 +151,10 @@ def ic_lenstr(self, t1, t2) -> None:
self.emit("lenstr", t1, t2)

def ic_load(self, type_: TYPE | sym.BASICTYPE, t1, t2) -> None:
self.emit("load" + self.TSUFFIX(type_), t1, t2)
self.emit(f"load{self.TSUFFIX(type_)}", t1, t2)

def ic_lt(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit("lt" + self.TSUFFIX(type_), t, t1, t2)
self.emit(f"lt{self.TSUFFIX(type_)}", t, t1, t2)

def ic_lvard(self, offset, default_value: list) -> None:
self.emit("lvard", offset, default_value)
Expand All @@ -166,16 +166,16 @@ def ic_memcopy(self, t1, t2, t3) -> None:
self.emit("memcopy", t1, t2, t3)

def ic_mod(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit("mod" + self.TSUFFIX(type_), t, t1, t2)
self.emit(f"mod{self.TSUFFIX(type_)}", t, t1, t2)

def ic_mul(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit("mul" + self.TSUFFIX(type_), t, t1, t2)
self.emit(f"mul{self.TSUFFIX(type_)}", t, t1, t2)

def ic_ne(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit("ne" + self.TSUFFIX(type_), t, t1, t2)
self.emit(f"ne{self.TSUFFIX(type_)}", t, t1, t2)

def ic_neg(self, type_: TYPE | sym.BASICTYPE, t1, t2) -> None:
self.emit("neg" + self.TSUFFIX(type_), t1, t2)
self.emit(f"neg{self.TSUFFIX(type_)}", t1, t2)

def ic_nop(self) -> None:
self.emit("nop")
Expand All @@ -186,9 +186,6 @@ def ic_not(self, type_: TYPE | sym.BASICTYPE, t1, t2) -> None:
def ic_or(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit(f"or{self._no_bool(type_)}", t, t1, t2)

def ic_org(self, type_: TYPE | sym.BASICTYPE) -> None:
self.emit("org" + self.TSUFFIX(type_))

def ic_out(self, t1, t2) -> None:
self.emit("out", t1, t2)

Expand All @@ -199,40 +196,40 @@ def ic_paddr(self, t1, t2) -> None:
self.emit("paddr", t1, t2)

def ic_paload(self, type_: TYPE | sym.BASICTYPE, t, offset: int) -> None:
self.emit("paload" + self.TSUFFIX(type_), t, offset)
self.emit(f"paload{self.TSUFFIX(type_)}", t, offset)

def ic_param(self, type_: TYPE | sym.BASICTYPE, t) -> None:
self.emit("param" + self.TSUFFIX(type_), t)
self.emit(f"param{self.TSUFFIX(type_)}", t)

def ic_pastore(self, type_: TYPE | sym.BASICTYPE, offset, t) -> None:
self.emit("pastore" + self.TSUFFIX(type_), offset, t)
self.emit(f"pastore{self.TSUFFIX(type_)}", offset, t)

def ic_pload(self, type_: TYPE | sym.BASICTYPE, t1, offset) -> None:
self.emit("pload" + self.TSUFFIX(type_), t1, offset)
self.emit(f"pload{self.TSUFFIX(type_)}", t1, offset)

def ic_pow(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit("pow" + self.TSUFFIX(type_), t, t1, t2)
self.emit(f"pow{self.TSUFFIX(type_)}", t, t1, t2)

def ic_pstore(self, type_: TYPE | sym.BASICTYPE, offset, t) -> None:
self.emit("pstore" + self.TSUFFIX(type_), offset, t)
self.emit(f"pstore{self.TSUFFIX(type_)}", offset, t)

def ic_ret(self, type_: TYPE | sym.BASICTYPE, t, addr) -> None:
self.emit("ret" + self.TSUFFIX(type_), t, addr)
self.emit(f"ret{self.TSUFFIX(type_)}", t, addr)

def ic_return(self, addr) -> None:
self.emit("ret", addr)

def ic_shl(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit(f"shl{self._no_bool(type_)}", t, t1, t2)
self.emit(f"shl{self.TSUFFIX(type_)}", t, t1, t2)

def ic_shr(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit(f"shr{self._no_bool(type_)}", t, t1, t2)
self.emit(f"shr{self.TSUFFIX(type_)}", t, t1, t2)

def ic_store(self, type_: TYPE | sym.BASICTYPE, t1, t2) -> None:
self.emit("store" + self.TSUFFIX(type_), t1, t2)
self.emit(f"store{self.TSUFFIX(type_)}", t1, t2)

def ic_sub(self, type_: TYPE | sym.BASICTYPE, t, t1, t2) -> None:
self.emit("sub" + self.TSUFFIX(type_), t, t1, t2)
self.emit(f"sub{self.TSUFFIX(type_)}", t, t1, t2)

def ic_var(self, name: str, size_) -> None:
self.emit("var", name, size_)
Expand Down
47 changes: 27 additions & 20 deletions src/symbols/binary.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,31 @@ def make_node(cls, operator, left, right, lineno, func=None, type_=None):
return None

a, b = left, right # short form names
if operator in {
"BAND",
"BOR",
"BXOR",
"AND",
"OR",
"XOR",
"MINUS",
"MULT",
"DIV",
"SHL",
"SHR",
} and not check.is_numeric(a, b):
errmsg.error(lineno, f"Operator {operator} cannot be used with strings")
return None

if operator not in {"AND", "OR", "XOR"}:
# Non-boolean operators use always numeric operands.
# We ensure operands are correctly converted to 0|1 values if they're boolean
if a.type_ == TYPE.boolean:
a = SymbolTYPECAST.make_node(TYPE.ubyte, a, lineno)

if b.type_ == TYPE.boolean:
b = SymbolTYPECAST.make_node(TYPE.ubyte, b, lineno)

# Check for constant non-numeric operations
c_type = check.common_type(a, b) # Resulting operation type or None
if TYPE.is_numeric(c_type): # there must be a common type for a and b
Expand All @@ -90,31 +115,13 @@ def make_node(cls, operator, left, right, lineno, func=None, type_=None):
b = SymbolTYPECAST.make_node(c_type, b, lineno) # ensure type
return SymbolCONSTEXPR(cls(operator, a, b, lineno, type_=type_, func=func), lineno=lineno)

if operator in {
"BNOT",
"BAND",
"BOR",
"BXOR",
"NOT",
"AND",
"OR",
"XOR",
"MINUS",
"MULT",
"DIV",
"SHL",
"SHR",
} and not check.is_numeric(a, b):
errmsg.error(lineno, "Operator %s cannot be used with STRINGS" % operator)
return None

if check.is_string(a, b) and func is not None: # Are they STRING Constants?
if operator == "PLUS":
return SymbolSTRING(func(a.value, b.value), lineno)

return SymbolNUMBER(int(func(a.text, b.text)), type_=TYPE.ubyte, lineno=lineno) # Convert to u8 (boolean)

if operator in ("BNOT", "BAND", "BOR", "BXOR"):
if operator in {"BNOT", "BAND", "BOR", "BXOR"}:
if TYPE.is_decimal(c_type):
c_type = TYPE.long_

Expand All @@ -129,7 +136,7 @@ def make_node(cls, operator, left, right, lineno, func=None, type_=None):
return None

if type_ is None:
if operator in ("LT", "GT", "EQ", "LE", "GE", "NE", "AND", "OR", "XOR", "NOT"):
if operator in {"LT", "GT", "EQ", "LE", "GE", "NE", "AND", "OR", "XOR"}:
type_ = TYPE.boolean
else:
type_ = c_type
Expand Down
17 changes: 17 additions & 0 deletions tests/functional/arch/zx48k/add8.asm
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,23 @@ _b:
ld a, (_a)
add a, h
ld (_b), a
ld hl, (_a - 1)
ld a, (_a)
sub h
sub 1
sbc a, a
neg
push af
ld hl, (_a - 1)
ld a, (_a)
sub h
sub 1
sbc a, a
neg
ld h, a
pop af
add a, h
ld (_b), a
ld hl, 0
ld b, h
ld c, l
Expand Down
2 changes: 2 additions & 0 deletions tests/functional/arch/zx48k/add8.bas
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ b = a + 1
b = 0 + a
b = 1 + a
b = a + a
b = (a = a) + (a = a)

21 changes: 19 additions & 2 deletions tests/functional/arch/zx48k/divu8.asm
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,23 @@ _b:
ld hl, (_a - 1)
call .core.__DIVU8_FAST
ld (_b), a
ld hl, (_a - 1)
ld a, (_a)
sub h
sub 1
sbc a, a
neg
push af
ld hl, (_a - 1)
ld a, (_a)
sub h
sub 1
sbc a, a
neg
ld h, a
pop af
call .core.__DIVU8_FAST
ld (_b), a
ld hl, 0
ld b, h
ld c, l
Expand All @@ -66,7 +83,7 @@ _b:
ei
ret
;; --- end of user code ---
#line 1 "/zxbasic/src/arch/zx48k/library-asm/div8.asm"
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div8.asm"
; --------------------------------
push namespace core
__DIVU8: ; 8 bit unsigned integer division
Expand Down Expand Up @@ -131,5 +148,5 @@ __MODI8_FAST: ; __FASTCALL__ entry
ld a, l ; remainder
ret ; a = Modulus
pop namespace
#line 44 "divu8.bas"
#line 61 "arch/zx48k/divu8.bas"
END
2 changes: 2 additions & 0 deletions tests/functional/arch/zx48k/divu8.bas
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ b = 1 / a
b = 2 / a
b = 4 / a
b = a / a
b = (a = a) / (a = a)

21 changes: 19 additions & 2 deletions tests/functional/arch/zx48k/mul8.asm
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,23 @@ _b:
ld a, (_a)
call .core.__MUL8_FAST
ld (_b), a
ld hl, (_a - 1)
ld a, (_a)
sub h
sub 1
sbc a, a
neg
push af
ld hl, (_a - 1)
ld a, (_a)
sub h
sub 1
sbc a, a
neg
ld h, a
pop af
call .core.__MUL8_FAST
ld (_b), a
ld hl, 0
ld b, h
ld c, l
Expand All @@ -67,7 +84,7 @@ _b:
ei
ret
;; --- end of user code ---
#line 1 "/zxbasic/src/arch/zx48k/library-asm/mul8.asm"
#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mul8.asm"
push namespace core
__MUL8: ; Performs 8bit x 8bit multiplication
PROC
Expand Down Expand Up @@ -113,5 +130,5 @@ __MUL8B:
ret ; result = HL
ENDP
pop namespace
#line 45 "mul8.bas"
#line 62 "arch/zx48k/mul8.bas"
END
2 changes: 2 additions & 0 deletions tests/functional/arch/zx48k/mul8.bas
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ b = 1 * a
b = 2 * a
b = 4 * a
b = a * a
b = (a = a) * (a = a)

5 changes: 4 additions & 1 deletion tests/functional/arch/zx48k/shlu16.asm
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ _b:
ld de, (_a)
ld hl, (_a)
call .core.__EQ16
sub 1
sbc a, a
inc a
push af
ld a, (_b)
pop hl
Expand Down Expand Up @@ -100,5 +103,5 @@ __EQ16: ; Test if 16bit values HL == DE
inc a
ret
pop namespace
#line 68 "arch/zx48k/shlu16.bas"
#line 71 "arch/zx48k/shlu16.bas"
END
Loading
Loading