mirror of
https://github.com/irmen/prog8.git
synced 2024-07-05 22:29:04 +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.IntermediateProgram
|
||||||
import prog8.compiler.intermediate.Opcode
|
import prog8.compiler.intermediate.Opcode
|
||||||
import prog8.compiler.intermediate.Value
|
import prog8.compiler.intermediate.Value
|
||||||
|
import prog8.optimizing.same
|
||||||
import prog8.stackvm.Syscall
|
import prog8.stackvm.Syscall
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
@ -760,6 +761,12 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
|
|
||||||
private fun translateFunctionCall(funcname: String, args: List<IExpression>) {
|
private fun translateFunctionCall(funcname: String, args: List<IExpression>) {
|
||||||
// some functions are implemented as vm opcodes
|
// some functions are implemented as vm opcodes
|
||||||
|
|
||||||
|
if(funcname == "swap") {
|
||||||
|
translateSwap(args)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
args.forEach { translate(it) } // place function argument(s) on the stack
|
args.forEach { translate(it) } // place function argument(s) on the stack
|
||||||
when (funcname) {
|
when (funcname) {
|
||||||
"len" -> {
|
"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) {
|
private fun translateSubroutineCall(subroutine: Subroutine, arguments: List<IExpression>, callPosition: Position) {
|
||||||
// evaluate the arguments and assign them into the subroutine's argument variables.
|
// evaluate the arguments and assign them into the subroutine's argument variables.
|
||||||
var restoreX = Register.X in subroutine.asmClobbers
|
var restoreX = Register.X in subroutine.asmClobbers
|
||||||
|
@ -68,6 +68,7 @@ val BuiltinFunctions = mapOf(
|
|||||||
"clear_carry" to FunctionSignature(false, emptyList(), null),
|
"clear_carry" to FunctionSignature(false, emptyList(), null),
|
||||||
"set_irqd" to FunctionSignature(false, emptyList(), null),
|
"set_irqd" to FunctionSignature(false, emptyList(), null),
|
||||||
"clear_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(
|
"memcopy" to FunctionSignature(false, listOf(
|
||||||
BuiltinFunctionParam("from", IntegerDatatypes + IterableDatatypes),
|
BuiltinFunctionParam("from", IntegerDatatypes + IterableDatatypes),
|
||||||
BuiltinFunctionParam("to", 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)
|
return (right is RegisterExpr && right.register==left.register)
|
||||||
is IdentifierReference ->
|
is IdentifierReference ->
|
||||||
return (right is IdentifierReference && right.nameInSource==left.nameInSource)
|
return (right is IdentifierReference && right.nameInSource==left.nameInSource)
|
||||||
is ArrayIndexedExpression ->
|
|
||||||
return (right is ArrayIndexedExpression && right.identifier==left.identifier && right.arrayspec==left.arrayspec)
|
|
||||||
is PrefixExpression ->
|
is PrefixExpression ->
|
||||||
return (right is PrefixExpression && right.operator==left.operator && same(right.expression, left.expression))
|
return (right is PrefixExpression && right.operator==left.operator && same(right.expression, left.expression))
|
||||||
is BinaryExpression ->
|
is BinaryExpression ->
|
||||||
return (right is BinaryExpression && right.operator==left.operator
|
return (right is BinaryExpression && right.operator==left.operator
|
||||||
&& same(right.left, left.left)
|
&& same(right.left, left.left)
|
||||||
&& same(right.right, left.right))
|
&& 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
|
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.
|
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.
|
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_carry() / clear_carry()
|
||||||
Set (or clear) the CPU status register Carry flag. No result value.
|
Set (or clear) the CPU status register Carry flag. No result value.
|
||||||
(translated into ``SEC`` or ``CLC`` cpu instruction)
|
(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() {
|
sub position_sprites() {
|
||||||
|
|
||||||
; set each of the 8 sprites to the correct vertex of the cube
|
; set each of the 8 sprites to the correct vertex of the cube
|
||||||
@ -140,20 +138,15 @@
|
|||||||
for ubyte i1 in 0 to sorti {
|
for ubyte i1 in 0 to sorti {
|
||||||
ubyte i2 = i1+1
|
ubyte i2 = i1+1
|
||||||
if(rotatedz[i1] > rotatedz[i2]) {
|
if(rotatedz[i1] > rotatedz[i2]) {
|
||||||
; @todo use a swap() builtin function?
|
swap(rotatedx[i1], rotatedx[i2])
|
||||||
word temp = rotatedx[i1]
|
swap(rotatedy[i1], rotatedy[i2])
|
||||||
rotatedx[i1] = rotatedx[i2]
|
swap(rotatedz[i1], rotatedz[i2])
|
||||||
rotatedx[i2] = temp
|
|
||||||
temp = rotatedy[i1]
|
|
||||||
rotatedy[i1] = rotatedy[i2]
|
|
||||||
rotatedy[i2] = temp
|
|
||||||
temp = rotatedz[i1]
|
|
||||||
rotatedz[i1] = rotatedz[i2]
|
|
||||||
rotatedz[i2] = temp
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ubyte[8] spritecolors = [1,1,7,15,12,11,9,9]
|
||||||
|
|
||||||
for ubyte i in 0 to 7 {
|
for ubyte i in 0 to 7 {
|
||||||
word zc = rotatedz[i]
|
word zc = rotatedz[i]
|
||||||
word persp = 300+zc/256
|
word persp = 300+zc/256
|
||||||
|
@ -18,15 +18,9 @@
|
|||||||
for ubyte i1 in 0 to sorti {
|
for ubyte i1 in 0 to sorti {
|
||||||
ubyte i2=i1+1
|
ubyte i2=i1+1
|
||||||
if(rotatedz[i2]>rotatedz[i1]) {
|
if(rotatedz[i2]>rotatedz[i1]) {
|
||||||
word t = rotatedx[i1]
|
swap(rotatedx[i1], rotatedx[i2])
|
||||||
rotatedx[i1] = rotatedx[i2]
|
swap(rotatedy[i1], rotatedy[i2])
|
||||||
rotatedx[i2] = t
|
swap(rotatedz[i1], rotatedz[i2])
|
||||||
t = rotatedy[i1]
|
|
||||||
rotatedy[i1] = rotatedy[i2]
|
|
||||||
rotatedy[i2] = t
|
|
||||||
t = rotatedz[i1]
|
|
||||||
rotatedz[i1] = rotatedz[i2]
|
|
||||||
rotatedz[i2] = t
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user