mirror of
https://github.com/KarolS/millfork.git
synced 2025-08-15 19:27:22 +00:00
Z80: RLA and RL A are two very different instructions
This commit is contained in:
@@ -12,6 +12,8 @@ import millfork.node.ZRegister
|
|||||||
|
|
||||||
object ZFlag extends Enumeration {
|
object ZFlag extends Enumeration {
|
||||||
val Z, P, C, S, H, N = Value
|
val Z, P, C, S, H, N = Value
|
||||||
|
|
||||||
|
val AllButSZ: Seq[Value] = Seq(P, C, H, N)
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed trait ZRegisters
|
sealed trait ZRegisters
|
||||||
@@ -179,7 +181,6 @@ case class ZLine(opcode: ZOpcode.Value, registers: ZRegisters, parameter: Consta
|
|||||||
case JR => 2
|
case JR => 2
|
||||||
case o if ZOpcodeClasses.EdInstructions(o) => 2
|
case o if ZOpcodeClasses.EdInstructions(o) => 2
|
||||||
case o if ZOpcodeClasses.CbInstructions(o) => 2
|
case o if ZOpcodeClasses.CbInstructions(o) => 2
|
||||||
case o if ZOpcodeClasses.CbInstructionsUnlessA(o) => if (registers == OneRegister(ZRegister.A)) 1 else 2
|
|
||||||
case _ => 1 // TODO!!!
|
case _ => 1 // TODO!!!
|
||||||
}
|
}
|
||||||
val fromParams = registers match {
|
val fromParams = registers match {
|
||||||
@@ -244,6 +245,7 @@ case class ZLine(opcode: ZOpcode.Value, registers: ZRegisters, parameter: Consta
|
|||||||
case RST => s" RST $parameter"
|
case RST => s" RST $parameter"
|
||||||
case IM => s" IM $parameter"
|
case IM => s" IM $parameter"
|
||||||
case EX_AF_AF => " EX AF,AF'"
|
case EX_AF_AF => " EX AF,AF'"
|
||||||
|
case EX_DE_HL => " EX DE,HL"
|
||||||
case LD_AHLI => " LD A,(HLI)"
|
case LD_AHLI => " LD A,(HLI)"
|
||||||
case LD_AHLD => " LD A,(HLD)"
|
case LD_AHLD => " LD A,(HLD)"
|
||||||
case LD_HLIA => " LD (HLI),A"
|
case LD_HLIA => " LD (HLI),A"
|
||||||
@@ -373,7 +375,7 @@ case class ZLine(opcode: ZOpcode.Value, registers: ZRegisters, parameter: Consta
|
|||||||
case OneRegisterOffset(s, _) => r == s
|
case OneRegisterOffset(s, _) => r == s
|
||||||
case _ => r == A
|
case _ => r == A
|
||||||
}
|
}
|
||||||
case INC | DEC | RL | RLC | RR | RRC | SLA | SLL | SRA | SRL => registers match {
|
case INC | DEC | RL | RLC | RR | RRC | SLA | SLL | SRA | SRL | SWAP => registers match {
|
||||||
case OneRegister(MEM_HL) => r == H || r == L
|
case OneRegister(MEM_HL) => r == H || r == L
|
||||||
case OneRegister(MEM_BC) => r == B || r == C
|
case OneRegister(MEM_BC) => r == B || r == C
|
||||||
case OneRegister(MEM_DE) => r == D || r == E
|
case OneRegister(MEM_DE) => r == D || r == E
|
||||||
@@ -401,11 +403,12 @@ case class ZLine(opcode: ZOpcode.Value, registers: ZRegisters, parameter: Consta
|
|||||||
case OneRegisterOffset(s, _) => r == s
|
case OneRegisterOffset(s, _) => r == s
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
|
case EX_DE_HL => r == D || r == E || r == H || r == L
|
||||||
case JP | JR | RET | RETI | RETN |
|
case JP | JR | RET | RETI | RETN |
|
||||||
POP |
|
POP |
|
||||||
DISCARD_A | DISCARD_BC | DISCARD_DE | DISCARD_IX | DISCARD_IY | DISCARD_HL | DISCARD_F => false
|
DISCARD_A | DISCARD_BC | DISCARD_DE | DISCARD_IX | DISCARD_IY | DISCARD_HL | DISCARD_F => false
|
||||||
case DJNZ => r == B
|
case DJNZ => r == B
|
||||||
case DAA | NEG | CPL => r == A
|
case DAA | NEG | CPL | RLA | RRA | RLCA | RRCA => r == A
|
||||||
case LABEL | DI | EI | NOP | HALT => false
|
case LABEL | DI | EI | NOP | HALT => false
|
||||||
case _ => true // TODO
|
case _ => true // TODO
|
||||||
}
|
}
|
||||||
@@ -511,7 +514,7 @@ case class ZLine(opcode: ZOpcode.Value, registers: ZRegisters, parameter: Consta
|
|||||||
case TwoRegistersOffset(s, _, _) => r == s
|
case TwoRegistersOffset(s, _, _) => r == s
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
case INC | DEC | RL | RLC | RR | RRC | SLA | SLL | SRA | SRL => registers match {
|
case INC | DEC | RL | RLC | RR | RRC | SLA | SLL | SRA | SRL | SWAP => registers match {
|
||||||
case OneRegister(s) => r == s
|
case OneRegister(s) => r == s
|
||||||
case OneRegisterOffset(s, _) => r == s
|
case OneRegisterOffset(s, _) => r == s
|
||||||
case _ => false
|
case _ => false
|
||||||
@@ -534,10 +537,11 @@ case class ZLine(opcode: ZOpcode.Value, registers: ZRegisters, parameter: Consta
|
|||||||
case OneRegisterOffset(s, _) => r == s
|
case OneRegisterOffset(s, _) => r == s
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
|
case EX_DE_HL => r == D || r == E || r == H || r == L
|
||||||
case JP | JR | RET | RETI | RETN |
|
case JP | JR | RET | RETI | RETN |
|
||||||
PUSH |
|
PUSH |
|
||||||
DISCARD_A | DISCARD_BC | DISCARD_DE | DISCARD_IX | DISCARD_IY | DISCARD_HL | DISCARD_F => false
|
DISCARD_A | DISCARD_BC | DISCARD_DE | DISCARD_IX | DISCARD_IY | DISCARD_HL | DISCARD_F => false
|
||||||
case ADD | ADC | AND | OR | XOR | SUB | SBC | DAA | NEG | CPL => r == A
|
case ADD | ADC | AND | OR | XOR | SUB | SBC | DAA | NEG | CPL | RLA | RRA | RLCA | RRCA => r == A
|
||||||
case CP => false
|
case CP => false
|
||||||
case DJNZ => r == B
|
case DJNZ => r == B
|
||||||
case LABEL | DI | EI | NOP | HALT => false
|
case LABEL | DI | EI | NOP | HALT => false
|
||||||
@@ -568,6 +572,7 @@ case class ZLine(opcode: ZOpcode.Value, registers: ZRegisters, parameter: Consta
|
|||||||
case JP | JR | RET | RETI | RETN |
|
case JP | JR | RET | RETI | RETN |
|
||||||
PUSH | DJNZ | DAA |
|
PUSH | DJNZ | DAA |
|
||||||
DISCARD_A | DISCARD_BC | DISCARD_DE | DISCARD_IX | DISCARD_IY | DISCARD_HL | DISCARD_F => false
|
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 LABEL | DI | EI | NOP => false
|
||||||
case _ => true // TODO
|
case _ => true // TODO
|
||||||
}
|
}
|
||||||
@@ -589,6 +594,7 @@ case class ZLine(opcode: ZOpcode.Value, registers: ZRegisters, parameter: Consta
|
|||||||
case JP | JR | RET | RETI | RETN |
|
case JP | JR | RET | RETI | RETN |
|
||||||
PUSH | DJNZ | DAA |
|
PUSH | DJNZ | DAA |
|
||||||
DISCARD_A | DISCARD_BC | DISCARD_DE | DISCARD_IX | DISCARD_IY | DISCARD_HL | DISCARD_F => false
|
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 LABEL | DI | EI | NOP | HALT => false
|
||||||
case _ => true // TODO
|
case _ => true // TODO
|
||||||
}
|
}
|
||||||
|
@@ -19,6 +19,7 @@ object ZOpcode extends Enumeration {
|
|||||||
POP, PUSH,
|
POP, PUSH,
|
||||||
NOP,
|
NOP,
|
||||||
RLC, RRC, RL, RR, SLA, SRA, SRL, SLL, RLD, RRD,
|
RLC, RRC, RL, RR, SLA, SRA, SRL, SLL, RLD, RRD,
|
||||||
|
RLCA, RLA, RRA, RRCA,
|
||||||
EXX, EX_DE_HL, EX_AF_AF, EX_SP,
|
EXX, EX_DE_HL, EX_AF_AF, EX_SP,
|
||||||
RST, IM, EI, DI,
|
RST, IM, EI, DI,
|
||||||
DJNZ, JP, JR, CALL, RET, RETN, RETI, HALT,
|
DJNZ, JP, JR, CALL, RET, RETN, RETI, HALT,
|
||||||
@@ -46,8 +47,7 @@ object ZOpcodeClasses {
|
|||||||
val AllSingleBit: Set[ZOpcode.Value] = RES ++ SET ++ BIT
|
val AllSingleBit: Set[ZOpcode.Value] = RES ++ SET ++ BIT
|
||||||
val RES_or_SET: Set[ZOpcode.Value] = RES ++ SET
|
val RES_or_SET: Set[ZOpcode.Value] = RES ++ SET
|
||||||
|
|
||||||
val CbInstructions: Set[ZOpcode.Value] = Set(SLA, SRA, SRL, SLL) ++ BIT ++ RES ++ SET
|
val CbInstructions: Set[ZOpcode.Value] = Set(SLA, SRA, SRL, SLL, RLC, RRC, RL, RR) ++ BIT ++ RES ++ SET
|
||||||
val CbInstructionsUnlessA = Set(RLC, RRC, RL, RR)
|
|
||||||
val EdInstructions: Set[ZOpcode.Value] = Set(NEG, RETN, RETI, IM, RRD, RLD,
|
val EdInstructions: Set[ZOpcode.Value] = Set(NEG, RETN, RETI, IM, RRD, RLD,
|
||||||
INI, INIR, OUTI, OUTIR, IND, INDR, OUTD, OUTDR,
|
INI, INIR, OUTI, OUTIR, IND, INDR, OUTD, OUTDR,
|
||||||
LDI, LDIR, LDD, LDDR, CPI, CPIR, CPD, CPDR) ++ BIT ++ RES ++ SET
|
LDI, LDIR, LDD, LDDR, CPI, CPIR, CPD, CPDR) ++ BIT ++ RES ++ SET
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
package millfork.assembly.z80.opt
|
package millfork.assembly.z80.opt
|
||||||
|
|
||||||
import millfork.assembly.opt.{AnyStatus, SingleStatus}
|
import millfork.assembly.opt.{AnyStatus, SingleStatus, Status}
|
||||||
import millfork.assembly.z80._
|
import millfork.assembly.z80._
|
||||||
import millfork.env.{Label, MemoryAddressConstant, NormalFunction, NumericConstant}
|
import millfork.env.{Label, MemoryAddressConstant, NormalFunction, NumericConstant}
|
||||||
import millfork.node.ZRegister
|
import millfork.node.ZRegister
|
||||||
import millfork.CompilationOptions
|
import millfork.{CompilationOptions, Cpu}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Karol Stasiak
|
* @author Karol Stasiak
|
||||||
@@ -102,6 +102,8 @@ object CoarseFlowAnalyzer {
|
|||||||
currentStatus = currentStatus.setRegister(t, currentStatus.getRegister(s))
|
currentStatus = currentStatus.setRegister(t, currentStatus.getRegister(s))
|
||||||
case ZLine(LD | LD_16, TwoRegistersOffset(t, s, o), _, _) =>
|
case ZLine(LD | LD_16, TwoRegistersOffset(t, s, o), _, _) =>
|
||||||
currentStatus = currentStatus.setRegister(t, currentStatus.getRegister(s, o), o)
|
currentStatus = currentStatus.setRegister(t, currentStatus.getRegister(s, o), o)
|
||||||
|
case ZLine(EX_DE_HL, _, _, _) =>
|
||||||
|
currentStatus = currentStatus.copy(d = currentStatus.h, e = currentStatus.l, h = currentStatus.d, l = currentStatus.e)
|
||||||
case ZLine(ADD_16, TwoRegisters(t, s), _, _) =>
|
case ZLine(ADD_16, TwoRegisters(t, s), _, _) =>
|
||||||
currentStatus = currentStatus.copy(cf = AnyStatus, zf = AnyStatus, sf = AnyStatus, pf = AnyStatus, hf = AnyStatus)
|
currentStatus = currentStatus.copy(cf = AnyStatus, zf = AnyStatus, sf = AnyStatus, pf = AnyStatus, hf = AnyStatus)
|
||||||
.setRegister(t, (currentStatus.getRegister(t) <*> currentStatus.getRegister(s)) ((m, n) => (m + n) & 0xffff))
|
.setRegister(t, (currentStatus.getRegister(t) <*> currentStatus.getRegister(s)) ((m, n) => (m + n) & 0xffff))
|
||||||
@@ -113,6 +115,13 @@ object CoarseFlowAnalyzer {
|
|||||||
currentStatus = currentStatus.copy(cf = AnyStatus, zf = AnyStatus, sf = AnyStatus, pf = AnyStatus, hf = AnyStatus)
|
currentStatus = currentStatus.copy(cf = AnyStatus, zf = AnyStatus, sf = AnyStatus, pf = AnyStatus, hf = AnyStatus)
|
||||||
.setRegister(r, currentStatus.getRegister(r).map(_.>>(1).&(0x7f)))
|
.setRegister(r, currentStatus.getRegister(r).map(_.>>(1).&(0x7f)))
|
||||||
|
|
||||||
|
|
||||||
|
case ZLine(RLA | RRA | RLCA | RRCA, _, _, _) =>
|
||||||
|
currentStatus = currentStatus.copy(
|
||||||
|
a = AnyStatus, cf = AnyStatus,
|
||||||
|
zf = AnyStatus,
|
||||||
|
pf = AnyStatus, hf = Status.SingleFalse)
|
||||||
|
|
||||||
case ZLine(opcode, registers, _, _) =>
|
case ZLine(opcode, registers, _, _) =>
|
||||||
currentStatus = currentStatus.copy(cf = AnyStatus, zf = AnyStatus, sf = AnyStatus, pf = AnyStatus, hf = AnyStatus)
|
currentStatus = currentStatus.copy(cf = AnyStatus, zf = AnyStatus, sf = AnyStatus, pf = AnyStatus, hf = AnyStatus)
|
||||||
if (ZOpcodeClasses.ChangesAAlways(opcode)) currentStatus = currentStatus.copy(a = AnyStatus)
|
if (ZOpcodeClasses.ChangesAAlways(opcode)) currentStatus = currentStatus.copy(a = AnyStatus)
|
||||||
|
@@ -227,6 +227,8 @@ object ReverseFlowAnalyzer {
|
|||||||
currentImportance = currentImportance.butWritesRegister(t, o).butReadsRegister(s, o)
|
currentImportance = currentImportance.butWritesRegister(t, o).butReadsRegister(s, o)
|
||||||
case ZLine(LD | LD_16, TwoRegisters(t, s), _, _) =>
|
case ZLine(LD | LD_16, TwoRegisters(t, s), _, _) =>
|
||||||
currentImportance = currentImportance.butWritesRegister(t).butReadsRegister(s)
|
currentImportance = currentImportance.butWritesRegister(t).butReadsRegister(s)
|
||||||
|
case ZLine(EX_DE_HL, TwoRegisters(t, s), _, _) =>
|
||||||
|
currentImportance = currentImportance.copy(d = currentImportance.h, e = currentImportance.l, h = currentImportance.d, l = currentImportance.e)
|
||||||
case ZLine(ADD_16, TwoRegisters(t, s), _, _) =>
|
case ZLine(ADD_16, TwoRegisters(t, s), _, _) =>
|
||||||
currentImportance = currentImportance.butReadsRegister(t).butReadsRegister(s)
|
currentImportance = currentImportance.butReadsRegister(t).butReadsRegister(s)
|
||||||
case ZLine(ADC_16 | SBC_16, TwoRegisters(t, s), _, _) =>
|
case ZLine(ADC_16 | SBC_16, TwoRegisters(t, s), _, _) =>
|
||||||
@@ -243,7 +245,7 @@ object ReverseFlowAnalyzer {
|
|||||||
)
|
)
|
||||||
case ZLine(OR | AND, OneRegister(ZRegister.A), _, _) =>
|
case ZLine(OR | AND, OneRegister(ZRegister.A), _, _) =>
|
||||||
currentImportance = currentImportance.copy(
|
currentImportance = currentImportance.copy(
|
||||||
a = currentImportance.zf ~ currentImportance.sf ~ currentImportance.pf,
|
a = currentImportance.zf ~ currentImportance.sf ~ currentImportance.pf ~ currentImportance.a,
|
||||||
cf = Unimportant,
|
cf = Unimportant,
|
||||||
zf = Unimportant,
|
zf = Unimportant,
|
||||||
sf = Unimportant,
|
sf = Unimportant,
|
||||||
@@ -429,9 +431,13 @@ object ReverseFlowAnalyzer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case ZLine(SLA | SRL, OneRegister(r), _, _) =>
|
case ZLine(SLA | SRL, OneRegister(r), _, _) =>
|
||||||
currentImportance = currentImportance.butReadsRegister(r).butWritesFlag(ZFlag.C).butWritesFlag(ZFlag.Z)
|
currentImportance = currentImportance.butReadsRegister(r).copy(cf = Unimportant, zf = Unimportant, hf = Unimportant, nf = Unimportant, pf = Unimportant)
|
||||||
case ZLine(RL | RR | RLC | RRC, OneRegister(r), _, _) =>
|
case ZLine(RL | RR | RLC | RRC, OneRegister(r), _, _) =>
|
||||||
currentImportance = currentImportance.butReadsRegister(r).butReadsFlag(ZFlag.C).butWritesFlag(ZFlag.Z)
|
currentImportance = currentImportance.butReadsRegister(r).copy(cf = Important, zf = Unimportant, hf = Unimportant, nf = Unimportant, pf = Unimportant)
|
||||||
|
case ZLine(SWAP, OneRegister(r), _, _) =>
|
||||||
|
currentImportance = currentImportance.butReadsRegister(r).copy(cf = Unimportant, zf = Unimportant, hf = Unimportant, nf = Unimportant, pf = Unimportant)
|
||||||
|
case ZLine(RLA | RRA | RLCA | RRCA, _, _, _) =>
|
||||||
|
currentImportance = currentImportance.butReadsRegister(ZRegister.A).copy(cf = Important, hf = Unimportant, nf = Unimportant)
|
||||||
case _ =>
|
case _ =>
|
||||||
currentImportance = finalImportance // TODO
|
currentImportance = finalImportance // TODO
|
||||||
}
|
}
|
||||||
|
@@ -278,7 +278,7 @@ object Z80BulkMemoryOperations {
|
|||||||
// TODO: tricks with AND?
|
// TODO: tricks with AND?
|
||||||
for (_ <- 0 until n.toInt) {
|
for (_ <- 0 until n.toInt) {
|
||||||
builder += ZLine.register(OR, ZRegister.A)
|
builder += ZLine.register(OR, ZRegister.A)
|
||||||
builder += ZLine.register(RR, ZRegister.A)
|
builder += ZLine.implied(RRA)
|
||||||
}
|
}
|
||||||
builder += ZLine.ld8(element, ZRegister.A)
|
builder += ZLine.ld8(element, ZRegister.A)
|
||||||
Some(builder.toList)
|
Some(builder.toList)
|
||||||
|
@@ -89,7 +89,7 @@ object Z80DecimalBuiltIns {
|
|||||||
case 1 => Nil
|
case 1 => Nil
|
||||||
case x =>
|
case x =>
|
||||||
val add1 = List(ZLine.register(ADD, D), ZLine.implied(DAA), ZLine.ld8(E, A))
|
val add1 = List(ZLine.register(ADD, D), ZLine.implied(DAA), ZLine.ld8(E, A))
|
||||||
val times10 = List(ZLine.register(RL, A), ZLine.register(RL, A), ZLine.register(RL, A), ZLine.register(RL, A), ZLine.imm8(AND, 0xf0))
|
val times10 = List(ZLine.implied(RLA), ZLine.implied(RLA), ZLine.implied(RLA), ZLine.implied(RLA), ZLine.imm8(AND, 0xf0))
|
||||||
// TODO: rethink this:
|
// TODO: rethink this:
|
||||||
val ways = if (ctx.options.flag(CompilationFlag.OptimizeForSpeed)) waysOptimizedForCycles else waysOptimizedForBytes
|
val ways = if (ctx.options.flag(CompilationFlag.OptimizeForSpeed)) waysOptimizedForCycles else waysOptimizedForBytes
|
||||||
ZLine.ld8(D, A) :: ZLine.ld8(E, A) :: ways(x).flatMap {
|
ZLine.ld8(D, A) :: ZLine.ld8(E, A) :: ways(x).flatMap {
|
||||||
|
@@ -497,7 +497,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
|||||||
List(
|
List(
|
||||||
ZLine.ld8(ZRegister.L, ZRegister.A),
|
ZLine.ld8(ZRegister.L, ZRegister.A),
|
||||||
ZLine.ldImm8(ZRegister.A, 0),
|
ZLine.ldImm8(ZRegister.A, 0),
|
||||||
ZLine.register(RL, ZRegister.A),
|
ZLine.implied(RLA),
|
||||||
ZLine.ld8(ZRegister.H, ZRegister.A))
|
ZLine.ld8(ZRegister.H, ZRegister.A))
|
||||||
}
|
}
|
||||||
case ZExpressionTarget.BC =>
|
case ZExpressionTarget.BC =>
|
||||||
@@ -510,7 +510,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
|||||||
List(
|
List(
|
||||||
ZLine.ld8(ZRegister.C, ZRegister.A),
|
ZLine.ld8(ZRegister.C, ZRegister.A),
|
||||||
ZLine.ldImm8(ZRegister.A, 0),
|
ZLine.ldImm8(ZRegister.A, 0),
|
||||||
ZLine.register(RL, ZRegister.A),
|
ZLine.implied(RLA),
|
||||||
ZLine.ld8(ZRegister.B, ZRegister.A))
|
ZLine.ld8(ZRegister.B, ZRegister.A))
|
||||||
}
|
}
|
||||||
case ZExpressionTarget.DE =>
|
case ZExpressionTarget.DE =>
|
||||||
@@ -523,7 +523,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
|||||||
List(
|
List(
|
||||||
ZLine.ld8(ZRegister.E, ZRegister.A),
|
ZLine.ld8(ZRegister.E, ZRegister.A),
|
||||||
ZLine.ldImm8(ZRegister.A, 0),
|
ZLine.ldImm8(ZRegister.A, 0),
|
||||||
ZLine.register(RL, ZRegister.A),
|
ZLine.implied(RLA),
|
||||||
ZLine.ld8(ZRegister.D, ZRegister.A))
|
ZLine.ld8(ZRegister.D, ZRegister.A))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@@ -54,9 +54,10 @@ object Z80Multiply {
|
|||||||
label(lblStart),
|
label(lblStart),
|
||||||
register(OR, A),
|
register(OR, A),
|
||||||
ld8(A, D),
|
ld8(A, D),
|
||||||
register(RR, A),
|
implied(RRA),
|
||||||
ld8(D, A),
|
ld8(D, A),
|
||||||
jumpR(ctx, lblAdd, IfFlagSet(ZFlag.C)),
|
jumpR(ctx, lblAdd, IfFlagSet(ZFlag.C)),
|
||||||
|
register(OR, A),
|
||||||
jumpR(ctx, lblLoop, IfFlagClear(ZFlag.Z)),
|
jumpR(ctx, lblLoop, IfFlagClear(ZFlag.Z)),
|
||||||
ld8(A, C))
|
ld8(A, C))
|
||||||
}
|
}
|
||||||
|
@@ -26,9 +26,9 @@ object Z80Shifting {
|
|||||||
val extendedOps = ctx.options.flag(CompilationFlag.EmitExtended80Opcodes)
|
val extendedOps = ctx.options.flag(CompilationFlag.EmitExtended80Opcodes)
|
||||||
val op =
|
val op =
|
||||||
if (extendedOps) {
|
if (extendedOps) {
|
||||||
if (left) ZOpcode.ADD else ZOpcode.SRL
|
if (left) ZLine.register(ZOpcode.ADD, ZRegister.A) else ZLine.register(ZOpcode.SRL, ZRegister.A)
|
||||||
} else {
|
} else {
|
||||||
if (left) ZOpcode.ADD else ZOpcode.RRC
|
if (left) ZLine.register(ZOpcode.ADD, ZRegister.A) else ZLine.implied(ZOpcode.RRCA)
|
||||||
}
|
}
|
||||||
val l = Z80ExpressionCompiler.compileToA(ctx, lhs)
|
val l = Z80ExpressionCompiler.compileToA(ctx, lhs)
|
||||||
env.eval(rhs) match {
|
env.eval(rhs) match {
|
||||||
@@ -38,12 +38,12 @@ object Z80Shifting {
|
|||||||
} else if (i >= 8) {
|
} else if (i >= 8) {
|
||||||
l :+ ZLine.ldImm8(ZRegister.A, 0)
|
l :+ ZLine.ldImm8(ZRegister.A, 0)
|
||||||
} else {
|
} else {
|
||||||
l ++ List.tabulate(i.toInt)(_ => ZLine.register(op, ZRegister.A)) ++ fixAfterShiftIfNeeded(extendedOps, left, i)
|
l ++ List.tabulate(i.toInt)(_ => op) ++ fixAfterShiftIfNeeded(extendedOps, left, i)
|
||||||
}
|
}
|
||||||
case _ =>
|
case _ =>
|
||||||
val calcCount = Z80ExpressionCompiler.compileToA(ctx, rhs) :+ ZLine.ld8(ZRegister.B, ZRegister.A)
|
val calcCount = Z80ExpressionCompiler.compileToA(ctx, rhs) :+ ZLine.ld8(ZRegister.B, ZRegister.A)
|
||||||
val l = Z80ExpressionCompiler.stashBCIfChanged(ctx, Z80ExpressionCompiler.compileToA(ctx, lhs))
|
val l = Z80ExpressionCompiler.stashBCIfChanged(ctx, Z80ExpressionCompiler.compileToA(ctx, lhs))
|
||||||
val loopBody = ZLine.register(op, ZRegister.A) :: fixAfterShiftIfNeeded(extendedOps, left, 1)
|
val loopBody = op :: fixAfterShiftIfNeeded(extendedOps, left, 1)
|
||||||
val label = Z80Compiler.nextLabel("sh")
|
val label = Z80Compiler.nextLabel("sh")
|
||||||
calcCount ++ l ++ List(ZLine.label(label)) ++ loopBody ++ ZLine.djnz(ctx, label)
|
calcCount ++ l ++ List(ZLine.label(label)) ++ loopBody ++ ZLine.djnz(ctx, label)
|
||||||
}
|
}
|
||||||
@@ -52,11 +52,11 @@ object Z80Shifting {
|
|||||||
def compile8BitShiftInPlace(ctx: CompilationContext, lhs: LhsExpression, rhs: Expression, left: Boolean): List[ZLine] = {
|
def compile8BitShiftInPlace(ctx: CompilationContext, lhs: LhsExpression, rhs: Expression, left: Boolean): List[ZLine] = {
|
||||||
val env = ctx.env
|
val env = ctx.env
|
||||||
val extendedOps = ctx.options.flag(CompilationFlag.EmitExtended80Opcodes)
|
val extendedOps = ctx.options.flag(CompilationFlag.EmitExtended80Opcodes)
|
||||||
val op =
|
val (op, opLine) =
|
||||||
if (extendedOps) {
|
if (extendedOps) {
|
||||||
if (left) ZOpcode.ADD else ZOpcode.SRL
|
if (left) ZOpcode.ADD -> ZLine.register(ZOpcode.ADD, ZRegister.A) else ZOpcode.SRL -> ZLine.register(ZOpcode.SRL, ZRegister.A)
|
||||||
} else {
|
} else {
|
||||||
if (left) ZOpcode.ADD else ZOpcode.RRC
|
if (left) ZOpcode.ADD -> ZLine.register(ZOpcode.ADD, ZRegister.A) else ZOpcode.LABEL -> ZLine.implied(ZOpcode.RRCA)
|
||||||
}
|
}
|
||||||
env.eval(rhs) match {
|
env.eval(rhs) match {
|
||||||
case Some(NumericConstant(i, _)) =>
|
case Some(NumericConstant(i, _)) =>
|
||||||
@@ -110,7 +110,7 @@ object Z80Shifting {
|
|||||||
l ++ List.tabulate(i.toInt)(_ => ZLine.register(ZOpcode.SLA, register))
|
l ++ List.tabulate(i.toInt)(_ => ZLine.register(ZOpcode.SLA, register))
|
||||||
} else {
|
} else {
|
||||||
l ++ List(ZLine.ld8(ZRegister.A, register)) ++
|
l ++ List(ZLine.ld8(ZRegister.A, register)) ++
|
||||||
List.tabulate(i.toInt)(_ => ZLine.register(op, ZRegister.A)) ++
|
List.tabulate(i.toInt)(_ => opLine) ++
|
||||||
fixAfterShiftIfNeeded(extendedOps, left, i) ++
|
fixAfterShiftIfNeeded(extendedOps, left, i) ++
|
||||||
List(ZLine.ld8(register, ZRegister.A))
|
List(ZLine.ld8(register, ZRegister.A))
|
||||||
}
|
}
|
||||||
@@ -150,18 +150,18 @@ object Z80Shifting {
|
|||||||
l ++ (1L until i).flatMap(_ => List(
|
l ++ (1L until i).flatMap(_ => List(
|
||||||
ZLine.ld8(ZRegister.A, ZRegister.H),
|
ZLine.ld8(ZRegister.A, ZRegister.H),
|
||||||
ZLine.register(ZOpcode.OR, ZRegister.A),
|
ZLine.register(ZOpcode.OR, ZRegister.A),
|
||||||
ZLine.register(ZOpcode.RR, ZRegister.A),
|
ZLine.implied(ZOpcode.RRA),
|
||||||
ZLine.ld8(ZRegister.H, ZRegister.A),
|
ZLine.ld8(ZRegister.H, ZRegister.A),
|
||||||
ZLine.ld8(ZRegister.A, ZRegister.L),
|
ZLine.ld8(ZRegister.A, ZRegister.L),
|
||||||
ZLine.register(ZOpcode.RR, ZRegister.A),
|
ZLine.implied(ZOpcode.RRA),
|
||||||
ZLine.ld8(ZRegister.L, ZRegister.A)
|
ZLine.ld8(ZRegister.L, ZRegister.A)
|
||||||
)) ++ List(
|
)) ++ List(
|
||||||
ZLine.ld8(ZRegister.A, ZRegister.H),
|
ZLine.ld8(ZRegister.A, ZRegister.H),
|
||||||
ZLine.register(ZOpcode.OR, ZRegister.A),
|
ZLine.register(ZOpcode.OR, ZRegister.A),
|
||||||
ZLine.register(ZOpcode.RR, ZRegister.A),
|
ZLine.implied(ZOpcode.RRA),
|
||||||
ZLine.ld8(ZRegister.H, ZRegister.A),
|
ZLine.ld8(ZRegister.H, ZRegister.A),
|
||||||
ZLine.ld8(ZRegister.A, ZRegister.L),
|
ZLine.ld8(ZRegister.A, ZRegister.L),
|
||||||
ZLine.register(ZOpcode.RR, ZRegister.A),
|
ZLine.implied(ZOpcode.RRA),
|
||||||
ZLine.ld8(ZRegister.L, ZRegister.A)
|
ZLine.ld8(ZRegister.L, ZRegister.A)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -187,16 +187,16 @@ object Z80Shifting {
|
|||||||
ZLine.register(ZOpcode.ADD, ZRegister.A),
|
ZLine.register(ZOpcode.ADD, ZRegister.A),
|
||||||
ZLine.ld8(ZRegister.L, ZRegister.A),
|
ZLine.ld8(ZRegister.L, ZRegister.A),
|
||||||
ZLine.ld8(ZRegister.A, ZRegister.H),
|
ZLine.ld8(ZRegister.A, ZRegister.H),
|
||||||
ZLine.register(ZOpcode.RL, ZRegister.A),
|
ZLine.implied(ZOpcode.RLA),
|
||||||
ZLine.ld8(ZRegister.H, ZRegister.A))
|
ZLine.ld8(ZRegister.H, ZRegister.A))
|
||||||
} else {
|
} else {
|
||||||
List(
|
List(
|
||||||
ZLine.ld8(ZRegister.A, ZRegister.H),
|
ZLine.ld8(ZRegister.A, ZRegister.H),
|
||||||
ZLine.register(ZOpcode.OR, ZRegister.A),
|
ZLine.register(ZOpcode.OR, ZRegister.A),
|
||||||
ZLine.register(ZOpcode.RR, ZRegister.A),
|
ZLine.implied(ZOpcode.RRA),
|
||||||
ZLine.ld8(ZRegister.H, ZRegister.A),
|
ZLine.ld8(ZRegister.H, ZRegister.A),
|
||||||
ZLine.ld8(ZRegister.A, ZRegister.L),
|
ZLine.ld8(ZRegister.A, ZRegister.L),
|
||||||
ZLine.register(ZOpcode.RR, ZRegister.A),
|
ZLine.implied(ZOpcode.RRA),
|
||||||
ZLine.ld8(ZRegister.L, ZRegister.A))
|
ZLine.ld8(ZRegister.L, ZRegister.A))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,14 +221,14 @@ object Z80Shifting {
|
|||||||
if (extended)
|
if (extended)
|
||||||
List(ZLine.register(SRL, H), ZLine.ld8(A, L), ZLine.register(RR, A))
|
List(ZLine.register(SRL, H), ZLine.ld8(A, L), ZLine.register(RR, A))
|
||||||
else
|
else
|
||||||
List(ZLine.ld8(A, H), ZLine.register(RR, A), ZLine.ld8(A, L), ZLine.register(RR, A))
|
List(ZLine.ld8(A, H), ZLine.implied(RRA), ZLine.ld8(A, L), ZLine.implied(RRA))
|
||||||
case Some(NumericConstant(2, _)) if extended=>
|
case Some(NumericConstant(2, _)) if extended=>
|
||||||
List(ZLine.register(SRL, H), ZLine.ld8(A, L), ZLine.register(RR, A), ZLine.register(SRL, A))
|
List(ZLine.register(SRL, H), ZLine.ld8(A, L), ZLine.implied(RRA), ZLine.register(SRL, A))
|
||||||
case Some(NumericConstant(n, _)) =>
|
case Some(NumericConstant(n, _)) =>
|
||||||
if (extended)
|
if (extended)
|
||||||
List(ZLine.register(SRL, H), ZLine.ld8(A, L)) ++ (List.fill(n.toInt)(ZLine.register(RR, A)) :+ ZLine.imm8(AND, 0x1ff >> n))
|
List(ZLine.register(SRL, H), ZLine.ld8(A, L)) ++ (List.fill(n.toInt)(ZLine.implied(RRA)) :+ ZLine.imm8(AND, 0x1ff >> n))
|
||||||
else
|
else
|
||||||
List(ZLine.ld8(A, H), ZLine.register(RR, A), ZLine.ld8(A, L)) ++ (List.fill(n.toInt)(ZLine.register(RR, A)) :+ ZLine.imm8(AND, 0x1ff >> n))
|
List(ZLine.ld8(A, H), ZLine.implied(RRA), ZLine.ld8(A, L)) ++ (List.fill(n.toInt)(ZLine.implied(RRA)) :+ ZLine.imm8(AND, 0x1ff >> n))
|
||||||
|
|
||||||
case _ =>
|
case _ =>
|
||||||
ctx.log.error("Non-constant shift amount", rhs.position) // TODO
|
ctx.log.error("Non-constant shift amount", rhs.position) // TODO
|
||||||
@@ -247,7 +247,7 @@ object Z80Shifting {
|
|||||||
import ZRegister._
|
import ZRegister._
|
||||||
val shiftByte =
|
val shiftByte =
|
||||||
if (ix == 0) List(ZLine.register(ADD, A))
|
if (ix == 0) List(ZLine.register(ADD, A))
|
||||||
else List(ZLine.register(RL, A))
|
else List(ZLine.implied(RLA))
|
||||||
ld ++ shiftByte ++ st
|
ld ++ shiftByte ++ st
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -257,8 +257,8 @@ object Z80Shifting {
|
|||||||
import ZRegister._
|
import ZRegister._
|
||||||
val shiftByte = if (ix == 0) {
|
val shiftByte = if (ix == 0) {
|
||||||
if (extended) List(ZLine.register(SRL, A))
|
if (extended) List(ZLine.register(SRL, A))
|
||||||
else List(ZLine.register(OR, A), ZLine.register(RR, A))
|
else List(ZLine.register(OR, A), ZLine.implied(RRA))
|
||||||
} else List(ZLine.register(RR, A))
|
} else List(ZLine.implied(RRA))
|
||||||
ld ++ shiftByte ++ st
|
ld ++ shiftByte ++ st
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -245,9 +245,6 @@ class Z80Assembler(program: Program,
|
|||||||
val o = oneRegister(op)
|
val o = oneRegister(op)
|
||||||
writeByte(bank, index, o.opcode + internalRegisterIndex(reg) * o.multiplier)
|
writeByte(bank, index, o.opcode + internalRegisterIndex(reg) * o.multiplier)
|
||||||
index + 1
|
index + 1
|
||||||
case ZLine(op@(RR|RRC|RL|RLC), OneRegister(A), _, _) =>
|
|
||||||
writeByte(bank, index, cbOneRegister(op).opcode + 7)
|
|
||||||
index + 1
|
|
||||||
case ZLine(SLL, OneRegister(reg), _, _) =>
|
case ZLine(SLL, OneRegister(reg), _, _) =>
|
||||||
requireZ80Illegals()
|
requireZ80Illegals()
|
||||||
writeByte(bank, index, 0xcb)
|
writeByte(bank, index, 0xcb)
|
||||||
@@ -641,6 +638,10 @@ object Z80Assembler {
|
|||||||
implieds(EI) = 0xfb
|
implieds(EI) = 0xfb
|
||||||
implieds(DI) = 0xf3
|
implieds(DI) = 0xf3
|
||||||
implieds(HALT) = 0x76
|
implieds(HALT) = 0x76
|
||||||
|
implieds(RLCA) = 7
|
||||||
|
implieds(RRCA) = 0xf
|
||||||
|
implieds(RLA) = 0x17
|
||||||
|
implieds(RRA) = 0x1f
|
||||||
|
|
||||||
immediates(ADD) = 0xc6
|
immediates(ADD) = 0xc6
|
||||||
immediates(ADC) = 0xce
|
immediates(ADC) = 0xce
|
||||||
|
@@ -198,10 +198,10 @@ case class Z80Parser(filename: String, input: String, currentDirectory: String,
|
|||||||
case "DEC" => one8Register(DEC)
|
case "DEC" => one8Register(DEC)
|
||||||
case "INC" => one8Register(INC)
|
case "INC" => one8Register(INC)
|
||||||
|
|
||||||
case "RLA" => regA(RL)
|
case "RLA" => imm(RLA)
|
||||||
case "RRA" => regA(RR)
|
case "RRA" => imm(RRA)
|
||||||
case "RLCA" => regA(RLC)
|
case "RLCA" => imm(RLCA)
|
||||||
case "RRCA" => regA(RRC)
|
case "RRCA" => imm(RRCA)
|
||||||
case "RL" => one8Register(RL)
|
case "RL" => one8Register(RL)
|
||||||
case "RR" => one8Register(RR)
|
case "RR" => one8Register(RR)
|
||||||
case "RLC" => one8Register(RLC)
|
case "RLC" => one8Register(RLC)
|
||||||
|
Reference in New Issue
Block a user