mirror of
https://github.com/KarolS/millfork.git
synced 2024-12-23 08:29:35 +00:00
Preparations for work on LR35902 support
This commit is contained in:
parent
c5b45947dc
commit
2ca30315ca
@ -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"
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
18
src/test/scala/millfork/test/emu/GameboyMemory.scala
Normal file
18
src/test/scala/millfork/test/emu/GameboyMemory.scala
Normal 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)
|
||||
}
|
29
src/test/scala/millfork/test/emu/GameboyStubs.scala
Normal file
29
src/test/scala/millfork/test/emu/GameboyStubs.scala
Normal 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)
|
||||
}
|
Loading…
Reference in New Issue
Block a user