1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-05-31 21:41:29 +00:00

Merge pull request #18 from catseye/more-modes-on-add-and-sub

More modes on add and sub
This commit is contained in:
Chris Pressey 2018-12-12 15:13:26 +00:00 committed by GitHub
commit 75449d7271
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 254 additions and 2 deletions

View File

@ -15,6 +15,8 @@ History of SixtyPical
* `cmp` instruction can now perform a 16-bit unsigned comparison
of `word` memory locations and `word` literals (at the cost of
trashing the `a` register.)
* `add` (resp. `sub`) now support adding (resp. subtracting) a
byte location or a byte literal from a byte location.
* Fixed pathological memory use in the lexical scanner - should
be much less inefficient now when parsing large source files.
* Reorganized the examples in `eg/rudiments/` to make them

View File

@ -333,8 +333,9 @@ this mode is used.
Adds the contents of src to dest and stores the result in dest.
* It is illegal if src OR dest OR c is uninitialized.
* It is illegal if src OR dest OR `c` is uninitialized.
* It is illegal if dest is read-only.
* It is illegal if dest is `x` or `y`.
* It is illegal if dest does not occur in the WRITES of the current routine.
Affects n, z, c, and v flags, requiring that they be in the WRITES,
@ -345,6 +346,9 @@ 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.
In fact, this instruction trashes the `a` register in all cases except
when the dest is `a`.
NOTE: If dest is a pointer, the addition does not check if the result of
the pointer arithmetic continues to be valid (within a buffer) or not.
@ -367,8 +371,9 @@ and initializing them afterwards.
Subtracts the contents of src from dest and stores the result in dest.
* It is illegal if src OR dest OR c is uninitialized.
* It is illegal if src OR dest OR `c` is uninitialized.
* It is illegal if dest is read-only.
* It is illegal if dest is `x` or `y`.
* It is illegal if dest does not occur in the WRITES of the current routine.
Affects n, z, c, and v flags, requiring that they be in the WRITES,
@ -379,6 +384,9 @@ 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.
In fact, this instruction trashes the `a` register in all cases except
when the dest is `a`.
### dec ###
dec <dest-memory-location>

View File

@ -533,6 +533,9 @@ class Analyzer(object):
context.assert_types_for_read_table(instr, src, dest, TYPE_BYTE)
elif src.type == TYPE_BYTE:
self.assert_type(TYPE_BYTE, src, dest)
if dest != REG_A:
context.set_touched(REG_A)
context.set_unmeaningful(REG_A)
else:
self.assert_type(TYPE_WORD, src)
if dest.type == TYPE_WORD:
@ -551,6 +554,9 @@ class Analyzer(object):
context.assert_types_for_read_table(instr, src, dest, TYPE_BYTE)
elif src.type == TYPE_BYTE:
self.assert_type(TYPE_BYTE, src, dest)
if dest != REG_A:
context.set_touched(REG_A)
context.set_unmeaningful(REG_A)
else:
self.assert_type(TYPE_WORD, src, dest)
context.set_touched(REG_A)

View File

@ -244,6 +244,8 @@ class Compiler(object):
raise UnsupportedOpcodeError(instr)
self.emitter.emit(op_cls(operand))
elif opcode == 'add':
if dest == REG_X or dest == REG_Y:
raise UnsupportedOpcodeError(instr)
if dest == REG_A:
if isinstance(src, ConstantRef):
self.emitter.emit(ADC(Immediate(Byte(src.value))))
@ -251,6 +253,20 @@ class Compiler(object):
self.emitter.emit(ADC(self.addressing_mode_for_index(src.index)(self.get_label(src.ref.name))))
else:
self.emitter.emit(ADC(Absolute(self.get_label(src.name))))
elif isinstance(dest, LocationRef) and src.type == TYPE_BYTE and dest.type == TYPE_BYTE:
if isinstance(src, ConstantRef):
dest_label = self.get_label(dest.name)
self.emitter.emit(LDA(Absolute(dest_label)))
self.emitter.emit(ADC(Immediate(Byte(src.low_byte()))))
self.emitter.emit(STA(Absolute(dest_label)))
elif isinstance(src, LocationRef):
src_label = self.get_label(src.name)
dest_label = self.get_label(dest.name)
self.emitter.emit(LDA(Absolute(dest_label)))
self.emitter.emit(ADC(Absolute(src_label)))
self.emitter.emit(STA(Absolute(dest_label)))
else:
raise UnsupportedOpcodeError(instr)
elif isinstance(dest, LocationRef) and src.type == TYPE_WORD and dest.type == TYPE_WORD:
if isinstance(src, ConstantRef):
dest_label = self.get_label(dest.name)
@ -294,6 +310,8 @@ class Compiler(object):
else:
raise UnsupportedOpcodeError(instr)
elif opcode == 'sub':
if dest == REG_X or dest == REG_Y:
raise UnsupportedOpcodeError(instr)
if dest == REG_A:
if isinstance(src, ConstantRef):
self.emitter.emit(SBC(Immediate(Byte(src.value))))
@ -301,6 +319,20 @@ class Compiler(object):
self.emitter.emit(SBC(self.addressing_mode_for_index(src.index)(self.get_label(src.ref.name))))
else:
self.emitter.emit(SBC(Absolute(self.get_label(src.name))))
elif isinstance(dest, LocationRef) and src.type == TYPE_BYTE and dest.type == TYPE_BYTE:
if isinstance(src, ConstantRef):
dest_label = self.get_label(dest.name)
self.emitter.emit(LDA(Absolute(dest_label)))
self.emitter.emit(SBC(Immediate(Byte(src.low_byte()))))
self.emitter.emit(STA(Absolute(dest_label)))
elif isinstance(src, LocationRef):
src_label = self.get_label(src.name)
dest_label = self.get_label(dest.name)
self.emitter.emit(LDA(Absolute(dest_label)))
self.emitter.emit(SBC(Absolute(src_label)))
self.emitter.emit(STA(Absolute(dest_label)))
else:
raise UnsupportedOpcodeError(instr)
elif isinstance(dest, LocationRef) and src.type == TYPE_WORD and dest.type == TYPE_WORD:
if isinstance(src, ConstantRef):
dest_label = self.get_label(dest.name)

