mirror of
https://github.com/KarolS/millfork.git
synced 2025-04-11 08:37:00 +00:00
Preliminary support for Intel 8080
This commit is contained in:
parent
749defd05a
commit
c5b45947dc
@ -28,10 +28,10 @@ case class CompilationOptions(platform: Platform, commandLineFlags: Map[Compilat
|
||||
invalids = invalids.filter(flags)
|
||||
|
||||
if (invalids.nonEmpty) {
|
||||
ErrorReporting.error("Invalid flags enabled for the currect CPU family: " + invalids.mkString(", "))
|
||||
ErrorReporting.error("Invalid flags enabled for the current CPU family: " + invalids.mkString(", "))
|
||||
}
|
||||
if (CpuFamily.forType(platform.cpu) != CpuFamily.M6502 && zpRegisterSize > 0) {
|
||||
ErrorReporting.error("Invalid flags enabled for the currect CPU family: zp_register" + invalids.mkString(", "))
|
||||
ErrorReporting.error("Invalid flags enabled for the current CPU family: zp_register" + invalids.mkString(", "))
|
||||
}
|
||||
CpuFamily.forType(platform.cpu) match {
|
||||
case CpuFamily.M6502 =>
|
||||
@ -97,39 +97,49 @@ case class CompilationOptions(platform: Platform, commandLineFlags: Map[Compilat
|
||||
}
|
||||
}
|
||||
if (flags(EmitZ80Opcodes)) {
|
||||
if (platform.cpu != Z80) {
|
||||
if (platform.cpu != Z80 && platform.cpu != EZ80) {
|
||||
ErrorReporting.error("Z80 opcodes enabled for architecture that doesn't support them")
|
||||
}
|
||||
}
|
||||
if (flags(EmitEZ80Opcodes)) {
|
||||
if (platform.cpu != Z80 && platform.cpu != EZ80) {
|
||||
ErrorReporting.error("eZ80 opcodes enabled for architecture that doesn't support them")
|
||||
}
|
||||
}
|
||||
if (flags(EmitSharpOpcodes)) {
|
||||
if (platform.cpu != Sharp) {
|
||||
ErrorReporting.error("Sharp LR35902 opcodes enabled for architecture that doesn't support them")
|
||||
}
|
||||
}
|
||||
if (flags(EmitExtended80Opcodes)) {
|
||||
if (platform.cpu != Sharp && platform.cpu != Z80) {
|
||||
if (platform.cpu != Sharp && platform.cpu != Z80 && platform.cpu != EZ80) {
|
||||
ErrorReporting.error("Extended 8080-like opcodes enabled for architecture that doesn't support them")
|
||||
}
|
||||
}
|
||||
if (flags(EmitIntel8080Opcodes)) {
|
||||
if (platform.cpu != Intel8080 && platform.cpu != Z80 && platform.cpu != EZ80) {
|
||||
ErrorReporting.error("Intel 8080 opcodes enabled for architecture that doesn't support them")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object CpuFamily extends Enumeration {
|
||||
val M6502, I80, M6809, I86, M68K, ARM = Value
|
||||
val M6502, I80, M6800, I86, M68K, ARM = Value
|
||||
|
||||
def forType(cpu: Cpu.Value): CpuFamily.Value = {
|
||||
import Cpu._
|
||||
cpu match {
|
||||
case Mos | StrictMos | Ricoh | StrictRicoh | Cmos | HuC6280 | CE02 | Sixteen => M6502
|
||||
case Intel8080 | Sharp | Z80 => I80
|
||||
case Intel8080 | Sharp | Z80 | EZ80 => I80
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object Cpu extends Enumeration {
|
||||
|
||||
val Mos, StrictMos, Ricoh, StrictRicoh, Cmos, HuC6280, CE02, Sixteen, Intel8080, Z80, Sharp = Value
|
||||
val Mos, StrictMos, Ricoh, StrictRicoh, Cmos, HuC6280, CE02, Sixteen, Intel8080, Z80, EZ80, Sharp = Value
|
||||
|
||||
val CmosCompatible = Set(Cmos, HuC6280, CE02, Sixteen)
|
||||
|
||||
@ -139,7 +149,7 @@ object Cpu extends Enumeration {
|
||||
VariableOverlap, CompactReturnDispatchParams
|
||||
)
|
||||
|
||||
private val i8080AlwaysDefaultFlags = Set(
|
||||
private val i80AlwaysDefaultFlags = Set(
|
||||
VariableOverlap, CompactReturnDispatchParams
|
||||
)
|
||||
|
||||
@ -161,11 +171,13 @@ object Cpu extends Enumeration {
|
||||
case Sixteen =>
|
||||
mosAlwaysDefaultFlags ++ Set(DecimalMode, EmitCmosOpcodes, EmitEmulation65816Opcodes, EmitNative65816Opcodes, ReturnWordsViaAccumulator)
|
||||
case Intel8080 =>
|
||||
i8080AlwaysDefaultFlags
|
||||
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes)
|
||||
case Z80 =>
|
||||
i8080AlwaysDefaultFlags ++ Set(EmitExtended80Opcodes, EmitZ80Opcodes, UseIxForStack)
|
||||
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, UseIxForStack)
|
||||
case EZ80 =>
|
||||
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, UseIxForStack, EmitEZ80Opcodes)
|
||||
case Sharp =>
|
||||
i8080AlwaysDefaultFlags ++ Set(EmitExtended80Opcodes, EmitSharpOpcodes)
|
||||
i80AlwaysDefaultFlags ++ Set(EmitExtended80Opcodes, EmitSharpOpcodes)
|
||||
}
|
||||
|
||||
def fromString(name: String): Cpu.Value = name match {
|
||||
@ -196,6 +208,15 @@ object Cpu extends Enumeration {
|
||||
case "strict2a03" => StrictRicoh
|
||||
case "strict2a07" => StrictRicoh
|
||||
case "z80" => Z80
|
||||
// disabled for now:
|
||||
// case "ez80" => EZ80
|
||||
// case "gameboy" => Sharp
|
||||
// case "gb" => Sharp
|
||||
// case "sharp" => Sharp
|
||||
// case "lr35902" => Sharp
|
||||
// case "8080" => Intel8080
|
||||
// case "i8080" => Intel8080
|
||||
// case "intel8080" => Intel8080
|
||||
case _ => ErrorReporting.fatal("Unknown CPU achitecture: " + name)
|
||||
}
|
||||
}
|
||||
@ -207,8 +228,8 @@ object CompilationFlag extends Enumeration {
|
||||
// compilation options for MOS:
|
||||
EmitCmosOpcodes, EmitCmosNopOpcodes, EmitHudsonOpcodes, Emit65CE02Opcodes, EmitEmulation65816Opcodes, EmitNative65816Opcodes,
|
||||
PreventJmpIndirectBug, LargeCode, ReturnWordsViaAccumulator,
|
||||
// compilation options for Z80
|
||||
EmitExtended80Opcodes, EmitZ80Opcodes, EmitSharpOpcodes, UseIxForStack,
|
||||
// compilation options for I80
|
||||
EmitIntel8080Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, EmitEZ80Opcodes, EmitSharpOpcodes, UseIxForStack,
|
||||
// optimization options:
|
||||
DangerousOptimizations, InlineFunctions, InterproceduralOptimization, OptimizeForSize, OptimizeForSpeed, OptimizeForSonicSpeed,
|
||||
// memory allocation options
|
||||
@ -233,7 +254,9 @@ object CompilationFlag extends Enumeration {
|
||||
"emit_65ce02" -> Emit65CE02Opcodes,
|
||||
"emit_huc6280" -> EmitHudsonOpcodes,
|
||||
"emit_z80" -> EmitZ80Opcodes,
|
||||
"emit_ez80" -> EmitEZ80Opcodes,
|
||||
"emit_x80" -> EmitExtended80Opcodes,
|
||||
"emit_8080" -> EmitIntel8080Opcodes,
|
||||
"emit_sharp" -> EmitSharpOpcodes,
|
||||
"ix_stack" -> UseIxForStack,
|
||||
"ipo" -> InterproceduralOptimization,
|
||||
|
@ -232,14 +232,18 @@ object Platform {
|
||||
def builtInCpuFeatures(cpu: Cpu.Value): Map[String, Long] = {
|
||||
Map[String, Long](
|
||||
"ARCH_6502" -> toLong(CpuFamily.forType(cpu) == CpuFamily.M6502),
|
||||
"ARCH_Z80" -> toLong(CpuFamily.forType(cpu) == CpuFamily.I80),
|
||||
"ARCH_I80" -> toLong(CpuFamily.forType(cpu) == CpuFamily.I80),
|
||||
"ARCH_Z80" -> toLong(cpu == Cpu.Z80 || cpu == Cpu.EZ80),
|
||||
"ARCH_X86" -> toLong(CpuFamily.forType(cpu) == CpuFamily.I86),
|
||||
"ARCH_6509" -> toLong(CpuFamily.forType(cpu) == CpuFamily.M6809),
|
||||
"ARCH_6500" -> toLong(CpuFamily.forType(cpu) == CpuFamily.M6800),
|
||||
"ARCH_ARM" -> toLong(CpuFamily.forType(cpu) == CpuFamily.ARM),
|
||||
"ARCH_68K" -> toLong(CpuFamily.forType(cpu) == CpuFamily.M68K),
|
||||
"HAS_HARDWARE_MULTIPLY" -> (CpuFamily.forType(cpu) match {
|
||||
case CpuFamily.M6502 | CpuFamily.I80 | CpuFamily.M6809 => 0L
|
||||
case CpuFamily.I86 | CpuFamily.ARM | CpuFamily.M68K => 1L
|
||||
"HAS_HARDWARE_MULTIPLY" -> (cpu match {
|
||||
case Cpu.EZ80 => 1L
|
||||
case _ => CpuFamily.forType(cpu) match {
|
||||
case CpuFamily.M6502 | CpuFamily.I80 | CpuFamily.M6800 => 0L
|
||||
case CpuFamily.I86 | CpuFamily.ARM | CpuFamily.M68K => 1L
|
||||
}
|
||||
})
|
||||
// TODO
|
||||
)
|
||||
|
@ -1,6 +1,8 @@
|
||||
package millfork.assembly.z80
|
||||
|
||||
import millfork.CompilationFlag
|
||||
import millfork.assembly.AbstractCode
|
||||
import millfork.compiler.CompilationContext
|
||||
import millfork.env.{Constant, Label, NumericConstant, ThingInMemory}
|
||||
import millfork.node.ZRegister
|
||||
|
||||
@ -89,17 +91,21 @@ object ZLine {
|
||||
|
||||
def jump(label: Label, condition: ZRegisters): ZLine = ZLine(JP, condition, label.toAddress)
|
||||
|
||||
def jumpR(label: String): ZLine = ZLine(JR, NoRegisters, Label(label).toAddress)
|
||||
def jumpR(ctx: CompilationContext, label: String): ZLine = ZLine(if (ctx.options.flag(CompilationFlag.EmitExtended80Opcodes)) JR else JP, NoRegisters, Label(label).toAddress)
|
||||
|
||||
def jumpR(label: Label): ZLine = ZLine(JR, NoRegisters, label.toAddress)
|
||||
def jumpR(ctx: CompilationContext, label: Label): ZLine = ZLine(if (ctx.options.flag(CompilationFlag.EmitExtended80Opcodes)) JR else JP, NoRegisters, label.toAddress)
|
||||
|
||||
def jumpR(label: String, condition: ZRegisters): ZLine = ZLine(JR, condition, Label(label).toAddress)
|
||||
def jumpR(ctx: CompilationContext, label: String, condition: ZRegisters): ZLine = ZLine(if (ctx.options.flag(CompilationFlag.EmitExtended80Opcodes)) JR else JP, condition, Label(label).toAddress)
|
||||
|
||||
def jumpR(label: Label, condition: ZRegisters): ZLine = ZLine(JR, condition, label.toAddress)
|
||||
def jumpR(ctx: CompilationContext, label: Label, condition: ZRegisters): ZLine = ZLine(if (ctx.options.flag(CompilationFlag.EmitExtended80Opcodes)) JR else JP, condition, label.toAddress)
|
||||
|
||||
def djnz(label: String): ZLine = ZLine(DJNZ, NoRegisters, Label(label).toAddress)
|
||||
def djnz(ctx: CompilationContext, label: String): List[ZLine] =
|
||||
if (ctx.options.flag(CompilationFlag.EmitZ80Opcodes)) List(ZLine(DJNZ, NoRegisters, Label(label).toAddress))
|
||||
else List(ZLine.register(DEC, ZRegister.B), ZLine.jumpR(ctx, label, IfFlagClear(ZFlag.Z)))
|
||||
|
||||
def djnz(label: Label): ZLine = ZLine(DJNZ, NoRegisters, label.toAddress)
|
||||
def djnz(ctx: CompilationContext, label: Label): List[ZLine] =
|
||||
if (ctx.options.flag(CompilationFlag.EmitZ80Opcodes)) List(ZLine(DJNZ, NoRegisters, label.toAddress))
|
||||
else List(ZLine.register(DEC, ZRegister.B), ZLine.jumpR(ctx, label, IfFlagClear(ZFlag.Z)))
|
||||
|
||||
def implied(opcode: ZOpcode.Value): ZLine = ZLine(opcode, NoRegisters, Constant.Zero)
|
||||
|
||||
|
@ -22,6 +22,8 @@ object ZOpcode extends Enumeration {
|
||||
EXX, EX_DE_HL, EX_AF_AF, EX_SP,
|
||||
RST, IM, EI, DI,
|
||||
DJNZ, JP, JR, CALL, RET, RETN, RETI, HALT,
|
||||
//sharp:
|
||||
LD_AHLI, LD_AHLD, LD_HLIA, LD_HLDA, SWAP, LD_H,
|
||||
DISCARD_A, DISCARD_F, DISCARD_HL, DISCARD_BCDEIX,
|
||||
LABEL, BYTE = Value
|
||||
}
|
||||
|
@ -462,6 +462,12 @@ object AlwaysGoodZ80Optimizations {
|
||||
ZLine.registers(code.last.opcode, ZRegister.HL, ZRegister.DE) :: code.take(2)
|
||||
},
|
||||
|
||||
(Elidable & HasOpcode(INC) & HasRegisterParam(ZRegister.A)) ~
|
||||
(Elidable & HasOpcode(ADD) & Has8BitImmediate(0xff) & DoesntMatterWhatItDoesWithFlags) ~~> (_ => Nil),
|
||||
|
||||
(Elidable & HasOpcode(NEG)) ~
|
||||
(Elidable & HasOpcode(ADD) & Has8BitImmediate(0xff) & DoesntMatterWhatItDoesWithFlags) ~~> (_ => List(ZLine.implied(CPL))),
|
||||
|
||||
)
|
||||
|
||||
val FreeHL = new RuleBasedAssemblyOptimization("Free HL",
|
||||
|
@ -353,10 +353,7 @@ object Z80BulkMemoryOperations {
|
||||
List(ZLine.implied(ldr.get))
|
||||
} else {
|
||||
ZLine.label(label) :: calculateSourceValue ++ (if (smallCount) {
|
||||
List(
|
||||
ZLine.register(next, if (useDEForTarget) ZRegister.DE else ZRegister.HL),
|
||||
ZLine.djnz(label)
|
||||
)
|
||||
ZLine.register(next, if (useDEForTarget) ZRegister.DE else ZRegister.HL) :: ZLine.djnz(ctx, label)
|
||||
} else {
|
||||
List(
|
||||
ZLine.register(next, if (useDEForTarget) ZRegister.DE else ZRegister.HL),
|
||||
|
@ -210,6 +210,16 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
case 1 => targetifyA(target, ZBuiltIns.compile8BitSum(ctx, params, decimal), isSigned = false)
|
||||
case 2 => targetifyHL(target, ZBuiltIns.compile16BitSum(ctx, params, decimal))
|
||||
}
|
||||
case SeparateBytesExpression(h, l) =>
|
||||
val hi = compileToA(ctx, h)
|
||||
val lo = compileToA(ctx, l)
|
||||
if (!lo.exists(x => x.changesRegister(ZRegister.H) || x.readsRegister(ZRegister.H))) {
|
||||
hi ++ List(ZLine.ld8(ZRegister.H, ZRegister.A)) ++
|
||||
lo ++ List(ZLine.ld8(ZRegister.L, ZRegister.A))
|
||||
} else if (!hi.exists(x => x.changesRegister(ZRegister.L) || x.readsRegister(ZRegister.L))) {
|
||||
lo ++ List(ZLine.ld8(ZRegister.L, ZRegister.A)) ++
|
||||
hi ++ List(ZLine.ld8(ZRegister.H, ZRegister.A))
|
||||
} else ???
|
||||
case f@FunctionCallExpression(name, params) =>
|
||||
name match {
|
||||
case "not" =>
|
||||
@ -423,20 +433,19 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
case 1 => ZBuiltIns.perform8BitInPlace(ctx, l, r, SUB, decimal = true)
|
||||
case _ => ZBuiltIns.performLongInPlace(ctx, l, r, SUB, SBC, size, decimal = true)
|
||||
}
|
||||
Nil
|
||||
case "<<=" =>
|
||||
val (l, r, size) = assertArithmeticAssignmentLike(ctx, params)
|
||||
size match {
|
||||
case 1 => Z80Shifting.compile8BitShiftInPlace(ctx, l, r, left = true)
|
||||
case 2 => Z80Shifting.compile16BitShift(ctx, l, r, left = true) ++ storeHL(ctx, l, signedSource = false)
|
||||
case _ => ???
|
||||
case _ => Z80Shifting.compileLongShiftInPlace(ctx, l, r, size, left = true)
|
||||
}
|
||||
case ">>=" =>
|
||||
val (l, r, size) = assertArithmeticAssignmentLike(ctx, params)
|
||||
size match {
|
||||
case 1 => Z80Shifting.compile8BitShiftInPlace(ctx, l, r, left = false)
|
||||
case 2 => Z80Shifting.compile16BitShift(ctx, l, r, left = false) ++ storeHL(ctx, l, signedSource = false)
|
||||
case _ => ???
|
||||
case _ => Z80Shifting.compileLongShiftInPlace(ctx, l, r, size, left = false)
|
||||
}
|
||||
case "<<'=" =>
|
||||
val (l, r, size) = assertArithmeticAssignmentLike(ctx, params)
|
||||
|
@ -13,7 +13,7 @@ object Z80Multiply {
|
||||
/**
|
||||
* Compiles A = A * D
|
||||
*/
|
||||
private def multiplication(): List[ZLine] = {
|
||||
private def multiplication(ctx: CompilationContext): List[ZLine] = {
|
||||
import millfork.assembly.z80.ZOpcode._
|
||||
import ZRegister._
|
||||
import ZLine._
|
||||
@ -23,15 +23,15 @@ object Z80Multiply {
|
||||
List(
|
||||
ld8(E, A),
|
||||
ldImm8(A, 0),
|
||||
jumpR(lblStart),
|
||||
jumpR(ctx, lblStart),
|
||||
label(lblAdd),
|
||||
register(ADD, E),
|
||||
label(lblLoop),
|
||||
register(SLA, E),
|
||||
label(lblStart),
|
||||
register(SRL, D),
|
||||
jumpR(lblAdd, IfFlagSet(ZFlag.C)),
|
||||
jumpR(lblLoop, IfFlagClear(ZFlag.Z)))
|
||||
jumpR(ctx, lblAdd, IfFlagSet(ZFlag.C)),
|
||||
jumpR(ctx, lblLoop, IfFlagClear(ZFlag.Z)))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,7 +81,7 @@ object Z80Multiply {
|
||||
} else {
|
||||
rb ++ List(ZLine.ld8(ZRegister.D, ZRegister.A)) ++ lb
|
||||
}
|
||||
load ++ multiplication()
|
||||
load ++ multiplication(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,7 +95,7 @@ object Z80Multiply {
|
||||
load ++ compile8BitMultiply(count.toInt) ++ store
|
||||
case Some(c) =>
|
||||
val (load, store) = Z80ExpressionCompiler.calculateLoadAndStoreForByte(ctx, l)
|
||||
load ++ List(ZLine.ldImm8(ZRegister.D, c)) ++ multiplication() ++ store
|
||||
load ++ List(ZLine.ldImm8(ZRegister.D, c)) ++ multiplication(ctx) ++ store
|
||||
case _ =>
|
||||
val (load, store) = Z80ExpressionCompiler.calculateLoadAndStoreForByte(ctx, l)
|
||||
val rb = Z80ExpressionCompiler.compileToA(ctx, r)
|
||||
@ -104,7 +104,7 @@ object Z80Multiply {
|
||||
} else {
|
||||
rb ++ List(ZLine.ld8(ZRegister.D, ZRegister.A)) ++ load
|
||||
}
|
||||
loadRegisters ++ multiplication() ++ store
|
||||
loadRegisters ++ multiplication(ctx) ++ store
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ object Z80Shifting {
|
||||
if (extendedOps) {
|
||||
if (left) ZOpcode.SLA else ZOpcode.SRL
|
||||
} else {
|
||||
if (left) ZOpcode.RL else ZOpcode.RR
|
||||
if (left) ZOpcode.RLC else ZOpcode.RRC
|
||||
}
|
||||
val l = Z80ExpressionCompiler.compileToA(ctx, lhs)
|
||||
env.eval(rhs) match {
|
||||
@ -47,7 +47,7 @@ object Z80Shifting {
|
||||
val l = Z80ExpressionCompiler.stashBCIfChanged(Z80ExpressionCompiler.compileToA(ctx, lhs))
|
||||
val loopBody = ZLine.register(op, ZRegister.A) :: fixAfterShiftIfNeeded(extendedOps, left, 1)
|
||||
val label = Z80Compiler.nextLabel("sh")
|
||||
calcCount ++ l ++ List(ZLine.label(label)) ++ loopBody :+ ZLine.djnz(label)
|
||||
calcCount ++ l ++ List(ZLine.label(label)) ++ loopBody ++ ZLine.djnz(ctx, label)
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ object Z80Shifting {
|
||||
if (extendedOps) {
|
||||
if (left) ZOpcode.SLA else ZOpcode.SRL
|
||||
} else {
|
||||
if (left) ZOpcode.RL else ZOpcode.RR
|
||||
if (left) ZOpcode.RLC else ZOpcode.RRC
|
||||
}
|
||||
env.eval(rhs) match {
|
||||
case Some(NumericConstant(i, _)) =>
|
||||
@ -101,7 +101,7 @@ object Z80Shifting {
|
||||
val l = Z80ExpressionCompiler.stashBCIfChanged(Z80ExpressionCompiler.compileToA(ctx, lhs))
|
||||
val loopBody = ZLine.register(op, ZRegister.A) :: fixAfterShiftIfNeeded(extendedOps, left, 1)
|
||||
val label = Z80Compiler.nextLabel("sh")
|
||||
calcCount ++ l ++ List(ZLine.label(label)) ++ loopBody ++ List(ZLine.djnz(label)) ++ Z80ExpressionCompiler.storeA(ctx, lhs, signedSource = false)
|
||||
calcCount ++ l ++ List(ZLine.label(label)) ++ loopBody ++ ZLine.djnz(ctx, label) ++ Z80ExpressionCompiler.storeA(ctx, lhs, signedSource = false)
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,13 +182,14 @@ object Z80Shifting {
|
||||
}
|
||||
}
|
||||
val label = Z80Compiler.nextLabel("sh")
|
||||
calcCount ++ l ++ List(ZLine.label(label)) ++ loopBody :+ ZLine.djnz(label)
|
||||
calcCount ++ l ++ List(ZLine.label(label)) ++ loopBody ++ ZLine.djnz(ctx, label)
|
||||
}
|
||||
}
|
||||
|
||||
def compileNonetShiftRight(ctx: CompilationContext, rhs: Expression): List[ZLine] = {
|
||||
import ZOpcode._
|
||||
import ZRegister._
|
||||
val extended = ctx.options.flag(CompilationFlag.EmitExtended80Opcodes)
|
||||
ctx.env.eval(rhs) match {
|
||||
case Some(NumericConstant(0, _)) =>
|
||||
List(ZLine.ld8(A, L))
|
||||
@ -198,11 +199,17 @@ object Z80Shifting {
|
||||
case Some(NumericConstant(n, _)) if n >= 9 =>
|
||||
List(ZLine.ldImm8(A, 0))
|
||||
case Some(NumericConstant(1, _)) =>
|
||||
List(ZLine.register(SRL, H), ZLine.ld8(A, L), ZLine.register(RR, A))
|
||||
case Some(NumericConstant(2, _)) =>
|
||||
List(ZLine.register(SRL, H), ZLine.ld8(A, L), ZLine.register(RR, A), ZLine.register(SRL, A))
|
||||
if (extended)
|
||||
List(ZLine.register(SRL, H), ZLine.ld8(A, L), ZLine.register(RR, A))
|
||||
else
|
||||
List(ZLine.ld8(A, H), ZLine.register(RR, A), ZLine.ld8(A, L), ZLine.register(RR, A))
|
||||
case Some(NumericConstant(2, _)) if extended=>
|
||||
List(ZLine.register(SRL, H), ZLine.ld8(A, L), ZLine.register(RR, A), ZLine.register(SRL, A))
|
||||
case Some(NumericConstant(n, _)) =>
|
||||
List(ZLine.register(SRL, H), ZLine.ld8(A, L)) ++ (List.fill(n.toInt)(ZLine.register(RR, A)) :+ ZLine.imm8(AND, 0x1ff >> n))
|
||||
if (extended)
|
||||
List(ZLine.register(SRL, H), ZLine.ld8(A, L)) ++ (List.fill(n.toInt)(ZLine.register(RR, A)) :+ ZLine.imm8(AND, 0x1ff >> n))
|
||||
else
|
||||
List(ZLine.ld8(A, H), ZLine.register(RR, A), ZLine.ld8(A, L)) ++ (List.fill(n.toInt)(ZLine.register(RR, A)) :+ ZLine.imm8(AND, 0x1ff >> n))
|
||||
|
||||
case _ =>
|
||||
ErrorReporting.error("Non-constant shift amount", rhs.position) // TODO
|
||||
@ -210,4 +217,45 @@ object Z80Shifting {
|
||||
}
|
||||
}
|
||||
|
||||
def compileLongShiftInPlace(ctx: CompilationContext, lhs: LhsExpression, rhs: Expression, size: Int, left: Boolean): List[ZLine] = {
|
||||
val extended = ctx.options.flag(CompilationFlag.EmitExtended80Opcodes)
|
||||
val store = Z80ExpressionCompiler.compileByteStores(ctx, lhs, size)
|
||||
val loadLeft = Z80ExpressionCompiler.compileByteReads(ctx, lhs, size, ZExpressionTarget.HL)
|
||||
val shiftOne = if (left) {
|
||||
loadLeft.zip(store).zipWithIndex.flatMap {
|
||||
case ((ld, st), ix) =>
|
||||
import ZOpcode._
|
||||
import ZRegister._
|
||||
val shiftByte = if (ix == 0) {
|
||||
if (extended) List(ZLine.register(SLA, A))
|
||||
else List(ZLine.register(RL, A), ZLine.imm8(AND, 0xfe))
|
||||
} else List(ZLine.register(RL, A))
|
||||
ld ++ shiftByte ++ st
|
||||
}
|
||||
} else {
|
||||
loadLeft.reverse.zip(store.reverse).zipWithIndex.flatMap {
|
||||
case ((ld, st), ix) =>
|
||||
import ZOpcode._
|
||||
import ZRegister._
|
||||
val shiftByte = if (ix == 0) {
|
||||
if (extended) List(ZLine.register(SRL, A))
|
||||
else List(ZLine.register(RR, A), ZLine.imm8(AND, 0x7f))
|
||||
} else List(ZLine.register(RR, A))
|
||||
ld ++ shiftByte ++ st
|
||||
}
|
||||
}
|
||||
ctx.env.eval(rhs) match {
|
||||
case Some(NumericConstant(0, _)) => Nil
|
||||
case Some(NumericConstant(n, _)) if n < 0 =>
|
||||
ErrorReporting.error("Negative shift amount", rhs.position) // TODO
|
||||
Nil
|
||||
case Some(NumericConstant(n, _)) =>
|
||||
List.fill(n.toInt)(shiftOne).flatten
|
||||
case _ =>
|
||||
val label = Z80Compiler.nextLabel("sh")
|
||||
val calcCount = Z80ExpressionCompiler.compileToA(ctx, rhs) :+ ZLine.ld8(ZRegister.B, ZRegister.A)
|
||||
calcCount ++ List(ZLine.label(label)) ++ shiftOne ++ ZLine.djnz(ctx, label)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -120,6 +120,7 @@ object ZBuiltIns {
|
||||
ctx.env.eval(expr) match {
|
||||
case None =>
|
||||
if (result.isEmpty) {
|
||||
if (decimal) ???
|
||||
result ++= Z80ExpressionCompiler.compileToA(ctx, expr)
|
||||
if (ctx.options.flag(CompilationFlag.EmitExtended80Opcodes)) {
|
||||
result += ZLine.implied(NEG)
|
||||
@ -148,9 +149,19 @@ object ZBuiltIns {
|
||||
}
|
||||
}
|
||||
if (hasConst) {
|
||||
result += ZLine.imm8(ADD, const.loByte)
|
||||
if (decimal) {
|
||||
result += ZLine.implied(DAA)
|
||||
const match {
|
||||
case CompoundConstant(MathOperator.DecimalMinus | MathOperator.Minus, NumericConstant(0, _), c) =>
|
||||
result += ZLine.imm8(SUB, c.loByte)
|
||||
if (decimal) {
|
||||
result += ZLine.implied(DAA)
|
||||
}
|
||||
case NumericConstant(n, _) if n < 0 && !decimal =>
|
||||
result += ZLine.imm8(SUB, (-n.toInt) & 0xff)
|
||||
case _ =>
|
||||
result += ZLine.imm8(ADD, const.loByte)
|
||||
if (decimal) {
|
||||
result += ZLine.implied(DAA)
|
||||
}
|
||||
}
|
||||
}
|
||||
result.toList
|
||||
|
@ -30,6 +30,6 @@ class MemoryBank {
|
||||
var end: Int = 0
|
||||
|
||||
def dump(startAddr: Int, count: Int)(dumper: String => Any): Unit = {
|
||||
(0 until count).map(i => output(i + startAddr)).grouped(16).zipWithIndex.map { case (c, i) => f"$i%04X: " + c.map(i => f"$i%02x").mkString(" ") }.foreach(dumper)
|
||||
(0 until count).map(i => (i + startAddr) -> output(i + startAddr)).grouped(16).zipWithIndex.map { case (c, i) => f"${c.head._1}%04X: " + c.map(i => f"${i._2}%02x").mkString(" ") }.foreach(dumper)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package millfork.output
|
||||
|
||||
import millfork.{CompilationOptions, Platform}
|
||||
import millfork.{CompilationFlag, CompilationOptions, Cpu, Platform}
|
||||
import millfork.assembly.z80._
|
||||
import millfork.compiler.z80.Z80Compiler
|
||||
import millfork.env._
|
||||
@ -44,6 +44,25 @@ class Z80Assembler(program: Program,
|
||||
import millfork.assembly.z80.ZOpcode._
|
||||
import ZRegister._
|
||||
import Z80Assembler._
|
||||
import CompilationFlag._
|
||||
def requireIntel8080(): Unit = if (!options.flag(EmitIntel8080Opcodes)) ErrorReporting.error("Unsupported instruction: " + instr)
|
||||
|
||||
def requireZ80(): Unit = if (!options.flag(EmitZ80Opcodes)) ErrorReporting.error("Unsupported instruction: " + instr)
|
||||
|
||||
def requireZ80Illegals(): Unit = if (!options.flag(EmitZ80Opcodes) || !options.flag(EmitIllegals)) ErrorReporting.error("Unsupported instruction: " + instr)
|
||||
|
||||
def requireExtended80(): Unit = if (!options.flag(EmitExtended80Opcodes)) ErrorReporting.error("Unsupported instruction: " + instr)
|
||||
|
||||
def requireSharp(): Unit = if (!options.flag(EmitSharpOpcodes)) ErrorReporting.error("Unsupported instruction: " + instr)
|
||||
|
||||
def requireEZ80(): Unit = if (!options.flag(EmitEZ80Opcodes)) ErrorReporting.error("Unsupported instruction: " + instr)
|
||||
|
||||
def useSharpOpcodes():Boolean = {
|
||||
if (!options.flag(EmitSharpOpcodes) && !options.flag(EmitIntel8080Opcodes))
|
||||
ErrorReporting.error("Cannot determine which variant to emit : " + instr)
|
||||
options.flag(EmitSharpOpcodes)
|
||||
}
|
||||
|
||||
instr match {
|
||||
case ZLine(LABEL, NoRegisters, MemoryAddressConstant(Label(labelName)), _) =>
|
||||
labelMap(labelName) = index
|
||||
@ -63,6 +82,7 @@ class Z80Assembler(program: Program,
|
||||
writeByte(bank, index, opcode)
|
||||
index + 1
|
||||
case ZLine(IM, NoRegisters, param, _) =>
|
||||
requireZ80()
|
||||
val opcode = param.quickSimplify match {
|
||||
case NumericConstant(0, _) => 0x46
|
||||
case NumericConstant(1, _) => 0x56
|
||||
@ -73,13 +93,33 @@ class Z80Assembler(program: Program,
|
||||
writeByte(bank, index + 1, opcode)
|
||||
index + 2
|
||||
case ZLine(op, OneRegister(reg), _, _) if ZOpcodeClasses.AllSingleBit(op) =>
|
||||
requireExtended80()
|
||||
writeByte(bank, index, 0xcb)
|
||||
writeByte(bank, index + 1, ZOpcodeClasses.singleBitOpcode(op) + internalRegisterIndex(reg))
|
||||
index + 2
|
||||
case ZLine(op, NoRegisters, _, _) if implieds.contains(op) =>
|
||||
writeByte(bank, index, implieds(op))
|
||||
index + 1
|
||||
case ZLine(EXX, NoRegisters, _, _)=>
|
||||
requireZ80()
|
||||
writeByte(bank, index, 0xd9)
|
||||
index + 1
|
||||
case ZLine(EX_AF_AF, NoRegisters, _, _)=>
|
||||
requireZ80()
|
||||
writeByte(bank, index, 8)
|
||||
index + 1
|
||||
case ZLine(RETI, NoRegisters, _, _) =>
|
||||
requireExtended80()
|
||||
if (useSharpOpcodes()) {
|
||||
writeByte(bank, index, 0xd9)
|
||||
index + 1
|
||||
} else {
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index + 1, 0x4d)
|
||||
index + 2
|
||||
}
|
||||
case ZLine(op, NoRegisters, _, _) if edImplieds.contains(op) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index + 1, edImplieds(op))
|
||||
index + 2
|
||||
@ -87,6 +127,7 @@ class Z80Assembler(program: Program,
|
||||
writeByte(bank, index, 9 + 16 * internalRegisterIndex(source))
|
||||
index + 1
|
||||
case ZLine(ADD_16, TwoRegisters(ix@(ZRegister.IX | ZRegister.IY), source@(ZRegister.IX | ZRegister.IY)), _, _)=>
|
||||
requireZ80()
|
||||
if (ix == source) {
|
||||
writeByte(bank, index, prefixByte(ix))
|
||||
writeByte(bank, index + 1, 9 + 16 * internalRegisterIndex(HL))
|
||||
@ -96,6 +137,7 @@ class Z80Assembler(program: Program,
|
||||
index
|
||||
}
|
||||
case ZLine(ADD_16, TwoRegisters(ix@(ZRegister.IX | ZRegister.IY), source), _, _) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, prefixByte(ix))
|
||||
writeByte(bank, index + 1, 9 + 16 * internalRegisterIndex(source))
|
||||
index + 2
|
||||
@ -108,6 +150,7 @@ class Z80Assembler(program: Program,
|
||||
writeByte(bank, index + 1, 0x42 + 0x10 * internalRegisterIndex(reg))
|
||||
index + 2
|
||||
case ZLine(LD_16, TwoRegisters(ix@(ZRegister.IX | ZRegister.IY), ZRegister.IMM_16), param, _) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, prefixByte(ix))
|
||||
writeByte(bank, index + 1, 0x21)
|
||||
writeWord(bank, index + 2, param)
|
||||
@ -117,29 +160,47 @@ class Z80Assembler(program: Program,
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
case ZLine(LD_16, TwoRegisters(ix@(ZRegister.IX | ZRegister.IY), ZRegister.MEM_ABS_16), param, _) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, prefixByte(ix))
|
||||
writeByte(bank, index + 1, 0x2a)
|
||||
writeWord(bank, index + 2, param)
|
||||
index + 4
|
||||
case ZLine(LD_16, TwoRegisters(ZRegister.MEM_ABS_16, ix@(ZRegister.IX | ZRegister.IY)), param, _) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, prefixByte(ix))
|
||||
writeByte(bank, index + 1, 0x22)
|
||||
writeWord(bank, index + 2, param)
|
||||
index + 4
|
||||
case ZLine(LD_16, TwoRegisters(ZRegister.HL, ZRegister.MEM_ABS_16), param, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0x2a)
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
case ZLine(LD_16, TwoRegisters(ZRegister.MEM_ABS_16, ZRegister.HL), param, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0x22)
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
case ZLine(LD_16, TwoRegisters(reg@(ZRegister.BC | ZRegister.DE | ZRegister.SP), ZRegister.MEM_ABS_16), param, _) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index+1, 0x4b + 0x10 * internalRegisterIndex(reg))
|
||||
writeWord(bank, index + 2, param)
|
||||
index + 4
|
||||
case ZLine(LD_16, TwoRegisters(ZRegister.MEM_ABS_16, reg@(ZRegister.BC | ZRegister.DE | ZRegister.SP)), param, _) =>
|
||||
case ZLine(LD_16, TwoRegisters(ZRegister.MEM_ABS_16, ZRegister.SP), param, _) =>
|
||||
requireExtended80()
|
||||
if (useSharpOpcodes()) {
|
||||
writeByte(bank, index, 8)
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
} else {
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index + 1, 0x43 + 0x10 * internalRegisterIndex(SP))
|
||||
writeWord(bank, index + 2, param)
|
||||
index + 4
|
||||
}
|
||||
case ZLine(LD_16, TwoRegisters(ZRegister.MEM_ABS_16, reg@(ZRegister.BC | ZRegister.DE)), param, _) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index+1, 0x43 + 0x10 * internalRegisterIndex(reg))
|
||||
writeWord(bank, index + 2, param)
|
||||
@ -148,6 +209,7 @@ class Z80Assembler(program: Program,
|
||||
writeByte(bank, index, 0xF9)
|
||||
index + 1
|
||||
case ZLine(LD_16, TwoRegisters(ZRegister.SP, ix@(ZRegister.IX | ZRegister.IY)), _, _) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, prefixByte(ix))
|
||||
writeByte(bank, index + 1, 0xF9)
|
||||
index + 2
|
||||
@ -157,18 +219,21 @@ class Z80Assembler(program: Program,
|
||||
writeByte(bank, index + 1, param)
|
||||
index + 2
|
||||
case ZLine(op, OneRegisterOffset(ix@(ZRegister.MEM_IX_D | ZRegister.MEM_IY_D), offset), _, _) if ZOpcodeClasses.AllSingleBit(op) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, prefixByte(ix))
|
||||
writeByte(bank, index + 1, 0xcb)
|
||||
writeByte(bank, index + 2, offset)
|
||||
writeByte(bank, index + 3, ZOpcodeClasses.singleBitOpcode(op) + internalRegisterIndex(ZRegister.MEM_HL))
|
||||
index + 4
|
||||
case ZLine(op, OneRegisterOffset(ix@(ZRegister.MEM_IX_D | ZRegister.MEM_IY_D), offset), _, _) if oneRegister.contains(op) =>
|
||||
requireZ80()
|
||||
val o = oneRegister(op)
|
||||
writeByte(bank, index, prefixByte(ix))
|
||||
writeByte(bank, index + 1, o.opcode + internalRegisterIndex(ZRegister.MEM_HL) * o.multiplier)
|
||||
writeByte(bank, index + 2, offset)
|
||||
index + 3
|
||||
case ZLine(op, OneRegister(ix@(ZRegister.IX | ZRegister.IY)), _, _) if oneRegister.contains(op) =>
|
||||
requireZ80()
|
||||
val o = oneRegister(op)
|
||||
writeByte(bank, index, prefixByte(ix))
|
||||
writeByte(bank, index + 1, o.opcode + internalRegisterIndex(ZRegister.HL) * o.multiplier)
|
||||
@ -181,12 +246,31 @@ class Z80Assembler(program: Program,
|
||||
case ZLine(op@(RR|RRC|RL|RLC), OneRegister(A), _, _) =>
|
||||
writeByte(bank, index, cbOneRegister(op).opcode + 7)
|
||||
index + 1
|
||||
case ZLine(SLL, OneRegister(reg), _, _) =>
|
||||
requireZ80Illegals()
|
||||
writeByte(bank, index, 0xcb)
|
||||
writeByte(bank, index + 1, 0x30 + internalRegisterIndex(reg))
|
||||
index + 2
|
||||
case ZLine(SWAP, OneRegister(reg), _, _) =>
|
||||
requireSharp()
|
||||
writeByte(bank, index, 0xcb)
|
||||
writeByte(bank, index + 1, 0x30 + internalRegisterIndex(reg))
|
||||
index + 2
|
||||
case ZLine(SLL, OneRegisterOffset(ix@(ZRegister.MEM_IX_D | ZRegister.MEM_IY_D), offset), _, _) =>
|
||||
requireZ80Illegals()
|
||||
writeByte(bank, index, prefixByte(ix))
|
||||
writeByte(bank, index + 1, 0xcb)
|
||||
writeByte(bank, index + 2, offset)
|
||||
writeByte(bank, index + 3, 0x30 + internalRegisterIndex(MEM_HL))
|
||||
index + 4
|
||||
case ZLine(op, OneRegister(reg), _, _) if cbOneRegister.contains(op) =>
|
||||
requireExtended80()
|
||||
val o = cbOneRegister(op)
|
||||
writeByte(bank, index, 0xcb)
|
||||
writeByte(bank, index + 1, o.opcode + internalRegisterIndex(reg) * o.multiplier)
|
||||
index + 2
|
||||
case ZLine(op, OneRegisterOffset(ix@(ZRegister.MEM_IX_D | ZRegister.MEM_IY_D), offset), _, _) if cbOneRegister.contains(op) =>
|
||||
requireZ80()
|
||||
val o = cbOneRegister(op)
|
||||
writeByte(bank, index, prefixByte(ix))
|
||||
writeByte(bank, index + 1, 0xcb)
|
||||
@ -196,18 +280,22 @@ class Z80Assembler(program: Program,
|
||||
case ZLine(LD, registers, _, _) =>
|
||||
registers match {
|
||||
case TwoRegisters(I, A) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index + 1, 0x47)
|
||||
index + 2
|
||||
case TwoRegisters(A, I) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index + 1, 0x57)
|
||||
index + 2
|
||||
case TwoRegisters(R, A) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index + 1, 0x4f)
|
||||
index + 2
|
||||
case TwoRegisters(A, R) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index + 1, 0x5f)
|
||||
index + 2
|
||||
@ -219,17 +307,26 @@ class Z80Assembler(program: Program,
|
||||
writeByte(bank, index + 1, instr.parameter)
|
||||
index + 2
|
||||
case TwoRegistersOffset(ix@(ZRegister.MEM_IX_D | ZRegister.MEM_IY_D), ZRegister.IMM_8, offset) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, prefixByte(ix))
|
||||
writeByte(bank, index + 1, 0x36)
|
||||
writeByte(bank, index + 2, offset)
|
||||
writeByte(bank, index + 3, instr.parameter)
|
||||
index + 4
|
||||
case TwoRegisters(ZRegister.A, ZRegister.MEM_ABS_8) =>
|
||||
writeByte(bank, index, 0x3a)
|
||||
if (useSharpOpcodes()) {
|
||||
writeByte(bank, index, 0xfa)
|
||||
} else {
|
||||
writeByte(bank, index, 0x3a)
|
||||
}
|
||||
writeWord(bank, index + 1, instr.parameter)
|
||||
index + 3
|
||||
case TwoRegisters(ZRegister.MEM_ABS_8, ZRegister.A) =>
|
||||
writeByte(bank, index, 0x32)
|
||||
if (useSharpOpcodes()) {
|
||||
writeByte(bank, index, 0xea)
|
||||
} else {
|
||||
writeByte(bank, index, 0x32)
|
||||
}
|
||||
writeWord(bank, index + 1, instr.parameter)
|
||||
index + 3
|
||||
case TwoRegisters(ZRegister.MEM_BC, ZRegister.A) =>
|
||||
@ -262,18 +359,22 @@ class Z80Assembler(program: Program,
|
||||
index + 1
|
||||
}
|
||||
case ZLine(IN_IMM, OneRegister(ZRegister.A), param, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xdb)
|
||||
writeByte(bank, index + 1, param)
|
||||
index + 2
|
||||
case ZLine(IN_C, OneRegister(reg), param, _) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index + 1, 0x40 + 8 * internalRegisterIndex(reg))
|
||||
index + 2
|
||||
case ZLine(OUT_IMM, OneRegister(ZRegister.A), param, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xd3)
|
||||
writeByte(bank, index + 1, param)
|
||||
index + 2
|
||||
case ZLine(OUT_C, OneRegister(reg), param, _) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index + 1, 0x41 + 8 * internalRegisterIndex(reg))
|
||||
index + 2
|
||||
@ -286,35 +387,43 @@ class Z80Assembler(program: Program,
|
||||
|
||||
|
||||
case ZLine(CALL, IfFlagClear(ZFlag.Z), param, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xc4)
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
case ZLine(CALL, IfFlagClear(ZFlag.C), param, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xd4)
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
case ZLine(CALL, IfFlagClear(ZFlag.P), param, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xe4)
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
case ZLine(CALL, IfFlagClear(ZFlag.S), param, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xf4)
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
|
||||
case ZLine(CALL, IfFlagSet(ZFlag.Z), param, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xcc)
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
case ZLine(CALL, IfFlagSet(ZFlag.C), param, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xdc)
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
case ZLine(CALL, IfFlagSet(ZFlag.P), param, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xec)
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
case ZLine(CALL, IfFlagSet(ZFlag.S), param, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xfc)
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
@ -333,10 +442,12 @@ class Z80Assembler(program: Program,
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
case ZLine(JP, IfFlagClear(ZFlag.P), param, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xe2)
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
case ZLine(JP, IfFlagClear(ZFlag.S), param, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xf2)
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
@ -350,10 +461,12 @@ class Z80Assembler(program: Program,
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
case ZLine(JP, IfFlagSet(ZFlag.P), param, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xea)
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
case ZLine(JP, IfFlagSet(ZFlag.S), param, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xfa)
|
||||
writeWord(bank, index + 1, param)
|
||||
index + 3
|
||||
@ -361,78 +474,98 @@ class Z80Assembler(program: Program,
|
||||
writeByte(bank, index, 0xe9)
|
||||
index + 1
|
||||
case ZLine(JP, OneRegister(IX), _, _) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, 0xdd)
|
||||
writeByte(bank, index, 0xe9)
|
||||
index + 2
|
||||
case ZLine(JP, OneRegister(IY), _, _) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, 0xfd)
|
||||
writeByte(bank, index, 0xe9)
|
||||
index + 2
|
||||
|
||||
case ZLine(RET, IfFlagClear(ZFlag.Z), _, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xc0)
|
||||
index + 1
|
||||
case ZLine(RET, IfFlagClear(ZFlag.C), _, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xd0)
|
||||
index + 1
|
||||
case ZLine(RET, IfFlagClear(ZFlag.P), _, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xe0)
|
||||
index + 1
|
||||
case ZLine(RET, IfFlagClear(ZFlag.S), _, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xf0)
|
||||
index + 1
|
||||
|
||||
case ZLine(RET, IfFlagSet(ZFlag.Z), _, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xc8)
|
||||
index + 1
|
||||
case ZLine(RET, IfFlagSet(ZFlag.C), _, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xd8)
|
||||
index + 1
|
||||
case ZLine(RET, IfFlagSet(ZFlag.P), _, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xe8)
|
||||
index + 1
|
||||
case ZLine(RET, IfFlagSet(ZFlag.S), _, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xf8)
|
||||
index + 1
|
||||
|
||||
case ZLine(JR, IfFlagClear(ZFlag.Z), param, _) =>
|
||||
requireExtended80()
|
||||
writeByte(bank, index, 0x20)
|
||||
writeByte(bank, index + 1, AssertByte(param - index - 2))
|
||||
index + 2
|
||||
case ZLine(JR, IfFlagClear(ZFlag.C), param, _) =>
|
||||
requireExtended80()
|
||||
writeByte(bank, index, 0x30)
|
||||
writeByte(bank, index + 1, AssertByte(param - index - 2))
|
||||
index + 2
|
||||
|
||||
case ZLine(JR, IfFlagSet(ZFlag.Z), param, _) =>
|
||||
requireExtended80()
|
||||
writeByte(bank, index, 0x28)
|
||||
writeByte(bank, index + 1, AssertByte(param - index - 2))
|
||||
index + 2
|
||||
case ZLine(JR, IfFlagSet(ZFlag.C), param, _) =>
|
||||
requireExtended80()
|
||||
writeByte(bank, index, 0x38)
|
||||
writeByte(bank, index + 1, AssertByte(param - index - 2))
|
||||
index + 2
|
||||
|
||||
case ZLine(JR, NoRegisters, param, _) =>
|
||||
requireExtended80()
|
||||
writeByte(bank, index, 0x18)
|
||||
writeByte(bank, index + 1, AssertByte(param - index - 2))
|
||||
index + 2
|
||||
case ZLine(DJNZ, NoRegisters, param, _) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, 0x10)
|
||||
writeByte(bank, index + 1, AssertByte(param - index - 2))
|
||||
index + 2
|
||||
case ZLine(EX_SP, OneRegister(HL), _, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xe3)
|
||||
index + 1
|
||||
case ZLine(EX_SP, OneRegister(IX), _, _) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, 0xdd)
|
||||
writeByte(bank, index + 1, 0xe3)
|
||||
index + 2
|
||||
case ZLine(EX_SP, OneRegister(IY), _, _) =>
|
||||
requireZ80()
|
||||
writeByte(bank, index, 0xfd)
|
||||
writeByte(bank, index + 1, 0xe3)
|
||||
index + 2
|
||||
case ZLine(EX_DE_HL, _, _, _) =>
|
||||
requireIntel8080()
|
||||
writeByte(bank, index, 0xeb)
|
||||
index + 1
|
||||
case _ =>
|
||||
@ -463,11 +596,9 @@ object Z80Assembler {
|
||||
implieds(NOP) = 0
|
||||
implieds(DAA) = 0x27
|
||||
implieds(SCF) = 0x37
|
||||
implieds(CPL) = 0x37
|
||||
implieds(CPL) = 0x2f
|
||||
implieds(CCF) = 0x3f
|
||||
implieds(EX_AF_AF) = 8
|
||||
implieds(RET) = 0xc9
|
||||
implieds(EXX) = 0xd9
|
||||
implieds(EI) = 0xfb
|
||||
implieds(DI) = 0xf3
|
||||
implieds(HALT) = 0x76
|
||||
@ -525,7 +656,6 @@ object Z80Assembler {
|
||||
cbOneRegister(RR) = One(0x18, 1)
|
||||
cbOneRegister(SLA) = One(0x20, 1)
|
||||
cbOneRegister(SRA) = One(0x28, 1)
|
||||
cbOneRegister(SLL) = One(0x30, 1)
|
||||
cbOneRegister(SRL) = One(0x38, 1)
|
||||
} while (false)
|
||||
|
||||
|
@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class AlgorithmSuite extends FunSuite with Matchers {
|
||||
|
||||
test("RLE decoding") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| array output [4000] @$c000
|
||||
| array input = [
|
||||
|
@ -175,7 +175,7 @@ class ArraySuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Syntax") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| array a = [1, 2, 3]
|
||||
| array b = "text" ascii
|
||||
@ -187,7 +187,7 @@ class ArraySuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Negative subindex") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
|
|
||||
| array output [$fff] @$c000
|
||||
@ -199,6 +199,7 @@ class ArraySuite extends FunSuite with Matchers {
|
||||
| }
|
||||
| noinline byte one() {return 1}
|
||||
""".stripMargin) { m =>
|
||||
m.dump(0xbf00, 0x200)(println(_))
|
||||
m.readByte(0xc100) should equal(55)
|
||||
m.readByte(0xc000) should equal(5)
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Duplicate RTS") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| void main () {
|
||||
| if 1 == 1 {
|
||||
@ -22,7 +22,7 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Inlining variable") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| array output [5] @$C000
|
||||
| void main () {
|
||||
@ -37,7 +37,7 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Inlining variable 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| array output [100] @$C000
|
||||
| void main () {
|
||||
@ -52,7 +52,7 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Loading modified variables") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$C000
|
||||
| void main () {
|
||||
@ -68,7 +68,7 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Bit ops") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$C000
|
||||
| void main () {
|
||||
@ -82,7 +82,7 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Inlining after a while") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| array output [2]@$C000
|
||||
| void main () {
|
||||
@ -99,7 +99,7 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Tail call") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$C000
|
||||
| void main () {
|
||||
@ -304,7 +304,7 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Adding a nonet") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| word output @$C000
|
||||
| byte source @$C002
|
||||
@ -323,7 +323,7 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Common indexing subexpression elimination") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| array output [55] @$C000
|
||||
| array input = [0,1,2,3,4,5,6,7,8,9,10]
|
||||
@ -342,7 +342,7 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Effectively const variable") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
|byte output @$c000
|
||||
|void main() {
|
||||
@ -410,7 +410,7 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Constant pointers") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
|byte output0 @$c000
|
||||
|byte output1 @$c001
|
||||
@ -430,7 +430,7 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Low bit") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main() {
|
||||
@ -449,7 +449,7 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Low bit 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main() {
|
||||
@ -468,7 +468,7 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Low bit 3") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main() {
|
||||
@ -490,7 +490,7 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Low bit 4") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main() {
|
||||
@ -530,7 +530,7 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Shift and increase") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main() {
|
||||
@ -546,7 +546,7 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Add one bit") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main() {
|
||||
|
@ -9,7 +9,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
*/
|
||||
class BasicSymonTest extends FunSuite with Matchers {
|
||||
test("Empty test") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| void main () {
|
||||
|
|
||||
@ -80,11 +80,13 @@ class BasicSymonTest extends FunSuite with Matchers {
|
||||
output += 1
|
||||
}
|
||||
"""
|
||||
EmuUnoptimizedRun(src).readByte(0xc000) should equal(src.count(_ == '+'))
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(src){m =>
|
||||
m.readByte(0xc000) should equal(src.count(_ == '+'))
|
||||
}
|
||||
}
|
||||
|
||||
test("Byte assignment") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -96,7 +98,7 @@ class BasicSymonTest extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Preallocated variables") {
|
||||
val m = EmuUnoptimizedRun(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| array output [2] @$c000
|
||||
| byte number = 4
|
||||
@ -105,13 +107,14 @@ class BasicSymonTest extends FunSuite with Matchers {
|
||||
| number += 1
|
||||
| output[1] = number
|
||||
| }
|
||||
""".stripMargin)
|
||||
m.readByte(0xc000) should equal(4)
|
||||
m.readByte(0xc001) should equal(5)
|
||||
""".stripMargin) { m =>
|
||||
m.readByte(0xc000) should equal(4)
|
||||
m.readByte(0xc001) should equal(5)
|
||||
}
|
||||
}
|
||||
|
||||
test("Preallocated variables 2") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| word output @$c000
|
||||
| word number = 344
|
||||
@ -124,7 +127,7 @@ class BasicSymonTest extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Else if") {
|
||||
val m = EmuUnoptimizedRun(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -136,12 +139,13 @@ class BasicSymonTest extends FunSuite with Matchers {
|
||||
| output = 65
|
||||
| }
|
||||
| }
|
||||
""".stripMargin)
|
||||
""".stripMargin) { m =>
|
||||
m.readWord(0xc000) should equal(4)
|
||||
}
|
||||
}
|
||||
|
||||
test("Segment syntax") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| segment(default)byte output @$c000
|
||||
| segment(default)array x[3]
|
||||
@ -151,7 +155,7 @@ class BasicSymonTest extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Alias test") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos)(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| alias small = byte
|
||||
| alias big = word
|
||||
@ -170,12 +174,12 @@ class BasicSymonTest extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Preprocessor test") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
|
|
||||
| #use ARCH_6502
|
||||
| #use ARCH_Z80
|
||||
| #use ARCH_I80
|
||||
|
|
||||
| #if 1
|
||||
| asm void main () {
|
||||
@ -183,8 +187,8 @@ class BasicSymonTest extends FunSuite with Matchers {
|
||||
| lda #ARCH_6502
|
||||
| sta output
|
||||
| rts
|
||||
| #elseif ARCH_Z80
|
||||
| ld a,ARCH_Z80
|
||||
| #elseif ARCH_I80
|
||||
| ld a,ARCH_I80
|
||||
| ld (output),a
|
||||
| ret
|
||||
| #else
|
||||
|
@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class BitOpSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Word AND") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| byte b
|
||||
@ -21,7 +21,7 @@ class BitOpSuite extends FunSuite with Matchers {
|
||||
""".stripMargin)(_.readWord(0xc000) should equal(0x44))
|
||||
}
|
||||
test("Long AND and EOR") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| long output @$c000
|
||||
| void main () {
|
||||
| byte b
|
||||
@ -36,7 +36,7 @@ class BitOpSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Smart bit set/reset") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Cmos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
| output = 5
|
||||
@ -50,7 +50,7 @@ class BitOpSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Smart bit set/reset 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Cmos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
| output = 5
|
||||
|
@ -11,7 +11,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class BitPackingSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Unpack bits from a byte") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| array output[8]
|
||||
| word output_addr @$c000
|
||||
| void main () {
|
||||
@ -40,7 +40,7 @@ class BitPackingSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Unpack bits from a word") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| array output[16]
|
||||
| word output_addr @$c000
|
||||
| void main () {
|
||||
@ -77,7 +77,7 @@ class BitPackingSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Pack bits into byte") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| byte output @$C000
|
||||
| array input = [$F0, 1, 0, $41, $10, 1, $61, 0]
|
||||
| void main () {
|
||||
@ -94,7 +94,7 @@ class BitPackingSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Pack bits into word") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$C000
|
||||
| array input = [$F0, 1, 0, $41, $10, 1, $61, 0,
|
||||
| 1, 1, 0, 0, 0, 0, 1, 1]
|
||||
@ -112,7 +112,7 @@ class BitPackingSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Pack bits into byte using plus") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| byte output @$C000
|
||||
| array input = [$F0, 1, 0, $41, $10, 1, $61, 0]
|
||||
| void main () {
|
||||
@ -129,7 +129,7 @@ class BitPackingSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Reverse byte") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output_addr @$C000
|
||||
| void main () {
|
||||
| byte i
|
||||
@ -151,7 +151,7 @@ class BitPackingSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Reverse byte 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| byte output_real @$C000
|
||||
| void main () {
|
||||
| byte i
|
||||
@ -172,7 +172,7 @@ class BitPackingSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Reverse word") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output_addr @$C000
|
||||
| void main () {
|
||||
| byte i
|
||||
|
@ -1,6 +1,7 @@
|
||||
package millfork.test
|
||||
|
||||
import millfork.test.emu.EmuBenchmarkRun
|
||||
import millfork.Cpu
|
||||
import millfork.test.emu.EmuCrossPlatformBenchmarkRun
|
||||
import org.scalatest.{FunSuite, Matchers}
|
||||
|
||||
/**
|
||||
@ -9,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class BooleanSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Not") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| array input = [5,6,7]
|
||||
@ -25,7 +26,7 @@ class BooleanSuite extends FunSuite with Matchers {
|
||||
|
||||
|
||||
test("And") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| array input = [5,6,7]
|
||||
@ -44,7 +45,7 @@ class BooleanSuite extends FunSuite with Matchers {
|
||||
|
||||
|
||||
test("Or") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| array input = [5,6,7]
|
||||
|
@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class BreakContinueSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Break from one-iteration loop 1") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -24,7 +24,7 @@ class BreakContinueSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Break from one-iteration loop 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -39,7 +39,7 @@ class BreakContinueSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Break from infinite loop 1") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -54,7 +54,7 @@ class BreakContinueSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Break and continue from infinite loop 1") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -70,7 +70,7 @@ class BreakContinueSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Nested break") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -87,7 +87,7 @@ class BreakContinueSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Continue in for loop 1") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| byte counter @$c001
|
||||
|
@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class ByteDecimalMathSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Decimal byte addition") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| byte a
|
||||
@ -22,7 +22,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Decimal byte addition 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| byte a
|
||||
@ -33,8 +33,20 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
|
||||
""".stripMargin)(_.readByte(0xc000) should equal(0x70))
|
||||
}
|
||||
|
||||
test("In-place decimal byte addition") {
|
||||
test("Decimal byte subtraction") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| byte a
|
||||
| void main () {
|
||||
| a = $50
|
||||
| output = a -' $35
|
||||
| }
|
||||
""".stripMargin)(_.readByte(0xc000) should equal(0x15))
|
||||
}
|
||||
|
||||
test("In-place decimal byte addition") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| array output[3] @$c000
|
||||
| byte a
|
||||
@ -48,7 +60,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("In-place decimal byte addition 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| array output[3] @$c000
|
||||
| void main () {
|
||||
@ -67,8 +79,34 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
|
||||
""".stripMargin)(_.readByte(0xc001) should equal(0x40))
|
||||
}
|
||||
|
||||
test("Flag switching test") {
|
||||
test("In-place decimal byte subtraction") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| byte a
|
||||
| void main () {
|
||||
| output = $50
|
||||
| output -'= $35
|
||||
| }
|
||||
""".stripMargin)(_.readByte(0xc000) should equal(0x15))
|
||||
}
|
||||
|
||||
test("In-place decimal word subtraction") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
"""
|
||||
| word output @$c000
|
||||
| word a
|
||||
| void main () {
|
||||
| output = $1500
|
||||
| output -'= $455
|
||||
| a = $264
|
||||
| output -'= a
|
||||
| }
|
||||
""".stripMargin)(_.readWord(0xc000) should equal(0x781))
|
||||
}
|
||||
|
||||
test("Flag switching test") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -79,7 +117,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Flag switching test 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -90,7 +128,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Flag switching test 3") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -101,7 +139,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Decimal left shift test") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -116,7 +154,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Decimal left shift test 2") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -130,7 +168,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Decimal left shift test 3") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
@ -234,7 +272,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
|
||||
test("Decimal byte multiplication comprehensive suite") {
|
||||
val numbers = List(0, 1, 2, 3, 6, 8, 10, 11, 12, 14, 15, 16, 20, 40, 73, 81, 82, 98, 99)
|
||||
for (i <- numbers; j <- numbers) {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -252,7 +290,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
|
||||
test("Decimal comparison") {
|
||||
// CMP#0 shouldn't be elided after a decimal operation.
|
||||
// Currently no emulator used for testing can catch that.
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
|
@ -178,7 +178,7 @@ class ByteMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Byte multiplication 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| import zp_reg
|
||||
| byte output1 @$c001
|
||||
@ -215,7 +215,7 @@ class ByteMathSuite extends FunSuite with Matchers {
|
||||
| #if ARCH_6502
|
||||
| if output1 != 20 { asm { lda $bfff }}
|
||||
| if output2 != 27 { asm { lda $bfff }}
|
||||
| #elseif ARCH_Z80
|
||||
| #elseif ARCH_I80
|
||||
| if output1 != 20 { asm { ld a,($bfff) }}
|
||||
| if output2 != 27 { asm { ld a,($bfff) }}
|
||||
| #else
|
||||
|
@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class CmosSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Zero store 1") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Cmos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| output = 1
|
||||
@ -19,7 +19,7 @@ class CmosSuite extends FunSuite with Matchers {
|
||||
""".stripMargin)(_.readWord(0xc000) should equal(0))
|
||||
}
|
||||
test("Zero store 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Cmos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
| output = 1
|
||||
|
@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class ComparisonSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Equality and inequality") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -28,7 +28,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Less") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -41,7 +41,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Compare to zero") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -76,7 +76,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Does it even work") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
@ -99,7 +99,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
| if 2222 == 3333 { output -= 1 }
|
||||
| }
|
||||
""".stripMargin
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(src)(_.readByte(0xc000) should equal(src.count(_ == '+')))
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(src)(_.readByte(0xc000) should equal(src.count(_ == '+')))
|
||||
}
|
||||
|
||||
test("Word comparison == and !=") {
|
||||
@ -122,7 +122,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
| if a != 0 { output += 1 }
|
||||
| }
|
||||
""".stripMargin
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(src)(_.readByte(0xc000) should equal(src.count(_ == '+')))
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(src)(_.readByte(0xc000) should equal(src.count(_ == '+')))
|
||||
}
|
||||
|
||||
test("Word comparison <=") {
|
||||
@ -143,7 +143,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
| if a <= c { output += 1 }
|
||||
| }
|
||||
""".stripMargin
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(src)(_.readByte(0xc000) should equal(src.count(_ == '+')))
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(src)(_.readByte(0xc000) should equal(src.count(_ == '+')))
|
||||
}
|
||||
test("Word comparison <") {
|
||||
val src =
|
||||
@ -162,7 +162,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
| if a < 257 { output += 1 }
|
||||
| }
|
||||
""".stripMargin
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(src)(_.readByte(0xc000) should equal(src.count(_ == '+')))
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(src)(_.readByte(0xc000) should equal(src.count(_ == '+')))
|
||||
}
|
||||
|
||||
|
||||
@ -183,7 +183,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
| if c > 0 { output += 1 }
|
||||
| }
|
||||
""".stripMargin
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(src)(_.readByte(0xc000) should equal(src.count(_ == '+')))
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(src)(_.readByte(0xc000) should equal(src.count(_ == '+')))
|
||||
}
|
||||
|
||||
test("Word comparison >=") {
|
||||
@ -206,7 +206,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
| if a >= 0 { output += 1 }
|
||||
| }
|
||||
""".stripMargin
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(src)(_.readByte(0xc000) should equal(src.count(_ == '+')))
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(src)(_.readByte(0xc000) should equal(src.count(_ == '+')))
|
||||
}
|
||||
|
||||
test("Signed comparison >=") {
|
||||
@ -265,7 +265,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Multiple params for equality") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -281,7 +281,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Multiple params for inequality") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -297,7 +297,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Warnings") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -339,7 +339,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
| if c > 335444 { output += 1 }
|
||||
| }
|
||||
""".stripMargin
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(src)(_.readByte(0xc000) should equal(src.count(_ == '+')))
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(src)(_.readByte(0xc000) should equal(src.count(_ == '+')))
|
||||
}
|
||||
|
||||
test("Mixed type comparison") {
|
||||
@ -357,6 +357,6 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
| if x < z { output += 1 }
|
||||
| }
|
||||
""".stripMargin
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(src)(_.readByte(0xc000) should equal(1))
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(src)(_.readByte(0xc000) should equal(1))
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class EnumSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Enum basic test") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| enum ugly {
|
||||
| a
|
||||
@ -29,7 +29,7 @@ class EnumSuite extends FunSuite with Matchers {
|
||||
| #if ARCH_6502
|
||||
| sta $bfff
|
||||
| rts
|
||||
| #elseif ARCH_Z80
|
||||
| #elseif ARCH_I80
|
||||
| ld ($bfff),a
|
||||
| ret
|
||||
| #else
|
||||
@ -40,7 +40,7 @@ class EnumSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Enum arrays") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| enum ugly {
|
||||
| a
|
||||
@ -56,7 +56,7 @@ class EnumSuite extends FunSuite with Matchers {
|
||||
| #if ARCH_6502
|
||||
| sta $bfff
|
||||
| rts
|
||||
| #elseif ARCH_Z80
|
||||
| #elseif ARCH_I80
|
||||
| ld ($bfff),a
|
||||
| ret
|
||||
| #else
|
||||
|
@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class ErasthotenesSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Erasthotenes") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| const pointer sieve = $C000
|
||||
| const byte sqrt = 128
|
||||
|
@ -1,6 +1,7 @@
|
||||
package millfork.test
|
||||
|
||||
import millfork.test.emu.EmuBenchmarkRun
|
||||
import millfork.Cpu
|
||||
import millfork.test.emu.{EmuBenchmarkRun, EmuCrossPlatformBenchmarkRun}
|
||||
import org.scalatest.{FunSuite, Matchers}
|
||||
|
||||
/**
|
||||
@ -9,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class FarwordTest extends FunSuite with Matchers {
|
||||
|
||||
test("Farword assignment") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| farword output3 @$c000
|
||||
| farword output2 @$c004
|
||||
@ -28,7 +29,7 @@ class FarwordTest extends FunSuite with Matchers {
|
||||
}
|
||||
}
|
||||
test("Farword assignment 2") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| farword output3 @$c000
|
||||
| farword output2 @$c004
|
||||
@ -52,7 +53,7 @@ class FarwordTest extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Farword assignment 3") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| farword output0 @$c000
|
||||
| farword output1 @$c003
|
||||
@ -69,7 +70,7 @@ class FarwordTest extends FunSuite with Matchers {
|
||||
}
|
||||
}
|
||||
test("Farword addition") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| farword output @$c000
|
||||
| void main () {
|
||||
@ -89,7 +90,7 @@ class FarwordTest extends FunSuite with Matchers {
|
||||
}
|
||||
}
|
||||
test("Farword addition 2") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| farword output @$c000
|
||||
| void main () {
|
||||
@ -103,7 +104,7 @@ class FarwordTest extends FunSuite with Matchers {
|
||||
}
|
||||
}
|
||||
test("Farword subtraction") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| farword output @$c000
|
||||
| void main () {
|
||||
@ -123,7 +124,7 @@ class FarwordTest extends FunSuite with Matchers {
|
||||
}
|
||||
}
|
||||
test("Farword subtraction 2") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| farword output @$c000
|
||||
| void main () {
|
||||
@ -137,7 +138,7 @@ class FarwordTest extends FunSuite with Matchers {
|
||||
}
|
||||
}
|
||||
test("Farword subtraction 3") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| farword output @$c000
|
||||
| void main () {
|
||||
@ -157,7 +158,7 @@ class FarwordTest extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Farword AND") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| farword output @$c000
|
||||
| void main () {
|
||||
@ -177,7 +178,7 @@ class FarwordTest extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Farword INC/DEC") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| farword output0 @$c000
|
||||
| farword output1 @$c004
|
||||
|
@ -11,8 +11,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class ForArraySuite extends FunSuite with Matchers {
|
||||
|
||||
test("Basic for-array test") {
|
||||
val m = EmuSuperOptimizedRun(
|
||||
"""
|
||||
val src = """
|
||||
| byte output @$c000
|
||||
| array input = for i,0,until,8 [i + i]
|
||||
|
|
||||
@ -37,7 +36,11 @@ class ForArraySuite extends FunSuite with Matchers {
|
||||
| output = useless0[0] + useless1[0] + useless2[0] + useless3[0] + useless4[0] + useless5[0] + useless6[0] + useless7[0]
|
||||
| output = input.length + input[5]
|
||||
| }
|
||||
""".stripMargin)
|
||||
""".stripMargin
|
||||
val m = EmuSuperOptimizedRun(src)
|
||||
m.readByte(0xc000) should equal(18)
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)(src) { m =>
|
||||
m.readByte(0xc000) should equal(18)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ class ForLoopSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Various loops") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| void init() {
|
||||
| zero = 0
|
||||
@ -228,7 +228,7 @@ class ForLoopSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Edge cases - positive") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| void main() {
|
||||
| byte i
|
||||
| for i,0,until,256 { f() }
|
||||
|
@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class LongTest extends FunSuite with Matchers {
|
||||
|
||||
test("Long assignment") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| long output4 @$c000
|
||||
| long output2 @$c004
|
||||
@ -29,7 +29,7 @@ class LongTest extends FunSuite with Matchers {
|
||||
}
|
||||
}
|
||||
test("Long assignment 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| long output4 @$c000
|
||||
| long output2 @$c004
|
||||
@ -52,7 +52,7 @@ class LongTest extends FunSuite with Matchers {
|
||||
}
|
||||
}
|
||||
test("Long addition") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| long output @$c000
|
||||
| void main () {
|
||||
@ -72,7 +72,7 @@ class LongTest extends FunSuite with Matchers {
|
||||
}
|
||||
}
|
||||
test("Long addition 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| long output @$c000
|
||||
| void main () {
|
||||
@ -86,7 +86,7 @@ class LongTest extends FunSuite with Matchers {
|
||||
}
|
||||
}
|
||||
test("Long subtraction") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| long output @$c000
|
||||
| void main () {
|
||||
@ -106,7 +106,7 @@ class LongTest extends FunSuite with Matchers {
|
||||
}
|
||||
}
|
||||
test("Long subtraction 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| long output @$c000
|
||||
| void main () {
|
||||
@ -120,7 +120,7 @@ class LongTest extends FunSuite with Matchers {
|
||||
}
|
||||
}
|
||||
test("Long subtraction 3") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| long output @$c000
|
||||
| void main () {
|
||||
@ -140,7 +140,7 @@ class LongTest extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Long AND") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| long output @$c000
|
||||
| void main () {
|
||||
@ -160,7 +160,7 @@ class LongTest extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Long INC/DEC") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| long output0 @$c000
|
||||
| long output1 @$c004
|
||||
|
@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class NonetSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Nonet operations") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| array output [5] @$c000
|
||||
| void main () {
|
||||
|
@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class ReturnDispatchSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Trivial test") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -28,7 +28,7 @@ class ReturnDispatchSuite extends FunSuite with Matchers {
|
||||
}
|
||||
}
|
||||
test("Parameter test") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| array output [200] @$c000
|
||||
| sbyte param
|
||||
|
@ -1,8 +1,7 @@
|
||||
package millfork.test
|
||||
|
||||
import millfork.assembly.mos.opt.{AlwaysGoodOptimizations, LaterOptimizations, VariableToRegisterOptimization}
|
||||
import millfork.test.emu.{EmuBenchmarkRun, EmuRun, EmuUltraBenchmarkRun}
|
||||
import millfork.{Cpu, OptimizationPresets}
|
||||
import millfork.Cpu
|
||||
import millfork.test.emu.{EmuBenchmarkRun, EmuCrossPlatformBenchmarkRun}
|
||||
import org.scalatest.{FunSuite, Matchers}
|
||||
|
||||
/**
|
||||
@ -11,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class SecondAssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Add-shift-add") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -24,7 +23,7 @@ class SecondAssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("And-shift-and") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -37,7 +36,7 @@ class SecondAssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Add with limit") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| const byte start = 5
|
||||
|
@ -1,6 +1,7 @@
|
||||
package millfork.test
|
||||
|
||||
import millfork.test.emu.EmuBenchmarkRun
|
||||
import millfork.Cpu
|
||||
import millfork.test.emu.{EmuBenchmarkRun, EmuCrossPlatformBenchmarkRun}
|
||||
import org.scalatest.{FunSuite, Matchers}
|
||||
|
||||
/**
|
||||
@ -9,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class SeparateBytesSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Separate assignment 1") {
|
||||
EmuBenchmarkRun("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| output = 2:3
|
||||
@ -18,7 +19,7 @@ class SeparateBytesSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Separate assignment 2") {
|
||||
EmuBenchmarkRun("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| byte output @$c000
|
||||
| byte ignore @$c001
|
||||
| void main () {
|
||||
@ -30,7 +31,7 @@ class SeparateBytesSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Separate assignment 3") {
|
||||
EmuBenchmarkRun("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| byte output @$c000
|
||||
| byte ignore @$c001
|
||||
| void main () {
|
||||
@ -43,7 +44,7 @@ class SeparateBytesSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Separate assignment 4") {
|
||||
EmuBenchmarkRun("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| array output [5] @$c000
|
||||
| byte ignore @$c001
|
||||
| void main () {
|
||||
@ -58,7 +59,7 @@ class SeparateBytesSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Separate assignment 5") {
|
||||
EmuBenchmarkRun("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| array output [5] @$c000
|
||||
| byte ignore @$c001
|
||||
| void main () {
|
||||
@ -73,7 +74,7 @@ class SeparateBytesSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Magic split array") {
|
||||
EmuBenchmarkRun("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| array hi [16] @$c000
|
||||
| array lo [16] @$c010
|
||||
| void main () {
|
||||
@ -106,7 +107,7 @@ class SeparateBytesSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Separate addition") {
|
||||
EmuBenchmarkRun("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| byte h
|
||||
@ -120,7 +121,7 @@ class SeparateBytesSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Separate increase") {
|
||||
EmuBenchmarkRun("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| byte h
|
||||
|
@ -9,7 +9,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class ShiftSuite extends FunSuite with Matchers {
|
||||
|
||||
test("In-place shifting") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| array output [3] @$c000
|
||||
| void main () {
|
||||
| output[0] = 1
|
||||
@ -20,7 +20,7 @@ class ShiftSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Byte shifting") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
| byte a
|
||||
@ -31,7 +31,7 @@ class ShiftSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Word shifting") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| byte a
|
||||
@ -50,10 +50,17 @@ class ShiftSuite extends FunSuite with Matchers {
|
||||
| output <<= 2
|
||||
| }
|
||||
""".stripMargin)(_.readLong(0xc000) should equal(0x4040C04))
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Z80, Cpu.Intel8080)("""
|
||||
| long output @$c000
|
||||
| void main () {
|
||||
| output = $1010301
|
||||
| output <<= 2
|
||||
| }
|
||||
""".stripMargin)(_.readLong(0xc000) should equal(0x4040C04))
|
||||
}
|
||||
|
||||
test("Long shifting right") {
|
||||
EmuBenchmarkRun("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| long output @$c000
|
||||
| void main () {
|
||||
| output = $4040C04
|
||||
@ -63,7 +70,7 @@ class ShiftSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Word shifting via pseudoregister") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| output = identity(three() << 7)
|
||||
@ -74,7 +81,7 @@ class ShiftSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Variable shifting") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output0 @$c000
|
||||
| word output2 @$c002
|
||||
| byte output4 @$c004
|
||||
|
@ -1,7 +1,7 @@
|
||||
package millfork.test
|
||||
|
||||
import millfork.Cpu
|
||||
import millfork.test.emu.{EmuCrossPlatformBenchmarkRun, EmuUnoptimizedCrossPlatformRun}
|
||||
import millfork.test.emu.EmuCrossPlatformBenchmarkRun
|
||||
import org.scalatest.{FunSuite, Matchers}
|
||||
|
||||
/**
|
||||
@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class SignExtensionSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Sbyte to Word") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| sbyte b
|
||||
@ -22,7 +22,7 @@ class SignExtensionSuite extends FunSuite with Matchers {
|
||||
}
|
||||
}
|
||||
test("Sbyte to Word 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| output = b()
|
||||
@ -33,7 +33,7 @@ class SignExtensionSuite extends FunSuite with Matchers {
|
||||
""".stripMargin){m => m.readWord(0xc000) should equal(0xffff)}
|
||||
}
|
||||
test("Sbyte to Long") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| long output @$c000
|
||||
| void main () {
|
||||
| output = 421
|
||||
@ -46,7 +46,7 @@ class SignExtensionSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Optimize pointless sign extension") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| array output [10] @$c000
|
||||
| word w
|
||||
| void main () {
|
||||
|
@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class StatementOptimizationSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Statement optimization 1") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Intel8080)(
|
||||
"""
|
||||
| array output[10] @$c000
|
||||
| void main() {
|
||||
|
@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class TypeSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Word to word") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| output = word(0x203)
|
||||
|
@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class TypeWideningSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Word after simple ops") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| output = random()
|
||||
|
@ -9,7 +9,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class WordMathSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Word addition") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| word a
|
||||
| void main () {
|
||||
@ -21,7 +21,7 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Word subtraction") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| word a
|
||||
| void main () {
|
||||
@ -33,7 +33,7 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Word subtraction 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Cmos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Cmos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| word a
|
||||
| void main () {
|
||||
@ -45,7 +45,7 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Byte-to-word addition") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| word pair
|
||||
| void main () {
|
||||
@ -58,7 +58,7 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Literal addition") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| output = 640
|
||||
@ -68,7 +68,7 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Array element addition") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| word pair
|
||||
| array b[2]
|
||||
@ -85,7 +85,7 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("nesdev.com example") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| byte output @$c000
|
||||
| array map [256] @$c300
|
||||
| array b[2]
|
||||
@ -103,7 +103,7 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("hi()/lo()") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| array output [7] @$c000
|
||||
| void main () {
|
||||
| output[0] = lo(33)
|
||||
@ -135,7 +135,7 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Word addition 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| word v
|
||||
@ -151,7 +151,7 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Word addition 3") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| byte c
|
||||
@ -167,7 +167,7 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Word addition 4") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| word v
|
||||
@ -187,7 +187,7 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Word bit ops 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| word v
|
||||
@ -203,7 +203,7 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Word shift") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| word v
|
||||
@ -221,7 +221,7 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Word shift 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| output = five()
|
||||
@ -236,7 +236,7 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Word shift 3") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| output = five()
|
||||
@ -251,7 +251,7 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Word shift 4") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| output = five()
|
||||
@ -266,7 +266,7 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Word shift 5") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| output = five()
|
||||
|
@ -1,6 +1,6 @@
|
||||
package millfork.test
|
||||
|
||||
import millfork.test.emu.EmuUnoptimizedZ80Run
|
||||
import millfork.test.emu.{EmuUnoptimizedIntel8080Run, EmuUnoptimizedZ80Run}
|
||||
import org.scalatest.{FunSuite, Matchers}
|
||||
|
||||
/**
|
||||
@ -9,7 +9,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class Z80AssemblySuite extends FunSuite with Matchers {
|
||||
|
||||
test("Common I80 instructions") {
|
||||
EmuUnoptimizedZ80Run(
|
||||
EmuUnoptimizedIntel8080Run(
|
||||
"""
|
||||
| asm void main () {
|
||||
| ret
|
||||
@ -37,7 +37,6 @@ class Z80AssemblySuite extends FunSuite with Matchers {
|
||||
| dec d
|
||||
| ld d,$16
|
||||
| rla
|
||||
| jr main
|
||||
| add hl,de
|
||||
| ld a,(de)
|
||||
| dec de
|
||||
@ -46,14 +45,12 @@ class Z80AssemblySuite extends FunSuite with Matchers {
|
||||
| ld e,$1e
|
||||
| rra
|
||||
|
|
||||
| jr nz,main
|
||||
| ld hl,$2121
|
||||
| inc hl
|
||||
| inc h
|
||||
| dec h
|
||||
| ld h,$26
|
||||
| daa
|
||||
| jr z,main
|
||||
| add hl,hl
|
||||
| dec hl
|
||||
| inc l
|
||||
@ -61,7 +58,6 @@ class Z80AssemblySuite extends FunSuite with Matchers {
|
||||
| ld l,$2e
|
||||
| cpl
|
||||
|
|
||||
| jr nc,main
|
||||
| ld hl,$2121
|
||||
| ld ($fffe),a
|
||||
| inc sp
|
||||
@ -69,7 +65,6 @@ class Z80AssemblySuite extends FunSuite with Matchers {
|
||||
| dec (hl)
|
||||
| ld h,$26
|
||||
| scf
|
||||
| jr c,main
|
||||
| add hl,sp
|
||||
| ld a,($fffe)
|
||||
| dec sp
|
||||
@ -280,16 +275,13 @@ class Z80AssemblySuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Intel 8080 instructions") {
|
||||
EmuUnoptimizedZ80Run(
|
||||
EmuUnoptimizedIntel8080Run(
|
||||
"""
|
||||
| asm void main () {
|
||||
| ret
|
||||
| ex af,af'
|
||||
| djnz main
|
||||
| ld ($fffe),hl
|
||||
| ld hl,($fffe)
|
||||
| out (1),a
|
||||
| exx
|
||||
| in a,(1)
|
||||
| ret po
|
||||
| jp po,main
|
||||
@ -317,6 +309,13 @@ class Z80AssemblySuite extends FunSuite with Matchers {
|
||||
| ret
|
||||
|
|
||||
| reti
|
||||
|
|
||||
| jr main
|
||||
| jr nz,main
|
||||
| jr z,main
|
||||
| jr nc,main
|
||||
| jr c,main
|
||||
| ld (34),sp
|
||||
|
|
||||
| rlc b
|
||||
| rlc c
|
||||
@ -489,6 +488,10 @@ class Z80AssemblySuite extends FunSuite with Matchers {
|
||||
| asm void main () {
|
||||
| ret
|
||||
|
|
||||
| djnz main
|
||||
| ex af,af'
|
||||
| exx
|
||||
|
|
||||
| sll b
|
||||
| sll c
|
||||
| sll d
|
||||
@ -533,7 +536,6 @@ class Z80AssemblySuite extends FunSuite with Matchers {
|
||||
| adc hl,hl
|
||||
| rld
|
||||
| sbc hl,sp
|
||||
| ld (34),sp
|
||||
| in a,(c)
|
||||
| out (c),a
|
||||
| adc hl,sp
|
||||
|
@ -44,6 +44,25 @@ object EmuZ80BenchmarkRun {
|
||||
}
|
||||
}
|
||||
|
||||
object EmuIntel8080BenchmarkRun {
|
||||
def apply(source: String)(verifier: MemoryBank => Unit): Unit = {
|
||||
val (Timings(t0, _), m0) = EmuUnoptimizedIntel8080Run.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) {
|
||||
|
@ -10,6 +10,7 @@ object EmuUnoptimizedCrossPlatformRun {
|
||||
def apply(platforms: Cpu.Value*)(source: String)(verifier: MemoryBank => Unit): Unit = {
|
||||
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
|
||||
if (platforms.contains(Cpu.Mos)) {
|
||||
println(f"Running MOS")
|
||||
verifier(mm)
|
||||
@ -18,5 +19,9 @@ object EmuUnoptimizedCrossPlatformRun {
|
||||
println(f"Running Z80")
|
||||
verifier(mz)
|
||||
}
|
||||
if (platforms.contains(Cpu.Intel8080)) {
|
||||
println(f"Running 8080")
|
||||
verifier(mi)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,4 +8,6 @@ import millfork.Cpu
|
||||
*/
|
||||
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)
|
||||
|
@ -34,6 +34,7 @@ class EmuZ80Run(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimizatio
|
||||
val platform = EmuPlatform.get(cpu)
|
||||
val extraFlags = Map(
|
||||
CompilationFlag.InlineFunctions -> this.inline,
|
||||
CompilationFlag.EmitIllegals -> (cpu == millfork.Cpu.Z80),
|
||||
CompilationFlag.LenientTextEncoding -> true)
|
||||
val options = CompilationOptions(platform, millfork.Cpu.defaultFlags(cpu).map(_ -> true).toMap ++ extraFlags, None, 0)
|
||||
ErrorReporting.hasErrors = false
|
||||
@ -110,7 +111,7 @@ class EmuZ80Run(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimizatio
|
||||
(0x200 until 0x2000).takeWhile(memoryBank.occupied(_)).map(memoryBank.output).grouped(16).map(_.map(i => f"$i%02x").mkString(" ")).foreach(ErrorReporting.debug(_))
|
||||
|
||||
val timings = platform.cpu match {
|
||||
case millfork.Cpu.Z80 =>
|
||||
case millfork.Cpu.Z80 | millfork.Cpu.Intel8080 =>
|
||||
val cpu = new Z80Core(Z80Memory(memoryBank), DummyIO)
|
||||
cpu.reset()
|
||||
cpu.setProgramCounter(0x1f0)
|
||||
|
Loading…
x
Reference in New Issue
Block a user