diff --git a/HISTORY.md b/HISTORY.md index 5b84be7..d93fc49 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -10,6 +10,9 @@ History of SixtyPical assigning a routine to a vector with a "wider" type. * Support for `copy [ptra]+y, [ptrb]+y` to indirect LDA indirect STA. * Support for `shl foo` and `shr foo` where `foo` is a byte storage. +* Support for `I a, btable + x` where `I` is `add`, `sub`, `cmp`, + `and`, `or`, or `xor` +* Support for `I btable + x` where `I` is `shl`, `shr`, `inc`, `dec` 0.15 ---- diff --git a/README.md b/README.md index 4cfaf60..8384f80 100644 --- a/README.md +++ b/README.md @@ -69,13 +69,8 @@ Documentation TODO ---- -### Save registers on stack - -This preserves them, so that, semantically, they can be used later even though they -are trashed inside the block. - -### And at some point... - +* Save registers on stack: this preserves them, so that, semantically, they can be used later even though they + are trashed inside the block. * `low` and `high` address operators - to turn `word` type into `byte`. * Related: can we simply view a (small) part of a buffer as a byte table? If not, why not? * Related: add constant to buffer to get new buffer. (Or to table, but... well, maybe.) @@ -84,7 +79,6 @@ are trashed inside the block. * `static` pointers -- currently not possible because pointers must be zero-page, thus `@`, thus uninitialized. * Question the value of the "consistent initialization" principle for `if` statement analysis. * `interrupt` routines -- to indicate that "the supervisor" has stored values on the stack, so we can trash them. -* Add absolute-indexed for add, sub, and, or, xor, shl, shr * Automatic tail-call optimization (could be tricky, w/constraints?) [VICE]: http://vice-emu.sourceforge.net/ diff --git a/src/sixtypical/compiler.py b/src/sixtypical/compiler.py index c21f6ce..a7d0f64 100644 --- a/src/sixtypical/compiler.py +++ b/src/sixtypical/compiler.py @@ -244,6 +244,8 @@ class Compiler(object): if dest == REG_A: if isinstance(src, ConstantRef): self.emitter.emit(ADC(Immediate(Byte(src.value)))) + elif isinstance(src, IndexedRef): + 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_WORD and dest.type == TYPE_WORD: @@ -292,6 +294,8 @@ class Compiler(object): if dest == REG_A: if isinstance(src, ConstantRef): self.emitter.emit(SBC(Immediate(Byte(src.value)))) + elif isinstance(src, IndexedRef): + 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_WORD and dest.type == TYPE_WORD: @@ -316,10 +320,6 @@ class Compiler(object): raise UnsupportedOpcodeError(instr) else: raise UnsupportedOpcodeError(instr) - elif opcode == 'inc': - self.compile_inc(instr, instr.dest) - elif opcode == 'dec': - self.compile_dec(instr, instr.dest) elif opcode == 'cmp': self.compile_cmp(instr, instr.src, instr.dest) elif opcode in ('and', 'or', 'xor',): @@ -331,10 +331,16 @@ class Compiler(object): if dest == REG_A: if isinstance(src, ConstantRef): self.emitter.emit(cls(Immediate(Byte(src.value)))) + elif isinstance(src, IndexedRef): + self.emitter.emit(cls(self.addressing_mode_for_index(src.index)(self.get_label(src.ref.name)))) else: self.emitter.emit(cls(self.absolute_or_zero_page(self.get_label(src.name)))) else: raise UnsupportedOpcodeError(instr) + elif opcode == 'inc': + self.compile_inc(instr, instr.dest) + elif opcode == 'dec': + self.compile_dec(instr, instr.dest) elif opcode in ('shl', 'shr'): cls = { 'shl': ROL, @@ -342,6 +348,8 @@ class Compiler(object): }[opcode] if dest == REG_A: self.emitter.emit(cls()) + elif isinstance(dest, IndexedRef): + self.emitter.emit(cls(self.addressing_mode_for_index(dest.index)(self.get_label(dest.ref.name)))) else: self.emitter.emit(cls(self.absolute_or_zero_page(self.get_label(dest.name)))) elif opcode == 'call': @@ -389,6 +397,9 @@ class Compiler(object): raise UnsupportedOpcodeError(instr) if isinstance(src, ConstantRef): self.emitter.emit(cls(Immediate(Byte(src.value)))) + elif isinstance(src, IndexedRef): + # FIXME might not work for some dest's (that is, cls's) + self.emitter.emit(cls(self.addressing_mode_for_index(src.index)(self.get_label(src.ref.name)))) else: self.emitter.emit(cls(Absolute(self.get_label(src.name)))) @@ -398,6 +409,8 @@ class Compiler(object): self.emitter.emit(INX()) elif dest == REG_Y: self.emitter.emit(INY()) + elif isinstance(dest, IndexedRef): + self.emitter.emit(INC(self.addressing_mode_for_index(dest.index)(self.get_label(dest.ref.name)))) else: self.emitter.emit(INC(Absolute(self.get_label(dest.name)))) @@ -407,6 +420,8 @@ class Compiler(object): self.emitter.emit(DEX()) elif dest == REG_Y: self.emitter.emit(DEY()) + elif isinstance(dest, IndexedRef): + self.emitter.emit(DEC(self.addressing_mode_for_index(dest.index)(self.get_label(dest.ref.name)))) else: self.emitter.emit(DEC(Absolute(self.get_label(dest.name)))) diff --git a/src/sixtypical/gen6502.py b/src/sixtypical/gen6502.py index a2a0962..c3c91d9 100644 --- a/src/sixtypical/gen6502.py +++ b/src/sixtypical/gen6502.py @@ -211,6 +211,7 @@ class CPY(Instruction): class DEC(Instruction): opcodes = { Absolute: 0xce, + AbsoluteX: 0xde, } diff --git a/tests/SixtyPical Compilation.md b/tests/SixtyPical Compilation.md index f441148..1a65e4d 100644 --- a/tests/SixtyPical Compilation.md +++ b/tests/SixtyPical Compilation.md @@ -220,6 +220,8 @@ Initialized byte table, initialized with list of byte values. Initialized word table, initialized with list of word values. +FIXME wait, is this not a word table[4]? + | word table[8] message : 65535, 0, 127 | | routine main @@ -313,6 +315,78 @@ Some instructions. = $0855 ROR $0859 = $0858 RTS +Some instructions on tables. (1/3) + + | byte table[256] many + | + | routine main + | inputs many + | outputs many + | trashes a, x, c, n, z, v + | { + | ld x, 0 + | ld a, 0 + | st off, c + | add a, many + x + | sub a, many + x + | cmp a, many + x + | } + = $080D LDX #$00 + = $080F LDA #$00 + = $0811 CLC + = $0812 ADC $081C,X + = $0815 SBC $081C,X + = $0818 CMP $081C,X + = $081B RTS + +Some instructions on tables. (2/3) + + | byte table[256] many + | + | routine main + | inputs many + | outputs many + | trashes a, x, c, n, z + | { + | ld x, 0 + | ld a, 0 + | and a, many + x + | or a, many + x + | xor a, many + x + | } + = $080D LDX #$00 + = $080F LDA #$00 + = $0811 AND $081B,X + = $0814 ORA $081B,X + = $0817 EOR $081B,X + = $081A RTS + +Some instructions on tables. (3/3) + + | byte table[256] many + | + | routine main + | inputs many + | outputs many + | trashes a, x, c, n, z + | { + | ld x, 0 + | ld a, 0 + | st off, c + | shl many + x + | shr many + x + | inc many + x + | dec many + x + | } + = $080D LDX #$00 + = $080F LDA #$00 + = $0811 CLC + = $0812 ROL $081F,X + = $0815 ROR $081F,X + = $0818 INC $081F,X + = $081B DEC $081F,X + = $081E RTS + Compiling `if`. | routine main @@ -525,7 +599,7 @@ Indexed access. = $0814 LDA $0819,X = $0817 RTS -Byte tables take up 256 bytes in memory. +Byte tables take up, at most, 256 bytes in memory. | byte table[256] tab1 | byte table[256] tab2