1
0
mirror of https://github.com/KarolS/millfork.git synced 2025-04-04 06:29:48 +00:00

Use zeropage indexed adressing when possible

This commit is contained in:
Karol Stasiak 2020-01-18 00:06:20 +01:00
parent 921a59bdad
commit b3fba658dd
3 changed files with 46 additions and 2 deletions

View File

@ -288,6 +288,17 @@ object OpcodeClasses {
SHY,
)
val SupportsZeroPageX = Set(
ORA, AND, EOR, ADC, CMP, SBC,
ORA_W, AND_W, EOR_W, ADC_W, CMP_W, SBC_W,
ASL, ROL, LSR, ROR, DEC, INC,
ASL_W, ROL_W, LSR_W, ROR_W, DEC_W, INC_W,
SLO, RLA, SRE, RRA, DCP, ISC,
ASR,
STA, LDA, LDY, STY, STZ,
STA_W, LDA_W, LDY_W, STY_W, STZ_W,
)
val SupportsAbsoluteY = Set(
ORA, AND, EOR, ADC, CMP, SBC,
ORA_W, AND_W, EOR_W, ADC_W, CMP_W, SBC_W,
@ -297,6 +308,12 @@ object OpcodeClasses {
LAX, AHX, SHX, TAS, LAS,
)
val SupportsZeroPageY = Set(
LDX, STX,
LDX_W, STX_W,
SAX, LAX,
)
val SupportsAbsolute = Set(
ORA, AND, EOR, ADC, STA, LDA, CMP, SBC,
ORA_W, AND_W, EOR_W, ADC_W, STA_W, LDA_W, CMP_W, SBC_W,

View File

@ -164,6 +164,8 @@ object MosStatementCompiler extends AbstractStatementCompiler[AssemblyLine] {
val c: Constant = compileParameterForAssemblyStatement(env, o, x)
val actualAddrMode = a match {
case Absolute if OpcodeClasses.ShortBranching(o) => Relative
case Absolute if (o == ROR_W || o == ASL_W) && ctx.options.flag(CompilationFlag.Emit65CE02Opcodes) =>
Absolute
case Absolute if OpcodeClasses.SupportsZeropage(o) && c.fitsProvablyIntoByte => ZeroPage
case ImmediateWithAbsolute if (c match {
case StructureConstant(_, List(a, b)) => b.fitsProvablyIntoByte

View File

@ -34,6 +34,13 @@ case class MosParser(filename: String, input: String, currentDirectory: String,
val farKeyword: P[Unit] = P(("f" | "F") ~ ("a" | "A") ~ ("r" | "R"))
def isObviouslyZeropage(e: Expression): Boolean = e match {
case LiteralExpression(value, size) => size == 1 && value >= 0 && value <= 0xff
case FunctionCallExpression("lo" | "hi", _) => true
case FunctionCallExpression("|" | "&" | "^", exprs) => exprs.forall(isObviouslyZeropage)
case _ => false
}
val asmParameter: P[(AddrMode.Value, Expression)] = {
(SWS ~ (
("##" ~ asmExpression).map(AddrMode.WordImmediate -> _) |
@ -48,8 +55,21 @@ case class MosParser(filename: String, input: String, currentDirectory: String,
(farKeyword ~ HWS ~ asmExpression ~ commaX).map(AddrMode.LongAbsoluteX -> _) |
(farKeyword ~ HWS ~ asmExpression).map(AddrMode.LongAbsolute -> _) |
(asmExpression ~ commaS).map(AddrMode.Stack -> _) |
(asmExpression ~ commaX).map(AddrMode.AbsoluteX -> _) |
(asmExpression ~ commaY).map(AddrMode.AbsoluteY -> _) |
(asmExpression ~ commaX).map { param =>
if (isObviouslyZeropage(param)) {
AddrMode.ZeroPageX -> param
} else {
AddrMode.AbsoluteX -> param
}
} |
(asmExpression ~ commaY).map { param =>
if (isObviouslyZeropage(param)) {
AddrMode.ZeroPageY -> param
} else {
AddrMode.AbsoluteY -> param
}
} |
// automatic zero page is handled elsewhere
asmExpression.map(AddrMode.Absolute -> _)
)).?.map(_.getOrElse(AddrMode.Implied -> LiteralExpression(0, 1)))
}
@ -78,7 +98,12 @@ case class MosParser(filename: String, input: String, currentDirectory: String,
case (Opcode.SAX, AddrMode.Implied) => MosAssemblyStatement(Opcode.HuSAX, param._1, param._2, elid)
case (Opcode.SBX, AddrMode.Immediate) => MosAssemblyStatement(Opcode.SBX, param._1, param._2, elid)
case (Opcode.SAY, AddrMode.AbsoluteX) => MosAssemblyStatement(Opcode.SHY, param._1, param._2, elid)
case (Opcode.SAX, AddrMode.AbsoluteY) => MosAssemblyStatement(Opcode.SAX, AddrMode.ZeroPageY, param._2, elid)
case (Opcode.ASR, AddrMode.Absolute) => MosAssemblyStatement(Opcode.ASR, AddrMode.ZeroPage, param._2, elid)
case (Opcode.ASR, AddrMode.AbsoluteX) => MosAssemblyStatement(Opcode.ASR, AddrMode.ZeroPageX, param._2, elid)
case (Opcode.SBX, _) => MosAssemblyStatement(Opcode.SAX, param._1, param._2, elid)
case (_, AddrMode.ZeroPageX) if !OpcodeClasses.SupportsZeroPageX(op) => MosAssemblyStatement(op, AddrMode.AbsoluteX, param._2, elid)
case (_, AddrMode.ZeroPageY) if !OpcodeClasses.SupportsZeroPageY(op) => MosAssemblyStatement(op, AddrMode.AbsoluteY, param._2, elid)
case (_, AddrMode.Absolute) if OpcodeClasses.SingleBit(op) => MosAssemblyStatement(op, AddrMode.ZeroPage, param._2, elid)
case (_, AddrMode.Indirect) if op != Opcode.JMP && op != Opcode.JSR => MosAssemblyStatement(op, AddrMode.IndexedZ, param._2, elid)
case _ => MosAssemblyStatement(op, param._1, param._2, elid)