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:
parent
a7365731ca
commit
ca1c877a60
@ -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.
|
||||
|
@ -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>
|
||||
|
@ -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:
|
||||
|
@ -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):
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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.)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user