added swap() slow version

This commit is contained in:
Irmen de Jong 2019-01-18 01:33:54 +01:00
parent 740dedc7a1
commit 75b38d7b84
6 changed files with 93 additions and 23 deletions

View File

@ -5,6 +5,7 @@ import prog8.ast.RegisterOrPair.*
import prog8.compiler.intermediate.IntermediateProgram
import prog8.compiler.intermediate.Opcode
import prog8.compiler.intermediate.Value
import prog8.optimizing.same
import prog8.stackvm.Syscall
import java.util.*
import kotlin.math.abs
@ -760,6 +761,12 @@ private class StatementTranslator(private val prog: IntermediateProgram,
private fun translateFunctionCall(funcname: String, args: List<IExpression>) {
// some functions are implemented as vm opcodes
if(funcname == "swap") {
translateSwap(args)
return
}
args.forEach { translate(it) } // place function argument(s) on the stack
when (funcname) {
"len" -> {
@ -923,6 +930,75 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
}
private fun StatementTranslator.translateSwap(args: List<IExpression>) {
// swap(x,y) is treated differently, it's not a normal function call
if (args.size != 2)
throw AstException("swap requires 2 arguments")
val dt1 = args[0].resultingDatatype(namespace, heap)!!
val dt2 = args[1].resultingDatatype(namespace, heap)!!
if (dt1 != dt2)
throw AstException("swap requires 2 args of identical type")
if (args[0].constValue(namespace, heap) != null || args[1].constValue(namespace, heap) != null)
throw AstException("swap requires 2 variables, not constant value(s)")
if (dt1 !in NumericDatatypes)
throw AstException("swap requires args of numerical type")
if(same(args[0], args[1]))
throw AstException("swap should have 2 different args")
// @todo implement the above errors as nice AstChecker expression errors.
// @todo implement this more efficiently with using the xor trick instead of the stack!
// Swap(X,Y) :=
// X ^= Y
// Y ^= X
// X ^= Y
// for floats, this doesn't work, use a temp variable instead.
// pop first then second arg
translate(args[0])
translate(args[1])
// pop stack in reverse order
when {
args[0] is IdentifierReference -> {
val target = AssignTarget(null, args[0] as IdentifierReference, null, null, args[0].position)
popValueIntoTarget(target, dt1)
}
args[0] is RegisterExpr -> {
val target = AssignTarget((args[0] as RegisterExpr).register, null, null, null, args[0].position)
popValueIntoTarget(target, dt1)
}
args[0] is ArrayIndexedExpression -> {
val target = AssignTarget(null, null, args[0] as ArrayIndexedExpression, null, args[0].position)
popValueIntoTarget(target, dt1)
}
args[0] is DirectMemoryRead -> {
val target = AssignTarget(null, null, null, DirectMemoryWrite((args[0] as DirectMemoryRead).addressExpression, args[0].position), args[0].position)
popValueIntoTarget(target, dt1)
}
else -> TODO("unpop type ${args[0]}")
}
when {
args[1] is IdentifierReference -> {
val target = AssignTarget(null, args[1] as IdentifierReference, null, null, args[1].position)
popValueIntoTarget(target, dt2)
}
args[1] is RegisterExpr -> {
val target = AssignTarget((args[1] as RegisterExpr).register, null, null, null, args[1].position)
popValueIntoTarget(target, dt2)
}
args[1] is ArrayIndexedExpression -> {
val target = AssignTarget(null, null, args[1] as ArrayIndexedExpression, null, args[1].position)
popValueIntoTarget(target, dt2)
}
args[1] is DirectMemoryRead -> {
val target = AssignTarget(null, null, null, DirectMemoryWrite((args[1] as DirectMemoryRead).addressExpression, args[1].position), args[1].position)
popValueIntoTarget(target, dt2)
}
else -> TODO("unpop type ${args[1]}")
}
return
}
private fun translateSubroutineCall(subroutine: Subroutine, arguments: List<IExpression>, callPosition: Position) {
// evaluate the arguments and assign them into the subroutine's argument variables.
var restoreX = Register.X in subroutine.asmClobbers

View File

@ -68,6 +68,7 @@ val BuiltinFunctions = mapOf(
"clear_carry" to FunctionSignature(false, emptyList(), null),
"set_irqd" to FunctionSignature(false, emptyList(), null),
"clear_irqd" to FunctionSignature(false, emptyList(), null),
"swap" to FunctionSignature(false, listOf(BuiltinFunctionParam("first", NumericDatatypes), BuiltinFunctionParam("second", NumericDatatypes)), null),
"memcopy" to FunctionSignature(false, listOf(
BuiltinFunctionParam("from", IntegerDatatypes + IterableDatatypes),
BuiltinFunctionParam("to", IntegerDatatypes + IterableDatatypes),

View File

@ -485,14 +485,17 @@ fun same(left: IExpression, right: IExpression): Boolean {
return (right is RegisterExpr && right.register==left.register)
is IdentifierReference ->
return (right is IdentifierReference && right.nameInSource==left.nameInSource)
is ArrayIndexedExpression ->
return (right is ArrayIndexedExpression && right.identifier==left.identifier && right.arrayspec==left.arrayspec)
is PrefixExpression ->
return (right is PrefixExpression && right.operator==left.operator && same(right.expression, left.expression))
is BinaryExpression ->
return (right is BinaryExpression && right.operator==left.operator
&& same(right.left, left.left)
&& same(right.right, left.right))
is ArrayIndexedExpression -> {
return (right is ArrayIndexedExpression && right.identifier.nameInSource == left.identifier.nameInSource
&& same(right.arrayspec.x, left.arrayspec.x))
}
is LiteralValue -> return (right is LiteralValue && right==left)
}
return false
}

View File

@ -664,6 +664,9 @@ memcopy(from, to, numbytes)
it is only faster if the number of bytes is larger than a certain threshold.
Compare the generated code to see if it was beneficial or not.
swap(x, y)
Swap the values of numerical variables (or memory locations) x and y in a fast way.
set_carry() / clear_carry()
Set (or clear) the CPU status register Carry flag. No result value.
(translated into ``SEC`` or ``CLC`` cpu instruction)

View File

@ -128,8 +128,6 @@
}
ubyte[8] spritecolors = [1,1,7,15,12,11,9,9]
sub position_sprites() {
; set each of the 8 sprites to the correct vertex of the cube
@ -140,20 +138,15 @@
for ubyte i1 in 0 to sorti {
ubyte i2 = i1+1
if(rotatedz[i1] > rotatedz[i2]) {
; @todo use a swap() builtin function?
word temp = rotatedx[i1]
rotatedx[i1] = rotatedx[i2]
rotatedx[i2] = temp
temp = rotatedy[i1]
rotatedy[i1] = rotatedy[i2]
rotatedy[i2] = temp
temp = rotatedz[i1]
rotatedz[i1] = rotatedz[i2]
rotatedz[i2] = temp
swap(rotatedx[i1], rotatedx[i2])
swap(rotatedy[i1], rotatedy[i2])
swap(rotatedz[i1], rotatedz[i2])
}
}
}
ubyte[8] spritecolors = [1,1,7,15,12,11,9,9]
for ubyte i in 0 to 7 {
word zc = rotatedz[i]
word persp = 300+zc/256

View File

@ -18,15 +18,9 @@
for ubyte i1 in 0 to sorti {
ubyte i2=i1+1
if(rotatedz[i2]>rotatedz[i1]) {
word t = rotatedx[i1]
rotatedx[i1] = rotatedx[i2]
rotatedx[i2] = t
t = rotatedy[i1]
rotatedy[i1] = rotatedy[i2]
rotatedy[i2] = t
t = rotatedz[i1]
rotatedz[i1] = rotatedz[i2]
rotatedz[i2] = t
swap(rotatedx[i1], rotatedx[i2])
swap(rotatedy[i1], rotatedy[i2])
swap(rotatedz[i1], rotatedz[i2])
}
}
}