mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-16 00:31:30 +00:00
ZX Spectrum Next CPU support
This commit is contained in:
parent
f7dd78e4c0
commit
d1058b6223
@ -31,6 +31,8 @@ if a line ends with a backslash character, the value continues to the next line.
|
||||
|
||||
* `strictz80` (Z80 without illegal instructions)
|
||||
|
||||
* `z80next` (Z80 core from ZX Spectrum Next)
|
||||
|
||||
* `i8080` (Intel 8080)
|
||||
|
||||
* `i8085` (Intel 8085)
|
||||
|
@ -25,6 +25,8 @@ Only instructions available on the current CPU architecture are available.
|
||||
Intel syntax does not support instructions that are unavailable on the 8080.
|
||||
Undocumented Z80 instructions are not supported, except for `SLL`.
|
||||
|
||||
Not all ZX Spectrum Next are supported. `JP (C)`, `BSLA` and similar instructions are not supported.
|
||||
|
||||
Labels have to be followed by a colon and they can optionally be on a separate line.
|
||||
Indentation is not important:
|
||||
|
||||
|
@ -52,7 +52,7 @@ The following features are defined based on the chosen CPU and compilation optio
|
||||
|
||||
* `CPUFEATURE_65C02`, `CPUFEATURE_65CE02`, `CPUFEATURE_HUC6280`, `CPUFEATURE_65816_EMULATION`, `CPUFEATURE_65816_NATIVE`,
|
||||
`CPUFEATURE_8080`, `CPUFEATURE_8085`, `CPUFEATURE_GAMEBOY`, `CPUFEATURE_Z80`,
|
||||
`CPUFEATURE_6502_ILLEGALS`, `CPUFEATURE_8085_ILLEGALS`, `CPUFEATURE_Z80_ILLEGALS` – 1 if given instruction subset is enabled, 0 otherwise
|
||||
`CPUFEATURE_6502_ILLEGALS`, `CPUFEATURE_8085_ILLEGALS`, `CPUFEATURE_Z80_ILLEGALS`, `CPUFEATURE_Z80_NEXT` – 1 if given instruction subset is enabled, 0 otherwise
|
||||
|
||||
* `ENCODING_SAME` - 1 if the encodings `default` and `src` are the same, 0 otherwise.
|
||||
|
||||
|
@ -4,9 +4,15 @@
|
||||
#endif
|
||||
|
||||
#pragma zilog_syntax
|
||||
|
||||
#if CPUFEATURE_Z80 || CPUFEATURE_GAMEBOY
|
||||
|
||||
#if CPUFEATURE_Z80_NEXT
|
||||
inline asm byte __mul_u8u8u8() {
|
||||
? LD E,A
|
||||
? MUL
|
||||
? LD A, E
|
||||
? RET
|
||||
}
|
||||
#elseif CPUFEATURE_Z80 || CPUFEATURE_GAMEBOY
|
||||
//A = A * D
|
||||
noinline asm byte __mul_u8u8u8() {
|
||||
? LD E,A
|
||||
? LD A, 0
|
||||
|
@ -43,7 +43,7 @@ case class CompilationOptions(platform: Platform,
|
||||
EmitIntel8085Opcodes, EmitIntel8080Opcodes, UseIxForStack, UseIntelSyntaxForInput, UseIntelSyntaxForOutput)
|
||||
|
||||
if (CpuFamily.forType(platform.cpu) != CpuFamily.I80) invalids ++= Set(
|
||||
EmitExtended80Opcodes, EmitZ80Opcodes, EmitSharpOpcodes, EmitEZ80Opcodes,
|
||||
EmitExtended80Opcodes, EmitZ80Opcodes, EmitSharpOpcodes, EmitEZ80Opcodes, EmitZ80NextOpcodes,
|
||||
UseIyForStack, UseIxForScratch, UseIyForScratch, UseShadowRegistersForInterrupts)
|
||||
|
||||
if (CpuFamily.forType(platform.cpu) != CpuFamily.M6809) invalids ++= Set(
|
||||
@ -111,7 +111,7 @@ case class CompilationOptions(platform: Platform,
|
||||
}
|
||||
case CpuFamily.I80 =>
|
||||
if (flags(EmitIllegals)) {
|
||||
if (platform.cpu != Z80 && platform.cpu != Intel8085) {
|
||||
if (platform.cpu != Z80 && platform.cpu != Intel8085 && platform.cpu != Z80Next) {
|
||||
log.error("Illegal opcodes enabled for architecture that doesn't support them")
|
||||
}
|
||||
}
|
||||
@ -160,6 +160,11 @@ case class CompilationOptions(platform: Platform,
|
||||
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")
|
||||
@ -221,6 +226,7 @@ case class CompilationOptions(platform: Platform,
|
||||
"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)),
|
||||
@ -276,7 +282,7 @@ object CpuFamily extends Enumeration {
|
||||
import Cpu._
|
||||
cpu match {
|
||||
case Mos | StrictMos | Ricoh | StrictRicoh | Cmos | HuC6280 | CE02 | Sixteen => M6502
|
||||
case Intel8080 | Intel8085 | StrictIntel8085 | Sharp | Z80 | StrictZ80 | EZ80 => I80
|
||||
case Intel8080 | Intel8085 | StrictIntel8085 | Sharp | Z80 | StrictZ80 | EZ80 | Z80Next => I80
|
||||
case Intel8086 | Intel80186 => I86
|
||||
case Cpu.Motorola6809 => M6809
|
||||
}
|
||||
@ -346,6 +352,10 @@ object Cpu extends Enumeration {
|
||||
* 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
|
||||
*/
|
||||
@ -370,11 +380,11 @@ object Cpu extends Enumeration {
|
||||
/**
|
||||
* Processors that can run code for Zilog Z80
|
||||
*/
|
||||
val Z80Compatible: Set[Cpu.Value] = Set(Z80, StrictZ80, EZ80)
|
||||
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)
|
||||
val Intel8080Compatible: Set[Cpu.Value] = Set(Intel8080, Intel8085, StrictIntel8085, Z80, StrictZ80, EZ80, Z80Next)
|
||||
/**
|
||||
* Processors that can run code for Intel 8085
|
||||
*/
|
||||
@ -415,6 +425,8 @@ object Cpu extends Enumeration {
|
||||
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 =>
|
||||
@ -456,6 +468,7 @@ object Cpu extends Enumeration {
|
||||
case "strict2a07" => StrictRicoh
|
||||
case "z80" => Z80
|
||||
case "strictz80" => Z80
|
||||
case "zx80next" => Z80Next
|
||||
// disabled for now:
|
||||
// case "ez80" => EZ80
|
||||
case "gameboy" => Sharp
|
||||
@ -504,7 +517,7 @@ object CompilationFlag extends Enumeration {
|
||||
EmitCmosOpcodes, EmitCmosNopOpcodes, EmitHudsonOpcodes, Emit65CE02Opcodes, EmitEmulation65816Opcodes, EmitNative65816Opcodes,
|
||||
PreventJmpIndirectBug, LargeCode, ReturnWordsViaAccumulator, SoftwareStack,
|
||||
// compilation options for I80
|
||||
EmitIntel8080Opcodes, EmitIntel8085Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, EmitEZ80Opcodes, EmitSharpOpcodes,
|
||||
EmitIntel8080Opcodes, EmitIntel8085Opcodes, EmitExtended80Opcodes, EmitZ80Opcodes, EmitEZ80Opcodes, EmitSharpOpcodes, EmitZ80NextOpcodes,
|
||||
UseShadowRegistersForInterrupts,
|
||||
UseIxForStack, UseIyForStack,
|
||||
UseIxForScratch, UseIyForScratch,
|
||||
|
@ -29,6 +29,8 @@ object ZOpcode extends Enumeration {
|
||||
LD_DESP, LD_DEHL, RRHL, RLDE, DSUB, RSTV, LHLX, SHLX,
|
||||
//sharp:
|
||||
LD_AHLI, LD_AHLD, LD_HLIA, LD_HLDA, SWAP, LDH_DA, LDH_AD, LDH_CA, LDH_AC, LD_HLSP, ADD_SP, STOP,
|
||||
// next:
|
||||
LDIX, LDWS, LDIRX, LDDX, LDDRX, LDPIRX, OUTINB, MUL, SWAPNIB, MIRROR, NEXTREG, PIXELDN, PIXELAD, SETAE, TEST,
|
||||
DISCARD_A, DISCARD_F, DISCARD_HL, DISCARD_BC, DISCARD_DE, DISCARD_IX, DISCARD_IY, CHANGED_MEM,
|
||||
LABEL, BYTE = Value
|
||||
}
|
||||
@ -69,19 +71,25 @@ object ZOpcodeClasses {
|
||||
val ChangesBCAlways: Set[ZOpcode.Value] = Set(
|
||||
INI, INIR, OUTI, OUTIR, IND, INDR, OUTD, OUTDR,
|
||||
LDI, LDIR, LDD, LDDR, CPI, CPIR, CPD, CPDR,
|
||||
LDIX, LDIRX, LDDX, LDDRX, LDPIRX,
|
||||
EXX, CALL, JR, JP, LABEL, DJNZ)
|
||||
val ChangesHLAlways: Set[ZOpcode.Value] = Set(
|
||||
INI, INIR, OUTI, OUTIR, IND, INDR, OUTD, OUTDR,
|
||||
LDI, LDIR, LDD, LDDR, CPI, CPIR, CPD, CPDR,
|
||||
LD_AHLI, LD_AHLD, LD_HLIA, LD_HLDA, LD_HLSP, DSUB,
|
||||
RRHL, LHLX,
|
||||
LDWS, LDIX, LDIRX, LDDX, LDDRX, LDPIRX, PIXELAD, PIXELDN, OUTINB,
|
||||
EXX, EX_DE_HL, CALL, JR, JP, LABEL)
|
||||
val ChangesDEAlways: Set[ZOpcode.Value] = Set(
|
||||
LDI, LDIR, LDD, LDDR,
|
||||
LD_DESP, LD_DEHL, RLDE,
|
||||
LDWS, LDIX, LDIRX, LDDX, LDDRX, LDPIRX, MUL,
|
||||
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[ZOpcode.Value] = Set(LD, LD_16, ADD_16, SBC_16)
|
||||
val ChangesAAlways: Set[ZOpcode.Value] = Set(DAA, ADD, ADC, SUB, SBC, XOR, OR, AND, LD_AHLI, LD_AHLD, RIM)
|
||||
val ChangesAAlways: Set[ZOpcode.Value] = Set(
|
||||
DAA, ADD, ADC, SUB, SBC, XOR, OR, AND, LD_AHLI, LD_AHLD, RIM,
|
||||
MIRROR, SETAE,
|
||||
)
|
||||
val NonLinear: Set[ZOpcode.Value] = Set(JP, JR, CALL, LABEL, BYTE, EXX, EX_DE_HL, EX_SP, EXX, RET, RETI, RETN, HALT, RST, RSTV)
|
||||
}
|
||||
|
@ -69,6 +69,8 @@ class Z80Assembler(program: Program,
|
||||
|
||||
def requireIntel8085Illegals(): Unit = if (!options.flag(EmitIntel8085Opcodes) || !options.flag(EmitIllegals)) log.error("Unsupported instruction: " + instr)
|
||||
|
||||
def requireNext(): Unit = if (!options.flag(EmitZ80NextOpcodes)) log.error("Unsupported instruction: " + instr)
|
||||
|
||||
def useSharpOpcodes():Boolean = {
|
||||
if (!options.flag(EmitSharpOpcodes) && !options.flag(EmitIntel8080Opcodes))
|
||||
log.error("Cannot determine which variant to emit : " + instr)
|
||||
@ -144,6 +146,47 @@ class Z80Assembler(program: Program,
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index + 1, edImplieds(op))
|
||||
index + 2
|
||||
case ZLine0(op, NoRegisters, _) if nextEdImplieds.contains(op) =>
|
||||
requireNext()
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index + 1, nextEdImplieds(op))
|
||||
index + 2
|
||||
case ZLine0(ADD_16, TwoRegisters(r@(ZRegister.HL | ZRegister.BC | ZRegister.DE), ZRegister.A), _) =>
|
||||
requireNext()
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index + 1, 0x33 - internalRegisterIndex(r))
|
||||
index + 2
|
||||
case ZLine0(ADD_16, TwoRegisters(r@(ZRegister.HL | ZRegister.BC | ZRegister.DE), ZRegister.IMM_16), nn) =>
|
||||
requireNext()
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index + 1, 0x36 - internalRegisterIndex(r))
|
||||
writeWord(bank, index + 2, nn)
|
||||
index + 4
|
||||
case ZLine0(PUSH, OneRegister(ZRegister.IMM_16), nn) =>
|
||||
requireNext()
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index + 1, 0x8A)
|
||||
writeByte(bank, index + 2, nn.hiByte)
|
||||
writeByte(bank, index + 3, nn.loByte)
|
||||
index + 4
|
||||
case ZLine0(TEST, OneRegister(ZRegister.IMM_8), nn) =>
|
||||
requireNext()
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index + 1, 0x27)
|
||||
writeByte(bank, index + 2, nn)
|
||||
index + 3
|
||||
case ZLine0(NEXTREG, TwoRegisters(ZRegister.IMM_8, ZRegister.IMM_8), nn) =>
|
||||
requireNext()
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index + 1, 0x91)
|
||||
writeWord(bank, index + 2, nn)
|
||||
index + 4
|
||||
case ZLine0(NEXTREG, TwoRegisters(ZRegister.IMM_8, ZRegister.A), nn) =>
|
||||
requireNext()
|
||||
writeByte(bank, index, 0xed)
|
||||
writeByte(bank, index + 1, 0x92)
|
||||
writeByte(bank, index + 2, nn)
|
||||
index + 3
|
||||
case ZLine0(ADD_16, TwoRegisters(ZRegister.HL, source), _) =>
|
||||
writeByte(bank, index, 9 + 16 * internalRegisterIndex(source))
|
||||
index + 1
|
||||
@ -776,6 +819,7 @@ object Z80Assembler {
|
||||
val edImplieds: mutable.Map[ZOpcode.Value, Int] = mutable.Map[ZOpcode.Value, Int]()
|
||||
val oneRegister: mutable.Map[ZOpcode.Value, One] = mutable.Map[ZOpcode.Value, One]()
|
||||
val cbOneRegister: mutable.Map[ZOpcode.Value, One] = mutable.Map[ZOpcode.Value, One]()
|
||||
val nextEdImplieds: mutable.Map[ZOpcode.Value, Int] = mutable.Map[ZOpcode.Value, Int]()
|
||||
|
||||
do {
|
||||
import ZOpcode._
|
||||
@ -846,6 +890,20 @@ object Z80Assembler {
|
||||
cbOneRegister(SLA) = One(0x20, 1)
|
||||
cbOneRegister(SRA) = One(0x28, 1)
|
||||
cbOneRegister(SRL) = One(0x38, 1)
|
||||
|
||||
nextEdImplieds(LDIX) = 0xa4
|
||||
nextEdImplieds(LDWS) = 0xa5
|
||||
nextEdImplieds(LDIRX) = 0xb4
|
||||
nextEdImplieds(LDDX) = 0xb5
|
||||
nextEdImplieds(LDDRX) = 0xac
|
||||
nextEdImplieds(LDPIRX) = 0xbc
|
||||
nextEdImplieds(OUTINB) = 0x90
|
||||
nextEdImplieds(MUL) = 0xa4
|
||||
nextEdImplieds(SWAPNIB) = 0x23
|
||||
nextEdImplieds(MIRROR) = 0x24
|
||||
nextEdImplieds(PIXELDN) = 0x93
|
||||
nextEdImplieds(PIXELAD) = 0x94
|
||||
nextEdImplieds(SETAE) = 0x95
|
||||
} while (false)
|
||||
|
||||
}
|
||||
|
@ -452,6 +452,20 @@ case class Z80Parser(filename: String,
|
||||
case (r1, e1, (r2, e2)) => merge(LD, LD_16, skipTargetA = false)((r1, e1, r2, e2))
|
||||
}
|
||||
case "ADD" => (param(allowAbsolute = false) ~ HWS ~ position("comma").map(_ => ()) ~ "," ~/ HWS ~ param(allowAbsolute = false)).map {
|
||||
|
||||
case (ZRegister.HL, None, (ZRegister.A, None)) if options.flags(CompilationFlag.EmitZ80NextOpcodes) =>
|
||||
(ADD_16, TwoRegisters(ZRegister.HL, ZRegister.A), None, zero)
|
||||
case (ZRegister.DE, None, (ZRegister.A, None)) if options.flags(CompilationFlag.EmitZ80NextOpcodes) =>
|
||||
(ADD_16, TwoRegisters(ZRegister.DE, ZRegister.A), None, zero)
|
||||
case (ZRegister.BC, None, (ZRegister.A, None)) if options.flags(CompilationFlag.EmitZ80NextOpcodes) =>
|
||||
(ADD_16, TwoRegisters(ZRegister.BC, ZRegister.A), None, zero)
|
||||
case (ZRegister.HL, None, (ZRegister.IMM_8, Some(expr))) =>
|
||||
(ADD_16, TwoRegisters(ZRegister.HL, ZRegister.IMM_16), None, expr)
|
||||
case (ZRegister.DE, None, (ZRegister.IMM_8, Some(expr))) =>
|
||||
(ADD_16, TwoRegisters(ZRegister.DE, ZRegister.IMM_16), None, expr)
|
||||
case (ZRegister.BC, None, (ZRegister.IMM_8, Some(expr))) =>
|
||||
(ADD_16, TwoRegisters(ZRegister.BC, ZRegister.IMM_16), None, expr)
|
||||
|
||||
case (ZRegister.SP, None, (ZRegister.IMM_8, Some(expr))) if options.flags(CompilationFlag.EmitSharpOpcodes) =>
|
||||
(ADD_SP, OneRegister(ZRegister.IMM_8), None, expr)
|
||||
case (r1, e1, (r2, e2)) => merge(ADD, ADD_16, skipTargetA = true)((r1, e1, r2, e2))
|
||||
@ -466,6 +480,28 @@ case class Z80Parser(filename: String,
|
||||
case "DSUB" => imm(DSUB)
|
||||
case "RSTV" => imm(RSTV)
|
||||
|
||||
case "LDIX" => imm(LDIX)
|
||||
case "LDWS" => imm(LDWS)
|
||||
case "LDIRX" => imm(LDIRX)
|
||||
case "LDDX" => imm(LDDX)
|
||||
case "LDDRX" => imm(LDDRX)
|
||||
case "LDPIRX" => imm(LDPIRX)
|
||||
case "OUTINB" => imm(OUTINB)
|
||||
case "SWAPNIB" => imm(SWAPNIB)
|
||||
case "PIXELDN" => imm(PIXELDN)
|
||||
case "PIXELAD" => imm(PIXELAD)
|
||||
case "SETAE" => imm(SETAE)
|
||||
case "MUL" => (("D"|"d") ~ HWS ~ "," ~/ HWS ~ ("E" | "e")).?.map { _ => (MUL, NoRegisters, None, zero)}
|
||||
case "MIRROR" => ("A"|"a").?.map { _ => (MUL, NoRegisters, None, zero)}
|
||||
case "NEXTREG" =>(param(allowAbsolute = false) ~ HWS ~ position("comma").map(_ => ()) ~ "," ~/ HWS ~ param(allowAbsolute = false)).map {
|
||||
case (ZRegister.IMM_8, Some(n), (ZRegister.A, None)) => (NEXTREG, TwoRegisters(ZRegister.IMM_8, ZRegister.A), None, n)
|
||||
case (ZRegister.IMM_8, Some(n), (ZRegister.IMM_8, Some(v))) => (NEXTREG, TwoRegisters(ZRegister.IMM_8, ZRegister.IMM_8), None, SeparateBytesExpression(v, n))
|
||||
case _ =>
|
||||
log.error("Invalid parameters for NEXTREG", Some(pos))
|
||||
(NOP, NoRegisters, None, zero)
|
||||
}
|
||||
case "TEST" => one8Register(TEST)
|
||||
|
||||
case _ =>
|
||||
log.error("Unsupported opcode " + opcode, Some(pos))
|
||||
imm(NOP)
|
||||
|
@ -1,7 +1,7 @@
|
||||
package millfork.test
|
||||
|
||||
import millfork.Cpu
|
||||
import millfork.test.emu.{EmuUnoptimizedCrossPlatformRun, EmuUnoptimizedIntel8080Run, EmuUnoptimizedIntel8085Run, EmuUnoptimizedSharpRun, EmuUnoptimizedZ80Run}
|
||||
import millfork.test.emu.{EmuUnoptimizedCrossPlatformRun, EmuUnoptimizedIntel8080Run, EmuUnoptimizedIntel8085Run, EmuUnoptimizedSharpRun, EmuUnoptimizedZ80NextRun, EmuUnoptimizedZ80Run}
|
||||
import org.scalatest.{FunSuite, Matchers}
|
||||
|
||||
/**
|
||||
@ -975,4 +975,41 @@ class Z80AssemblySuite extends FunSuite with Matchers {
|
||||
| }
|
||||
""".stripMargin)
|
||||
}
|
||||
|
||||
test("Z80 Next instructions (Zilog syntax)") {
|
||||
EmuUnoptimizedZ80NextRun(
|
||||
"""
|
||||
| #pragma zilog_syntax
|
||||
| asm void main () {
|
||||
| ret
|
||||
| ldix
|
||||
| ldws
|
||||
| ldirx
|
||||
| lddx
|
||||
| lddrx
|
||||
| ldpirx
|
||||
| outinb
|
||||
| mul
|
||||
| mul d,e
|
||||
| add hl,a
|
||||
| add de,a
|
||||
| add bc,a
|
||||
| add hl,1
|
||||
| add de,2
|
||||
| add bc,3
|
||||
| swapnib
|
||||
| mirror
|
||||
| mirror a
|
||||
| push $5555
|
||||
| nextreg 1,2
|
||||
| nextreg 1,a
|
||||
| pixeldn
|
||||
| pixelad
|
||||
| setae
|
||||
| test 8
|
||||
| ret
|
||||
| }
|
||||
""".stripMargin)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ object EmuUnoptimizedIntel8080Run extends EmuZ80Run(Cpu.Intel8080, Nil, Nil)
|
||||
|
||||
object EmuUnoptimizedIntel8085Run extends EmuZ80Run(Cpu.Intel8085, Nil, Nil)
|
||||
|
||||
object EmuUnoptimizedZ80NextRun extends EmuZ80Run(Cpu.Z80Next, Nil, Nil)
|
||||
|
||||
object EmuUnoptimizedIntel8086Run extends EmuI86Run(Nil, Nil)
|
||||
|
||||
object EmuUnoptimizedSharpRun extends EmuZ80Run(Cpu.Sharp, Nil, Nil)
|
||||
|
@ -83,7 +83,8 @@ class EmuZ80Run(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimizatio
|
||||
CompilationFlag.OptimizeStdlib -> this.inline,
|
||||
CompilationFlag.OptimizeForSize -> this.optimizeForSize,
|
||||
CompilationFlag.SubroutineExtraction -> optimizeForSize,
|
||||
CompilationFlag.EmitIllegals -> (cpu == millfork.Cpu.Z80 || cpu == millfork.Cpu.Intel8085),
|
||||
CompilationFlag.EmitIllegals -> (cpu == millfork.Cpu.Z80 || cpu == millfork.Cpu.Intel8085 || cpu == millfork.Cpu.Z80Next),
|
||||
CompilationFlag.EmitZ80NextOpcodes -> (cpu == millfork.Cpu.Z80Next),
|
||||
CompilationFlag.LenientTextEncoding -> true)
|
||||
val options = CompilationOptions(platform, millfork.Cpu.defaultFlags(cpu).map(_ -> true).toMap ++ extraFlags, None, 0, Map(), JobContext(log, new LabelGenerator))
|
||||
println(cpu)
|
||||
|
Loading…
x
Reference in New Issue
Block a user