Initial attempt at 16-bit compare. Not super well tested yet.
Chris Pressey
3 years ago
287 | 287 | |
288 | 288 | copy <src-memory-location>, <dest-memory-location> |
289 | 289 | |
290 | Reads from src and writes to dest. Differs from `st` in that is able to | |
291 | copy more general types of data (for example, vectors,) and it trashes the | |
292 | `z` and `n` flags and the `a` register. | |
290 | Reads from src and writes to dest. Differs from `ld` and `st` in that | |
291 | it is able to copy more general types of data (for example, vectors,) | |
292 | and it trashes the `z` and `n` flags and the `a` register. | |
293 | 293 | |
294 | 294 | * It is illegal if dest is read-only. |
295 | 295 | * It is illegal if dest does not occur in the WRITES of the current routine. |
394 | 394 | |
395 | 395 | Subtracts the contents of src from dest (without considering carry) but |
396 | 396 | does not store the result anywhere, only sets the resulting flags. |
397 | ||
398 | * It is illegal if src OR dest is uninitialized. | |
399 | ||
400 | Affects n, z, and c flags, requiring that they be in the WRITES, | |
401 | and initializing them afterwards. | |
402 | ||
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. | |
397 | 411 | |
398 | 412 | * It is illegal if src OR dest is uninitialized. |
399 | 413 |
506 | 506 | context.assert_types_for_read_table(instr, src, dest, TYPE_BYTE) |
507 | 507 | else: |
508 | 508 | 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 | 515 | context.set_written(FLAG_Z, FLAG_N, FLAG_C) |
510 | 516 | elif opcode == 'and': |
511 | 517 | if isinstance(src, IndexedRef): |
324 | 324 | raise UnsupportedOpcodeError(instr) |
325 | 325 | elif opcode == 'cmp': |
326 | 326 | self.compile_cmp(instr, instr.src, instr.dest) |
327 | elif opcode == 'compare': | |
328 | self.compile_compare(instr, instr.src, instr.dest) | |
327 | 329 | elif opcode in ('and', 'or', 'xor',): |
328 | 330 | cls = { |
329 | 331 | 'and': AND, |
404 | 406 | self.emitter.emit(cls(self.addressing_mode_for_index(src.index)(self.get_label(src.ref.name)))) |
405 | 407 | else: |
406 | 408 | 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) | |
407 | 426 | |
408 | 427 | def compile_inc(self, instr, dest): |
409 | 428 | """`instr` is only for reporting purposes""" |
462 | 462 | dest = self.indlocexpr() |
463 | 463 | instr = SingleOp(self.scanner.line_number, opcode=opcode, dest=dest, src=src) |
464 | 464 | 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 | |
465 | 473 | elif self.scanner.consume("with"): |
466 | 474 | self.scanner.expect("interrupts") |
467 | 475 | self.scanner.expect("off") |
1116 | 1116 | | cmp a, 4 |
1117 | 1117 | | } |
1118 | 1118 | ? UnmeaningfulReadError: a |
1119 | ||
1120 | ### compare ### | |
1121 | ||
1122 | Some rudimentary tests for `compare`. | |
1123 | ||
1124 | | word za | |
1125 | | word zb | |
1126 | | | |
1127 | | define main routine | |
1128 | | inputs za, zb | |
1129 | | trashes a, z, c, n | |
1130 | | { | |
1131 | | compare za, zb | |
1132 | | } | |
1133 | = ok | |
1134 | ||
1135 | | word za | |
1136 | | word zb | |
1137 | | | |
1138 | | define main routine | |
1139 | | inputs za, zb | |
1140 | | trashes a, z, n | |
1141 | | { | |
1142 | | compare za, zb | |
1143 | | } | |
1144 | ? ForbiddenWriteError: c | |
1145 | ||
1146 | | word za | |
1147 | | word zb | |
1148 | | | |
1149 | | define main routine | |
1150 | | inputs za, zb | |
1151 | | trashes z, c, n | |
1152 | | { | |
1153 | | compare za, zb | |
1154 | | } | |
1155 | ? ForbiddenWriteError: a | |
1156 | ||
1157 | | word za | |
1158 | | word zb | |
1159 | | | |
1160 | | define main routine | |
1161 | | inputs za | |
1162 | | trashes z, c, n | |
1163 | | { | |
1164 | | compare za, zb | |
1165 | | } | |
1166 | ? UnmeaningfulReadError: zb | |
1119 | 1167 | |
1120 | 1168 | ### and ### |
1121 | 1169 |
384 | 384 | = $081B DEC $081F,X |
385 | 385 | = $081E RTS |
386 | 386 | |
387 | Compiling `compare`. | |
388 | ||
389 | | word za @ 60001 | |
390 | | word zb : 3003 | |
391 | | | |
392 | | define main routine | |
393 | | inputs za, zb | |
394 | | trashes a, z, c, n | |
395 | | { | |
396 | | compare za, zb | |
397 | | } | |
398 | = $080D LDA $081C | |
399 | = $0810 CMP $EA61 | |
400 | = $0813 BNE $081B | |
401 | = $0815 LDA $081D | |
402 | = $0818 CMP $EA62 | |
403 | = $081B RTS | |
404 | = $081C .byte $BB | |
405 | = $081D .byte $0B | |
406 | ||
387 | 407 | Compiling `if`. |
388 | 408 | |
389 | 409 | | define main routine |