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
cli
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
sta c64.VICIRQ ; acknowledge raster irq
lda c64.CIA1ICR ; acknowledge CIA1 interrupt
@ -305,9 +307,63 @@ asmsub set_irqvec() -> clobbers(A) -> () {
sta c64.CINV+1
cli
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
_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
_raster_irq_handler
jsr set_irqvec._irq_handler_init
jsr irq.irq
jsr set_irqvec._irq_handler_end
lda #$ff
sta c64.VICIRQ ; acknowledge raster irq
jmp c64.IRQDFRT
@ -380,7 +438,9 @@ asmsub set_rasterirq_excl(uword rasterpos @ AY) -> clobbers(A) -> () {
rts
_raster_irq_handler
jsr set_irqvec._irq_handler_init
jsr irq.irq
jsr set_irqvec._irq_handler_end
lda #$ff
sta c64.VICIRQ ; acknowledge raster irq
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)
throw VmExecutionException("too many nested/recursive calls")
} catch (bp: VmBreakpointException) {
currentInstructionPtr++ // TODO necessary still?
println("breakpoint encountered, source line: $sourceLine")
throw bp
} catch (es: EmptyStackException) {
@ -702,50 +701,50 @@ class StackVm(private var traceOutputFile: String?) {
Opcode.SHIFTEDL_BYTE, Opcode.SHL_BYTE -> {
val v = evalstack.pop()
checkDt(v, DataType.UBYTE, DataType.BYTE)
P_carry = (v.integerValue() and 0x80)!=0
val value=v.shl()
evalstack.push(value)
setFlags(value)
// TODO carry flag
}
Opcode.SHIFTEDL_WORD, Opcode.SHL_WORD -> {
val v = evalstack.pop()
checkDt(v, DataType.UWORD, DataType.WORD)
P_carry = (v.integerValue() and 0x8000)!=0
val value=v.shl()
evalstack.push(value)
setFlags(value)
// TODO carry flag
}
Opcode.SHIFTEDR_UBYTE, Opcode.SHR_UBYTE -> {
val v = evalstack.pop()
checkDt(v, DataType.UBYTE)
P_carry = (v.integerValue() and 0x01)!=0
val value=v.shr()
evalstack.push(value)
setFlags(value)
// TODO carry flag
}
Opcode.SHIFTEDR_SBYTE, Opcode.SHR_SBYTE -> {
val v = evalstack.pop()
checkDt(v, DataType.BYTE)
P_carry = (v.integerValue() and 0x01)!=0
val value=v.shr()
evalstack.push(value)
setFlags(value)
// TODO carry flag
}
Opcode.SHIFTEDR_UWORD, Opcode.SHR_UWORD -> {
val v = evalstack.pop()
checkDt(v, DataType.UWORD)
P_carry = (v.integerValue() and 0x01)!=0
val value=v.shr()
evalstack.push(value)
setFlags(value)
// TODO carry flag
}
Opcode.SHIFTEDR_SWORD, Opcode.SHR_SWORD -> {
val v = evalstack.pop()
checkDt(v, DataType.WORD)
P_carry = (v.integerValue() and 0x01)!=0
val value=v.shr()
evalstack.push(value)
setFlags(value)
// TODO carry flag
}
Opcode.ROL_BYTE -> {
val v = evalstack.pop()

View File

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

View File

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