mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-10 20: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"
|
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:
|
// get them from the following links or just build millfork without tests:
|
||||||
// https://github.com/sethm/symon/tree/71905fdb1998ee4f142260879504bc46cf27648f
|
// https://github.com/sethm/symon/tree/71905fdb1998ee4f142260879504bc46cf27648f
|
||||||
// https://github.com/andrew-hoffman/halfnes/tree/061
|
// 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.loomcom.symon" % "symon" % "1.3.0-SNAPSHOT" % "test"
|
||||||
|
|
||||||
libraryDependencies += "com.grapeshot" % "halfnes" % "061" % "test"
|
libraryDependencies += "com.grapeshot" % "halfnes" % "061" % "test"
|
||||||
|
|
||||||
|
libraryDependencies += "eu.rekawek.coffeegb" % "coffee-gb" % "1.0.0" % "test"
|
||||||
|
|
||||||
mainClass in Compile := Some("millfork.Main")
|
mainClass in Compile := Some("millfork.Main")
|
||||||
|
|
||||||
assemblyJarName := "millfork.jar"
|
assemblyJarName := "millfork.jar"
|
||||||
|
@ -9,7 +9,7 @@ import org.scalatest.{FunSuite, Matchers}
|
|||||||
*/
|
*/
|
||||||
class BasicSymonTest extends FunSuite with Matchers {
|
class BasicSymonTest extends FunSuite with Matchers {
|
||||||
test("Empty test") {
|
test("Empty test") {
|
||||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)(
|
||||||
"""
|
"""
|
||||||
| void main () {
|
| void main () {
|
||||||
|
|
|
|
||||||
@ -80,13 +80,13 @@ class BasicSymonTest extends FunSuite with Matchers {
|
|||||||
output += 1
|
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(_ == '+'))
|
m.readByte(0xc000) should equal(src.count(_ == '+'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test("Byte assignment") {
|
test("Byte assignment") {
|
||||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)(
|
||||||
"""
|
"""
|
||||||
| byte output @$c000
|
| byte output @$c000
|
||||||
| void main () {
|
| void main () {
|
||||||
@ -98,7 +98,7 @@ class BasicSymonTest extends FunSuite with Matchers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("Preallocated variables") {
|
test("Preallocated variables") {
|
||||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)(
|
||||||
"""
|
"""
|
||||||
| array output [2] @$c000
|
| array output [2] @$c000
|
||||||
| byte number = 4
|
| byte number = 4
|
||||||
@ -127,7 +127,7 @@ class BasicSymonTest extends FunSuite with Matchers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("Else if") {
|
test("Else if") {
|
||||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)(
|
||||||
"""
|
"""
|
||||||
| byte output @$c000
|
| byte output @$c000
|
||||||
| void main () {
|
| void main () {
|
||||||
@ -145,7 +145,7 @@ class BasicSymonTest extends FunSuite with Matchers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("Segment syntax") {
|
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)byte output @$c000
|
||||||
| segment(default)array x[3]
|
| segment(default)array x[3]
|
||||||
@ -174,7 +174,7 @@ class BasicSymonTest extends FunSuite with Matchers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("Preprocessor test") {
|
test("Preprocessor test") {
|
||||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)(
|
||||||
"""
|
"""
|
||||||
| byte output @$c000
|
| 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 {
|
object EmuCrossPlatformBenchmarkRun {
|
||||||
def apply(platforms: millfork.Cpu.Value*)(source: String)(verifier: MemoryBank => Unit): Unit = {
|
def apply(platforms: millfork.Cpu.Value*)(source: String)(verifier: MemoryBank => Unit): Unit = {
|
||||||
if (platforms.isEmpty) {
|
if (platforms.isEmpty) {
|
||||||
@ -77,5 +96,11 @@ object EmuCrossPlatformBenchmarkRun {
|
|||||||
if (platforms.contains(millfork.Cpu.Z80)) {
|
if (platforms.contains(millfork.Cpu.Z80)) {
|
||||||
EmuZ80BenchmarkRun.apply(source)(verifier)
|
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 (_, 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 (_, 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 (_, 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)) {
|
if (platforms.contains(Cpu.Mos)) {
|
||||||
println(f"Running MOS")
|
println(f"Running MOS")
|
||||||
verifier(mm)
|
verifier(mm)
|
||||||
@ -23,5 +24,9 @@ object EmuUnoptimizedCrossPlatformRun {
|
|||||||
println(f"Running 8080")
|
println(f"Running 8080")
|
||||||
verifier(mi)
|
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 EmuUnoptimizedZ80Run extends EmuZ80Run(Cpu.Z80, Nil, Nil)
|
||||||
|
|
||||||
object EmuUnoptimizedIntel8080Run extends EmuZ80Run(Cpu.Intel8080, 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
|
package millfork.test.emu
|
||||||
|
|
||||||
import com.codingrodent.microprocessor.Z80.{CPUConstants, Z80Core}
|
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 fastparse.core.Parsed.{Failure, Success}
|
||||||
import millfork.assembly.AssemblyOptimization
|
import millfork.assembly.AssemblyOptimization
|
||||||
import millfork.assembly.z80.ZLine
|
import millfork.assembly.z80.ZLine
|
||||||
@ -123,6 +126,16 @@ class EmuZ80Run(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimizatio
|
|||||||
}
|
}
|
||||||
val tStates = cpu.getTStates
|
val tStates = cpu.getTStates
|
||||||
Timings(tStates, tStates) -> memoryBank
|
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 _ =>
|
case _ =>
|
||||||
Timings(-1, -1) -> memoryBank
|
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…
x
Reference in New Issue
Block a user