diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index c202a17b6..f804cefc2 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -6,7 +6,6 @@ import prog8.ast.Program import prog8.ast.expressions.* import prog8.ast.statements.ArrayIndex import prog8.ast.statements.BuiltinFunctionCallStatement -import prog8.ast.statements.DirectMemoryWrite import prog8.ast.statements.Subroutine import prog8.code.core.* import prog8.codegen.cpu6502.assignment.* @@ -82,7 +81,6 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, "lsb" -> funcLsb(fcall, resultToStack, resultRegister) "mkword" -> funcMkword(fcall, resultToStack, resultRegister) "abs" -> funcAbs(fcall, func, resultToStack, resultRegister, sscope) - "swap" -> funcSwap(fcall) "any", "all" -> funcAnyAll(fcall, func, resultToStack, resultRegister, sscope) "sgn" -> funcSgn(fcall, func, resultToStack, resultRegister, sscope) "rnd", "rndw" -> funcRnd(func, resultToStack, resultRegister, sscope) @@ -709,494 +707,6 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, } } - - private fun funcSwap(fcall: IFunctionCall) { - val first = fcall.args[0] - val second = fcall.args[1] - - // optimized simple case: swap two variables - if(first is IdentifierReference && second is IdentifierReference) { - val firstName = asmgen.asmVariableName(first) - val secondName = asmgen.asmVariableName(second) - val dt = first.inferType(program) - if(dt istype DataType.BYTE || dt istype DataType.UBYTE) { - asmgen.out(" ldy $firstName | lda $secondName | sta $firstName | sty $secondName") - return - } - if(dt istype DataType.WORD || dt istype DataType.UWORD) { - asmgen.out(""" - ldy $firstName - lda $secondName - sta $firstName - sty $secondName - ldy $firstName+1 - lda $secondName+1 - sta $firstName+1 - sty $secondName+1 - """) - return - } - if(dt istype DataType.FLOAT) { - asmgen.out(""" - lda #<$firstName - sta P8ZP_SCRATCH_W1 - lda #>$firstName - sta P8ZP_SCRATCH_W1+1 - lda #<$secondName - sta P8ZP_SCRATCH_W2 - lda #>$secondName - sta P8ZP_SCRATCH_W2+1 - jsr floats.func_swap_f - """) - return - } - } - - // optimized simple case: swap two memory locations - if(first is DirectMemoryRead && second is DirectMemoryRead) { - val addr1 = (first.addressExpression as? NumericLiteral)?.number?.toHex() - val addr2 = (second.addressExpression as? NumericLiteral)?.number?.toHex() - val name1 = if(first.addressExpression is IdentifierReference) asmgen.asmVariableName(first.addressExpression as IdentifierReference) else null - val name2 = if(second.addressExpression is IdentifierReference) asmgen.asmVariableName(second.addressExpression as IdentifierReference) else null - - when { - addr1!=null && addr2!=null -> { - asmgen.out(" ldy $addr1 | lda $addr2 | sta $addr1 | sty $addr2") - return - } - addr1!=null && name2!=null -> { - asmgen.out(" ldy $addr1 | lda $name2 | sta $addr1 | sty $name2") - return - } - name1!=null && addr2 != null -> { - asmgen.out(" ldy $name1 | lda $addr2 | sta $name1 | sty $addr2") - return - } - name1!=null && name2!=null -> { - asmgen.out(" ldy $name1 | lda $name2 | sta $name1 | sty $name2") - return - } - addr1==null && addr2==null && name1==null && name2==null -> { - val firstExpr = first.addressExpression as? BinaryExpression - val secondExpr = second.addressExpression as? BinaryExpression - if(firstExpr!=null && secondExpr!=null) { - val pointerVariable = firstExpr.left as? IdentifierReference - val firstOffset = firstExpr.right - val secondOffset = secondExpr.right - if(pointerVariable != null - && pointerVariable isSameAs secondExpr.left - && firstExpr.operator == "+" && secondExpr.operator == "+" - && (firstOffset is NumericLiteral || firstOffset is IdentifierReference || firstOffset is TypecastExpression) - && (secondOffset is NumericLiteral || secondOffset is IdentifierReference || secondOffset is TypecastExpression) - ) { - if(firstOffset is NumericLiteral && secondOffset is NumericLiteral) { - if(firstOffset!=secondOffset) { - swapArrayBytesViaPointers(pointerVariable, firstOffset, pointerVariable, secondOffset) - return - } - } else if(firstOffset is TypecastExpression && secondOffset is TypecastExpression) { - if(firstOffset.type in WordDatatypes && secondOffset.type in WordDatatypes) { - val firstOffsetVar = firstOffset.expression as? IdentifierReference - val secondOffsetVar = secondOffset.expression as? IdentifierReference - if(firstOffsetVar!=null && secondOffsetVar!=null) { - if(firstOffsetVar!=secondOffsetVar) { - swapArrayBytesViaPointers(pointerVariable, firstOffsetVar, pointerVariable, secondOffsetVar) - return - } - } - } - } else if(firstOffset is IdentifierReference || secondOffset is IdentifierReference) { - throw AssemblyError("expected a typecast-to-word for index variable at ${firstOffset.position} and/or ${secondOffset.position}") - } - } - } - } - } - } - - if(first is ArrayIndexedExpression && second is ArrayIndexedExpression) { - val arrayVarDecl1 = first.arrayvar.targetVarDecl(program)!! - val arrayVarDecl2 = second.arrayvar.targetVarDecl(program)!! - if(!arrayVarDecl1.isArray || !arrayVarDecl2.isArray) - throw AssemblyError("no asm gen for swapping bytes to and/or from indexed pointer var ${fcall.position}") - - val arrayVarName1 = asmgen.asmVariableName(first.arrayvar) - val arrayVarName2 = asmgen.asmVariableName(second.arrayvar) - val elementIDt = first.inferType(program) - val elementDt = elementIDt.getOrElse { throw AssemblyError("unknown dt") } - - val firstNum = first.indexer.indexExpr as? NumericLiteral - val firstVar = first.indexer.indexExpr as? IdentifierReference - val secondNum = second.indexer.indexExpr as? NumericLiteral - val secondVar = second.indexer.indexExpr as? IdentifierReference - - if (firstNum != null && secondNum != null) { - swapArrayValues(elementDt, arrayVarName1, firstNum, arrayVarName2, secondNum) - return - } else if (firstVar != null && secondVar != null) { - swapArrayValues(elementDt, arrayVarName1, firstVar, arrayVarName2, secondVar) - return - } else if (firstNum != null && secondVar != null) { - swapArrayValues(elementDt, arrayVarName1, firstNum, arrayVarName2, secondVar) - return - } else if (firstVar != null && secondNum != null) { - swapArrayValues(elementDt, arrayVarName1, firstVar, arrayVarName2, secondNum) - return - } - } - - 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}") - - // all other types of swap() calls are done via a temporary variable - - fun targetFromExpr(expr: Expression, datatype: DataType): AsmAssignTarget { - return when (expr) { - is IdentifierReference -> AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, datatype, expr.definingSubroutine, variableAsmName = asmgen.asmVariableName(expr)) - is ArrayIndexedExpression -> AsmAssignTarget(TargetStorageKind.ARRAY, program, asmgen, datatype, expr.definingSubroutine, array = expr) - is DirectMemoryRead -> AsmAssignTarget(TargetStorageKind.MEMORY, program, asmgen, datatype, expr.definingSubroutine, memory = DirectMemoryWrite(expr.addressExpression, expr.position)) - else -> throw AssemblyError("invalid expression object $expr") - } - } - - when(val datatype: DataType = first.inferType(program).getOr(DataType.UNDEFINED)) { - in ByteDatatypes, in WordDatatypes -> { - asmgen.assignExpressionToVariable(first, "P8ZP_SCRATCH_W1", datatype, null) - asmgen.assignExpressionToVariable(second, "P8ZP_SCRATCH_W2", datatype, null) - val assignFirst = AsmAssignment( - AsmAssignSource(SourceStorageKind.VARIABLE, program, asmgen, datatype, variableAsmName = "P8ZP_SCRATCH_W2"), - targetFromExpr(first, datatype), - false, program.memsizer, first.position - ) - val assignSecond = AsmAssignment( - AsmAssignSource(SourceStorageKind.VARIABLE, program, asmgen, datatype, variableAsmName = "P8ZP_SCRATCH_W1"), - targetFromExpr(second, datatype), - false, program.memsizer, second.position - ) - asmgen.translateNormalAssignment(assignFirst) - asmgen.translateNormalAssignment(assignSecond) - } - DataType.FLOAT -> { - // via temp variable and FAC1 - asmgen.assignExpressionTo(first, AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, DataType.FLOAT, first.definingSubroutine, "floats.tempvar_swap_float")) - asmgen.assignExpressionTo(second, AsmAssignTarget(TargetStorageKind.REGISTER, program, asmgen, DataType.FLOAT, null, register=RegisterOrPair.FAC1)) - asmgen.translateNormalAssignment( - AsmAssignment( - AsmAssignSource(SourceStorageKind.REGISTER, program, asmgen, datatype, register = RegisterOrPair.FAC1), - targetFromExpr(first, datatype), - false, program.memsizer, first.position - ) - ) - asmgen.translateNormalAssignment( - AsmAssignment( - AsmAssignSource(SourceStorageKind.VARIABLE, program, asmgen, datatype, "floats.tempvar_swap_float"), - targetFromExpr(second, datatype), - false, program.memsizer, second.position - ) - ) - } - else -> throw AssemblyError("weird swap dt") - } - } - - 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) - when(elementDt) { - DataType.UBYTE, DataType.BYTE -> { - asmgen.out(""" - lda $arrayVarName1+$index1 - ldy $arrayVarName2+$index2 - sta $arrayVarName2+$index2 - sty $arrayVarName1+$index1 - """) - } - DataType.UWORD, DataType.WORD -> { - asmgen.out(""" - lda $arrayVarName1+$index1 - ldy $arrayVarName2+$index2 - sta $arrayVarName2+$index2 - sty $arrayVarName1+$index1 - lda $arrayVarName1+$index1+1 - ldy $arrayVarName2+$index2+1 - sta $arrayVarName2+$index2+1 - sty $arrayVarName1+$index1+1 - """) - } - DataType.FLOAT -> { - asmgen.out(""" - lda #<(${arrayVarName1}+$index1) - sta P8ZP_SCRATCH_W1 - lda #>(${arrayVarName1}+$index1) - sta P8ZP_SCRATCH_W1+1 - lda #<(${arrayVarName2}+$index2) - sta P8ZP_SCRATCH_W2 - lda #>(${arrayVarName2}+$index2) - sta P8ZP_SCRATCH_W2+1 - jsr floats.func_swap_f - """) - } - else -> throw AssemblyError("invalid aray elt type") - } - } - - private fun swapArrayValues(elementDt: DataType, arrayVarName1: String, indexName1: IdentifierReference, arrayVarName2: String, indexName2: IdentifierReference) { - val idxAsmName1 = asmgen.asmVariableName(indexName1) - val idxAsmName2 = asmgen.asmVariableName(indexName2) - when(elementDt) { - DataType.UBYTE, DataType.BYTE -> { - asmgen.out(""" - stx P8ZP_SCRATCH_REG - ldx $idxAsmName1 - ldy $idxAsmName2 - lda $arrayVarName1,x - pha - lda $arrayVarName2,y - sta $arrayVarName1,x - pla - sta $arrayVarName2,y - ldx P8ZP_SCRATCH_REG - """) - } - DataType.UWORD, DataType.WORD -> { - asmgen.out(""" - stx P8ZP_SCRATCH_REG - lda $idxAsmName1 - asl a - tax - lda $idxAsmName2 - asl a - tay - lda $arrayVarName1,x - pha - lda $arrayVarName2,y - sta $arrayVarName1,x - pla - sta $arrayVarName2,y - lda $arrayVarName1+1,x - pha - lda $arrayVarName2+1,y - sta $arrayVarName1+1,x - pla - sta $arrayVarName2+1,y - ldx P8ZP_SCRATCH_REG - """) - } - DataType.FLOAT -> { - asmgen.out(""" - lda #>$arrayVarName1 - sta P8ZP_SCRATCH_W1+1 - lda $idxAsmName1 - asl a - asl a - clc - adc $idxAsmName1 - adc #<$arrayVarName1 - sta P8ZP_SCRATCH_W1 - bcc + - inc P8ZP_SCRATCH_W1+1 -+ lda #>$arrayVarName2 - sta P8ZP_SCRATCH_W2+1 - lda $idxAsmName2 - asl a - asl a - clc - adc $idxAsmName2 - adc #<$arrayVarName2 - sta P8ZP_SCRATCH_W2 - bcc + - inc P8ZP_SCRATCH_W2+1 -+ jsr floats.func_swap_f - """) - } - else -> throw AssemblyError("invalid aray elt type") - } - } - - private fun swapArrayValues(elementDt: DataType, arrayVarName1: String, indexValue1: NumericLiteral, arrayVarName2: String, indexName2: IdentifierReference) { - val index1 = indexValue1.number.toInt() * program.memsizer.memorySize(elementDt) - val idxAsmName2 = asmgen.asmVariableName(indexName2) - when(elementDt) { - DataType.UBYTE, DataType.BYTE -> { - asmgen.out(""" - lda $arrayVarName1 + $index1 - pha - ldy $idxAsmName2 - lda $arrayVarName2,y - sta $arrayVarName1 + $index1 - pla - sta $arrayVarName2,y - """) - } - DataType.UWORD, DataType.WORD -> { - asmgen.out(""" - lda $arrayVarName1 + $index1 - pha - lda $idxAsmName2 - asl a - tay - lda $arrayVarName2,y - sta $arrayVarName1 + $index1 - pla - sta $arrayVarName2,y - lda $arrayVarName1 + $index1+1 - pha - lda $arrayVarName2+1,y - sta $arrayVarName1 + $index1+1 - pla - sta $arrayVarName2+1,y - """) - } - DataType.FLOAT -> { - asmgen.out(""" - lda #<(${arrayVarName1}+$index1) - sta P8ZP_SCRATCH_W1 - lda #>(${arrayVarName1}+$index1) - sta P8ZP_SCRATCH_W1+1 - lda #>$arrayVarName1 - sta P8ZP_SCRATCH_W1+1 - lda $idxAsmName2 - asl a - asl a - clc - adc $idxAsmName2 - adc #<$arrayVarName1 - sta P8ZP_SCRATCH_W1 - bcc + - inc P8ZP_SCRATCH_W1+1 -+ jsr floats.func_swap_f - """) - } - else -> throw AssemblyError("invalid aray elt type") - } - } - - private fun swapArrayValues(elementDt: DataType, arrayVarName1: String, indexName1: IdentifierReference, arrayVarName2: String, indexValue2: NumericLiteral) { - val idxAsmName1 = asmgen.asmVariableName(indexName1) - val index2 = indexValue2.number.toInt() * program.memsizer.memorySize(elementDt) - when(elementDt) { - DataType.UBYTE, DataType.BYTE -> { - asmgen.out(""" - lda $arrayVarName2 + $index2 - pha - ldy $idxAsmName1 - lda $arrayVarName1,y - sta $arrayVarName2 + $index2 - pla - sta $arrayVarName1,y - """) - } - DataType.UWORD, DataType.WORD -> { - asmgen.out(""" - lda $arrayVarName2 + $index2 - pha - lda $idxAsmName1 - asl a - tay - lda $arrayVarName1,y - sta $arrayVarName2 + $index2 - pla - sta $arrayVarName1,y - lda $arrayVarName2 + $index2+1 - pha - lda $arrayVarName1+1,y - sta $arrayVarName2 + $index2+1 - pla - sta $arrayVarName1+1,y - """) - } - DataType.FLOAT -> { - asmgen.out(""" - lda #>$arrayVarName1 - sta P8ZP_SCRATCH_W1+1 - lda $idxAsmName1 - asl a - asl a - clc - adc $idxAsmName1 - adc #<$arrayVarName1 - sta P8ZP_SCRATCH_W1 - bcc + - inc P8ZP_SCRATCH_W1+1 -+ lda #<(${arrayVarName2}+$index2) - sta P8ZP_SCRATCH_W2 - lda #>(${arrayVarName2}+$index2) - sta P8ZP_SCRATCH_W2+1 - jsr floats.func_swap_f - """) - } - else -> throw AssemblyError("invalid aray elt type") - } - } - private fun funcAbs(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: Subroutine?) { translateArguments(fcall.args, func, scope) val dt = fcall.args.single().inferType(program).getOr(DataType.UNDEFINED) diff --git a/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt index 45916146a..6241cffb4 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt @@ -41,7 +41,6 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: "mkword" -> funcMkword(call, resultRegister) "sort" -> funcSort(call) "reverse" -> funcReverse(call) - "swap" -> funcSwap(call) "rol" -> funcRolRor(Opcode.ROXL, call, resultRegister) "ror" -> funcRolRor(Opcode.ROXR, call, resultRegister) "rol2" -> funcRolRor(Opcode.ROL, call, resultRegister) @@ -184,19 +183,6 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: return code } - private fun funcSwap(call: PtBuiltinFunctionCall): VmCodeChunk { - val left = call.args[0] - val right = call.args[1] - val leftReg = codeGen.vmRegisters.nextFree() - val rightReg = codeGen.vmRegisters.nextFree() - val code = VmCodeChunk() - code += exprGen.translateExpression(left, leftReg, -1) - code += exprGen.translateExpression(right, rightReg, -1) - code += assignRegisterTo(left, rightReg) - code += assignRegisterTo(right, leftReg) - return code - } - private fun funcReverse(call: PtBuiltinFunctionCall): VmCodeChunk { val arrayName = call.args[0] as PtIdentifier val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable diff --git a/compiler/res/prog8lib/c64/floats.p8 b/compiler/res/prog8lib/c64/floats.p8 index dc5c5b204..a5f2f12ad 100644 --- a/compiler/res/prog8lib/c64/floats.p8 +++ b/compiler/res/prog8lib/c64/floats.p8 @@ -9,7 +9,6 @@ floats { const float PI = 3.141592653589793 const float TWOPI = 6.283185307179586 - float tempvar_swap_float ; used for some swap() operations ; ---- C64 basic and kernal ROM float constants and functions ---- diff --git a/compiler/res/prog8lib/c64/graphics.p8 b/compiler/res/prog8lib/c64/graphics.p8 index ca9b6bf98..58ddc5fd1 100644 --- a/compiler/res/prog8lib/c64/graphics.p8 +++ b/compiler/res/prog8lib/c64/graphics.p8 @@ -38,8 +38,12 @@ graphics { if y1>y2 { ; make sure dy is always positive to have only 4 instead of 8 special cases - swap(x1, x2) - swap(y1, y2) + cx16.r0 = x1 + x1 = x2 + x2 = cx16.r0 + cx16.r0L = y1 + y1 = y2 + y2 = cx16.r0L } word @zp dx = (x2 as word)-x1 word @zp dy = (y2 as word)-y1 diff --git a/compiler/res/prog8lib/cx16/gfx2.p8 b/compiler/res/prog8lib/cx16/gfx2.p8 index 9fdac2118..64cebdb12 100644 --- a/compiler/res/prog8lib/cx16/gfx2.p8 +++ b/compiler/res/prog8lib/cx16/gfx2.p8 @@ -394,8 +394,12 @@ _done ; This code special-cases various quadrant loops to allow simple ++ and -- operations. if y1>y2 { ; make sure dy is always positive to have only 4 instead of 8 special cases - swap(x1, x2) - swap(y1, y2) + cx16.r0 = x1 + x1 = x2 + x2 = cx16.r0 + cx16.r0 = y1 + y1 = y2 + y2 = cx16.r0 } word @zp dx = (x2 as word)-x1 word @zp dy = (y2 as word)-y1 diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 55b2d8eb7..413d672fb 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -1063,20 +1063,7 @@ internal class AstChecker(private val program: Program, errors.err("cannot use arguments when calling a label", position) if(target is BuiltinFunctionPlaceholder) { - if(target.name=="swap") { - // swap() is a bit weird because this one is translated into an operations directly, instead of being a function call - val dt1 = args[0].inferType(program) - val dt2 = args[1].inferType(program) - if (dt1 != dt2) - errors.err("swap requires 2 args of identical type", position) - else if (args[0].constValue(program) != null || args[1].constValue(program) != null) - errors.err("swap requires 2 variables, not constant value(s)", position) - else if(args[0] isSameAs args[1]) - errors.err("swap should have 2 different args", position) - else if(!dt1.isNumeric) - errors.err("swap requires args of numerical type", position) - } - else if(target.name=="all" || target.name=="any") { + if(target.name=="all" || target.name=="any") { if((args[0] as? AddressOf)?.identifier?.targetVarDecl(program)?.datatype == DataType.STR || args[0].inferType(program).getOr(DataType.STR) == DataType.STR) { errors.err("any/all on a string is useless (is always true unless the string is empty)", position) diff --git a/compiler/test/arithmetic/builtins.p8 b/compiler/test/arithmetic/builtins.p8 index 5dcb54bf7..dc44f6870 100644 --- a/compiler/test/arithmetic/builtins.p8 +++ b/compiler/test/arithmetic/builtins.p8 @@ -444,9 +444,6 @@ main { txt.print_b(bb) txt.nl() - swap(fl, fzero) - swap(fzero, fl) - ub = any(flarr) txt.print_ub(ub) txt.nl() diff --git a/compilerAst/src/prog8/compiler/BuiltinFunctions.kt b/compilerAst/src/prog8/compiler/BuiltinFunctions.kt index 16f53bdf4..8050a0d5a 100644 --- a/compilerAst/src/prog8/compiler/BuiltinFunctions.kt +++ b/compilerAst/src/prog8/compiler/BuiltinFunctions.kt @@ -123,13 +123,12 @@ private val functionSignatures: List = listOf( FSignature("rnd" , false, emptyList(), DataType.UBYTE), FSignature("rndw" , false, emptyList(), DataType.UWORD), FSignature("memory" , true, listOf(FParam("name", arrayOf(DataType.STR)), FParam("size", arrayOf(DataType.UWORD)), FParam("alignment", arrayOf(DataType.UWORD))), DataType.UWORD), - FSignature("swap" , false, listOf(FParam("first", NumericDatatypes), FParam("second", NumericDatatypes)), null), FSignature("callfar" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), null), FSignature("callrom" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), null), ) val BuiltinFunctions = functionSignatures.associateBy { it.name } -val InplaceModifyingBuiltinFunctions = setOf("rol", "ror", "rol2", "ror2", "swap", "sort", "reverse") +val InplaceModifyingBuiltinFunctions = setOf("rol", "ror", "rol2", "ror2", "sort", "reverse") private fun builtinAny(array: List): Double = if(array.any { it!=0.0 }) 1.0 else 0.0 diff --git a/docs/source/index.rst b/docs/source/index.rst index 7370f457d..badf5c413 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -72,7 +72,7 @@ Language features - Floating point math also supported if the target system provides floating point library routines (C64 and Cx16 both do). - Strings can contain escaped characters but also many symbols directly if they have a petscii equivalent, such as "♠♥♣♦π▚●○╳". Characters like ^, _, \\, {, } and | are also accepted and converted to the closest petscii equivalents. - High-level code optimizations, such as const-folding, expression and statement simplifications/rewriting. -- Many built-in functions, such as ``sin``, ``cos``, ``rnd``, ``abs``, ``sqrt``, ``msb``, ``rol``, ``ror``, ``swap``, ``sort`` and ``reverse`` +- Many built-in functions, such as ``sin``, ``cos``, ``rnd``, ``abs``, ``sqrt``, ``msb``, ``rol``, ``ror``, ``sort`` and ``reverse`` - Programs can be run multiple times without reloading because of automatic variable (re)initializations. - Supports the sixteen 'virtual' 16-bit registers R0 .. R15 from the Commander X16, also on the other machines. - If you only use standard kernal and core prog8 library routines, it is possible to compile the *exact same program* for different machines (just change the compilation target flag)! diff --git a/docs/source/programming.rst b/docs/source/programming.rst index ba5e28d04..4fa86e3cf 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -869,10 +869,6 @@ sizeof(name) For an 10 element array of floats, it is 50 (on the C-64, where a float is 5 bytes). Note: usually you will be interested in the number of elements in an array, use len() for that. -swap(x, y) - Swap the values of numerical variables (or memory locations) x and y in a fast way. - You can swap two memory locations directly by using the direct memory access syntax, so like ``swap(@($5000), @($5001))`` - memory(name, size, alignment) Returns the address of the first location of a statically "reserved" block of memory of the given size in bytes, with the given name. If you specify an alignment value >1, it means the block of memory will diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 8e81c0622..7293704b1 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,7 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- optimize pointervar indexing codegen: fix 6502 codegen for params to in-place modifying functions (rol, swap, ...) +- optimize pointervar indexing codegen: fix 6502 codegen for params to in-place modifying functions (rol, ror, ...) - optimize pointervar indexing codegen: writing (all sorts of things) - pipe operator: (targets other than 'Virtual'): allow non-unary function calls in the pipe that specify the other argument(s) in the calls. Already working for VM target. - add McCarthy evaluation to shortcircuit and/or expressions. First do ifs by splitting them up? Then do expressions that compute a value? diff --git a/examples/cube3d-sprites.p8 b/examples/cube3d-sprites.p8 index 93c132c50..719386299 100644 --- a/examples/cube3d-sprites.p8 +++ b/examples/cube3d-sprites.p8 @@ -148,9 +148,15 @@ main { for i1 in 0 to i { ubyte i2 = i1+1 if(rotatedz[i1] > rotatedz[i2]) { - swap(rotatedx[i1], rotatedx[i2]) - swap(rotatedy[i1], rotatedy[i2]) - swap(rotatedz[i1], rotatedz[i2]) + word @zp 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 } } } diff --git a/examples/test.p8 b/examples/test.p8 index c9f35843d..e4b2025e1 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -73,9 +73,8 @@ main { bitmapbuf[2] += 4 bitmapbuf[2] -= 2 bitmapbuf[2] -= 2 - swap(bitmapbuf[0], bitmapbuf[1]) - ; 2 1 3 + ; 1 2 3 txt.print_ub(bitmapbuf[0]) txt.spc() txt.print_ub(bitmapbuf[1])