mirror of
https://github.com/KarolS/millfork.git
synced 2024-09-10 11:54:30 +00:00
6502: Track values of zeropage registers
This commit is contained in:
parent
64744f7559
commit
8dd8415432
@ -73,7 +73,7 @@ object CoarseFlowAnalyzer {
|
|||||||
currentStatus = FlowAnalyzerForImmediate.get(op)(nn.toInt, currentStatus)
|
currentStatus = FlowAnalyzerForImmediate.get(op)(nn.toInt, currentStatus)
|
||||||
|
|
||||||
case AssemblyLine(op, _, _, _) if FlowAnalyzerForTheRest.hasDefinition(op) =>
|
case AssemblyLine(op, _, _, _) if FlowAnalyzerForTheRest.hasDefinition(op) =>
|
||||||
currentStatus = FlowAnalyzerForTheRest.get(op)(currentStatus)
|
currentStatus = FlowAnalyzerForTheRest.get(op)(currentStatus, None)
|
||||||
|
|
||||||
case AssemblyLine(opcode, addrMode, _, _) =>
|
case AssemblyLine(opcode, addrMode, _, _) =>
|
||||||
currentStatus = currentStatus.copy(src = AnyStatus)
|
currentStatus = currentStatus.copy(src = AnyStatus)
|
||||||
|
@ -47,6 +47,10 @@ case class CpuStatus(a: Status[Int] = UnknownStatus,
|
|||||||
x: Status[Int] = UnknownStatus,
|
x: Status[Int] = UnknownStatus,
|
||||||
y: Status[Int] = UnknownStatus,
|
y: Status[Int] = UnknownStatus,
|
||||||
iz: Status[Int] = UnknownStatus,
|
iz: Status[Int] = UnknownStatus,
|
||||||
|
r0: Status[Int] = UnknownStatus,
|
||||||
|
r1: Status[Int] = UnknownStatus,
|
||||||
|
r2: Status[Int] = UnknownStatus,
|
||||||
|
r3: Status[Int] = UnknownStatus,
|
||||||
src: Status[SourceOfNZ] = UnknownStatus,
|
src: Status[SourceOfNZ] = UnknownStatus,
|
||||||
eqSX: Boolean = false,
|
eqSX: Boolean = false,
|
||||||
z: Status[Boolean] = UnknownStatus,
|
z: Status[Boolean] = UnknownStatus,
|
||||||
@ -90,7 +94,7 @@ case class CpuStatus(a: Status[Int] = UnknownStatus,
|
|||||||
// case _ =>
|
// case _ =>
|
||||||
// }
|
// }
|
||||||
|
|
||||||
override def toString: String = s"A=$a,B=$ah,X=$x,Y=$y,Z=$iz; Z=$z,N=$n,C=$c,V=$v,D=$d,M=$m,X=$w; A7=$a7,A0=$a0,NZ:$src" +
|
override def toString: String = s"A=$a,B=$ah,X=$x,Y=$y,Z=$iz; Z=$z,N=$n,C=$c,V=$v,D=$d,M=$m,X=$w; R0=$r0,R1=$r1,R2=$r2,R3=$r3; A7=$a7,A0=$a0,NZ:$src" +
|
||||||
(if (eqSX) "; S=X"
|
(if (eqSX) "; S=X"
|
||||||
else /* */ " ")
|
else /* */ " ")
|
||||||
|
|
||||||
@ -159,6 +163,39 @@ case class CpuStatus(a: Status[Int] = UnknownStatus,
|
|||||||
case State.W => w.contains(true)
|
case State.W => w.contains(true)
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def reg(i: Int) : Status[Int] = i match {
|
||||||
|
case 0 => r0
|
||||||
|
case 1 => r1
|
||||||
|
case 2 => r2
|
||||||
|
case 3 => r3
|
||||||
|
case _ => AnyStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
def getReg(i: Option[Int]) : Status[Int] = i match {
|
||||||
|
case Some(0) => r0
|
||||||
|
case Some(1) => r1
|
||||||
|
case Some(2) => r2
|
||||||
|
case Some(3) => r3
|
||||||
|
case _ => AnyStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
def getRegHi(i: Option[Int]) : Status[Int] = i match {
|
||||||
|
case Some(0) => r1
|
||||||
|
case Some(1) => r2
|
||||||
|
case Some(2) => r3
|
||||||
|
case _ => AnyStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
def setReg(i: Option[Int], status: Status[Int]): CpuStatus = {
|
||||||
|
i match {
|
||||||
|
case Some(0) => this.copy(r0 = status)
|
||||||
|
case Some(1) => this.copy(r1 = status)
|
||||||
|
case Some(2) => this.copy(r2 = status)
|
||||||
|
case Some(3) => this.copy(r3 = status)
|
||||||
|
case None => this
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object CpuStatus {
|
object CpuStatus {
|
||||||
@ -173,7 +210,11 @@ object CpuStatus {
|
|||||||
d = SingleStatus(false),
|
d = SingleStatus(false),
|
||||||
m = SingleStatus(true),
|
m = SingleStatus(true),
|
||||||
w = SingleStatus(true),
|
w = SingleStatus(true),
|
||||||
iz = SingleStatus(0)
|
iz = SingleStatus(0),
|
||||||
|
r0 = AnyStatus,
|
||||||
|
r1 = AnyStatus,
|
||||||
|
r2 = AnyStatus,
|
||||||
|
r3 = AnyStatus,
|
||||||
)
|
)
|
||||||
val initialStatusCE = CpuStatus(
|
val initialStatusCE = CpuStatus(
|
||||||
a = AnyStatus,
|
a = AnyStatus,
|
||||||
@ -186,7 +227,11 @@ object CpuStatus {
|
|||||||
d = SingleStatus(false),
|
d = SingleStatus(false),
|
||||||
m = SingleStatus(true),
|
m = SingleStatus(true),
|
||||||
w = SingleStatus(true),
|
w = SingleStatus(true),
|
||||||
iz = AnyStatus
|
iz = AnyStatus,
|
||||||
|
r0 = AnyStatus,
|
||||||
|
r1 = AnyStatus,
|
||||||
|
r2 = AnyStatus,
|
||||||
|
r3 = AnyStatus,
|
||||||
)
|
)
|
||||||
|
|
||||||
val initialInterruptStatusStandard = CpuStatus(
|
val initialInterruptStatusStandard = CpuStatus(
|
||||||
@ -200,7 +245,11 @@ object CpuStatus {
|
|||||||
d = AnyStatus,
|
d = AnyStatus,
|
||||||
m = AnyStatus,
|
m = AnyStatus,
|
||||||
w = AnyStatus,
|
w = AnyStatus,
|
||||||
iz = SingleStatus(0)
|
iz = SingleStatus(0),
|
||||||
|
r0 = AnyStatus,
|
||||||
|
r1 = AnyStatus,
|
||||||
|
r2 = AnyStatus,
|
||||||
|
r3 = AnyStatus,
|
||||||
)
|
)
|
||||||
val initialInterruptStatusCmos = CpuStatus(
|
val initialInterruptStatusCmos = CpuStatus(
|
||||||
a = AnyStatus,
|
a = AnyStatus,
|
||||||
@ -213,7 +262,11 @@ object CpuStatus {
|
|||||||
d = SingleStatus(false),
|
d = SingleStatus(false),
|
||||||
m = AnyStatus,
|
m = AnyStatus,
|
||||||
w = AnyStatus,
|
w = AnyStatus,
|
||||||
iz = SingleStatus(0)
|
iz = SingleStatus(0),
|
||||||
|
r0 = AnyStatus,
|
||||||
|
r1 = AnyStatus,
|
||||||
|
r2 = AnyStatus,
|
||||||
|
r3 = AnyStatus,
|
||||||
)
|
)
|
||||||
val initialInterruptStatusCE = CpuStatus(
|
val initialInterruptStatusCE = CpuStatus(
|
||||||
a = AnyStatus,
|
a = AnyStatus,
|
||||||
@ -226,7 +279,11 @@ object CpuStatus {
|
|||||||
d = SingleStatus(false),
|
d = SingleStatus(false),
|
||||||
m = AnyStatus,
|
m = AnyStatus,
|
||||||
w = AnyStatus,
|
w = AnyStatus,
|
||||||
iz = AnyStatus
|
iz = AnyStatus,
|
||||||
|
r0 = AnyStatus,
|
||||||
|
r1 = AnyStatus,
|
||||||
|
r2 = AnyStatus,
|
||||||
|
r3 = AnyStatus,
|
||||||
)
|
)
|
||||||
|
|
||||||
val emptyStatusStandard = CpuStatus(iz = SingleStatus(0))
|
val emptyStatusStandard = CpuStatus(iz = SingleStatus(0))
|
||||||
|
@ -72,7 +72,7 @@ object FlowAnalyzerForImmediate {
|
|||||||
},
|
},
|
||||||
ADC -> {(nn, currentStatus) =>
|
ADC -> {(nn, currentStatus) =>
|
||||||
val n = nn & 0xff
|
val n = nn & 0xff
|
||||||
val newA = currentStatus.a.adc(n, currentStatus.c, currentStatus.d)
|
val (newA, newC) = currentStatus.a.adc(n, currentStatus.c, currentStatus.d)
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
n = newA.n(),
|
n = newA.n(),
|
||||||
z = newA.z(),
|
z = newA.z(),
|
||||||
@ -80,7 +80,7 @@ object FlowAnalyzerForImmediate {
|
|||||||
a = newA,
|
a = newA,
|
||||||
a0 = newA.bit0,
|
a0 = newA.bit0,
|
||||||
a7 = newA.bit7,
|
a7 = newA.bit7,
|
||||||
c = Status.flatMap3(currentStatus.a, currentStatus.c, currentStatus.d) {
|
c = newC | Status.flatMap3(currentStatus.a, currentStatus.c, currentStatus.d) {
|
||||||
case (aa, false, false) => SingleStatus((aa & 0xff) + n >= 0x100)
|
case (aa, false, false) => SingleStatus((aa & 0xff) + n >= 0x100)
|
||||||
case _ => AnyStatus
|
case _ => AnyStatus
|
||||||
},
|
},
|
||||||
@ -88,7 +88,7 @@ object FlowAnalyzerForImmediate {
|
|||||||
},
|
},
|
||||||
SBC -> {(nn, currentStatus) =>
|
SBC -> {(nn, currentStatus) =>
|
||||||
val n = nn & 0xff
|
val n = nn & 0xff
|
||||||
val newA = currentStatus.a.sbc(n, currentStatus.c, currentStatus.d)
|
val (newA, newC) = currentStatus.a.sbc(n, currentStatus.c, currentStatus.d)
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
n = newA.n(),
|
n = newA.n(),
|
||||||
z = newA.z(),
|
z = newA.z(),
|
||||||
@ -96,7 +96,7 @@ object FlowAnalyzerForImmediate {
|
|||||||
a = newA,
|
a = newA,
|
||||||
a0 = newA.bit0,
|
a0 = newA.bit0,
|
||||||
a7 = newA.bit7,
|
a7 = newA.bit7,
|
||||||
c = AnyStatus,
|
c = newC,
|
||||||
v = AnyStatus)
|
v = AnyStatus)
|
||||||
},
|
},
|
||||||
EOR -> {(nn, currentStatus) =>
|
EOR -> {(nn, currentStatus) =>
|
||||||
|
@ -8,35 +8,35 @@ import millfork.assembly.opt.{AnyStatus, SingleStatus, Status}
|
|||||||
* @author Karol Stasiak
|
* @author Karol Stasiak
|
||||||
*/
|
*/
|
||||||
object FlowAnalyzerForTheRest {
|
object FlowAnalyzerForTheRest {
|
||||||
private val map: Map[Opcode.Value, CpuStatus => CpuStatus] = Map(
|
private val map: Map[Opcode.Value, (CpuStatus, Option[Int]) => CpuStatus] = Map(
|
||||||
STA -> identity,
|
STA -> ((c,zpreg) => c.setReg(zpreg, c.a)),
|
||||||
STX -> identity,
|
STX -> ((c,zpreg) => c.setReg(zpreg, c.x)),
|
||||||
STY -> identity,
|
STY -> ((c,zpreg) => c.setReg(zpreg, c.y)),
|
||||||
STZ -> identity,
|
STZ -> ((c,zpreg) => c.setReg(zpreg, c.iz)),
|
||||||
SAX -> identity,
|
SAX -> ((c,zpreg) => c.setReg(zpreg, (c.a <*> c.x)(_ & _))),
|
||||||
NOP -> identity,
|
NOP -> ((x,_) => x),
|
||||||
DISCARD_AF -> identity,
|
DISCARD_AF -> ((x,_) => x),
|
||||||
DISCARD_XF -> identity,
|
DISCARD_XF -> ((x,_) => x),
|
||||||
DISCARD_YF -> identity,
|
DISCARD_YF -> ((x,_) => x),
|
||||||
REP -> (currentStatus => {
|
REP -> ((currentStatus, zpreg) => {
|
||||||
currentStatus.copy(c = AnyStatus, d = AnyStatus, n = AnyStatus, z= AnyStatus, v = AnyStatus, m = AnyStatus, w = AnyStatus)
|
currentStatus.copy(c = AnyStatus, d = AnyStatus, n = AnyStatus, z= AnyStatus, v = AnyStatus, m = AnyStatus, w = AnyStatus)
|
||||||
}),
|
}),
|
||||||
SEP -> (currentStatus => {
|
SEP -> ((currentStatus, zpreg) => {
|
||||||
currentStatus.copy(c = AnyStatus, d = AnyStatus, n = AnyStatus, z= AnyStatus, v = AnyStatus, m = AnyStatus, w = AnyStatus)
|
currentStatus.copy(c = AnyStatus, d = AnyStatus, n = AnyStatus, z= AnyStatus, v = AnyStatus, m = AnyStatus, w = AnyStatus)
|
||||||
}),
|
}),
|
||||||
BCC -> (currentStatus => {
|
BCC -> ((currentStatus, zpreg) => {
|
||||||
currentStatus.copy(c = Status.SingleTrue)
|
currentStatus.copy(c = Status.SingleTrue)
|
||||||
}),
|
}),
|
||||||
BCS -> (currentStatus => {
|
BCS -> ((currentStatus, zpreg) => {
|
||||||
currentStatus.copy(c = Status.SingleFalse)
|
currentStatus.copy(c = Status.SingleFalse)
|
||||||
}),
|
}),
|
||||||
BVS -> (currentStatus => {
|
BVS -> ((currentStatus, zpreg) => {
|
||||||
currentStatus.copy(v = Status.SingleFalse)
|
currentStatus.copy(v = Status.SingleFalse)
|
||||||
}),
|
}),
|
||||||
BVC -> (currentStatus => {
|
BVC -> ((currentStatus, zpreg) => {
|
||||||
currentStatus.copy(v = Status.SingleTrue)
|
currentStatus.copy(v = Status.SingleTrue)
|
||||||
}),
|
}),
|
||||||
BMI -> (c => {
|
BMI -> ((c, zpreg) => {
|
||||||
var currentStatus = c
|
var currentStatus = c
|
||||||
currentStatus = currentStatus.copy(n = Status.SingleFalse)
|
currentStatus = currentStatus.copy(n = Status.SingleFalse)
|
||||||
if (currentStatus.src.isFromA) {
|
if (currentStatus.src.isFromA) {
|
||||||
@ -44,7 +44,7 @@ object FlowAnalyzerForTheRest {
|
|||||||
}
|
}
|
||||||
currentStatus
|
currentStatus
|
||||||
}),
|
}),
|
||||||
BPL -> (c => {
|
BPL -> ((c, zpreg) => {
|
||||||
var currentStatus = c
|
var currentStatus = c
|
||||||
currentStatus = currentStatus.copy(n = Status.SingleTrue)
|
currentStatus = currentStatus.copy(n = Status.SingleTrue)
|
||||||
if (currentStatus.src.isFromA) {
|
if (currentStatus.src.isFromA) {
|
||||||
@ -52,10 +52,10 @@ object FlowAnalyzerForTheRest {
|
|||||||
}
|
}
|
||||||
currentStatus
|
currentStatus
|
||||||
}),
|
}),
|
||||||
BEQ -> (currentStatus => {
|
BEQ -> ((currentStatus, zpreg) => {
|
||||||
currentStatus.copy(z = Status.SingleFalse)
|
currentStatus.copy(z = Status.SingleFalse)
|
||||||
}),
|
}),
|
||||||
BNE -> (c => {
|
BNE -> ((c, zpreg) => {
|
||||||
var currentStatus = c
|
var currentStatus = c
|
||||||
currentStatus = currentStatus.copy(z = Status.SingleTrue)
|
currentStatus = currentStatus.copy(z = Status.SingleTrue)
|
||||||
if (currentStatus.src.isFromA) {
|
if (currentStatus.src.isFromA) {
|
||||||
@ -79,100 +79,123 @@ object FlowAnalyzerForTheRest {
|
|||||||
}
|
}
|
||||||
currentStatus
|
currentStatus
|
||||||
}),
|
}),
|
||||||
LDX -> (currentStatus => {
|
LDX -> ((currentStatus, zpreg) => {
|
||||||
|
val newX = currentStatus.getReg(zpreg)
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
x = AnyStatus,
|
x = newX,
|
||||||
n = AnyStatus,
|
n = newX.n(),
|
||||||
z = AnyStatus,
|
z = newX.z(),
|
||||||
src = SourceOfNZ.X)
|
src = SourceOfNZ.X)
|
||||||
}),
|
}),
|
||||||
LDY -> (currentStatus => {
|
LDY -> ((currentStatus, zpreg) => {
|
||||||
|
val newY = currentStatus.getReg(zpreg)
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
y = AnyStatus,
|
y = newY,
|
||||||
n = AnyStatus,
|
n = newY.n(),
|
||||||
z = AnyStatus,
|
z = newY.z(),
|
||||||
src = SourceOfNZ.Y)
|
src = SourceOfNZ.Y)
|
||||||
}),
|
}),
|
||||||
LDA -> (currentStatus => {
|
LDA -> ((currentStatus, zpreg) => {
|
||||||
|
val newA = currentStatus.getReg(zpreg)
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
a = AnyStatus,
|
a = newA,
|
||||||
a7 = AnyStatus,
|
a7 = newA.bit7,
|
||||||
a0 = AnyStatus,
|
a0 = newA.bit0,
|
||||||
n = AnyStatus,
|
n = newA.n(),
|
||||||
z = AnyStatus,
|
z = newA.z(),
|
||||||
src = SourceOfNZ.A)
|
src = SourceOfNZ.A)
|
||||||
}),
|
}),
|
||||||
LDZ -> (currentStatus => {
|
LDZ -> ((currentStatus, zpreg) => {
|
||||||
|
val newZ = currentStatus.getReg(zpreg)
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
iz = AnyStatus,
|
iz = newZ,
|
||||||
n = AnyStatus,
|
n = newZ.n(),
|
||||||
z = AnyStatus,
|
z = newZ.z(),
|
||||||
src = SourceOfNZ.Z)
|
src = SourceOfNZ.Z)
|
||||||
}),
|
}),
|
||||||
LAX -> (currentStatus => {
|
LAX -> ((currentStatus, zpreg) => {
|
||||||
|
val newA = currentStatus.getReg(zpreg)
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
x = AnyStatus,
|
x = newA,
|
||||||
a = AnyStatus,
|
a = newA,
|
||||||
a7 = AnyStatus,
|
a7 = newA.bit7,
|
||||||
a0 = AnyStatus,
|
a0 = newA.bit0,
|
||||||
n = AnyStatus,
|
n = newA.n(),
|
||||||
z = AnyStatus,
|
z = newA.z(),
|
||||||
src = SourceOfNZ.AX)
|
src = SourceOfNZ.AX)
|
||||||
}),
|
}),
|
||||||
LDA_W -> (currentStatus => {
|
LDA_W -> ((currentStatus, zpreg) => {
|
||||||
|
val newA = currentStatus.getReg(zpreg)
|
||||||
|
val newAH = currentStatus.getRegHi(zpreg)
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
ah = AnyStatus,
|
ah = newAH,
|
||||||
a = AnyStatus,
|
a = newA,
|
||||||
a7 = AnyStatus,
|
a7 = AnyStatus,
|
||||||
a0 = AnyStatus,
|
a0 = newA.bit0,
|
||||||
n = AnyStatus,
|
n = AnyStatus,
|
||||||
z = AnyStatus,
|
z = AnyStatus,
|
||||||
src = SourceOfNZ.AW)
|
src = SourceOfNZ.AW)
|
||||||
}),
|
}),
|
||||||
LDX_W -> (currentStatus => {
|
LDX_W -> ((currentStatus, zpreg) => {
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
x = AnyStatus,
|
x = AnyStatus,
|
||||||
n = AnyStatus,
|
n = AnyStatus,
|
||||||
z = AnyStatus,
|
z = AnyStatus,
|
||||||
src = AnyStatus)
|
src = AnyStatus)
|
||||||
}),
|
}),
|
||||||
LDY_W -> (currentStatus => {
|
LDY_W -> ((currentStatus, zpreg) => {
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
y = AnyStatus,
|
y = AnyStatus,
|
||||||
n = AnyStatus,
|
n = AnyStatus,
|
||||||
z = AnyStatus,
|
z = AnyStatus,
|
||||||
src = AnyStatus)
|
src = AnyStatus)
|
||||||
}),
|
}),
|
||||||
ADC -> (currentStatus => {
|
ADC -> ((currentStatus, zpreg) => {
|
||||||
|
val r = currentStatus.getReg(zpreg)
|
||||||
|
val newA: Status[Int]= if (currentStatus.d.contains(false)) Status.flatMap3(currentStatus.a, r, currentStatus.c) {
|
||||||
|
case (m, n, false) => SingleStatus((m + n) & 0xff)
|
||||||
|
case (m, n, true) => SingleStatus((m + n + 1) & 0xff)
|
||||||
|
} else AnyStatus
|
||||||
|
val newC: Status[Boolean]= if (currentStatus.d.contains(false)) Status.flatMap3(currentStatus.a, r, currentStatus.c) {
|
||||||
|
case (m, n, false) => SingleStatus((m.&(0xff) + n.&(0xff)) > 0xff)
|
||||||
|
case (m, n, true) => SingleStatus((m.&(0xff) + n.&(0xff) + 1) > 0xff)
|
||||||
|
} else AnyStatus
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
a = AnyStatus,
|
a = newA,
|
||||||
a7 = AnyStatus,
|
a7 = newA.bit7,
|
||||||
a0 = AnyStatus,
|
a0 = newA.bit0,
|
||||||
v = AnyStatus,
|
v = AnyStatus,
|
||||||
c = Status.flatMap3(currentStatus.a, currentStatus.c, currentStatus.d) {
|
c = newC | Status.flatMap3(currentStatus.a, currentStatus.c, currentStatus.d) {
|
||||||
case (0, false, false) => SingleStatus[Boolean](false)
|
case (0, false, false) => SingleStatus[Boolean](false)
|
||||||
case _ => AnyStatus
|
case _ => AnyStatus
|
||||||
},
|
},
|
||||||
z = AnyStatus,
|
z = newA.z(),
|
||||||
n = AnyStatus,
|
n = newA.n(),
|
||||||
src = currentStatus.d.flatMap((dec: Boolean) => if (dec) AnyStatus else SourceOfNZ.A))
|
src = currentStatus.d.flatMap((dec: Boolean) => if (dec) AnyStatus else SourceOfNZ.A))
|
||||||
}),
|
}),
|
||||||
SBC -> (currentStatus => {
|
SBC -> ((currentStatus, zpreg) => {
|
||||||
|
val r = currentStatus.getReg(zpreg)
|
||||||
|
val newA: Status[Int]= if (currentStatus.d.contains(false)) Status.flatMap3(currentStatus.a, r, currentStatus.c) {
|
||||||
|
case (m, n, false) => SingleStatus((m - n + 0xff) & 0xff)
|
||||||
|
case (m, n, true) => SingleStatus((m - n + 0x100) & 0xff)
|
||||||
|
} else AnyStatus
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
a = AnyStatus,
|
a = newA,
|
||||||
a7 = AnyStatus,
|
a7 = newA.bit7,
|
||||||
a0 = AnyStatus,
|
a0 = newA.bit0,
|
||||||
v = AnyStatus,
|
v = AnyStatus,
|
||||||
c = Status.flatMap3(currentStatus.a, currentStatus.c, currentStatus.d) {
|
c = Status.flatMap3(currentStatus.a, currentStatus.c, currentStatus.d) {
|
||||||
case (0xff, true, false) => SingleStatus[Boolean](true)
|
case (0xff, true, false) => SingleStatus[Boolean](true)
|
||||||
case _ => AnyStatus
|
case _ => AnyStatus
|
||||||
},
|
},
|
||||||
z = AnyStatus,
|
z = newA.z(),
|
||||||
n = AnyStatus,
|
n = newA.n(),
|
||||||
src = currentStatus.d.flatMap((dec: Boolean) => if (dec) AnyStatus else SourceOfNZ.A))
|
src = currentStatus.d.flatMap((dec: Boolean) => if (dec) AnyStatus else SourceOfNZ.A))
|
||||||
}),
|
}),
|
||||||
AND -> (currentStatus => {
|
AND -> ((currentStatus, zpreg) => {
|
||||||
val newA: Status[Int] = currentStatus.a.flatMap(v => if ((v & 0xff) == 0) Status.SingleZero else AnyStatus)
|
val newA: Status[Int] =
|
||||||
|
currentStatus.a.flatMap(v => if ((v & 0xff) == 0) Status.SingleZero else AnyStatus) |
|
||||||
|
(currentStatus.a <*> currentStatus.getReg(zpreg))(_ & _)
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
a = newA,
|
a = newA,
|
||||||
a7 = currentStatus.a7.flatMap(v => if (!v) Status.SingleFalse else AnyStatus),
|
a7 = currentStatus.a7.flatMap(v => if (!v) Status.SingleFalse else AnyStatus),
|
||||||
@ -181,8 +204,10 @@ object FlowAnalyzerForTheRest {
|
|||||||
z = newA.z(),
|
z = newA.z(),
|
||||||
src = SourceOfNZ.A)
|
src = SourceOfNZ.A)
|
||||||
}),
|
}),
|
||||||
ORA -> (currentStatus => {
|
ORA -> ((currentStatus, zpreg) => {
|
||||||
val newA: Status[Int] = currentStatus.a.flatMap(v => if ((v & 0xff) == 0xff) Status.SingleFF else AnyStatus)
|
val newA: Status[Int] =
|
||||||
|
currentStatus.a.flatMap(v => if ((v & 0xff) == 0xff) Status.SingleFF else AnyStatus) |
|
||||||
|
(currentStatus.a <*> currentStatus.getReg(zpreg))(_ | _)
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
a = newA,
|
a = newA,
|
||||||
a7 = currentStatus.a7.flatMap(v => if (v) Status.SingleTrue else AnyStatus),
|
a7 = currentStatus.a7.flatMap(v => if (v) Status.SingleTrue else AnyStatus),
|
||||||
@ -191,7 +216,7 @@ object FlowAnalyzerForTheRest {
|
|||||||
z = newA.z(),
|
z = newA.z(),
|
||||||
src = SourceOfNZ.A)
|
src = SourceOfNZ.A)
|
||||||
}),
|
}),
|
||||||
SLO -> (currentStatus => {
|
SLO -> ((currentStatus, zpreg) => {
|
||||||
val newA: Status[Int] = currentStatus.a.flatMap(v => if ((v & 0xff) == 0xff) Status.SingleFF else AnyStatus)
|
val newA: Status[Int] = currentStatus.a.flatMap(v => if ((v & 0xff) == 0xff) Status.SingleFF else AnyStatus)
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
c = AnyStatus,
|
c = AnyStatus,
|
||||||
@ -200,18 +225,19 @@ object FlowAnalyzerForTheRest {
|
|||||||
a0 = currentStatus.a0.flatMap(v => if (v) Status.SingleTrue else AnyStatus),
|
a0 = currentStatus.a0.flatMap(v => if (v) Status.SingleTrue else AnyStatus),
|
||||||
n = newA.n(),
|
n = newA.n(),
|
||||||
z = newA.z(),
|
z = newA.z(),
|
||||||
src = SourceOfNZ.A)
|
src = SourceOfNZ.A).setReg(zpreg, AnyStatus)
|
||||||
}),
|
}),
|
||||||
EOR -> (currentStatus => {
|
EOR -> ((currentStatus, zpreg) => {
|
||||||
|
val newA: Status[Int] = (currentStatus.a <*> currentStatus.getReg(zpreg))(_ ^ _)
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
n = AnyStatus,
|
n = newA.n(),
|
||||||
z = AnyStatus,
|
z = newA.z(),
|
||||||
a = AnyStatus,
|
a = newA,
|
||||||
a7 = AnyStatus,
|
a7 = newA.bit7,
|
||||||
a0 = AnyStatus,
|
a0 = newA.bit0,
|
||||||
src = SourceOfNZ.A)
|
src = SourceOfNZ.A).setReg(zpreg, AnyStatus)
|
||||||
}),
|
}),
|
||||||
SRE -> (currentStatus => {
|
SRE -> ((currentStatus, zpreg) => {
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
c = AnyStatus,
|
c = AnyStatus,
|
||||||
n = AnyStatus,
|
n = AnyStatus,
|
||||||
@ -219,9 +245,9 @@ object FlowAnalyzerForTheRest {
|
|||||||
a = AnyStatus,
|
a = AnyStatus,
|
||||||
a7 = AnyStatus,
|
a7 = AnyStatus,
|
||||||
a0 = AnyStatus,
|
a0 = AnyStatus,
|
||||||
src = SourceOfNZ.A)
|
src = SourceOfNZ.A).setReg(zpreg, AnyStatus)
|
||||||
}),
|
}),
|
||||||
RLA -> (currentStatus => {
|
RLA -> ((currentStatus, zpreg) => {
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
c = AnyStatus,
|
c = AnyStatus,
|
||||||
n = AnyStatus,
|
n = AnyStatus,
|
||||||
@ -229,9 +255,9 @@ object FlowAnalyzerForTheRest {
|
|||||||
a = AnyStatus,
|
a = AnyStatus,
|
||||||
a7 = AnyStatus,
|
a7 = AnyStatus,
|
||||||
a0 = AnyStatus,
|
a0 = AnyStatus,
|
||||||
src = SourceOfNZ.A)
|
src = SourceOfNZ.A).setReg(zpreg, AnyStatus)
|
||||||
}),
|
}),
|
||||||
RRA -> (currentStatus => {
|
RRA -> ((currentStatus, zpreg) => {
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
c = AnyStatus,
|
c = AnyStatus,
|
||||||
n = AnyStatus,
|
n = AnyStatus,
|
||||||
@ -240,9 +266,18 @@ object FlowAnalyzerForTheRest {
|
|||||||
a7 = AnyStatus,
|
a7 = AnyStatus,
|
||||||
a0 = AnyStatus,
|
a0 = AnyStatus,
|
||||||
z = AnyStatus,
|
z = AnyStatus,
|
||||||
src = currentStatus.d.flatMap(dec => if (dec) AnyStatus else SourceOfNZ.A))
|
src = currentStatus.d.flatMap(dec => if (dec) AnyStatus else SourceOfNZ.A)).setReg(zpreg, AnyStatus)
|
||||||
}),
|
}),
|
||||||
ISC -> (currentStatus => {
|
DCP -> ((currentStatus, zpreg) => {
|
||||||
|
val r = currentStatus.getReg(zpreg)
|
||||||
|
currentStatus.copy(
|
||||||
|
c = AnyStatus,
|
||||||
|
n = AnyStatus,
|
||||||
|
z = AnyStatus,
|
||||||
|
src = AnyStatus).setReg(zpreg, r.map(n => (n - 1) & 0xff))
|
||||||
|
}),
|
||||||
|
ISC -> ((currentStatus, zpreg) => {
|
||||||
|
val r = currentStatus.getReg(zpreg)
|
||||||
currentStatus.copy(
|
currentStatus.copy(
|
||||||
c = AnyStatus,
|
c = AnyStatus,
|
||||||
n = AnyStatus,
|
n = AnyStatus,
|
||||||
@ -251,27 +286,61 @@ object FlowAnalyzerForTheRest {
|
|||||||
a7 = AnyStatus,
|
a7 = AnyStatus,
|
||||||
a0 = AnyStatus,
|
a0 = AnyStatus,
|
||||||
z = AnyStatus,
|
z = AnyStatus,
|
||||||
src = currentStatus.d.flatMap(dec => if (dec) AnyStatus else SourceOfNZ.A))
|
src = currentStatus.d.flatMap(dec => if (dec) AnyStatus else SourceOfNZ.A)).setReg(zpreg, r.map(n => (n + 1) & 0xff))
|
||||||
}),
|
}),
|
||||||
ROL -> (_.copy(c = AnyStatus, n = AnyStatus, z = AnyStatus, src = AnyStatus)),
|
ROL -> ((currentStatus, zpreg) => {
|
||||||
ROR -> (_.copy(c = AnyStatus, n = AnyStatus, z = AnyStatus, src = AnyStatus)),
|
val r = currentStatus.getReg(zpreg)
|
||||||
ASL -> (_.copy(c = AnyStatus, n = AnyStatus, z = AnyStatus, src = AnyStatus)),
|
currentStatus.copy(c = r.bit7, n = AnyStatus, z = AnyStatus, src = AnyStatus).setReg(zpreg, currentStatus.c.flatMap { c =>
|
||||||
LSR -> (_.copy(c = AnyStatus, n = AnyStatus, z = AnyStatus, src = AnyStatus)),
|
r.map(n => (n << 1) & 0xff | (if (c) 1 else 0))
|
||||||
INC -> (_.copy(n = AnyStatus, z = AnyStatus, src = AnyStatus)),
|
})
|
||||||
DEC -> (_.copy(n = AnyStatus, z = AnyStatus, src = AnyStatus)),
|
}),
|
||||||
CMP -> (_.copy(c = AnyStatus, n = AnyStatus, z = AnyStatus, src = AnyStatus)),
|
ROR -> ((currentStatus, zpreg) => {
|
||||||
CPX -> (_.copy(c = AnyStatus, n = AnyStatus, z = AnyStatus, src = AnyStatus)),
|
val r = currentStatus.getReg(zpreg)
|
||||||
CPY -> (_.copy(c = AnyStatus, n = AnyStatus, z = AnyStatus, src = AnyStatus)),
|
currentStatus.copy(c = r.bit0, n = AnyStatus, z = AnyStatus, src = AnyStatus).setReg(zpreg, currentStatus.c.flatMap { c =>
|
||||||
CPZ -> (_.copy(c = AnyStatus, n = AnyStatus, z = AnyStatus, src = AnyStatus)),
|
r.map(n => (n >> 1) & 0x7f | (if (c) 0x80 else 0))
|
||||||
BIT -> (_.copy(v = AnyStatus, n = AnyStatus, z = AnyStatus, src = AnyStatus)),
|
})
|
||||||
TRB -> (_.copy(z = AnyStatus, src = AnyStatus)),
|
}),
|
||||||
TSB -> (_.copy(z = AnyStatus, src = AnyStatus)),
|
ASL -> ((currentStatus, zpreg) => {
|
||||||
JMP -> (_ => CpuStatus()),
|
val r = currentStatus.getReg(zpreg)
|
||||||
BRA -> (_ => CpuStatus()),
|
currentStatus.copy(c = r.bit7, n = AnyStatus, z = AnyStatus, src = AnyStatus).setReg(zpreg, r.map(n => (n << 1) & 0xff))
|
||||||
BRL -> (_ => CpuStatus()),
|
}),
|
||||||
|
LSR -> ((currentStatus, zpreg) => {
|
||||||
|
val r = currentStatus.getReg(zpreg)
|
||||||
|
currentStatus.copy(c = r.bit0, n = AnyStatus, z = AnyStatus, src = AnyStatus).setReg(zpreg, r.map(n => (n >> 1) & 0xff))
|
||||||
|
}),
|
||||||
|
INC -> ((currentStatus, zpreg) => {
|
||||||
|
val r = currentStatus.getReg(zpreg)
|
||||||
|
currentStatus.copy(n = AnyStatus, z = AnyStatus, src = AnyStatus).setReg(zpreg, r.map(n => (n + 1) & 0xff))
|
||||||
|
}),
|
||||||
|
DEC -> ((currentStatus, zpreg) => {
|
||||||
|
val r = currentStatus.getReg(zpreg)
|
||||||
|
currentStatus.copy(n = AnyStatus, z = AnyStatus, src = AnyStatus).setReg(zpreg, r.map(n => (n - 1) & 0xff))
|
||||||
|
}),
|
||||||
|
CMP -> ((currentStatus, zpreg) => {
|
||||||
|
val r = currentStatus.getReg(zpreg)
|
||||||
|
currentStatus.copy(c = AnyStatus, n = AnyStatus, z = (currentStatus.a <*> r)(_==_), src = if (r.contains(0)) SourceOfNZ.A else AnyStatus)
|
||||||
|
}),
|
||||||
|
CPX -> ((currentStatus, zpreg) => {
|
||||||
|
val r = currentStatus.getReg(zpreg)
|
||||||
|
currentStatus.copy(c = AnyStatus, n = AnyStatus, z = (currentStatus.x <*> r)(_==_), src = if (r.contains(0)) SourceOfNZ.X else AnyStatus)
|
||||||
|
}),
|
||||||
|
CPY -> ((currentStatus, zpreg) => {
|
||||||
|
val r = currentStatus.getReg(zpreg)
|
||||||
|
currentStatus.copy(c = AnyStatus, n = AnyStatus, z = (currentStatus.y <*> r)(_==_), src = if (r.contains(0)) SourceOfNZ.Y else AnyStatus)
|
||||||
|
}),
|
||||||
|
CPZ -> ((currentStatus, zpreg) => {
|
||||||
|
val r = currentStatus.getReg(zpreg)
|
||||||
|
currentStatus.copy(c = AnyStatus, n = AnyStatus, z = (currentStatus.iz <*> r)(_==_), src = if (r.contains(0)) SourceOfNZ.Z else AnyStatus)
|
||||||
|
}),
|
||||||
|
BIT -> ((currentStatus, zpreg) => currentStatus.copy(v = AnyStatus, n = AnyStatus, z = AnyStatus, src = AnyStatus)),
|
||||||
|
TRB -> ((currentStatus, zpreg) => currentStatus.copy(z = AnyStatus, src = AnyStatus).setReg(zpreg, AnyStatus)),
|
||||||
|
TSB -> ((currentStatus, zpreg) => currentStatus.copy(z = AnyStatus, src = AnyStatus).setReg(zpreg, AnyStatus)),
|
||||||
|
JMP -> ((_,_) => CpuStatus()),
|
||||||
|
BRA -> ((_,_) => CpuStatus()),
|
||||||
|
BRL -> ((_,_) => CpuStatus()),
|
||||||
)
|
)
|
||||||
|
|
||||||
def hasDefinition(opcode: Opcode.Value): Boolean = map.contains(opcode)
|
def hasDefinition(opcode: Opcode.Value): Boolean = map.contains(opcode)
|
||||||
|
|
||||||
def get(opcode: Opcode.Value): CpuStatus => CpuStatus = map(opcode)
|
def get(opcode: Opcode.Value): (CpuStatus, Option[Int]) => CpuStatus = map(opcode)
|
||||||
}
|
}
|
||||||
|
@ -547,6 +547,17 @@ case class MatchY(i: Int) extends AssemblyLinePattern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case class MatchZpReg(i: Int, registerIndex: Int) extends AssemblyLinePattern {
|
||||||
|
override def validate(needsFlowInfo: FlowInfoRequirement.Value): Unit =
|
||||||
|
FlowInfoRequirement.assertForward(needsFlowInfo)
|
||||||
|
|
||||||
|
override def matchLineTo(ctx: AssemblyMatchingContext, flowInfo: FlowInfo, line: AssemblyLine): Boolean =
|
||||||
|
flowInfo.statusBefore.reg(registerIndex) match {
|
||||||
|
case SingleStatus(value) => ctx.addObject(i, value)
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case class HasA(value: Int) extends AssemblyLinePattern {
|
case class HasA(value: Int) extends AssemblyLinePattern {
|
||||||
override def validate(needsFlowInfo: FlowInfoRequirement.Value): Unit =
|
override def validate(needsFlowInfo: FlowInfoRequirement.Value): Unit =
|
||||||
FlowInfoRequirement.assertForward(needsFlowInfo)
|
FlowInfoRequirement.assertForward(needsFlowInfo)
|
||||||
|
@ -5,7 +5,7 @@ import millfork.assembly.mos.AddrMode._
|
|||||||
import millfork.assembly.AssemblyOptimization
|
import millfork.assembly.AssemblyOptimization
|
||||||
import millfork.assembly.mos.{AssemblyLine, Opcode, State}
|
import millfork.assembly.mos.{AssemblyLine, Opcode, State}
|
||||||
import millfork.env.{CompoundConstant, Constant, MathOperator}
|
import millfork.env.{CompoundConstant, Constant, MathOperator}
|
||||||
|
import millfork.DecimalUtils.asDecimal
|
||||||
/**
|
/**
|
||||||
* @author Karol Stasiak
|
* @author Karol Stasiak
|
||||||
*/
|
*/
|
||||||
@ -27,6 +27,11 @@ object ZeropageRegisterOptimizations {
|
|||||||
code.init :+ AssemblyLine.immediate(LDA, product & 0xff)
|
code.init :+ AssemblyLine.immediate(LDA, product & 0xff)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
(Elidable & HasOpcode(JSR) & RefersTo("__mul_u8u8u8", 0) & MatchZpReg(4, 0) & MatchZpReg(5, 1)) ~~> { (code, ctx) =>
|
||||||
|
val product = ctx.get[Int](4) * ctx.get[Int](5)
|
||||||
|
code.init :+ AssemblyLine.immediate(LDA, product & 0xff)
|
||||||
|
},
|
||||||
|
|
||||||
// TODO: constants other than power of 2:
|
// TODO: constants other than power of 2:
|
||||||
|
|
||||||
(Elidable & HasOpcode(STA) & RefersTo("__reg", 0) & MatchAddrMode(0) & MatchParameter(1)) ~
|
(Elidable & HasOpcode(STA) & RefersTo("__reg", 0) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||||
@ -171,41 +176,74 @@ object ZeropageRegisterOptimizations {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val PointlessLoad = new RuleBasedAssemblyOptimization("Pointless load from zeropage register",
|
||||||
|
needsFlowInfo = FlowInfoRequirement.BothFlows,
|
||||||
|
MultipleAssemblyRules((0 until 4).flatMap{ zpregIndex =>
|
||||||
|
List(
|
||||||
|
(Elidable & HasOpcode(LDA) & RefersTo("__reg", zpregIndex) &
|
||||||
|
MatchZpReg(4, zpregIndex) & MatchA(4) &
|
||||||
|
DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_ => Nil),
|
||||||
|
(Elidable & HasOpcode(LDX) & RefersTo("__reg", zpregIndex) &
|
||||||
|
MatchZpReg(4, zpregIndex) & MatchX(4) &
|
||||||
|
DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_ => Nil),
|
||||||
|
(Elidable & HasOpcode(LDY) & RefersTo("__reg", zpregIndex) &
|
||||||
|
MatchZpReg(4, zpregIndex) & MatchY(4) &
|
||||||
|
DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_ => Nil),
|
||||||
|
|
||||||
private def parseNormalToDecimalValue(a: Long): Long = {
|
(Elidable & HasOpcode(LDA) & RefersTo("__reg", zpregIndex) &
|
||||||
if (a < 0) -parseNormalToDecimalValue(-a)
|
MatchZpReg(4, zpregIndex) & MatchX(4)) ~~> (_ => List(AssemblyLine.implied(TXA))),
|
||||||
var x = a
|
(Elidable & HasOpcode(LDA) & RefersTo("__reg", zpregIndex) &
|
||||||
var result = 0L
|
MatchZpReg(4, zpregIndex) & MatchY(4)) ~~> (_ => List(AssemblyLine.implied(TYA))),
|
||||||
var multiplier = 1L
|
(Elidable & HasOpcode(LDX) & RefersTo("__reg", zpregIndex) &
|
||||||
while (x > 0) {
|
MatchZpReg(4, zpregIndex) & MatchA(4)) ~~> (_ => List(AssemblyLine.implied(TAX))),
|
||||||
result += multiplier * (x % 16L)
|
(Elidable & HasOpcode(LDY) & RefersTo("__reg", zpregIndex) &
|
||||||
x /= 16L
|
MatchZpReg(4, zpregIndex) & MatchA(4)) ~~> (_ => List(AssemblyLine.implied(TAY))),
|
||||||
multiplier *= 10L
|
(Elidable & HasOpcode(LAX) & RefersTo("__reg", zpregIndex) &
|
||||||
}
|
MatchZpReg(4, zpregIndex) & MatchX(4)) ~~> (_ => List(AssemblyLine.implied(TXA))),
|
||||||
result
|
(Elidable & HasOpcode(LAX) & RefersTo("__reg", zpregIndex) &
|
||||||
}
|
MatchZpReg(4, zpregIndex) & MatchA(4)) ~~> (_ => List(AssemblyLine.implied(TAX))),
|
||||||
|
|
||||||
private def storeDecimalValueInNormalRespresentation(a: Long): Long = {
|
(Elidable & HasOpcode(ADC) & RefersTo("__reg", zpregIndex) &
|
||||||
if (a < 0) -storeDecimalValueInNormalRespresentation(-a)
|
MatchZpReg(5, zpregIndex) & MatchA(4) & HasClear(State.D) & HasClear(State.C) &
|
||||||
var x = a
|
DoesntMatterWhatItDoesWith(State.C, State.V)) ~~> { (code, ctx) =>
|
||||||
var result = 0L
|
val sum = ctx.get[Int](4) + ctx.get[Int](5)
|
||||||
var multiplier = 1L
|
List(AssemblyLine.immediate(LDA, sum & 0xff))
|
||||||
while (x > 0) {
|
},
|
||||||
result += multiplier * (x % 10L)
|
|
||||||
x /= 10L
|
|
||||||
multiplier *= 16L
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
private def asDecimal(a: Long, b: Long, f: (Long, Long) => Long): Long =
|
(Elidable & HasOpcode(SBC) & RefersTo("__reg", zpregIndex) &
|
||||||
storeDecimalValueInNormalRespresentation(f(parseNormalToDecimalValue(a), parseNormalToDecimalValue(b)))
|
MatchZpReg(5, zpregIndex) & MatchA(4) & HasClear(State.D) & HasSet(State.C) &
|
||||||
|
DoesntMatterWhatItDoesWith(State.C, State.V)) ~~> { (code, ctx) =>
|
||||||
|
val sum = ctx.get[Int](4) - ctx.get[Int](5)
|
||||||
|
List(AssemblyLine.immediate(LDA, sum & 0xff))
|
||||||
|
},
|
||||||
|
|
||||||
|
(Elidable & HasOpcode(AND) & RefersTo("__reg", zpregIndex) &
|
||||||
|
MatchZpReg(5, zpregIndex) & MatchA(4)) ~~> { (code, ctx) =>
|
||||||
|
val sum = ctx.get[Int](4) & ctx.get[Int](5)
|
||||||
|
List(AssemblyLine.immediate(LDA, sum & 0xff))
|
||||||
|
},
|
||||||
|
|
||||||
|
(Elidable & HasOpcode(ORA) & RefersTo("__reg", zpregIndex) &
|
||||||
|
MatchZpReg(5, zpregIndex) & MatchA(4)) ~~> { (code, ctx) =>
|
||||||
|
val sum = ctx.get[Int](4) | ctx.get[Int](5)
|
||||||
|
List(AssemblyLine.immediate(LDA, sum & 0xff))
|
||||||
|
},
|
||||||
|
|
||||||
|
(Elidable & HasOpcode(EOR) & RefersTo("__reg", zpregIndex) &
|
||||||
|
MatchZpReg(5, zpregIndex) & MatchA(4)) ~~> { (code, ctx) =>
|
||||||
|
val sum = ctx.get[Int](4) ^ ctx.get[Int](5)
|
||||||
|
List(AssemblyLine.immediate(LDA, sum & 0xff))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
val All: List[AssemblyOptimization[AssemblyLine]] = List(
|
val All: List[AssemblyOptimization[AssemblyLine]] = List(
|
||||||
ConstantDecimalMath,
|
ConstantDecimalMath,
|
||||||
ConstantMultiplication,
|
ConstantMultiplication,
|
||||||
DeadRegStore,
|
DeadRegStore,
|
||||||
DeadRegStoreFromFlow,
|
DeadRegStoreFromFlow,
|
||||||
|
PointlessLoad,
|
||||||
StashInRegInsteadOfStack,
|
StashInRegInsteadOfStack,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -93,6 +93,12 @@ object Status {
|
|||||||
case _ => AnyStatus
|
case _ => AnyStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def flatMap4[T, U, V, W, R](a: Status[T], b: Status[U], c: Status[V], d: Status[W])(f: (T, U, V, W) => Status[R]): Status[R] = (a, b, c, d) match {
|
||||||
|
case (SingleStatus(t), SingleStatus(u), SingleStatus(v), SingleStatus(w)) => f(t, u, v, w)
|
||||||
|
case (UnknownStatus, UnknownStatus, UnknownStatus, UnknownStatus) => UnknownStatus
|
||||||
|
case _ => AnyStatus
|
||||||
|
}
|
||||||
|
|
||||||
implicit class BoolStatusOps(val inner: Status[Boolean]) extends AnyVal {
|
implicit class BoolStatusOps(val inner: Status[Boolean]) extends AnyVal {
|
||||||
def withHiddenHi: Status[Boolean] = inner match {
|
def withHiddenHi: Status[Boolean] = inner match {
|
||||||
case SingleStatus(false) => inner
|
case SingleStatus(false) => inner
|
||||||
@ -187,28 +193,28 @@ object Status {
|
|||||||
case _ => AnyStatus
|
case _ => AnyStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
def adc(value: Int, carry: Status[Boolean], decimal: Status[Boolean]): Status[Int] = inner match {
|
def adc(value: Int, carry: Status[Boolean], decimal: Status[Boolean]): (Status[Int], Status[Boolean]) = inner match {
|
||||||
case SingleStatus(x) => decimal match {
|
case SingleStatus(x) => decimal match {
|
||||||
case SingleStatus(false) => carry match {
|
case SingleStatus(false) => carry match {
|
||||||
case SingleStatus(true) => SingleStatus((x + value + 1) & 0xff)
|
case SingleStatus(true) => SingleStatus((x + value + 1) & 0xff) -> SingleStatus((x.&(0xff) + value.&(0xff) + 1) > 0xff)
|
||||||
case SingleStatus(false) => SingleStatus((x + value) & 0xff)
|
case SingleStatus(false) => SingleStatus((x + value) & 0xff) -> SingleStatus((x.&(0xff) + value.&(0xff)) > 0xff)
|
||||||
case _ => AnyStatus
|
case _ => AnyStatus -> (if (value == 0) SingleFalse else AnyStatus)
|
||||||
}
|
}
|
||||||
case _ => AnyStatus
|
case _ => AnyStatus -> AnyStatus
|
||||||
}
|
}
|
||||||
case _ => AnyStatus
|
case _ => AnyStatus -> AnyStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
def sbc(value: Int, carry: Status[Boolean], decimal: Status[Boolean]): Status[Int] = inner match {
|
def sbc(value: Int, carry: Status[Boolean], decimal: Status[Boolean]): (Status[Int], Status[Boolean]) = inner match {
|
||||||
case SingleStatus(x) => decimal match {
|
case SingleStatus(x) => decimal match {
|
||||||
case SingleStatus(false) => carry match {
|
case SingleStatus(false) => carry match {
|
||||||
case SingleStatus(true) => SingleStatus((x - value) & 0xff)
|
case SingleStatus(true) => SingleStatus((x - value) & 0xff) -> SingleStatus((x.&(0xff) - value.&(0xff)) >= 0)
|
||||||
case SingleStatus(false) => SingleStatus((x - value - 1) & 0xff)
|
case SingleStatus(false) => SingleStatus((x - value - 1) & 0xff) -> SingleStatus((x.&(0xff) - value.&(0xff) - 1) >= 0)
|
||||||
case _ => AnyStatus
|
case _ => AnyStatus -> (if (value == 0) SingleTrue else AnyStatus)
|
||||||
}
|
}
|
||||||
case _ => AnyStatus
|
case _ => AnyStatus -> AnyStatus
|
||||||
}
|
}
|
||||||
case _ => AnyStatus
|
case _ => AnyStatus -> AnyStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
def adc_w(value: Int, carry: Status[Boolean], decimal: Status[Boolean]): Status[Int] = inner match {
|
def adc_w(value: Int, carry: Status[Boolean], decimal: Status[Boolean]): Status[Int] = inner match {
|
||||||
|
Loading…
Reference in New Issue
Block a user