1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-06-01 09:41:36 +00:00

Preparations for work on LR35902 support

This commit is contained in:
Karol Stasiak 2018-07-24 23:44:00 +02:00
parent c5b45947dc
commit 2ca30315ca
8 changed files with 103 additions and 8 deletions

View File

@ -14,15 +14,18 @@ libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.4" % "test"
libraryDependencies += "com.codingrodent.microprocessor" % "Z80Processor" % "2.0.2" % "test"
// these two are not in Maven Central or any other public repo
// these three are not in Maven Central or any other public repo
// get them from the following links or just build millfork without tests:
// https://github.com/sethm/symon/tree/71905fdb1998ee4f142260879504bc46cf27648f
// https://github.com/andrew-hoffman/halfnes/tree/061
// https://github.com/trekawek/coffee-gb/tree/coffee-gb-1.0.0
libraryDependencies += "com.loomcom.symon" % "symon" % "1.3.0-SNAPSHOT" % "test"
libraryDependencies += "com.grapeshot" % "halfnes" % "061" % "test"
libraryDependencies += "eu.rekawek.coffeegb" % "coffee-gb" % "1.0.0" % "test"
mainClass in Compile := Some("millfork.Main")
assemblyJarName := "millfork.jar"

View File

@ -9,7 +9,7 @@ import org.scalatest.{FunSuite, Matchers}
*/
class BasicSymonTest extends FunSuite with Matchers {
test("Empty test") {
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)(
"""
| void main () {
|
@ -80,13 +80,13 @@ class BasicSymonTest extends FunSuite with Matchers {
output += 1
}
"""
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(src){m =>
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)(src){m =>
m.readByte(0xc000) should equal(src.count(_ == '+'))
}
}
test("Byte assignment") {
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)(
"""
| byte output @$c000
| void main () {
@ -98,7 +98,7 @@ class BasicSymonTest extends FunSuite with Matchers {
}
test("Preallocated variables") {
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)(
"""
| array output [2] @$c000
| byte number = 4
@ -127,7 +127,7 @@ class BasicSymonTest extends FunSuite with Matchers {
}
test("Else if") {
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)(
"""
| byte output @$c000
| void main () {
@ -145,7 +145,7 @@ class BasicSymonTest extends FunSuite with Matchers {
}
test("Segment syntax") {
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)(
"""
| segment(default)byte output @$c000
| segment(default)array x[3]
@ -174,7 +174,7 @@ class BasicSymonTest extends FunSuite with Matchers {
}
test("Preprocessor test") {
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)(
"""
| byte output @$c000
|

View File

@ -63,6 +63,25 @@ object EmuIntel8080BenchmarkRun {
}
}
object EmuSharpBenchmarkRun {
def apply(source: String)(verifier: MemoryBank => Unit): Unit = {
val (Timings(t0, _), m0) = EmuUnoptimizedSharpRun.apply2(source)
// val (Timings(t1, _), m1) = EmuOptimizedZ80Run.apply2(source)
// val (Timings(t2, _), m2) = EmuOptimizedInlinedZ80Run.apply2(source)
println(f"Before optimization: $t0%7d")
// println(f"After optimization: $t1%7d")
// println(f"After inlining: $t2%7d")
// println(f"Gain: ${(100L * (t0 - t1) / t0.toDouble).round}%7d%%")
// println(f"Gain with inlining: ${(100L * (t0 - t2) / t0.toDouble).round}%7d%%")
println(f"Running unoptimized")
verifier(m0)
// println(f"Running optimized")
// verifier(m1)
// println(f"Running optimized inlined")
// verifier(m2)
}
}
object EmuCrossPlatformBenchmarkRun {
def apply(platforms: millfork.Cpu.Value*)(source: String)(verifier: MemoryBank => Unit): Unit = {
if (platforms.isEmpty) {
@ -77,5 +96,11 @@ object EmuCrossPlatformBenchmarkRun {
if (platforms.contains(millfork.Cpu.Z80)) {
EmuZ80BenchmarkRun.apply(source)(verifier)
}
if (platforms.contains(millfork.Cpu.Intel8080)) {
EmuIntel8080BenchmarkRun.apply(source)(verifier)
}
if (platforms.contains(millfork.Cpu.Sharp)) {
EmuSharpBenchmarkRun.apply(source)(verifier)
}
}
}

View File

@ -11,6 +11,7 @@ object EmuUnoptimizedCrossPlatformRun {
val (_, mm) = if (platforms.contains(Cpu.Mos)) EmuUnoptimizedRun.apply2(source) else Timings(-1, -1) -> null
val (_, mz) = if (platforms.contains(Cpu.Z80)) EmuUnoptimizedZ80Run.apply2(source) else Timings(-1, -1) -> null
val (_, mi) = if (platforms.contains(Cpu.Intel8080)) EmuUnoptimizedIntel8080Run.apply2(source) else Timings(-1, -1) -> null
val (_, ms) = if (platforms.contains(Cpu.Sharp)) EmuUnoptimizedSharpRun.apply2(source) else Timings(-1, -1) -> null
if (platforms.contains(Cpu.Mos)) {
println(f"Running MOS")
verifier(mm)
@ -23,5 +24,9 @@ object EmuUnoptimizedCrossPlatformRun {
println(f"Running 8080")
verifier(mi)
}
if (platforms.contains(Cpu.Sharp)) {
println(f"Running LR35902")
verifier(ms)
}
}
}

View File

@ -11,3 +11,5 @@ object EmuUnoptimizedRun extends EmuRun(Cpu.StrictMos, Nil, Nil)
object EmuUnoptimizedZ80Run extends EmuZ80Run(Cpu.Z80, Nil, Nil)
object EmuUnoptimizedIntel8080Run extends EmuZ80Run(Cpu.Intel8080, Nil, Nil)
object EmuUnoptimizedSharpRun extends EmuZ80Run(Cpu.Sharp, Nil, Nil)

View File

@ -1,6 +1,9 @@
package millfork.test.emu
import com.codingrodent.microprocessor.Z80.{CPUConstants, Z80Core}
import eu.rekawek.coffeegb.AddressSpace
import eu.rekawek.coffeegb.cpu.{Cpu, InterruptManager, SpeedMode}
import eu.rekawek.coffeegb.gpu.Gpu
import fastparse.core.Parsed.{Failure, Success}
import millfork.assembly.AssemblyOptimization
import millfork.assembly.z80.ZLine
@ -123,6 +126,16 @@ class EmuZ80Run(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimizatio
}
val tStates = cpu.getTStates
Timings(tStates, tStates) -> memoryBank
case millfork.Cpu.Sharp =>
var ticks = 0L
val cpu = GameboyStubs(memoryBank).cpu
cpu.getRegisters.setPC(0x1f0)
while (cpu.getState != Cpu.State.HALTED) {
cpu.tick()
ticks += 4
ticks should be < TooManyCycles
}
Timings(ticks, ticks) -> memoryBank
case _ =>
Timings(-1, -1) -> memoryBank
}

View File

@ -0,0 +1,18 @@
package millfork.test.emu
import eu.rekawek.coffeegb.AddressSpace
import millfork.output.MemoryBank
/**
* @author Karol Stasiak
*/
case class GameboyMemory(memoryBank: MemoryBank) extends AddressSpace {
override def accepts(i: Int): Boolean = true
override def setByte(address: Int, data: Int): Unit = {
// if (!memoryBank.writeable(address)) throw new RuntimeException("Can't write to $" + address.toHexString)
memoryBank.output(address) = data.toByte
}
override def getByte(address: Int): Int = memoryBank.readByte(address)
}

View File

@ -0,0 +1,29 @@
package millfork.test.emu
import eu.rekawek.coffeegb.AddressSpace
import eu.rekawek.coffeegb.cpu.{Cpu, InterruptManager, SpeedMode}
import eu.rekawek.coffeegb.gpu.{Display, Gpu}
import eu.rekawek.coffeegb.memory.{Dma, Ram}
import millfork.output.MemoryBank
/**
* @author Karol Stasiak
*/
case class GameboyStubs(memoryBank: MemoryBank) {
val display: Display = Display.NULL_DISPLAY
val interruptManager: InterruptManager = new InterruptManager(false)
interruptManager.disableInterrupts(false)
val addressSpace: AddressSpace = GameboyMemory(memoryBank)
val oamRam: Ram = new Ram(0, 0)
val speedMode: SpeedMode = new SpeedMode
val dma: Dma = new Dma(addressSpace, oamRam, speedMode)
val gpu: Gpu = new Gpu(display, interruptManager, dma, oamRam, false)
val cpu: Cpu = new Cpu(addressSpace, interruptManager, gpu, display, speedMode)
}