git @ Cat's Eye Technologies SixtyPical / dcc944d
If add and sub can work on words, then cmp can work on words too. Chris Pressey 3 years ago
8 changed file(s) with 33 addition(s) and 71 deletion(s). Raw diff Collapse all Expand all
33 0.18
44 ----
55
6 * Added `compare` instruction, which is like `cmp` but can
7 directly compare two `word` memory locations (trashing `a`.)
6 * `cmp` instruction can now perform a 16-bit unsigned comparison
7 of `word` memory locations (at the cost of trashing `a`.)
88 * Fixed pathological memory use in the lexical scanner - should
99 be much less inefficient now when parsing large source files.
1010
375375
376376 dest and src continue to be initialized afterwards.
377377
378 In addition, if dest is of `word` type, then src must also be of `word`
379 type, and in this case this instruction trashes the `a` register.
380
378381 ### dec ###
379382
380383 dec <dest-memory-location>
400403 Affects n, z, and c flags, requiring that they be in the WRITES,
401404 and initializing them afterwards.
402405
403 ### compare ###
404
405 compare <dest-memory-location>, <src-memory-location>
406
407 Subtracts the contents of src from dest, discarding the result
408 and only setting the resulting flags. Differs from `cmp` in
409 that it is able to work on more general types of data (notably,
410 words) and it trashes the `a` register.
411
412 * It is illegal if src OR dest is uninitialized.
413
414 Affects n, z, and c flags, requiring that they be in the WRITES,
415 and initializing them afterwards.
416
417 Note that, like `cmp`, `compare` is not suitable for making a
406 In addition, if dest is of `word` type, then src must also be of `word`
407 type, and in this case this instruction trashes the `a` register.
408
409 Note that, like `cmp` is not suitable for making a
418410 signed comparison; this article, which mentions
419411 techniques that a SixtyPical compiler could use to
420 implement `compare`, also explains why that is:
412 implement `cmp`, also explains why that is:
421413 [Beyond 8-bit Unsigned Comparisons, by Bruce Clark](http://www.6502.org/tutorials/compare_beyond.html).
422414
423415 ### and, or, xor ###
504504 context.assert_meaningful(src, dest)
505505 if isinstance(src, IndexedRef):
506506 context.assert_types_for_read_table(instr, src, dest, TYPE_BYTE)
507 else:
507 elif src.type == TYPE_BYTE:
508508 self.assert_type(TYPE_BYTE, src, dest)
509 context.set_written(FLAG_Z, FLAG_N, FLAG_C)
510 elif opcode == 'compare':
511 context.assert_meaningful(src, dest)
512 self.assert_type(TYPE_WORD, src, dest)
513 context.set_touched(REG_A)
514 context.set_unmeaningful(REG_A)
509 else:
510 self.assert_type(TYPE_WORD, src, dest)
511 context.set_touched(REG_A)
512 context.set_unmeaningful(REG_A)
515513 context.set_written(FLAG_Z, FLAG_N, FLAG_C)
516514 elif opcode == 'and':
517515 if isinstance(src, IndexedRef):
324324 raise UnsupportedOpcodeError(instr)
325325 elif opcode == 'cmp':
326326 self.compile_cmp(instr, instr.src, instr.dest)
327 elif opcode == 'compare':
328 self.compile_compare(instr, instr.src, instr.dest)
329327 elif opcode in ('and', 'or', 'xor',):
330328 cls = {
331329 'and': AND,
392390
393391 def compile_cmp(self, instr, src, dest):
394392 """`instr` is only for reporting purposes"""
393 if isinstance(src, LocationRef) and src.type == TYPE_WORD:
394 src_label = self.get_label(src.name)
395 dest_label = self.get_label(dest.name)
396 self.emitter.emit(LDA(Absolute(src_label)))
397 self.emitter.emit(CMP(Absolute(dest_label)))
398 end_label = Label('end_label')
399 self.emitter.emit(BNE(Relative(end_label)))
400 self.emitter.emit(LDA(Absolute(Offset(src_label, 1))))
401 self.emitter.emit(CMP(Absolute(Offset(dest_label, 1))))
402 self.emitter.resolve_label(end_label)
403 return
395404 cls = {
396405 'a': CMP,
397406 'x': CPX,
406415 self.emitter.emit(cls(self.addressing_mode_for_index(src.index)(self.get_label(src.ref.name))))
407416 else:
408417 self.emitter.emit(cls(Absolute(self.get_label(src.name))))
409
410 def compile_compare(self, instr, src, dest):
411 """`instr` is only for reporting purposes"""
412 if not isinstance(src, LocationRef) or not isinstance(dest, LocationRef):
413 raise UnsupportedOpcodeError(instr)
414 if src.type != TYPE_WORD or dest.type != TYPE_WORD:
415 raise UnsupportedOpcodeError(instr)
416
417 src_label = self.get_label(src.name)
418 dest_label = self.get_label(dest.name)
419 self.emitter.emit(LDA(Absolute(src_label)))
420 self.emitter.emit(CMP(Absolute(dest_label)))
421 end_label = Label('end_label')
422 self.emitter.emit(BNE(Relative(end_label)))
423 self.emitter.emit(LDA(Absolute(Offset(src_label, 1))))
424 self.emitter.emit(CMP(Absolute(Offset(dest_label, 1))))
425 self.emitter.resolve_label(end_label)
426418
427419 def compile_inc(self, instr, dest):
428420 """`instr` is only for reporting purposes"""
462462 dest = self.indlocexpr()
463463 instr = SingleOp(self.scanner.line_number, opcode=opcode, dest=dest, src=src)
464464 return instr
465 elif self.scanner.token in ("compare",):
466 opcode = self.scanner.token
467 self.scanner.scan()
468 dest = self.locexpr()
469 self.scanner.expect(',')
470 src = self.indexed_locexpr()
471 instr = SingleOp(self.scanner.line_number, opcode=opcode, dest=dest, src=src)
472 return instr
473465 elif self.scanner.consume("with"):
474466 self.scanner.expect("interrupts")
475467 self.scanner.expect("off")
11171117 | }
11181118 ? UnmeaningfulReadError: a
11191119
1120 ### compare ###
1121
1122 Some rudimentary tests for `compare`.
1120 `cmp` can work on words. In this case, it trashes `a`.
11231121
11241122 | word za
11251123 | word zb
11281126 | inputs za, zb
11291127 | trashes a, z, c, n
11301128 | {
1131 | compare za, zb
1129 | cmp za, zb
11321130 | }
11331131 = ok
11341132
11391137 | inputs za, zb
11401138 | trashes a, z, n
11411139 | {
1142 | compare za, zb
1140 | cmp za, zb
11431141 | }
11441142 ? ForbiddenWriteError: c
11451143
11501148 | inputs za, zb
11511149 | trashes z, c, n
11521150 | {
1153 | compare za, zb
1151 | cmp za, zb
11541152 | }
11551153 ? ForbiddenWriteError: a
11561154
11611159 | inputs za
11621160 | trashes z, c, n
11631161 | {
1164 | compare za, zb
1162 | cmp za, zb
11651163 | }
11661164 ? UnmeaningfulReadError: zb
11671165
384384 = $081B DEC $081F,X
385385 = $081E RTS
386386
387 Compiling `compare`.
387 Compiling 16-bit `cmp`.
388388
389389 | word za @ 60001
390390 | word zb : 3003
393393 | inputs za, zb
394394 | trashes a, z, c, n
395395 | {
396 | compare za, zb
396 | cmp za, zb
397397 | }
398398 = $080D LDA $081C
399399 = $0810 CMP $EA61
585585 | }
586586 = ok
587587
588 Comparison of words.
589
590 | word za
591 | word zb
592 |
593 | define main routine inputs za, zb {
594 | compare za, zb
595 | }
596 = ok
597
598588 Routines can be defined in a new style.
599589
600590 | typedef routine