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:
parent
5fcbfa1d21
commit
bc91ef1602
@ -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
|
||||||
----
|
----
|
||||||
|
10
README.md
10
README.md
@ -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/
|
||||||
|
@ -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))))
|
||||||
|
|
||||||
|
@ -211,6 +211,7 @@ class CPY(Instruction):
|
|||||||
class DEC(Instruction):
|
class DEC(Instruction):
|
||||||
opcodes = {
|
opcodes = {
|
||||||
Absolute: 0xce,
|
Absolute: 0xce,
|
||||||
|
AbsoluteX: 0xde,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user