mirror of
https://github.com/irmen/prog8.git
synced 2025-01-26 19:30:59 +00:00
added swap() slow version
This commit is contained in:
parent
740dedc7a1
commit
75b38d7b84
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user