1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-06-12 06:29:34 +00:00
millfork/src/main/scala/millfork/CompilationOptions.scala

655 lines
25 KiB
Scala
Raw Normal View History

2017-12-06 23:23:30 +00:00
package millfork
import millfork.buildinfo.BuildInfo
import millfork.compiler.LabelGenerator
import millfork.error.{ConsoleLogger, Logger}
2020-04-30 23:31:54 +00:00
import millfork.parser.TextCodecRepository
2017-12-06 23:23:30 +00:00
/**
* @author Karol Stasiak
*/
case class CompilationOptions(platform: Platform,
commandLineFlags: Map[CompilationFlag.Value, Boolean],
outputFileName: Option[String],
zpRegisterSize: Int,
featureOverrides: Map[String, Long],
2020-04-30 23:31:54 +00:00
textCodecRepository: TextCodecRepository,
jobContext: JobContext) {
2017-12-06 23:23:30 +00:00
import CompilationFlag._
import Cpu._
@inline
def log: Logger = jobContext.log
@inline
def nextLabel: LabelGenerator = jobContext.nextLabel
2019-07-29 20:51:08 +00:00
@inline
def isBigEndian: Boolean = platform.isBigEndian
2017-12-06 23:23:30 +00:00
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)
2017-12-06 23:23:30 +00:00
2018-06-17 00:01:35 +00:00
{
2018-07-30 16:15:44 +00:00
log.setFatalWarnings(flags(CompilationFlag.FatalWarnings))
2018-06-17 00:01:35 +00:00
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)
2018-06-17 00:01:35 +00:00
2019-05-31 15:03:35 +00:00
if (CpuFamily.forType(platform.cpu) != CpuFamily.I80 && CpuFamily.forType(platform.cpu) != CpuFamily.I86) invalids ++= Set(
EmitIntel8085Opcodes, EmitIntel8080Opcodes, UseIxForStack, UseIntelSyntaxForInput, UseIntelSyntaxForOutput)
2019-05-31 15:03:35 +00:00
if (CpuFamily.forType(platform.cpu) != CpuFamily.I80) invalids ++= Set(
2019-09-30 22:46:15 +00:00
EmitExtended80Opcodes, EmitZ80Opcodes, EmitSharpOpcodes, EmitEZ80Opcodes, EmitZ80NextOpcodes,
2019-08-15 22:46:46 +00:00
UseIyForStack, UseIxForScratch, UseIyForScratch, UseShadowRegistersForInterrupts)
if (CpuFamily.forType(platform.cpu) != CpuFamily.M6809) invalids ++= Set(
UseUForStack, UseYForStack)
2018-06-17 00:01:35 +00:00
invalids = invalids.filter(flags)
if (invalids.nonEmpty) {
2018-07-30 16:15:44 +00:00
log.error("Invalid flags enabled for the current CPU family: " + invalids.mkString(", "))
2017-12-06 23:23:30 +00:00
}
if (CpuFamily.forType(platform.cpu) != CpuFamily.M6502 && zpRegisterSize > 0) {
log.error("Invalid flags enabled for the current CPU family: zp_register")
}
2018-06-17 00:01:35 +00:00
CpuFamily.forType(platform.cpu) match {
case CpuFamily.M6502 =>
if (flags(DecimalMode)) {
if (platform.cpu == Ricoh || platform.cpu == StrictRicoh) {
2018-07-30 16:15:44 +00:00
log.warn("Decimal mode enabled for Ricoh architecture")
2018-06-17 00:01:35 +00:00
}
}
if (platform.cpu == Sixteen) {
if (flags(LargeCode)) {
2018-07-30 16:15:44 +00:00
log.warn("Large code model doesn't work correctly yet")
2018-06-17 00:01:35 +00:00
}
}
if (platform.cpu != Sixteen) {
if (flags(LargeCode)) {
2018-07-30 16:15:44 +00:00
log.error("Cannot use large code model on architectures other than 65816")
2018-06-17 00:01:35 +00:00
}
if (flags(ReturnWordsViaAccumulator)) {
2018-07-30 16:15:44 +00:00
log.error("Cannot return words via accumulator on non-65816 architecture")
2018-06-17 00:01:35 +00:00
}
if (flags(EmitNative65816Opcodes) || flags(EmitEmulation65816Opcodes)) {
2018-07-30 16:15:44 +00:00
log.error("65816 opcodes enabled for non-65816 architecture")
2018-06-17 00:01:35 +00:00
}
}
if (platform.cpu != CE02) {
if (flags(Emit65CE02Opcodes)) {
2018-07-30 16:15:44 +00:00
log.error("65CE02 opcodes enabled for non-65CE02 architecture")
2018-06-17 00:01:35 +00:00
}
}
if (flags(Emit65CE02Opcodes)) {
2018-07-30 16:15:44 +00:00
log.warn("65CE02 opcodes are highly experimental")
2018-06-17 00:01:35 +00:00
}
if (platform.cpu != HuC6280) {
if (flags(EmitHudsonOpcodes)) {
2018-07-30 16:15:44 +00:00
log.error("HuC6280 opcodes enabled for non-HuC6280 architecture")
2018-06-17 00:01:35 +00:00
}
}
if (!CmosCompatible(platform.cpu)) {
if (!flags(PreventJmpIndirectBug)) {
2018-07-30 16:15:44 +00:00
log.warn("JMP bug prevention should be enabled for non-CMOS architecture")
2018-06-17 00:01:35 +00:00
}
if (flags(EmitCmosOpcodes)) {
2018-07-30 16:15:44 +00:00
log.error("CMOS opcodes enabled for non-CMOS architecture")
2018-06-17 00:01:35 +00:00
}
}
if (flags(EmitIllegals)) {
if (CmosCompatible(platform.cpu)) {
2018-07-30 16:15:44 +00:00
log.error("Illegal opcodes enabled for architecture that doesn't support them")
2018-06-17 00:01:35 +00:00
}
if (platform.cpu == StrictRicoh || platform.cpu == StrictMos) {
2018-07-30 16:15:44 +00:00
log.warn("Illegal opcodes enabled for strict architecture")
2018-06-17 00:01:35 +00:00
}
}
case CpuFamily.I80 =>
if (flags(EmitIllegals)) {
2019-09-30 22:46:15 +00:00
if (platform.cpu != Z80 && platform.cpu != Intel8085 && platform.cpu != Z80Next) {
2018-07-30 16:15:44 +00:00
log.error("Illegal opcodes enabled for architecture that doesn't support them")
2018-06-17 00:01:35 +00:00
}
}
if (flags(UseIxForStack) || flags(UseIxForScratch)) {
if (!Z80Compatible(platform.cpu)) {
2018-07-30 16:15:44 +00:00
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")
2018-06-17 00:01:35 +00:00
}
}
if (flags(EmitZ80Opcodes)) {
if (!Z80Compatible(platform.cpu)) {
2018-07-30 16:15:44 +00:00
log.error("Z80 opcodes enabled for architecture that doesn't support them")
2018-06-17 00:01:35 +00:00
}
}
2018-07-24 21:14:41 +00:00
if (flags(EmitEZ80Opcodes)) {
if (platform.cpu != EZ80) {
2018-07-30 16:15:44 +00:00
log.error("eZ80 opcodes enabled for architecture that doesn't support them")
2018-07-24 21:14:41 +00:00
}
}
2018-06-17 00:01:35 +00:00
if (flags(EmitSharpOpcodes)) {
if (platform.cpu != Sharp) {
2018-07-30 16:15:44 +00:00
log.error("Sharp LR35902 opcodes enabled for architecture that doesn't support them")
2018-06-17 00:01:35 +00:00
}
}
2019-09-30 22:46:15 +00:00
if (flags(EmitZ80NextOpcodes)) {
if (platform.cpu != Z80Next) {
log.error("ZX Spectrum Next opcodes enabled for architecture that doesn't support them")
}
}
2018-06-17 00:01:35 +00:00
if (flags(EmitExtended80Opcodes)) {
if (platform.cpu != Sharp && !Z80Compatible(platform.cpu)) {
2018-07-30 16:15:44 +00:00
log.error("Extended 8080-like opcodes enabled for architecture that doesn't support them")
2018-06-17 00:01:35 +00:00
}
}
2018-07-24 21:14:41 +00:00
if (flags(EmitIntel8080Opcodes)) {
if (!Intel8080Compatible(platform.cpu)) {
2018-07-30 16:15:44 +00:00
log.error("Intel 8080 opcodes enabled for architecture that doesn't support them")
2018-07-24 21:14:41 +00:00
}
}
2019-05-31 15:27:38 +00:00
if (flags(EmitIntel8085Opcodes)) {
if (!Intel8085Compatible(platform.cpu)) {
2019-05-31 15:27:38 +00:00
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")
2019-05-31 15:03:35 +00:00
}
case CpuFamily.I86 =>
2019-07-08 07:26:51 +00:00
case CpuFamily.M6809 =>
2019-08-15 22:46:46 +00:00
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.")
}
2017-12-06 23:23:30 +00:00
}
}
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)),
2019-05-31 15:27:38 +00:00
"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)),
2019-09-30 22:46:15 +00:00
"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)),
2019-08-15 22:46:46 +00:00
"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
}
2017-12-06 23:23:30 +00:00
}
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
2019-09-30 22:46:15 +00:00
case Intel8080 | Intel8085 | StrictIntel8085 | Sharp | Z80 | StrictZ80 | EZ80 | Z80Next => I80
2019-05-31 15:27:38 +00:00
case Intel8086 | Intel80186 => I86
2019-07-08 07:26:51 +00:00
case Cpu.Motorola6809 => M6809
}
}
def isBigEndian(family: CpuFamily.Value): Boolean = family match {
case M6502 | I80 | I86 | ARM => false
case M6800 | M6809 | M68K => true
}
}
2017-12-06 23:23:30 +00:00
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
2019-09-30 22:46:15 +00:00
/**
* 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
2019-07-08 07:26:51 +00:00
/**
* 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
*/
2019-09-30 22:46:15 +00:00
val Z80Compatible: Set[Cpu.Value] = Set(Z80, StrictZ80, EZ80, Z80Next)
/**
* Processors that can run code for Intel 8080
*/
2019-09-30 22:46:15 +00:00
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)
2017-12-06 23:23:30 +00:00
import CompilationFlag._
private val alwaysDefaultFlags = Set(
VariableOverlap,
CompactReturnDispatchParams,
FunctionFallthrough,
RegisterVariables,
FunctionDeduplication,
EnableBreakpoints,
2021-03-14 23:44:14 +00:00
UseOptimizationHints,
GenericWarnings,
UselessCodeWarning,
BuggyCodeWarning,
FallbackValueUseWarning,
DeprecationWarning,
NonZeroTerminatedLiteralWarning,
CallToOverlappingBankWarning,
DataMissingInOutputWarning,
2021-03-14 23:44:14 +00:00
UnsupportedOptimizationHintWarning,
)
private val mosAlwaysDefaultFlags = alwaysDefaultFlags
private val i80AlwaysDefaultFlags = alwaysDefaultFlags
2018-06-17 00:01:35 +00:00
2019-07-08 07:26:51 +00:00
private val m6809AlwaysDefaultFlags = alwaysDefaultFlags
2017-12-06 23:23:30 +00:00
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)
2018-06-17 00:01:35 +00:00
case Intel8080 =>
2018-08-03 11:23:37 +00:00
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, UseIntelSyntaxForInput, UseIntelSyntaxForOutput)
case StrictIntel8085 | Intel8085 =>
2019-05-31 15:27:38 +00:00
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, EmitIntel8085Opcodes, UseIntelSyntaxForInput, UseIntelSyntaxForOutput)
case StrictZ80 | Z80 =>
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, UseIxForStack, UseShadowRegistersForInterrupts)
2019-09-30 22:46:15 +00:00
case Z80Next =>
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, UseIxForStack, UseShadowRegistersForInterrupts, EmitIllegals, EmitZ80NextOpcodes)
2018-07-24 21:14:41 +00:00
case EZ80 =>
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, UseIxForStack, UseShadowRegistersForInterrupts, EmitEZ80Opcodes)
2018-06-17 00:01:35 +00:00
case Sharp =>
2018-07-24 21:14:41 +00:00
i80AlwaysDefaultFlags ++ Set(EmitExtended80Opcodes, EmitSharpOpcodes)
2019-05-31 15:03:35 +00:00
case Intel8086 | Intel80186 =>
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, UseIxForStack, EmitIntel8085Opcodes, EmitIllegals)
2019-07-08 07:26:51 +00:00
case Motorola6809 =>
m6809AlwaysDefaultFlags
2017-12-06 23:23:30 +00:00
}
2018-07-30 16:15:44 +00:00
def fromString(name: String)(implicit log: Logger): Cpu.Value = name match {
2017-12-06 23:23:30 +00:00
case "nmos" => Mos
case "6502" => Mos
case "6510" => Mos
case "strict" => StrictMos
2018-06-08 22:18:21 +00:00
case "strictnmos" => StrictMos
case "strict6502" => StrictMos
case "strict6510" => StrictMos
2017-12-06 23:23:30 +00:00
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
2017-12-06 23:23:30 +00:00
case "ricoh" => Ricoh
case "2a03" => Ricoh
case "2a07" => Ricoh
case "strictricoh" => StrictRicoh
case "strict2a03" => StrictRicoh
case "strict2a07" => StrictRicoh
case "z80" => Z80
case "strictz80" => Z80
2019-09-30 22:46:15 +00:00
case "zx80next" => Z80Next
case "z80next" => Z80Next
2018-07-24 21:14:41 +00:00
// disabled for now:
// case "ez80" => EZ80
2018-07-27 17:12:54 +00:00
case "gameboy" => Sharp
case "gb" => Sharp
case "sharp" => Sharp
case "lr35902" => Sharp
case "8080" => Intel8080
case "i8080" => Intel8080
case "intel8080" => Intel8080
2019-05-31 15:27:38 +00:00
case "8085" => Intel8085
case "i8085" => Intel8085
case "intel8085" => Intel8085
case "strict8085" => StrictIntel8085
case "stricti8085" => StrictIntel8085
case "strictintel8085" => StrictIntel8085
2019-05-31 15:03:35 +00:00
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
2019-07-28 22:55:24 +00:00
// undocumented for now
case "6809" => Motorola6809
2018-07-30 16:15:44 +00:00
case _ => log.fatal("Unknown CPU achitecture: " + name)
2017-12-06 23:23:30 +00:00
}
def getMaxSizeReturnableViaRegisters(cpu: Cpu.Value, compilationOptions: CompilationOptions): Int =
CpuFamily.forType(cpu) match {
case CpuFamily.M6502 => 2
case CpuFamily.I80 | CpuFamily.I86 => 4
2019-07-08 07:26:51 +00:00
case CpuFamily.M6809 => 2
case _ => ???
}
def isBigEndian(cpu: Cpu.Value): Boolean = CpuFamily.isBigEndian(CpuFamily.forType(cpu))
2017-12-06 23:23:30 +00:00
}
object CompilationFlag extends Enumeration {
val
2018-06-17 00:01:35 +00:00
// common compilation options:
EmitIllegals, DecimalMode, LenientTextEncoding, LineNumbersInAssembly, SourceInAssembly, EnableBreakpoints,
2018-06-17 00:01:35 +00:00
// compilation options for MOS:
EmitCmosOpcodes, EmitCmosNopOpcodes, EmitSC02Opcodes, EmitRockwellOpcodes, EmitWdcOpcodes, EmitHudsonOpcodes, Emit65CE02Opcodes, EmitEmulation65816Opcodes, EmitNative65816Opcodes,
PreventJmpIndirectBug, LargeCode, ReturnWordsViaAccumulator, SoftwareStack,
2018-07-24 21:14:41 +00:00
// compilation options for I80
2019-09-30 22:46:15 +00:00
EmitIntel8080Opcodes, EmitIntel8085Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, EmitEZ80Opcodes, EmitSharpOpcodes, EmitZ80NextOpcodes,
UseShadowRegistersForInterrupts,
UseIxForStack, UseIyForStack,
UseIxForScratch, UseIyForScratch,
2018-08-01 19:16:20 +00:00
UseIntelSyntaxForInput,
UseIntelSyntaxForOutput,
2019-08-15 22:46:46 +00:00
// compilation options for 6809
UseUForStack, UseYForStack,
2017-12-06 23:23:30 +00:00
// optimization options:
OptimizeForSize, OptimizeForSpeed, OptimizeForSonicSpeed, OptimizeForDebugging,
2018-12-21 21:33:27 +00:00
DangerousOptimizations, InlineFunctions, InterproceduralOptimization,
FunctionFallthrough, RegisterVariables, FunctionDeduplication, SubroutineExtraction,
2018-12-21 21:33:27 +00:00
OptimizeStdlib,
UseOptimizationHints,
2017-12-06 23:23:30 +00:00
// memory allocation options
2018-06-08 22:18:21 +00:00
VariableOverlap, CompactReturnDispatchParams, LUnixRelocatableCode,
2018-01-08 00:17:25 +00:00
// runtime check options
CheckIndexOutOfBounds,
2018-03-06 00:01:22 +00:00
// special options
SingleThreaded,
2017-12-06 23:23:30 +00:00
// warning options
GenericWarnings,
UselessCodeWarning,
BuggyCodeWarning,
DeprecationWarning,
FallbackValueUseWarning,
2017-12-06 23:23:30 +00:00
ExtraComparisonWarnings,
RorWarning,
NonZeroTerminatedLiteralWarning,
CallToOverlappingBankWarning,
DataMissingInOutputWarning,
2021-03-14 23:44:14 +00:00
UnsupportedOptimizationHintWarning,
FatalWarnings,
// special options for internal compiler use
EnableInternalTestSyntax,
InternalCurrentlyOptimizingForMeasurement = Value
2017-12-06 23:23:30 +00:00
val allWarnings: Set[CompilationFlag.Value] = Set(
GenericWarnings,
UselessCodeWarning,
BuggyCodeWarning,
DeprecationWarning,
FallbackValueUseWarning,
ExtraComparisonWarnings,
NonZeroTerminatedLiteralWarning,
CallToOverlappingBankWarning,
DataMissingInOutputWarning,
2021-03-14 23:44:14 +00:00
UnsupportedOptimizationHintWarning,
)
2017-12-06 23:23:30 +00:00
val fromString: Map[String, CompilationFlag.Value] = Map(
2018-06-08 22:18:21 +00:00
"lunix" -> LUnixRelocatableCode,
2017-12-06 23:23:30 +00:00
"emit_illegals" -> EmitIllegals,
"emit_cmos" -> EmitCmosOpcodes,
"emit_65sc02" -> EmitSC02Opcodes,
"emit_rockwell" -> EmitRockwellOpcodes,
"emit_wdc" -> EmitWdcOpcodes,
"emit_65ce02" -> Emit65CE02Opcodes,
"emit_huc6280" -> EmitHudsonOpcodes,
2018-06-17 00:01:35 +00:00
"emit_z80" -> EmitZ80Opcodes,
2018-07-24 21:14:41 +00:00
"emit_ez80" -> EmitEZ80Opcodes,
2018-06-17 00:01:35 +00:00
"emit_x80" -> EmitExtended80Opcodes,
2018-07-24 21:14:41 +00:00
"emit_8080" -> EmitIntel8080Opcodes,
2019-05-31 15:27:38 +00:00
"emit_8085" -> EmitIntel8085Opcodes,
2018-06-17 00:01:35 +00:00
"emit_sharp" -> EmitSharpOpcodes,
"ix_stack" -> UseIxForStack,
"iy_stack" -> UseIyForStack,
"ix_scratch" -> UseIxForScratch,
"iy_scratch" -> UseIyForScratch,
2019-08-15 22:46:46 +00:00
"u_stack" -> UseUForStack,
"y_stack" -> UseYForStack,
"software_stack" -> SoftwareStack,
"use_shadow_registers_for_irq" -> UseShadowRegistersForInterrupts,
2018-08-01 19:16:20 +00:00
"output_intel_syntax" -> UseIntelSyntaxForOutput,
2018-08-03 11:23:37 +00:00
"input_intel_syntax" -> UseIntelSyntaxForInput,
"ipo" -> InterproceduralOptimization,
2018-12-21 21:33:27 +00:00
"optimize_stdlib" -> OptimizeStdlib,
"function_fallthrough" -> FunctionFallthrough,
"function_deduplication" -> FunctionDeduplication,
"subroutine_extraction" -> SubroutineExtraction,
2018-07-01 17:19:30 +00:00
"inline" -> InlineFunctions,
"dangerous_optimizations" -> DangerousOptimizations,
2017-12-06 23:23:30 +00:00
"decimal_mode" -> DecimalMode,
"ror_warn" -> RorWarning,
"prevent_jmp_indirect_bug" -> PreventJmpIndirectBug,
2018-01-30 16:38:32 +00:00
"compact_dispatch_params" -> CompactReturnDispatchParams,
2018-07-06 22:58:44 +00:00
"lenient_encoding" -> LenientTextEncoding,
"breakpoints" -> EnableBreakpoints,
2017-12-06 23:23:30 +00:00
)
}