git @ Cat's Eye Technologies SixtyPical / bda0202
Confirm that AND clips the range and INC/DEC invalidate it. Chris Pressey 3 years ago
3 changed file(s) with 72 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
3030 * [SixtyPical specification](doc/SixtyPical.md)
3131 * [SixtyPical revision history](HISTORY.md)
3232 * [Literate test suite for SixtyPical syntax](tests/SixtyPical%20Syntax.md)
33 * [Literate test suite for SixtyPical execution](tests/SixtyPical%20Execution.md)
3433 * [Literate test suite for SixtyPical analysis](tests/SixtyPical%20Analysis.md)
3534 * [Literate test suite for SixtyPical compilation](tests/SixtyPical%20Compilation.md)
3635 * [6502 Opcodes used/not used in SixtyPical](doc/6502%20Opcodes.md)
7776 ### Re-order routines and optimize tail-calls to fallthroughs
7877
7978 Not because it saves 3 bytes, but because it's a neat trick. Doing it optimally
80 is probably NP-complete. But doing it adeuqately is probably not that hard.
79 is probably NP-complete. But doing it adequately is probably not that hard.
80
81 ### Different preludes for different architectures
82
83 `--prelude=c64-basic`
8184
8285 ### And at some point...
8386
84 * Confirm that `and` can be used to restrict the range of table reads/writes.
8587 * `low` and `high` address operators - to turn `word` type into `byte`.
8688 * `const`s that can be used in defining the size of tables, etc.
8789 * Tests, and implementation, ensuring a routine can be assigned to a vector of "wider" type
193193 def set_touched(self, *refs):
194194 for ref in refs:
195195 self._touched.add(ref)
196 # TODO: it might be possible to invalidate the range here
196197
197198 def set_meaningful(self, *refs):
198199 for ref in refs:
218219 else:
219220 src_range = src.max_range()
220221 self._range[dest] = src_range
222
223 def invalidate_range(self, ref):
224 self.assert_meaningful(ref)
225 self._range[ref] = ref.max_range()
221226
222227 def set_unmeaningful(self, *refs):
223228 for ref in refs:
376381 raise TypeMismatchError(instr, '{} and {}'.format(src, name))
377382 else:
378383 context.set_written(dest)
384 # FIXME: context.copy_range(src, dest) ?
379385 context.assert_meaningful(src)
380386 elif opcode == 'add':
381387 context.assert_meaningful(src, dest, FLAG_C)
394400 context.set_unmeaningful(REG_A)
395401 else:
396402 self.assert_type(TYPE_WORD, dest)
403 context.invalidate_range(dest)
397404 elif opcode == 'sub':
398405 context.assert_meaningful(src, dest, FLAG_C)
399406 if src.type == TYPE_BYTE:
404411 context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V)
405412 context.set_touched(REG_A)
406413 context.set_unmeaningful(REG_A)
414 context.invalidate_range(dest)
407415 elif opcode in ('inc', 'dec'):
408416 self.assert_type(TYPE_BYTE, dest)
409417 context.assert_meaningful(dest)
410418 context.set_written(dest, FLAG_Z, FLAG_N)
419 context.invalidate_range(dest)
411420 elif opcode == 'cmp':
412421 self.assert_type(TYPE_BYTE, src, dest)
413422 context.assert_meaningful(src, dest)
424433 self.assert_type(TYPE_BYTE, src, dest)
425434 context.assert_meaningful(src, dest)
426435 context.set_written(dest, FLAG_Z, FLAG_N)
436 context.invalidate_range(dest)
427437 elif opcode in ('shl', 'shr'):
428438 self.assert_type(TYPE_BYTE, dest)
429439 context.assert_meaningful(dest, FLAG_C)
430440 context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C)
441 context.invalidate_range(dest)
431442 elif opcode == 'call':
432443 type = instr.location.type
433444 if isinstance(type, VectorType):
619619 | {
620620 | ld x, 32
621621 | copy one, many + x
622 | }
623 ? RangeExceededError
624
625 `AND`'ing a register with a value ensures the range of the
626 register will not exceed the range of the value. This can
627 be used to "clip" the range of an index so that it fits in
628 a table.
629
630 | word one: 77
631 | word table[32] many
632 |
633 | routine main
634 | inputs a, many, one
635 | outputs many, one
636 | trashes a, x, n, z
637 | {
638 | and a, 31
639 | ld x, a
640 | copy one, many + x
641 | copy many + x, one
642 | }
643 = ok
644
645 Test for "clipping", but not enough.
646
647 | word one: 77
648 | word table[32] many
649 |
650 | routine main
651 | inputs a, many, one
652 | outputs many, one
653 | trashes a, x, n, z
654 | {
655 | and a, 63
656 | ld x, a
657 | copy one, many + x
658 | copy many + x, one
659 | }
660 ? RangeExceededError
661
662 If you alter the value after "clipping" it, the range can
663 no longer be guaranteed.
664
665 | word one: 77
666 | word table[32] many
667 |
668 | routine main
669 | inputs a, many, one
670 | outputs many, one
671 | trashes a, x, n, z
672 | {
673 | and a, 31
674 | ld x, a
675 | inc x
676 | copy one, many + x
677 | copy many + x, one
622678 | }
623679 ? RangeExceededError
624680