mirror of
https://github.com/KarolS/millfork.git
synced 2024-09-10 11:54:30 +00:00
Z80: LDH instruction for LR35902
This commit is contained in:
parent
f4a2c96512
commit
48b183828b
@ -12,15 +12,13 @@ There are two ways to include raw assembly code in your Millfork programs:
|
||||
|
||||
Millfork uses Zilog syntax for Intel 8080, Z80 and LR35902 assembly.
|
||||
|
||||
**Work in progress**:
|
||||
Intel syntax is not supported yet.
|
||||
LR35902 instructions for faster access to the $FFxx addresses are not available yet.
|
||||
|
||||
Indexing via the IX/IY register uses the following syntax: `IX(1)`
|
||||
|
||||
LR35902 instructions that load/store the accumulator indirectly via HL and then increment/decrement HL are written
|
||||
`LD A,(HLI)`, `LD, A,(HLD)`, `LD (HLI),A` and `LD (HLD),A`
|
||||
|
||||
LR35902 instructions for faster access to the $FFxx addresses use the `LDH` mnemonic: `LDH A,(4)`, `LDH (C),A` etc.
|
||||
|
||||
Only instructions available on the current CPU architecture are available.
|
||||
Undocumented instructions are not supported, except for `SLL`.
|
||||
|
||||
|
@ -279,6 +279,10 @@ case class ZLine(opcode: ZOpcode.Value, registers: ZRegisters, parameter: Consta
|
||||
case LD_AHLD => " LD A,(HLD)"
|
||||
case LD_HLIA => " LD (HLI),A"
|
||||
case LD_HLDA => " LD (HLD),A"
|
||||
case LDH_AC => " LDH A,(C)"
|
||||
case LDH_CA => " LDH (C),A"
|
||||
case LDH_DA => s" LDH ($parameter),A"
|
||||
case LDH_AD => s" LDH A,($parameter)"
|
||||
case LD_HLSP => " LD HL,SP+" + parameter
|
||||
case ADD_SP => " ADD SP," + parameter
|
||||
case EX_SP => registers match {
|
||||
@ -606,6 +610,12 @@ case class ZLine(opcode: ZOpcode.Value, registers: ZRegisters, parameter: Consta
|
||||
case DJNZ => r == B
|
||||
case DAA | NEG | CPL | RLA | RRA | RLCA | RRCA => r == A
|
||||
case LABEL | DI | EI | NOP | HALT => false
|
||||
case LDH_AC => r == C
|
||||
case LDH_CA => r == C || r == A
|
||||
case LDH_DA => r == A
|
||||
case LDH_AD => false
|
||||
case LD_HLIA | LD_HLDA => r == H || r == L | r == A
|
||||
case LD_AHLI | LD_AHLD => r == H || r == L
|
||||
case _ => true // TODO
|
||||
}
|
||||
}
|
||||
@ -742,6 +752,10 @@ case class ZLine(opcode: ZOpcode.Value, registers: ZRegisters, parameter: Consta
|
||||
case DJNZ => r == B
|
||||
case LABEL | DI | EI | NOP | HALT => false
|
||||
case CALL => r != IXH && r != IXL && r != SP
|
||||
case LDH_CA | LDH_DA => false
|
||||
case LDH_AC | LDH_AD => r == A
|
||||
case LD_HLIA | LD_HLDA => r == H || r == L
|
||||
case LD_AHLI | LD_AHLD => r == H || r == L | r == A
|
||||
case _ => true // TODO
|
||||
}
|
||||
}
|
||||
@ -770,6 +784,8 @@ case class ZLine(opcode: ZOpcode.Value, registers: ZRegisters, parameter: Consta
|
||||
DISCARD_A | DISCARD_BC | DISCARD_DE | DISCARD_IX | DISCARD_IY | DISCARD_HL | DISCARD_F => false
|
||||
case EX_DE_HL | NEG => false
|
||||
case LABEL | DI | EI | NOP => false
|
||||
case LDH_AC | LDH_AD | LD_AHLI | LD_AHLD => false
|
||||
case LDH_CA | LDH_DA | LD_HLIA | LD_HLDA => true
|
||||
case _ => true // TODO
|
||||
}
|
||||
}
|
||||
@ -792,6 +808,8 @@ case class ZLine(opcode: ZOpcode.Value, registers: ZRegisters, parameter: Consta
|
||||
DISCARD_A | DISCARD_BC | DISCARD_DE | DISCARD_IX | DISCARD_IY | DISCARD_HL | DISCARD_F => false
|
||||
case EX_DE_HL | NEG => false
|
||||
case LABEL | DI | EI | NOP | HALT => false
|
||||
case LDH_AC | LDH_AD | LD_AHLI | LD_AHLD => true
|
||||
case LDH_CA | LDH_DA | LD_HLIA | LD_HLDA => false
|
||||
case _ => true // TODO
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ object ZOpcode extends Enumeration {
|
||||
RST, IM, EI, DI,
|
||||
DJNZ, JP, JR, CALL, RET, RETN, RETI, HALT,
|
||||
//sharp:
|
||||
LD_AHLI, LD_AHLD, LD_HLIA, LD_HLDA, SWAP, LD_H, LD_HLSP, ADD_SP, STOP,
|
||||
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,
|
||||
LABEL, BYTE = Value
|
||||
}
|
||||
@ -57,6 +57,7 @@ object ZOpcodeClasses {
|
||||
val ChangesAFAlways = Set( // TODO: !
|
||||
DAA, ADD, ADC, SUB, SBC, XOR, OR, AND, INC, DEC,
|
||||
SCF, CCF, NEG,
|
||||
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,
|
||||
LDI, LDIR, LDD, LDDR, CPI, CPIR, CPD, CPDR,
|
||||
@ -68,6 +69,7 @@ object ZOpcodeClasses {
|
||||
val ChangesHLAlways = 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,
|
||||
EXX, EX_DE_HL, CALL, JR, JP, LABEL)
|
||||
val ChangesDEAlways = Set(
|
||||
LDI, LDIR, LDD, LDDR,
|
||||
|
@ -596,6 +596,24 @@ class Z80Assembler(program: Program,
|
||||
requireSharp()
|
||||
writeByte(bank, index, 0x32)
|
||||
index + 1
|
||||
case ZLine(LDH_AD, _, param, _) =>
|
||||
requireSharp()
|
||||
writeByte(bank, index, 0xf0)
|
||||
writeByte(bank, index + 1, param.loByte)
|
||||
index + 2
|
||||
case ZLine(LDH_DA, _, param, _) =>
|
||||
requireSharp()
|
||||
writeByte(bank, index, 0xe0)
|
||||
writeByte(bank, index + 1, param.loByte)
|
||||
index + 2
|
||||
case ZLine(LDH_AC, _, _, _) =>
|
||||
requireSharp()
|
||||
writeByte(bank, index, 0xf2)
|
||||
index + 1
|
||||
case ZLine(LDH_CA, _, _, _) =>
|
||||
requireSharp()
|
||||
writeByte(bank, index, 0xe2)
|
||||
index + 1
|
||||
case ZLine(STOP, _, _, _) =>
|
||||
requireSharp()
|
||||
writeByte(bank, index, 0x10)
|
||||
|
@ -88,10 +88,15 @@ case class Z80Parser(filename: String,
|
||||
"SP" -> ZRegister.SP, "sp" -> ZRegister.SP,
|
||||
)
|
||||
|
||||
private def param(allowAbsolute: Boolean, allowRI: Boolean = false): P[(ZRegister.Value, Option[Expression])] = asmExpressionWithParens.map {
|
||||
private def param(allowAbsolute: Boolean, allowRI: Boolean = false, allowFfc: Boolean = false): P[(ZRegister.Value, Option[Expression])] = asmExpressionWithParens.map {
|
||||
case (VariableExpression("R" | "r"), false) if allowRI => (ZRegister.R, None)
|
||||
case (VariableExpression("I" | "i"), false) if allowRI => (ZRegister.I, None)
|
||||
case (VariableExpression(r), false) if toRegister.contains(r)=> (toRegister(r), None)
|
||||
case (SumExpression(List(
|
||||
(false, LiteralExpression(0xff00, _)),
|
||||
(false, VariableExpression("C" | "c"))
|
||||
), false), true) if allowFfc => (ZRegister.MEM_BC, None) // MEM_BC is a placeholder here for ($FF00 + C)
|
||||
case (VariableExpression("C" | "c"), true) if allowFfc => (ZRegister.MEM_BC, None) // MEM_BC is a placeholder here for ($FF00 + C)
|
||||
case (VariableExpression("HL" | "hl"), true) => (ZRegister.MEM_HL, None)
|
||||
case (VariableExpression("BC" | "bc"), true) => (ZRegister.MEM_BC, None)
|
||||
case (VariableExpression("DE" | "de"), true) => (ZRegister.MEM_DE, None)
|
||||
@ -361,6 +366,15 @@ case class Z80Parser(filename: String,
|
||||
}
|
||||
}
|
||||
|
||||
case "LDH" => (param(allowAbsolute = true, allowFfc = true) ~ HWS ~ position("comma").map(_ => ()) ~ "," ~/ HWS ~ param(allowAbsolute = true, allowFfc = true)).map {
|
||||
case (ZRegister.MEM_ABS_8, Some(expr), (ZRegister.A, None)) => (LDH_DA, NoRegisters, None, expr)
|
||||
case (ZRegister.A, None, (ZRegister.MEM_ABS_8, Some(expr))) => (LDH_AD, NoRegisters, None, expr)
|
||||
case (ZRegister.A, None, (ZRegister.MEM_BC, None)) => (LDH_AC, NoRegisters, None, zero)
|
||||
case (ZRegister.MEM_BC, None, (ZRegister.A, None)) => (LDH_CA, NoRegisters, None, zero)
|
||||
case _ =>
|
||||
log.error("Invalid parameters for LDH", Some(pos))
|
||||
(NOP, NoRegisters, None, zero)
|
||||
}
|
||||
case "LD" => (param(allowAbsolute = true, allowRI = true) ~ HWS ~ position("comma").map(_ => ()) ~ "," ~/ HWS ~ param(allowAbsolute = true, allowRI = true)).map {
|
||||
case (ZRegister.HL, None, (ZRegister.IMM_8 | ZRegister.IMM_16, Some(SumExpression((false, VariableExpression("sp" | "SP")) :: offset, false))))
|
||||
if options.flags(CompilationFlag.EmitSharpOpcodes) =>
|
||||
|
@ -879,6 +879,10 @@ class Z80AssemblySuite extends FunSuite with Matchers {
|
||||
| swap c
|
||||
| swap(hl)
|
||||
|
|
||||
| ldh a,(9)
|
||||
| ldh (9),a
|
||||
| ldh a,(c)
|
||||
| ldh (c),a
|
||||
| ret
|
||||
| }
|
||||
""".stripMargin)
|
||||
|
Loading…
Reference in New Issue
Block a user