1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2025-01-24 01:35:50 +00:00

Support indirect refs in st, e.g. st a, [ptr] + y.

This commit is contained in:
Chris Pressey 2018-02-09 11:23:18 +00:00
parent a7365731ca
commit ca1c877a60
7 changed files with 92 additions and 20 deletions

View File

@ -4,8 +4,9 @@ History of SixtyPical
0.12
----
* `copy` is now understood to trash `a`, thus `copy ..., a` is not valid.
Indirect addressing is supported in `ld`, as in `ld a, [ptr] + y`, to compensate.
* `copy` is now understood to trash `a`, thus it is not valid to use it in `copy`.
To compensate, indirect addressing is supported in `ld` and `st`, for example,
as `ld a, [ptr] + y` and `st a, [ptr] + y`.
* Implements the "union rule for trashes" when analyzing `if` blocks.
* Even if we `goto` another routine, we can't trash an output.
* Fixed bug where `trash` was not marking the location as being virtually altered.

View File

@ -240,7 +240,7 @@ underlying opcodes.
There is another mode of `ld` which reads into `a` indirectly through a pointer.
copy [<src-memory-location>] + y, <dest-memory-location>
ld a, [<src-memory-location>] + y
The memory location in this syntax must be a pointer.
@ -266,6 +266,19 @@ changed by this instruction (unless of course dest is a flag.)
If and only if dest is a byte table, the index-memory-location must be given.
There is another mode of `st` which write `a` into memory, indirectly through
a pointer.
st a, [<dest-memory-location>] + y
The memory location in this syntax must be a pointer.
This syntax copies the constents of the `a` register into
the contents of memory at the pointer (offset by the `y` register).
In addition to the constraints above, `y` must be initialized before
this mode is used.
### copy ###
copy <src-memory-location>, <dest-memory-location>

View File

@ -273,18 +273,28 @@ class Analyzer(object):
context.assert_meaningful(src)
context.set_written(dest, FLAG_Z, FLAG_N)
elif opcode == 'st':
if instr.index:
if src.type == TYPE_BYTE and TableType.is_a_table_type(dest.type, TYPE_BYTE):
if isinstance(dest, IndexedRef):
if src.type == TYPE_BYTE and TableType.is_a_table_type(dest.ref.type, TYPE_BYTE):
pass
else:
raise TypeMismatchError((src, dest))
context.assert_meaningful(instr.index)
context.assert_meaningful(dest.index)
context.set_written(dest.ref)
elif isinstance(dest, IndirectRef):
# copying this analysis from the matching branch in `copy`, below
if isinstance(dest.ref.type, PointerType) and src.type == TYPE_BYTE:
pass
else:
raise TypeMismatchError((src, dest))
context.assert_meaningful(dest.ref, REG_Y)
context.set_written(dest.ref)
elif src.type != dest.type:
raise TypeMismatchError('%r and %r in %s' %
(src, dest, self.current_routine.name)
)
else:
context.set_written(dest)
context.assert_meaningful(src)
context.set_written(dest)
elif opcode == 'add':
context.assert_meaningful(src, dest, FLAG_C)
if src.type == TYPE_BYTE:

View File

@ -137,8 +137,6 @@ class Compiler(object):
self.emitter.emit(LDA(AbsoluteY(self.labels[src.name])))
elif isinstance(src, IndirectRef) and isinstance(src.ref.type, PointerType):
self.emitter.emit(LDA(IndirectY(self.labels[src.ref.name])))
elif isinstance(src, IndirectRef) and src.index == REG_Y:
self.emitter.emit(LDA(AbsoluteY(self.labels[src.name])))
else:
self.emitter.emit(LDA(Absolute(self.labels[src.name])))
elif dest == REG_X:
@ -172,14 +170,23 @@ class Compiler(object):
REG_X: STX,
REG_Y: STY
}.get(src, None)
mode_cls = {
REG_X: AbsoluteX,
REG_Y: AbsoluteY,
None: Absolute
}.get(instr.index, None)
if isinstance(dest, IndexedRef):
mode_cls = {
REG_X: AbsoluteX,
REG_Y: AbsoluteY,
}[dest.index]
label = self.labels[dest.ref.name]
elif isinstance(dest, IndirectRef) and isinstance(dest.ref.type, PointerType):
mode_cls = IndirectY
label = self.labels[dest.ref.name]
else:
mode_cls = Absolute
label = self.labels[dest.name]
if op_cls is None or mode_cls is None:
raise UnsupportedOpcodeError(instr)
self.emitter.emit(op_cls(mode_cls(self.labels[dest.name])))
self.emitter.emit(op_cls(mode_cls(label)))
elif opcode == 'add':
if dest == REG_A:
if isinstance(src, ConstantRef):

View File

@ -339,11 +339,8 @@ class Parser(object):
self.scanner.scan()
src = self.locexpr()
self.scanner.expect(',')
dest = self.locexpr()
index = None
if self.scanner.consume('+'):
index = self.locexpr()
return Instr(opcode=opcode, dest=dest, src=src, index=index)
dest = self.indlocexpr()
return Instr(opcode=opcode, dest=dest, src=src, index=None)
elif self.scanner.token in ("shl", "shr", "inc", "dec"):
opcode = self.scanner.token
self.scanner.scan()

View File

@ -1763,6 +1763,25 @@ not `copy`.
| }
= ok
Write the `a` register through a pointer. Note that this is done with `st`,
not `copy`.
| buffer[2048] buf
| pointer ptr
| byte foo
|
| routine main
| inputs buf
| outputs buf
| trashes a, y, z, n, ptr
| {
| ld y, 0
| copy ^buf, ptr
| ld a, 255
| st a, [ptr] + y
| }
= ok
### routines ###
Routines are constants. You need not, and in fact cannot, specify a constant

View File

@ -858,6 +858,31 @@ Read through a pointer, into a byte storage location, or the `a` register.
= $081C LDA ($FE),Y
= $081E RTS
Write the `a` register through a pointer.
| buffer[2048] buf
| pointer ptr @ 254
| byte foo
|
| routine main
| inputs buf
| outputs buf
| trashes a, y, z, n, ptr
| {
| ld y, 0
| copy ^buf, ptr
| ld a, 255
| st a, [ptr] + y
| }
= $080D LDY #$00
= $080F LDA #$1C
= $0811 STA $FE
= $0813 LDA #$08
= $0815 STA $FF
= $0817 LDA #$FF
= $0819 STA ($FE),Y
= $081B RTS
Add a word memory location, and a literal word, to a pointer, and then read through it.
Note that this is *not* range-checked. (Yet.)