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

More granular differentiation of various 65C02 variants; HuC6280 improvements

This commit is contained in:
Karol Stasiak 2019-11-04 14:28:36 +01:00
parent 088688122e
commit d634e24e92
17 changed files with 251 additions and 30 deletions

View File

@ -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)

View File

@ -1,5 +1,5 @@
[compilation]
arch=cmos
arch=65sc02
modules=atari_lynx_hardware, default_panic,stdlib
; TODO: is this a good choice?
encoding=atascii

View File

@ -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,

View File

@ -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)

View File

@ -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,
)

View File

@ -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

View File

@ -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")

View File

@ -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)
}

View File

@ -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)

View File

@ -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 => {

View File

@ -178,6 +178,7 @@ object ReverseFlowAnalyzerPerImpiedOpcode {
CLA -> (_.copy(a = Unimportant)),
CLX -> (_.copy(x = Unimportant)),
CLY -> (_.copy(y = Unimportant)),
SET -> (_.copy(x = Important)),
)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)
}
}

View File

@ -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,

View File

@ -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
}