From cc53d698bffc22f67c5e0bc88bd3dee445641426 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 24 Nov 2024 03:53:03 +0100 Subject: [PATCH] added msw() and lsw() builtin functions (experimental) --- codeCore/src/prog8/code/ast/AstExpressions.kt | 2 +- .../src/prog8/code/core/BuiltinFunctions.kt | 2 ++ .../codegen/cpu6502/BuiltinFunctionsAsmGen.kt | 2 ++ .../codegen/cpu6502/FunctionCallAsmGen.kt | 2 +- .../cpu6502/assignment/AssignmentAsmGen.kt | 2 +- .../codegen/intermediate/BuiltinFuncGen.kt | 2 ++ .../src/prog8/compiler/BuiltinFunctions.kt | 2 ++ .../compiler/astprocessing/AstChecker.kt | 3 ++- .../IntermediateAstPostprocess.kt | 2 +- .../compiler/astprocessing/VariousCleanups.kt | 19 +++++++++++++++++-- .../prog8/ast/expressions/AstExpressions.kt | 1 - docs/source/todo.rst | 3 ++- examples/test.p8 | 7 +++++++ 13 files changed, 40 insertions(+), 9 deletions(-) diff --git a/codeCore/src/prog8/code/ast/AstExpressions.kt b/codeCore/src/prog8/code/ast/AstExpressions.kt index 76393ded8..3928d8e9e 100644 --- a/codeCore/src/prog8/code/ast/AstExpressions.kt +++ b/codeCore/src/prog8/code/ast/AstExpressions.kt @@ -92,7 +92,7 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit is PtBinaryExpression -> false is PtBuiltinFunctionCall -> { when (name) { - in arrayOf("msb", "lsb", "bankof", "mkword", "set_carry", "set_irqd", "clear_carry", "clear_irqd") -> this.args.all { it.isSimple() } + in arrayOf("msb", "lsb", "msw", "lsw", "bankof", "mkword", "set_carry", "set_irqd", "clear_carry", "clear_irqd") -> this.args.all { it.isSimple() } else -> false } } diff --git a/codeCore/src/prog8/code/core/BuiltinFunctions.kt b/codeCore/src/prog8/code/core/BuiltinFunctions.kt index b04e0e35d..6da7016ad 100644 --- a/codeCore/src/prog8/code/core/BuiltinFunctions.kt +++ b/codeCore/src/prog8/code/core/BuiltinFunctions.kt @@ -110,7 +110,9 @@ val BuiltinFunctions: Map = mapOf( "divmod__ubyte" to FSignature(false, listOf(FParam("dividend", arrayOf(DataType.UBYTE)), FParam("divisor", arrayOf(DataType.UBYTE)), FParam("quotient", arrayOf(DataType.UBYTE)), FParam("remainder", arrayOf(DataType.UBYTE))), null), "divmod__uword" to FSignature(false, listOf(FParam("dividend", arrayOf(DataType.UWORD)), FParam("divisor", arrayOf(DataType.UWORD)), FParam("quotient", arrayOf(DataType.UWORD)), FParam("remainder", arrayOf(DataType.UWORD))), null), "lsb" to FSignature(true, listOf(FParam("value", arrayOf(DataType.UWORD, DataType.WORD, DataType.LONG))), DataType.UBYTE), + "lsw" to FSignature(true, listOf(FParam("value", arrayOf(DataType.UWORD, DataType.WORD, DataType.LONG))), DataType.UWORD), "msb" to FSignature(true, listOf(FParam("value", arrayOf(DataType.UWORD, DataType.WORD, DataType.LONG))), DataType.UBYTE), + "msw" to FSignature(true, listOf(FParam("value", arrayOf(DataType.UWORD, DataType.WORD, DataType.LONG))), DataType.UWORD), "bankof" to FSignature(true, listOf(FParam("value", arrayOf(DataType.UWORD, DataType.WORD, DataType.LONG))), DataType.UBYTE), "mkword" to FSignature(true, listOf(FParam("msb", arrayOf(DataType.UBYTE)), FParam("lsb", arrayOf(DataType.UBYTE))), DataType.UWORD), "clamp" to FSignature(true, listOf(FParam("value", arrayOf(DataType.BYTE)), FParam("minimum", arrayOf(DataType.BYTE)), FParam("maximum", arrayOf(DataType.BYTE))), null), diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index 053871f5f..876f35e64 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -25,6 +25,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, when (fcall.name) { "bankof" -> throw AssemblyError("bankof() should have been replaced by a const value (either the bank number of a long const, or zero for any other smaller value)") + "lsw" -> throw AssemblyError("lsw() should have been removed or replaced by a const value") + "msw" -> throw AssemblyError("msw() should have been removed or replaced by a const value") "msb" -> funcMsb(fcall, resultRegister) "lsb" -> funcLsb(fcall, resultRegister) "mkword" -> funcMkword(fcall, resultRegister) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt index 8336e2bbc..4130a4558 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt @@ -161,7 +161,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as private fun usesOtherRegistersWhileEvaluating(arg: PtExpression): Boolean { return when(arg) { is PtBuiltinFunctionCall -> { - if (arg.name in arrayOf("lsb", "msb", "bankof")) + if (arg.name in arrayOf("lsb", "msb", "lsw", "msw", "bankof")) return usesOtherRegistersWhileEvaluating(arg.args[0]) if (arg.name == "mkword") return usesOtherRegistersWhileEvaluating(arg.args[0]) || usesOtherRegistersWhileEvaluating(arg.args[1]) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index d4eaee6eb..3a161d481 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -928,7 +928,7 @@ internal class AssignmentAsmGen( is PtIdentifier -> true is PtIrRegister -> true is PtNumber -> true - is PtBuiltinFunctionCall -> expr.name in arrayOf("lsb", "msb", "bankof") + is PtBuiltinFunctionCall -> expr.name in arrayOf("lsb", "msb", "lsw", "msw", "bankof") else -> false } } diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt index caf93b0e7..23c1eaca8 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt @@ -20,6 +20,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe "callfar2" -> funcCallfar2(call) "call" -> funcCall(call) "bankof" -> throw AssemblyError("bankof() should have been replaced by a const value (either the bank number of a long const, or zero for any other smaller value)") + "lsw" -> throw AssemblyError("lsw() should have been removed or replaced by a const value") + "msw" -> throw AssemblyError("msw() should have been removed or replaced by a const value") "msb" -> funcMsb(call) "lsb" -> funcLsb(call) "memory" -> funcMemory(call) diff --git a/compiler/src/prog8/compiler/BuiltinFunctions.kt b/compiler/src/prog8/compiler/BuiltinFunctions.kt index 168e8e267..77f1cba73 100644 --- a/compiler/src/prog8/compiler/BuiltinFunctions.kt +++ b/compiler/src/prog8/compiler/BuiltinFunctions.kt @@ -20,7 +20,9 @@ internal val constEvaluatorsForBuiltinFuncs: Map "sqrt__uword" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, false) { sqrt(it.toDouble()) } }, "sqrt__float" to { a, p, prg -> oneFloatArgOutputFloat(a, p, prg) { sqrt(it) } }, "lsb" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, true) { x: Int -> (x and 255).toDouble() } }, + "lsw" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, true) { x: Int -> (x and 65535).toDouble() } }, "msb" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, true) { x: Int -> (x ushr 8 and 255).toDouble()} }, + "msw" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, true) { x: Int -> (x ushr 16 and 65535).toDouble()} }, "bankof" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, true) { x: Int -> (x ushr 16 and 255).toDouble()} }, "mkword" to ::builtinMkword, "clamp__ubyte" to ::builtinClampUByte, diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 666c50cf4..03e15f52f 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -1514,7 +1514,8 @@ internal class AstChecker(private val program: Program, ident = arg.value as IdentifierReference else if(arg.value is FunctionCallExpression) { val fcall = arg.value as FunctionCallExpression - if(fcall.target.nameInSource == listOf("lsb") || fcall.target.nameInSource == listOf("msb") || fcall.target.nameInSource == listOf("bankof")) + val name = fcall.target.nameInSource + if(name==listOf("lsb") || name==listOf("msb") || name==listOf("bankof") || name==listOf("msw") || name==listOf("lsw")) ident = fcall.args[0] as? IdentifierReference } if(ident!=null && ident.nameInSource[0] == "cx16" && ident.nameInSource[1].startsWith("r")) { diff --git a/compiler/src/prog8/compiler/astprocessing/IntermediateAstPostprocess.kt b/compiler/src/prog8/compiler/astprocessing/IntermediateAstPostprocess.kt index 600c334ae..8f3f1fc52 100644 --- a/compiler/src/prog8/compiler/astprocessing/IntermediateAstPostprocess.kt +++ b/compiler/src/prog8/compiler/astprocessing/IntermediateAstPostprocess.kt @@ -118,7 +118,7 @@ private fun integrateDefers(subdefers: Map>, program: PtPro is PtAddressOf -> value.arrayIndexExpr == null || notComplex(value.arrayIndexExpr!!) is PtBuiltinFunctionCall -> { when (value.name) { - in arrayOf("msb", "lsb", "bankof", "mkword", "set_carry", "set_irqd", "clear_carry", "clear_irqd") -> value.args.all { notComplex(it) } + in arrayOf("msb", "lsb", "msw", "lsw", "bankof", "mkword", "set_carry", "set_irqd", "clear_carry", "clear_irqd") -> value.args.all { notComplex(it) } else -> false } } diff --git a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt index 7940e8d9a..1e1aa4e00 100644 --- a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt +++ b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt @@ -366,12 +366,27 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter, } override fun after(functionCallExpr: FunctionCallExpression, parent: Node): Iterable { - if(functionCallExpr.target.nameInSource==listOf("bankof")) { + val name = functionCallExpr.target.nameInSource + if(name==listOf("bankof")) { val valueDt = functionCallExpr.args[0].inferType(program) if(valueDt.isWords || valueDt.isBytes) { - val zero = NumericLiteral.optimalInteger(0, functionCallExpr.position) + val zero = NumericLiteral(DataType.UBYTE, 0.0, functionCallExpr.position) return listOf(IAstModification.ReplaceNode(functionCallExpr, zero, parent)) } + } else if(name==listOf("msw")) { + val valueDt = functionCallExpr.args[0].inferType(program) + if(valueDt.isWords || valueDt.isBytes) { + val zero = NumericLiteral(DataType.UWORD, 0.0, functionCallExpr.position) + return listOf(IAstModification.ReplaceNode(functionCallExpr, zero, parent)) + } + } else if(name==listOf("lsw")) { + val valueDt = functionCallExpr.args[0].inferType(program) + if(valueDt.isWords) + return listOf(IAstModification.ReplaceNode(functionCallExpr, functionCallExpr.args[0], parent)) + if(valueDt.isBytes) { + val cast = TypecastExpression(functionCallExpr.args[0], DataType.UWORD, true, functionCallExpr.position) + return listOf(IAstModification.ReplaceNode(functionCallExpr, cast, parent)) + } } return noModifications } diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index 889683c24..c2a430a9f 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -13,7 +13,6 @@ import prog8.code.target.encodings.JapaneseCharacterConverter import java.io.CharConversionException import java.util.Objects import kotlin.math.abs -import kotlin.math.exp import kotlin.math.floor import kotlin.math.truncate diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 8f8079e71..e3508a1a8 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -5,7 +5,8 @@ what to do with bankof(): keep it? add another syntax like \`value or ^value t add a function like addr() or lsw() to complement bnk() in getting easy access to the lower 16 bits of a long integer? -> added unary ^ operator as alternative to bankof() -> added unary << operator as alternative to addr() / lsb(x>>16) / lsw() --> TODO document whatever remains of those! +-> added msw() and lsw() . note: msw() on a 24 bits constant can ALSO be used to get the bank byte because the value, while a word type, will be <=255 +-> TODO document whatever remains of those! (and add to syntax files) ... diff --git a/examples/test.p8 b/examples/test.p8 index 412805716..c8038ce8e 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -21,6 +21,13 @@ main { txt.print_ubhex(bankof(foo2), true) txt.spc() txt.print_uwhex(foo2 &$ffff, false) + txt.nl() + + txt.print_ubhex(msw(foo2), true) + txt.spc() + txt.print_uwhex(lsw(foo2), false) + txt.nl() + } }