2018-01-14 14:18:50 +00:00
|
|
|
"""
|
|
|
|
Programming Language for 6502/6510 microprocessors, codename 'Sick'
|
|
|
|
This is the code generator for assignment statements.
|
|
|
|
|
|
|
|
Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
|
|
|
"""
|
|
|
|
|
|
|
|
from typing import Callable
|
2018-01-23 23:41:50 +00:00
|
|
|
from ..plyparse import Scope, Assignment, AugAssignment, Register, LiteralValue, SymbolName, VarDef
|
|
|
|
from . import CodeError, preserving_registers, to_hex
|
|
|
|
from ..datatypes import REGISTER_BYTES, REGISTER_WORDS, VarType, DataType
|
|
|
|
from ..compile import Zeropage
|
2018-01-14 14:18:50 +00:00
|
|
|
|
|
|
|
|
2018-01-23 23:41:50 +00:00
|
|
|
def generate_assignment(out: Callable, stmt: Assignment, scope: Scope) -> None:
|
|
|
|
out("\v\t\t\t; " + stmt.lineref)
|
|
|
|
out("\v; @todo assignment")
|
|
|
|
# @todo assignment
|
|
|
|
|
|
|
|
|
|
|
|
def generate_aug_assignment(out: Callable, stmt: AugAssignment, scope: Scope) -> None:
|
2018-01-28 20:58:16 +00:00
|
|
|
# for instance: value += 3 (value = 0-255 for now)
|
2018-01-23 23:41:50 +00:00
|
|
|
# left: Register, SymbolName, or Dereference. right: Expression/LiteralValue
|
|
|
|
out("\v\t\t\t; " + stmt.lineref)
|
|
|
|
lvalue = stmt.left
|
2018-01-14 14:18:50 +00:00
|
|
|
rvalue = stmt.right
|
2018-01-23 23:41:50 +00:00
|
|
|
if isinstance(lvalue, Register):
|
|
|
|
if isinstance(rvalue, LiteralValue):
|
|
|
|
if type(rvalue.value) is int:
|
2018-01-28 20:58:16 +00:00
|
|
|
if 0 <= rvalue.value <= 255:
|
2018-01-27 00:07:00 +00:00
|
|
|
_generate_aug_reg_constant_int(out, lvalue, stmt.operator, rvalue.value, "", scope)
|
|
|
|
else:
|
2018-02-01 00:56:36 +00:00
|
|
|
raise CodeError("aug. assignment value must be 0..255", rvalue)
|
2018-01-23 23:41:50 +00:00
|
|
|
else:
|
2018-01-27 00:07:00 +00:00
|
|
|
raise CodeError("constant integer literal or variable required for now", rvalue) # XXX
|
2018-01-23 23:41:50 +00:00
|
|
|
elif isinstance(rvalue, SymbolName):
|
|
|
|
symdef = scope.lookup(rvalue.name)
|
2018-01-27 00:07:00 +00:00
|
|
|
if isinstance(symdef, VarDef) and symdef.vartype == VarType.CONST and symdef.datatype.isinteger():
|
2018-01-29 21:34:28 +00:00
|
|
|
if 0 <= symdef.value.const_value() <= 255: # type: ignore
|
2018-01-28 20:58:16 +00:00
|
|
|
_generate_aug_reg_constant_int(out, lvalue, stmt.operator, 0, symdef.name, scope)
|
|
|
|
else:
|
2018-02-01 00:56:36 +00:00
|
|
|
raise CodeError("aug. assignment value must be 0..255", rvalue)
|
2018-01-23 23:41:50 +00:00
|
|
|
else:
|
2018-01-27 00:07:00 +00:00
|
|
|
raise CodeError("constant integer literal or variable required for now", rvalue) # XXX
|
2018-01-23 23:41:50 +00:00
|
|
|
elif isinstance(rvalue, Register):
|
2018-01-27 00:07:00 +00:00
|
|
|
# @todo check value range (single register; 0-255) @todo support combined registers
|
2018-01-23 23:41:50 +00:00
|
|
|
_generate_aug_reg_reg(out, lvalue, stmt.operator, rvalue, scope)
|
|
|
|
else:
|
|
|
|
# @todo Register += symbolname / dereference , _generate_aug_reg_mem?
|
2018-02-01 00:56:36 +00:00
|
|
|
raise CodeError("invalid rvalue for aug. assignment on register", rvalue)
|
2018-01-23 23:41:50 +00:00
|
|
|
else:
|
2018-02-01 00:56:36 +00:00
|
|
|
raise CodeError("aug. assignment only implemented for registers for now", stmt.sourceref) # XXX
|
2018-01-23 23:41:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
def _generate_aug_reg_constant_int(out: Callable, lvalue: Register, operator: str, rvalue: int, rname: str, scope: Scope) -> None:
|
|
|
|
r_str = rname or to_hex(rvalue)
|
|
|
|
if operator == "+=":
|
2018-01-28 20:58:16 +00:00
|
|
|
if lvalue.name == "A":
|
2018-01-23 23:41:50 +00:00
|
|
|
out("\vclc")
|
|
|
|
out("\vadc #" + r_str)
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "X":
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtxa")
|
|
|
|
out("\vclc")
|
|
|
|
out("\vadc #" + r_str)
|
|
|
|
out("\vtax")
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "Y":
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtya")
|
|
|
|
out("\vclc")
|
|
|
|
out("\vadc #" + r_str)
|
|
|
|
out("\vtay")
|
|
|
|
else:
|
|
|
|
raise CodeError("unsupported register for aug assign", str(lvalue)) # @todo +=.word
|
|
|
|
elif operator == "-=":
|
2018-01-28 20:58:16 +00:00
|
|
|
if lvalue.name == "A":
|
2018-01-23 23:41:50 +00:00
|
|
|
out("\vsec")
|
|
|
|
out("\vsbc #" + r_str)
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "X":
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtxa")
|
|
|
|
out("\vsec")
|
|
|
|
out("\vsbc #" + r_str)
|
|
|
|
out("\vtax")
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "Y":
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtya")
|
|
|
|
out("\vsec")
|
|
|
|
out("\vsbc #" + r_str)
|
|
|
|
out("\vtay")
|
|
|
|
else:
|
|
|
|
raise CodeError("unsupported register for aug assign", str(lvalue)) # @todo -=.word
|
|
|
|
elif operator == "&=":
|
2018-01-28 20:58:16 +00:00
|
|
|
if lvalue.name == "A":
|
2018-01-23 23:41:50 +00:00
|
|
|
out("\vand #" + r_str)
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "X":
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtxa")
|
|
|
|
out("\vand #" + r_str)
|
|
|
|
out("\vtax")
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "Y":
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtya")
|
|
|
|
out("\vand #" + r_str)
|
|
|
|
out("\vtay")
|
|
|
|
else:
|
|
|
|
raise CodeError("unsupported register for aug assign", str(lvalue)) # @todo &=.word
|
|
|
|
elif operator == "|=":
|
2018-01-28 20:58:16 +00:00
|
|
|
if lvalue.name == "A":
|
2018-01-23 23:41:50 +00:00
|
|
|
out("\vora #" + r_str)
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "X":
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtxa")
|
|
|
|
out("\vora #" + r_str)
|
|
|
|
out("\vtax")
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "Y":
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtya")
|
|
|
|
out("\vora #" + r_str)
|
|
|
|
out("\vtay")
|
|
|
|
else:
|
|
|
|
raise CodeError("unsupported register for aug assign", str(lvalue)) # @todo |=.word
|
|
|
|
elif operator == "^=":
|
2018-01-28 20:58:16 +00:00
|
|
|
if lvalue.name == "A":
|
2018-01-23 23:41:50 +00:00
|
|
|
out("\veor #" + r_str)
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "X":
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtxa")
|
|
|
|
out("\veor #" + r_str)
|
|
|
|
out("\vtax")
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "Y":
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtya")
|
|
|
|
out("\veor #" + r_str)
|
|
|
|
out("\vtay")
|
|
|
|
else:
|
|
|
|
raise CodeError("unsupported register for aug assign", str(lvalue)) # @todo ^=.word
|
|
|
|
elif operator == ">>=":
|
2018-01-29 21:34:28 +00:00
|
|
|
if rvalue > 0:
|
2018-01-23 23:41:50 +00:00
|
|
|
def shifts_A(times: int) -> None:
|
|
|
|
if times >= 8:
|
|
|
|
out("\vlda #0")
|
|
|
|
else:
|
|
|
|
for _ in range(min(8, times)):
|
|
|
|
out("\vlsr a")
|
2018-01-28 20:58:16 +00:00
|
|
|
if lvalue.name == "A":
|
2018-01-29 21:34:28 +00:00
|
|
|
shifts_A(rvalue)
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "X":
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtxa")
|
2018-01-29 21:34:28 +00:00
|
|
|
shifts_A(rvalue)
|
2018-01-23 23:41:50 +00:00
|
|
|
out("\vtax")
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "Y":
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtya")
|
2018-01-29 21:34:28 +00:00
|
|
|
shifts_A(rvalue)
|
2018-01-23 23:41:50 +00:00
|
|
|
out("\vtay")
|
|
|
|
else:
|
|
|
|
raise CodeError("unsupported register for aug assign", str(lvalue)) # @todo >>=.word
|
|
|
|
elif operator == "<<=":
|
2018-01-29 21:34:28 +00:00
|
|
|
if rvalue > 0:
|
2018-01-23 23:41:50 +00:00
|
|
|
def shifts_A(times: int) -> None:
|
|
|
|
if times >= 8:
|
|
|
|
out("\vlda #0")
|
|
|
|
else:
|
|
|
|
for _ in range(min(8, times)):
|
|
|
|
out("\vasl a")
|
2018-01-28 20:58:16 +00:00
|
|
|
if lvalue.name == "A":
|
2018-01-29 21:34:28 +00:00
|
|
|
shifts_A(rvalue)
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "X":
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtxa")
|
2018-01-29 21:34:28 +00:00
|
|
|
shifts_A(rvalue)
|
2018-01-23 23:41:50 +00:00
|
|
|
out("\vtax")
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "Y":
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtya")
|
2018-01-29 21:34:28 +00:00
|
|
|
shifts_A(rvalue)
|
2018-01-23 23:41:50 +00:00
|
|
|
out("\vtay")
|
|
|
|
else:
|
|
|
|
raise CodeError("unsupported register for aug assign", str(lvalue)) # @todo <<=.word
|
2018-01-14 14:18:50 +00:00
|
|
|
|
|
|
|
|
2018-01-23 23:41:50 +00:00
|
|
|
def _generate_aug_reg_reg(out: Callable, lvalue: Register, operator: str, rvalue: Register, scope: Scope) -> None:
|
|
|
|
if operator == "+=":
|
2018-01-28 20:58:16 +00:00
|
|
|
if rvalue.name not in REGISTER_BYTES:
|
2018-01-23 23:41:50 +00:00
|
|
|
raise CodeError("unsupported rvalue register for aug assign", str(rvalue)) # @todo +=.word
|
2018-01-28 20:58:16 +00:00
|
|
|
if lvalue.name == "A":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
out("\vclc")
|
|
|
|
out("\vadc " + to_hex(Zeropage.SCRATCH_B1))
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "X":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtxa")
|
|
|
|
out("\vclc")
|
|
|
|
out("\vadc " + to_hex(Zeropage.SCRATCH_B1))
|
|
|
|
out("\vtax")
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "Y":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtya")
|
|
|
|
out("\vclc")
|
|
|
|
out("\vadc " + to_hex(Zeropage.SCRATCH_B1))
|
|
|
|
out("\vtay")
|
|
|
|
else:
|
|
|
|
raise CodeError("unsupported lvalue register for aug assign", str(lvalue)) # @todo +=.word
|
|
|
|
elif operator == "-=":
|
2018-01-28 20:58:16 +00:00
|
|
|
if rvalue.name not in REGISTER_BYTES:
|
2018-01-23 23:41:50 +00:00
|
|
|
raise CodeError("unsupported rvalue register for aug assign", str(rvalue)) # @todo -=.word
|
2018-01-28 20:58:16 +00:00
|
|
|
if lvalue.name == "A":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
out("\vsec")
|
|
|
|
out("\vsbc " + to_hex(Zeropage.SCRATCH_B1))
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "X":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtxa")
|
|
|
|
out("\vsec")
|
|
|
|
out("\vsbc " + to_hex(Zeropage.SCRATCH_B1))
|
|
|
|
out("\vtax")
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "Y":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtya")
|
|
|
|
out("\vsec")
|
|
|
|
out("\vsbc " + to_hex(Zeropage.SCRATCH_B1))
|
|
|
|
out("\vtay")
|
|
|
|
else:
|
|
|
|
raise CodeError("unsupported lvalue register for aug assign", str(lvalue)) # @todo -=.word
|
|
|
|
elif operator == "&=":
|
2018-01-28 20:58:16 +00:00
|
|
|
if rvalue.name not in REGISTER_BYTES:
|
2018-01-23 23:41:50 +00:00
|
|
|
raise CodeError("unsupported rvalue register for aug assign", str(rvalue)) # @todo &=.word
|
2018-01-28 20:58:16 +00:00
|
|
|
if lvalue.name == "A":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
out("\vand " + to_hex(Zeropage.SCRATCH_B1))
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "X":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtxa")
|
|
|
|
out("\vand " + to_hex(Zeropage.SCRATCH_B1))
|
|
|
|
out("\vtax")
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "Y":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtya")
|
|
|
|
out("\vand " + to_hex(Zeropage.SCRATCH_B1))
|
|
|
|
out("\vtay")
|
|
|
|
else:
|
|
|
|
raise CodeError("unsupported lvalue register for aug assign", str(lvalue)) # @todo &=.word
|
|
|
|
elif operator == "|=":
|
2018-01-28 20:58:16 +00:00
|
|
|
if rvalue.name not in REGISTER_BYTES:
|
2018-01-23 23:41:50 +00:00
|
|
|
raise CodeError("unsupported rvalue register for aug assign", str(rvalue)) # @todo |=.word
|
2018-01-28 20:58:16 +00:00
|
|
|
if lvalue.name == "A":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
out("\vora " + to_hex(Zeropage.SCRATCH_B1))
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "X":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtxa")
|
|
|
|
out("\vora " + to_hex(Zeropage.SCRATCH_B1))
|
|
|
|
out("\vtax")
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "Y":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtya")
|
|
|
|
out("\vora " + to_hex(Zeropage.SCRATCH_B1))
|
|
|
|
out("\vtay")
|
|
|
|
else:
|
|
|
|
raise CodeError("unsupported lvalue register for aug assign", str(lvalue)) # @todo |=.word
|
|
|
|
elif operator == "^=":
|
2018-01-28 20:58:16 +00:00
|
|
|
if rvalue.name not in REGISTER_BYTES:
|
2018-01-23 23:41:50 +00:00
|
|
|
raise CodeError("unsupported rvalue register for aug assign", str(rvalue)) # @todo ^=.word
|
2018-01-28 20:58:16 +00:00
|
|
|
if lvalue.name == "A":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
out("\veor " + to_hex(Zeropage.SCRATCH_B1))
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "X":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtxa")
|
|
|
|
out("\veor " + to_hex(Zeropage.SCRATCH_B1))
|
|
|
|
out("\vtax")
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "Y":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtya")
|
|
|
|
out("\veor " + to_hex(Zeropage.SCRATCH_B1))
|
|
|
|
out("\vtay")
|
|
|
|
else:
|
|
|
|
raise CodeError("unsupported lvalue register for aug assign", str(lvalue)) # @todo ^=.word
|
|
|
|
elif operator == ">>=":
|
2018-01-28 20:58:16 +00:00
|
|
|
if rvalue.name not in REGISTER_BYTES:
|
2018-01-23 23:41:50 +00:00
|
|
|
raise CodeError("unsupported rvalue register for aug assign", str(rvalue)) # @todo >>=.word
|
2018-01-28 20:58:16 +00:00
|
|
|
if lvalue.name == "A":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
out("\vlsr " + to_hex(Zeropage.SCRATCH_B1))
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "X":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtxa")
|
|
|
|
out("\vlsr " + to_hex(Zeropage.SCRATCH_B1))
|
|
|
|
out("\vtax")
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "Y":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtya")
|
|
|
|
out("\vlsr " + to_hex(Zeropage.SCRATCH_B1))
|
|
|
|
out("\vtay")
|
|
|
|
else:
|
|
|
|
raise CodeError("unsupported lvalue register for aug assign", str(lvalue)) # @todo >>=.word
|
|
|
|
elif operator == "<<=":
|
2018-01-28 20:58:16 +00:00
|
|
|
if rvalue.name not in REGISTER_BYTES:
|
2018-01-23 23:41:50 +00:00
|
|
|
raise CodeError("unsupported rvalue register for aug assign", str(rvalue)) # @todo <<=.word
|
2018-01-28 20:58:16 +00:00
|
|
|
if lvalue.name == "A":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
out("\vasl " + to_hex(Zeropage.SCRATCH_B1))
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "X":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtxa")
|
|
|
|
out("\vasl " + to_hex(Zeropage.SCRATCH_B1))
|
|
|
|
out("\vtax")
|
2018-01-28 20:58:16 +00:00
|
|
|
elif lvalue.name == "Y":
|
|
|
|
out("\vst{:s} {:s}".format(rvalue.name.lower(), to_hex(Zeropage.SCRATCH_B1)))
|
2018-01-23 23:41:50 +00:00
|
|
|
with preserving_registers({'A'}, scope, out):
|
|
|
|
out("\vtya")
|
|
|
|
out("\vasl " + to_hex(Zeropage.SCRATCH_B1))
|
|
|
|
out("\vtay")
|
|
|
|
else:
|
|
|
|
raise CodeError("unsupported lvalue register for aug assign", str(lvalue)) # @todo <<=.word
|