remove last trace of getTempVar (arry index expression)

tiny optimization
This commit is contained in:
Irmen de Jong 2023-10-26 22:28:07 +02:00
parent 32becdbced
commit 0904712a00
9 changed files with 265 additions and 315 deletions

View File

@ -76,6 +76,13 @@ enum class RegisterOrPair {
companion object {
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) {

View File

@ -503,24 +503,18 @@ class AsmGen6502Internal (
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) {
when (register) {
CpuRegister.A -> out(" lda $indexName")
CpuRegister.X -> out(" ldx $indexName")
CpuRegister.Y -> out(" ldy $indexName")
}
assignExpressionToRegister(expr.index, RegisterOrPair.fromCpuRegister(register), false)
return
}
when (elementDt) {
in ByteDatatypes -> out(" ld$reg $indexName")
in ByteDatatypes -> {
assignExpressionToRegister(expr.index, RegisterOrPair.fromCpuRegister(register), false)
}
in WordDatatypes -> {
out(" lda $indexName | asl a")
assignExpressionToRegister(expr.index, RegisterOrPair.A, false)
out(" asl a")
when (register) {
CpuRegister.A -> {}
CpuRegister.X -> out(" tax")
@ -529,12 +523,13 @@ class AsmGen6502Internal (
}
DataType.FLOAT -> {
require(options.compTarget.memorySize(DataType.FLOAT) == 5) {"invalid float size ${expr.position}"}
assignExpressionToRegister(expr.index, RegisterOrPair.A, false)
out("""
lda $indexName
sta P8ZP_SCRATCH_REG
asl a
asl a
clc
adc $indexName"""
adc P8ZP_SCRATCH_REG"""
)
when (register) {
CpuRegister.A -> {}

View File

@ -205,239 +205,251 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
}
TargetStorageKind.ARRAY -> {
val indexNum = target.array!!.index as? PtNumber
val indexVar = target.array.index as? PtIdentifier
when {
indexNum!=null -> {
val targetVarName = if(target.array.splitWords)
"${target.asmVarname} + ${indexNum.number.toInt()}"
else
"${target.asmVarname} + ${indexNum.number.toInt()*program.memsizer.memorySize(target.datatype)}"
when (target.datatype) {
in ByteDatatypes -> {
when(value.kind) {
SourceStorageKind.LITERALNUMBER -> inplacemodificationByteVariableWithLiteralval(targetVarName, target.datatype, operator, value.number!!.number.toInt())
SourceStorageKind.VARIABLE -> inplacemodificationByteVariableWithVariable(targetVarName, target.datatype, operator, value.asmVarname)
SourceStorageKind.REGISTER -> inplacemodificationByteVariableWithVariable(targetVarName, target.datatype, operator, regName(value))
SourceStorageKind.MEMORY -> inplacemodificationByteVariableWithValue(targetVarName, target.datatype, operator, value.memory!!)
SourceStorageKind.ARRAY -> inplacemodificationByteVariableWithValue(targetVarName, target.datatype, operator, value.array!!)
SourceStorageKind.EXPRESSION -> {
if(value.expression is PtTypeCast) {
if (tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator)) return
inplacemodificationByteVariableWithValue(targetVarName, target.datatype, operator, value.expression)
} else {
inplacemodificationByteVariableWithValue(targetVarName, target.datatype, operator, value.expression!!)
}
if (indexNum!=null) {
val targetVarName = if(target.array.splitWords)
"${target.asmVarname} + ${indexNum.number.toInt()}"
else
"${target.asmVarname} + ${indexNum.number.toInt()*program.memsizer.memorySize(target.datatype)}"
when (target.datatype) {
in ByteDatatypes -> {
when(value.kind) {
SourceStorageKind.LITERALNUMBER -> inplacemodificationByteVariableWithLiteralval(targetVarName, target.datatype, operator, value.number!!.number.toInt())
SourceStorageKind.VARIABLE -> inplacemodificationByteVariableWithVariable(targetVarName, target.datatype, operator, value.asmVarname)
SourceStorageKind.REGISTER -> inplacemodificationByteVariableWithVariable(targetVarName, target.datatype, operator, regName(value))
SourceStorageKind.MEMORY -> inplacemodificationByteVariableWithValue(targetVarName, target.datatype, operator, value.memory!!)
SourceStorageKind.ARRAY -> inplacemodificationByteVariableWithValue(targetVarName, target.datatype, operator, value.array!!)
SourceStorageKind.EXPRESSION -> {
if(value.expression is PtTypeCast) {
if (tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator)) return
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) {
in ByteDatatypes -> {
if(value.kind==SourceStorageKind.EXPRESSION
&& value.expression is PtTypeCast
&& tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator))
return
asmgen.loadScaledArrayIndexIntoRegister(target.array, DataType.UBYTE, CpuRegister.Y)
asmgen.saveRegisterStack(CpuRegister.Y, false)
}
else {
when (target.datatype) {
in ByteDatatypes -> {
if(value.kind==SourceStorageKind.EXPRESSION
&& value.expression is PtTypeCast
&& tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator))
return
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")
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")
asmgen.out(" ldx ${target.array.variable.name}+1,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(" 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 -> {
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")
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")
}
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
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""")
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")
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")

View File

@ -4,8 +4,10 @@ import prog8.ast.IStatementContainer
import prog8.ast.Node
import prog8.ast.Program
import prog8.ast.base.FatalAstException
import prog8.ast.expressions.*
import prog8.ast.getTempVar
import prog8.ast.expressions.BinaryExpression
import prog8.ast.expressions.ContainmentCheck
import prog8.ast.expressions.IdentifierReference
import prog8.ast.expressions.NumericLiteral
import prog8.ast.statements.*
import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification
@ -155,35 +157,4 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
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
}
}

View File

@ -52,10 +52,6 @@ internal class StatementReorderer(
// 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'
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)
return noModifications // an initializer assignment for a vardecl is already here
val nextFor = decl.nextSibling() as? ForLoop

View File

@ -147,5 +147,18 @@ main {
compileText(C64Target(), 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
}
})

View File

@ -1,52 +1,9 @@
package prog8.ast
import prog8.ast.base.FatalAstException
import prog8.ast.expressions.BinaryExpression
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 ok(expr: Expression): Boolean {
return when(expr) {

View File

@ -178,8 +178,7 @@ enum class VarDeclOrigin {
USERCODE,
SUBROUTINEPARAM,
STRINGLITERAL,
ARRAYLITERAL,
AUTOGENERATED
ARRAYLITERAL
}
enum class VarDeclType {

View File

@ -54,6 +54,6 @@ main {
return 0
else if screenx>255+32
return 255
return lsb(screenx-32)
return lsb(screenx)-32
}
}