1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-06-25 19:29:49 +00:00

6502: fix invalid short jumps

This commit is contained in:
Karol Stasiak 2019-07-19 15:45:57 +02:00
parent 20f4baf2b2
commit 09f5ab269d
2 changed files with 37 additions and 29 deletions

View File

@ -2,12 +2,11 @@ package millfork.assembly.mos.opt
import java.util.concurrent.atomic.AtomicInteger
import millfork.assembly.mos.{AddrMode, AssemblyLine, AssemblyLine0, Opcode}
import millfork.assembly.mos.Opcode._
import millfork.env.{Label, MemoryAddressConstant, NormalFunction}
import millfork.error.ConsoleLogger
import millfork.CompilationOptions
import millfork.assembly.Elidability
import millfork.assembly.mos.Opcode._
import millfork.assembly.mos.{AddrMode, AssemblyLine, AssemblyLine0, Opcode}
import millfork.env.{Label, MemoryAddressConstant, NormalFunction, ThingInMemory}
/**
* @author Karol Stasiak
@ -46,32 +45,41 @@ object JumpFixing {
case _ => None
}.toMap
var changed = false
def makeLong(line: AssemblyLine) = {
changed = true
val op = line.opcode
val long: List[AssemblyLine] = op match {
case BRA => List(line.copy(opcode = JMP, addrMode = AddrMode.Absolute))
case BSR => List(line.copy(opcode = JSR, addrMode = AddrMode.Absolute))
case _ =>
val label = generateNextLabel()
List(
AssemblyLine.relative(negate(op), label),
line.copy(opcode = JMP, addrMode = AddrMode.Absolute),
AssemblyLine.label(label)
)
}
options.log.debug("Changing branch from short to long")
if (options.log.traceEnabled) {
options.log.trace(line.toString)
options.log.trace(" ↓")
long.foreach(l => options.log.trace(l.toString))
}
long
}
val result = code.zipWithIndex.flatMap {
case (line@AssemblyLine(op, AddrMode.Relative, MemoryAddressConstant(Label(label)), Elidability.Elidable, _), ix) =>
labelOffsets.get(label).fold(List(line)) { labelOffset =>
val thisOffset = offsets(ix)
if (invalidShortJump(thisOffset, labelOffset)) {
changed = true
val long: List[AssemblyLine] = op match {
case BRA => List(line.copy(opcode = JMP, addrMode = AddrMode.Absolute))
case BSR => List(line.copy(opcode = JSR, addrMode = AddrMode.Absolute))
case _ =>
val label = generateNextLabel()
List(
AssemblyLine.relative(negate(op), label),
line.copy(opcode = JMP, addrMode = AddrMode.Absolute),
AssemblyLine.label(label)
)
}
options.log.debug("Changing branch from short to long")
if (options.log.traceEnabled) {
options.log.trace(line.toString)
options.log.trace(" ↓")
long.foreach(l => options.log.trace(l.toString))
}
long
} else List(line)
case (line@AssemblyLine(_, AddrMode.Relative, MemoryAddressConstant(th: ThingInMemory), Elidability.Elidable, _), ix) =>
labelOffsets.get(th.name) match {
case None => makeLong(line)
case Some(labelOffset) =>
val thisOffset = offsets(ix)
if (invalidShortJump(thisOffset, labelOffset)) makeLong(line)
else List(line)
}
case (line@AssemblyLine(_, AddrMode.Relative, _, Elidability.Elidable, _), _) =>
makeLong(line)
case (line, _) => List(line)
}
if (changed) apply(f, result, options) else result

View File

@ -92,7 +92,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
case AssertByte(inner) =>
val value = deepConstResolve(inner)
if (value.toByte == value) value else {
log.error("Invalid relative jump: " + c)
log.error("Invalid relative jump: " + c + " calculated offset: " + value)
-2 // spin
}
case MemoryAddressConstant(th) =>