fix postincrdecr on array value

This commit is contained in:
Irmen de Jong 2020-08-23 18:32:53 +02:00
parent 3991d23a69
commit 93b2ff2e52
4 changed files with 89 additions and 91 deletions

View File

@ -8,7 +8,6 @@ import prog8.ast.base.*
import prog8.ast.expressions.*
import prog8.ast.statements.*
import prog8.compiler.*
import prog8.compiler.target.CompilationTarget
import prog8.compiler.target.IAssemblyGenerator
import prog8.compiler.target.IAssemblyProgram
import prog8.compiler.target.c64.AssemblyProgram
@ -583,20 +582,6 @@ internal class AsmGen(private val program: Program,
}
}
internal fun loadUnscaledArrayIndexIntoA(expr: ArrayIndexedExpression) {
when (val index = expr.arrayspec.index) {
is NumericLiteralValue -> throw AssemblyError("constant array index should be optimized earlier")
is IdentifierReference -> {
val indexName = asmIdentifierName(index)
out(" lda $indexName")
}
else -> {
expressionsAsmGen.translateExpression(index)
out(" inx | lda $ESTACK_LO_HEX,x")
}
}
}
internal fun loadScaledArrayIndexIntoRegister(expr: ArrayIndexedExpression,
elementDt: DataType,
register: CpuRegister,
@ -648,7 +633,17 @@ internal class AsmGen(private val program: Program,
}
}
else {
TODO("+1")
expressionsAsmGen.translateExpression(index)
out("""
inc $ESTACK_LO_HEX,x
bne +
inc $ESTACK_HI_HEX,x
+""")
when(register) {
CpuRegister.A -> out(" inx | lda $ESTACK_LO_HEX,x")
CpuRegister.X -> throw AssemblyError("can't use X here")
CpuRegister.Y -> out(" inx | ldy $ESTACK_LO_HEX,x")
}
}
} else {
if (index is IdentifierReference) {

View File

@ -73,71 +73,65 @@ internal class PostIncrDecrAsmGen(private val program: Program, private val asmg
}
targetArrayIdx!=null -> {
val index = targetArrayIdx.arrayspec.index
val what = asmgen.asmIdentifierName(targetArrayIdx.identifier)
val asmArrayvarname = asmgen.asmIdentifierName(targetArrayIdx.identifier)
val elementDt = targetArrayIdx.inferType(program).typeOrElse(DataType.STRUCT)
when(index) {
is NumericLiteralValue -> {
val indexValue = index.number.toInt() * elementDt.memorySize()
when(elementDt) {
in ByteDatatypes -> asmgen.out(if (incr) " inc $what+$indexValue" else " dec $what+$indexValue")
in ByteDatatypes -> asmgen.out(if (incr) " inc $asmArrayvarname+$indexValue" else " dec $asmArrayvarname+$indexValue")
in WordDatatypes -> {
if(incr)
asmgen.out(" inc $what+$indexValue | bne + | inc $what+$indexValue+1 |+")
asmgen.out(" inc $asmArrayvarname+$indexValue | bne + | inc $asmArrayvarname+$indexValue+1 |+")
else
asmgen.out("""
lda $what+$indexValue
lda $asmArrayvarname+$indexValue
bne +
dec $what+$indexValue+1
+ dec $what+$indexValue
dec $asmArrayvarname+$indexValue+1
+ dec $asmArrayvarname+$indexValue
""")
}
DataType.FLOAT -> {
asmgen.out(" lda #<$what+$indexValue | ldy #>$what+$indexValue")
asmgen.out(" lda #<$asmArrayvarname+$indexValue | ldy #>$asmArrayvarname+$indexValue")
asmgen.out(if(incr) " jsr c64flt.inc_var_f" else " jsr c64flt.dec_var_f")
}
else -> throw AssemblyError("need numeric type")
}
}
is IdentifierReference -> {
// TODO rewrite using scaled?
asmgen.loadUnscaledArrayIndexIntoA(targetArrayIdx)
incrDecrArrayvalueWithIndexA(incr, elementDt, what) // TODO is this ok for word/float array?
}
else -> {
// TODO rewrite using scaled?
asmgen.loadUnscaledArrayIndexIntoA(targetArrayIdx)
incrDecrArrayvalueWithIndexA(incr, elementDt, what)// TODO is this ok for word/float array?
asmgen.loadScaledArrayIndexIntoRegister(targetArrayIdx, elementDt, CpuRegister.A)
asmgen.out(" stx ${C64Zeropage.SCRATCH_REG_X} | tax")
when(elementDt) {
in ByteDatatypes -> {
asmgen.out(if(incr) " inc $asmArrayvarname,x" else " dec $asmArrayvarname,x")
}
in WordDatatypes -> {
if(incr)
asmgen.out(" inc $asmArrayvarname,x | bne + | inc $asmArrayvarname+1,x |+")
else
asmgen.out("""
lda $asmArrayvarname,x
bne +
dec $asmArrayvarname+1,x
+ dec $asmArrayvarname
""")
}
DataType.FLOAT -> {
asmgen.out("""
ldy #>$asmArrayvarname
clc
adc #<$asmArrayvarname
bcc +
iny
+ jsr c64flt.inc_var_f""")
}
else -> throw AssemblyError("weird array elt dt")
}
asmgen.out(" ldx ${C64Zeropage.SCRATCH_REG_X}")
}
}
}
else -> throw AssemblyError("weird target type ${stmt.target}")
}
}
private fun incrDecrArrayvalueWithIndexA(incr: Boolean, elementDt: DataType, arrayVarName: String) {
asmgen.out(" stx ${C64Zeropage.SCRATCH_REG_X} | tax")
when(elementDt) {
in ByteDatatypes -> {
asmgen.out(if(incr) " inc $arrayVarName,x" else " dec $arrayVarName,x")
}
in WordDatatypes -> {
if(incr)
asmgen.out(" inc $arrayVarName,x | bne + | inc $arrayVarName+1,x |+")
else
asmgen.out("""
lda $arrayVarName,x
bne +
dec $arrayVarName+1,x
+ dec $arrayVarName
""")
}
DataType.FLOAT -> {
asmgen.out(" lda #<$arrayVarName | ldy #>$arrayVarName")
asmgen.out(if(incr) " jsr c64flt.inc_indexed_var_f" else " jsr c64flt.dec_indexed_var_f")
}
else -> throw AssemblyError("weird array elt dt")
}
asmgen.out(" ldx ${C64Zeropage.SCRATCH_REG_X}")
}
}

