mirror of
https://github.com/irmen/prog8.git
synced 2025-08-09 03:25:24 +00:00
remove last trace of getTempVar (arry index expression)
tiny optimization
This commit is contained in:
@@ -76,6 +76,13 @@ enum class RegisterOrPair {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val names by lazy { values().map { it.toString()} }
|
val names by lazy { values().map { it.toString()} }
|
||||||
|
fun fromCpuRegister(cpu: CpuRegister): RegisterOrPair {
|
||||||
|
return when(cpu) {
|
||||||
|
CpuRegister.A -> A
|
||||||
|
CpuRegister.X -> X
|
||||||
|
CpuRegister.Y -> Y
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun asCpuRegister(): CpuRegister = when(this) {
|
fun asCpuRegister(): CpuRegister = when(this) {
|
||||||
|
@@ -503,24 +503,18 @@ class AsmGen6502Internal (
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val indexVar = expr.index as? PtIdentifier
|
|
||||||
?: throw AssemblyError("array indexer should have been replaced with a temp var @ ${expr.index.position}")
|
|
||||||
|
|
||||||
val indexName = asmVariableName(indexVar)
|
|
||||||
|
|
||||||
if(expr.splitWords) {
|
if(expr.splitWords) {
|
||||||
when (register) {
|
assignExpressionToRegister(expr.index, RegisterOrPair.fromCpuRegister(register), false)
|
||||||
CpuRegister.A -> out(" lda $indexName")
|
|
||||||
CpuRegister.X -> out(" ldx $indexName")
|
|
||||||
CpuRegister.Y -> out(" ldy $indexName")
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
when (elementDt) {
|
when (elementDt) {
|
||||||
in ByteDatatypes -> out(" ld$reg $indexName")
|
in ByteDatatypes -> {
|
||||||
|
assignExpressionToRegister(expr.index, RegisterOrPair.fromCpuRegister(register), false)
|
||||||
|
}
|
||||||
in WordDatatypes -> {
|
in WordDatatypes -> {
|
||||||
out(" lda $indexName | asl a")
|
assignExpressionToRegister(expr.index, RegisterOrPair.A, false)
|
||||||
|
out(" asl a")
|
||||||
when (register) {
|
when (register) {
|
||||||
CpuRegister.A -> {}
|
CpuRegister.A -> {}
|
||||||
CpuRegister.X -> out(" tax")
|
CpuRegister.X -> out(" tax")
|
||||||
@@ -529,12 +523,13 @@ class AsmGen6502Internal (
|
|||||||
}
|
}
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> {
|
||||||
require(options.compTarget.memorySize(DataType.FLOAT) == 5) {"invalid float size ${expr.position}"}
|
require(options.compTarget.memorySize(DataType.FLOAT) == 5) {"invalid float size ${expr.position}"}
|
||||||
|
assignExpressionToRegister(expr.index, RegisterOrPair.A, false)
|
||||||
out("""
|
out("""
|
||||||
lda $indexName
|
sta P8ZP_SCRATCH_REG
|
||||||
asl a
|
asl a
|
||||||
asl a
|
asl a
|
||||||
clc
|
clc
|
||||||
adc $indexName"""
|
adc P8ZP_SCRATCH_REG"""
|
||||||
)
|
)
|
||||||
when (register) {
|
when (register) {
|
||||||
CpuRegister.A -> {}
|
CpuRegister.A -> {}
|
||||||
|
@@ -205,239 +205,251 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
TargetStorageKind.ARRAY -> {
|
TargetStorageKind.ARRAY -> {
|
||||||
val indexNum = target.array!!.index as? PtNumber
|
val indexNum = target.array!!.index as? PtNumber
|
||||||
val indexVar = target.array.index as? PtIdentifier
|
if (indexNum!=null) {
|
||||||
when {
|
val targetVarName = if(target.array.splitWords)
|
||||||
indexNum!=null -> {
|
"${target.asmVarname} + ${indexNum.number.toInt()}"
|
||||||
val targetVarName = if(target.array.splitWords)
|
else
|
||||||
"${target.asmVarname} + ${indexNum.number.toInt()}"
|
"${target.asmVarname} + ${indexNum.number.toInt()*program.memsizer.memorySize(target.datatype)}"
|
||||||
else
|
when (target.datatype) {
|
||||||
"${target.asmVarname} + ${indexNum.number.toInt()*program.memsizer.memorySize(target.datatype)}"
|
in ByteDatatypes -> {
|
||||||
when (target.datatype) {
|
when(value.kind) {
|
||||||
in ByteDatatypes -> {
|
SourceStorageKind.LITERALNUMBER -> inplacemodificationByteVariableWithLiteralval(targetVarName, target.datatype, operator, value.number!!.number.toInt())
|
||||||
when(value.kind) {
|
SourceStorageKind.VARIABLE -> inplacemodificationByteVariableWithVariable(targetVarName, target.datatype, operator, value.asmVarname)
|
||||||
SourceStorageKind.LITERALNUMBER -> inplacemodificationByteVariableWithLiteralval(targetVarName, target.datatype, operator, value.number!!.number.toInt())
|
SourceStorageKind.REGISTER -> inplacemodificationByteVariableWithVariable(targetVarName, target.datatype, operator, regName(value))
|
||||||
SourceStorageKind.VARIABLE -> inplacemodificationByteVariableWithVariable(targetVarName, target.datatype, operator, value.asmVarname)
|
SourceStorageKind.MEMORY -> inplacemodificationByteVariableWithValue(targetVarName, target.datatype, operator, value.memory!!)
|
||||||
SourceStorageKind.REGISTER -> inplacemodificationByteVariableWithVariable(targetVarName, target.datatype, operator, regName(value))
|
SourceStorageKind.ARRAY -> inplacemodificationByteVariableWithValue(targetVarName, target.datatype, operator, value.array!!)
|
||||||
SourceStorageKind.MEMORY -> inplacemodificationByteVariableWithValue(targetVarName, target.datatype, operator, value.memory!!)
|
SourceStorageKind.EXPRESSION -> {
|
||||||
SourceStorageKind.ARRAY -> inplacemodificationByteVariableWithValue(targetVarName, target.datatype, operator, value.array!!)
|
if(value.expression is PtTypeCast) {
|
||||||
SourceStorageKind.EXPRESSION -> {
|
if (tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator)) return
|
||||||
if(value.expression is PtTypeCast) {
|
inplacemodificationByteVariableWithValue(targetVarName, target.datatype, operator, value.expression)
|
||||||
if (tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator)) return
|
} else {
|
||||||
inplacemodificationByteVariableWithValue(targetVarName, target.datatype, operator, value.expression)
|
inplacemodificationByteVariableWithValue(targetVarName, target.datatype, operator, value.expression!!)
|
||||||
} else {
|
|
||||||
inplacemodificationByteVariableWithValue(targetVarName, target.datatype, operator, value.expression!!)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
in WordDatatypes -> {
|
|
||||||
val block = target.origAstTarget?.definingBlock()
|
|
||||||
when(value.kind) {
|
|
||||||
SourceStorageKind.LITERALNUMBER -> inplacemodificationWordWithLiteralval(targetVarName, target.datatype, operator, value.number!!.number.toInt(), block)
|
|
||||||
SourceStorageKind.VARIABLE -> inplacemodificationWordWithVariable(targetVarName, target.datatype, operator, value.asmVarname, value.datatype, block)
|
|
||||||
SourceStorageKind.REGISTER -> inplacemodificationWordWithVariable(targetVarName, target.datatype, operator, regName(value), value.datatype, block)
|
|
||||||
SourceStorageKind.MEMORY -> inplacemodificationWordWithMemread(targetVarName, target.datatype, operator, value.memory!!)
|
|
||||||
SourceStorageKind.ARRAY -> inplacemodificationWordWithValue(targetVarName, target.datatype, operator, value.array!!, block)
|
|
||||||
SourceStorageKind.EXPRESSION -> {
|
|
||||||
if(value.expression is PtTypeCast) {
|
|
||||||
if (tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator)) return
|
|
||||||
inplacemodificationWordWithValue(targetVarName, target.datatype, operator, value.expression, block)
|
|
||||||
} else {
|
|
||||||
inplacemodificationWordWithValue(targetVarName, target.datatype, operator, value.expression!!, block)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DataType.FLOAT -> {
|
|
||||||
when(value.kind) {
|
|
||||||
SourceStorageKind.LITERALNUMBER -> inplacemodificationFloatWithLiteralval(targetVarName, operator, value.number!!.number)
|
|
||||||
SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(targetVarName, operator, value.asmVarname)
|
|
||||||
SourceStorageKind.REGISTER -> inplacemodificationFloatWithVariable(targetVarName, operator, regName(value))
|
|
||||||
SourceStorageKind.MEMORY -> TODO("memread into float array")
|
|
||||||
SourceStorageKind.ARRAY -> inplacemodificationFloatWithValue(targetVarName, operator, value.array!!)
|
|
||||||
SourceStorageKind.EXPRESSION -> {
|
|
||||||
if(value.expression is PtTypeCast) {
|
|
||||||
if (tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator)) return
|
|
||||||
inplacemodificationFloatWithValue(targetVarName, operator, value.expression)
|
|
||||||
} else {
|
|
||||||
inplacemodificationFloatWithValue(targetVarName, operator, value.expression!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> throw AssemblyError("weird type to do in-place modification on ${target.datatype}")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
in WordDatatypes -> {
|
||||||
|
val block = target.origAstTarget?.definingBlock()
|
||||||
|
when(value.kind) {
|
||||||
|
SourceStorageKind.LITERALNUMBER -> inplacemodificationWordWithLiteralval(targetVarName, target.datatype, operator, value.number!!.number.toInt(), block)
|
||||||
|
SourceStorageKind.VARIABLE -> inplacemodificationWordWithVariable(targetVarName, target.datatype, operator, value.asmVarname, value.datatype, block)
|
||||||
|
SourceStorageKind.REGISTER -> inplacemodificationWordWithVariable(targetVarName, target.datatype, operator, regName(value), value.datatype, block)
|
||||||
|
SourceStorageKind.MEMORY -> inplacemodificationWordWithMemread(targetVarName, target.datatype, operator, value.memory!!)
|
||||||
|
SourceStorageKind.ARRAY -> inplacemodificationWordWithValue(targetVarName, target.datatype, operator, value.array!!, block)
|
||||||
|
SourceStorageKind.EXPRESSION -> {
|
||||||
|
if(value.expression is PtTypeCast) {
|
||||||
|
if (tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator)) return
|
||||||
|
inplacemodificationWordWithValue(targetVarName, target.datatype, operator, value.expression, block)
|
||||||
|
} else {
|
||||||
|
inplacemodificationWordWithValue(targetVarName, target.datatype, operator, value.expression!!, block)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataType.FLOAT -> {
|
||||||
|
when(value.kind) {
|
||||||
|
SourceStorageKind.LITERALNUMBER -> inplacemodificationFloatWithLiteralval(targetVarName, operator, value.number!!.number)
|
||||||
|
SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(targetVarName, operator, value.asmVarname)
|
||||||
|
SourceStorageKind.REGISTER -> inplacemodificationFloatWithVariable(targetVarName, operator, regName(value))
|
||||||
|
SourceStorageKind.MEMORY -> TODO("memread into float array")
|
||||||
|
SourceStorageKind.ARRAY -> inplacemodificationFloatWithValue(targetVarName, operator, value.array!!)
|
||||||
|
SourceStorageKind.EXPRESSION -> {
|
||||||
|
if(value.expression is PtTypeCast) {
|
||||||
|
if (tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator)) return
|
||||||
|
inplacemodificationFloatWithValue(targetVarName, operator, value.expression)
|
||||||
|
} else {
|
||||||
|
inplacemodificationFloatWithValue(targetVarName, operator, value.expression!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> throw AssemblyError("weird type to do in-place modification on ${target.datatype}")
|
||||||
}
|
}
|
||||||
indexVar!=null -> {
|
}
|
||||||
when (target.datatype) {
|
else {
|
||||||
in ByteDatatypes -> {
|
when (target.datatype) {
|
||||||
if(value.kind==SourceStorageKind.EXPRESSION
|
in ByteDatatypes -> {
|
||||||
&& value.expression is PtTypeCast
|
if(value.kind==SourceStorageKind.EXPRESSION
|
||||||
&& tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator))
|
&& value.expression is PtTypeCast
|
||||||
return
|
&& tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator))
|
||||||
asmgen.loadScaledArrayIndexIntoRegister(target.array, DataType.UBYTE, CpuRegister.Y)
|
return
|
||||||
asmgen.saveRegisterStack(CpuRegister.Y, false)
|
asmgen.loadScaledArrayIndexIntoRegister(target.array, DataType.UBYTE, CpuRegister.Y)
|
||||||
|
asmgen.saveRegisterStack(CpuRegister.Y, false)
|
||||||
|
asmgen.out(" lda ${target.array.variable.name},y")
|
||||||
|
when(value.kind) {
|
||||||
|
SourceStorageKind.LITERALNUMBER -> {
|
||||||
|
inplacemodificationRegisterAwithVariable(operator, "#${value.number!!.number.toInt()}", target.datatype in SignedDatatypes)
|
||||||
|
asmgen.restoreRegisterStack(CpuRegister.Y, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceStorageKind.VARIABLE -> {
|
||||||
|
inplacemodificationRegisterAwithVariable(operator, value.asmVarname, target.datatype in SignedDatatypes)
|
||||||
|
asmgen.restoreRegisterStack(CpuRegister.Y, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceStorageKind.REGISTER -> {
|
||||||
|
inplacemodificationRegisterAwithVariable(operator, regName(value), target.datatype in SignedDatatypes)
|
||||||
|
asmgen.restoreRegisterStack(CpuRegister.Y, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceStorageKind.MEMORY -> {
|
||||||
|
asmgen.out(" sta P8ZP_SCRATCH_B1")
|
||||||
|
inplacemodificationByteVariableWithValue("P8ZP_SCRATCH_B1", target.datatype, operator, value.memory!!)
|
||||||
|
asmgen.restoreRegisterStack(CpuRegister.Y, false)
|
||||||
|
asmgen.out(" lda P8ZP_SCRATCH_B1")
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceStorageKind.ARRAY -> {
|
||||||
|
asmgen.out(" sta P8ZP_SCRATCH_B1")
|
||||||
|
inplacemodificationByteVariableWithValue("P8ZP_SCRATCH_B1", target.datatype, operator, value.array!!)
|
||||||
|
asmgen.restoreRegisterStack(CpuRegister.Y, false)
|
||||||
|
asmgen.out(" lda P8ZP_SCRATCH_B1")
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceStorageKind.EXPRESSION -> {
|
||||||
|
asmgen.out(" sta P8ZP_SCRATCH_B1")
|
||||||
|
if(value.expression is PtTypeCast)
|
||||||
|
inplacemodificationByteVariableWithValue("P8ZP_SCRATCH_B1", target.datatype, operator, value.expression)
|
||||||
|
else
|
||||||
|
inplacemodificationByteVariableWithValue("P8ZP_SCRATCH_B1", target.datatype, operator, value.expression!!)
|
||||||
|
asmgen.restoreRegisterStack(CpuRegister.Y, false)
|
||||||
|
asmgen.out(" lda P8ZP_SCRATCH_B1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
asmgen.out(" sta ${target.array.variable.name},y")
|
||||||
|
}
|
||||||
|
|
||||||
|
in WordDatatypes -> {
|
||||||
|
if(value.kind==SourceStorageKind.EXPRESSION
|
||||||
|
&& value.expression is PtTypeCast
|
||||||
|
&& tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator))
|
||||||
|
return
|
||||||
|
asmgen.loadScaledArrayIndexIntoRegister(target.array, DataType.UWORD, CpuRegister.Y)
|
||||||
|
asmgen.saveRegisterStack(CpuRegister.Y, false)
|
||||||
|
if(target.array.splitWords) {
|
||||||
|
asmgen.out(" lda ${target.array.variable.name}_lsb,y")
|
||||||
|
asmgen.out(" ldx ${target.array.variable.name}_msb,y")
|
||||||
|
} else {
|
||||||
asmgen.out(" lda ${target.array.variable.name},y")
|
asmgen.out(" lda ${target.array.variable.name},y")
|
||||||
when(value.kind) {
|
asmgen.out(" ldx ${target.array.variable.name}+1,y")
|
||||||
SourceStorageKind.LITERALNUMBER -> {
|
|
||||||
inplacemodificationRegisterAwithVariable(operator, "#${value.number!!.number.toInt()}", target.datatype in SignedDatatypes)
|
|
||||||
asmgen.restoreRegisterStack(CpuRegister.Y, true)
|
|
||||||
}
|
|
||||||
SourceStorageKind.VARIABLE -> {
|
|
||||||
inplacemodificationRegisterAwithVariable(operator, value.asmVarname, target.datatype in SignedDatatypes)
|
|
||||||
asmgen.restoreRegisterStack(CpuRegister.Y, true)
|
|
||||||
}
|
|
||||||
SourceStorageKind.REGISTER -> {
|
|
||||||
inplacemodificationRegisterAwithVariable(operator, regName(value), target.datatype in SignedDatatypes)
|
|
||||||
asmgen.restoreRegisterStack(CpuRegister.Y, true)
|
|
||||||
}
|
|
||||||
SourceStorageKind.MEMORY -> {
|
|
||||||
asmgen.out(" sta P8ZP_SCRATCH_B1")
|
|
||||||
inplacemodificationByteVariableWithValue("P8ZP_SCRATCH_B1", target.datatype, operator, value.memory!!)
|
|
||||||
asmgen.restoreRegisterStack(CpuRegister.Y, false)
|
|
||||||
asmgen.out(" lda P8ZP_SCRATCH_B1")
|
|
||||||
}
|
|
||||||
SourceStorageKind.ARRAY -> {
|
|
||||||
asmgen.out(" sta P8ZP_SCRATCH_B1")
|
|
||||||
inplacemodificationByteVariableWithValue("P8ZP_SCRATCH_B1", target.datatype, operator, value.array!!)
|
|
||||||
asmgen.restoreRegisterStack(CpuRegister.Y, false)
|
|
||||||
asmgen.out(" lda P8ZP_SCRATCH_B1")
|
|
||||||
}
|
|
||||||
SourceStorageKind.EXPRESSION -> {
|
|
||||||
asmgen.out(" sta P8ZP_SCRATCH_B1")
|
|
||||||
if(value.expression is PtTypeCast)
|
|
||||||
inplacemodificationByteVariableWithValue("P8ZP_SCRATCH_B1", target.datatype, operator, value.expression)
|
|
||||||
else
|
|
||||||
inplacemodificationByteVariableWithValue("P8ZP_SCRATCH_B1", target.datatype, operator, value.expression!!)
|
|
||||||
asmgen.restoreRegisterStack(CpuRegister.Y, false)
|
|
||||||
asmgen.out(" lda P8ZP_SCRATCH_B1")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
asmgen.out(" sta ${target.array.variable.name},y")
|
|
||||||
}
|
}
|
||||||
in WordDatatypes -> {
|
val block = target.origAstTarget?.definingBlock()
|
||||||
if(value.kind==SourceStorageKind.EXPRESSION
|
when(value.kind) {
|
||||||
&& value.expression is PtTypeCast
|
SourceStorageKind.LITERALNUMBER -> {
|
||||||
&& tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator))
|
val number = value.number!!.number.toInt()
|
||||||
return
|
if(!inplacemodificationRegisterAXwithLiteralval(operator, number)) {
|
||||||
asmgen.loadScaledArrayIndexIntoRegister(target.array, DataType.UWORD, CpuRegister.Y)
|
|
||||||
asmgen.saveRegisterStack(CpuRegister.Y, false)
|
|
||||||
if(target.array.splitWords) {
|
|
||||||
asmgen.out(" lda ${target.array.variable.name}_lsb,y")
|
|
||||||
asmgen.out(" ldx ${target.array.variable.name}_msb,y")
|
|
||||||
} else {
|
|
||||||
asmgen.out(" lda ${target.array.variable.name},y")
|
|
||||||
asmgen.out(" ldx ${target.array.variable.name}+1,y")
|
|
||||||
}
|
|
||||||
val block = target.origAstTarget?.definingBlock()
|
|
||||||
when(value.kind) {
|
|
||||||
SourceStorageKind.LITERALNUMBER -> {
|
|
||||||
val number = value.number!!.number.toInt()
|
|
||||||
if(!inplacemodificationRegisterAXwithLiteralval(operator, number)) {
|
|
||||||
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
|
||||||
inplacemodificationWordWithLiteralval("P8ZP_SCRATCH_W1", target.datatype, operator, number, block)
|
|
||||||
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SourceStorageKind.VARIABLE -> {
|
|
||||||
if(!inplacemodificationRegisterAXwithVariable(
|
|
||||||
operator,
|
|
||||||
value.asmVarname,
|
|
||||||
value.datatype
|
|
||||||
)) {
|
|
||||||
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
|
||||||
inplacemodificationWordWithVariable("P8ZP_SCRATCH_W1", target.datatype, operator, value.asmVarname, value.datatype, block)
|
|
||||||
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SourceStorageKind.REGISTER -> {
|
|
||||||
if(!inplacemodificationRegisterAXwithVariable(
|
|
||||||
operator,
|
|
||||||
regName(value),
|
|
||||||
value.datatype
|
|
||||||
)) {
|
|
||||||
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
|
||||||
inplacemodificationWordWithVariable("P8ZP_SCRATCH_W1", target.datatype, operator, regName(value), value.datatype, block)
|
|
||||||
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SourceStorageKind.MEMORY -> {
|
|
||||||
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
||||||
inplacemodificationWordWithMemread("P8ZP_SCRATCH_W1", target.datatype, operator, value.memory!!)
|
inplacemodificationWordWithLiteralval("P8ZP_SCRATCH_W1", target.datatype, operator, number, block)
|
||||||
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
||||||
}
|
}
|
||||||
SourceStorageKind.ARRAY -> {
|
|
||||||
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
|
||||||
inplacemodificationWordWithValue("P8ZP_SCRATCH_W1", target.datatype, operator, value.array!!, block)
|
|
||||||
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
|
||||||
}
|
|
||||||
SourceStorageKind.EXPRESSION -> {
|
|
||||||
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
|
||||||
if(value.expression is PtTypeCast)
|
|
||||||
inplacemodificationWordWithValue("P8ZP_SCRATCH_W1", target.datatype, operator, value.expression, block)
|
|
||||||
else
|
|
||||||
inplacemodificationWordWithValue("P8ZP_SCRATCH_W1", target.datatype, operator, value.expression!!, block)
|
|
||||||
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
asmgen.restoreRegisterStack(CpuRegister.Y, true)
|
|
||||||
if(target.array.splitWords)
|
|
||||||
asmgen.out(" sta ${target.array.variable.name}_lsb,y | txa | sta ${target.array.variable.name}_msb,y")
|
|
||||||
else
|
|
||||||
asmgen.out(" sta ${target.array.variable.name},y | txa | sta ${target.array.variable.name}+1,y")
|
|
||||||
}
|
|
||||||
DataType.FLOAT -> {
|
|
||||||
// copy array value into tempvar
|
|
||||||
val tempvar = asmgen.getTempVarName(DataType.FLOAT)
|
|
||||||
asmgen.loadScaledArrayIndexIntoRegister(target.array, DataType.FLOAT, CpuRegister.A)
|
|
||||||
asmgen.out("""
|
|
||||||
ldy #>${target.asmVarname}
|
|
||||||
clc
|
|
||||||
adc #<${target.asmVarname}
|
|
||||||
bcc +
|
|
||||||
iny
|
|
||||||
+ sta P8ZP_SCRATCH_W1
|
|
||||||
sty P8ZP_SCRATCH_W1+1
|
|
||||||
pha ; save array ptr lsb
|
|
||||||
tya
|
|
||||||
pha ; save array ptr msb
|
|
||||||
lda #<$tempvar
|
|
||||||
ldy #>$tempvar
|
|
||||||
jsr floats.copy_float""")
|
|
||||||
|
|
||||||
// calculate on tempvar
|
|
||||||
when(value.kind) {
|
|
||||||
SourceStorageKind.LITERALNUMBER -> inplacemodificationFloatWithLiteralval(tempvar, operator, value.number!!.number)
|
|
||||||
SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(tempvar, operator, value.asmVarname)
|
|
||||||
SourceStorageKind.REGISTER -> inplacemodificationFloatWithVariable(tempvar, operator, regName(value))
|
|
||||||
SourceStorageKind.MEMORY -> TODO("memread into float")
|
|
||||||
SourceStorageKind.ARRAY -> inplacemodificationFloatWithValue(tempvar, operator, value.array!!)
|
|
||||||
SourceStorageKind.EXPRESSION -> {
|
|
||||||
if(value.expression is PtTypeCast) {
|
|
||||||
if (tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator))
|
|
||||||
return
|
|
||||||
inplacemodificationFloatWithValue(tempvar, operator, value.expression)
|
|
||||||
} else {
|
|
||||||
inplacemodificationFloatWithValue(tempvar, operator, value.expression!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy tempvar back into array
|
SourceStorageKind.VARIABLE -> {
|
||||||
asmgen.out("""
|
if(!inplacemodificationRegisterAXwithVariable(
|
||||||
lda #<$tempvar
|
operator,
|
||||||
ldy #>$tempvar
|
value.asmVarname,
|
||||||
sta P8ZP_SCRATCH_W1
|
value.datatype
|
||||||
sty P8ZP_SCRATCH_W1+1
|
)) {
|
||||||
pla ; restore array ptr msb
|
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
||||||
tay
|
inplacemodificationWordWithVariable("P8ZP_SCRATCH_W1", target.datatype, operator, value.asmVarname, value.datatype, block)
|
||||||
pla ; restore array ptr lsb
|
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
||||||
jsr floats.copy_float""")
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceStorageKind.REGISTER -> {
|
||||||
|
if(!inplacemodificationRegisterAXwithVariable(
|
||||||
|
operator,
|
||||||
|
regName(value),
|
||||||
|
value.datatype
|
||||||
|
)) {
|
||||||
|
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
||||||
|
inplacemodificationWordWithVariable("P8ZP_SCRATCH_W1", target.datatype, operator, regName(value), value.datatype, block)
|
||||||
|
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceStorageKind.MEMORY -> {
|
||||||
|
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
||||||
|
inplacemodificationWordWithMemread("P8ZP_SCRATCH_W1", target.datatype, operator, value.memory!!)
|
||||||
|
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceStorageKind.ARRAY -> {
|
||||||
|
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
||||||
|
inplacemodificationWordWithValue("P8ZP_SCRATCH_W1", target.datatype, operator, value.array!!, block)
|
||||||
|
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceStorageKind.EXPRESSION -> {
|
||||||
|
asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1")
|
||||||
|
if(value.expression is PtTypeCast)
|
||||||
|
inplacemodificationWordWithValue("P8ZP_SCRATCH_W1", target.datatype, operator, value.expression, block)
|
||||||
|
else
|
||||||
|
inplacemodificationWordWithValue("P8ZP_SCRATCH_W1", target.datatype, operator, value.expression!!, block)
|
||||||
|
asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("weird type to do in-place modification on ${target.datatype}")
|
asmgen.restoreRegisterStack(CpuRegister.Y, true)
|
||||||
|
if(target.array.splitWords)
|
||||||
|
asmgen.out(" sta ${target.array.variable.name}_lsb,y | txa | sta ${target.array.variable.name}_msb,y")
|
||||||
|
else
|
||||||
|
asmgen.out(" sta ${target.array.variable.name},y | txa | sta ${target.array.variable.name}+1,y")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DataType.FLOAT -> {
|
||||||
|
// copy array value into tempvar
|
||||||
|
val tempvar = asmgen.getTempVarName(DataType.FLOAT)
|
||||||
|
asmgen.loadScaledArrayIndexIntoRegister(target.array, DataType.FLOAT, CpuRegister.A)
|
||||||
|
asmgen.out("""
|
||||||
|
ldy #>${target.asmVarname}
|
||||||
|
clc
|
||||||
|
adc #<${target.asmVarname}
|
||||||
|
bcc +
|
||||||
|
iny
|
||||||
|
+ sta P8ZP_SCRATCH_W1
|
||||||
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
pha ; save array ptr lsb
|
||||||
|
tya
|
||||||
|
pha ; save array ptr msb
|
||||||
|
lda #<$tempvar
|
||||||
|
ldy #>$tempvar
|
||||||
|
jsr floats.copy_float""")
|
||||||
|
|
||||||
|
// calculate on tempvar
|
||||||
|
when(value.kind) {
|
||||||
|
SourceStorageKind.LITERALNUMBER -> inplacemodificationFloatWithLiteralval(tempvar, operator, value.number!!.number)
|
||||||
|
SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(tempvar, operator, value.asmVarname)
|
||||||
|
SourceStorageKind.REGISTER -> inplacemodificationFloatWithVariable(tempvar, operator, regName(value))
|
||||||
|
SourceStorageKind.MEMORY -> TODO("memread into float")
|
||||||
|
SourceStorageKind.ARRAY -> inplacemodificationFloatWithValue(tempvar, operator, value.array!!)
|
||||||
|
SourceStorageKind.EXPRESSION -> {
|
||||||
|
if(value.expression is PtTypeCast) {
|
||||||
|
if (tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator))
|
||||||
|
return
|
||||||
|
inplacemodificationFloatWithValue(tempvar, operator, value.expression)
|
||||||
|
} else {
|
||||||
|
inplacemodificationFloatWithValue(tempvar, operator, value.expression!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy tempvar back into array
|
||||||
|
asmgen.out("""
|
||||||
|
lda #<$tempvar
|
||||||
|
ldy #>$tempvar
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
pla ; restore array ptr msb
|
||||||
|
tay
|
||||||
|
pla ; restore array ptr lsb
|
||||||
|
jsr floats.copy_float""")
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> throw AssemblyError("weird type to do in-place modification on ${target.datatype}")
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("indexer expression should have been replaced by auto indexer var")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TargetStorageKind.REGISTER -> throw AssemblyError("no asm gen for reg in-place modification")
|
TargetStorageKind.REGISTER -> throw AssemblyError("no asm gen for reg in-place modification")
|
||||||
|
@@ -4,8 +4,10 @@ import prog8.ast.IStatementContainer
|
|||||||
import prog8.ast.Node
|
import prog8.ast.Node
|
||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
import prog8.ast.base.FatalAstException
|
import prog8.ast.base.FatalAstException
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.BinaryExpression
|
||||||
import prog8.ast.getTempVar
|
import prog8.ast.expressions.ContainmentCheck
|
||||||
|
import prog8.ast.expressions.IdentifierReference
|
||||||
|
import prog8.ast.expressions.NumericLiteral
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
import prog8.ast.walk.AstWalker
|
import prog8.ast.walk.AstWalker
|
||||||
import prog8.ast.walk.IAstModification
|
import prog8.ast.walk.IAstModification
|
||||||
@@ -155,35 +157,4 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
|
|||||||
|
|
||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> {
|
|
||||||
|
|
||||||
if(options.compTarget.name!=VMTarget.NAME) { // don't apply this optimization/check for Vm target
|
|
||||||
val index = arrayIndexedExpression.indexer.indexExpr
|
|
||||||
if (index !is NumericLiteral && index !is IdentifierReference) {
|
|
||||||
// replace complex indexing expression with a temp variable to hold the computed index first
|
|
||||||
return getAutoIndexerVarFor(arrayIndexedExpression)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return noModifications
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getAutoIndexerVarFor(expr: ArrayIndexedExpression): MutableList<IAstModification> {
|
|
||||||
val modifications = mutableListOf<IAstModification>()
|
|
||||||
val statement = expr.containingStatement
|
|
||||||
val dt = expr.indexer.indexExpr.inferType(program)
|
|
||||||
val (tempVarName, _) = program.getTempVar(dt.getOrElse { throw FatalAstException("invalid dt") })
|
|
||||||
val target = AssignTarget(IdentifierReference(tempVarName, expr.indexer.position), null, null, expr.indexer.position)
|
|
||||||
val assign = Assignment(target, expr.indexer.indexExpr, AssignmentOrigin.ASMGEN, expr.indexer.position)
|
|
||||||
modifications.add(IAstModification.InsertBefore(statement, assign, statement.parent as IStatementContainer))
|
|
||||||
modifications.add(
|
|
||||||
IAstModification.ReplaceNode(
|
|
||||||
expr.indexer.indexExpr,
|
|
||||||
target.identifier!!.copy(),
|
|
||||||
expr.indexer
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return modifications
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -52,10 +52,6 @@ internal class StatementReorderer(
|
|||||||
// This allows you to restart the program and have the same starting values of the variables
|
// This allows you to restart the program and have the same starting values of the variables
|
||||||
// So basically consider 'ubyte xx' as a short form for 'ubyte xx; xx=0'
|
// So basically consider 'ubyte xx' as a short form for 'ubyte xx; xx=0'
|
||||||
decl.value = null
|
decl.value = null
|
||||||
if(decl.name.startsWith("tempvar_") && decl.definingScope.name=="prog8_lib") {
|
|
||||||
// no need to zero out the special internal temporary variables.
|
|
||||||
return noModifications
|
|
||||||
}
|
|
||||||
if(decl.findInitializer(program)!=null)
|
if(decl.findInitializer(program)!=null)
|
||||||
return noModifications // an initializer assignment for a vardecl is already here
|
return noModifications // an initializer assignment for a vardecl is already here
|
||||||
val nextFor = decl.nextSibling() as? ForLoop
|
val nextFor = decl.nextSibling() as? ForLoop
|
||||||
|
@@ -147,5 +147,18 @@ main {
|
|||||||
compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null
|
compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null
|
||||||
compileText(VMTarget(), false, text, writeAssembly = true) shouldNotBe null
|
compileText(VMTarget(), false, text, writeAssembly = true) shouldNotBe null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("array target with expression for index") {
|
||||||
|
val text = """
|
||||||
|
main {
|
||||||
|
sub start() {
|
||||||
|
ubyte[] array = [1,2,3]
|
||||||
|
array[cx16.r0L+1] += 42
|
||||||
|
cx16.r0L = array[cx16.r0L+1]
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
compileText(VMTarget(), false, text, writeAssembly = true) shouldNotBe null
|
||||||
|
compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -1,52 +1,9 @@
|
|||||||
package prog8.ast
|
package prog8.ast
|
||||||
|
|
||||||
import prog8.ast.base.FatalAstException
|
|
||||||
import prog8.ast.expressions.BinaryExpression
|
import prog8.ast.expressions.BinaryExpression
|
||||||
import prog8.ast.expressions.Expression
|
import prog8.ast.expressions.Expression
|
||||||
import prog8.ast.statements.VarDecl
|
|
||||||
import prog8.ast.statements.VarDeclOrigin
|
|
||||||
import prog8.ast.statements.VarDeclType
|
|
||||||
import prog8.code.core.DataType
|
|
||||||
import prog8.code.core.Position
|
|
||||||
import prog8.code.core.ZeropageWish
|
|
||||||
|
|
||||||
|
|
||||||
fun Program.getTempVar(dt: DataType, altNames: Boolean=false): Pair<List<String>, VarDecl> {
|
|
||||||
val tmpvarName = if(altNames) {
|
|
||||||
when (dt) {
|
|
||||||
DataType.UBYTE, DataType.BOOL -> listOf("prog8_lib", "tempvar_ub2")
|
|
||||||
DataType.BYTE -> listOf("prog8_lib", "tempvar_b2")
|
|
||||||
DataType.UWORD -> listOf("prog8_lib", "tempvar_uw2")
|
|
||||||
DataType.WORD -> listOf("prog8_lib", "tempvar_w2")
|
|
||||||
DataType.FLOAT -> listOf("floats", "tempvar_swap_float2")
|
|
||||||
else -> throw FatalAstException("invalid dt")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
when (dt) {
|
|
||||||
DataType.UBYTE, DataType.BOOL -> listOf("prog8_lib", "tempvar_ub")
|
|
||||||
DataType.BYTE -> listOf("prog8_lib", "tempvar_b")
|
|
||||||
DataType.UWORD -> listOf("prog8_lib", "tempvar_uw")
|
|
||||||
DataType.WORD -> listOf("prog8_lib", "tempvar_w")
|
|
||||||
DataType.FLOAT -> listOf("floats", "tempvar_swap_float")
|
|
||||||
else -> throw FatalAstException("invalid dt")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val block = this.allBlocks.first { it.name==tmpvarName[0] }
|
|
||||||
val existingDecl = block.statements.firstOrNull { it is VarDecl && it.name == tmpvarName[1] }
|
|
||||||
if(existingDecl!=null)
|
|
||||||
return Pair(tmpvarName, existingDecl as VarDecl)
|
|
||||||
|
|
||||||
// add new temp variable to the ast directly (we can do this here because we're not iterating inside those container blocks)
|
|
||||||
val decl = VarDecl(
|
|
||||||
VarDeclType.VAR, VarDeclOrigin.AUTOGENERATED, dt, ZeropageWish.DONTCARE,
|
|
||||||
null, tmpvarName[1], null, isArray = false, sharedWithAsm = false, splitArray = false, position = Position.DUMMY
|
|
||||||
)
|
|
||||||
block.statements.add(decl)
|
|
||||||
decl.linkParents(block)
|
|
||||||
return Pair(tmpvarName, decl)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun maySwapOperandOrder(binexpr: BinaryExpression): Boolean {
|
fun maySwapOperandOrder(binexpr: BinaryExpression): Boolean {
|
||||||
fun ok(expr: Expression): Boolean {
|
fun ok(expr: Expression): Boolean {
|
||||||
return when(expr) {
|
return when(expr) {
|
||||||
|
@@ -178,8 +178,7 @@ enum class VarDeclOrigin {
|
|||||||
USERCODE,
|
USERCODE,
|
||||||
SUBROUTINEPARAM,
|
SUBROUTINEPARAM,
|
||||||
STRINGLITERAL,
|
STRINGLITERAL,
|
||||||
ARRAYLITERAL,
|
ARRAYLITERAL
|
||||||
AUTOGENERATED
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class VarDeclType {
|
enum class VarDeclType {
|
||||||
|
@@ -54,6 +54,6 @@ main {
|
|||||||
return 0
|
return 0
|
||||||
else if screenx>255+32
|
else if screenx>255+32
|
||||||
return 255
|
return 255
|
||||||
return lsb(screenx-32)
|
return lsb(screenx)-32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user