diff --git a/HISTORY.markdown b/HISTORY.markdown index 4675caa..1b7104d 100644 --- a/HISTORY.markdown +++ b/HISTORY.markdown @@ -5,6 +5,8 @@ History of SixtyPical --- * Add word (constant or memory location) to word memory location. +* Add word to pointer (unchecked for now). +* Implementation: `--debug` shows some extra info during analysis. 0.8 --- diff --git a/README.markdown b/README.markdown index 6092815..4081ba8 100644 --- a/README.markdown +++ b/README.markdown @@ -42,8 +42,6 @@ TODO ### Operations on 16 bit values -Add word (constant or memory location) to pointer. (Not necessarily range-checked yet though.) - Compare word (constant or memory location) with memory location or pointer. (Maybe?) And then write a little demo "game" where you can move a block around the screen with diff --git a/src/sixtypical/analyzer.py b/src/sixtypical/analyzer.py index cd04653..93d1e02 100644 --- a/src/sixtypical/analyzer.py +++ b/src/sixtypical/analyzer.py @@ -255,16 +255,22 @@ class Analyzer(object): context.assert_meaningful(src) context.set_written(dest) elif opcode == 'add': + context.assert_meaningful(src, dest, FLAG_C) if src.type == TYPE_BYTE: self.assert_type(TYPE_BYTE, src, dest) - context.assert_meaningful(src, dest, FLAG_C) context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V) else: - self.assert_type(TYPE_WORD, src, dest) - context.assert_meaningful(src, dest, FLAG_C) - context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V) - context.set_touched(REG_A) - context.set_unmeaningful(REG_A) + self.assert_type(TYPE_WORD, src) + if dest.type == TYPE_WORD: + context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V) + context.set_touched(REG_A) + context.set_unmeaningful(REG_A) + elif isinstance(dest.type, PointerType): + context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V) + context.set_touched(REG_A) + context.set_unmeaningful(REG_A) + else: + self.assert_type(TYPE_WORD, dest) elif opcode == 'sub': self.assert_type(TYPE_BYTE, src, dest) context.assert_meaningful(src, dest, FLAG_C) diff --git a/src/sixtypical/compiler.py b/src/sixtypical/compiler.py index 0f98d5a..ecb1f5b 100644 --- a/src/sixtypical/compiler.py +++ b/src/sixtypical/compiler.py @@ -147,7 +147,7 @@ class Compiler(object): self.emitter.emit(ADC(Immediate(Byte(src.value)))) else: self.emitter.emit(ADC(Absolute(self.labels[src.name]))) - elif isinstance(dest, LocationRef) and dest.type == TYPE_WORD and src.type == TYPE_WORD: + elif isinstance(dest, LocationRef) and src.type == TYPE_WORD and dest.type == TYPE_WORD: if isinstance(src, ConstantRef): dest_label = self.labels[dest.name] self.emitter.emit(LDA(Absolute(dest_label))) @@ -167,6 +167,26 @@ class Compiler(object): self.emitter.emit(STA(Absolute(Offset(dest_label, 1)))) else: raise UnsupportedOpcodeError(instr) + elif isinstance(dest, LocationRef) and src.type == TYPE_WORD and isinstance(dest.type, PointerType): + if isinstance(src, ConstantRef): + dest_label = self.labels[dest.name] # this. is. zero-page. + self.emitter.emit(LDA(ZeroPage(dest_label))) + self.emitter.emit(ADC(Immediate(Byte(src.low_byte())))) + self.emitter.emit(STA(ZeroPage(dest_label))) + self.emitter.emit(LDA(ZeroPage(Offset(dest_label, 1)))) + self.emitter.emit(ADC(Immediate(Byte(src.high_byte())))) + self.emitter.emit(STA(ZeroPage(Offset(dest_label, 1)))) + elif isinstance(src, LocationRef): + src_label = self.labels[src.name] + dest_label = self.labels[dest.name] # this. is. zero-page. + self.emitter.emit(LDA(ZeroPage(dest_label))) + self.emitter.emit(ADC(Absolute(src_label))) + self.emitter.emit(STA(ZeroPage(dest_label))) + self.emitter.emit(LDA(ZeroPage(Offset(dest_label, 1)))) + self.emitter.emit(ADC(Absolute(Offset(src_label, 1)))) + self.emitter.emit(STA(ZeroPage(Offset(dest_label, 1)))) + else: + raise UnsupportedOpcodeError(instr) else: raise UnsupportedOpcodeError(instr) elif opcode == 'sub': diff --git a/tests/SixtyPical Analysis.md b/tests/SixtyPical Analysis.md index e6813b5..d100da5 100644 --- a/tests/SixtyPical Analysis.md +++ b/tests/SixtyPical Analysis.md @@ -440,6 +440,36 @@ You can `add` a word memory location to another word memory location. | } ? ForbiddenWriteError: a in main +You can `add` a word memory location, or a constant, to a pointer. + + | pointer ptr + | word delta + | routine main + | inputs ptr, delta + | outputs ptr + | trashes a, c, z, v, n + | { + | st off, c + | add ptr, delta + | add ptr, word 1 + | } + = ok + +`add`ing a word memory location, or a constant, to a pointer, trashes `a`. + + | pointer ptr + | word delta + | routine main + | inputs ptr, delta + | outputs ptr + | trashes c, z, v, n + | { + | st off, c + | add ptr, delta + | add ptr, word 1 + | } + ? ForbiddenWriteError: a in main + ### sub ### Can't `sub` from or to a memory location that isn't initialized. diff --git a/tests/SixtyPical Compilation.md b/tests/SixtyPical Compilation.md index 87d7378..936fd4f 100644 --- a/tests/SixtyPical Compilation.md +++ b/tests/SixtyPical Compilation.md @@ -437,3 +437,25 @@ Read through a pointer. | copy [ptr] + y, foo | } = 00c0a000a91085fea9c085ffb1fe8d12c060 + +Add a word memory location, and a literal word, to a pointer, and then read through it. +Note that this is *not* range-checked. (Yet.) + + | buffer[2048] buf + | pointer ptr @ 254 + | byte foo + | word delta + | + | routine main + | inputs buf + | outputs y, foo, delta + | trashes a, z, n, ptr + | { + | copy 619, delta + | ld y, 0 + | copy ^buf, ptr + | add ptr, delta + | add ptr, word 1 + | copy [ptr] + y, foo + | } + = 00c0a9028d38c0a96b8d39c0a000a93485fea9c085ffa5fe6d38c085fea5ff6d39c085ffa5fe690185fea5ff690085ffb1fe8d36c060