mirror of
https://github.com/irmen/prog8.git
synced 2025-08-16 05:27:31 +00:00
some more optimized in-array assignments codegeneration
This commit is contained in:
@@ -781,3 +781,18 @@ set_array_float .proc
|
|||||||
; -- copies the 5 bytes of the mflt value pointed to by SCRATCH_ZPWORD1,
|
; -- 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.
|
; into the 5 bytes pointed to by A/Y. Clobbers A,Y.
|
||||||
.pend
|
.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
|
||||||
|
@@ -1 +1 @@
|
|||||||
2.2
|
2.3-SNAPSHOT
|
||||||
|
@@ -731,6 +731,8 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
|
|||||||
fun targetVarDecl(namespace: INameScope): VarDecl? = targetStatement(namespace) as? VarDecl
|
fun targetVarDecl(namespace: INameScope): VarDecl? = targetStatement(namespace) as? VarDecl
|
||||||
fun targetSubroutine(namespace: INameScope): Subroutine? = targetStatement(namespace) as? Subroutine
|
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) {
|
override fun linkParents(parent: Node) {
|
||||||
this.parent = parent
|
this.parent = parent
|
||||||
}
|
}
|
||||||
|
@@ -691,7 +691,6 @@ internal class AsmGen(private val program: Program,
|
|||||||
loopEndLabels.push(endLabel)
|
loopEndLabels.push(endLabel)
|
||||||
loopContinueLabels.push(whileLabel)
|
loopContinueLabels.push(whileLabel)
|
||||||
out(whileLabel)
|
out(whileLabel)
|
||||||
// TODO optimize for the simple cases, can we avoid stack use?
|
|
||||||
expressionsAsmGen.translateExpression(stmt.condition)
|
expressionsAsmGen.translateExpression(stmt.condition)
|
||||||
val conditionDt = stmt.condition.inferType(program)
|
val conditionDt = stmt.condition.inferType(program)
|
||||||
if(!conditionDt.isKnown)
|
if(!conditionDt.isKnown)
|
||||||
@@ -720,7 +719,6 @@ internal class AsmGen(private val program: Program,
|
|||||||
loopEndLabels.push(endLabel)
|
loopEndLabels.push(endLabel)
|
||||||
loopContinueLabels.push(repeatLabel)
|
loopContinueLabels.push(repeatLabel)
|
||||||
out(repeatLabel)
|
out(repeatLabel)
|
||||||
// TODO optimize this for the simple cases, can we avoid stack use?
|
|
||||||
translate(stmt.body)
|
translate(stmt.body)
|
||||||
expressionsAsmGen.translateExpression(stmt.untilCondition)
|
expressionsAsmGen.translateExpression(stmt.untilCondition)
|
||||||
val conditionDt = stmt.untilCondition.inferType(program)
|
val conditionDt = stmt.untilCondition.inferType(program)
|
||||||
|
@@ -167,33 +167,108 @@ internal class AssignmentAsmGen(private val program: Program, private val errors
|
|||||||
TODO("$assign")
|
TODO("$assign")
|
||||||
}
|
}
|
||||||
is ArrayIndexedExpression -> {
|
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 valueArrayExpr = assign.value as ArrayIndexedExpression
|
||||||
val valueArrayIndex = valueArrayExpr.arrayspec.index
|
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 valueVariablename = asmgen.asmIdentifierName(valueArrayExpr.identifier)
|
||||||
val valueDt = valueArrayExpr.identifier.inferType(program).typeOrElse(DataType.STRUCT)
|
val valueDt = valueArrayExpr.identifier.inferType(program).typeOrElse(DataType.STRUCT)
|
||||||
when(arrayDt) {
|
when(arrayDt) {
|
||||||
DataType.ARRAY_UB -> {
|
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.STR -> {
|
||||||
if (arrayDt != DataType.ARRAY_B && arrayDt != DataType.ARRAY_UB && arrayDt != DataType.STR)
|
if (valueArrayIndex is NumericLiteralValue)
|
||||||
throw AssemblyError("assignment to array: expected byte array or string")
|
asmgen.out(" ldy #${valueArrayIndex.number.toHex()}")
|
||||||
if (assign.aug_op == "setvalue") {
|
else
|
||||||
if (valueArrayIndex is NumericLiteralValue)
|
asmgen.translateArrayIndexIntoY(valueArrayExpr)
|
||||||
asmgen.out(" ldy #${valueArrayIndex.number.toHex()}")
|
asmgen.out(" lda $valueVariablename,y")
|
||||||
else
|
if (arrayIndex is NumericLiteralValue)
|
||||||
asmgen.translateArrayIndexIntoY(valueArrayExpr)
|
asmgen.out(" ldy #${arrayIndex.number.toHex()}")
|
||||||
asmgen.out(" lda $valueVariablename,y")
|
else
|
||||||
if (arrayIndex is NumericLiteralValue)
|
asmgen.translateArrayIndexIntoY(targetArray)
|
||||||
asmgen.out(" ldy #${arrayIndex.number.toHex()}")
|
asmgen.out(" sta $targetName,y")
|
||||||
else
|
}
|
||||||
asmgen.translateArrayIndexIntoY(targetArray)
|
DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
||||||
asmgen.out(" sta $targetName,y")
|
if (valueArrayIndex is NumericLiteralValue)
|
||||||
} else {
|
asmgen.out(" ldy #2*${valueArrayIndex.number.toHex()}")
|
||||||
return false // TODO optimize
|
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")
|
else -> throw AssemblyError("assignment to array: invalid array dt")
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@@ -581,23 +581,63 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
ldy $firstName
|
ldy $firstName
|
||||||
lda $secondName
|
lda $secondName
|
||||||
sta $firstName
|
sta $firstName
|
||||||
tya
|
sty $secondName
|
||||||
sta $secondName
|
|
||||||
ldy $firstName+1
|
ldy $firstName+1
|
||||||
lda $secondName+1
|
lda $secondName+1
|
||||||
sta $firstName+1
|
sta $firstName+1
|
||||||
tya
|
sty $secondName+1
|
||||||
sta $secondName+1
|
|
||||||
""")
|
""")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if(dt.istype(DataType.FLOAT)) {
|
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
|
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...
|
// suboptimal code via the evaluation stack...
|
||||||
asmgen.translateExpression(first)
|
asmgen.translateExpression(first)
|
||||||
|
@@ -143,9 +143,18 @@ main {
|
|||||||
for i1 in 0 to i {
|
for i1 in 0 to i {
|
||||||
ubyte i2 = i1+1
|
ubyte i2 = i1+1
|
||||||
if(rotatedz[i1] > rotatedz[i2]) {
|
if(rotatedz[i1] > rotatedz[i2]) {
|
||||||
swap(rotatedx[i1], rotatedx[i2])
|
; swap(rotatedx[i1], rotatedx[i2]) ; TODO eventually, implment the swap()
|
||||||
swap(rotatedy[i1], rotatedy[i2])
|
; swap(rotatedy[i1], rotatedy[i2])
|
||||||
swap(rotatedz[i1], rotatedz[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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,41 @@
|
|||||||
main {
|
main {
|
||||||
|
|
||||||
sub start() {
|
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')
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user