mirror of https://github.com/KarolS/millfork.git
655 lines
25 KiB
Scala
655 lines
25 KiB
Scala
package millfork
|
|
|
|
import millfork.buildinfo.BuildInfo
|
|
import millfork.compiler.LabelGenerator
|
|
import millfork.error.{ConsoleLogger, Logger}
|
|
import millfork.parser.TextCodecRepository
|
|
|
|
/**
|
|
* @author Karol Stasiak
|
|
*/
|
|
case class CompilationOptions(platform: Platform,
|
|
commandLineFlags: Map[CompilationFlag.Value, Boolean],
|
|
outputFileName: Option[String],
|
|
zpRegisterSize: Int,
|
|
featureOverrides: Map[String, Long],
|
|
textCodecRepository: TextCodecRepository,
|
|
jobContext: JobContext) {
|
|
|
|
import CompilationFlag._
|
|
import Cpu._
|
|
|
|
@inline
|
|
def log: Logger = jobContext.log
|
|
@inline
|
|
def nextLabel: LabelGenerator = jobContext.nextLabel
|
|
@inline
|
|
def isBigEndian: Boolean = platform.isBigEndian
|
|
|
|
val flags: Map[CompilationFlag.Value, Boolean] = CompilationFlag.values.map { f =>
|
|
f -> commandLineFlags.getOrElse(f, platform.flagOverrides.getOrElse(f, Cpu.defaultFlags(platform.cpu)(f)))
|
|
}.toMap
|
|
|
|
def flag(f: CompilationFlag.Value): Boolean = flags(f)
|
|
|
|
{
|
|
log.setFatalWarnings(flags(CompilationFlag.FatalWarnings))
|
|
|
|
var invalids = Set[CompilationFlag.Value]()
|
|
|
|
if (CpuFamily.forType(platform.cpu) != CpuFamily.M6502) invalids ++= Set(
|
|
EmitCmosOpcodes, EmitCmosNopOpcodes, EmitHudsonOpcodes, EmitSC02Opcodes, EmitRockwellOpcodes, EmitWdcOpcodes, Emit65CE02Opcodes, EmitEmulation65816Opcodes, EmitNative65816Opcodes, LUnixRelocatableCode,
|
|
PreventJmpIndirectBug, LargeCode, ReturnWordsViaAccumulator, LUnixRelocatableCode, RorWarning, SoftwareStack)
|
|
|
|
if (CpuFamily.forType(platform.cpu) != CpuFamily.I80 && CpuFamily.forType(platform.cpu) != CpuFamily.I86) invalids ++= Set(
|
|
EmitIntel8085Opcodes, EmitIntel8080Opcodes, UseIxForStack, UseIntelSyntaxForInput, UseIntelSyntaxForOutput)
|
|
|
|
if (CpuFamily.forType(platform.cpu) != CpuFamily.I80) invalids ++= Set(
|
|
EmitExtended80Opcodes, EmitZ80Opcodes, EmitSharpOpcodes, EmitEZ80Opcodes, EmitZ80NextOpcodes,
|
|
UseIyForStack, UseIxForScratch, UseIyForScratch, UseShadowRegistersForInterrupts)
|
|
|
|
if (CpuFamily.forType(platform.cpu) != CpuFamily.M6809) invalids ++= Set(
|
|
UseUForStack, UseYForStack)
|
|
|
|
invalids = invalids.filter(flags)
|
|
|
|
if (invalids.nonEmpty) {
|
|
log.error("Invalid flags enabled for the current CPU family: " + invalids.mkString(", "))
|
|
}
|
|
if (CpuFamily.forType(platform.cpu) != CpuFamily.M6502 && zpRegisterSize > 0) {
|
|
log.error("Invalid flags enabled for the current CPU family: zp_register")
|
|
}
|
|
CpuFamily.forType(platform.cpu) match {
|
|
case CpuFamily.M6502 =>
|
|
if (flags(DecimalMode)) {
|
|
if (platform.cpu == Ricoh || platform.cpu == StrictRicoh) {
|
|
log.warn("Decimal mode enabled for Ricoh architecture")
|
|
}
|
|
}
|
|
if (platform.cpu == Sixteen) {
|
|
if (flags(LargeCode)) {
|
|
log.warn("Large code model doesn't work correctly yet")
|
|
}
|
|
}
|
|
if (platform.cpu != Sixteen) {
|
|
if (flags(LargeCode)) {
|
|
log.error("Cannot use large code model on architectures other than 65816")
|
|
}
|
|
if (flags(ReturnWordsViaAccumulator)) {
|
|
log.error("Cannot return words via accumulator on non-65816 architecture")
|
|
}
|
|
if (flags(EmitNative65816Opcodes) || flags(EmitEmulation65816Opcodes)) {
|
|
log.error("65816 opcodes enabled for non-65816 architecture")
|
|
}
|
|
}
|
|
if (platform.cpu != CE02) {
|
|
if (flags(Emit65CE02Opcodes)) {
|
|
log.error("65CE02 opcodes enabled for non-65CE02 architecture")
|
|
}
|
|
}
|
|
if (flags(Emit65CE02Opcodes)) {
|
|
log.warn("65CE02 opcodes are highly experimental")
|
|
}
|
|
if (platform.cpu != HuC6280) {
|
|
if (flags(EmitHudsonOpcodes)) {
|
|
log.error("HuC6280 opcodes enabled for non-HuC6280 architecture")
|
|
}
|
|
}
|
|
if (!CmosCompatible(platform.cpu)) {
|
|
if (!flags(PreventJmpIndirectBug)) {
|
|
log.warn("JMP bug prevention should be enabled for non-CMOS architecture")
|
|
}
|
|
if (flags(EmitCmosOpcodes)) {
|
|
log.error("CMOS opcodes enabled for non-CMOS architecture")
|
|
}
|
|
}
|
|
if (flags(EmitIllegals)) {
|
|
if (CmosCompatible(platform.cpu)) {
|
|
log.error("Illegal opcodes enabled for architecture that doesn't support them")
|
|
}
|
|
if (platform.cpu == StrictRicoh || platform.cpu == StrictMos) {
|
|
log.warn("Illegal opcodes enabled for strict architecture")
|
|
}
|
|
}
|
|
case CpuFamily.I80 =>
|
|
if (flags(EmitIllegals)) {
|
|
if (platform.cpu != Z80 && platform.cpu != Intel8085 && platform.cpu != Z80Next) {
|
|
log.error("Illegal opcodes enabled for architecture that doesn't support them")
|
|
}
|
|
}
|
|
if (flags(UseIxForStack) || flags(UseIxForScratch)) {
|
|
if (!Z80Compatible(platform.cpu)) {
|
|
log.error("IX register enabled for architecture that doesn't support it")
|
|
} else if (!flags(EmitZ80Opcodes)) {
|
|
log.error("IX register is enabled but instructions using it are disabled")
|
|
}
|
|
}
|
|
if (flags(UseIyForStack) || flags(UseIyForScratch)) {
|
|
if (!Z80Compatible(platform.cpu)) {
|
|
log.error("IY register enabled for architecture that doesn't support it")
|
|
} else if (!flags(EmitZ80Opcodes)) {
|
|
log.error("IY register is enabled but instructions using it are disabled")
|
|
}
|
|
}
|
|
if (flags(UseIxForScratch) && flags(UseIxForStack)) {
|
|
log.error("Cannot use the IX register for both stack variables and scratch simultaneously")
|
|
}
|
|
if (flags(UseIyForScratch) && flags(UseIyForStack)) {
|
|
log.error("Cannot use the IY register for both stack variables and scratch simultaneously")
|
|
}
|
|
if (flags(UseIxForStack) && flags(UseIyForStack)) {
|
|
log.error("Cannot use both IX and IY registers for stack variables simultaneously")
|
|
}
|
|
if (flags(UseShadowRegistersForInterrupts)) {
|
|
if (!Z80Compatible(platform.cpu)) {
|
|
log.error("Shadow registers enabled for architecture that doesn't support them")
|
|
} else if (!flags(EmitZ80Opcodes)) {
|
|
log.error("Shadow registers are enabled but instructions using them are disabled")
|
|
}
|
|
}
|
|
if (flags(EmitZ80Opcodes)) {
|
|
if (!Z80Compatible(platform.cpu)) {
|
|
log.error("Z80 opcodes enabled for architecture that doesn't support them")
|
|
}
|
|
}
|
|
if (flags(EmitEZ80Opcodes)) {
|
|
if (platform.cpu != EZ80) {
|
|
log.error("eZ80 opcodes enabled for architecture that doesn't support them")
|
|
}
|
|
}
|
|
if (flags(EmitSharpOpcodes)) {
|
|
if (platform.cpu != Sharp) {
|
|
log.error("Sharp LR35902 opcodes enabled for architecture that doesn't support them")
|
|
}
|
|
}
|
|
if (flags(EmitZ80NextOpcodes)) {
|
|
if (platform.cpu != Z80Next) {
|
|
log.error("ZX Spectrum Next opcodes enabled for architecture that doesn't support them")
|
|
}
|
|
}
|
|
if (flags(EmitExtended80Opcodes)) {
|
|
if (platform.cpu != Sharp && !Z80Compatible(platform.cpu)) {
|
|
log.error("Extended 8080-like opcodes enabled for architecture that doesn't support them")
|
|
}
|
|
}
|
|
if (flags(EmitIntel8080Opcodes)) {
|
|
if (!Intel8080Compatible(platform.cpu)) {
|
|
log.error("Intel 8080 opcodes enabled for architecture that doesn't support them")
|
|
}
|
|
}
|
|
if (flags(EmitIntel8085Opcodes)) {
|
|
if (!Intel8085Compatible(platform.cpu)) {
|
|
log.error("Intel 8085 opcodes enabled for architecture that doesn't support them")
|
|
}
|
|
}
|
|
if (!flags(CompilationFlag.EmitSharpOpcodes) && !flags(CompilationFlag.EmitIntel8080Opcodes)) {
|
|
log.error("Either Sharp LR35902 or Intel 8080 opcodes have to be enabled")
|
|
}
|
|
case CpuFamily.I86 =>
|
|
case CpuFamily.M6809 =>
|
|
if (flags(UseUForStack) && flags(UseYForStack)) {
|
|
log.error("Cannot use both U and Y registers for stack variables simultaneously")
|
|
}
|
|
if (!flags(UseUForStack) && !flags(UseYForStack)) {
|
|
log.error("You need to use either the U register or the Y register as the base pointer. This might be relaxed in the future.")
|
|
}
|
|
}
|
|
}
|
|
|
|
private def parseVersion(): Long = {
|
|
val tokens = BuildInfo.version.split("[.-]")
|
|
|
|
def extract(ix: Int):Int = {
|
|
tokens.lift(ix).filter(_ != "SNAPSHOT").getOrElse("0").toInt
|
|
}
|
|
|
|
val major = extract(0)
|
|
val minor = extract(1)
|
|
val patch = extract(2)
|
|
major * 10000 + minor * 100 + patch
|
|
}
|
|
|
|
def features: Map[String, Long] = {
|
|
@inline
|
|
def toLong(b: Boolean): Long = if (b) 1L else 0L
|
|
val featuresFromOptions = Map[String, Long](
|
|
"MILLFORK_VERSION" -> parseVersion(),
|
|
"OPTIMIZE_FOR_SIZE" -> toLong(flag(CompilationFlag.OptimizeForSize)),
|
|
"OPTIMIZE_FOR_SPEED" -> toLong(flag(CompilationFlag.OptimizeForSpeed)),
|
|
"OPTIMIZE_INLINE" -> toLong(flag(CompilationFlag.InlineFunctions)),
|
|
"OPTIMIZE_IPO" -> toLong(flag(CompilationFlag.InterproceduralOptimization)),
|
|
"CPUFEATURE_DECIMAL_MODE" -> toLong(flag(CompilationFlag.DecimalMode)),
|
|
"CPUFEATURE_Z80" -> toLong(flag(CompilationFlag.EmitZ80Opcodes)),
|
|
"CPUFEATURE_EZ80" -> toLong(flag(CompilationFlag.EmitEZ80Opcodes)),
|
|
"CPUFEATURE_8080" -> toLong(flag(CompilationFlag.EmitIntel8080Opcodes)),
|
|
"CPUFEATURE_8085" -> toLong(flag(CompilationFlag.EmitIntel8085Opcodes)),
|
|
"CPUFEATURE_GAMEBOY" -> toLong(flag(CompilationFlag.EmitSharpOpcodes)),
|
|
"CPUFEATURE_65C02" -> toLong(flag(CompilationFlag.EmitCmosOpcodes)),
|
|
"CPUFEATURE_65SC02" -> toLong(flag(CompilationFlag.EmitSC02Opcodes)),
|
|
"CPUFEATURE_ROCKWELL_65C02" -> toLong(flag(CompilationFlag.EmitRockwellOpcodes)),
|
|
"CPUFEATURE_WDC_65C02" -> toLong(flag(CompilationFlag.EmitWdcOpcodes)),
|
|
"CPUFEATURE_65CE02" -> toLong(flag(CompilationFlag.Emit65CE02Opcodes)),
|
|
"CPUFEATURE_HUC6280" -> toLong(flag(CompilationFlag.EmitHudsonOpcodes)),
|
|
"CPUFEATURE_65816_EMULATION" -> toLong(flag(CompilationFlag.EmitEmulation65816Opcodes)),
|
|
"CPUFEATURE_65816_NATIVE" -> toLong(flag(CompilationFlag.EmitNative65816Opcodes)),
|
|
"CPUFEATURE_6502_ILLEGALS" -> toLong(platform.cpuFamily == CpuFamily.M6502 && flag(CompilationFlag.EmitIllegals)),
|
|
"CPUFEATURE_Z80_ILLEGALS" -> toLong(flag(CompilationFlag.EmitZ80Opcodes) && flag(CompilationFlag.EmitIllegals)),
|
|
"CPUFEATURE_Z80_NEXT" -> toLong(flag(CompilationFlag.EmitZ80NextOpcodes)),
|
|
"CPUFEATURE_8085_ILLEGALS" -> toLong(flag(CompilationFlag.EmitIntel8080Opcodes) && flag(CompilationFlag.EmitIllegals)),
|
|
"BIG_ENDIAN" -> toLong(Cpu.isBigEndian(platform.cpu)),
|
|
"LITTLE_ENDIAN" -> toLong(!Cpu.isBigEndian(platform.cpu)),
|
|
"INIT_RW_MEMORY" -> toLong(platform.ramInitialValuesBank.isDefined),
|
|
"SYNTAX_INTEL" -> toLong(platform.cpuFamily == CpuFamily.I80 && flag(CompilationFlag.UseIntelSyntaxForInput)),
|
|
"SYNTAX_ZILOG" -> toLong(platform.cpuFamily == CpuFamily.I80 && !flag(CompilationFlag.UseIntelSyntaxForInput)),
|
|
"TINY_RW_MEMORY" -> toLong(platform.variableAllocators("default").totalHimemSize <= 256),
|
|
"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)
|
|
)
|
|
platform.features ++ featuresFromOptions ++ featureOverrides
|
|
}
|
|
|
|
}
|
|
|
|
object CpuFamily extends Enumeration {
|
|
/**
|
|
* Family based on the MOS 6502 processor and its descendants
|
|
*/
|
|
val M6502: CpuFamily.Value = Value
|
|
/**
|
|
* Family based on the Intel 8080 processor and similar architectures
|
|
*/
|
|
val I80: CpuFamily.Value = Value
|
|
/**
|
|
* Family based on the Motorola 6800 processor
|
|
*/
|
|
val M6800: CpuFamily.Value = Value
|
|
/**
|
|
* Family based on the Motorola 6809 processor
|
|
*/
|
|
val M6809: CpuFamily.Value = Value
|
|
/**
|
|
* Family based on the Intel 8086/8088 processor and its descendants
|
|
*/
|
|
val I86: CpuFamily.Value = Value
|
|
/**
|
|
* Family based on the Motorola 68000 processor and its descendants
|
|
*/
|
|
val M68K: CpuFamily.Value = Value
|
|
/**
|
|
* Family based on the ARM processors
|
|
*/
|
|
val ARM: CpuFamily.Value = Value
|
|
|
|
def forType(cpu: Cpu.Value): CpuFamily.Value = {
|
|
import Cpu._
|
|
cpu match {
|
|
case Mos | StrictMos | Ricoh | StrictRicoh | Cmos | SC02 | Rockwell | Wdc | HuC6280 | CE02 | Sixteen => M6502
|
|
case Intel8080 | Intel8085 | StrictIntel8085 | Sharp | Z80 | StrictZ80 | EZ80 | Z80Next => I80
|
|
case Intel8086 | Intel80186 => I86
|
|
case Cpu.Motorola6809 => M6809
|
|
}
|
|
}
|
|
|
|
def isBigEndian(family: CpuFamily.Value): Boolean = family match {
|
|
case M6502 | I80 | I86 | ARM => false
|
|
case M6800 | M6809 | M68K => true
|
|
}
|
|
}
|
|
|
|
object Cpu extends Enumeration {
|
|
|
|
/**
|
|
* The MOS 6502/6507/6510 processor
|
|
*/
|
|
val Mos: Cpu.Value = Value
|
|
/**
|
|
* The MOS 6502/6507/6510 processor, without illegal instructions
|
|
*/
|
|
val StrictMos: Cpu.Value = Value
|
|
/**
|
|
* The Ricoh 2A03/2A07 processor
|
|
*/
|
|
val Ricoh: Cpu.Value = Value
|
|
/**
|
|
* The Ricoh 2A03/2A07 processor, without illegal instructions
|
|
*/
|
|
val StrictRicoh: Cpu.Value = Value
|
|
/**
|
|
* The base 65C02 processor
|
|
*/
|
|
val Cmos: Cpu.Value = Value
|
|
/**
|
|
* The 65SC02 processor
|
|
*/
|
|
val SC02: Cpu.Value = Value
|
|
/**
|
|
* The Rockwell 65C02 processor
|
|
*/
|
|
val Rockwell: Cpu.Value = Value
|
|
/**
|
|
* The WDC 65C02 processor
|
|
*/
|
|
val Wdc: Cpu.Value = Value
|
|
/**
|
|
* The Hudson Soft HuC6280 processor
|
|
*/
|
|
val HuC6280: Cpu.Value = Value
|
|
/**
|
|
* The CSG 65CE02 processor
|
|
*/
|
|
val CE02: Cpu.Value = Value
|
|
/**
|
|
* The WDC 65816 processor
|
|
*/
|
|
val Sixteen: Cpu.Value = Value
|
|
/**
|
|
* The Intel 8080 processor
|
|
*/
|
|
val Intel8080: Cpu.Value = Value
|
|
/**
|
|
* The Intel 8085 processor
|
|
*/
|
|
val Intel8085: Cpu.Value = Value
|
|
/**
|
|
* The Intel 8085 processor, without illegal instructions
|
|
*/
|
|
val StrictIntel8085: Cpu.Value = Value
|
|
/**
|
|
* The Zilog Z80 processor
|
|
*/
|
|
val Z80: Cpu.Value = Value
|
|
/**
|
|
* The Zilog Z80 processor, without illegal instructions
|
|
*/
|
|
val StrictZ80: Cpu.Value = Value
|
|
/**
|
|
* The Zilog eZ80 processor
|
|
*/
|
|
val EZ80: Cpu.Value = Value
|
|
/**
|
|
* The Z80 core from the ZX Spectrum Next
|
|
*/
|
|
val Z80Next: Cpu.Value = Value
|
|
/**
|
|
* The Sharp LR35902 processor
|
|
*/
|
|
val Sharp: Cpu.Value = Value
|
|
/**
|
|
* The Intel 8086 or 8088 processor
|
|
*/
|
|
val Intel8086: Cpu.Value = Value
|
|
/**
|
|
* The Intel 80186 or 80188 processor
|
|
*/
|
|
val Intel80186: Cpu.Value = Value
|
|
/**
|
|
* The Motorola 6809 processor
|
|
*/
|
|
val Motorola6809: Cpu.Value = Value
|
|
|
|
/**
|
|
* Processors that can run code for WDC 65C02
|
|
*/
|
|
val CmosCompatible: Set[Cpu.Value] = Set(Cmos, HuC6280, CE02, Sixteen, SC02, Rockwell, Wdc)
|
|
/**
|
|
* Processors that can run code for Zilog Z80
|
|
*/
|
|
val Z80Compatible: Set[Cpu.Value] = Set(Z80, StrictZ80, EZ80, Z80Next)
|
|
/**
|
|
* Processors that can run code for Intel 8080
|
|
*/
|
|
val Intel8080Compatible: Set[Cpu.Value] = Set(Intel8080, Intel8085, StrictIntel8085, Z80, StrictZ80, EZ80, Z80Next)
|
|
/**
|
|
* Processors that can run code for Intel 8085
|
|
*/
|
|
val Intel8085Compatible: Set[Cpu.Value] = Set(Intel8085, StrictIntel8085)
|
|
|
|
import CompilationFlag._
|
|
|
|
private val alwaysDefaultFlags = Set(
|
|
VariableOverlap,
|
|
CompactReturnDispatchParams,
|
|
FunctionFallthrough,
|
|
RegisterVariables,
|
|
FunctionDeduplication,
|
|
EnableBreakpoints,
|
|
UseOptimizationHints,
|
|
GenericWarnings,
|
|
UselessCodeWarning,
|
|
BuggyCodeWarning,
|
|
FallbackValueUseWarning,
|
|
DeprecationWarning,
|
|
NonZeroTerminatedLiteralWarning,
|
|
CallToOverlappingBankWarning,
|
|
DataMissingInOutputWarning,
|
|
UnsupportedOptimizationHintWarning,
|
|
)
|
|
|
|
private val mosAlwaysDefaultFlags = alwaysDefaultFlags
|
|
|
|
private val i80AlwaysDefaultFlags = alwaysDefaultFlags
|
|
|
|
private val m6809AlwaysDefaultFlags = alwaysDefaultFlags
|
|
|
|
def defaultFlags(x: Cpu.Value): Set[CompilationFlag.Value] = x match {
|
|
case StrictMos =>
|
|
mosAlwaysDefaultFlags ++ Set(DecimalMode, PreventJmpIndirectBug)
|
|
case Mos =>
|
|
mosAlwaysDefaultFlags ++ Set(DecimalMode, PreventJmpIndirectBug)
|
|
case Ricoh =>
|
|
mosAlwaysDefaultFlags ++ Set(PreventJmpIndirectBug)
|
|
case StrictRicoh =>
|
|
mosAlwaysDefaultFlags ++ Set(PreventJmpIndirectBug)
|
|
case Cmos =>
|
|
mosAlwaysDefaultFlags ++ Set(DecimalMode, EmitCmosOpcodes)
|
|
case SC02 =>
|
|
mosAlwaysDefaultFlags ++ Set(DecimalMode, EmitCmosOpcodes, EmitSC02Opcodes)
|
|
case Rockwell =>
|
|
mosAlwaysDefaultFlags ++ Set(DecimalMode, EmitCmosOpcodes, EmitSC02Opcodes, EmitRockwellOpcodes)
|
|
case Wdc =>
|
|
mosAlwaysDefaultFlags ++ Set(DecimalMode, EmitCmosOpcodes, EmitSC02Opcodes, EmitRockwellOpcodes, EmitWdcOpcodes)
|
|
case HuC6280 =>
|
|
mosAlwaysDefaultFlags ++ Set(DecimalMode, EmitCmosOpcodes, EmitSC02Opcodes, EmitRockwellOpcodes, EmitHudsonOpcodes)
|
|
case CE02 =>
|
|
mosAlwaysDefaultFlags ++ Set(DecimalMode, EmitCmosOpcodes, EmitSC02Opcodes, EmitRockwellOpcodes, Emit65CE02Opcodes)
|
|
case Sixteen =>
|
|
mosAlwaysDefaultFlags ++ Set(DecimalMode, EmitCmosOpcodes, EmitSC02Opcodes, EmitEmulation65816Opcodes, EmitNative65816Opcodes, ReturnWordsViaAccumulator)
|
|
case Intel8080 =>
|
|
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, UseIntelSyntaxForInput, UseIntelSyntaxForOutput)
|
|
case StrictIntel8085 | Intel8085 =>
|
|
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, EmitIntel8085Opcodes, UseIntelSyntaxForInput, UseIntelSyntaxForOutput)
|
|
case StrictZ80 | Z80 =>
|
|
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, UseIxForStack, UseShadowRegistersForInterrupts)
|
|
case Z80Next =>
|
|
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, UseIxForStack, UseShadowRegistersForInterrupts, EmitIllegals, EmitZ80NextOpcodes)
|
|
case EZ80 =>
|
|
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, UseIxForStack, UseShadowRegistersForInterrupts, EmitEZ80Opcodes)
|
|
case Sharp =>
|
|
i80AlwaysDefaultFlags ++ Set(EmitExtended80Opcodes, EmitSharpOpcodes)
|
|
case Intel8086 | Intel80186 =>
|
|
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, UseIxForStack, EmitIntel8085Opcodes, EmitIllegals)
|
|
case Motorola6809 =>
|
|
m6809AlwaysDefaultFlags
|
|
}
|
|
|
|
def fromString(name: String)(implicit log: Logger): Cpu.Value = name match {
|
|
case "nmos" => Mos
|
|
case "6502" => Mos
|
|
case "6510" => Mos
|
|
case "strict" => StrictMos
|
|
case "strictnmos" => StrictMos
|
|
case "strict6502" => StrictMos
|
|
case "strict6510" => StrictMos
|
|
case "cmos" => Cmos
|
|
case "65sc02" => SC02
|
|
case "sc02" => SC02
|
|
case "65c02" => Rockwell
|
|
case "c02" => Rockwell
|
|
case "w65c02" => Wdc
|
|
case "wdc65c02" => Wdc
|
|
case "wdc" => Wdc
|
|
case "hudson" => HuC6280
|
|
case "huc6280" => HuC6280
|
|
case "c6280" => HuC6280
|
|
case "6280" => HuC6280
|
|
case "65ce02" => CE02
|
|
case "ce02" => CE02
|
|
case "65816" => Sixteen
|
|
case "65c816" => Sixteen
|
|
case "816" => Sixteen
|
|
case "5a22" => Sixteen
|
|
case "ricoh" => Ricoh
|
|
case "2a03" => Ricoh
|
|
case "2a07" => Ricoh
|
|
case "strictricoh" => StrictRicoh
|
|
case "strict2a03" => StrictRicoh
|
|
case "strict2a07" => StrictRicoh
|
|
case "z80" => Z80
|
|
case "strictz80" => Z80
|
|
case "zx80next" => Z80Next
|
|
case "z80next" => Z80Next
|
|
// 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 "8085" => Intel8085
|
|
case "i8085" => Intel8085
|
|
case "intel8085" => Intel8085
|
|
case "strict8085" => StrictIntel8085
|
|
case "stricti8085" => StrictIntel8085
|
|
case "strictintel8085" => StrictIntel8085
|
|
case "intel8086" => Intel8086
|
|
case "i8086" => Intel8086
|
|
case "8086" => Intel8086
|
|
case "intel80186" => Intel80186
|
|
case "i80186" => Intel80186
|
|
case "80186" => Intel80186
|
|
case "intel80286" => Intel80186
|
|
case "i80286" => Intel80186
|
|
case "80286" => Intel80186
|
|
// undocumented for now
|
|
case "6809" => Motorola6809
|
|
case _ => log.fatal("Unknown CPU achitecture: " + name)
|
|
}
|
|
|
|
def getMaxSizeReturnableViaRegisters(cpu: Cpu.Value, compilationOptions: CompilationOptions): Int =
|
|
CpuFamily.forType(cpu) match {
|
|
case CpuFamily.M6502 => 2
|
|
case CpuFamily.I80 | CpuFamily.I86 => 4
|
|
case CpuFamily.M6809 => 2
|
|
case _ => ???
|
|
}
|
|
|
|
def isBigEndian(cpu: Cpu.Value): Boolean = CpuFamily.isBigEndian(CpuFamily.forType(cpu))
|
|
}
|
|
|
|
object CompilationFlag extends Enumeration {
|
|
val
|
|
// common compilation options:
|
|
EmitIllegals, DecimalMode, LenientTextEncoding, LineNumbersInAssembly, SourceInAssembly, EnableBreakpoints,
|
|
// compilation options for MOS:
|
|
EmitCmosOpcodes, EmitCmosNopOpcodes, EmitSC02Opcodes, EmitRockwellOpcodes, EmitWdcOpcodes, EmitHudsonOpcodes, Emit65CE02Opcodes, EmitEmulation65816Opcodes, EmitNative65816Opcodes,
|
|
PreventJmpIndirectBug, LargeCode, ReturnWordsViaAccumulator, SoftwareStack,
|
|
// compilation options for I80
|
|
EmitIntel8080Opcodes, EmitIntel8085Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, EmitEZ80Opcodes, EmitSharpOpcodes, EmitZ80NextOpcodes,
|
|
UseShadowRegistersForInterrupts,
|
|
UseIxForStack, UseIyForStack,
|
|
UseIxForScratch, UseIyForScratch,
|
|
UseIntelSyntaxForInput,
|
|
UseIntelSyntaxForOutput,
|
|
// compilation options for 6809
|
|
UseUForStack, UseYForStack,
|
|
// optimization options:
|
|
OptimizeForSize, OptimizeForSpeed, OptimizeForSonicSpeed, OptimizeForDebugging,
|
|
DangerousOptimizations, InlineFunctions, InterproceduralOptimization,
|
|
FunctionFallthrough, RegisterVariables, FunctionDeduplication, SubroutineExtraction,
|
|
OptimizeStdlib,
|
|
UseOptimizationHints,
|
|
// memory allocation options
|
|
VariableOverlap, CompactReturnDispatchParams, LUnixRelocatableCode,
|
|
// runtime check options
|
|
CheckIndexOutOfBounds,
|
|
// special options
|
|
SingleThreaded,
|
|
// warning options
|
|
GenericWarnings,
|
|
UselessCodeWarning,
|
|
BuggyCodeWarning,
|
|
DeprecationWarning,
|
|
FallbackValueUseWarning,
|
|
ExtraComparisonWarnings,
|
|
RorWarning,
|
|
NonZeroTerminatedLiteralWarning,
|
|
CallToOverlappingBankWarning,
|
|
DataMissingInOutputWarning,
|
|
UnsupportedOptimizationHintWarning,
|
|
FatalWarnings,
|
|
// special options for internal compiler use
|
|
EnableInternalTestSyntax,
|
|
InternalCurrentlyOptimizingForMeasurement = Value
|
|
|
|
val allWarnings: Set[CompilationFlag.Value] = Set(
|
|
GenericWarnings,
|
|
UselessCodeWarning,
|
|
BuggyCodeWarning,
|
|
DeprecationWarning,
|
|
FallbackValueUseWarning,
|
|
ExtraComparisonWarnings,
|
|
NonZeroTerminatedLiteralWarning,
|
|
CallToOverlappingBankWarning,
|
|
DataMissingInOutputWarning,
|
|
UnsupportedOptimizationHintWarning,
|
|
)
|
|
|
|
val fromString: Map[String, CompilationFlag.Value] = Map(
|
|
"lunix" -> LUnixRelocatableCode,
|
|
"emit_illegals" -> EmitIllegals,
|
|
"emit_cmos" -> EmitCmosOpcodes,
|
|
"emit_65sc02" -> EmitSC02Opcodes,
|
|
"emit_rockwell" -> EmitRockwellOpcodes,
|
|
"emit_wdc" -> EmitWdcOpcodes,
|
|
"emit_65ce02" -> Emit65CE02Opcodes,
|
|
"emit_huc6280" -> EmitHudsonOpcodes,
|
|
"emit_z80" -> EmitZ80Opcodes,
|
|
"emit_ez80" -> EmitEZ80Opcodes,
|
|
"emit_x80" -> EmitExtended80Opcodes,
|
|
"emit_8080" -> EmitIntel8080Opcodes,
|
|
"emit_8085" -> EmitIntel8085Opcodes,
|
|
"emit_sharp" -> EmitSharpOpcodes,
|
|
"ix_stack" -> UseIxForStack,
|
|
"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,
|
|
"input_intel_syntax" -> UseIntelSyntaxForInput,
|
|
"ipo" -> InterproceduralOptimization,
|
|
"optimize_stdlib" -> OptimizeStdlib,
|
|
"function_fallthrough" -> FunctionFallthrough,
|
|
"function_deduplication" -> FunctionDeduplication,
|
|
"subroutine_extraction" -> SubroutineExtraction,
|
|
"inline" -> InlineFunctions,
|
|
"dangerous_optimizations" -> DangerousOptimizations,
|
|
"decimal_mode" -> DecimalMode,
|
|
"ror_warn" -> RorWarning,
|
|
"prevent_jmp_indirect_bug" -> PreventJmpIndirectBug,
|
|
"compact_dispatch_params" -> CompactReturnDispatchParams,
|
|
"lenient_encoding" -> LenientTextEncoding,
|
|
"breakpoints" -> EnableBreakpoints,
|
|
)
|
|
|
|
} |