67 lines
1.2 KiB
Go
67 lines
1.2 KiB
Go
package optimizer
|
|
|
|
// passImmElimination removes redundant immediate loads.
|
|
// Pattern: lda #N; ... (no A modification) ...; lda #N → remove second
|
|
// Applies to A, X, Y.
|
|
func passImmElimination(lines []asmLine) []asmLine {
|
|
rs := newRegState()
|
|
var result []asmLine
|
|
|
|
for _, line := range lines {
|
|
if !line.isCode {
|
|
if line.optMarker {
|
|
continue
|
|
}
|
|
if line.isLabel {
|
|
rs.reset()
|
|
}
|
|
result = append(result, line)
|
|
continue
|
|
}
|
|
|
|
if isChainBreaker(line.opcode) {
|
|
rs.reset()
|
|
result = append(result, line)
|
|
continue
|
|
}
|
|
|
|
if isRedundantImm(line, rs) {
|
|
continue // remove line
|
|
}
|
|
|
|
updateRegState(line, rs)
|
|
result = append(result, line)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func isRedundantImm(line asmLine, rs *regState) bool {
|
|
switch line.opcode {
|
|
case "lda":
|
|
if isImmediate(line.operand) {
|
|
val := parseHexOrDec(line.operand[1:])
|
|
if rs.a.val == val {
|
|
return true
|
|
}
|
|
rs.loadImm("a", val)
|
|
}
|
|
case "ldx":
|
|
if isImmediate(line.operand) {
|
|
val := parseHexOrDec(line.operand[1:])
|
|
if rs.x.val == val {
|
|
return true
|
|
}
|
|
rs.loadImm("x", val)
|
|
}
|
|
case "ldy":
|
|
if isImmediate(line.operand) {
|
|
val := parseHexOrDec(line.operand[1:])
|
|
if rs.y.val == val {
|
|
return true
|
|
}
|
|
rs.loadImm("y", val)
|
|
}
|
|
}
|
|
return false
|
|
}
|