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

If add and sub can work on words, then cmp can work on words too.

This commit is contained in:
Chris Pressey 2018-11-23 23:00:41 +00:00
parent a765a50c1e
commit dcc944d732
8 changed files with 32 additions and 70 deletions

View File

@ -4,8 +4,8 @@ History of SixtyPical
0.18
----
* Added `compare` instruction, which is like `cmp` but can
directly compare two `word` memory locations (trashing `a`.)
* `cmp` instruction can now perform a 16-bit unsigned comparison
of `word` memory locations (at the cost of trashing `a`.)
* Fixed pathological memory use in the lexical scanner - should
be much less inefficient now when parsing large source files.

View File

@ -376,6 +376,9 @@ and initializing them afterwards.
dest and src continue to be initialized afterwards.
In addition, if dest is of `word` type, then src must also be of `word`
type, and in this case this instruction trashes the `a` register.
### dec ###
dec <dest-memory-location>
@ -401,24 +404,13 @@ does not store the result anywhere, only sets the resulting flags.
Affects n, z, and c flags, requiring that they be in the WRITES,
and initializing them afterwards.
### compare ###
In addition, if dest is of `word` type, then src must also be of `word`
type, and in this case this instruction trashes the `a` register.
compare <dest-memory-location>, <src-memory-location>
Subtracts the contents of src from dest, discarding the result
and only setting the resulting flags. Differs from `cmp` in
that it is able to work on more general types of data (notably,
words) and it trashes the `a` register.
* It is illegal if src OR dest is uninitialized.
Affects n, z, and c flags, requiring that they be in the WRITES,
and initializing them afterwards.
Note that, like `cmp`, `compare` is not suitable for making a
Note that, like `cmp` is not suitable for making a
signed comparison; this article, which mentions
techniques that a SixtyPical compiler could use to
implement `compare`, also explains why that is:
implement `cmp`, also explains why that is:
[Beyond 8-bit Unsigned Comparisons, by Bruce Clark](http://www.6502.org/tutorials/compare_beyond.html).
### and, or, xor ###

View File

@ -505,14 +505,12 @@ class Analyzer(object):
context.assert_meaningful(src, dest)
if isinstance(src, IndexedRef):
context.assert_types_for_read_table(instr, src, dest, TYPE_BYTE)
else:
elif src.type == TYPE_BYTE:
self.assert_type(TYPE_BYTE, src, dest)
context.set_written(FLAG_Z, FLAG_N, FLAG_C)
elif opcode == 'compare':
context.assert_meaningful(src, dest)
self.assert_type(TYPE_WORD, src, dest)
context.set_touched(REG_A)
context.set_unmeaningful(REG_A)
else:
self.assert_type(TYPE_WORD, src, dest)
context.set_touched(REG_A)
context.set_unmeaningful(REG_A)
context.set_written(FLAG_Z, FLAG_N, FLAG_C)
elif opcode == 'and':
if isinstance(src, IndexedRef):

View File

@ -325,8 +325,6 @@ class Compiler(object):
raise UnsupportedOpcodeError(instr)
elif opcode == 'cmp':
self.compile_cmp(instr, instr.src, instr.dest)
elif opcode == 'compare':
self.compile_compare(instr, instr.src, instr.dest)
elif opcode in ('and', 'or', 'xor',):
cls = {
'and': AND,
@ -393,6 +391,17 @@ class Compiler(object):
def compile_cmp(self, instr, src, dest):
"""`instr` is only for reporting purposes"""
if isinstance(src, LocationRef) and src.type == TYPE_WORD:
src_label = self.get_label(src.name)
dest_label = self.get_label(dest.name)
self.emitter.emit(LDA(Absolute(src_label)))
self.emitter.emit(CMP(Absolute(dest_label)))
end_label = Label('end_label')
self.emitter.emit(BNE(Relative(end_label)))
self.emitter.emit(LDA(Absolute(Offset(src_label, 1))))
self.emitter.emit(CMP(Absolute(Offset(dest_label, 1))))
self.emitter.resolve_label(end_label)
return
cls = {
'a': CMP,
'x': CPX,
@ -408,23 +417,6 @@ class Compiler(object):
else:
self.emitter.emit(cls(Absolute(self.get_label(src.name))))
def compile_compare(self, instr, src, dest):
"""`instr` is only for reporting purposes"""
if not isinstance(src, LocationRef) or not isinstance(dest, LocationRef):
raise UnsupportedOpcodeError(instr)
if src.type != TYPE_WORD or dest.type != TYPE_WORD:
raise UnsupportedOpcodeError(instr)
src_label = self.get_label(src.name)
dest_label = self.get_label(dest.name)
self.emitter.emit(LDA(Absolute(src_label)))
self.emitter.emit(CMP(Absolute(dest_label)))
end_label = Label('end_label')
self.emitter.emit(BNE(Relative(end_label)))
self.emitter.emit(LDA(Absolute(Offset(src_label, 1))))
self.emitter.emit(CMP(Absolute(Offset(dest_label, 1))))
self.emitter.resolve_label(end_label)
def compile_inc(self, instr, dest):
"""`instr` is only for reporting purposes"""
if dest == REG_X:

View File

@ -463,14 +463,6 @@ class Parser(object):
dest = self.indlocexpr()
instr = SingleOp(self.scanner.line_number, opcode=opcode, dest=dest, src=src)
return instr
elif self.scanner.token in ("compare",):
opcode = self.scanner.token
self.scanner.scan()
dest = self.locexpr()
self.scanner.expect(',')
src = self.indexed_locexpr()
instr = SingleOp(self.scanner.line_number, opcode=opcode, dest=dest, src=src)
return instr
elif self.scanner.consume("with"):
self.scanner.expect("interrupts")
self.scanner.expect("off")

View File

@ -1118,9 +1118,7 @@ Some rudimentary tests for `cmp`.
| }
? UnmeaningfulReadError: a
### compare ###
Some rudimentary tests for `compare`.
`cmp` can work on words. In this case, it trashes `a`.
| word za
| word zb
@ -1129,7 +1127,7 @@ Some rudimentary tests for `compare`.
| inputs za, zb
| trashes a, z, c, n
| {
| compare za, zb
| cmp za, zb
| }
= ok
@ -1140,7 +1138,7 @@ Some rudimentary tests for `compare`.
| inputs za, zb
| trashes a, z, n
| {
| compare za, zb
| cmp za, zb
| }
? ForbiddenWriteError: c
@ -1151,7 +1149,7 @@ Some rudimentary tests for `compare`.
| inputs za, zb
| trashes z, c, n
| {
| compare za, zb
| cmp za, zb
| }
? ForbiddenWriteError: a
@ -1162,7 +1160,7 @@ Some rudimentary tests for `compare`.
| inputs za
| trashes z, c, n
| {
| compare za, zb
| cmp za, zb
| }
? UnmeaningfulReadError: zb

View File

@ -385,7 +385,7 @@ Some instructions on tables. (3/3)
= $081B DEC $081F,X
= $081E RTS
Compiling `compare`.
Compiling 16-bit `cmp`.
| word za @ 60001
| word zb : 3003
@ -394,7 +394,7 @@ Compiling `compare`.
| inputs za, zb
| trashes a, z, c, n
| {
| compare za, zb
| cmp za, zb
| }
= $080D LDA $081C
= $0810 CMP $EA61

View File

@ -586,16 +586,6 @@ Buffers and pointers.
| }
= ok
Comparison of words.
| word za
| word zb
|
| define main routine inputs za, zb {
| compare za, zb
| }
= ok
Routines can be defined in a new style.
| typedef routine