mirror of
https://github.com/KarolS/millfork.git
synced 2024-12-23 23:30:22 +00:00
6809: Make some progress
This commit is contained in:
parent
960d16fa18
commit
1d530d896a
@ -44,7 +44,10 @@ case class CompilationOptions(platform: Platform,
|
||||
|
||||
if (CpuFamily.forType(platform.cpu) != CpuFamily.I80) invalids ++= Set(
|
||||
EmitExtended80Opcodes, EmitZ80Opcodes, EmitSharpOpcodes, EmitEZ80Opcodes,
|
||||
UseIyForStack, UseShadowRegistersForInterrupts)
|
||||
UseIyForStack, UseIxForScratch, UseIyForScratch, UseShadowRegistersForInterrupts)
|
||||
|
||||
if (CpuFamily.forType(platform.cpu) != CpuFamily.M6809) invalids ++= Set(
|
||||
UseUForStack, UseYForStack)
|
||||
|
||||
invalids = invalids.filter(flags)
|
||||
|
||||
@ -177,6 +180,9 @@ case class CompilationOptions(platform: Platform,
|
||||
}
|
||||
case CpuFamily.I86 =>
|
||||
case CpuFamily.M6809 =>
|
||||
if (flags(UseUForStack) && flags(UseYForStack)) {
|
||||
log.error("Cannot use both U and Y registers for stack variables simultaneously")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,6 +231,8 @@ case class CompilationOptions(platform: Platform,
|
||||
"USES_ZPREG" -> toLong(platform.cpuFamily == CpuFamily.M6502 && zpRegisterSize > 0),
|
||||
"USES_IX_STACK" -> toLong(flag(CompilationFlag.UseIxForStack)),
|
||||
"USES_IY_STACK" -> toLong(flag(CompilationFlag.UseIyForStack)),
|
||||
"USES_U_STACK" -> toLong(flag(CompilationFlag.UseUForStack)),
|
||||
"USES_Y_STACK" -> toLong(flag(CompilationFlag.UseYForStack)),
|
||||
"USES_SOFTWARE_STACK" -> toLong(flag(CompilationFlag.SoftwareStack)),
|
||||
"USES_SHADOW_REGISTERS" -> toLong(flag(CompilationFlag.UseShadowRegistersForInterrupts)),
|
||||
"ZPREG_SIZE" -> (if (platform.cpuFamily == CpuFamily.M6502) zpRegisterSize.toLong else 0)
|
||||
@ -502,6 +510,8 @@ object CompilationFlag extends Enumeration {
|
||||
UseIxForScratch, UseIyForScratch,
|
||||
UseIntelSyntaxForInput,
|
||||
UseIntelSyntaxForOutput,
|
||||
// compilation options for 6809
|
||||
UseUForStack, UseYForStack,
|
||||
// optimization options:
|
||||
OptimizeForSize, OptimizeForSpeed, OptimizeForSonicSpeed, OptimizeForDebugging,
|
||||
DangerousOptimizations, InlineFunctions, InterproceduralOptimization,
|
||||
@ -540,6 +550,8 @@ object CompilationFlag extends Enumeration {
|
||||
"iy_stack" -> UseIyForStack,
|
||||
"ix_scratch" -> UseIxForScratch,
|
||||
"iy_scratch" -> UseIyForScratch,
|
||||
"u_stack" -> UseUForStack,
|
||||
"y_stack" -> UseYForStack,
|
||||
"software_stack" -> SoftwareStack,
|
||||
"use_shadow_registers_for_irq" -> UseShadowRegistersForInterrupts,
|
||||
"output_intel_syntax" -> UseIntelSyntaxForOutput,
|
||||
|
@ -540,6 +540,12 @@ object Main {
|
||||
flag("-fuse-iy-for-stack").action { c =>
|
||||
c.changeFlag(CompilationFlag.UseIyForStack, true).changeFlag(CompilationFlag.UseIxForStack, false)
|
||||
}.description("Use IY as base pointer for stack variables (Z80 only)")
|
||||
flag("-fuse-u-for-stack").action { c =>
|
||||
c.changeFlag(CompilationFlag.UseIxForStack, true).changeFlag(CompilationFlag.UseUForStack, false)
|
||||
}.description("Use U as base pointer for stack variables (6809 only)").hidden()
|
||||
flag("-fuse-y-for-stack").action { c =>
|
||||
c.changeFlag(CompilationFlag.UseIyForStack, true).changeFlag(CompilationFlag.UseYForStack, false)
|
||||
}.description("Use Y as base pointer for stack variables (6809 only)").hidden()
|
||||
boolean("-fuse-ix-for-scratch", "-fno-use-ix-for-scratch").action { (c, v) =>
|
||||
if (v) {
|
||||
c.changeFlag(CompilationFlag.UseIxForScratch, true).changeFlag(CompilationFlag.UseIxForStack, false)
|
||||
@ -557,6 +563,9 @@ object Main {
|
||||
flag("-fno-use-index-for-stack").action { c =>
|
||||
c.changeFlag(CompilationFlag.UseIyForStack, false).changeFlag(CompilationFlag.UseIxForStack, false)
|
||||
}.description("Don't use either IX or IY as base pointer for stack variables (Z80 only)")
|
||||
flag("-fno-use-uy-for-stack").action { c =>
|
||||
c.changeFlag(CompilationFlag.UseUForStack, false).changeFlag(CompilationFlag.UseYForStack, false)
|
||||
}.description("Don't use either U or Y as base pointer for stack variables (6809 only)").hidden()
|
||||
boolean("-fsoftware-stack", "-fno-software-stack").action { (c, v) =>
|
||||
c.changeFlag(CompilationFlag.SoftwareStack, v)
|
||||
}.description("Use software stack for stack variables (6502 only)")
|
||||
|
@ -6,6 +6,8 @@ import millfork.node.{M6809Register, Position}
|
||||
* @author Karol Stasiak
|
||||
*/
|
||||
sealed trait MAddrMode {
|
||||
def changesRegister(reg: M6809Register.Value): Boolean = false
|
||||
|
||||
def makeIndirect(position: Position): MAddrMode
|
||||
}
|
||||
|
||||
@ -14,10 +16,14 @@ case object Inherent extends MAddrMode {
|
||||
}
|
||||
|
||||
case object InherentA extends MAddrMode {
|
||||
override def changesRegister(reg: M6809Register.Value): Boolean = reg == M6809Register.A || reg == M6809Register.D
|
||||
|
||||
def makeIndirect(position: Position): MAddrMode = ???
|
||||
}
|
||||
|
||||
case object InherentB extends MAddrMode {
|
||||
override def changesRegister(reg: M6809Register.Value): Boolean = reg == M6809Register.B || reg == M6809Register.D
|
||||
|
||||
def makeIndirect(position: Position): MAddrMode = ???
|
||||
}
|
||||
|
||||
@ -70,10 +76,14 @@ case class DAccumulatorIndexed(base: M6809Register.Value, indirect: Boolean) ext
|
||||
}
|
||||
|
||||
case class PostIncremented(base: M6809Register.Value, amount: Int, indirect: Boolean) extends MAddrMode {
|
||||
override def changesRegister(reg: M6809Register.Value): Boolean = reg == base
|
||||
|
||||
def makeIndirect(position: Position): MAddrMode = copy(indirect = true)
|
||||
}
|
||||
|
||||
case class PreDecremented(base: M6809Register.Value, amount: Int, indirect: Boolean) extends MAddrMode {
|
||||
override def changesRegister(reg: M6809Register.Value): Boolean = reg == base
|
||||
|
||||
def makeIndirect(position: Position): MAddrMode = copy(indirect = true)
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
package millfork.assembly.m6809
|
||||
|
||||
import millfork.CompilationFlag
|
||||
import millfork.assembly.{AbstractCode, Elidability, SourceLine}
|
||||
import millfork.compiler.CompilationContext
|
||||
import millfork.env.{Constant, Label, MemoryVariable, NumericConstant, StackVariable, Variable, VariableInMemory}
|
||||
import millfork.node.{M6809Register, Position}
|
||||
|
||||
@ -33,6 +35,9 @@ object MLine {
|
||||
def indexedS(opcode: MOpcode.Value, offset: Int = 0): MLine =
|
||||
MLine(opcode, Indexed(M6809Register.S, indirect = false), NumericConstant(offset, 1))
|
||||
|
||||
def indexedX(opcode: MOpcode.Value, offset: Constant): MLine =
|
||||
MLine(opcode, Indexed(M6809Register.X, indirect = false), offset)
|
||||
|
||||
def accessAndPullS(opcode: MOpcode.Value): MLine =
|
||||
MLine(opcode, PostIncremented(M6809Register.S, 1, indirect = false), Constant.Zero)
|
||||
|
||||
@ -51,12 +56,21 @@ object MLine {
|
||||
|
||||
def absolute(opcode: MOpcode.Value, param: Constant): MLine = MLine(opcode, Absolute(false), param)
|
||||
|
||||
def userstack(opcode: MOpcode.Value, offset: Int): MLine = MLine(opcode, Indexed(M6809Register.U, indirect = false), Constant(offset))
|
||||
//def userstack(opcode: MOpcode.Value, offset: Int): MLine = MLine(opcode, Indexed(M6809Register.U, indirect = false), Constant(offset))
|
||||
|
||||
def variable(opcode: MOpcode.Value, variable: Variable, offset: Int = 0): MLine = {
|
||||
def variablestack(ctx: CompilationContext, opcode: MOpcode.Value, offset: Int): MLine = {
|
||||
if (ctx.options.flag(CompilationFlag.UseUForStack)) MLine(opcode, Indexed(M6809Register.U, indirect = false), Constant(offset))
|
||||
else if (ctx.options.flag(CompilationFlag.UseYForStack)) MLine(opcode, Indexed(M6809Register.Y, indirect = false), Constant(offset))
|
||||
else MLine(opcode, Indexed(M6809Register.S, indirect = false), Constant(ctx.extraStackOffset + offset))
|
||||
}
|
||||
|
||||
def variable(ctx: CompilationContext, opcode : MOpcode.Value, variable: Variable, offset: Int = 0): MLine = {
|
||||
variable match {
|
||||
case v: VariableInMemory => MLine.absolute(opcode, v.toAddress)
|
||||
case v: StackVariable => MLine(opcode, Indexed(M6809Register.U, indirect = false), NumericConstant(v.baseOffset, 1))
|
||||
case v: StackVariable =>
|
||||
if (ctx.options.flag(CompilationFlag.UseUForStack)) MLine(opcode, Indexed(M6809Register.U, indirect = false), NumericConstant(v.baseOffset, 1))
|
||||
else if (ctx.options.flag(CompilationFlag.UseYForStack)) MLine(opcode, Indexed(M6809Register.Y, indirect = false), NumericConstant(v.baseOffset, 1))
|
||||
else MLine(opcode, Indexed(M6809Register.S, indirect = false), NumericConstant(v.baseOffset + ctx.extraStackOffset, 1))
|
||||
case _ => ???
|
||||
}
|
||||
}
|
||||
@ -122,5 +136,37 @@ case class MLine(opcode: MOpcode.Value, addrMode: MAddrMode, parameter: Constant
|
||||
}
|
||||
s" $opcode$suffix"
|
||||
}
|
||||
|
||||
def changesRegister(reg: M6809Register.Value): Boolean = {
|
||||
import M6809Register._
|
||||
def overlaps(other: M6809Register.Value): Boolean = {
|
||||
if (reg == D && (other == A || other == B)) true
|
||||
else if (other == D && (reg == A || reg == B)) true
|
||||
else reg == other
|
||||
}
|
||||
import MOpcode._
|
||||
(opcode, addrMode) match {
|
||||
case (_, InherentA) => reg == A
|
||||
case (_, InherentB) => reg == B
|
||||
case (PULU, set:RegisterSet) => reg == U || set.contains(reg)
|
||||
case (PULS, set:RegisterSet) => reg == S || set.contains(reg)
|
||||
case (PSHS, _) => reg == U
|
||||
case (PSHU, _) => reg == S
|
||||
case (TFR, TwoRegisters(_, dest)) => overlaps(dest)
|
||||
case (EXG, TwoRegisters(r1, r2)) => overlaps(r1) || overlaps(r2)
|
||||
case (op, _) if MOpcode.ChangesAAlways(op) => overlaps(A) || addrMode.changesRegister(reg)
|
||||
case (op, _) if MOpcode.ChangesBAlways(op) => overlaps(B) || addrMode.changesRegister(reg)
|
||||
case (LDB, _) => overlaps(B) || addrMode.changesRegister(reg)
|
||||
case (LDD, _) => overlaps(D) || addrMode.changesRegister(reg)
|
||||
case (LDU | LEAU, _) => reg == U || addrMode.changesRegister(reg)
|
||||
case (LDS | LEAS, _) => reg == S || addrMode.changesRegister(reg)
|
||||
case (LDX | LEAX, _) => reg == X || addrMode.changesRegister(reg)
|
||||
case (LDY | LEAY, _) => reg == Y || addrMode.changesRegister(reg)
|
||||
case (MUL, _) => overlaps(D)
|
||||
case (ABX, _) => reg == X
|
||||
case (NOP | SWI | SWI2 | SWI3 | SYNC, _) => false
|
||||
case _ => true // TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,9 @@ object MOpcode extends Enumeration {
|
||||
val Prefixed: Set[MOpcode.Value] = PrefixedBy10 ++ PrefixedBy11
|
||||
val CanHaveInherentAccumulator: Set[MOpcode.Value] = Set(ASL, ASR, CLR, COM, DEC, INC, LSR, NEG, ROL, ROR, TST)
|
||||
val Branching: Set[MOpcode.Value] = Set(BRA, BRN, BHI, BLS, BCC, BCS, BNE, BEQ, BVC, BVS, BPL, BMI, BGE, BLT, BGT, BLE)
|
||||
val ChangesAAlways: Set[MOpcode.Value] = Set(ADDA, ADCA, SUBA, SBCA, ANDA, ORA, EORA, SEX, DAA)
|
||||
val ChangesBAlways: Set[MOpcode.Value] = Set(ADDB, ADCB, SUBB, SBCB, ANDB, ORB, EORB)
|
||||
val ChangesDAlways: Set[MOpcode.Value] = Set(ADDD, SUBD, ANDB, ORB, EORB)
|
||||
|
||||
def lookup(opcode: String, position: Some[Position], log: Logger): (MOpcode.Value, Option[MAddrMode]) = {
|
||||
val o = opcode.toUpperCase(Locale.ROOT)
|
||||
|
68
src/main/scala/millfork/assembly/m6809/opt/CpuStatus.scala
Normal file
68
src/main/scala/millfork/assembly/m6809/opt/CpuStatus.scala
Normal file
@ -0,0 +1,68 @@
|
||||
package millfork.assembly.m6809.opt
|
||||
|
||||
import millfork.assembly.mos.State
|
||||
import millfork.assembly.opt._
|
||||
import millfork.env.Constant
|
||||
|
||||
//noinspection RedundantNewCaseClass
|
||||
case class CpuStatus(a: Status[Int] = UnknownStatus,
|
||||
b0: Status[Boolean] = UnknownStatus,
|
||||
b7: Status[Boolean] = UnknownStatus,
|
||||
memStack: Map[Int, Status[Int]] = Map(),
|
||||
b: Status[Int] = UnknownStatus,
|
||||
x: Status[Constant] = UnknownStatus,
|
||||
y: Status[Constant] = UnknownStatus,
|
||||
u: Status[Constant] = UnknownStatus,
|
||||
z: Status[Boolean] = UnknownStatus,
|
||||
n: Status[Boolean] = UnknownStatus,
|
||||
c: Status[Boolean] = UnknownStatus,
|
||||
v: Status[Boolean] = UnknownStatus
|
||||
) {
|
||||
|
||||
|
||||
override def toString: String = s"A=$a,B=$b,X=$x,Y=$y; Z=$z,N=$n,C=$c,V=$v; B7=$b7,B0=$b0"
|
||||
|
||||
def d: Status[Int] = (a, b) match {
|
||||
case (SingleStatus(h), SingleStatus(l)) => SingleStatus(h.&(0xff).<<(8).+(l&0xff))
|
||||
case (UnknownStatus, UnknownStatus) => UnknownStatus
|
||||
case _ => AnyStatus
|
||||
}
|
||||
|
||||
def nz: CpuStatus =
|
||||
this.copy(n = AnyStatus, z = AnyStatus)
|
||||
|
||||
def nz(i: Long): CpuStatus =
|
||||
this.copy(n = SingleStatus((i & 0x80) != 0), z = SingleStatus((i & 0xff) == 0))
|
||||
|
||||
def ~(that: CpuStatus) = new CpuStatus(
|
||||
a = this.a ~ that.a,
|
||||
b = this.b ~ that.b,
|
||||
b7 = this.b7 ~ that.b7,
|
||||
b0 = this.b0 ~ that.b0,
|
||||
x = this.x ~ that.x,
|
||||
y = this.y ~ that.y,
|
||||
u = this.u ~ that.u,
|
||||
memStack = (this.memStack.keySet | that.memStack.keySet).map(k => k -> (this.memStack.getOrElse(k, UnknownStatus) ~ that.memStack.getOrElse(k, UnknownStatus))).toMap,
|
||||
z = this.z ~ that.z,
|
||||
n = this.n ~ that.n,
|
||||
c = this.c ~ that.c,
|
||||
v = this.v ~ that.v
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
object CpuStatus {
|
||||
val initialStatusStandard = CpuStatus(
|
||||
a = AnyStatus,
|
||||
b = AnyStatus,
|
||||
b0 = AnyStatus,
|
||||
b7 = AnyStatus,
|
||||
x = AnyStatus,
|
||||
y = AnyStatus,
|
||||
u = AnyStatus,
|
||||
c = AnyStatus,
|
||||
v = AnyStatus,
|
||||
z = AnyStatus,
|
||||
n = AnyStatus,
|
||||
)
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package millfork.assembly.m6809.opt
|
||||
|
||||
import millfork.CompilationFlag
|
||||
import millfork.assembly.OptimizationContext
|
||||
import millfork.assembly.m6809.{MLine, MLine0}
|
||||
import millfork.assembly.opt.{AnyStatus, FlowCache, SingleStatus, Status}
|
||||
import millfork.env._
|
||||
import millfork.node.{M6809Register, NiceFunctionProperty}
|
||||
|
||||
import scala.util.control.Breaks._
|
||||
|
||||
/**
|
||||
* @author Karol Stasiak
|
||||
*/
|
||||
object ForwardFlowAnalysis {
|
||||
|
||||
val cache = new FlowCache[MLine, CpuStatus]("m6809 forward")
|
||||
|
||||
def analyze(f: NormalFunction, code: List[MLine], optimizationContext: OptimizationContext): List[CpuStatus] = {
|
||||
cache.get(code).foreach(return _)
|
||||
val compilationOptions = optimizationContext.options
|
||||
val bpInU = compilationOptions.flag(CompilationFlag.UseUForStack)
|
||||
val bpInY = compilationOptions.flag(CompilationFlag.UseYForStack)
|
||||
val BP = if (bpInU) M6809Register.U else if (bpInY) M6809Register.Y else M6809Register.CC // CC is a nonsense sentinel value
|
||||
val niceFunctionProperties = optimizationContext.niceFunctionProperties
|
||||
def extractNiceConstant[T](callee: String)(matcher: NiceFunctionProperty => Option[T]): Status[T] = {
|
||||
var result: Status[T] = AnyStatus
|
||||
breakable {
|
||||
niceFunctionProperties.foreach{ np =>
|
||||
if (np._2 == callee) matcher(np._1) match {
|
||||
case Some(x) =>
|
||||
result = SingleStatus(x)
|
||||
break
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
val initialStatus = CpuStatus.initialStatusStandard
|
||||
val functionStartStatus = CpuStatus.initialStatusStandard
|
||||
val emptyStatus = CpuStatus()
|
||||
val flagArray = Array.fill[CpuStatus](code.length)(emptyStatus)
|
||||
val codeArray = code.toArray
|
||||
|
||||
var changed = true
|
||||
while (changed) {
|
||||
changed = false
|
||||
var currentStatus: CpuStatus = functionStartStatus
|
||||
for (i <- codeArray.indices) {
|
||||
import millfork.assembly.m6809.MOpcode._
|
||||
if (flagArray(i) != currentStatus) {
|
||||
changed = true
|
||||
flagArray(i) = currentStatus
|
||||
}
|
||||
codeArray(i) match {
|
||||
case MLine0(LABEL, _, MemoryAddressConstant(Label(l))) =>
|
||||
val L = l
|
||||
currentStatus = codeArray.indices.flatMap(j => codeArray(j) match {
|
||||
case MLine0(_, _, MemoryAddressConstant(Label(L))) => Some(flagArray(j))
|
||||
case _ => None
|
||||
}).fold(currentStatus)(_ ~ _)
|
||||
|
||||
case MLine0(JSR, _, MemoryAddressConstant(th)) =>
|
||||
currentStatus = initialStatus.copy(
|
||||
memStack = currentStatus.memStack,
|
||||
u = if (bpInU) currentStatus.u else AnyStatus,
|
||||
y = if (bpInY) currentStatus.y else AnyStatus
|
||||
)
|
||||
|
||||
case MLine0(JSR | BYTE, _, _) =>
|
||||
currentStatus = initialStatus
|
||||
|
||||
case MLine0(NOP, _, _) =>
|
||||
()
|
||||
|
||||
case MLine0(opcode, addrMode, _) =>
|
||||
// TODO
|
||||
currentStatus = initialStatus
|
||||
}
|
||||
}
|
||||
// flagArray.zip(codeArray).foreach{
|
||||
// case (fl, y) => if (y.isPrintable) println(f"$fl%-32s $y%-32s")
|
||||
// }
|
||||
// println("---------------------")
|
||||
}
|
||||
|
||||
cache.put(code, flagArray.toList)
|
||||
}
|
||||
}
|
@ -26,7 +26,8 @@ object M6809Buitins {
|
||||
case (_, List(ldr@MLine0(LDB, Absolute(false), _))) if lc.last.opcode == LDB =>
|
||||
lc ++ List(ldr.copy(opcode = opcode), lc.last.copy(opcode = STB))
|
||||
case _ if lc.last.opcode == LDB =>
|
||||
lc ++ List(MLine.pp(PSHS, M6809Register.B)) ++ rc ++ List(MLine.accessAndPullS(opcode))
|
||||
// TODO: preserve X?
|
||||
lc ++ List(MLine.pp(PSHS, M6809Register.B)) ++ rc ++ List(MLine.accessAndPullS(opcode), lc.last.copy(opcode = STB))
|
||||
case _ =>
|
||||
println(lc)
|
||||
???
|
||||
|
@ -3,7 +3,7 @@ package millfork.compiler.m6809
|
||||
import millfork.assembly.Elidability
|
||||
import millfork.assembly.m6809.{Inherent, MLine, MOpcode, NonExistent}
|
||||
import millfork.compiler.{AbstractCompiler, CompilationContext}
|
||||
import millfork.env.{Constant, Label, MemoryAddressConstant}
|
||||
import millfork.env.{Constant, Label, MemoryAddressConstant, NormalParamSignature}
|
||||
|
||||
/**
|
||||
* @author Karol Stasiak
|
||||
@ -11,9 +11,17 @@ import millfork.env.{Constant, Label, MemoryAddressConstant}
|
||||
object M6809Compiler extends AbstractCompiler[MLine] {
|
||||
override def compile(ctx: CompilationContext): List[MLine] = {
|
||||
ctx.env.nameCheck(ctx.function.code)
|
||||
import MOpcode._
|
||||
val storeParamsFromRegisters = ctx.function.params match {
|
||||
case NormalParamSignature(List(param)) if param.typ.size == 1 =>
|
||||
List(MLine.absolute(STB, param.toAddress))
|
||||
case NormalParamSignature(List(param)) if param.typ.size == 2 =>
|
||||
List(MLine.absolute(STD, param.toAddress))
|
||||
case _ => Nil
|
||||
}
|
||||
val label = MLine.label(Label(ctx.function.name)).copy(elidability = Elidability.Fixed)
|
||||
val chunk = packHalves(M6809StatementCompiler.compile(ctx, new M6809StatementPreprocessor(ctx, ctx.function.code)()))
|
||||
// TODO
|
||||
label :: chunk
|
||||
// TODO: stackframe etc.
|
||||
label :: (storeParamsFromRegisters ++ chunk)
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import millfork.assembly.m6809.{DAccumulatorIndexed, Indexed, MLine, MOpcode, Tw
|
||||
import millfork.compiler.{AbstractExpressionCompiler, BranchIfFalse, BranchIfTrue, BranchSpec, ComparisonType, CompilationContext, NoBranching}
|
||||
import millfork.node.{DerefExpression, Expression, FunctionCallExpression, GeneratedConstantExpression, IndexedExpression, LhsExpression, LiteralExpression, M6809Register, SumExpression, VariableExpression}
|
||||
import millfork.assembly.m6809.MOpcode._
|
||||
import millfork.env.{Constant, ConstantBooleanType, ConstantPointy, FatBooleanType, MathOperator, MemoryVariable, NormalFunction, NormalParamSignature, NumericConstant, StackVariablePointy, Variable, VariablePointy}
|
||||
import millfork.env.{AssemblyParamSignature, Constant, ConstantBooleanType, ConstantPointy, ExternFunction, FatBooleanType, M6809RegisterVariable, MathOperator, MemoryVariable, NormalFunction, NormalParamSignature, NumericConstant, StackVariablePointy, Variable, VariablePointy}
|
||||
|
||||
import scala.collection.GenTraversableOnce
|
||||
|
||||
@ -12,7 +12,7 @@ import scala.collection.GenTraversableOnce
|
||||
* @author Karol Stasiak
|
||||
*/
|
||||
object MExpressionTarget extends Enumeration {
|
||||
val A, B, D, X, Y, NOTHING = Value
|
||||
val A, B, D, X, Y, U, NOTHING = Value
|
||||
|
||||
def toLd(r: Value): MOpcode.Value = r match {
|
||||
case A => LDA
|
||||
@ -20,18 +20,20 @@ object MExpressionTarget extends Enumeration {
|
||||
case D => LDD
|
||||
case X => LDX
|
||||
case Y => LDY
|
||||
case U => LDU
|
||||
case _ => ???
|
||||
}
|
||||
|
||||
def toLea(r: Value): MOpcode.Value = r match {
|
||||
case X => LEAX
|
||||
case Y => LEAY
|
||||
case U => LEAU
|
||||
case _ => ???
|
||||
}
|
||||
|
||||
def size(r: Value): Int = r match {
|
||||
case A | B => 1
|
||||
case D | X | Y => 2
|
||||
case D | X | Y | U => 2
|
||||
case NOTHING => 0
|
||||
}
|
||||
|
||||
@ -73,13 +75,13 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
case 1 =>
|
||||
targetSize match {
|
||||
case 0 => Nil
|
||||
case 1 => List(MLine.variable(toLd(target), variable))
|
||||
case 2 => List(MLine.variable(LDB, variable)) ++ zeroextendB(ctx, target, exprType.isSigned)
|
||||
case 1 => List(MLine.variable(ctx, toLd(target), variable))
|
||||
case 2 => List(MLine.variable(ctx, LDB, variable)) ++ zeroextendB(ctx, target, exprType.isSigned)
|
||||
}
|
||||
case 2 =>
|
||||
targetSize match {
|
||||
case 0 => Nil
|
||||
case 2 => List(MLine.variable(toLd(target), variable))
|
||||
case 2 => List(MLine.variable(ctx, toLd(target), variable))
|
||||
}
|
||||
}
|
||||
case LiteralExpression(c, _) =>
|
||||
@ -89,6 +91,45 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
}
|
||||
case DerefExpression(inner, offset, _) =>
|
||||
compileToX(ctx, inner) :+ MLine(toLd(target), Indexed(M6809Register.X, indirect = false), NumericConstant(offset, 2))
|
||||
case IndexedExpression(name, index) =>
|
||||
env.getPointy(name) match {
|
||||
case c: ConstantPointy =>
|
||||
val (variableIndex, constIndex) = env.evalVariableAndConstantSubParts(index)
|
||||
val constantOffset = (c.value + constIndex).quickSimplify
|
||||
variableIndex match {
|
||||
case (Some(ix)) =>
|
||||
compileToX(ctx, ix) ++ (
|
||||
targetSize match {
|
||||
case 0 => Nil
|
||||
case 1 => List(MLine.indexedX(toLd(target), constantOffset))
|
||||
case 2 => List(MLine.indexedX(LDB, constantOffset)) ++ zeroextendB(ctx, target, exprType.isSigned)
|
||||
})
|
||||
case None =>
|
||||
targetSize match {
|
||||
case 0 => Nil
|
||||
case 1 => List(MLine.absolute(toLd(target), constantOffset))
|
||||
case 2 => List(MLine.absolute(LDB, constantOffset)) ++ zeroextendB(ctx, target, exprType.isSigned)
|
||||
}
|
||||
}
|
||||
case v:VariablePointy =>
|
||||
val (prepareIndex, offset): (List[MLine], Constant) = ctx.env.eval(index) match {
|
||||
case Some(ix) => List(MLine.absolute(LDX, v.addr)) -> (ix * v.elementType.size).quickSimplify
|
||||
case _ =>
|
||||
v.indexType.size match {
|
||||
case 1 =>
|
||||
(compileToD(ctx, index) :+ MLine(LEAX, DAccumulatorIndexed(M6809Register.X, indirect = false), Constant.Zero)) -> Constant.Zero
|
||||
}
|
||||
}
|
||||
prepareIndex ++ (targetSize match {
|
||||
case 0 => Nil
|
||||
case 1 => List(MLine.indexedX(toLd(target), offset))
|
||||
case 2 => List(MLine.indexedX(LDB, offset)) ++ zeroextendB(ctx, target, exprType.isSigned)
|
||||
})
|
||||
case v:StackVariablePointy =>
|
||||
ctx.env.eval(index) match {
|
||||
case Some(ix) => List(MLine.variablestack(ctx, LDX, v.offset), MLine.indexedX(LDB, ix * v.elementType.size))
|
||||
}
|
||||
}
|
||||
case e@SumExpression(expressions, decimal) =>
|
||||
getArithmeticParamMaxSize(ctx, expressions.map(_._2)) match {
|
||||
case 1 => M6809Buitins.compileByteSum(ctx, e, fromScratch = true) ++ targetifyB(ctx, target, isSigned = false)
|
||||
@ -112,12 +153,12 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
case 1 => M6809Buitins.compileByteBitwise(ctx, params, fromScratch = true, ANDB, MathOperator.And, 0xff) ++ targetifyB(ctx, target, isSigned = false)
|
||||
case 2 => M6809Buitins.compileWordBitwise(ctx, params, fromScratch = true, ANDA, ANDB, MathOperator.And, 0xffff) ++ targetifyB(ctx, target, isSigned = false)
|
||||
}
|
||||
case "|" => ???
|
||||
case "|" =>
|
||||
getArithmeticParamMaxSize(ctx, params) match {
|
||||
case 1 => M6809Buitins.compileByteBitwise(ctx, params, fromScratch = true, ORB, MathOperator.Or, 0) ++ targetifyB(ctx, target, isSigned = false)
|
||||
case 2 => M6809Buitins.compileWordBitwise(ctx, params, fromScratch = true, ORA, ORB, MathOperator.Or, 0) ++ targetifyB(ctx, target, isSigned = false)
|
||||
}
|
||||
case "^" => ???
|
||||
case "^" =>
|
||||
getArithmeticParamMaxSize(ctx, params) match {
|
||||
case 1 => M6809Buitins.compileByteBitwise(ctx, params, fromScratch = true, EORB, MathOperator.Exor, 0) ++ targetifyB(ctx, target, isSigned = false)
|
||||
case 2 => M6809Buitins.compileWordBitwise(ctx, params, fromScratch = true, EORA, EORB, MathOperator.Exor, 0) ++ targetifyB(ctx, target, isSigned = false)
|
||||
@ -242,32 +283,71 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
case ">>>>=" => ???
|
||||
case _ =>
|
||||
val f = lookupFunction(ctx, fce)
|
||||
f.params match {
|
||||
case NormalParamSignature(Nil) => //ok
|
||||
val prepareParams: List[MLine] = f.params match {
|
||||
case NormalParamSignature(List(param)) if param.typ.size == 1 =>
|
||||
compileToB(ctx, params.head)
|
||||
case NormalParamSignature(List(param)) if param.typ.size == 2 =>
|
||||
compileToD(ctx, params.head)
|
||||
case NormalParamSignature(signature) =>
|
||||
params.zip(signature).flatMap { case (paramExpr, paramVar) =>
|
||||
val callCtx = callingContext(ctx, f.name, paramVar)
|
||||
paramVar.typ.size match {
|
||||
case 1 =>
|
||||
compileToB(ctx, paramExpr) ++ storeB(callCtx, VariableExpression(paramVar.name + "`aa"))
|
||||
case 2 =>
|
||||
compileToD(ctx, paramExpr) ++ storeD(callCtx, VariableExpression(paramVar.name + "`aa"))
|
||||
case _ =>
|
||||
???
|
||||
}
|
||||
}
|
||||
case AssemblyParamSignature(signature) =>
|
||||
params.zip(signature).flatMap { case (e, a) =>
|
||||
val compiled = a.variable match {
|
||||
case M6809RegisterVariable(M6809Register.A, _) => compileToA(ctx, e)
|
||||
case M6809RegisterVariable(M6809Register.B, _) => compileToB(ctx, e)
|
||||
case M6809RegisterVariable(M6809Register.D, _) => compileToD(ctx, e)
|
||||
case M6809RegisterVariable(M6809Register.X, _) => compileToX(ctx, e)
|
||||
case M6809RegisterVariable(M6809Register.Y, _) => compileToY(ctx, e)
|
||||
case M6809RegisterVariable(M6809Register.U, _) => compileToU(ctx, e)
|
||||
case _ => ???
|
||||
}
|
||||
if (compiled.length > 1) ???
|
||||
compiled
|
||||
}
|
||||
case _ => ???
|
||||
}
|
||||
f match {
|
||||
val actualCall = f match {
|
||||
case nf:NormalFunction =>
|
||||
List(MLine.absolute(JSR, nf.toAddress))
|
||||
case nf:ExternFunction =>
|
||||
List(MLine.absolute(JSR, nf.toAddress))
|
||||
case _ => ???
|
||||
}
|
||||
prepareParams ++ actualCall
|
||||
}
|
||||
case _ => ???
|
||||
}
|
||||
}
|
||||
|
||||
def compileToA(ctx: CompilationContext, expr: Expression): List[MLine] = compile(ctx, expr, MExpressionTarget.A)
|
||||
|
||||
def compileToB(ctx: CompilationContext, expr: Expression): List[MLine] = compile(ctx, expr, MExpressionTarget.B)
|
||||
|
||||
def compileToD(ctx: CompilationContext, expr: Expression): List[MLine] = compile(ctx, expr, MExpressionTarget.D)
|
||||
|
||||
def compileToX(ctx: CompilationContext, expr: Expression): List[MLine] = compile(ctx, expr, MExpressionTarget.X)
|
||||
|
||||
def compileToY(ctx: CompilationContext, expr: Expression): List[MLine] = compile(ctx, expr, MExpressionTarget.Y)
|
||||
|
||||
def compileToU(ctx: CompilationContext, expr: Expression): List[MLine] = compile(ctx, expr, MExpressionTarget.U)
|
||||
|
||||
def zeroextendB(ctx: CompilationContext, target: MExpressionTarget.Value, isSigned: Boolean): List[MLine] = {
|
||||
val extendToA = if (isSigned) MLine.immediate(LDA, 0) else MLine.inherent(SEX)
|
||||
val extendToA = if (isSigned) MLine.inherent(SEX) else MLine.immediate(LDA, 0)
|
||||
target match {
|
||||
case MExpressionTarget.D => List(extendToA)
|
||||
case MExpressionTarget.X => List(extendToA, MLine.tfr(M6809Register.D, M6809Register.X))
|
||||
case MExpressionTarget.Y => List(extendToA, MLine.tfr(M6809Register.D, M6809Register.Y))
|
||||
case MExpressionTarget.U => List(extendToA, MLine.tfr(M6809Register.D, M6809Register.U))
|
||||
case _ => ???
|
||||
}
|
||||
}
|
||||
@ -281,27 +361,34 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
target match {
|
||||
case VariableExpression(name) =>
|
||||
val variable = ctx.env.get[Variable](name)
|
||||
List(MLine.variable(STB, variable))
|
||||
List(MLine.variable(ctx, STB, variable))
|
||||
case DerefExpression(inner, offset, _) =>
|
||||
compileToX(ctx, inner) :+ MLine(STB, Indexed(M6809Register.X, indirect = false), NumericConstant(offset, 2))
|
||||
compileToX(ctx, inner) :+ MLine.indexedX(STB, NumericConstant(offset, 2))
|
||||
case IndexedExpression(name, index) =>
|
||||
ctx.env.getPointy(name) match {
|
||||
case p: ConstantPointy =>
|
||||
compileToX(ctx, index) :+ MLine(STB, Indexed(M6809Register.X, indirect = false), p.value)
|
||||
val (variableIndex, constOffset) = ctx.env.evalVariableAndConstantSubParts(index)
|
||||
val effectiveBase = (p.value + constOffset).quickSimplify
|
||||
variableIndex match {
|
||||
case Some(ix) =>
|
||||
stashBIfNeeded(ctx, compileToX(ctx, ix)) :+ MLine.indexedX(STB, effectiveBase)
|
||||
case None =>
|
||||
List(MLine.absolute(STB, effectiveBase))
|
||||
}
|
||||
case v: VariablePointy =>
|
||||
ctx.env.eval(index) match {
|
||||
case Some(ix) => List(MLine.absolute(LDX, v.addr), MLine(STB, Indexed(M6809Register.X, indirect = false), ix * v.elementType.size))
|
||||
case Some(ix) => List(MLine.absolute(LDX, v.addr), MLine.indexedX(STB, ix * v.elementType.size))
|
||||
case _ =>
|
||||
v.indexType.size match {
|
||||
case 1 =>
|
||||
stashBIfNeeded(ctx,
|
||||
compileToD(ctx, index) :+ MLine(LEAX, DAccumulatorIndexed(M6809Register.X, indirect = false), Constant.Zero)) :+
|
||||
MLine(STB, Indexed(M6809Register.X, indirect = false), Constant.Zero)
|
||||
MLine.indexedX(STB, Constant.Zero)
|
||||
}
|
||||
}
|
||||
case v: StackVariablePointy =>
|
||||
ctx.env.eval(index) match {
|
||||
case Some(ix) => List(MLine.userstack(LDX, v.offset), MLine(STB, Indexed(M6809Register.X, indirect = false), ix * v.elementType.size))
|
||||
case Some(ix) => List(MLine.variablestack(ctx, LDX, v.offset), MLine.indexedX(STB, ix * v.elementType.size))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -311,7 +398,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
target match {
|
||||
case VariableExpression(name) =>
|
||||
val variable = ctx.env.get[Variable](name)
|
||||
List(MLine.variable(STD, variable))
|
||||
List(MLine.variable(ctx, STD, variable))
|
||||
case DerefExpression(inner, offset, _) =>
|
||||
compileToX(ctx, inner) :+ MLine(STD, Indexed(M6809Register.X, indirect = false), NumericConstant(offset, 2))
|
||||
}
|
||||
@ -321,14 +408,14 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
case MExpressionTarget.NOTHING => Nil
|
||||
case MExpressionTarget.B => Nil
|
||||
case MExpressionTarget.A => List(MLine.tfr(M6809Register.B, M6809Register.A))
|
||||
case MExpressionTarget.D | MExpressionTarget.X | MExpressionTarget.Y => zeroextendB(ctx, target, isSigned)
|
||||
case MExpressionTarget.D | MExpressionTarget.X | MExpressionTarget.Y | MExpressionTarget.U => zeroextendB(ctx, target, isSigned)
|
||||
}
|
||||
|
||||
def targetifyA(ctx: CompilationContext, target: MExpressionTarget.Value, isSigned: Boolean): List[MLine] = target match {
|
||||
case MExpressionTarget.NOTHING => Nil
|
||||
case MExpressionTarget.A => Nil
|
||||
case MExpressionTarget.B => List(MLine.tfr(M6809Register.A, M6809Register.B))
|
||||
case MExpressionTarget.D | MExpressionTarget.X | MExpressionTarget.Y =>
|
||||
case MExpressionTarget.D | MExpressionTarget.X | MExpressionTarget.Y | MExpressionTarget.U =>
|
||||
List(MLine.tfr(M6809Register.A, M6809Register.B)) ++ zeroextendB(ctx, target, isSigned)
|
||||
}
|
||||
|
||||
@ -337,6 +424,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
case MExpressionTarget.D => Nil
|
||||
case MExpressionTarget.X => List(MLine.tfr(M6809Register.D, M6809Register.X))
|
||||
case MExpressionTarget.Y => List(MLine.tfr(M6809Register.D, M6809Register.Y))
|
||||
case MExpressionTarget.U => List(MLine.tfr(M6809Register.D, M6809Register.U))
|
||||
}
|
||||
|
||||
|
||||
|
8
src/main/scala/millfork/env/Constant.scala
vendored
8
src/main/scala/millfork/env/Constant.scala
vendored
@ -81,6 +81,14 @@ sealed trait Constant {
|
||||
}
|
||||
}
|
||||
|
||||
def subwordReversed(index: Int): Constant = {
|
||||
if (requiredSize <= index) Constant.Zero
|
||||
else {
|
||||
// TODO: check if ok
|
||||
CompoundConstant(MathOperator.Or, CompoundConstant(MathOperator.Shl, subbyte(index), NumericConstant(8, 1)), subbyte(index + 1)).quickSimplify
|
||||
}
|
||||
}
|
||||
|
||||
def subconstant(offset: Int, length: Int): Constant = {
|
||||
if (offset == 0 && length == requiredSize) {
|
||||
this
|
||||
|
@ -142,7 +142,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
|
||||
s.typ.size match {
|
||||
case 0 => 0
|
||||
case 1 => deepConstResolve(s.subbyte(0))
|
||||
case 2 => deepConstResolve(s.subword(0)) // TODO: endianness?
|
||||
case 2 => if (platform.isBigEndian) deepConstResolve(s.subwordReversed(0)) else deepConstResolve(s.subword(0)) // TODO: endianness?
|
||||
case _ => ???
|
||||
}
|
||||
case CompoundConstant(operator, lc, rc) =>
|
||||
|
@ -90,12 +90,12 @@ class M6809Assembler(program: Program,
|
||||
case MLine0(TFR, TwoRegisters(source, target), param)
|
||||
if M6809Register.registerSize(source) == M6809Register.registerSize(target) && param.isProvablyZero =>
|
||||
writeByte(bank, index, 0x1f)
|
||||
writeByte(bank, index, registerCode(source) * 16 + registerCode(target))
|
||||
writeByte(bank, index + 1, registerCode(source) * 16 + registerCode(target))
|
||||
index + 2
|
||||
case MLine0(EXG, TwoRegisters(source, target), param)
|
||||
if M6809Register.registerSize(source) == M6809Register.registerSize(target) && param.isProvablyZero =>
|
||||
writeByte(bank, index, 0x1e)
|
||||
writeByte(bank, index, registerCode(source) * 16 + registerCode(target))
|
||||
writeByte(bank, index + 1, registerCode(source) * 16 + registerCode(target))
|
||||
index + 2
|
||||
case l@MLine0(op, RegisterSet(set), param) if param.isProvablyZero && M6809Assembler.pushpull.contains(op) =>
|
||||
writeByte(bank, index, M6809Assembler.pushpull(op))
|
||||
|
@ -29,6 +29,7 @@ case class M6809Parser(filename: String,
|
||||
case "d" => ByM6809Register(M6809Register.D)
|
||||
case "x" => ByM6809Register(M6809Register.X)
|
||||
case "y" => ByM6809Register(M6809Register.Y)
|
||||
case "u" => ByM6809Register(M6809Register.U)
|
||||
case x => log.fatal(s"Unknown assembly parameter passing convention: `$x`")
|
||||
}
|
||||
override val asmParamDefinition: P[ParameterDeclaration] = for {
|
||||
|
@ -28,7 +28,7 @@ class ArraySuite extends FunSuite with Matchers with AppendedClues {
|
||||
m.readByte(0xc000) should equal(5)
|
||||
m.readByte(0xc001) should equal(6)
|
||||
m.readByte(0xc002) should equal(7)
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)(src) { m =>
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)(src) { m =>
|
||||
m.readByte(0xc000) should equal(5)
|
||||
m.readByte(0xc001) should equal(6)
|
||||
m.readByte(0xc002) should equal(7)
|
||||
@ -53,7 +53,7 @@ class ArraySuite extends FunSuite with Matchers with AppendedClues {
|
||||
m.readByte(0xc002) should equal(1)
|
||||
m.readByte(0xc007) should equal(6)
|
||||
}
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)(src) { m =>
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)(src) { m =>
|
||||
m.readByte(0xc002) should equal(1)
|
||||
m.readByte(0xc007) should equal(6)
|
||||
}
|
||||
@ -118,7 +118,7 @@ class ArraySuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Array simple read") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| array a[7]
|
||||
|
@ -63,7 +63,7 @@ class ByteMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("In-place byte addition") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)(
|
||||
"""
|
||||
| array output[3] @$c000
|
||||
| byte a
|
||||
@ -77,7 +77,7 @@ class ByteMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("LHS evaluation during in-place byte addition") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)(
|
||||
"""
|
||||
| array output[1] @$c000
|
||||
| byte call_count @$c001
|
||||
@ -97,7 +97,7 @@ class ByteMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Parameter order") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| array arr[6]
|
||||
@ -179,7 +179,7 @@ class ByteMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
private def multiplyCase2(x: Int, y: Int): Unit = {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)(
|
||||
s"""
|
||||
| import zp_reg
|
||||
| byte output @$$c000
|
||||
|
@ -22,6 +22,7 @@ class M6809Memory(memoryBank: MemoryBank, resetVector: Int) extends MemorySegmen
|
||||
|
||||
override def load(addr: Int): Int = {
|
||||
if (!memoryBank.readable(addr)) {
|
||||
println(s"Accessing memory for read at $$${addr.toHexString}")
|
||||
???
|
||||
}
|
||||
memoryBank.readByte(addr)
|
||||
@ -29,6 +30,7 @@ class M6809Memory(memoryBank: MemoryBank, resetVector: Int) extends MemorySegmen
|
||||
|
||||
override def store(addr: Int, `val`: Int): Unit = {
|
||||
if (!memoryBank.writeable(addr)) {
|
||||
println(s"Accessing memory for write at $$${addr.toHexString}")
|
||||
???
|
||||
}
|
||||
memoryBank.output(addr) = `val`.toByte
|
||||
|
Loading…
Reference in New Issue
Block a user