mirror of
https://github.com/irmen/prog8.git
synced 2025-01-26 19:30:59 +00:00
several optimizations and compiler error fix for @(&var) and @(&var+1)
This commit is contained in:
parent
00b0ec58b4
commit
31c132c2eb
@ -986,17 +986,17 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
} else {
|
||||
when(resultRegister) {
|
||||
null, RegisterOrPair.A -> {
|
||||
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY)
|
||||
asmgen.assignExpressionToRegister(arg, RegisterOrPair.AY)
|
||||
asmgen.out(" tya")
|
||||
}
|
||||
RegisterOrPair.X -> {
|
||||
asmgen.out(" pha")
|
||||
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AX)
|
||||
asmgen.assignExpressionToRegister(arg, RegisterOrPair.AX)
|
||||
asmgen.out(" pla")
|
||||
}
|
||||
RegisterOrPair.Y -> {
|
||||
asmgen.out(" pha")
|
||||
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY)
|
||||
asmgen.assignExpressionToRegister(arg, RegisterOrPair.AY)
|
||||
asmgen.out(" pla")
|
||||
}
|
||||
else -> throw AssemblyError("invalid reg")
|
||||
@ -1032,35 +1032,35 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
} else {
|
||||
when(resultRegister) {
|
||||
null, RegisterOrPair.A -> {
|
||||
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY)
|
||||
asmgen.assignExpressionToRegister(arg, RegisterOrPair.AY)
|
||||
// NOTE: we rely on the fact that the above assignment to AY, assigns the Lsb to A as the last instruction.
|
||||
// this is required because the compiler assumes the status bits are set according to what A is (lsb)
|
||||
// and will not generate another cmp when lsb() is directly used inside a comparison expression.
|
||||
}
|
||||
RegisterOrPair.X -> {
|
||||
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.XY)
|
||||
asmgen.assignExpressionToRegister(arg, RegisterOrPair.XY)
|
||||
// NOTE: we rely on the fact that the above assignment to XY, assigns the Lsb to X as the last instruction.
|
||||
// this is required because the compiler assumes the status bits are set according to what X is (lsb)
|
||||
// and will not generate another cmp when lsb() is directly used inside a comparison expression.
|
||||
}
|
||||
RegisterOrPair.Y -> {
|
||||
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY)
|
||||
asmgen.assignExpressionToRegister(arg, RegisterOrPair.AY)
|
||||
asmgen.out(" tay | cpy #0")
|
||||
}
|
||||
RegisterOrPair.AY -> {
|
||||
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY)
|
||||
asmgen.assignExpressionToRegister(arg, RegisterOrPair.AY)
|
||||
asmgen.out(" ldy #0 | cmp #0")
|
||||
}
|
||||
RegisterOrPair.AX -> {
|
||||
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AX)
|
||||
asmgen.assignExpressionToRegister(arg, RegisterOrPair.AX)
|
||||
asmgen.out(" ldx #0 | cmp #0")
|
||||
}
|
||||
RegisterOrPair.XY -> {
|
||||
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.XY)
|
||||
asmgen.assignExpressionToRegister(arg, RegisterOrPair.XY)
|
||||
asmgen.out(" ldy #0 | cpx #0")
|
||||
}
|
||||
in Cx16VirtualRegisters -> {
|
||||
asmgen.assignExpressionToRegister(fcall.args.single(), resultRegister)
|
||||
asmgen.assignExpressionToRegister(arg, resultRegister)
|
||||
val zero = PtNumber(DataType.UBYTE, 0.0, Position.DUMMY)
|
||||
zero.parent=fcall
|
||||
assignAsmGen.assignExpressionToVariable(zero, "cx16.${resultRegister.toString().lowercase()}H", DataType.UBYTE)
|
||||
|
@ -3592,6 +3592,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
private fun storeRegisterAInMemoryAddress(memoryAddress: PtMemoryByte) {
|
||||
val addressExpr = memoryAddress.address
|
||||
val addressLv = addressExpr as? PtNumber
|
||||
val addressOf = addressExpr as? PtAddressOf
|
||||
|
||||
fun storeViaExprEval() {
|
||||
when(addressExpr) {
|
||||
@ -3613,10 +3614,21 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
addressLv != null -> {
|
||||
asmgen.out(" sta ${addressLv.number.toHex()}")
|
||||
}
|
||||
addressOf != null -> {
|
||||
asmgen.out(" sta ${asmgen.asmSymbolName(addressOf.identifier)}")
|
||||
}
|
||||
addressExpr is PtIdentifier -> {
|
||||
asmgen.storeAIntoPointerVar(addressExpr)
|
||||
}
|
||||
addressExpr is PtBinaryExpression -> {
|
||||
if(addressExpr.operator=="+" || addressExpr.operator=="-") {
|
||||
val addrOf = addressExpr.left as? PtAddressOf
|
||||
val offset = (addressExpr.right as? PtNumber)?.number?.toInt()
|
||||
if(addrOf!=null && offset!=null) {
|
||||
asmgen.out(" sta ${asmgen.asmSymbolName(addrOf.identifier)}${addressExpr.operator}${offset}")
|
||||
return
|
||||
}
|
||||
}
|
||||
if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, addressExpr.operator, true))
|
||||
storeViaExprEval()
|
||||
}
|
||||
|
@ -19,12 +19,13 @@ import kotlin.math.floor
|
||||
class ConstantFoldingOptimizer(private val program: Program) : AstWalker() {
|
||||
|
||||
override fun before(memread: DirectMemoryRead, parent: Node): Iterable<IAstModification> {
|
||||
// @( &thing ) --> thing
|
||||
// @( &thing ) --> thing (but only if thing is a byte type!)
|
||||
val addrOf = memread.addressExpression as? AddressOf
|
||||
return if(addrOf!=null)
|
||||
listOf(IAstModification.ReplaceNode(memread, addrOf.identifier, parent))
|
||||
else
|
||||
noModifications
|
||||
if(addrOf!=null) {
|
||||
if(addrOf.identifier.inferType(program).isBytes)
|
||||
return listOf(IAstModification.ReplaceNode(memread, addrOf.identifier, parent))
|
||||
}
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun after(containment: ContainmentCheck, parent: Node): Iterable<IAstModification> {
|
||||
|
@ -24,6 +24,7 @@ internal class CodeDesugarer(val program: Program, private val errors: IErrorRep
|
||||
// - replace peek() and poke() by direct memory accesses.
|
||||
// - repeat-forever loops replaced by label+jump.
|
||||
// - pointer[word] replaced by @(pointer+word)
|
||||
// - @(&var) and @(&var+1) replaced by lsb(var) and msb(var) if var is a word
|
||||
|
||||
|
||||
override fun before(breakStmt: Break, parent: Node): Iterable<IAstModification> {
|
||||
@ -211,4 +212,28 @@ _after:
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun after(memread: DirectMemoryRead, parent: Node): Iterable<IAstModification> {
|
||||
// for word variables:
|
||||
// @(&var) --> lsb(var)
|
||||
// @(&var+1) --> msb(var)
|
||||
|
||||
val addrOf = memread.addressExpression as? AddressOf
|
||||
if(addrOf!=null && addrOf.identifier.inferType(program).isWords) {
|
||||
val lsb = FunctionCallExpression(IdentifierReference(listOf("lsb"), memread.position), mutableListOf(addrOf.identifier), memread.position)
|
||||
return listOf(IAstModification.ReplaceNode(memread, lsb, parent))
|
||||
}
|
||||
val expr = memread.addressExpression as? BinaryExpression
|
||||
if(expr!=null && expr.operator=="+") {
|
||||
val addressOf = expr.left as? AddressOf
|
||||
val offset = (expr.right as? NumericLiteral)?.number?.toInt()
|
||||
if(addressOf!=null && offset==1) {
|
||||
val msb = FunctionCallExpression(IdentifierReference(listOf("msb"), memread.position), mutableListOf(addressOf.identifier), memread.position)
|
||||
return listOf(IAstModification.ReplaceNode(memread, msb, parent))
|
||||
}
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,16 +1,22 @@
|
||||
%import textio
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
uword w1
|
||||
uword w2
|
||||
|
||||
sub start() {
|
||||
bool zz = (w1 & w2)==0
|
||||
uword zz = 0
|
||||
|
||||
if (w1 & w2)
|
||||
w1++
|
||||
|
||||
if not(w1 & w2)
|
||||
w1++
|
||||
@(&zz) = 1
|
||||
txt.print_uw(zz)
|
||||
txt.nl()
|
||||
@(&zz+1) = 2
|
||||
txt.print_uw(zz)
|
||||
txt.nl()
|
||||
ubyte bb
|
||||
bb = @(&zz)
|
||||
txt.print_ub(bb)
|
||||
txt.nl()
|
||||
bb = @(&zz+1)
|
||||
txt.print_ub(bb)
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user