mirror of
https://github.com/catseye/SixtyPical.git
synced 2025-01-23 10:30:16 +00:00
Analyze reads and updates of tables.
This commit is contained in:
parent
0c22944afc
commit
5fcbfa1d21
@ -279,6 +279,19 @@ class Context(object):
|
||||
def encountered_gotos(self):
|
||||
return self._gotos_encountered
|
||||
|
||||
def assert_types_for_read_table(self, instr, src, dest, type_):
|
||||
if (not TableType.is_a_table_type(src.ref.type, type_)) or (not dest.type == type_):
|
||||
raise TypeMismatchError(instr, '{} and {}'.format(src.ref.name, dest.name))
|
||||
self.assert_meaningful(src, src.index)
|
||||
self.assert_in_range(src.index, src.ref)
|
||||
|
||||
def assert_types_for_update_table(self, instr, dest, type_):
|
||||
if not TableType.is_a_table_type(dest.ref.type, type_):
|
||||
raise TypeMismatchError(instr, '{}'.format(dest.ref.name))
|
||||
self.assert_meaningful(dest.index)
|
||||
self.assert_in_range(dest.index, dest.ref)
|
||||
self.set_written(dest.ref)
|
||||
|
||||
|
||||
class Analyzer(object):
|
||||
|
||||
@ -386,12 +399,7 @@ class Analyzer(object):
|
||||
|
||||
if opcode == 'ld':
|
||||
if isinstance(src, IndexedRef):
|
||||
if TableType.is_a_table_type(src.ref.type, TYPE_BYTE) and dest.type == TYPE_BYTE:
|
||||
pass
|
||||
else:
|
||||
raise TypeMismatchError(instr, '{} and {}'.format(src.ref.name, dest.name))
|
||||
context.assert_meaningful(src, src.index)
|
||||
context.assert_in_range(src.index, src.ref)
|
||||
context.assert_types_for_read_table(instr, src, dest, TYPE_BYTE)
|
||||
elif isinstance(src, IndirectRef):
|
||||
# copying this analysis from the matching branch in `copy`, below
|
||||
if isinstance(src.ref.type, PointerType) and dest.type == TYPE_BYTE:
|
||||
@ -407,13 +415,9 @@ class Analyzer(object):
|
||||
context.set_written(dest, FLAG_Z, FLAG_N)
|
||||
elif opcode == 'st':
|
||||
if isinstance(dest, IndexedRef):
|
||||
if src.type == TYPE_BYTE and TableType.is_a_table_type(dest.ref.type, TYPE_BYTE):
|
||||
pass
|
||||
else:
|
||||
if src.type != TYPE_BYTE:
|
||||
raise TypeMismatchError(instr, (src, dest))
|
||||
context.assert_meaningful(dest.index)
|
||||
context.assert_in_range(dest.index, dest.ref)
|
||||
context.set_written(dest.ref)
|
||||
context.assert_types_for_update_table(instr, dest, TYPE_BYTE)
|
||||
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:
|
||||
@ -430,58 +434,79 @@ class Analyzer(object):
|
||||
context.assert_meaningful(src)
|
||||
elif opcode == 'add':
|
||||
context.assert_meaningful(src, dest, FLAG_C)
|
||||
if src.type == TYPE_BYTE:
|
||||
if isinstance(src, IndexedRef):
|
||||
context.assert_types_for_read_table(instr, src, dest, TYPE_BYTE)
|
||||
elif src.type == TYPE_BYTE:
|
||||
self.assert_type(TYPE_BYTE, src, dest)
|
||||
context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V)
|
||||
else:
|
||||
self.assert_type(TYPE_WORD, src)
|
||||
if dest.type == TYPE_WORD:
|
||||
context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V)
|
||||
context.set_touched(REG_A)
|
||||
context.set_unmeaningful(REG_A)
|
||||
elif isinstance(dest.type, PointerType):
|
||||
context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V)
|
||||
context.set_touched(REG_A)
|
||||
context.set_unmeaningful(REG_A)
|
||||
else:
|
||||
self.assert_type(TYPE_WORD, dest)
|
||||
context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V)
|
||||
context.invalidate_range(dest)
|
||||
elif opcode == 'sub':
|
||||
context.assert_meaningful(src, dest, FLAG_C)
|
||||
if src.type == TYPE_BYTE:
|
||||
if isinstance(src, IndexedRef):
|
||||
context.assert_types_for_read_table(instr, src, dest, TYPE_BYTE)
|
||||
elif src.type == TYPE_BYTE:
|
||||
self.assert_type(TYPE_BYTE, src, dest)
|
||||
context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V)
|
||||
else:
|
||||
self.assert_type(TYPE_WORD, src, dest)
|
||||
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.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V)
|
||||
context.invalidate_range(dest)
|
||||
elif opcode == 'cmp':
|
||||
self.assert_type(TYPE_BYTE, src, dest)
|
||||
context.assert_meaningful(src, dest)
|
||||
if isinstance(src, IndexedRef):
|
||||
context.assert_types_for_read_table(instr, src, dest, TYPE_BYTE)
|
||||
else:
|
||||
self.assert_type(TYPE_BYTE, src, dest)
|
||||
context.set_written(FLAG_Z, FLAG_N, FLAG_C)
|
||||
elif opcode == 'and':
|
||||
if isinstance(src, IndexedRef):
|
||||
context.assert_types_for_read_table(instr, src, dest, TYPE_BYTE)
|
||||
else:
|
||||
self.assert_type(TYPE_BYTE, src, dest)
|
||||
context.assert_meaningful(src, dest)
|
||||
context.set_written(dest, FLAG_Z, FLAG_N)
|
||||
# If you AND the A register with a value V, the resulting value of A
|
||||
# cannot exceed the value of V; i.e. the maximum value of A becomes
|
||||
# the maximum value of V.
|
||||
if not isinstance(src, IndexedRef):
|
||||
context.set_top_of_range(dest, context.get_top_of_range(src))
|
||||
elif opcode in ('or', 'xor'):
|
||||
if isinstance(src, IndexedRef):
|
||||
context.assert_types_for_read_table(instr, src, dest, TYPE_BYTE)
|
||||
else:
|
||||
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'):
|
||||
elif opcode in ('inc', 'dec'):
|
||||
context.assert_meaningful(dest)
|
||||
if isinstance(dest, IndexedRef):
|
||||
context.assert_types_for_update_table(instr, dest, TYPE_BYTE)
|
||||
context.set_written(dest.ref, FLAG_Z, FLAG_N)
|
||||
#context.invalidate_range(dest)
|
||||
else:
|
||||
self.assert_type(TYPE_BYTE, dest)
|
||||
context.set_written(dest, FLAG_Z, FLAG_N)
|
||||
context.invalidate_range(dest)
|
||||
elif opcode in ('shl', 'shr'):
|
||||
context.assert_meaningful(dest, FLAG_C)
|
||||
if isinstance(dest, IndexedRef):
|
||||
context.assert_types_for_update_table(instr, dest, TYPE_BYTE)
|
||||
context.set_written(dest.ref, FLAG_Z, FLAG_N, FLAG_C)
|
||||
#context.invalidate_range(dest)
|
||||
else:
|
||||
self.assert_type(TYPE_BYTE, dest)
|
||||
context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C)
|
||||
context.invalidate_range(dest)
|
||||
elif opcode == 'call':
|
||||
|
@ -474,7 +474,43 @@ The index must be initialized.
|
||||
| }
|
||||
? UnmeaningfulReadError: x
|
||||
|
||||
There are other operations you can do on tables.
|
||||
There are other operations you can do on tables. (1/3)
|
||||
|
||||
| byte table[256] many
|
||||
|
|
||||
| routine main
|
||||
| inputs many
|
||||
| outputs many
|
||||
| trashes a, x, c, n, z, v
|
||||
| {
|
||||
| ld x, 0
|
||||
| ld a, 0
|
||||
| st off, c
|
||||
| add a, many + x
|
||||
| sub a, many + x
|
||||
| cmp a, many + x
|
||||
| }
|
||||
= ok
|
||||
|
||||
There are other operations you can do on tables. (2/3)
|
||||
|
||||
| byte table[256] many
|
||||
|
|
||||
| routine main
|
||||
| inputs many
|
||||
| outputs many
|
||||
| trashes a, x, c, n, z
|
||||
| {
|
||||
| ld x, 0
|
||||
| ld a, 0
|
||||
| and a, many + x
|
||||
| or a, many + x
|
||||
| xor a, many + x
|
||||
| }
|
||||
= ok
|
||||
|
||||
|
||||
There are other operations you can do on tables. (3/3)
|
||||
|
||||
| byte table[256] many
|
||||
|
|
||||
@ -486,12 +522,6 @@ There are other operations you can do on tables.
|
||||
| ld x, 0
|
||||
| ld a, 0
|
||||
| st off, c
|
||||
| add a, many + x
|
||||
| sub a, many + x
|
||||
| cmp a, many + x
|
||||
| and a, many + x
|
||||
| or a, many + x
|
||||
| xor a, many + x
|
||||
| shl many + x
|
||||
| shr many + x
|
||||
| inc many + x
|
||||
|
Loading…
x
Reference in New Issue
Block a user