fix swap() code for pointervars

This commit is contained in:
Irmen de Jong 2022-06-03 23:13:35 +02:00
parent c7eafd7c79
commit 5fe6aa2800
2 changed files with 145 additions and 31 deletions

View File

@ -710,6 +710,11 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
val first = fcall.args[0]
val second = fcall.args[1]
val arrayVarDecl1 = (first as? ArrayIndexedExpression)?.arrayvar?.targetVarDecl(program)
val arrayVarDecl2 = (second as? ArrayIndexedExpression)?.arrayvar?.targetVarDecl(program)
if((arrayVarDecl1!=null && !arrayVarDecl1.isArray) || (arrayVarDecl2!=null && !arrayVarDecl2.isArray))
throw AssemblyError("no asm gen for swapping bytes to and/or from indexed pointer var ${fcall.position}")
// optimized simple case: swap two variables
if(first is IdentifierReference && second is IdentifierReference) {
val firstName = asmgen.asmVariableName(first)
@ -787,11 +792,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
) {
if(firstOffset is NumericLiteral && secondOffset is NumericLiteral) {
if(firstOffset!=secondOffset) {
swapArrayValues(
DataType.UBYTE,
asmgen.asmVariableName(pointerVariable), firstOffset,
asmgen.asmVariableName(pointerVariable), secondOffset
)
swapArrayBytesViaPointers(pointerVariable, firstOffset, pointerVariable, secondOffset)
return
}
} else if(firstOffset is TypecastExpression && secondOffset is TypecastExpression) {
@ -800,11 +801,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
val secondOffsetVar = secondOffset.expression as? IdentifierReference
if(firstOffsetVar!=null && secondOffsetVar!=null) {
if(firstOffsetVar!=secondOffsetVar) {
swapArrayValues(
DataType.UBYTE,
asmgen.asmVariableName(pointerVariable), firstOffsetVar,
asmgen.asmVariableName(pointerVariable), secondOffsetVar
)
swapArrayBytesViaPointers(pointerVariable, firstOffsetVar, pointerVariable, secondOffsetVar)
return
}
}
@ -829,16 +826,16 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
val secondNum = second.indexer.indexExpr as? NumericLiteral
val secondVar = second.indexer.indexExpr as? IdentifierReference
if(firstNum!=null && secondNum!=null) {
if (firstNum != null && secondNum != null) {
swapArrayValues(elementDt, arrayVarName1, firstNum, arrayVarName2, secondNum)
return
} else if(firstVar!=null && secondVar!=null) {
} else if (firstVar != null && secondVar != null) {
swapArrayValues(elementDt, arrayVarName1, firstVar, arrayVarName2, secondVar)
return
} else if(firstNum!=null && secondVar!=null) {
} else if (firstNum != null && secondVar != null) {
swapArrayValues(elementDt, arrayVarName1, firstNum, arrayVarName2, secondVar)
return
} else if(firstVar!=null && secondNum!=null) {
} else if (firstVar != null && secondNum != null) {
swapArrayValues(elementDt, arrayVarName1, firstVar, arrayVarName2, secondNum)
return
}
@ -895,6 +892,72 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
}
}
private fun swapArrayBytesViaPointers(
firstZpPtr: IdentifierReference,
firstOffset: NumericLiteral,
secondZpPtr: IdentifierReference,
secondOffset: NumericLiteral
) {
var firstZpPtrName = asmgen.asmSymbolName(firstZpPtr)
if(!asmgen.isZpVar(firstZpPtr)) {
asmgen.out(" lda $firstZpPtrName | sta P8ZP_SCRATCH_W1")
asmgen.out(" lda $firstZpPtrName+1 | sta P8ZP_SCRATCH_W1+1")
firstZpPtrName = "P8ZP_SCRATCH_W1"
}
var secondZpPtrName = asmgen.asmSymbolName(secondZpPtr)
if(!asmgen.isZpVar(secondZpPtr)) {
asmgen.out(" lda $secondZpPtrName | sta P8ZP_SCRATCH_W2")
asmgen.out(" lda $secondZpPtrName+1 | sta P8ZP_SCRATCH_W2+1")
secondZpPtrName = "P8ZP_SCRATCH_W2"
}
asmgen.out("""
ldy #${firstOffset.number.toInt()}
lda ($firstZpPtrName),y
pha
ldy #${secondOffset.number.toInt()}
lda ($secondZpPtrName),y
ldy #${firstOffset.number.toInt()}
sta ($firstZpPtrName),y
pla
ldy #${secondOffset.number.toInt()}
sta ($secondZpPtrName),y
""")
}
private fun swapArrayBytesViaPointers(
firstZpPtr: IdentifierReference,
index1Var: IdentifierReference,
secondZpPtr: IdentifierReference,
index2Var: IdentifierReference
) {
var firstZpPtrName = asmgen.asmSymbolName(firstZpPtr)
if(!asmgen.isZpVar(firstZpPtr)) {
asmgen.out(" lda $firstZpPtrName | sta P8ZP_SCRATCH_W1")
asmgen.out(" lda $firstZpPtrName+1 | sta P8ZP_SCRATCH_W1+1")
firstZpPtrName = "P8ZP_SCRATCH_W1"
}
var secondZpPtrName = asmgen.asmSymbolName(secondZpPtr)
if(!asmgen.isZpVar(secondZpPtr)) {
asmgen.out(" lda $secondZpPtrName | sta P8ZP_SCRATCH_W2")
asmgen.out(" lda $secondZpPtrName+1 | sta P8ZP_SCRATCH_W2+1")
secondZpPtrName = "P8ZP_SCRATCH_W2"
}
val index1Name = asmgen.asmVariableName(index1Var)
val index2Name = asmgen.asmVariableName(index2Var)
asmgen.out("""
ldy $index1Name
lda ($firstZpPtrName),y
pha
ldy $index2Name
lda ($secondZpPtrName),y
ldy $index1Name
sta ($firstZpPtrName),y
pla
ldy $index2Name
sta ($secondZpPtrName),y
""")
}
private fun swapArrayValues(elementDt: DataType, arrayVarName1: String, indexValue1: NumericLiteral, arrayVarName2: String, indexValue2: NumericLiteral) {
val index1 = indexValue1.number.toInt() * program.memsizer.memorySize(elementDt)
val index2 = indexValue2.number.toInt() * program.memsizer.memorySize(elementDt)

View File

@ -1,5 +1,5 @@
%import textio
%zeropage basicsafe
%zeropage dontuse
; NOTE: meant to test to virtual machine output target (use -target vitual)
@ -31,27 +31,78 @@ main {
sub start() {
; mcCarthy()
ubyte[20] sieve
uword count=0
if count < 256
txt.print("<256 ok! 1\n")
if count > 256
txt.print(">256 nok! 2\n")
count=257
if count < 256
txt.print("<256 nok! 3\n")
if count > 256
txt.print(">256 ok! 4\n")
count=256
ubyte value = 0
ubyte size = 9
ubyte[10] data = [11,22,33,4,5,6,7,8,9,10]
uword bitmapbuf = &data
count=0
while count < 256 { ; TODO fix this while loop
txt.print_uw(count)
; ; 11 22 33
; txt.print_ub(bitmapbuf[0])
; txt.spc()
; txt.print_ub(bitmapbuf[1])
; txt.spc()
; txt.print_ub(bitmapbuf[2])
; txt.nl()
; rol(bitmapbuf[0])
; rol(bitmapbuf[0])
; txt.print_ub(bitmapbuf[0]) ; 44
; txt.spc()
; ror(bitmapbuf[0])
; ror(bitmapbuf[0])
; txt.print_ub(bitmapbuf[0]) ; 11
; txt.nl()
;
; ; 22 44 66
; txt.print_ub(bitmapbuf[0]*2)
; txt.spc()
; txt.print_ub(bitmapbuf[1]*2)
; txt.spc()
; txt.print_ub(bitmapbuf[2]*2)
; txt.nl()
ubyte one = 1
bitmapbuf[0] = one
bitmapbuf[1] = one+one
bitmapbuf[2] = one+one+one
bitmapbuf[2] += 4
bitmapbuf[2] -= 2
bitmapbuf[2] -= 2
swap(bitmapbuf[0], bitmapbuf[1])
; 1 2 3
txt.print_ub(bitmapbuf[0])
txt.spc()
txt.print_ub(bitmapbuf[1])
txt.spc()
txt.print_ub(bitmapbuf[2])
txt.nl()
for value in data {
txt.print_ub(value)
txt.spc()
count += 10
}
txt.nl()
; TODO why is this loop much larger in code than the one below.
value = 0
ubyte xx
for xx in 0 to size-1 {
value += bitmapbuf[xx]
}
txt.print_ub(value) ; 45
txt.nl()
; TODO this one is much more compact
value = 0
uword srcptr = bitmapbuf
repeat size {
value += @(srcptr)
srcptr++
}
txt.print_ub(value) ; 45
txt.nl()
; ; a "pixelshader":
; sys.gfx_enable(0) ; enable lo res screen
; ubyte shifter