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:
parent
b8547ed154
commit
6f00cacc6d
@ -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) ++
|
||||
|
@ -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")
|
||||
|
3
src/main/scala/millfork/env/Constant.scala
vendored
3
src/main/scala/millfork/env/Constant.scala
vendored
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user