git @ Cat's Eye Technologies SixtyPical / 35a1053
Support more modes on `add` and `sub`. Chris Pressey 2 years ago
6 changed file(s) with 186 addition(s) and 17 deletion(s). Raw diff Collapse all Expand all
1111 * `cmp` instruction can now perform a 16-bit unsigned comparison
1212 of `word` memory locations and `word` literals (at the cost of
1313 trashing the `a` register.)
14 * `add` (resp. `sub`) now support adding (resp. subtracting) a
15 byte location or a byte literal from a byte location.
1416 * Fixed pathological memory use in the lexical scanner - should
1517 be much less inefficient now when parsing large source files.
1618 * Reorganized the examples in `eg/rudiments/` to make them
332332
333333 Adds the contents of src to dest and stores the result in dest.
334334
335 * It is illegal if src OR dest OR c is uninitialized.
335 * It is illegal if src OR dest OR `c` is uninitialized.
336336 * It is illegal if dest is read-only.
337 * It is illegal if dest is `x` or `y`.
337338 * It is illegal if dest does not occur in the WRITES of the current routine.
338339
339340 Affects n, z, c, and v flags, requiring that they be in the WRITES,
344345 In addition, if dest is of `word` type, then src must also be of `word`
345346 type, and in this case this instruction trashes the `a` register.
346347
348 In fact, this instruction trashes the `a` register in all cases except
349 when the dest is `a`.
350
347351 NOTE: If dest is a pointer, the addition does not check if the result of
348352 the pointer arithmetic continues to be valid (within a buffer) or not.
349353
366370
367371 Subtracts the contents of src from dest and stores the result in dest.
368372
369 * It is illegal if src OR dest OR c is uninitialized.
373 * It is illegal if src OR dest OR `c` is uninitialized.
370374 * It is illegal if dest is read-only.
375 * It is illegal if dest is `x` or `y`.
371376 * It is illegal if dest does not occur in the WRITES of the current routine.
372377
373378 Affects n, z, c, and v flags, requiring that they be in the WRITES,
377382
378383 In addition, if dest is of `word` type, then src must also be of `word`
379384 type, and in this case this instruction trashes the `a` register.
385
386 In fact, this instruction trashes the `a` register in all cases except
387 when the dest is `a`.
380388
381389 ### dec ###
382390
532532 context.assert_types_for_read_table(instr, src, dest, TYPE_BYTE)
533533 elif src.type == TYPE_BYTE:
534534 self.assert_type(TYPE_BYTE, src, dest)
535 if dest != REG_A:
536 context.set_touched(REG_A)
537 context.set_unmeaningful(REG_A)
535538 else:
536539 self.assert_type(TYPE_WORD, src)
537540 if dest.type == TYPE_WORD:
550553 context.assert_types_for_read_table(instr, src, dest, TYPE_BYTE)
551554 elif src.type == TYPE_BYTE:
552555 self.assert_type(TYPE_BYTE, src, dest)
556 if dest != REG_A:
557 context.set_touched(REG_A)
558 context.set_unmeaningful(REG_A)
553559 else:
554560 self.assert_type(TYPE_WORD, src, dest)
555561 context.set_touched(REG_A)
243243 raise UnsupportedOpcodeError(instr)
244244 self.emitter.emit(op_cls(operand))
245245 elif opcode == 'add':
246 if dest == REG_X or dest == REG_Y:
247 raise UnsupportedOpcodeError(instr)
246248 if dest == REG_A:
247249 if isinstance(src, ConstantRef):
248250 self.emitter.emit(ADC(Immediate(Byte(src.value))))
250252 self.emitter.emit(ADC(self.addressing_mode_for_index(src.index)(self.get_label(src.ref.name))))
251253 else:
252254 self.emitter.emit(ADC(Absolute(self.get_label(src.name))))
255 elif isinstance(dest, LocationRef) and src.type == TYPE_BYTE and dest.type == TYPE_BYTE:
256 if isinstance(src, ConstantRef):
257 dest_label = self.get_label(dest.name)
258 self.emitter.emit(LDA(Absolute(dest_label)))
259 self.emitter.emit(ADC(Immediate(Byte(src.low_byte()))))
260 self.emitter.emit(STA(Absolute(dest_label)))
261 elif isinstance(src, LocationRef):
262 src_label = self.get_label(src.name)
263 dest_label = self.get_label(dest.name)
264 self.emitter.emit(LDA(Absolute(dest_label)))
265 self.emitter.emit(ADC(Absolute(src_label)))
266 self.emitter.emit(STA(Absolute(dest_label)))
267 else:
268 raise UnsupportedOpcodeError(instr)
253269 elif isinstance(dest, LocationRef) and src.type == TYPE_WORD and dest.type == TYPE_WORD:
254270 if isinstance(src, ConstantRef):
255271 dest_label = self.get_label(dest.name)
293309 else:
294310 raise UnsupportedOpcodeError(instr)
295311 elif opcode == 'sub':
312 if dest == REG_X or dest == REG_Y:
313 raise UnsupportedOpcodeError(instr)
296314 if dest == REG_A:
297315 if isinstance(src, ConstantRef):
298316 self.emitter.emit(SBC(Immediate(Byte(src.value))))
300318 self.emitter.emit(SBC(self.addressing_mode_for_index(src.index)(self.get_label(src.ref.name))))
301319 else:
302320 self.emitter.emit(SBC(Absolute(self.get_label(src.name))))
321 elif isinstance(dest, LocationRef) and src.type == TYPE_BYTE and dest.type == TYPE_BYTE:
322 if isinstance(src, ConstantRef):
323 dest_label = self.get_label(dest.name)
324 self.emitter.emit(LDA(Absolute(dest_label)))
325 self.emitter.emit(SBC(Immediate(Byte(src.low_byte()))))
326 self.emitter.emit(STA(Absolute(dest_label)))
327 elif isinstance(src, LocationRef):
328 src_label = self.get_label(src.name)
329 dest_label = self.get_label(dest.name)
330 self.emitter.emit(LDA(Absolute(dest_label)))
331 self.emitter.emit(SBC(Absolute(src_label)))
332 self.emitter.emit(STA(Absolute(dest_label)))
333 else:
334 raise UnsupportedOpcodeError(instr)
303335 elif isinstance(dest, LocationRef) and src.type == TYPE_WORD and dest.type == TYPE_WORD:
304336 if isinstance(src, ConstantRef):
305337 dest_label = self.get_label(dest.name)
869869 | byte lives
870870 | define main routine
871871 | inputs a, lives
872 | outputs lives
872 | outputs a, lives
873873 | trashes c, z, v, n
874874 | {
875875 | st off, c
876876 | add lives, 3
877 | }
878 ? UnmeaningfulOutputError: a
879
880 You can `add` a byte memory location to another byte memory location.
881 This trashes `a`.
882
883 | byte lives
884 | byte extra
885 | define main routine
886 | inputs a, lives, extra
887 | outputs lives
888 | trashes a, c, z, v, n
889 | {
890 | st off, c
891 | add lives, extra
892 | }
893 = ok
894
895 | byte lives
896 | byte extra
897 | define main routine
898 | inputs a, lives, extra
899 | outputs a, lives
900 | trashes c, z, v, n
901 | {
902 | st off, c
903 | add lives, extra
877904 | }
878905 ? UnmeaningfulOutputError: a
879906
10391066 | byte lives
10401067 | define main routine
10411068 | inputs a, lives
1042 | outputs lives
1069 | outputs a, lives
10431070 | trashes c, z, v, n
10441071 | {
10451072 | st on, c
10461073 | sub lives, 3
1074 | }
1075 ? UnmeaningfulOutputError: a
1076
1077 You can `sub` a byte memory location from another byte memory location.
1078 This trashes `a`.
1079
1080 | byte lives
1081 | byte extra
1082 | define main routine
1083 | inputs a, lives, extra
1084 | outputs lives
1085 | trashes a, c, z, v, n
1086 | {
1087 | st on, c
1088 | sub lives, extra
1089 | }
1090 = ok
1091
1092 | byte lives
1093 | byte extra
1094 | define main routine
1095 | inputs a, lives, extra
1096 | outputs a, lives
1097 | trashes c, z, v, n
1098 | {
1099 | st on, c
1100 | sub lives, extra
10471101 | }
10481102 ? UnmeaningfulOutputError: a
10491103
10291029 Various modes of `add`.
10301030
10311031 | byte lives
1032 | byte extra
10321033 | word score
1033 | define main routine
1034 | inputs lives, score
1034 | word bonus
1035 | define main routine
1036 | inputs lives, score, extra, bonus
10351037 | outputs lives, score
10361038 | trashes a, x, y, c, z, v, n
10371039 | {
10411043 | st off, c
10421044 | add a, 7
10431045 | add a, lives
1044 | // add x, 7
1045 | // add y, 7
10461046 | add lives, 2
1047 | add lives, extra
10471048 | add score, 1999
1048 | }
1049 = $080D CLC
1050 = $080E LDA $081F
1051 = $0811 ADC #$CF
1052 = $0813 STA $081F
1053 = $0816 LDA $0820
1054 = $0819 ADC #$07
1055 = $081B STA $0820
1056 = $081E RTS
1049 | add score, bonus
1050 | }
1051 = $080D LDA #$00
1052 = $080F LDX #$00
1053 = $0811 LDY #$00
1054 = $0813 CLC
1055 = $0814 ADC #$07
1056 = $0816 ADC $084D
1057 = $0819 LDA $084D
1058 = $081C ADC #$02
1059 = $081E STA $084D
1060 = $0821 LDA $084D
1061 = $0824 ADC $084E
1062 = $0827 STA $084D
1063 = $082A LDA $084F
1064 = $082D ADC #$CF
1065 = $082F STA $084F
1066 = $0832 LDA $0850
1067 = $0835 ADC #$07
1068 = $0837 STA $0850
1069 = $083A LDA $084F
1070 = $083D ADC $0851
1071 = $0840 STA $084F
1072 = $0843 LDA $0850
1073 = $0846 ADC $0852
1074 = $0849 STA $0850
1075 = $084C RTS
1076
1077 Various modes of `sub`.
1078
1079 | byte lives
1080 | byte extra
1081 | word score
1082 | word bonus
1083 | define main routine
1084 | inputs lives, score, extra, bonus
1085 | outputs lives, score
1086 | trashes a, x, y, c, z, v, n
1087 | {
1088 | ld a, 0
1089 | ld x, 0
1090 | ld y, 0
1091 | st on, c
1092 | sub a, 7
1093 | sub a, lives
1094 | sub lives, 2
1095 | sub lives, extra
1096 | sub score, 1999
1097 | sub score, bonus
1098 | }
1099 = $080D LDA #$00
1100 = $080F LDX #$00
1101 = $0811 LDY #$00
1102 = $0813 SEC
1103 = $0814 SBC #$07
1104 = $0816 SBC $084D
1105 = $0819 LDA $084D
1106 = $081C SBC #$02
1107 = $081E STA $084D
1108 = $0821 LDA $084D
1109 = $0824 SBC $084E
1110 = $0827 STA $084D
1111 = $082A LDA $084F
1112 = $082D SBC #$CF
1113 = $082F STA $084F
1114 = $0832 LDA $0850
1115 = $0835 SBC #$07
1116 = $0837 STA $0850
1117 = $083A LDA $084F
1118 = $083D SBC $0851
1119 = $0840 STA $084F
1120 = $0843 LDA $0850
1121 = $0846 SBC $0852
1122 = $0849 STA $0850
1123 = $084C RTS
10571124
10581125 ### word operations
10591126