1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-08-13 02:28:59 +00:00

6502: Use zeropage addressing mode when accessing fixed zeropage locations

This commit is contained in:
Karol Stasiak 2018-09-29 01:16:22 +02:00
parent cbe6d03e60
commit 3736b5ae56
4 changed files with 71 additions and 3 deletions

View File

@ -339,6 +339,21 @@ object OpcodeClasses {
val DiscardsD = OverwritesD
val DiscardsI = NoopDiscardsFlags | OverwritesI
val SupportsZeropage = Set(
LDA, LDX, LDY, LAX, // LDZ doesn't!
LDA_W, LDX_W, LDY_W,
STA, STX, STY, SAX, STZ,
STA_W, LDX_W, LDY_W,
BIT,
CPX, CPY, CPZ,
ADC, SBC, CMP, AND, ORA, EOR,
ADC_W, SBC_W, CMP_W, AND_W, ORA_W, EOR_W,
INC, DEC, ROL, ROR, ASL, LSR,
INC_W, DEC_W, ROL_W, ROR_W, ASL_W, LSR_W,
ISC, DCP, RLA, RRA, SLO, SRE,
TSB, TRB,
)
}
object AssemblyLine {

View File

@ -156,6 +156,7 @@ object MosStatementCompiler extends AbstractStatementCompiler[AssemblyLine] {
}
val actualAddrMode = a match {
case Absolute if OpcodeClasses.ShortBranching(o) => Relative
case Absolute if OpcodeClasses.SupportsZeropage(o) && c.fitsProvablyIntoByte => ZeroPage
case IndexedX if o == JMP => AbsoluteIndexedX
case Indirect if o != JMP => IndexedZ
case _ => a

View File

@ -26,6 +26,7 @@ sealed trait Constant {
case NumericConstant(0, _) => true
case _ => false
}
def fitsProvablyIntoByte: Boolean = false
def asl(i: Constant): Constant = i match {
case NumericConstant(sa, _) => asl(sa.toInt)
@ -100,6 +101,7 @@ case class AssertByte(c: Constant) extends Constant {
override def isProvablyZero: Boolean = c.isProvablyZero
override def isProvably(i: Int): Boolean = c.isProvably(i)
override def isProvablyNonnegative: Boolean = c.isProvablyNonnegative
override def fitsProvablyIntoByte: Boolean = true
override def requiredSize: Int = 1
@ -132,6 +134,7 @@ case class NumericConstant(value: Long, requiredSize: Int) extends Constant {
override def isProvablyZero: Boolean = value == 0
override def isProvably(i: Int): Boolean = value == i
override def isProvablyNonnegative: Boolean = value >= 0
override def fitsProvablyIntoByte: Boolean = requiredSize == 1
override def isLowestByteAlwaysEqual(i: Int) : Boolean = (value & 0xff) == (i&0xff)
@ -211,6 +214,7 @@ case class SubbyteConstant(base: Constant, index: Int) extends Constant {
override def requiredSize = 1
override def isProvablyNonnegative: Boolean = true
override def fitsProvablyIntoByte: Boolean = true
override def toString: String = index match {
case 0 => s"lo($base)"

View File

@ -1,11 +1,11 @@
package millfork.test
import millfork.test.emu.EmuBenchmarkRun
import org.scalatest.{FunSuite, Matchers}
import millfork.test.emu.{EmuBenchmarkRun, EmuOptimizedCmosRun, EmuOptimizedRun}
import org.scalatest.{AppendedClues, FunSuite, Matchers}
/**
* @author Karol Stasiak
*/
class AssemblySuite extends FunSuite with Matchers {
class AssemblySuite extends FunSuite with Matchers with AppendedClues {
test("Inline assembly") {
EmuBenchmarkRun(
@ -163,4 +163,52 @@ class AssemblySuite extends FunSuite with Matchers {
| }
""".stripMargin)(_.readByte(0xc000) should equal(10))
}
test("Correctly use zeropage for CPU port on C64") {
val m = EmuOptimizedRun(
"""
| byte port @1
| const byte port_addr = 1
| byte port_alt @port_addr
| void main () {
| a()
| b()
| c()
| d()
| e()
| f()
| }
| noinline void a() {
| port = 1
| }
| noinline void b() {
| port_alt = 2
| }
| noinline asm void c() {
| lda #3
| sta 1
| rts
| }
| noinline asm void d() {
| lda #4
| sta port
| rts
| }
| noinline asm void e() {
| lda #5
| sta port_addr
| rts
| }
| noinline asm void f() {
| lda #6
| sta port_alt
| rts
| }
""".stripMargin)
for (addr <- 0x0200 to 0x02ff) {
m.readable(addr) = true
m.readByte(addr) should not equal 0x8d withClue f"STA abs at $addr%04x"
}
}
}