several optimizations and compiler error fix for @(&var) and @(&var+1)

This commit is contained in:
Irmen de Jong 2023-09-14 23:04:23 +02:00
parent 00b0ec58b4
commit 31c132c2eb
5 changed files with 68 additions and 24 deletions

View File

@ -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)

View File

@ -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()
}

View File

@ -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> {

View File

@ -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
}
}

View File

@ -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()
}
}