65C02 cpu: use TRB and TSB instructions for in-place AND/OR.

This commit is contained in:
Irmen de Jong 2023-11-24 00:50:36 +01:00
parent 11b7c4459e
commit 82a15b5a16
3 changed files with 40 additions and 86 deletions

View File

@ -1192,8 +1192,8 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
} }
} }
} }
"&" -> asmgen.out(" lda $name | and #$value | sta $name") "&" -> immediateAndInplace(name, value)
"|" -> asmgen.out(" lda $name | ora #$value | sta $name") "|" -> immediateOrInplace(name, value)
"^" -> asmgen.out(" lda $name | eor #$value | sta $name") "^" -> asmgen.out(" lda $name | eor #$value | sta $name")
"==" -> { "==" -> {
asmgen.out(""" asmgen.out("""
@ -1314,6 +1314,22 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
} }
} }
private fun immediateAndInplace(name: String, value: Int) {
if(asmgen.isTargetCpu(CpuType.CPU65c02)) {
asmgen.out(" lda #${value xor 255} | trb $name") // reset bit
} else {
asmgen.out(" lda $name | and #$value | sta $name")
}
}
private fun immediateOrInplace(name: String, value: Int) {
if(asmgen.isTargetCpu(CpuType.CPU65c02) && ((value and (value-1))==0)) {
asmgen.out(" lda #$value | tsb $name") // set bit
} else {
asmgen.out(" lda $name | ora #$value | sta $name")
}
}
private fun inplacemodificationWordWithMemread(name: String, dt: DataType, operator: String, memread: PtMemoryByte) { private fun inplacemodificationWordWithMemread(name: String, dt: DataType, operator: String, memread: PtMemoryByte) {
when (operator) { when (operator) {
"+" -> { "+" -> {
@ -1611,7 +1627,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
asmgen.out(" lda $name+1 | and #>$value | sta $name+1") asmgen.out(" lda $name+1 | and #>$value | sta $name+1")
} }
value < 0x0100 -> { value < 0x0100 -> {
asmgen.out(" lda $name | and #$value | sta $name") immediateAndInplace(name, value)
if(asmgen.isTargetCpu(CpuType.CPU65c02)) if(asmgen.isTargetCpu(CpuType.CPU65c02))
asmgen.out(" stz $name+1") asmgen.out(" stz $name+1")
else else
@ -1624,7 +1640,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
when { when {
value == 0 -> {} value == 0 -> {}
value and 255 == 0 -> asmgen.out(" lda $name+1 | ora #>$value | sta $name+1") value and 255 == 0 -> asmgen.out(" lda $name+1 | ora #>$value | sta $name+1")
value < 0x0100 -> asmgen.out(" lda $name | ora #$value | sta $name") value < 0x0100 -> immediateOrInplace(name, value)
else -> asmgen.out(" lda $name | ora #<$value | sta $name | lda $name+1 | ora #>$value | sta $name+1") else -> asmgen.out(" lda $name | ora #<$value | sta $name | lda $name+1 | ora #>$value | sta $name+1")
} }
} }

View File

@ -2,8 +2,9 @@
TODO TODO
==== ====
- use TRB/TSB instructions more on the x16 such as when ack vera irq bits cx16.VERA_ISR |= 4 - new cx16 master irq handler:
xx |= %0001000, xx &= %1110111 - describe the order in which irq sources are handled, should they occur at the same time
- change the order? line, vsync, sprcol, aflow?
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 .... - [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....

View File

@ -1,88 +1,25 @@
%import palette
%import textio %import textio
%import syslib %import syslib
%zeropage basicsafe %zeropage basicsafe
; Example that shows a way to handle multiple IRQ sources on the X16.
; This uses the "OLD" way using the interrupt handler routines in sys.
; (see multi-irq-new example to do it the "new" way)
; Currently only Vera interrupts are supported. VIA irqs are an exercise for the reader.
main { main {
sub start() { sub start() {
sys.set_rasterline(150) ubyte xx = 1
sys.set_irq(&irq.master_handler) ; ..will just enable vsync.. uword ww=1
cx16.VERA_IEN |= 2 ; .. so also enable line irq here.
txt.print("\n\n\nx16 irq handlers installed (old style)\n")
txt.print("red = vsync irq\n") xx |= %0001000
txt.print("green = first line irq\n") txt.print_ubbin(xx, true)
txt.print("blue = second line irq\n") txt.nl()
} xx &= %11110111
} txt.print_ubbin(xx, true)
txt.nl()
irq {
sub master_handler() -> bool {
ubyte irqsrc = cx16.VERA_ISR & cx16.VERA_IEN ; only consider sources that are enabled ww |= %0001000
ror(irqsrc) txt.print_uwbin(ww, true)
if_cs { txt.nl()
vsync_irq() ww &= %11110111
return true ; run system IRQ handler. It will ack the vsync IRQ as well. txt.print_uwbin(ww, true)
} txt.nl()
ror(irqsrc)
if_cs {
line_irq()
cx16.VERA_ISR |= 2 ; ack the irq
return false
}
ror(irqsrc)
if_cs {
sprcol_irq()
cx16.VERA_ISR |= 4 ; ack the irq
return false
}
ror(irqsrc)
if_cs {
aflow_irq()
; note: AFLOW can only be cleared by filling the audio FIFO for at least 1/4. Not via the ISR bit.
return false
}
; weird irq
return false
}
sub vsync_irq() {
cx16.save_vera_context()
palette.set_color(0, $f00)
repeat 1000 {
cx16.r0++
}
palette.set_color(0, $000)
cx16.restore_vera_context()
}
sub line_irq() {
cx16.save_vera_context()
if cx16.VERA_SCANLINE_L==150 {
palette.set_color(0, $0f0)
sys.set_rasterline(200) ; prepare next line irq
} else {
palette.set_color(0, $00f)
sys.set_rasterline(150) ; back to first line irq
}
repeat 500 {
cx16.r0++
}
palette.set_color(0, $000)
cx16.restore_vera_context()
}
sub sprcol_irq() {
; nothing here yet
}
sub aflow_irq() {
; nothing here yet
} }
} }