some more optimized in-array assignments codegeneration

This commit is contained in:
Irmen de Jong 2020-06-17 21:41:38 +02:00
parent 76cda82e23
commit cb9825484d
8 changed files with 207 additions and 34 deletions

View File

@ -781,3 +781,18 @@ set_array_float .proc
; -- copies the 5 bytes of the mflt value pointed to by SCRATCH_ZPWORD1,
; into the 5 bytes pointed to by A/Y. Clobbers A,Y.
.pend
swap_floats .proc
; -- swap floats pointed to by SCRATCH_ZPWORD1, SCRATCH_ZPWORD2
ldy #4
- lda (c64.SCRATCH_ZPWORD1),y
pha
lda (c64.SCRATCH_ZPWORD2),y
sta (c64.SCRATCH_ZPWORD1),y
pla
sta (c64.SCRATCH_ZPWORD2),y
dey
bpl -
rts
.pend

View File

@ -1 +1 @@
2.2
2.3-SNAPSHOT

View File

@ -731,6 +731,8 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
fun targetVarDecl(namespace: INameScope): VarDecl? = targetStatement(namespace) as? VarDecl
fun targetSubroutine(namespace: INameScope): Subroutine? = targetStatement(namespace) as? Subroutine
override fun equals(other: Any?) = other is IdentifierReference && other.nameInSource==nameInSource
override fun linkParents(parent: Node) {
this.parent = parent
}

View File

