From f3fc2fe523ebda264718e2575c0de77a457e235b Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 19 Mar 2019 01:22:26 +0100 Subject: [PATCH] irq handler saves zeropage scratch registers, fixes #8 --- compiler/res/prog8lib/c64utils.p8 | 66 +++++++++++++++++++++++++-- compiler/src/prog8/stackvm/StackVm.kt | 13 +++--- examples/rasterbars.p8 | 12 ++--- examples/test.p8 | 54 ++++++++-------------- 4 files changed, 93 insertions(+), 52 deletions(-) diff --git a/compiler/res/prog8lib/c64utils.p8 b/compiler/res/prog8lib/c64utils.p8 index e86f77569..8e00b71b2 100644 --- a/compiler/res/prog8lib/c64utils.p8 +++ b/compiler/res/prog8lib/c64utils.p8 @@ -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,10 +307,64 @@ 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 diff --git a/compiler/src/prog8/stackvm/StackVm.kt b/compiler/src/prog8/stackvm/StackVm.kt index 1997616cd..cd688d26c 100644 --- a/compiler/src/prog8/stackvm/StackVm.kt +++ b/compiler/src/prog8/stackvm/StackVm.kt @@ -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() diff --git a/examples/rasterbars.p8 b/examples/rasterbars.p8 index dac94f363..32e8f27a2 100644 --- a/examples/rasterbars.p8 +++ b/examples/rasterbars.p8 @@ -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 } } } diff --git a/examples/test.p8 b/examples/test.p8 index 9a2c8329d..54c79fb79 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -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 } }