From 33ee5115e0bbdcb0f063b0ffbd526345c6369f82 Mon Sep 17 00:00:00 2001 From: Karol Stasiak Date: Sat, 3 Mar 2018 14:32:11 +0100 Subject: [PATCH] Better stack- and interrupt handling for 65816 and 65CE02 --- .../scala/millfork/compiler/BuiltIns.scala | 16 ++++++--- .../scala/millfork/compiler/MfCompiler.scala | 28 +++++++++++++-- .../millfork/compiler/StatementCompiler.scala | 35 ++++++++++++++++--- 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/src/main/scala/millfork/compiler/BuiltIns.scala b/src/main/scala/millfork/compiler/BuiltIns.scala index 25667dbe..3e73e0b7 100644 --- a/src/main/scala/millfork/compiler/BuiltIns.scala +++ b/src/main/scala/millfork/compiler/BuiltIns.scala @@ -71,11 +71,17 @@ object BuiltIns { return simpleOperation(opcode, ctx, param, indexChoice, preserveA, commutative, decimal) case _: FunctionCallExpression | _:SumExpression if commutative => // TODO: is it ok? - return List(AssemblyLine.implied(PHA)) ++ ExpressionCompiler.compile(ctx.addStack(1), source, Some(b -> RegisterVariable(Register.A, b)), NoBranching) ++ wrapInSedCldIfNeeded(decimal, List( - AssemblyLine.implied(TSX), - AssemblyLine.absoluteX(opcode, 0x101), - AssemblyLine.implied(INX), - AssemblyLine.implied(TXS))) + if (ctx.options.flag(CompilationFlag.EmitEmulation65816Opcodes)) { + return List(AssemblyLine.implied(PHA)) ++ ExpressionCompiler.compile(ctx.addStack(1), source, Some(b -> RegisterVariable(Register.A, b)), NoBranching) ++ wrapInSedCldIfNeeded(decimal, List( + AssemblyLine.stackRelative(opcode, 1), + AssemblyLine.implied(PHX))) + } else { + return List(AssemblyLine.implied(PHA)) ++ ExpressionCompiler.compile(ctx.addStack(1), source, Some(b -> RegisterVariable(Register.A, b)), NoBranching) ++ wrapInSedCldIfNeeded(decimal, List( + AssemblyLine.implied(TSX), + AssemblyLine.absoluteX(opcode, 0x101), + AssemblyLine.implied(INX), + AssemblyLine.implied(TXS))) // this TXS is fine, it won't appear in 65816 code + } case _ => ErrorReporting.error("Right-hand-side expression is too complex", source.position) return Nil diff --git a/src/main/scala/millfork/compiler/MfCompiler.scala b/src/main/scala/millfork/compiler/MfCompiler.scala index 07bd2511..833fcf22 100644 --- a/src/main/scala/millfork/compiler/MfCompiler.scala +++ b/src/main/scala/millfork/compiler/MfCompiler.scala @@ -27,7 +27,31 @@ object MfCompiler { ctx.env.nameCheck(ctx.function.code) val chunk = StatementCompiler.compile(ctx, ctx.function.code) val prefix = (if (ctx.function.interrupt) { - if (ctx.options.flag(CompilationFlag.EmitCmosOpcodes)) { + + if (ctx.options.flag(CompilationFlag.EmitNative65816Opcodes)) { + List( + AssemblyLine.implied(PHB), + AssemblyLine.implied(PHD), + AssemblyLine.immediate(REP, 0x30), + AssemblyLine.implied(PHA), + AssemblyLine.implied(PHX), + AssemblyLine.implied(PHY), + AssemblyLine.immediate(SEP, 0x30)) + } else if (ctx.options.flag(CompilationFlag.EmitEmulation65816Opcodes)) { + List( + AssemblyLine.implied(PHB), + AssemblyLine.implied(PHD), + AssemblyLine.implied(PHA), + AssemblyLine.implied(PHX), + AssemblyLine.implied(PHY)) + } else if (ctx.options.flag(CompilationFlag.Emit65CE02Opcodes)) { + List( + AssemblyLine.implied(PHA), + AssemblyLine.implied(PHX), + AssemblyLine.implied(PHY), + AssemblyLine.implied(PHZ), + AssemblyLine.implied(CLD)) + } else if (ctx.options.flag(CompilationFlag.EmitCmosOpcodes)) { List( AssemblyLine.implied(PHA), AssemblyLine.implied(PHX), @@ -56,7 +80,7 @@ object MfCompiler { AssemblyLine.implied(TSX), AssemblyLine.immediate(LDA, 0xff), AssemblyLine.immediate(SBX, m.stackVariablesSize), - AssemblyLine.implied(TXS)) + AssemblyLine.implied(TXS)) // this TXS is fine, it won't appear in 65816 code } List.fill(m.stackVariablesSize)(AssemblyLine.implied(PHA)) } diff --git a/src/main/scala/millfork/compiler/StatementCompiler.scala b/src/main/scala/millfork/compiler/StatementCompiler.scala index 22c637ca..8d3b152c 100644 --- a/src/main/scala/millfork/compiler/StatementCompiler.scala +++ b/src/main/scala/millfork/compiler/StatementCompiler.scala @@ -35,7 +35,32 @@ object StatementCompiler { val someRegisterAX = Some(w, RegisterVariable(Register.AX, w)) val someRegisterYA = Some(w, RegisterVariable(Register.YA, w)) val returnInstructions = if (m.interrupt) { - if (ctx.options.flag(CompilationFlag.EmitCmosOpcodes)) { + if (ctx.options.flag(CompilationFlag.EmitNative65816Opcodes)) { + List( + AssemblyLine.immediate(REP, 0x30), + AssemblyLine.implied(PLY), + AssemblyLine.implied(PLX), + AssemblyLine.implied(PLA), + AssemblyLine.implied(PLD), + AssemblyLine.implied(PLB), + AssemblyLine.implied(RTI)) + } else + if (ctx.options.flag(CompilationFlag.EmitEmulation65816Opcodes)) { + List( + AssemblyLine.implied(PLY), + AssemblyLine.implied(PLX), + AssemblyLine.implied(PLA), + AssemblyLine.implied(PLD), + AssemblyLine.implied(PLB), + AssemblyLine.implied(RTI)) + } else if (ctx.options.flag(CompilationFlag.Emit65CE02Opcodes)) { + List( + AssemblyLine.implied(PLZ), + AssemblyLine.implied(PLY), + AssemblyLine.implied(PLX), + AssemblyLine.implied(PLA), + AssemblyLine.implied(RTI)) + } else if (ctx.options.flag(CompilationFlag.EmitCmosOpcodes)) { List( AssemblyLine.implied(PLY), AssemblyLine.implied(PLX), @@ -50,6 +75,8 @@ object StatementCompiler { AssemblyLine.implied(PLA), AssemblyLine.implied(RTI)) } + } else if (m.isFar(ctx.options)) { + List(AssemblyLine.implied(RTL)) } else { List(AssemblyLine.implied(RTS)) } @@ -373,17 +400,17 @@ object StatementCompiler { AssemblyLine.implied(TSX), AssemblyLine.immediate(LDA, 0xff), AssemblyLine.immediate(SBX, 256 - m.stackVariablesSize), - AssemblyLine.implied(TXS)) + AssemblyLine.implied(TXS)) // this TXS is fine, it won't appear in 65816 code if (m.returnType.size == 1 && m.stackVariablesSize > 6) return List( AssemblyLine.implied(TAY), AssemblyLine.implied(TSX), AssemblyLine.immediate(LDA, 0xff), AssemblyLine.immediate(SBX, 256 - m.stackVariablesSize), - AssemblyLine.implied(TXS), + AssemblyLine.implied(TXS), // this TXS is fine, it won't appear in 65816 code AssemblyLine.implied(TYA)) } - AssemblyLine.implied(TSX) :: (List.fill(m.stackVariablesSize)(AssemblyLine.implied(INX)) :+ AssemblyLine.implied(TXS)) + AssemblyLine.implied(TSX) :: (List.fill(m.stackVariablesSize)(AssemblyLine.implied(INX)) :+ AssemblyLine.implied(TXS)) // this TXS is fine, it won't appear in 65816 code } }