1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-06-07 06:29:32 +00:00

Confirm that AND clips the range and INC/DEC invalidate it.

This commit is contained in:
Chris Pressey 2018-03-06 15:42:12 +00:00
parent 1eaec602e3
commit bda0202dee
3 changed files with 72 additions and 3 deletions

View File

@ -31,7 +31,6 @@ Documentation
* [SixtyPical specification](doc/SixtyPical.md)
* [SixtyPical revision history](HISTORY.md)
* [Literate test suite for SixtyPical syntax](tests/SixtyPical%20Syntax.md)
* [Literate test suite for SixtyPical execution](tests/SixtyPical%20Execution.md)
* [Literate test suite for SixtyPical analysis](tests/SixtyPical%20Analysis.md)
* [Literate test suite for SixtyPical compilation](tests/SixtyPical%20Compilation.md)
* [6502 Opcodes used/not used in SixtyPical](doc/6502%20Opcodes.md)
@ -78,11 +77,14 @@ are trashed inside the block.
### Re-order routines and optimize tail-calls to fallthroughs
Not because it saves 3 bytes, but because it's a neat trick. Doing it optimally
is probably NP-complete. But doing it adeuqately is probably not that hard.
is probably NP-complete. But doing it adequately is probably not that hard.
### Different preludes for different architectures
`--prelude=c64-basic`
### And at some point...
* Confirm that `and` can be used to restrict the range of table reads/writes.
* `low` and `high` address operators - to turn `word` type into `byte`.
* `const`s that can be used in defining the size of tables, etc.
* Tests, and implementation, ensuring a routine can be assigned to a vector of "wider" type

View File

@ -194,6 +194,7 @@ class Context(object):
def set_touched(self, *refs):
for ref in refs:
self._touched.add(ref)
# TODO: it might be possible to invalidate the range here
def set_meaningful(self, *refs):
for ref in refs:
@ -220,6 +221,10 @@ class Context(object):
src_range = src.max_range()
self._range[dest] = src_range
def invalidate_range(self, ref):
self.assert_meaningful(ref)
self._range[ref] = ref.max_range()
def set_unmeaningful(self, *refs):
for ref in refs:
if ref in self._range:
@ -377,6 +382,7 @@ class Analyzer(object):
raise TypeMismatchError(instr, '{} and {}'.format(src, name))
else:
context.set_written(dest)
# FIXME: context.copy_range(src, dest) ?
context.assert_meaningful(src)
elif opcode == 'add':
context.assert_meaningful(src, dest, FLAG_C)
@ -395,6 +401,7 @@ class Analyzer(object):
context.set_unmeaningful(REG_A)
else:
self.assert_type(TYPE_WORD, dest)
context.invalidate_range(dest)
elif opcode == 'sub':
context.assert_meaningful(src, dest, FLAG_C)
if src.type == TYPE_BYTE:
@ -405,10 +412,12 @@ class Analyzer(object):
context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V)
context.set_touched(REG_A)
context.set_unmeaningful(REG_A)
context.invalidate_range(dest)
elif opcode in ('inc', 'dec'):
self.assert_type(TYPE_BYTE, dest)
context.assert_meaningful(dest)
context.set_written(dest, FLAG_Z, FLAG_N)
context.invalidate_range(dest)
elif opcode == 'cmp':
self.assert_type(TYPE_BYTE, src, dest)
context.assert_meaningful(src, dest)
@ -425,10 +434,12 @@ class Analyzer(object):
self.assert_type(TYPE_BYTE, src, dest)
context.assert_meaningful(src, dest)
context.set_written(dest, FLAG_Z, FLAG_N)
context.invalidate_range(dest)
elif opcode in ('shl', 'shr'):
self.assert_type(TYPE_BYTE, dest)
context.assert_meaningful(dest, FLAG_C)
context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C)
context.invalidate_range(dest)
elif opcode == 'call':
type = instr.location.type
if isinstance(type, VectorType):

View File

@ -623,6 +623,62 @@ This applies to `copy` as well.
| }
? RangeExceededError
`AND`'ing a register with a value ensures the range of the
register will not exceed the range of the value. This can
be used to "clip" the range of an index so that it fits in
a table.
| word one: 77
| word table[32] many
|
| routine main
| inputs a, many, one
| outputs many, one
| trashes a, x, n, z
| {
| and a, 31
| ld x, a
| copy one, many + x
| copy many + x, one
| }
= ok
Test for "clipping", but not enough.
| word one: 77
| word table[32] many
|
| routine main
| inputs a, many, one
| outputs many, one
| trashes a, x, n, z
| {
| and a, 63
| ld x, a
| copy one, many + x
| copy many + x, one
| }
? RangeExceededError
If you alter the value after "clipping" it, the range can
no longer be guaranteed.
| word one: 77
| word table[32] many
|
| routine main
| inputs a, many, one
| outputs many, one
| trashes a, x, n, z
| {
| and a, 31
| ld x, a
| inc x
| copy one, many + x
| copy many + x, one
| }
? RangeExceededError
### add ###
Can't `add` from or to a memory location that isn't initialized.