View File

@ -83,7 +83,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
}
} else {
// TODO rewrite to use Scaled
asmgen.loadUnscaledArrayIndexIntoA(value)
loadUnscaledArrayIndexIntoA(value)
readAndPushArrayvalueWithUnscaledIndexA(elementDt, arrayVarName)
}
assignStackValue(assign.target)
@ -201,9 +201,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
throw AssemblyError("no asm gen for assign address $sourceName to memory word $target")
}
TargetStorageKind.ARRAY -> {
val targetArrayIdx = target.array!!
val index = targetArrayIdx.arrayspec.index
throw AssemblyError("no asm gen for assign address $sourceName to array ${target.asmVarname} [ $index ]")
throw AssemblyError("no asm gen for assign address $sourceName to array ${target.asmVarname}")
}
TargetStorageKind.REGISTER -> TODO()
TargetStorageKind.STACK -> TODO()
@ -372,7 +370,6 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
}
TargetStorageKind.ARRAY -> {
val index = target.array!!.arrayspec.index
val targetName = asmgen.asmIdentifierName(target.array.identifier)
asmgen.translateExpression(index)
asmgen.out("""
inx
@ -380,9 +377,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
asl a
tay
lda #<${word.toHex()}
sta $targetName,y
sta ${target.asmVarname},y
lda #>${word.toHex()}
sta $targetName+1,y
sta ${target.asmVarname}+1,y
""")
}
TargetStorageKind.REGISTER -> TODO()
@ -400,13 +397,12 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
}
TargetStorageKind.ARRAY -> {
val index = target.array!!.arrayspec.index
val targetName = asmgen.asmIdentifierName(target.array.identifier)
asmgen.translateExpression(index)
asmgen.out("""
inx
ldy $ESTACK_LO_HEX,x
lda #${byte.toHex()}
sta $targetName,y
sta ${target.asmVarname},y
""")
}
else -> throw AssemblyError("no asm gen for assign byte $byte to $target")
@ -472,7 +468,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
}
TargetStorageKind.ARRAY -> {
val index = target.array!!.arrayspec.index
val arrayVarName = asmgen.asmIdentifierName(target.array.identifier)
val arrayVarName = target.asmVarname
if (index is NumericLiteralValue) {
val indexValue = index.number.toInt() * DataType.FLOAT.memorySize()
asmgen.out("""
@ -520,9 +516,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
storeByteViaRegisterAInMemoryAddress(address.toHex(), target.memory!!)
}
TargetStorageKind.ARRAY -> {
val index = target.array!!.arrayspec.index
val targetName = asmgen.asmIdentifierName(target.array.identifier)
throw AssemblyError("no asm gen for assign memory byte at $address to array $targetName [ $index ]")
throw AssemblyError("no asm gen for assign memory byte at $address to array ${target.asmVarname}")
}
TargetStorageKind.REGISTER -> TODO()
TargetStorageKind.STACK -> TODO()
@ -544,9 +538,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
storeByteViaRegisterAInMemoryAddress(sourceName, target.memory!!)
}
TargetStorageKind.ARRAY -> {
val index = target.array!!.arrayspec.index
val targetName = asmgen.asmIdentifierName(target.array.identifier)
throw AssemblyError("no asm gen for assign memory byte $sourceName to array $targetName [ $index ]")
throw AssemblyError("no asm gen for assign memory byte $sourceName to array ${target.asmVarname} ")
}
else -> throw AssemblyError("no asm gen for assign memory byte $target")
}
@ -646,6 +638,21 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
}
}
private fun loadUnscaledArrayIndexIntoA(expr: ArrayIndexedExpression) {
// TODO this is only used once, remove this when that is rewritten using scaled
when (val index = expr.arrayspec.index) {
is NumericLiteralValue -> throw AssemblyError("constant array index should be optimized earlier")
is IdentifierReference -> {
val indexName = asmgen.asmIdentifierName(index)
asmgen.out(" lda $indexName")
}
else -> {
asmgen.translateExpression(index)
asmgen.out(" inx | lda $ESTACK_LO_HEX,x")
}
}
}
private fun readAndPushArrayvalueWithUnscaledIndexA(elementDt: DataType, asmVarname: String) {
// TODO this is only used once, remove this when that is rewritten using scaled
when (elementDt) {

View File

@ -7,27 +7,29 @@ main {
sub start() {
; uword[] array=[$1111 ,$2222,$3333]
; uword uw = $ee33
; ubyte i = 2
; array[1] = array[1] as ubyte
; array[i] = array[i] as ubyte
; c64scr.print_uwhex(array[0], 1)
; c64.CHROUT(',')
; c64scr.print_uwhex(array[1], 1)
; c64.CHROUT(',')
; c64scr.print_uwhex(array[2], 1)
; c64.CHROUT('\n')
ubyte[] arr1=[11,22,33]
uword[] array=[1111 ,2222,3333]
float[] farr = [1.111, 2.222, 3.333]
ubyte i = 1
c64scr.print_ub(arr1[1])
c64.CHROUT('\n')
arr1 [i] ++
c64scr.print_ub(arr1[1])
c64.CHROUT('\n')
c64scr.print_uw(array[1])
c64.CHROUT('\n')
array[i] ++
c64scr.print_uw(array[1])
c64.CHROUT('\n')
c64flt.print_f(farr[1])
c64.CHROUT('\n')
float ff
float ff2 = 0
ff = ff2 + farr[1] + 99
c64flt.print_f(ff)
farr[i] ++
c64flt.print_f(farr[1])
c64.CHROUT('\n')
}
}