mirror of
https://github.com/catseye/SixtyPical.git
synced 2025-02-12 05:30:32 +00:00
If add and sub can work on words, then cmp can work on words too.
This commit is contained in:
parent
a765a50c1e
commit
dcc944d732
@ -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.
|
||||
|
||||
|
@ -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 ###
|
||||
|
@ -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):
|
||||
|
@ -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:
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user