mirror of
https://github.com/KarolS/millfork.git
synced 2024-12-23 23:30:22 +00:00
Intel 8085 support
This commit is contained in:
parent
1cb3b672b1
commit
b3bb9bb063
@ -6,6 +6,8 @@
|
||||
|
||||
* Super experimental and very incomplete Intel 8086 support via 8080-to-8086 translation.
|
||||
|
||||
* Support for Intel 8085.
|
||||
|
||||
* Added `memory_barrier` macro.
|
||||
|
||||
* Added `random` module.
|
||||
|
@ -44,11 +44,11 @@ If given, then the compiler will NOT try to detect the default include directory
|
||||
* `-finput_intel_syntax`, `-finput_zilog_syntax` –
|
||||
Choose syntax for assembly sources on 8080-like targets.
|
||||
Can be overridden by the source file itself using `#pragma`.
|
||||
`.ini` equivalent: `input_intel_syntax`. Default: Intel (true) on Intel 8080, Zilog (false) otherwise.
|
||||
`.ini` equivalent: `input_intel_syntax`. Default: Intel (true) on Intel 8080/8085, Zilog (false) otherwise.
|
||||
|
||||
* `-foutput_intel_syntax`, `-foutput_zilog_syntax` –
|
||||
Choose syntax for assembly output on 8080-like targets.
|
||||
`.ini` equivalent: `output_intel_syntax`. Default: Intel (true) on Intel 8080, Zilog (false) otherwise.
|
||||
`.ini` equivalent: `output_intel_syntax`. Default: Intel (true) on Intel 8080/8085, Zilog (false) otherwise.
|
||||
|
||||
* `--syntax=intel`, `--syntax=zilog` – sets both previous options at once
|
||||
|
||||
|
@ -27,11 +27,13 @@ if a line ends with a backslash character, the value continues to the next line.
|
||||
|
||||
* `65816` (WDC 65816/65802; experimental; currently only programs that use only 16-bit addressing are supported)
|
||||
|
||||
* `z80` (Zilog Z80; experimental and slightly incomplete)
|
||||
* `z80` (Zilog Z80)
|
||||
|
||||
* `i8080` (Intel 8080; experimental, buggy and very incomplete)
|
||||
* `i8080` (Intel 8080)
|
||||
|
||||
* `gameboy` (Sharp LR35902; experimental, buggy and very incomplete)
|
||||
* `i8085` (Intel 8085)
|
||||
|
||||
* `gameboy` (Sharp LR35902; experimental)
|
||||
|
||||
* `i8086` (Intel 8086; very experimental, very buggy and very, very incomplete –
|
||||
see the [8086 support disclaimer](../lang/x86disclaimer.md))
|
||||
@ -94,7 +96,7 @@ Default: the same as `encoding`.
|
||||
|
||||
* `software_stach` – use software stack for stack variables, default is `false`
|
||||
|
||||
* `output_intel_syntax` – use Intel syntax instead of Zilog syntax, default is `true` for Intel 8080 and `false` otherwise
|
||||
* `output_intel_syntax` – use Intel syntax instead of Zilog syntax, default is `true` for Intel 8080/8085 and `false` otherwise
|
||||
|
||||
|
||||
#### `[define]` section
|
||||
|
@ -44,7 +44,7 @@ You may be also interested in the following:
|
||||
* `-fipo` – enable interprocedural optimization
|
||||
|
||||
* `-s` – additionally generate assembly output
|
||||
(if targeting Intel 8080, use `--syntax=intel` or `--syntax=zilog` to choose the preferred assembly syntax)
|
||||
(if targeting Intel 8080/8085, use `--syntax=intel` or `--syntax=zilog` to choose the preferred assembly syntax)
|
||||
|
||||
* `-fsource-in-asm` – show original Millfork source in the assembly output
|
||||
|
||||
|
@ -26,7 +26,7 @@ Support for other devices using supported processors can be easily added, usuall
|
||||
|
||||
* 6502 and its descendants: 6510, 65C02, Ricoh 2A03, and to a lesser degree CSG 65CE02, Hudson Soft HuC6280 and WDC 65816. 6509 is not supported and will not be.
|
||||
|
||||
* Intel 8080, Zilog Z80, Sharp LR35902 (also known as GBZ80)
|
||||
* Intel 8080, Intel 8085, Zilog Z80, Sharp LR35902 (also known as GBZ80)
|
||||
|
||||
* There is also partial experimental support for Intel 8086, via automatic 8080-to-8086 translation.
|
||||
The generated code is very large and very slow.
|
||||
|
@ -10,7 +10,7 @@ There are two ways to include raw assembly code in your Millfork programs:
|
||||
|
||||
## Assembly syntax
|
||||
|
||||
By default, Millfork uses Zilog syntax for Z80 and LR35902 assembly and Intel syntax for Intel 8080 assembly.
|
||||
By default, Millfork uses Zilog syntax for Z80 and LR35902 assembly and Intel syntax for Intel 8080/8085 assembly.
|
||||
This can be overridden per file by a pragma directive or by several other means.
|
||||
Using both kinds of syntax in one file is not supported.
|
||||
|
||||
|
@ -41,7 +41,7 @@ case class CompilationOptions(platform: Platform,
|
||||
EmitIntel8080Opcodes, UseIxForStack, UseIntelSyntaxForInput, UseIntelSyntaxForOutput)
|
||||
|
||||
if (CpuFamily.forType(platform.cpu) != CpuFamily.I80) invalids ++= Set(
|
||||
EmitExtended80Opcodes, EmitZ80Opcodes, EmitSharpOpcodes, EmitEZ80Opcodes,
|
||||
EmitIntel8085Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, EmitSharpOpcodes, EmitEZ80Opcodes,
|
||||
UseIyForStack, UseShadowRegistersForInterrupts)
|
||||
|
||||
invalids = invalids.filter(flags)
|
||||
@ -161,10 +161,15 @@ case class CompilationOptions(platform: Platform,
|
||||
}
|
||||
}
|
||||
if (flags(EmitIntel8080Opcodes)) {
|
||||
if (platform.cpu != Intel8080 && platform.cpu != Z80 && platform.cpu != EZ80) {
|
||||
if (platform.cpu != Intel8080 && platform.cpu != Intel8085 && platform.cpu != Z80 && platform.cpu != EZ80) {
|
||||
log.error("Intel 8080 opcodes enabled for architecture that doesn't support them")
|
||||
}
|
||||
}
|
||||
if (flags(EmitIntel8085Opcodes)) {
|
||||
if (platform.cpu != Intel8085) {
|
||||
log.error("Intel 8085 opcodes enabled for architecture that doesn't support them")
|
||||
}
|
||||
}
|
||||
case CpuFamily.I86 =>
|
||||
if (flags(EmitIllegals)) {
|
||||
log.error("Illegal opcodes enabled for architecture that doesn't support them")
|
||||
@ -198,6 +203,7 @@ case class CompilationOptions(platform: Platform,
|
||||
"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_65CE02" -> toLong(flag(CompilationFlag.Emit65CE02Opcodes)),
|
||||
@ -227,15 +233,15 @@ object CpuFamily extends Enumeration {
|
||||
import Cpu._
|
||||
cpu match {
|
||||
case Mos | StrictMos | Ricoh | StrictRicoh | Cmos | HuC6280 | CE02 | Sixteen => M6502
|
||||
case Intel8080 | Sharp | Z80 | EZ80 => I80
|
||||
case Intel8086 => I86
|
||||
case Intel8080 | Intel8085 | Sharp | Z80 | EZ80 => I80
|
||||
case Intel8086 | Intel80186 => I86
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object Cpu extends Enumeration {
|
||||
|
||||
val Mos, StrictMos, Ricoh, StrictRicoh, Cmos, HuC6280, CE02, Sixteen, Intel8080, Z80, EZ80, Sharp, Intel8086, Intel80186 = Value
|
||||
val Mos, StrictMos, Ricoh, StrictRicoh, Cmos, HuC6280, CE02, Sixteen, Intel8080, Intel8085, Z80, EZ80, Sharp, Intel8086, Intel80186 = Value
|
||||
|
||||
val CmosCompatible = Set(Cmos, HuC6280, CE02, Sixteen)
|
||||
|
||||
@ -268,6 +274,8 @@ object Cpu extends Enumeration {
|
||||
mosAlwaysDefaultFlags ++ Set(DecimalMode, EmitCmosOpcodes, EmitEmulation65816Opcodes, EmitNative65816Opcodes, ReturnWordsViaAccumulator)
|
||||
case Intel8080 =>
|
||||
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, UseIntelSyntaxForInput, UseIntelSyntaxForOutput)
|
||||
case Intel8085 =>
|
||||
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, EmitIntel8085Opcodes, UseIntelSyntaxForInput, UseIntelSyntaxForOutput)
|
||||
case Z80 =>
|
||||
i80AlwaysDefaultFlags ++ Set(EmitIntel8080Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, UseIxForStack, UseShadowRegistersForInterrupts)
|
||||
case EZ80 =>
|
||||
@ -315,6 +323,9 @@ object Cpu extends Enumeration {
|
||||
case "8080" => Intel8080
|
||||
case "i8080" => Intel8080
|
||||
case "intel8080" => Intel8080
|
||||
case "8085" => Intel8085
|
||||
case "i8085" => Intel8085
|
||||
case "intel8085" => Intel8085
|
||||
case "intel8086" => Intel8086
|
||||
case "i8086" => Intel8086
|
||||
case "8086" => Intel8086
|
||||
@ -343,7 +354,7 @@ object CompilationFlag extends Enumeration {
|
||||
EmitCmosOpcodes, EmitCmosNopOpcodes, EmitHudsonOpcodes, Emit65CE02Opcodes, EmitEmulation65816Opcodes, EmitNative65816Opcodes,
|
||||
PreventJmpIndirectBug, LargeCode, ReturnWordsViaAccumulator, SoftwareStack,
|
||||
// compilation options for I80
|
||||
EmitIntel8080Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, EmitEZ80Opcodes, EmitSharpOpcodes,
|
||||
EmitIntel8080Opcodes, EmitIntel8085Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, EmitEZ80Opcodes, EmitSharpOpcodes,
|
||||
UseShadowRegistersForInterrupts,
|
||||
UseIxForStack, UseIyForStack,
|
||||
UseIxForScratch, UseIyForScratch,
|
||||
@ -381,6 +392,7 @@ object CompilationFlag extends Enumeration {
|
||||
"emit_ez80" -> EmitEZ80Opcodes,
|
||||
"emit_x80" -> EmitExtended80Opcodes,
|
||||
"emit_8080" -> EmitIntel8080Opcodes,
|
||||
"emit_8085" -> EmitIntel8085Opcodes,
|
||||
"emit_sharp" -> EmitSharpOpcodes,
|
||||
"ix_stack" -> UseIxForStack,
|
||||
"iy_stack" -> UseIyForStack,
|
||||
|
@ -258,7 +258,7 @@ object Main {
|
||||
case 0 => Nil
|
||||
case _ => platform.cpu match {
|
||||
case Cpu.Z80 | Cpu.EZ80 => Z80OptimizationPresets.GoodForZ80
|
||||
case Cpu.Intel8080 => Z80OptimizationPresets.GoodForIntel8080
|
||||
case Cpu.Intel8080 | Cpu.Intel8085 => Z80OptimizationPresets.GoodForIntel8080
|
||||
case Cpu.Sharp => Z80OptimizationPresets.GoodForSharp
|
||||
case _ => Nil
|
||||
}
|
||||
|
@ -249,6 +249,9 @@ object Platform {
|
||||
"CPU_Z80" -> toLong(cpu == Cpu.Z80),
|
||||
"CPU_EZ80" -> toLong(cpu == Cpu.EZ80),
|
||||
"CPU_8080" -> toLong(cpu == Cpu.Intel8080),
|
||||
"CPU_8085" -> toLong(cpu == Cpu.Intel8085),
|
||||
"CPU_8086" -> toLong(cpu == Cpu.Intel8086),
|
||||
"CPU_80186" -> toLong(cpu == Cpu.Intel80186),
|
||||
"CPU_GAMEBOY" -> toLong(cpu == Cpu.Sharp),
|
||||
"ARCH_X86" -> toLong(CpuFamily.forType(cpu) == CpuFamily.I86),
|
||||
"ARCH_6800" -> toLong(CpuFamily.forType(cpu) == CpuFamily.M6800),
|
||||
|
@ -23,6 +23,8 @@ object ZOpcode extends Enumeration {
|
||||
EXX, EX_DE_HL, EX_AF_AF, EX_SP,
|
||||
RST, IM, EI, DI,
|
||||
DJNZ, JP, JR, CALL, RET, RETN, RETI, HALT,
|
||||
// 8085:
|
||||
RIM, SIM,
|
||||
//sharp:
|
||||
LD_AHLI, LD_AHLD, LD_HLIA, LD_HLDA, SWAP, LDH_DA, LDH_AD, LDH_CA, LDH_AC, LD_HLSP, ADD_SP, STOP,
|
||||
DISCARD_A, DISCARD_F, DISCARD_HL, DISCARD_BC, DISCARD_DE, DISCARD_IX, DISCARD_IY, CHANGED_MEM,
|
||||
@ -56,7 +58,7 @@ object ZOpcodeClasses {
|
||||
|
||||
val ChangesAFAlways = Set( // TODO: !
|
||||
DAA, ADD, ADC, SUB, SBC, XOR, OR, AND, INC, DEC,
|
||||
SCF, CCF, NEG,
|
||||
SCF, CCF, NEG, RIM,
|
||||
LDH_AC, LDH_AD, LD_AHLI, LD_AHLD,
|
||||
ADD_16, ADC_16, SBC_16, INC_16, DEC_16,
|
||||
INI, INIR, OUTI, OUTIR, IND, INDR, OUTD, OUTDR,
|
||||
@ -76,6 +78,6 @@ object ZOpcodeClasses {
|
||||
EXX, EX_DE_HL, CALL, JR, JP, LABEL)
|
||||
val ChangesOnlyRegister: Set[ZOpcode.Value] = Set(INC, DEC, INC_16, DEC_16, POP, EX_SP, IN_C, IN_IMM, RL, RR, RLC, RRC, SLA, SRA, SRL, SLL) ++ SET ++ RES
|
||||
val ChangesFirstRegister = Set(LD, LD_16, ADD_16, SBC_16)
|
||||
val ChangesAAlways = Set(DAA, ADD, ADC, SUB, SBC, XOR, OR, AND, LD_AHLI, LD_AHLD)
|
||||
val ChangesAAlways = Set(DAA, ADD, ADC, SUB, SBC, XOR, OR, AND, LD_AHLI, LD_AHLD, RIM)
|
||||
val NonLinear = Set(JP, JR, CALL, LABEL, BYTE, EXX, EX_DE_HL, EX_SP, EXX, RET, RETI, RETN, HALT)
|
||||
}
|
@ -10,7 +10,7 @@ import millfork.DecimalUtils._
|
||||
import millfork.error.FatalErrorReporting
|
||||
|
||||
/**
|
||||
* Optimizations valid for Intel8080, Z80, EZ80 and Sharp
|
||||
* Optimizations valid for Intel8080, Intel8085, Z80, EZ80 and Sharp
|
||||
* @author Karol Stasiak
|
||||
*/
|
||||
object AlwaysGoodI80Optimizations {
|
||||
|
@ -67,7 +67,7 @@ object CoarseFlowAnalyzer {
|
||||
)
|
||||
}
|
||||
|
||||
case ZLine0(NOP | DISCARD_A | DISCARD_BC | DISCARD_DE | DISCARD_HL | DISCARD_F, _, _) =>
|
||||
case ZLine0(NOP | DISCARD_A | DISCARD_BC | DISCARD_DE | DISCARD_HL | DISCARD_F | SIM, _, _) =>
|
||||
()
|
||||
case ZLine0(PUSH, _, _) =>
|
||||
()
|
||||
@ -287,6 +287,8 @@ object CoarseFlowAnalyzer {
|
||||
pf = AnyStatus,
|
||||
nf = Status.SingleFalse)
|
||||
|
||||
case ZLine0(RIM, _, _) =>
|
||||
currentStatus = currentStatus.copy(a = AnyStatus)
|
||||
|
||||
case ZLine0(opcode, registers, _) =>
|
||||
currentStatus = currentStatus.copy(cf = AnyStatus, zf = AnyStatus, sf = AnyStatus, pf = AnyStatus, hf = AnyStatus)
|
||||
|
@ -459,6 +459,10 @@ object ReverseFlowAnalyzer {
|
||||
currentImportance = currentImportance.butReadsRegister(ZRegister.A).copy(cf = Important, hf = Unimportant, nf = Unimportant)
|
||||
case ZLine0(SCF, _, _) =>
|
||||
currentImportance = currentImportance.copy(cf = Unimportant, hf = Unimportant, nf = Unimportant)
|
||||
case ZLine0(RIM, _, _) =>
|
||||
currentImportance = currentImportance.copy(a = Unimportant)
|
||||
case ZLine0(SIM, _, _) =>
|
||||
currentImportance = currentImportance.copy(a = Important)
|
||||
case _ =>
|
||||
currentImportance = finalImportance // TODO
|
||||
}
|
||||
|
@ -61,6 +61,8 @@ class Z80Assembler(program: Program,
|
||||
|
||||
def requireEZ80(): Unit = if (!options.flag(EmitEZ80Opcodes)) log.error("Unsupported instruction: " + instr)
|
||||
|
||||
def requireIntel8085(): Unit = if (!options.flag(EmitIntel8085Opcodes)) log.error("Unsupported instruction: " + instr)
|
||||
|
||||
def useSharpOpcodes():Boolean = {
|
||||
if (!options.flag(EmitSharpOpcodes) && !options.flag(EmitIntel8080Opcodes))
|
||||
log.error("Cannot determine which variant to emit : " + instr)
|
||||
@ -78,6 +80,14 @@ class Z80Assembler(program: Program,
|
||||
index
|
||||
case ZLine0(LABEL | BYTE | DISCARD_F | DISCARD_HL | DISCARD_BC | DISCARD_DE | DISCARD_IX | DISCARD_IY | DISCARD_A | CHANGED_MEM, _, _) =>
|
||||
???
|
||||
case ZLine0(RIM, NoRegisters, _) =>
|
||||
requireIntel8085()
|
||||
writeByte(bank, index, 0x20)
|
||||
index + 1
|
||||
case ZLine0(SIM, NoRegisters, _) =>
|
||||
requireIntel8085()
|
||||
writeByte(bank, index, 0x30)
|
||||
index + 1
|
||||
case ZLine0(RST, NoRegisters, param) =>
|
||||
val opcode = param.quickSimplify match {
|
||||
case NumericConstant(n, _) if n >=0 && n <= 0x38 && n % 8 == 0 => 0xc7 + n.toInt
|
||||
|
@ -230,6 +230,8 @@ case class Z80Parser(filename: String,
|
||||
case "HLT" => imm(HALT)
|
||||
case "HALT" => imm(HALT)
|
||||
case "STOP" => imm(STOP)
|
||||
case "RIM" => imm(RIM)
|
||||
case "SIM" => imm(SIM)
|
||||
|
||||
case "RETN" => imm(RETN)
|
||||
case "RETI" => imm(RETI)
|
||||
@ -449,6 +451,8 @@ case class Z80Parser(filename: String,
|
||||
case "CMA" => imm(CPL)
|
||||
case "STC" => imm(SCF)
|
||||
case "CMC" => imm(CCF)
|
||||
case "RIM" => imm(RIM)
|
||||
case "SIM" => imm(SIM)
|
||||
|
||||
case "HLT" => imm(HALT)
|
||||
case "EI" => imm(EI)
|
||||
|
@ -1,7 +1,7 @@
|
||||
package millfork.test
|
||||
|
||||
import millfork.Cpu
|
||||
import millfork.test.emu.{EmuUnoptimizedCrossPlatformRun, EmuUnoptimizedIntel8080Run, EmuUnoptimizedSharpRun, EmuUnoptimizedZ80Run}
|
||||
import millfork.test.emu.{EmuUnoptimizedCrossPlatformRun, EmuUnoptimizedIntel8080Run, EmuUnoptimizedIntel8085Run, EmuUnoptimizedSharpRun, EmuUnoptimizedZ80Run}
|
||||
import org.scalatest.{FunSuite, Matchers}
|
||||
|
||||
/**
|
||||
@ -900,4 +900,32 @@ class Z80AssemblySuite extends FunSuite with Matchers {
|
||||
| }
|
||||
""".stripMargin)
|
||||
}
|
||||
|
||||
|
||||
test("Intel 8085 instructions (Zilog syntax)") {
|
||||
EmuUnoptimizedIntel8085Run(
|
||||
"""
|
||||
| #pragma zilog_syntax
|
||||
| asm void main () {
|
||||
| ret
|
||||
| rim
|
||||
| sim
|
||||
| ret
|
||||
| }
|
||||
""".stripMargin)
|
||||
}
|
||||
|
||||
|
||||
test("Intel 8085 instructions (Intel syntax)") {
|
||||
EmuUnoptimizedIntel8085Run(
|
||||
"""
|
||||
| #pragma intelg_syntax
|
||||
| asm void main () {
|
||||
| ret
|
||||
| rim
|
||||
| sim
|
||||
| ret
|
||||
| }
|
||||
""".stripMargin)
|
||||
}
|
||||
}
|
@ -20,6 +20,8 @@ object EmuUnoptimizedZ80Run extends EmuZ80Run(Cpu.Z80, Nil, Nil)
|
||||
|
||||
object EmuUnoptimizedIntel8080Run extends EmuZ80Run(Cpu.Intel8080, Nil, Nil)
|
||||
|
||||
object EmuUnoptimizedIntel8085Run extends EmuZ80Run(Cpu.Intel8085, Nil, Nil)
|
||||
|
||||
object EmuUnoptimizedIntel8086Run extends EmuI86Run(Nil, Nil)
|
||||
|
||||
object EmuUnoptimizedSharpRun extends EmuZ80Run(Cpu.Sharp, Nil, Nil)
|
||||
|
Loading…
Reference in New Issue
Block a user