@ -691,7 +691,6 @@ internal class AsmGen(private val program: Program,
loopEndLabels.push(endLabel)
loopContinueLabels.push(whileLabel)
out(whileLabel)
// TODO optimize for the simple cases, can we avoid stack use?
expressionsAsmGen.translateExpression(stmt.condition)
val conditionDt = stmt.condition.inferType(program)
if(!conditionDt.isKnown)
@ -720,7 +719,6 @@ internal class AsmGen(private val program: Program,
loopEndLabels.push(endLabel)
loopContinueLabels.push(repeatLabel)
out(repeatLabel)
// TODO optimize this for the simple cases, can we avoid stack use?
translate(stmt.body)
expressionsAsmGen.translateExpression(stmt.untilCondition)
val conditionDt = stmt.untilCondition.inferType(program)

View File

@ -167,33 +167,108 @@ internal class AssignmentAsmGen(private val program: Program, private val errors
TODO("$assign")
}
is ArrayIndexedExpression -> {
if(assign.aug_op != "setvalue")
return false // we don't put effort into optimizing anything beside simple assignment
val valueArrayExpr = assign.value as ArrayIndexedExpression
val valueArrayIndex = valueArrayExpr.arrayspec.index
if(valueArrayIndex is RegisterExpr || arrayIndex is RegisterExpr) {
throw AssemblyError("cannot generate code for array operations with registers as index")
}
val valueVariablename = asmgen.asmIdentifierName(valueArrayExpr.identifier)
val valueDt = valueArrayExpr.identifier.inferType(program).typeOrElse(DataType.STRUCT)
when(arrayDt) {
DataType.ARRAY_UB -> {
if (arrayDt != DataType.ARRAY_B && arrayDt != DataType.ARRAY_UB && arrayDt != DataType.STR)
throw AssemblyError("assignment to array: expected byte array or string")
if (assign.aug_op == "setvalue") {
if (valueArrayIndex is NumericLiteralValue)
asmgen.out(" ldy #${valueArrayIndex.number.toHex()}")
else
asmgen.translateArrayIndexIntoY(valueArrayExpr)
asmgen.out(" lda $valueVariablename,y")
if (arrayIndex is NumericLiteralValue)
asmgen.out(" ldy #${arrayIndex.number.toHex()}")
else
asmgen.translateArrayIndexIntoY(targetArray)
asmgen.out(" sta $targetName,y")
} else {
return false // TODO optimize
}
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.STR -> {
if (valueArrayIndex is NumericLiteralValue)
asmgen.out(" ldy #${valueArrayIndex.number.toHex()}")
else
asmgen.translateArrayIndexIntoY(valueArrayExpr)
asmgen.out(" lda $valueVariablename,y")
if (arrayIndex is NumericLiteralValue)
asmgen.out(" ldy #${arrayIndex.number.toHex()}")
else
asmgen.translateArrayIndexIntoY(targetArray)
asmgen.out(" sta $targetName,y")
}
DataType.ARRAY_UW, DataType.ARRAY_W -> {
if (valueArrayIndex is NumericLiteralValue)
asmgen.out(" ldy #2*${valueArrayIndex.number.toHex()}")
else {
asmgen.translateArrayIndexIntoA(valueArrayExpr)
asmgen.out(" asl a | tay")
}
asmgen.out("""
lda $valueVariablename,y
pha
lda $valueVariablename+1,y
pha
""")
if (arrayIndex is NumericLiteralValue)
asmgen.out(" ldy #2*${arrayIndex.number.toHex()}")
else {
asmgen.translateArrayIndexIntoA(targetArray)
asmgen.out(" asl a | tay")
}
asmgen.out("""
pla
sta $targetName+1,y
pla
sta $targetName,y
""")
return true
}
DataType.ARRAY_F -> {
if (valueArrayIndex is NumericLiteralValue)
asmgen.out(" ldy #5*${valueArrayIndex.number.toHex()}")
else {
asmgen.translateArrayIndexIntoA(valueArrayExpr)
asmgen.out("""
sta ${C64Zeropage.SCRATCH_REG}
asl a
asl a
clc
adc ${C64Zeropage.SCRATCH_REG}
tay
""")
}
asmgen.out("""
lda $valueVariablename,y
pha
lda $valueVariablename+1,y
pha
lda $valueVariablename+2,y
pha
lda $valueVariablename+3,y
pha
lda $valueVariablename+4,y
pha
""")
if (arrayIndex is NumericLiteralValue)
asmgen.out(" ldy #5*${arrayIndex.number.toHex()}")
else {
asmgen.translateArrayIndexIntoA(targetArray)
asmgen.out("""
sta ${C64Zeropage.SCRATCH_REG}
asl a
asl a
clc
adc ${C64Zeropage.SCRATCH_REG}
tay
""")
}
asmgen.out("""
pla
sta $targetName+4,y
pla
sta $targetName+3,y
pla
sta $targetName+2,y
pla
sta $targetName+1,y
pla
sta $targetName,y
""")
return true
}
DataType.ARRAY_B -> TODO()
DataType.ARRAY_UW -> TODO()
DataType.ARRAY_W -> TODO()
DataType.ARRAY_F -> TODO()
else -> throw AssemblyError("assignment to array: invalid array dt")
}
return true

View File

@ -581,23 +581,63 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
ldy $firstName
lda $secondName
sta $firstName
tya
sta $secondName
sty $secondName
ldy $firstName+1
lda $secondName+1
sta $firstName+1
tya
sta $secondName+1
sty $secondName+1
""")
return
}
if(dt.istype(DataType.FLOAT)) {
TODO("optimized case for swapping 2 float vars-- asm subroutine")
asmgen.out("""
lda #<$firstName
sta ${C64Zeropage.SCRATCH_W1}
lda #>$firstName
sta ${C64Zeropage.SCRATCH_W1+1}
lda #<$secondName
sta ${C64Zeropage.SCRATCH_W2}
lda #>$secondName
sta ${C64Zeropage.SCRATCH_W2+1}
jsr c64flt.swap_floats
""")
return
}
}
// TODO more optimized cases? for instance swapping elements of array vars?
// TODO more optimized cases?
// if(first is ArrayIndexedExpression && second is ArrayIndexedExpression && first.identifier == second.identifier) {
// // swapping two elements of an array
// // we optimize just some simple cases here: same array, const/var/reg index.
// val arrayName = asmgen.asmIdentifierName(first.identifier)
// val dt = first.inferType(program).typeOrElse(DataType.STRUCT)
// val constIndex1 = first.arrayspec.index.constValue(program)
// val constIndex2 = second.arrayspec.index.constValue(program)
// val varIndex1 = first.arrayspec.index as? IdentifierReference
// val varIndex2 = first.arrayspec.index as? IdentifierReference
// val regIndex1 = (first.arrayspec.index as? RegisterExpr)?.register
// val regIndex2 = (first.arrayspec.index as? RegisterExpr)?.register
// when(dt) {
// DataType.UBYTE, DataType.BYTE -> {
// TODO("swap byte in array $arrayName")
// }
// DataType.UWORD, DataType.WORD -> {
// // swap word in array
// if(varIndex1!=null && varIndex2!=null){
// TODO("swap word in array $arrayName with varindexes")
// } else if(constIndex1!=null && constIndex2!=null) {
// TODO("swap word in array $arrayName with constants")
// } else if(regIndex1!=null && regIndex2!=null) {
// TODO("swap word in array $arrayName with register indexes")
// }
// }
// DataType.FLOAT -> {
// TODO("swap float in array $arrayName")
// }
// else -> throw AssemblyError("invalid array dt")
// }
// }
// suboptimal code via the evaluation stack...
asmgen.translateExpression(first)

View File

@ -143,9 +143,18 @@ main {
for i1 in 0 to i {
ubyte i2 = i1+1
if(rotatedz[i1] > rotatedz[i2]) {
swap(rotatedx[i1], rotatedx[i2])
swap(rotatedy[i1], rotatedy[i2])
swap(rotatedz[i1], rotatedz[i2])
; swap(rotatedx[i1], rotatedx[i2]) ; TODO eventually, implment the swap()
; swap(rotatedy[i1], rotatedy[i2])
; swap(rotatedz[i1], rotatedz[i2])
word tmp1 = rotatedx[i1]
rotatedx[i1] = rotatedx[i2] ; TODO fix assignment error
rotatedx[i2] = tmp1
tmp1 = rotatedy[i1]
rotatedy[i1] = rotatedy[i2]
rotatedy[i2] = tmp1
tmp1 = rotatedz[i1]
rotatedz[i1] = rotatedz[i2]
rotatedz[i2] = tmp1
}
}
}

View File

@ -8,7 +8,41 @@
main {
sub start() {
A=42
float[] fa=[1.1111,2.2222,3.3333,4.4444]
ubyte[] uba = [1,2,3,4]
word[] uwa = [1111,2222,3333,4444]
ubyte ii = 1
ubyte jj = 3
float f1 = 1.123456
float f2 = 2.223344
swap(f1, f2)
swap(fa[0], fa[1])
swap(uba[0], uba[1])
swap(uwa[0], uwa[1])
swap(fa[A], fa[Y])
swap(uba[A], uba[Y])
swap(uwa[A], uwa[Y])
ubyte i1
ubyte i2
swap(fa[i1], fa[i2])
swap(uba[i1], uba[i2])
swap(uwa[i1], uwa[i2])
c64flt.print_f(f1)
c64.CHROUT('\n')
c64flt.print_f(f2)
c64.CHROUT('\n')
swap(f1,f2)
c64flt.print_f(f1)
c64.CHROUT('\n')
c64flt.print_f(f2)
c64.CHROUT('\n')
}
}