mirror of
https://github.com/irmen/prog8.git
synced 2026-04-21 17:16:33 +00:00
optimize some result register cases for peekw()
This commit is contained in:
@@ -2576,7 +2576,7 @@ $repeatLabel""")
|
||||
jsr floats.MOVFM""")
|
||||
}
|
||||
|
||||
internal fun loadIndirectWord(zpPtrVar: String, offset: UByte) {
|
||||
internal fun loadIndirectWordAY(zpPtrVar: String, offset: UByte) {
|
||||
// loads word pointed to by the ptr var into AY
|
||||
if (offset > 0u) {
|
||||
out("""
|
||||
@@ -2606,6 +2606,41 @@ $repeatLabel""")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun loadIndirectWordAX(zpPtrVar: String, offset: UByte) {
|
||||
// loads word pointed to by the ptr var into AX
|
||||
if (offset > 0u) {
|
||||
out("""
|
||||
ldy #$offset+1
|
||||
lda ($zpPtrVar),y
|
||||
tax
|
||||
dey
|
||||
lda ($zpPtrVar),y""")
|
||||
} else {
|
||||
if(isTargetCpu(CpuType.CPU65C02))
|
||||
out("""
|
||||
ldy #1
|
||||
lda ($zpPtrVar),y
|
||||
tax
|
||||
lda ($zpPtrVar)""")
|
||||
else
|
||||
out("""
|
||||
ldy #1
|
||||
lda ($zpPtrVar),y
|
||||
tax
|
||||
dey
|
||||
lda ($zpPtrVar),y""")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun loadIndirectWordIntoRegisters(zpPtrVar: String, offset: UByte, register: RegisterOrPair) {
|
||||
when(register) {
|
||||
RegisterOrPair.AY -> loadIndirectWordAY(zpPtrVar, offset)
|
||||
RegisterOrPair.AX -> loadIndirectWordAX(zpPtrVar, offset)
|
||||
RegisterOrPair.XY -> TODO("load into XY")
|
||||
else -> throw AssemblyError("invalid register for indirect load word $register")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun loadIndirectLongIntoCombinedLongRegister(zpPtrVar: String, offset: UByte, targetRegPair: RegisterOrPair) {
|
||||
val regstart = targetRegPair.startregname()
|
||||
out("""
|
||||
|
||||
@@ -1646,7 +1646,12 @@ import prog8.codegen.cpu6502.assignment.*
|
||||
is PtIdentifier -> {
|
||||
val varname = asmgen.asmVariableName(addrExpr)
|
||||
if(asmgen.isZpVar(addrExpr)) {
|
||||
asmgen.loadIndirectWord(varname, 0u)
|
||||
if(resultReg in arrayOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) {
|
||||
asmgen.loadIndirectWordIntoRegisters(varname, 0u, resultReg)
|
||||
return arrayOf(resultReg)
|
||||
} else {
|
||||
asmgen.loadIndirectWordAY(varname, 0u)
|
||||
}
|
||||
}
|
||||
else
|
||||
fallback()
|
||||
@@ -1659,25 +1664,70 @@ import prog8.codegen.cpu6502.assignment.*
|
||||
// can do (ZP),Y indexing
|
||||
val varname = asmgen.asmVariableName(pointer)
|
||||
asmgen.assignExpressionToRegister(result.second, RegisterOrPair.Y)
|
||||
asmgen.out("""
|
||||
lda ($varname),y
|
||||
tax
|
||||
iny
|
||||
lda ($varname),y
|
||||
tay
|
||||
txa""")
|
||||
when(resultReg) {
|
||||
RegisterOrPair.AX -> {
|
||||
asmgen.out("""
|
||||
iny
|
||||
lda ($varname),y
|
||||
tax
|
||||
dey
|
||||
lda ($varname),y""")
|
||||
return arrayOf(RegisterOrPair.AX)
|
||||
}
|
||||
RegisterOrPair.AY -> {
|
||||
asmgen.out("""
|
||||
lda ($varname),y
|
||||
tax
|
||||
iny
|
||||
lda ($varname),y
|
||||
tay
|
||||
txa""")
|
||||
return arrayOf(RegisterOrPair.AY)
|
||||
}
|
||||
RegisterOrPair.XY -> TODO("peekw into xy ${fcall.position}")
|
||||
else -> throw AssemblyError("invalid register for indirect load word $resultReg ${fcall.position}")
|
||||
}
|
||||
} else if(addressOfIdentifier!=null && (addressOfIdentifier.type.isWord || addressOfIdentifier.type.isPointer || addressOfIdentifier.type.isByteArray)) {
|
||||
val varname = asmgen.asmVariableName(addressOfIdentifier)
|
||||
if(result.second is PtNumber) {
|
||||
val offset = (result.second as PtNumber).number.toInt()
|
||||
asmgen.out(" lda $varname+$offset | ldy $varname+${offset + 1}")
|
||||
when(resultReg) {
|
||||
RegisterOrPair.AX -> asmgen.out(" lda $varname+$offset | ldx $varname+${offset + 1}")
|
||||
RegisterOrPair.AY -> asmgen.out(" lda $varname+$offset | ldy $varname+${offset + 1}")
|
||||
RegisterOrPair.XY -> asmgen.out(" ldx $varname+$offset | ldy $varname+${offset + 1}")
|
||||
else -> throw AssemblyError("peekw must have result in AX, AY or XY ${fcall.position}")
|
||||
}
|
||||
} else if(result.second is PtIdentifier) {
|
||||
val offsetname = asmgen.asmVariableName(result.second as PtIdentifier)
|
||||
asmgen.out("""
|
||||
ldx $offsetname
|
||||
lda $varname+1,x
|
||||
tay
|
||||
lda $varname,x""")
|
||||
when(resultReg) {
|
||||
RegisterOrPair.AX -> {
|
||||
asmgen.out("""
|
||||
ldy $offsetname
|
||||
lda $varname+1,y
|
||||
tax
|
||||
lda $varname,y""")
|
||||
return arrayOf(RegisterOrPair.AX)
|
||||
}
|
||||
RegisterOrPair.AY -> {
|
||||
asmgen.out("""
|
||||
ldx $offsetname
|
||||
lda $varname+1,x
|
||||
tay
|
||||
lda $varname,x""")
|
||||
return arrayOf(RegisterOrPair.AY)
|
||||
}
|
||||
RegisterOrPair.XY -> {
|
||||
asmgen.out("""
|
||||
ldx $offsetname
|
||||
lda $varname+1,x
|
||||
tay
|
||||
lda $varname,x
|
||||
tax""")
|
||||
return arrayOf(RegisterOrPair.XY)
|
||||
}
|
||||
else -> throw AssemblyError("peekw must have result in AX, AY or XY ${fcall.position}")
|
||||
}
|
||||
// TODO load directly into other registers
|
||||
} else fallback()
|
||||
} else if(addrExpr.operator=="+" && addrExpr.left is PtIdentifier) {
|
||||
readValueFromPointerPlusOffset(addrExpr.left as PtIdentifier, addrExpr.right, BaseDataType.UWORD)
|
||||
@@ -2072,7 +2122,15 @@ import prog8.codegen.cpu6502.assignment.*
|
||||
else -> throw AssemblyError("invalid register for lsb: $resultReg")
|
||||
}
|
||||
} else {
|
||||
if(arg is PtArrayIndexer) {
|
||||
if(fromLong) {
|
||||
asmgen.assignExpressionToRegister(arg, RegisterOrPair.R14R15, arg.type.isSigned)
|
||||
when(resultReg) {
|
||||
RegisterOrPair.A -> asmgen.out(" lda cx16.r14")
|
||||
RegisterOrPair.X -> asmgen.out(" ldx cx16.r14")
|
||||
RegisterOrPair.Y -> asmgen.out(" ldy cx16.r14")
|
||||
else -> throw AssemblyError("invalid register for lsb: $resultReg")
|
||||
}
|
||||
} else if(arg is PtArrayIndexer) {
|
||||
// just read the lsb byte out of the word array
|
||||
if(arg.variable==null)
|
||||
TODO("support for ptr indexing ${arg.position}")
|
||||
@@ -2094,19 +2152,19 @@ import prog8.codegen.cpu6502.assignment.*
|
||||
}
|
||||
else -> throw AssemblyError("invalid register for lsb: $resultReg")
|
||||
}
|
||||
} else if(fromLong) {
|
||||
asmgen.assignExpressionToRegister(arg, RegisterOrPair.R14R15, arg.type.isSigned)
|
||||
when(resultReg) {
|
||||
RegisterOrPair.A -> asmgen.out(" lda cx16.r14")
|
||||
RegisterOrPair.X -> asmgen.out(" ldx cx16.r14")
|
||||
RegisterOrPair.Y -> asmgen.out(" ldy cx16.r14")
|
||||
else -> throw AssemblyError("invalid register for lsb: $resultReg")
|
||||
}
|
||||
} else {
|
||||
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.
|
||||
when(resultReg) {
|
||||
RegisterOrPair.A -> asmgen.assignExpressionToRegister(arg, RegisterOrPair.AY)
|
||||
RegisterOrPair.X -> asmgen.assignExpressionToRegister(arg, RegisterOrPair.XY)
|
||||
RegisterOrPair.Y -> {
|
||||
asmgen.assignExpressionToRegister(arg, RegisterOrPair.AY)
|
||||
asmgen.out(" tay")
|
||||
}
|
||||
else -> throw AssemblyError("invalid register for lsb: $resultReg")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -548,8 +548,12 @@ internal class AssignmentAsmGen(
|
||||
asmgen.assignRegister(RegisterOrPair.A, assign.target)
|
||||
}
|
||||
dt.isWord ||dt.isPointer -> {
|
||||
asmgen.loadIndirectWord(zpPtrVar, offset)
|
||||
asmgen.assignRegister(RegisterOrPair.AY, assign.target)
|
||||
if(assign.target.register in arrayOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) {
|
||||
asmgen.loadIndirectWordIntoRegisters(zpPtrVar, offset, assign.target.register!!)
|
||||
} else {
|
||||
asmgen.loadIndirectWordAY(zpPtrVar, offset)
|
||||
asmgen.assignRegister(RegisterOrPair.AY, assign.target)
|
||||
}
|
||||
}
|
||||
dt.isFloat -> {
|
||||
asmgen.loadIndirectFloat(zpPtrVar, offset)
|
||||
|
||||
@@ -248,8 +248,12 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
asmgen.assignRegister(RegisterOrPair.A, target)
|
||||
}
|
||||
else if(value.type.isWord || value.type.isPointer) {
|
||||
asmgen.loadIndirectWord(zpPtrVar, offset)
|
||||
asmgen.assignRegister(RegisterOrPair.AY, target)
|
||||
if(target.register in arrayOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) {
|
||||
asmgen.loadIndirectWordIntoRegisters(zpPtrVar, offset, target.register!!)
|
||||
} else {
|
||||
asmgen.loadIndirectWordAY(zpPtrVar, offset)
|
||||
asmgen.assignRegister(RegisterOrPair.AY, target)
|
||||
}
|
||||
}
|
||||
else if(value.type.isFloat) {
|
||||
asmgen.loadIndirectFloat(zpPtrVar, offset)
|
||||
@@ -1738,7 +1742,7 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
|
||||
fun multiply() {
|
||||
// on entry here: number placed in routine argument variable
|
||||
asmgen.loadIndirectWord(zpPtrVar, 0u)
|
||||
asmgen.loadIndirectWordAY(zpPtrVar, 0u)
|
||||
asmgen.out("""
|
||||
jsr prog8_math.multiply_words
|
||||
tax
|
||||
@@ -1807,7 +1811,7 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
val number = value.number!!.number.toInt()
|
||||
if(number in powersOfTwoInt)
|
||||
throw AssemblyError("divide by power of two should have been a shift $value.position")
|
||||
asmgen.loadIndirectWord(zpPtrVar, 0u)
|
||||
asmgen.loadIndirectWordAY(zpPtrVar, 0u)
|
||||
asmgen.out("""
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
@@ -1818,7 +1822,7 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
SourceStorageKind.VARIABLE -> {
|
||||
require(value.datatype.isWord)
|
||||
val varname = value.asmVarname
|
||||
asmgen.loadIndirectWord(zpPtrVar, 0u)
|
||||
asmgen.loadIndirectWordAY(zpPtrVar, 0u)
|
||||
asmgen.out("""
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
@@ -1830,7 +1834,7 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
val register = value.register!!
|
||||
require(register.isWord())
|
||||
val regname = asmgen.asmSymbolName(register)
|
||||
asmgen.loadIndirectWord(zpPtrVar, 0u)
|
||||
asmgen.loadIndirectWordAY(zpPtrVar, 0u)
|
||||
asmgen.out("""
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
@@ -1839,7 +1843,7 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
divide(target.dt.isSigned)
|
||||
}
|
||||
SourceStorageKind.EXPRESSION -> {
|
||||
asmgen.loadIndirectWord(zpPtrVar, 0u)
|
||||
asmgen.loadIndirectWordAY(zpPtrVar, 0u)
|
||||
asmgen.out(" sta P8ZP_SCRATCH_W1 | sty P8ZP_SCRATCH_W1+1")
|
||||
asmgen.assignExpressionToRegister(value.expression!!, RegisterOrPair.AY)
|
||||
divide(target.dt.isSigned)
|
||||
@@ -1869,7 +1873,7 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
val number = value.number!!.number.toInt()
|
||||
if(number in powersOfTwoInt)
|
||||
throw AssemblyError("divide by power of two should have been a shift $value.position")
|
||||
asmgen.loadIndirectWord(zpPtrVar, 0u)
|
||||
asmgen.loadIndirectWordAY(zpPtrVar, 0u)
|
||||
asmgen.out("""
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
@@ -1880,7 +1884,7 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
SourceStorageKind.VARIABLE -> {
|
||||
require(value.datatype.isWord)
|
||||
val varname = value.asmVarname
|
||||
asmgen.loadIndirectWord(zpPtrVar, 0u)
|
||||
asmgen.loadIndirectWordAY(zpPtrVar, 0u)
|
||||
asmgen.out("""
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
@@ -1892,7 +1896,7 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
val register = value.register!!
|
||||
require(register.isWord())
|
||||
val regname = asmgen.asmSymbolName(register)
|
||||
asmgen.loadIndirectWord(zpPtrVar, 0u)
|
||||
asmgen.loadIndirectWordAY(zpPtrVar, 0u)
|
||||
asmgen.out("""
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
@@ -1901,7 +1905,7 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
modulus()
|
||||
}
|
||||
SourceStorageKind.EXPRESSION -> {
|
||||
asmgen.loadIndirectWord(zpPtrVar, 0u)
|
||||
asmgen.loadIndirectWordAY(zpPtrVar, 0u)
|
||||
asmgen.out(" sta P8ZP_SCRATCH_W1 | sty P8ZP_SCRATCH_W1+1")
|
||||
asmgen.assignExpressionToRegister(value.expression!!, RegisterOrPair.AY)
|
||||
modulus()
|
||||
|
||||
Reference in New Issue
Block a user