diff --git a/src/main/scala/millfork/compiler/mos/BuiltIns.scala b/src/main/scala/millfork/compiler/mos/BuiltIns.scala index 4239f0b0..d2de5a4e 100644 --- a/src/main/scala/millfork/compiler/mos/BuiltIns.scala +++ b/src/main/scala/millfork/compiler/mos/BuiltIns.scala @@ -205,6 +205,33 @@ object BuiltIns { firstParamCompiled ++ remainingParamsCompiled } + def maybeCompileShiftFromByteToWord(ctx: CompilationContext, l: Expression, r: Expression, left: Boolean): Option[List[AssemblyLine]] = { + val env = ctx.env + env.eval(r) match { + case Some(NumericConstant(n, _)) => + l match { + case FunctionCallExpression(wordTypeName, List(param)) => + if (AbstractExpressionCompiler.getExpressionType(ctx, param).size == 1 && env.maybeGet[Type](wordTypeName).exists(_.size == 2)) { + Some(MosExpressionCompiler.compileToA(ctx, param) ++ BuiltIns.compileShiftFromByteToWord(ctx, n.toInt, left)) + } else { + None + } + } + case _ => None + } + } + + def compileShiftFromByteToWord(ctx: CompilationContext, count: Int, left: Boolean): List[AssemblyLine] = { + if (count == 8) { + List(AssemblyLine.implied(TAX), AssemblyLine.immediate(LDA, 0)) + } else { + List(AssemblyLine.implied(PHA)) ++ + List.fill(8 - count)(AssemblyLine.implied(if (left) LSR else ASL)) ++ + List(AssemblyLine.implied(TAX), AssemblyLine.implied(PLA)) ++ + List.fill(count)(AssemblyLine.implied(if (left) ASL else LSR)) + } + } + def compileShiftOps(opcode: Opcode.Value, ctx: CompilationContext, l: Expression, r: Expression): List[AssemblyLine] = { val b = ctx.env.get[Type]("byte") val firstParamCompiled = MosExpressionCompiler.compile(ctx, l, Some(b -> RegisterVariable(MosRegister.A, b)), NoBranching) diff --git a/src/main/scala/millfork/compiler/mos/MosExpressionCompiler.scala b/src/main/scala/millfork/compiler/mos/MosExpressionCompiler.scala index c4906862..7473f05c 100644 --- a/src/main/scala/millfork/compiler/mos/MosExpressionCompiler.scala +++ b/src/main/scala/millfork/compiler/mos/MosExpressionCompiler.scala @@ -831,7 +831,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] { zeroExtend = true BuiltIns.compileShiftOps(ASL, ctx, l, r) case 2 => - PseudoregisterBuiltIns.compileWordShiftOps(left = true, ctx, l, r) + BuiltIns.maybeCompileShiftFromByteToWord(ctx, l, r, left = true).getOrElse(PseudoregisterBuiltIns.compileWordShiftOps(left = true, ctx, l, r)) case _ => ctx.log.error("Long shift ops not supported", l.position) Nil @@ -843,7 +843,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] { zeroExtend = true BuiltIns.compileShiftOps(LSR, ctx, l, r) case 2 => - PseudoregisterBuiltIns.compileWordShiftOps(left = false, ctx, l, r) + BuiltIns.maybeCompileShiftFromByteToWord(ctx, l, r, left = false).getOrElse(PseudoregisterBuiltIns.compileWordShiftOps(left = false, ctx, l, r)) case _ => ctx.log.error("Long shift ops not supported", l.position) Nil diff --git a/src/main/scala/millfork/compiler/mos/PseudoregisterBuiltIns.scala b/src/main/scala/millfork/compiler/mos/PseudoregisterBuiltIns.scala index d640e721..31eda58c 100644 --- a/src/main/scala/millfork/compiler/mos/PseudoregisterBuiltIns.scala +++ b/src/main/scala/millfork/compiler/mos/PseudoregisterBuiltIns.scala @@ -229,7 +229,7 @@ object PseudoregisterBuiltIns { val firstParamCompiled = MosExpressionCompiler.compile(ctx, l, Some(MosExpressionCompiler.getExpressionType(ctx, l) -> reg), NoBranching) ctx.env.eval(r) match { case Some(NumericConstant(0, _)) => - Nil + List(AssemblyLine.zeropage(LDA, reg), AssemblyLine.zeropage(LDX, reg, 1)) case Some(NumericConstant(v, _)) if v > 0 => if (ctx.options.flag(CompilationFlag.EmitNative65816Opcodes)) { firstParamCompiled ++