mirror of
https://github.com/KarolS/millfork.git
synced 2025-02-06 01:30:13 +00:00
More granular differentiation of various 65C02 variants; HuC6280 improvements
This commit is contained in:
parent
088688122e
commit
d634e24e92
@ -19,11 +19,17 @@ if a line ends with a backslash character, the value continues to the next line.
|
||||
|
||||
* `strictricoh` (Ricoh 2A03/2A07 without illegal instructions)
|
||||
|
||||
* `cmos` (WDC 65C02 or 65SC02)
|
||||
* `cmos` (65SC02, or any 65C02 without bit instructions)
|
||||
|
||||
* `65sc02` (65SC02)
|
||||
|
||||
* `65c02` (Rockwell 65C02; the instructions `BBRn`, `BBSn`, `SMBn`, `RMBn` are not supported yet)
|
||||
|
||||
* `w65c02` (WDC 65C02)
|
||||
|
||||
* `65ce02` (CSG 65CE02; experimental)
|
||||
|
||||
* `huc6280` (Hudson HuC6280; experimental)
|
||||
* `huc6280` (Hudson HuC6280; experimental, many instructions are not supported yet)
|
||||
|
||||
* `65816` (WDC 65816/65802; experimental; currently only programs that use only 16-bit addressing are supported)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
[compilation]
|
||||
arch=cmos
|
||||
arch=65sc02
|
||||
modules=atari_lynx_hardware, default_panic,stdlib
|
||||
; TODO: is this a good choice?
|
||||
encoding=atascii
|
||||
|
@ -36,7 +36,7 @@ case class CompilationOptions(platform: Platform,
|
||||
var invalids = Set[CompilationFlag.Value]()
|
||||
|
||||
if (CpuFamily.forType(platform.cpu) != CpuFamily.M6502) invalids ++= Set(
|
||||
EmitCmosOpcodes, EmitCmosNopOpcodes, EmitHudsonOpcodes, Emit65CE02Opcodes, EmitEmulation65816Opcodes, EmitNative65816Opcodes, LUnixRelocatableCode,
|
||||
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(
|
||||
@ -220,6 +220,9 @@ case class CompilationOptions(platform: Platform,
|
||||
"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)),
|
||||
@ -281,7 +284,7 @@ object CpuFamily extends Enumeration {
|
||||
def forType(cpu: Cpu.Value): CpuFamily.Value = {
|
||||
import Cpu._
|
||||
cpu match {
|
||||
case Mos | StrictMos | Ricoh | StrictRicoh | Cmos | HuC6280 | CE02 | Sixteen => M6502
|
||||
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
|
||||
@ -313,9 +316,21 @@ object Cpu extends Enumeration {
|
||||
*/
|
||||
val StrictRicoh: Cpu.Value = Value
|
||||
/**
|
||||
* The WDC 65C02 processor
|
||||
* 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
|
||||
*/
|
||||
@ -413,12 +428,18 @@ object Cpu extends Enumeration {
|
||||
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, EmitHudsonOpcodes)
|
||||
mosAlwaysDefaultFlags ++ Set(DecimalMode, EmitCmosOpcodes, EmitSC02Opcodes, EmitRockwellOpcodes, EmitHudsonOpcodes)
|
||||
case CE02 =>
|
||||
mosAlwaysDefaultFlags ++ Set(DecimalMode, EmitCmosOpcodes, Emit65CE02Opcodes)
|
||||
mosAlwaysDefaultFlags ++ Set(DecimalMode, EmitCmosOpcodes, EmitSC02Opcodes, EmitRockwellOpcodes, Emit65CE02Opcodes)
|
||||
case Sixteen =>
|
||||
mosAlwaysDefaultFlags ++ Set(DecimalMode, EmitCmosOpcodes, EmitEmulation65816Opcodes, EmitNative65816Opcodes, ReturnWordsViaAccumulator)
|
||||
mosAlwaysDefaultFlags ++ Set(DecimalMode, EmitCmosOpcodes, EmitSC02Opcodes, EmitEmulation65816Opcodes, EmitNative65816Opcodes, ReturnWordsViaAccumulator)
|
||||
case Intel8080 =>
|
||||
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, UseIntelSyntaxForInput, UseIntelSyntaxForOutput)
|
||||
case StrictIntel8085 | Intel8085 =>
|
||||
@ -446,10 +467,13 @@ object Cpu extends Enumeration {
|
||||
case "strict6502" => StrictMos
|
||||
case "strict6510" => StrictMos
|
||||
case "cmos" => Cmos
|
||||
case "65sc02" => Cmos
|
||||
case "sc02" => Cmos
|
||||
case "65c02" => Cmos
|
||||
case "c02" => 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
|
||||
@ -514,7 +538,7 @@ object CompilationFlag extends Enumeration {
|
||||
// common compilation options:
|
||||
EmitIllegals, DecimalMode, LenientTextEncoding, LineNumbersInAssembly, SourceInAssembly,
|
||||
// compilation options for MOS:
|
||||
EmitCmosOpcodes, EmitCmosNopOpcodes, EmitHudsonOpcodes, Emit65CE02Opcodes, EmitEmulation65816Opcodes, EmitNative65816Opcodes,
|
||||
EmitCmosOpcodes, EmitCmosNopOpcodes, EmitSC02Opcodes, EmitRockwellOpcodes, EmitWdcOpcodes, EmitHudsonOpcodes, Emit65CE02Opcodes, EmitEmulation65816Opcodes, EmitNative65816Opcodes,
|
||||
PreventJmpIndirectBug, LargeCode, ReturnWordsViaAccumulator, SoftwareStack,
|
||||
// compilation options for I80
|
||||
EmitIntel8080Opcodes, EmitIntel8085Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, EmitEZ80Opcodes, EmitSharpOpcodes, EmitZ80NextOpcodes,
|
||||
@ -551,6 +575,9 @@ object CompilationFlag extends Enumeration {
|
||||
"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,
|
||||
|
@ -495,13 +495,72 @@ object Main {
|
||||
fluff("", "Code generation options:", "")
|
||||
|
||||
boolean("-fcmos-ops", "-fno-cmos-ops").action { (c, v) =>
|
||||
c.changeFlag(CompilationFlag.EmitCmosOpcodes, v)
|
||||
}.description("Whether should emit CMOS opcodes.")
|
||||
if (v) {
|
||||
c.changeFlag(CompilationFlag.EmitCmosOpcodes, true)
|
||||
} else {
|
||||
c.changeFlag(CompilationFlag.EmitCmosOpcodes, false)
|
||||
c.changeFlag(CompilationFlag.EmitSC02Opcodes, false)
|
||||
c.changeFlag(CompilationFlag.EmitRockwellOpcodes, false)
|
||||
c.changeFlag(CompilationFlag.EmitWdcOpcodes, false)
|
||||
c.changeFlag(CompilationFlag.Emit65CE02Opcodes, false)
|
||||
c.changeFlag(CompilationFlag.EmitHudsonOpcodes, false)
|
||||
c.changeFlag(CompilationFlag.EmitNative65816Opcodes, false)
|
||||
c.changeFlag(CompilationFlag.EmitEmulation65816Opcodes, false)
|
||||
}
|
||||
}.description("Whether should emit the core 65C02 opcodes.")
|
||||
boolean("-f65sc02-ops", "-fno-65sc02-ops").action { (c, v) =>
|
||||
if (v) {
|
||||
c.changeFlag(CompilationFlag.EmitSC02Opcodes, true)
|
||||
c.changeFlag(CompilationFlag.EmitCmosOpcodes, true)
|
||||
} else {
|
||||
c.changeFlag(CompilationFlag.EmitSC02Opcodes, false)
|
||||
c.changeFlag(CompilationFlag.EmitRockwellOpcodes, false)
|
||||
c.changeFlag(CompilationFlag.EmitWdcOpcodes, false)
|
||||
c.changeFlag(CompilationFlag.Emit65CE02Opcodes, false)
|
||||
c.changeFlag(CompilationFlag.EmitHudsonOpcodes, false)
|
||||
}
|
||||
}.description("Whether should emit 65SC02 opcodes.")
|
||||
boolean("-frockwell-ops", "-fno-rockwell-ops").action { (c, v) =>
|
||||
if (v) {
|
||||
c.changeFlag(CompilationFlag.EmitRockwellOpcodes, true)
|
||||
c.changeFlag(CompilationFlag.EmitSC02Opcodes, true)
|
||||
c.changeFlag(CompilationFlag.EmitCmosOpcodes, true)
|
||||
} else {
|
||||
c.changeFlag(CompilationFlag.EmitRockwellOpcodes, false)
|
||||
c.changeFlag(CompilationFlag.EmitWdcOpcodes, false)
|
||||
c.changeFlag(CompilationFlag.Emit65CE02Opcodes, false)
|
||||
c.changeFlag(CompilationFlag.EmitHudsonOpcodes, false)
|
||||
}
|
||||
}.description("Whether should emit Rockwell 65C02 opcodes.")
|
||||
boolean("-fwdc-ops", "-fno-wdc-ops").action { (c, v) =>
|
||||
if (v) {
|
||||
c.changeFlag(CompilationFlag.EmitWdcOpcodes, true)
|
||||
c.changeFlag(CompilationFlag.EmitRockwellOpcodes, true)
|
||||
c.changeFlag(CompilationFlag.EmitSC02Opcodes, true)
|
||||
c.changeFlag(CompilationFlag.EmitCmosOpcodes, true)
|
||||
} else {
|
||||
c.changeFlag(CompilationFlag.EmitWdcOpcodes, false)
|
||||
}
|
||||
}.description("Whether should emit WDC 65C02 opcodes.")
|
||||
boolean("-f65ce02-ops", "-fno-65ce02-ops").action { (c, v) =>
|
||||
c.changeFlag(CompilationFlag.Emit65CE02Opcodes, v)
|
||||
if (v) {
|
||||
c.changeFlag(CompilationFlag.Emit65CE02Opcodes, true)
|
||||
c.changeFlag(CompilationFlag.EmitRockwellOpcodes, true)
|
||||
c.changeFlag(CompilationFlag.EmitSC02Opcodes, true)
|
||||
c.changeFlag(CompilationFlag.EmitCmosOpcodes, true)
|
||||
} else {
|
||||
c.changeFlag(CompilationFlag.Emit65CE02Opcodes, false)
|
||||
}
|
||||
}.description("Whether should emit 65CE02 opcodes.")
|
||||
boolean("-fhuc6280-ops", "-fno-huc6280-ops").action { (c, v) =>
|
||||
c.changeFlag(CompilationFlag.EmitHudsonOpcodes, v)
|
||||
if (v) {
|
||||
c.changeFlag(CompilationFlag.EmitHudsonOpcodes, true)
|
||||
c.changeFlag(CompilationFlag.EmitRockwellOpcodes, true)
|
||||
c.changeFlag(CompilationFlag.EmitSC02Opcodes, true)
|
||||
c.changeFlag(CompilationFlag.EmitCmosOpcodes, true)
|
||||
} else {
|
||||
c.changeFlag(CompilationFlag.EmitCmosOpcodes, false)
|
||||
}
|
||||
}.description("Whether should emit HuC6280 opcodes.")
|
||||
flag("-fno-65816-ops").action { c =>
|
||||
c.changeFlag(CompilationFlag.EmitEmulation65816Opcodes, b = false)
|
||||
|
@ -40,7 +40,7 @@ object OpcodeClasses {
|
||||
TXA, TXS, SBX,
|
||||
PLX, PLX_W,
|
||||
XAA, SAX, AHX, SHX, TAS,
|
||||
HuSAX, SXY,
|
||||
HuSAX, SXY, SET,
|
||||
TXY,
|
||||
)
|
||||
val ReadsYAlways = Set(CPY, DEY, INY, STY, TYA, PLY, SHY, SAY, SXY, TYX)
|
||||
@ -138,9 +138,11 @@ object OpcodeClasses {
|
||||
STA, STY, STZ, STX,
|
||||
STA_W, STY_W, STZ_W, STX_W,
|
||||
TRB, TSB,
|
||||
TRB_W, TSB_W,
|
||||
SAX, DCP, ISC,
|
||||
SLO, RLA, SRE, RRA,
|
||||
AHX, SHY, SHX, TAS, LAS,
|
||||
TAM, TIN, TII, TIA, TAI, TST, TDD,
|
||||
COP,
|
||||
CHANGED_MEM,
|
||||
)
|
||||
@ -159,6 +161,7 @@ object OpcodeClasses {
|
||||
LAS,
|
||||
TRB, TSB,
|
||||
TRB_W, TSB_W,
|
||||
TST, TAM, TII, TAI, TIN, TIA, TDD,
|
||||
CHANGED_MEM,
|
||||
)
|
||||
|
||||
|
@ -95,8 +95,8 @@ object Opcode extends Enumeration {
|
||||
CLA, CLX, CLY,
|
||||
CSH, CSL,
|
||||
SAY, SXY, HuSAX,
|
||||
// SET,
|
||||
// ST0, ST1, ST2,
|
||||
SET,
|
||||
ST0, ST1, ST2,
|
||||
// BSR, // the same as on 65CE02
|
||||
TAM, TMA,
|
||||
TAI, TIA, TDD, TIN, TII, // memcpy instructions
|
||||
@ -193,11 +193,15 @@ object Opcode extends Enumeration {
|
||||
case "CLD" => CLD
|
||||
case "CLI" => CLI
|
||||
case "CLV" => CLV
|
||||
case "CLX" => CLX
|
||||
case "CLY" => CLY
|
||||
case "CMP" => CMP
|
||||
case "COP" => COP
|
||||
case "CPX" => CPX
|
||||
case "CPY" => CPY
|
||||
case "CPZ" => CPZ
|
||||
case "CSH" => CSH
|
||||
case "CSL" => CSL
|
||||
case "DCM" => DCP
|
||||
case "DCP" => DCP
|
||||
case "DEC" => DEC
|
||||
@ -262,16 +266,22 @@ object Opcode extends Enumeration {
|
||||
case "SED" => SED
|
||||
case "SEI" => SEI
|
||||
case "SEP" => SEP
|
||||
case "SET" => SET
|
||||
case "SHX" => SHX
|
||||
case "SHY" => SHY
|
||||
case "SLO" => SLO
|
||||
case "SRE" => SRE
|
||||
case "ST0" => ST0
|
||||
case "ST1" => ST1
|
||||
case "ST2" => ST2
|
||||
case "STA" => STA
|
||||
case "STP" => STP
|
||||
case "STX" => STX
|
||||
case "STY" => STY
|
||||
case "STZ" => STZ
|
||||
case "SXY" => SXY
|
||||
case "TAB" => TAB
|
||||
case "TAI" => TAI
|
||||
case "TAM" => TAM
|
||||
case "TAS" => TAS
|
||||
case "TAX" => TAX
|
||||
@ -280,7 +290,10 @@ object Opcode extends Enumeration {
|
||||
case "TBA" => TBA
|
||||
case "TCD" => TCD
|
||||
case "TDC" => TDC
|
||||
case "TDD" => TDD
|
||||
case "TCS" => TCS
|
||||
case "TIA" => TIA
|
||||
case "TII" => TII
|
||||
case "TSC" => TSC
|
||||
case "TMA" => TMA
|
||||
case "TRB" => TRB
|
||||
|
@ -51,6 +51,7 @@ object CoarseFlowAnalyzer {
|
||||
val codeArray = code.toArray
|
||||
|
||||
var changed = true
|
||||
var tFlag = false
|
||||
while (changed) {
|
||||
changed = false
|
||||
var currentStatus: CpuStatus = functionStartStatus
|
||||
@ -66,6 +67,10 @@ object CoarseFlowAnalyzer {
|
||||
var staSpIsNow = false
|
||||
codeArray(i) match {
|
||||
case AssemblyLine0(LABEL, _, MemoryAddressConstant(Label(l))) =>
|
||||
if (tFlag) {
|
||||
// T flag should not be set at a label!
|
||||
optimizationContext.log.warn("The SET instruction shouldn't occur before a label")
|
||||
}
|
||||
val L = l
|
||||
currentStatus = codeArray.indices.flatMap(j => codeArray(j) match {
|
||||
case AssemblyLine0(_, _, MemoryAddressConstant(Label(L))) => Some(flagArray(j))
|
||||
@ -121,6 +126,12 @@ object CoarseFlowAnalyzer {
|
||||
z = currentStatus.a.z(),
|
||||
src = SourceOfNZ.AX)
|
||||
|
||||
case AssemblyLine0(ADC | SBC | CMP, _, _) if tFlag =>
|
||||
currentStatus = currentStatus.copy(z = AnyStatus, n = AnyStatus, v = AnyStatus, c = AnyStatus)
|
||||
case AssemblyLine0(EOR | AND | ORA, _, _) if tFlag =>
|
||||
currentStatus = currentStatus.copy(z = AnyStatus, n = AnyStatus, v = AnyStatus, c = AnyStatus)
|
||||
// TODO: find a better documentation for the T flag
|
||||
|
||||
case AssemblyLine0(op, Implied, _) if FlowAnalyzerForImplied.hasDefinition(op) =>
|
||||
currentStatus = FlowAnalyzerForImplied.get(op)(currentStatus)
|
||||
|
||||
@ -161,6 +172,13 @@ object CoarseFlowAnalyzer {
|
||||
if (OpcodeClasses.ChangesStack(opcode) || OpcodeClasses.ChangesS(opcode)) currentStatus = currentStatus.copy(eqSX = false)
|
||||
}
|
||||
staSpWasLast = staSpIsNow
|
||||
if (tFlag) {
|
||||
if (OpcodeClasses.ShortBranching(codeArray(i).opcode) || codeArray(i).opcode == JMP || codeArray(i).opcode == JSR) {
|
||||
// T flag should not be set at a jump!
|
||||
optimizationContext.log.warn("The SET instruction shouldn't occur before a jump")
|
||||
}
|
||||
}
|
||||
tFlag = codeArray(i).opcode == SET
|
||||
}
|
||||
// flagArray.zip(codeArray).foreach{
|
||||
// case (fl, y) => if (y.isPrintable) println(f"$fl%-32s $y%-32s")
|
||||
|
@ -34,6 +34,10 @@ case class SourceOfNZ(a: Boolean = false, aw: Boolean = false, x: Boolean = fals
|
||||
if (builder.isEmpty) "?"
|
||||
else builder.mkString
|
||||
}
|
||||
|
||||
def swapAX: SourceOfNZ = copy(a = x, x = a)
|
||||
def swapAY: SourceOfNZ = copy(a = y, y = a)
|
||||
def swapXY: SourceOfNZ = copy(y = x, x = y)
|
||||
}
|
||||
|
||||
|
||||
|
@ -262,7 +262,13 @@ object FlowAnalyzerForImmediate {
|
||||
eqSX = false,
|
||||
eqSpX = false,
|
||||
src = SourceOfNZ.X)
|
||||
}
|
||||
},
|
||||
|
||||
TAM -> { (nn, currentStatus) => currentStatus },
|
||||
TMA -> { (nn, currentStatus) =>
|
||||
val newX = (currentStatus.x <*> currentStatus.a) { (x, a) => (x - (x & a)) & 0xff }
|
||||
currentStatus.copy(a = AnyStatus)
|
||||
},
|
||||
)
|
||||
|
||||
def hasDefinition(opcode: Opcode.Value): Boolean = map.contains(opcode)
|
||||
|
@ -263,6 +263,7 @@ object FlowAnalyzerForImplied {
|
||||
a = currentStatus.x,
|
||||
a0 = currentStatus.x.bit0,
|
||||
a7 = currentStatus.x.bit7,
|
||||
src = currentStatus.src.map(_.swapAX),
|
||||
eqSX = false,
|
||||
eqSpX = false,
|
||||
x = currentStatus.a)
|
||||
@ -272,6 +273,7 @@ object FlowAnalyzerForImplied {
|
||||
a = currentStatus.y,
|
||||
a0 = currentStatus.y.bit0,
|
||||
a7 = currentStatus.y.bit7,
|
||||
src = currentStatus.src.map(_.swapAY),
|
||||
y = currentStatus.a)
|
||||
}),
|
||||
SXY -> (currentStatus => {
|
||||
@ -279,6 +281,7 @@ object FlowAnalyzerForImplied {
|
||||
y = currentStatus.x,
|
||||
eqSX = false,
|
||||
eqSpX = false,
|
||||
src = currentStatus.src.map(_.swapXY),
|
||||
x = currentStatus.y)
|
||||
}),
|
||||
ASL -> (currentStatus => {
|
||||
|
@ -178,6 +178,7 @@ object ReverseFlowAnalyzerPerImpiedOpcode {
|
||||
CLA -> (_.copy(a = Unimportant)),
|
||||
CLX -> (_.copy(x = Unimportant)),
|
||||
CLY -> (_.copy(y = Unimportant)),
|
||||
SET -> (_.copy(x = Important)),
|
||||
|
||||
)
|
||||
|
||||
|
@ -212,6 +212,12 @@ object ReverseFlowAnalyzerPerOpcode {
|
||||
STY_W -> (importance => importance.copy(y = Important, w = Important)),
|
||||
STZ_W -> (importance => importance.copy(iz = Important, m = Important)),
|
||||
|
||||
ST0 -> (importance => importance.copy(a = Important)),
|
||||
ST1 -> (importance => importance.copy(a = Important)),
|
||||
ST2 -> (importance => importance.copy(a = Important)),
|
||||
TAM -> (importance => importance.copy(a = Important)),
|
||||
TMA -> (importance => importance.copy(a = Unimportant)),
|
||||
|
||||
)
|
||||
|
||||
def hasDefinition(opcode: Opcode.Value): Boolean = map.contains(opcode)
|
||||
|
@ -219,6 +219,9 @@ object MosAssembler {
|
||||
private val opcodes = mutable.Map[(Opcode.Value, AddrMode.Value), Byte]()
|
||||
private val illegalOpcodes = mutable.Map[(Opcode.Value, AddrMode.Value), Byte]()
|
||||
private val cmosOpcodes = mutable.Map[(Opcode.Value, AddrMode.Value), Byte]()
|
||||
private val sc02Opcodes = mutable.Map[(Opcode.Value, AddrMode.Value), Byte]()
|
||||
private val rockwellOpcodes = mutable.Map[(Opcode.Value, AddrMode.Value), Byte]()
|
||||
private val wdcOpcodes = mutable.Map[(Opcode.Value, AddrMode.Value), Byte]()
|
||||
private val cmosNopOpcodes = mutable.Map[(Opcode.Value, AddrMode.Value), Byte]()
|
||||
private val ce02Opcodes = mutable.Map[(Opcode.Value, AddrMode.Value), Byte]()
|
||||
private val hudsonOpcodes = mutable.Map[(Opcode.Value, AddrMode.Value), Byte]()
|
||||
@ -230,6 +233,9 @@ object MosAssembler {
|
||||
opcodes.get(key).foreach(return _)
|
||||
if (options.flag(CompilationFlag.EmitIllegals)) illegalOpcodes.get(key).foreach(return _)
|
||||
if (options.flag(CompilationFlag.EmitCmosOpcodes)) cmosOpcodes.get(key).foreach(return _)
|
||||
if (options.flag(CompilationFlag.EmitSC02Opcodes)) sc02Opcodes.get(key).foreach(return _)
|
||||
if (options.flag(CompilationFlag.EmitRockwellOpcodes)) rockwellOpcodes.get(key).foreach(return _)
|
||||
if (options.flag(CompilationFlag.EmitWdcOpcodes)) wdcOpcodes.get(key).foreach(return _)
|
||||
if (options.flag(CompilationFlag.EmitCmosNopOpcodes)) cmosNopOpcodes.get(key).foreach(return _)
|
||||
if (options.flag(CompilationFlag.Emit65CE02Opcodes)) ce02Opcodes.get(key).foreach(return _)
|
||||
if (options.flag(CompilationFlag.EmitHudsonOpcodes)) hudsonOpcodes.get(key).foreach(return _)
|
||||
@ -249,6 +255,21 @@ object MosAssembler {
|
||||
cmosOpcodes(op -> am) = x.toByte
|
||||
}
|
||||
|
||||
private def sc(op: Opcode.Value, am: AddrMode.Value, x: Int): Unit = {
|
||||
if (x < 0 || x > 0xff) FatalErrorReporting.reportFlyingPig("Invalid code for" + (op -> am))
|
||||
sc02Opcodes(op -> am) = x.toByte
|
||||
}
|
||||
|
||||
private def rw(op: Opcode.Value, am: AddrMode.Value, x: Int): Unit = {
|
||||
if (x < 0 || x > 0xff) FatalErrorReporting.reportFlyingPig("Invalid code for" + (op -> am))
|
||||
rockwellOpcodes(op -> am) = x.toByte
|
||||
}
|
||||
|
||||
private def wd(op: Opcode.Value, am: AddrMode.Value, x: Int): Unit = {
|
||||
if (x < 0 || x > 0xff) FatalErrorReporting.reportFlyingPig("Invalid code for" + (op -> am))
|
||||
wdcOpcodes(op -> am) = x.toByte
|
||||
}
|
||||
|
||||
private def cn(op: Opcode.Value, am: AddrMode.Value, x: Int): Unit = {
|
||||
if (x < 0 || x > 0xff) FatalErrorReporting.reportFlyingPig("Invalid code for" + (op -> am))
|
||||
cmosNopOpcodes(op -> am) = x.toByte
|
||||
@ -566,10 +587,10 @@ object MosAssembler {
|
||||
cm(CMP, IndexedZ, 0xD2)
|
||||
cm(SBC, IndexedZ, 0xF2)
|
||||
|
||||
cm(TSB, ZeroPage, 0x04)
|
||||
cm(TSB, Absolute, 0x0C)
|
||||
cm(TRB, ZeroPage, 0x14)
|
||||
cm(TRB, Absolute, 0x1C)
|
||||
sc(TSB, ZeroPage, 0x04)
|
||||
sc(TSB, Absolute, 0x0C)
|
||||
sc(TRB, ZeroPage, 0x14)
|
||||
sc(TRB, Absolute, 0x1C)
|
||||
|
||||
cm(BRA, Relative, 0x80)
|
||||
cm(BIT, ZeroPageX, 0x34)
|
||||
@ -577,8 +598,8 @@ object MosAssembler {
|
||||
cm(INC, Implied, 0x1A)
|
||||
cm(DEC, Implied, 0x3A)
|
||||
cm(JMP, AbsoluteIndexedX, 0x7C)
|
||||
cm(WAI, Implied, 0xCB)
|
||||
cm(STP, Implied, 0xDB)
|
||||
wd(WAI, Implied, 0xCB)
|
||||
wd(STP, Implied, 0xDB)
|
||||
|
||||
ce(CPZ, Immediate, 0xC2)
|
||||
ce(CPZ, ZeroPage, 0xD4)
|
||||
@ -615,11 +636,16 @@ object MosAssembler {
|
||||
hu(CLA, Implied, 0x62)
|
||||
hu(CSH, Implied, 0xD4)
|
||||
hu(CSL, Implied, 0x54)
|
||||
hu(SET, Implied, 0xF4)
|
||||
hu(HuSAX, Implied, 0x22)
|
||||
hu(SAY, Implied, 0x42)
|
||||
hu(SXY, Implied, 0x02)
|
||||
hu(TAM, Immediate, 0x53)
|
||||
hu(TMA, Immediate, 0x43)
|
||||
hu(ST0, Immediate, 0x03)
|
||||
hu(ST1, Immediate, 0x13)
|
||||
hu(ST2, Immediate, 0x23)
|
||||
hu(STP, Implied, 0xDB)
|
||||
|
||||
em(ORA, Stack, 0x03)
|
||||
em(ORA, IndexedSY, 0x13)
|
||||
|
@ -26,7 +26,7 @@ case class MosParser(filename: String, input: String, currentDirectory: String,
|
||||
|
||||
// def zeropageAddrModeHint: P[Option[Boolean]] = Pass
|
||||
|
||||
val asmOpcode: P[Opcode.Value] = (position() ~ letter.rep(exactly = 3).! ~ ("_W" | "_w").?.!).map { case (p, suffix, o) => Opcode.lookup(o + suffix, Some(p), log) }
|
||||
val asmOpcode: P[Opcode.Value] = (position() ~ mosOpcodeLetter.rep(exactly = 3).! ~ octalDigit.?.! ~ ("_W" | "_w").?.!).map { case (p, bitNo, suffix, o) => Opcode.lookup(o + bitNo + suffix, Some(p), log) }
|
||||
|
||||
private val commaX = HWS ~ "," ~ HWS ~ ("X" | "x") ~ HWS
|
||||
private val commaY = HWS ~ "," ~ HWS ~ ("Y" | "y") ~ HWS
|
||||
|
@ -1,6 +1,6 @@
|
||||
package millfork.test
|
||||
import millfork.Cpu
|
||||
import millfork.test.emu.{EmuBenchmarkRun, EmuCrossPlatformBenchmarkRun, EmuOptimizedCmosRun, EmuOptimizedRun}
|
||||
import millfork.test.emu.{EmuBenchmarkRun, EmuCrossPlatformBenchmarkRun, EmuOptimizedCmosRun, EmuOptimizedRun, EmuUnoptimizedHudsonRun}
|
||||
import org.scalatest.{AppendedClues, FunSuite, Matchers}
|
||||
|
||||
/**
|
||||
@ -226,4 +226,48 @@ class AssemblySuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
}
|
||||
|
||||
test("HuC6280 opcodes") {
|
||||
EmuUnoptimizedHudsonRun(
|
||||
"""
|
||||
| asm void main() {
|
||||
| rts
|
||||
| tam #1
|
||||
| tma #2
|
||||
| ;bbr0 main
|
||||
| ;bbs0 main
|
||||
| clx
|
||||
| cly
|
||||
| csh
|
||||
| csl
|
||||
| ;rmb0 $800
|
||||
| ;smb0 $800
|
||||
| sax
|
||||
| say
|
||||
| set
|
||||
| st0 #1
|
||||
| st1 #1
|
||||
| st2 #1
|
||||
| stp
|
||||
| sxy
|
||||
| tam #3
|
||||
| tma #5
|
||||
| trb $800
|
||||
| trb $4
|
||||
| tsb $800
|
||||
| tsb $4
|
||||
| ; tai $4000,$5000,$300
|
||||
| ; tia $4000,$5000,$300
|
||||
| ; tii $4000,$5000,$300
|
||||
| ; tin $4000,$5000,$300
|
||||
| ; tdd $4000,$5000,$300
|
||||
| ; tst #$44,4
|
||||
| ; tst #$44,4,X
|
||||
| ; tst #$44,3334,X
|
||||
| ; tst #$44,3334,X
|
||||
| rts
|
||||
| }
|
||||
|
|
||||
|""".stripMargin)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -148,9 +148,12 @@ class EmuRun(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimization],
|
||||
CompilationFlag.CompactReturnDispatchParams -> true,
|
||||
CompilationFlag.SoftwareStack -> softwareStack,
|
||||
CompilationFlag.EmitCmosOpcodes -> millfork.Cpu.CmosCompatible.contains(platform.cpu),
|
||||
CompilationFlag.EmitSC02Opcodes -> millfork.Cpu.CmosCompatible.contains(platform.cpu),
|
||||
CompilationFlag.EmitRockwellOpcodes -> millfork.Cpu.CmosCompatible.contains(platform.cpu),
|
||||
CompilationFlag.EmitEmulation65816Opcodes -> (platform.cpu == millfork.Cpu.Sixteen),
|
||||
CompilationFlag.EmitNative65816Opcodes -> (platform.cpu == millfork.Cpu.Sixteen && native16),
|
||||
CompilationFlag.Emit65CE02Opcodes -> (platform.cpu == millfork.Cpu.CE02),
|
||||
CompilationFlag.EmitWdcOpcodes -> (platform.cpu == millfork.Cpu.Wdc),
|
||||
CompilationFlag.EmitHudsonOpcodes -> (platform.cpu == millfork.Cpu.HuC6280),
|
||||
CompilationFlag.SubroutineExtraction -> optimizeForSize,
|
||||
CompilationFlag.OptimizeForSize -> optimizeForSize,
|
||||
|
@ -12,6 +12,8 @@ object EmuUnoptimizedRicohRun extends EmuRun(Cpu.Ricoh, Nil, Nil)
|
||||
|
||||
object EmuUnoptimizedCmosRun extends EmuRun(Cpu.Cmos, Nil, Nil)
|
||||
|
||||
object EmuUnoptimizedHudsonRun extends EmuRun(Cpu.HuC6280, Nil, Nil)
|
||||
|
||||
object EmuUnoptimizedNative65816Run extends EmuRun(Cpu.Sixteen, Nil, Nil) {
|
||||
override def native16: Boolean = true
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user