1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2025-02-02 15:30:40 +00:00

Compile byte-table add, sub, cmp, and, or, xor, shl, shr, inc, dec.

This commit is contained in:
Chris Pressey 2018-04-18 16:32:12 +01:00
parent 5fcbfa1d21
commit bc91ef1602
5 changed files with 100 additions and 13 deletions

View File

@ -10,6 +10,9 @@ History of SixtyPical
assigning a routine to a vector with a "wider" type. assigning a routine to a vector with a "wider" type.
* Support for `copy [ptra]+y, [ptrb]+y` to indirect LDA indirect STA. * 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 `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 0.15
---- ----

View File

@ -69,13 +69,8 @@ Documentation
TODO TODO
---- ----
### Save registers on stack * Save registers on stack: this preserves them, so that, semantically, they can be used later even though they
are trashed inside the block.
This preserves them, so that, semantically, they can be used later even though they
are trashed inside the block.
### And at some point...
* `low` and `high` address operators - to turn `word` type into `byte`. * `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: 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.) * 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. * `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. * 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. * `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?) * Automatic tail-call optimization (could be tricky, w/constraints?)
[VICE]: http://vice-emu.sourceforge.net/ [VICE]: http://vice-emu.sourceforge.net/

View File

@ -244,6 +244,8 @@ class Compiler(object):
if dest == REG_A: if dest == REG_A:
if isinstance(src, ConstantRef): if isinstance(src, ConstantRef):
self.emitter.emit(ADC(Immediate(Byte(src.value)))) 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: else:
self.emitter.emit(ADC(Absolute(self.get_label(src.name)))) self.emitter.emit(ADC(Absolute(self.get_label(src.name))))
elif isinstance(dest, LocationRef) and src.type == TYPE_WORD and dest.type == TYPE_WORD: 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 dest == REG_A:
if isinstance(src, ConstantRef): if isinstance(src, ConstantRef):
self.emitter.emit(SBC(Immediate(Byte(src.value)))) 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: else:
self.emitter.emit(SBC(Absolute(self.get_label(src.name)))) self.emitter.emit(SBC(Absolute(self.get_label(src.name))))
elif isinstance(dest, LocationRef) and src.type == TYPE_WORD and dest.type == TYPE_WORD: elif isinstance(dest, LocationRef) and src.type == TYPE_WORD and dest.type == TYPE_WORD:
@ -316,10 +320,6 @@ class Compiler(object):
raise UnsupportedOpcodeError(instr) raise UnsupportedOpcodeError(instr)
else: else:
raise UnsupportedOpcodeError(instr) raise UnsupportedOpcodeError(instr)
elif opcode == 'inc':
self.compile_inc(instr, instr.dest)
elif opcode == 'dec':
self.compile_dec(instr, instr.dest)
elif opcode == 'cmp': elif opcode == 'cmp':
self.compile_cmp(instr, instr.src, instr.dest) self.compile_cmp(instr, instr.src, instr.dest)
elif opcode in ('and', 'or', 'xor',): elif opcode in ('and', 'or', 'xor',):
@ -331,10 +331,16 @@ class Compiler(object):
if dest == REG_A: if dest == REG_A:
if isinstance(src, ConstantRef): if isinstance(src, ConstantRef):
self.emitter.emit(cls(Immediate(Byte(src.value)))) 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: else:
self.emitter.emit(cls(self.absolute_or_zero_page(self.get_label(src.name)))) self.emitter.emit(cls(self.absolute_or_zero_page(self.get_label(src.name))))
else: else:
raise UnsupportedOpcodeError(instr) 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'): elif opcode in ('shl', 'shr'):
cls = { cls = {
'shl': ROL, 'shl': ROL,
@ -342,6 +348,8 @@ class Compiler(object):
}[opcode] }[opcode]
if dest == REG_A: if dest == REG_A:
self.emitter.emit(cls()) 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: else:
self.emitter.emit(cls(self.absolute_or_zero_page(self.get_label(dest.name)))) self.emitter.emit(cls(self.absolute_or_zero_page(self.get_label(dest.name))))
elif opcode == 'call': elif opcode == 'call':
@ -389,6 +397,9 @@ class Compiler(object):
raise UnsupportedOpcodeError(instr) raise UnsupportedOpcodeError(instr)
if isinstance(src, ConstantRef): if isinstance(src, ConstantRef):
self.emitter.emit(cls(Immediate(Byte(src.value)))) 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: else:
self.emitter.emit(cls(Absolute(self.get_label(src.name)))) self.emitter.emit(cls(Absolute(self.get_label(src.name))))
@ -398,6 +409,8 @@ class Compiler(object):
self.emitter.emit(INX()) self.emitter.emit(INX())
elif dest == REG_Y: elif dest == REG_Y:
self.emitter.emit(INY()) 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: else:
self.emitter.emit(INC(Absolute(self.get_label(dest.name)))) self.emitter.emit(INC(Absolute(self.get_label(dest.name))))
@ -407,6 +420,8 @@ class Compiler(object):
self.emitter.emit(DEX()) self.emitter.emit(DEX())
elif dest == REG_Y: elif dest == REG_Y:
self.emitter.emit(DEY()) 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: else:
self.emitter.emit(DEC(Absolute(self.get_label(dest.name)))) self.emitter.emit(DEC(Absolute(self.get_label(dest.name))))

View File

@ -211,6 +211,7 @@ class CPY(Instruction):
class DEC(Instruction): class DEC(Instruction):
opcodes = { opcodes = {
Absolute: 0xce, Absolute: 0xce,
AbsoluteX: 0xde,
} }

View File

@ -220,6 +220,8 @@ Initialized byte table, initialized with list of byte values.
Initialized word table, initialized with list of word 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 | word table[8] message : 65535, 0, 127
| |
| routine main | routine main
@ -313,6 +315,78 @@ Some instructions.
= $0855 ROR $0859 = $0855 ROR $0859
= $0858 RTS = $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`. Compiling `if`.
| routine main | routine main
@ -525,7 +599,7 @@ Indexed access.
= $0814 LDA $0819,X = $0814 LDA $0819,X
= $0817 RTS = $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] tab1
| byte table[256] tab2 | byte table[256] tab2