From 615a0d7dc1d57d4f9414c82396cb3b0ec817d3e1 Mon Sep 17 00:00:00 2001 From: Karol Stasiak Date: Wed, 9 Sep 2020 01:46:34 +0200 Subject: [PATCH] Interrupt functions in assembly should not have prologue (fixes #62) --- .../millfork/compiler/mos/MosCompiler.scala | 2 +- .../millfork/compiler/z80/Z80Compiler.scala | 2 +- src/main/scala/millfork/env/Environment.scala | 1 + src/main/scala/millfork/env/Thing.scala | 1 + .../scala/millfork/test/AssemblySuite.scala | 45 +++++++++++++++++++ 5 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/main/scala/millfork/compiler/mos/MosCompiler.scala b/src/main/scala/millfork/compiler/mos/MosCompiler.scala index 0ae186b5..1f1fe551 100644 --- a/src/main/scala/millfork/compiler/mos/MosCompiler.scala +++ b/src/main/scala/millfork/compiler/mos/MosCompiler.scala @@ -37,7 +37,7 @@ object MosCompiler extends AbstractCompiler[AssemblyLine] { List(AssemblyLine.absolute(LDA, ctx.env.get[ThingInMemory]("__sp")), AssemblyLine.implied(PHA)) } else Nil) - val prefix = storeParamsFromRegisters ++ (if (ctx.function.interrupt) { + val prefix = storeParamsFromRegisters ++ (if (ctx.function.interrupt && !ctx.function.inAssembly) { if (ctx.options.flag(CompilationFlag.EmitNative65816Opcodes)) { if (zpRegisterSize > 0) { diff --git a/src/main/scala/millfork/compiler/z80/Z80Compiler.scala b/src/main/scala/millfork/compiler/z80/Z80Compiler.scala index 0c56a62f..5b3a89fc 100644 --- a/src/main/scala/millfork/compiler/z80/Z80Compiler.scala +++ b/src/main/scala/millfork/compiler/z80/Z80Compiler.scala @@ -68,7 +68,7 @@ object Z80Compiler extends AbstractCompiler[ZLine] { def preserveRegisters(ctx: CompilationContext): List[ZLine] = { import millfork.assembly.z80.ZOpcode._ import ZRegister._ - if (ctx.function.interrupt) { + if (ctx.function.interrupt && !ctx.function.inAssembly) { if (ctx.options.flag(CompilationFlag.EmitZ80Opcodes)) { if (ctx.options.flag(CompilationFlag.UseShadowRegistersForInterrupts)) { List( diff --git a/src/main/scala/millfork/env/Environment.scala b/src/main/scala/millfork/env/Environment.scala index 418f2df8..e7fb1ed8 100644 --- a/src/main/scala/millfork/env/Environment.scala +++ b/src/main/scala/millfork/env/Environment.scala @@ -1378,6 +1378,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa hasElidedReturnVariable = hasElidedReturnVariable, interrupt = stmt.interrupt, kernalInterrupt = stmt.kernalInterrupt, + inAssembly = stmt.assembly, reentrant = stmt.reentrant, isConstPure = stmt.constPure, position = stmt.position, diff --git a/src/main/scala/millfork/env/Thing.scala b/src/main/scala/millfork/env/Thing.scala index 07362b93..6f5fcffd 100644 --- a/src/main/scala/millfork/env/Thing.scala +++ b/src/main/scala/millfork/env/Thing.scala @@ -481,6 +481,7 @@ case class NormalFunction(name: String, hasElidedReturnVariable: Boolean, interrupt: Boolean, kernalInterrupt: Boolean, + inAssembly: Boolean, isConstPure: Boolean, reentrant: Boolean, position: Option[Position], diff --git a/src/test/scala/millfork/test/AssemblySuite.scala b/src/test/scala/millfork/test/AssemblySuite.scala index d388db95..df934f0c 100644 --- a/src/test/scala/millfork/test/AssemblySuite.scala +++ b/src/test/scala/millfork/test/AssemblySuite.scala @@ -460,4 +460,49 @@ class AssemblySuite extends FunSuite with Matchers with AppendedClues { m.readByte(0xc001) should equal(1) m.readByte(0xc002) should equal(2) } + + test("Interrupt functions in assembly should not have prologue (6502)") { + val m = EmuUnoptimizedRun( + """ + |byte output @$c000 + |noinline interrupt asm void i() { + | nop + | rti + |} + |void main() { + | output = pointer(i.addr)[0] + |} + |""".stripMargin) + m.readByte(0xc000) should equal(0xea) + } + + test("Interrupt functions in assembly should not have prologue (Z80)") { + val m = EmuUnoptimizedZ80Run( + """ + |byte output @$c000 + |noinline interrupt asm void i() { + | nop + | reti + |} + |void main() { + | output = pointer(i.addr)[0] + |} + |""".stripMargin) + m.readByte(0xc000) should equal(0) + } + + test("Interrupt functions in assembly should not have prologue (M6809)") { + val m = EmuUnoptimizedM6809Run( + """ + |byte output @$c000 + |noinline interrupt asm void i() { + | nop + | rti + |} + |void main() { + | output = pointer(i.addr)[0] + |} + |""".stripMargin) + m.readByte(0xc000) should equal(0x12) + } }