View File

@ -852,6 +852,59 @@ Can't `add` to a memory location that isn't writeable.
| }
? ForbiddenWriteError: a
You can `add` a byte constant to a byte memory location.
| byte lives
| define main routine
| inputs a, lives
| outputs lives
| trashes a, c, z, v, n
| {
| st off, c
| add lives, 3
| }
= ok
`add`ing a byte constant to a byte memory location trashes `a`.
| byte lives
| define main routine
| inputs a, lives
| outputs a, lives
| trashes c, z, v, n
| {
| st off, c
| add lives, 3
| }
? UnmeaningfulOutputError: a
You can `add` a byte memory location to another byte memory location.
This trashes `a`.
| byte lives
| byte extra
| define main routine
| inputs a, lives, extra
| outputs lives
| trashes a, c, z, v, n
| {
| st off, c
| add lives, extra
| }
= ok
| byte lives
| byte extra
| define main routine
| inputs a, lives, extra
| outputs a, lives
| trashes c, z, v, n
| {
| st off, c
| add lives, extra
| }
? UnmeaningfulOutputError: a
You can `add` a word constant to a word memory location.
| word score
@ -996,6 +1049,59 @@ Can't `sub` to a memory location that isn't writeable.
| }
? ForbiddenWriteError: a
You can `sub` a byte constant from a byte memory location.
| byte lives
| define main routine
| inputs a, lives
| outputs lives
| trashes a, c, z, v, n
| {
| st on, c
| sub lives, 3
| }
= ok
`sub`ing a byte constant from a byte memory location trashes `a`.
| byte lives
| define main routine
| inputs a, lives
| outputs a, lives
| trashes c, z, v, n
| {
| st on, c
| sub lives, 3
| }
? UnmeaningfulOutputError: a
You can `sub` a byte memory location from another byte memory location.
This trashes `a`.
| byte lives
| byte extra
| define main routine
| inputs a, lives, extra
| outputs lives
| trashes a, c, z, v, n
| {
| st on, c
| sub lives, extra
| }
= ok
| byte lives
| byte extra
| define main routine
| inputs a, lives, extra
| outputs a, lives
| trashes c, z, v, n
| {
| st on, c
| sub lives, extra
| }
? UnmeaningfulOutputError: a
You can `sub` a word constant from a word memory location.
| word score

View File

@ -1025,6 +1025,104 @@ Copying to and from a vector table.
= $0842 JMP ($0846)
= $0845 RTS
### add, sub
Various modes of `add`.
| byte lives
| byte extra
| word score
| word bonus
| define main routine
| inputs lives, score, extra, bonus
| outputs lives, score
| trashes a, x, y, c, z, v, n
| {
| ld a, 0
| ld x, 0
| ld y, 0
| st off, c
| add a, 7
| add a, lives
| add lives, 2
| add lives, extra
| add score, 1999
| add score, bonus
| }
= $080D LDA #$00
= $080F LDX #$00
= $0811 LDY #$00
= $0813 CLC
= $0814 ADC #$07
= $0816 ADC $084D
= $0819 LDA $084D
= $081C ADC #$02
= $081E STA $084D
= $0821 LDA $084D
= $0824 ADC $084E
= $0827 STA $084D
= $082A LDA $084F
= $082D ADC #$CF
= $082F STA $084F
= $0832 LDA $0850
= $0835 ADC #$07
= $0837 STA $0850
= $083A LDA $084F
= $083D ADC $0851
= $0840 STA $084F
= $0843 LDA $0850
= $0846 ADC $0852
= $0849 STA $0850
= $084C RTS
Various modes of `sub`.
| byte lives
| byte extra
| word score
| word bonus
| define main routine
| inputs lives, score, extra, bonus
| outputs lives, score
| trashes a, x, y, c, z, v, n
| {
| ld a, 0
| ld x, 0
| ld y, 0
| st on, c
| sub a, 7
| sub a, lives
| sub lives, 2
| sub lives, extra
| sub score, 1999
| sub score, bonus
| }
= $080D LDA #$00
= $080F LDX #$00
= $0811 LDY #$00
= $0813 SEC
= $0814 SBC #$07
= $0816 SBC $084D
= $0819 LDA $084D
= $081C SBC #$02
= $081E STA $084D
= $0821 LDA $084D
= $0824 SBC $084E
= $0827 STA $084D
= $082A LDA $084F
= $082D SBC #$CF
= $082F STA $084F
= $0832 LDA $0850
= $0835 SBC #$07
= $0837 STA $0850
= $083A LDA $084F
= $083D SBC $0851
= $0840 STA $084F
= $0843 LDA $0850
= $0846 SBC $0852
= $0849 STA $0850
= $084C RTS
### word operations
Adding a constant word to a word memory location.