mirror of
https://github.com/irmen/prog8.git
synced 2024-12-02 07:49:27 +00:00
76 lines
2.5 KiB
Python
76 lines
2.5 KiB
Python
"""
|
|
Programming Language for 6502/6510 microprocessors, codename 'Sick'
|
|
This is the 6502 assembly code generator (directly from the parse tree)
|
|
|
|
Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
|
"""
|
|
|
|
import contextlib
|
|
import attr
|
|
from typing import Set, Callable
|
|
from ...plyparse import Scope, AstNode
|
|
from ...compile import Zeropage
|
|
|
|
|
|
@attr.s(repr=False, cmp=False)
|
|
class Context:
|
|
out = attr.ib(type=Callable)
|
|
stmt = attr.ib(type=AstNode)
|
|
scope = attr.ib(type=Scope)
|
|
floats_enabled = attr.ib(type=bool)
|
|
|
|
|
|
@contextlib.contextmanager
|
|
def preserving_registers(registers: Set[str], scope: Scope, out: Callable, loads_a_within: bool=False, force_preserve: bool=False):
|
|
# this sometimes clobbers a ZP scratch register and is therefore NOT safe to use in interrupts
|
|
# see http://6502.org/tutorials/register_preservation.html
|
|
if not scope.save_registers and not force_preserve:
|
|
yield
|
|
return
|
|
if registers == {'A'}:
|
|
out("\t\tpha")
|
|
yield
|
|
out("\t\tpla")
|
|
elif registers:
|
|
if not loads_a_within:
|
|
out("\t\tsta ${:02x}".format(Zeropage.SCRATCH_B2))
|
|
if 'A' in registers:
|
|
out("\t\tpha")
|
|
if 'X' in registers:
|
|
out("\t\ttxa\n\t\tpha")
|
|
if 'Y' in registers:
|
|
out("\t\ttya\n\t\tpha")
|
|
if not loads_a_within:
|
|
out("\t\tlda ${:02x}".format(Zeropage.SCRATCH_B2))
|
|
yield
|
|
if 'X' in registers and 'Y' in registers:
|
|
if 'A' not in registers:
|
|
out("\t\tsta ${:02x}".format(Zeropage.SCRATCH_B2))
|
|
out("\t\tpla\n\t\ttay")
|
|
out("\t\tpla\n\t\ttax")
|
|
out("\t\tlda ${:02x}".format(Zeropage.SCRATCH_B2))
|
|
else:
|
|
out("\t\tpla\n\t\ttay")
|
|
out("\t\tpla\n\t\ttax")
|
|
else:
|
|
if 'Y' in registers:
|
|
if 'A' not in registers:
|
|
out("\t\tsta ${:02x}".format(Zeropage.SCRATCH_B2))
|
|
out("\t\tpla\n\t\ttay")
|
|
out("\t\tlda ${:02x}".format(Zeropage.SCRATCH_B2))
|
|
else:
|
|
out("\t\tpla\n\t\ttay")
|
|
if 'X' in registers:
|
|
if 'A' not in registers:
|
|
out("\t\tsta ${:02x}".format(Zeropage.SCRATCH_B2))
|
|
out("\t\tpla\n\t\ttax")
|
|
out("\t\tlda ${:02x}".format(Zeropage.SCRATCH_B2))
|
|
else:
|
|
out("\t\tpla\n\t\ttax")
|
|
if 'A' in registers:
|
|
out("\t\tpla")
|
|
else:
|
|
yield
|
|
|
|
|