mirror of
https://github.com/catseye/SixtyPical.git
synced 2025-02-12 20:30:27 +00:00
Compile repeat
loops.
This commit is contained in:
parent
f7eb0d48a8
commit
c5998ed240
@ -18,3 +18,8 @@ in future versions.
|
||||
---
|
||||
|
||||
Added ability to compile to 6502 machine code and output a `PRG` file.
|
||||
|
||||
0.4
|
||||
---
|
||||
|
||||
Added `repeat` loops to the language.
|
||||
|
@ -34,8 +34,6 @@ TODO
|
||||
For 0.4:
|
||||
|
||||
* `if not`.
|
||||
* `while` loops.
|
||||
* `repeat` loops.
|
||||
* explicitly-addressed memory locations
|
||||
|
||||
For 0.5:
|
||||
|
@ -74,7 +74,8 @@ if __name__ == '__main__':
|
||||
|
||||
# we are outputting a .PRG, so we output the load address first
|
||||
# we don't use the Emitter for this b/c not part of addr space
|
||||
fh.write(Word(start_addr).serialize(0))
|
||||
if not options.debug:
|
||||
fh.write(Word(start_addr).serialize(0))
|
||||
|
||||
emitter = Emitter(start_addr)
|
||||
for byte in prelude:
|
||||
|
16
eg/loop.p60
Normal file
16
eg/loop.p60
Normal file
@ -0,0 +1,16 @@
|
||||
routine chrout
|
||||
inputs a
|
||||
trashes a
|
||||
@ 65490
|
||||
|
||||
routine main
|
||||
trashes a, y, z, n, c
|
||||
{
|
||||
ld y, 65
|
||||
repeat {
|
||||
ld a, y
|
||||
call chrout
|
||||
inc y
|
||||
cmp y, 91
|
||||
} until z
|
||||
}
|
@ -9,10 +9,11 @@ from sixtypical.emitter import Label, Byte
|
||||
from sixtypical.gen6502 import (
|
||||
Immediate, Absolute, Relative,
|
||||
LDA, LDX, LDY, STA, STX, STY,
|
||||
TAX, TAY, TXA, TYA,
|
||||
CLC, SEC, ADC, SBC, ROL, ROR,
|
||||
INC, INX, INY, DEC, DEX, DEY,
|
||||
CMP, CPX, CPY, AND, ORA, EOR,
|
||||
BCC, BNE,
|
||||
BCC, BCS, BNE, BEQ,
|
||||
JMP, JSR, RTS,
|
||||
)
|
||||
|
||||
@ -70,17 +71,25 @@ class Compiler(object):
|
||||
|
||||
if opcode == 'ld':
|
||||
if dest == REG_A:
|
||||
if isinstance(src, ConstantRef):
|
||||
if src == REG_X:
|
||||
self.emitter.emit(TXA())
|
||||
elif src == REG_Y:
|
||||
self.emitter.emit(TYA())
|
||||
elif isinstance(src, ConstantRef):
|
||||
self.emitter.emit(LDA(Immediate(Byte(src.value))))
|
||||
else:
|
||||
self.emitter.emit(LDA(Absolute(self.labels[src.name])))
|
||||
elif dest == REG_X:
|
||||
if isinstance(src, ConstantRef):
|
||||
if src == REG_A:
|
||||
self.emitter.emit(TAX())
|
||||
elif isinstance(src, ConstantRef):
|
||||
self.emitter.emit(LDX(Immediate(Byte(src.value))))
|
||||
else:
|
||||
self.emitter.emit(LDX(Absolute(self.labels[src.name])))
|
||||
elif dest == REG_Y:
|
||||
if isinstance(src, ConstantRef):
|
||||
if src == REG_A:
|
||||
self.emitter.emit(TAY())
|
||||
elif isinstance(src, ConstantRef):
|
||||
self.emitter.emit(LDY(Immediate(Byte(src.value))))
|
||||
else:
|
||||
self.emitter.emit(LDY(Absolute(self.labels[src.name])))
|
||||
@ -184,5 +193,15 @@ class Compiler(object):
|
||||
self.emitter.resolve_label(end_label)
|
||||
else:
|
||||
self.emitter.resolve_label(else_label)
|
||||
elif opcode == 'repeat':
|
||||
cls = {
|
||||
'c': BCC,
|
||||
'z': BNE,
|
||||
}.get(src.name)
|
||||
if cls is None:
|
||||
raise UnsupportedOpcodeError(instr)
|
||||
top_label = self.emitter.make_label()
|
||||
self.compile_block(instr.block)
|
||||
self.emitter.emit(cls(Relative(top_label)))
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
@ -99,6 +99,18 @@ class BCC(Opcode):
|
||||
}
|
||||
|
||||
|
||||
class BCS(Opcode):
|
||||
opcodes = {
|
||||
Relative: 0xb0,
|
||||
}
|
||||
|
||||
|
||||
class BEQ(Opcode):
|
||||
opcodes = {
|
||||
Relative: 0xf0,
|
||||
}
|
||||
|
||||
|
||||
class BNE(Opcode):
|
||||
opcodes = {
|
||||
Relative: 0xd0,
|
||||
|
@ -144,3 +144,17 @@ Compiling `if` without `else`.
|
||||
| }
|
||||
| }
|
||||
= 00c0a900d002a00160
|
||||
|
||||
Compiling `repeat`.
|
||||
|
||||
| routine main
|
||||
| trashes a, y, z, n, c
|
||||
| {
|
||||
| ld y, 65
|
||||
| repeat {
|
||||
| ld a, y
|
||||
| inc y
|
||||
| cmp y, 91
|
||||
| } until z
|
||||
| }
|
||||
= 00c0a04198c8c05bd0fa60
|
||||
|
Loading…
x
Reference in New Issue
Block a user