irq handler saves zeropage scratch registers, fixes #8

This commit is contained in:
Irmen de Jong 2019-03-19 01:22:26 +01:00
parent 1e045b6a62
commit f3fc2fe523
4 changed files with 93 additions and 52 deletions

View File

@ -288,7 +288,9 @@ asmsub set_irqvec_excl() -> clobbers(A) -> () {
sta c64.CINV+1 sta c64.CINV+1
cli cli
rts rts
_irq_handler jsr irq.irq _irq_handler jsr set_irqvec._irq_handler_init
jsr irq.irq
jsr set_irqvec._irq_handler_end
lda #$ff lda #$ff
sta c64.VICIRQ ; acknowledge raster irq sta c64.VICIRQ ; acknowledge raster irq
lda c64.CIA1ICR ; acknowledge CIA1 interrupt lda c64.CIA1ICR ; acknowledge CIA1 interrupt
@ -305,9 +307,63 @@ asmsub set_irqvec() -> clobbers(A) -> () {
sta c64.CINV+1 sta c64.CINV+1
cli cli
rts rts
_irq_handler jsr irq.irq _irq_handler jsr _irq_handler_init
jsr irq.irq
jsr _irq_handler_end
jmp c64.IRQDFRT ; continue with normal kernel irq routine jmp c64.IRQDFRT ; continue with normal kernel irq routine
_irq_handler_init
; save all zp scratch registers and the X register as these might be clobbered by the irq routine
stx IRQ_X_REG
lda c64.SCRATCH_ZPB1
sta IRQ_SCRATCH_ZPB1
lda c64.SCRATCH_ZPREG
sta IRQ_SCRATCH_ZPREG
lda c64.SCRATCH_ZPREGX
sta IRQ_SCRATCH_ZPREGX
lda c64.SCRATCH_ZPWORD1
sta IRQ_SCRATCH_ZPWORD1
lda c64.SCRATCH_ZPWORD1+1
sta IRQ_SCRATCH_ZPWORD1+1
lda c64.SCRATCH_ZPWORD2
sta IRQ_SCRATCH_ZPWORD2
lda c64.SCRATCH_ZPWORD2+1
sta IRQ_SCRATCH_ZPWORD2+1
; stack protector; make sure we don't clobber the top of the evaluation stack
dex
dex
dex
dex
dex
dex
rts
_irq_handler_end
; restore all zp scratch registers and the X register
lda IRQ_SCRATCH_ZPB1
sta c64.SCRATCH_ZPB1
lda IRQ_SCRATCH_ZPREG
sta c64.SCRATCH_ZPREG
lda IRQ_SCRATCH_ZPREGX
sta c64.SCRATCH_ZPREGX
lda IRQ_SCRATCH_ZPWORD1
sta c64.SCRATCH_ZPWORD1
lda IRQ_SCRATCH_ZPWORD1+1
sta c64.SCRATCH_ZPWORD1+1
lda IRQ_SCRATCH_ZPWORD2
sta c64.SCRATCH_ZPWORD2
lda IRQ_SCRATCH_ZPWORD2+1
sta c64.SCRATCH_ZPWORD2+1
ldx IRQ_X_REG
rts
IRQ_X_REG .byte 0
IRQ_SCRATCH_ZPB1 .byte 0
IRQ_SCRATCH_ZPREG .byte 0
IRQ_SCRATCH_ZPREGX .byte 0
IRQ_SCRATCH_ZPWORD1 .word 0
IRQ_SCRATCH_ZPWORD2 .word 0
}} }}
} }
@ -341,7 +397,9 @@ asmsub set_rasterirq(uword rasterpos @ AY) -> clobbers(A) -> () {
rts rts
_raster_irq_handler _raster_irq_handler
jsr set_irqvec._irq_handler_init
jsr irq.irq jsr irq.irq
jsr set_irqvec._irq_handler_end
lda #$ff lda #$ff
sta c64.VICIRQ ; acknowledge raster irq sta c64.VICIRQ ; acknowledge raster irq
jmp c64.IRQDFRT jmp c64.IRQDFRT
@ -380,7 +438,9 @@ asmsub set_rasterirq_excl(uword rasterpos @ AY) -> clobbers(A) -> () {
rts rts
_raster_irq_handler _raster_irq_handler
jsr set_irqvec._irq_handler_init
jsr irq.irq jsr irq.irq
jsr set_irqvec._irq_handler_end
lda #$ff lda #$ff
sta c64.VICIRQ ; acknowledge raster irq sta c64.VICIRQ ; acknowledge raster irq
jmp c64.IRQDFEND ; end irq processing - don't call kernel jmp c64.IRQDFEND ; end irq processing - don't call kernel

View File

@ -227,7 +227,6 @@ class StackVm(private var traceOutputFile: String?) {
if (callstack.size > 128) if (callstack.size > 128)
throw VmExecutionException("too many nested/recursive calls") throw VmExecutionException("too many nested/recursive calls")
} catch (bp: VmBreakpointException) { } catch (bp: VmBreakpointException) {
currentInstructionPtr++ // TODO necessary still?
println("breakpoint encountered, source line: $sourceLine") println("breakpoint encountered, source line: $sourceLine")
throw bp throw bp
} catch (es: EmptyStackException) { } catch (es: EmptyStackException) {
@ -702,50 +701,50 @@ class StackVm(private var traceOutputFile: String?) {
Opcode.SHIFTEDL_BYTE, Opcode.SHL_BYTE -> { Opcode.SHIFTEDL_BYTE, Opcode.SHL_BYTE -> {
val v = evalstack.pop() val v = evalstack.pop()
checkDt(v, DataType.UBYTE, DataType.BYTE) checkDt(v, DataType.UBYTE, DataType.BYTE)
P_carry = (v.integerValue() and 0x80)!=0
val value=v.shl() val value=v.shl()
evalstack.push(value) evalstack.push(value)
setFlags(value) setFlags(value)
// TODO carry flag
} }
Opcode.SHIFTEDL_WORD, Opcode.SHL_WORD -> { Opcode.SHIFTEDL_WORD, Opcode.SHL_WORD -> {
val v = evalstack.pop() val v = evalstack.pop()
checkDt(v, DataType.UWORD, DataType.WORD) checkDt(v, DataType.UWORD, DataType.WORD)
P_carry = (v.integerValue() and 0x8000)!=0
val value=v.shl() val value=v.shl()
evalstack.push(value) evalstack.push(value)
setFlags(value) setFlags(value)
// TODO carry flag
} }
Opcode.SHIFTEDR_UBYTE, Opcode.SHR_UBYTE -> { Opcode.SHIFTEDR_UBYTE, Opcode.SHR_UBYTE -> {
val v = evalstack.pop() val v = evalstack.pop()
checkDt(v, DataType.UBYTE) checkDt(v, DataType.UBYTE)
P_carry = (v.integerValue() and 0x01)!=0
val value=v.shr() val value=v.shr()
evalstack.push(value) evalstack.push(value)
setFlags(value) setFlags(value)
// TODO carry flag
} }
Opcode.SHIFTEDR_SBYTE, Opcode.SHR_SBYTE -> { Opcode.SHIFTEDR_SBYTE, Opcode.SHR_SBYTE -> {
val v = evalstack.pop() val v = evalstack.pop()
checkDt(v, DataType.BYTE) checkDt(v, DataType.BYTE)
P_carry = (v.integerValue() and 0x01)!=0
val value=v.shr() val value=v.shr()
evalstack.push(value) evalstack.push(value)
setFlags(value) setFlags(value)
// TODO carry flag
} }
Opcode.SHIFTEDR_UWORD, Opcode.SHR_UWORD -> { Opcode.SHIFTEDR_UWORD, Opcode.SHR_UWORD -> {
val v = evalstack.pop() val v = evalstack.pop()
checkDt(v, DataType.UWORD) checkDt(v, DataType.UWORD)
P_carry = (v.integerValue() and 0x01)!=0
val value=v.shr() val value=v.shr()
evalstack.push(value) evalstack.push(value)
setFlags(value) setFlags(value)
// TODO carry flag
} }
Opcode.SHIFTEDR_SWORD, Opcode.SHR_SWORD -> { Opcode.SHIFTEDR_SWORD, Opcode.SHR_SWORD -> {
val v = evalstack.pop() val v = evalstack.pop()
checkDt(v, DataType.WORD) checkDt(v, DataType.WORD)
P_carry = (v.integerValue() and 0x01)!=0
val value=v.shr() val value=v.shr()
evalstack.push(value) evalstack.push(value)
setFlags(value) setFlags(value)
// TODO carry flag
} }
Opcode.ROL_BYTE -> { Opcode.ROL_BYTE -> {
val v = evalstack.pop() val v = evalstack.pop()

View File

@ -23,23 +23,19 @@
ubyte ypos = 0 ubyte ypos = 0
sub irq() { sub irq() {
Y++ ; delay for alignment Y++ ; slight timing delay to avoid rasterline transition issues
Y++ ; delay for alignment
Y++ ; delay for alignment
Y++ ; delay for alignment
ubyte rasterpos = c64.RASTER ubyte rasterpos = c64.RASTER
if color!=len(colors) { if color!=len(colors) {
c64.EXTCOL = colors[color] c64.EXTCOL = colors[color]
c64.RASTER = rasterpos+barheight
color++ color++
c64.RASTER = rasterpos+barheight
} }
else { else {
Y++ ; delay for alignment
Y++ ; delay for alignment
ypos += 2 ypos += 2
c64.EXTCOL = 0 c64.EXTCOL = 0
c64.RASTER = sin8u(ypos)/2+40
color = 0 color = 0
c64.RASTER = sin8u(ypos)/2+40
} }
} }
} }

View File

@ -1,47 +1,33 @@
%import c64utils %import c64utils
%import c64lib
%zeropage basicsafe %zeropage basicsafe
~ main {
; @todo see problem in looplabelproblem.p8 ; @todo see problem in looplabelproblem.p8
~ main {
sub start() { sub start() {
ubyte ub1 c64utils.set_rasterirq(220) ; enable animation
ubyte ub2
ubyte ub3
ubyte ub4
ubyte ub5
ub1, ub2 = test2() uword offs=0
c64scr.print_ub(ub1) while(true) {
c64.CHROUT('\n') uword z=1
c64scr.print_ub(ub2) for ubyte x in 0 to 200 {
c64.CHROUT('\n') @(z*($0400+offs)) = lsb(offs+x)
c64.CHROUT('\n') offs += 1
ub1, ub2 = test3() if offs > 40*25
c64scr.print_ub(ub1) offs=0
c64.CHROUT('\n') }
c64scr.print_ub(ub2) }
c64.CHROUT('\n') }
c64.CHROUT('\n')
} }
asmsub test2() -> clobbers() -> (ubyte @Pc, ubyte @A) {
%asm {{
lda #100
ldy #100
sec
rts
}}
}
asmsub test3() -> clobbers() -> (ubyte @Pc, ubyte @A) { ~ irq {
%asm {{
lda #101 sub irq() {
ldy #101 c64.EXTCOL = X
clc
rts
}}
} }
} }