1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-12-23 23:30:22 +00:00

6502: Optimize 16-bit multiplication by a constant

This commit is contained in:
Karol Stasiak 2019-03-18 20:01:40 +01:00
parent b8547ed154
commit 6f00cacc6d
3 changed files with 21 additions and 0 deletions

View File

@ -862,6 +862,8 @@ object BuiltIns {
}
}
private def isPowerOfTwoUpTo15(n: Long): Boolean = if (n <= 0 || n >= 0x8000) false else 0 == ((n-1) & n)
def compileInPlaceWordMultiplication(ctx: CompilationContext, v: LhsExpression, addend: Expression): List[AssemblyLine] = {
val b = ctx.env.get[Type]("byte")
val w = ctx.env.get[Type]("word")
@ -870,6 +872,8 @@ object BuiltIns {
MosExpressionCompiler.compile(ctx, v, None, NoBranching) ++ MosExpressionCompiler.compileAssignment(ctx, LiteralExpression(0, 2), v)
case Some(NumericConstant(1, _)) =>
MosExpressionCompiler.compile(ctx, v, None, NoBranching)
case Some(NumericConstant(n, _)) if isPowerOfTwoUpTo15(n) =>
BuiltIns.compileInPlaceWordOrLongShiftOps(ctx, v, LiteralExpression(java.lang.Long.bitCount(n - 1), 1), aslRatherThanLsr = true)
case _ =>
// TODO: optimize?
PseudoregisterBuiltIns.compileWordMultiplication(ctx, Some(v), addend, storeInRegLo = true) ++

View File

@ -380,6 +380,8 @@ object PseudoregisterBuiltIns {
load ++ calculate
}
private def isPowerOfTwoUpTo15(n: Long): Boolean = if (n <= 0 || n >= 0x8000) false else 0 == ((n-1) & n)
def compileWordMultiplication(ctx: CompilationContext, param1OrRegister: Option[Expression], param2: Expression, storeInRegLo: Boolean): List[AssemblyLine] = {
if (ctx.options.zpRegisterSize < 3) {
ctx.log.error("Variable word multiplication requires the zeropage pseudoregister of size at least 3", param1OrRegister.flatMap(_.position))
@ -391,6 +393,18 @@ object PseudoregisterBuiltIns {
case (2 | 1, 1) => // ok
case _ => ctx.log.fatal("Invalid code path", param2.position)
}
if (!storeInRegLo && param1OrRegister.isDefined) {
(ctx.env.eval(param1OrRegister.get), ctx.env.eval(param2)) match {
case (Some(l), Some(r)) =>
val product = CompoundConstant(MathOperator.Times, l, r).quickSimplify
return List(AssemblyLine.immediate(LDA, product.loByte), AssemblyLine.immediate(LDX, product.hiByte))
case (Some(NumericConstant(c, _)), _) if isPowerOfTwoUpTo15(c)=>
return compileWordShiftOps(left = true, ctx, param2, LiteralExpression(java.lang.Long.bitCount(c - 1), 1))
case (_, Some(NumericConstant(c, _))) if isPowerOfTwoUpTo15(c)=>
return compileWordShiftOps(left = true, ctx, param1OrRegister.get, LiteralExpression(java.lang.Long.bitCount(c - 1), 1))
case _ =>
}
}
val b = ctx.env.get[Type]("byte")
val w = ctx.env.get[Type]("word")
val reg = ctx.env.get[VariableInMemory]("__reg")

View File

@ -98,6 +98,9 @@ sealed trait Constant {
def refersTo(name: String): Boolean
def fitsInto(typ: Type): Boolean = true // TODO
final def succ: Constant = (this + 1).quickSimplify
}
case class AssertByte(c: Constant) extends Constant {