diff --git a/README.md b/README.md index 7e571ec1e..6c4627693 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ What does Prog8 provide? - conditional branches - ``when`` statement to provide a concise jump table alternative to if/elseif chains - ``in`` expression for concise and efficient multi-value/containment check -- many built-in functions such as ``sin``, ``cos``, ``rnd``, ``abs``, ``min``, ``max``, ``sqrt``, ``msb``, ``rol``, ``ror``, ``swap``, ``sort`` and ``reverse`` +- several specialized built-in functions such as ``lsb``, ``msb``, ``min``, ``max``, ``rol``, ``ror`` - various powerful built-in libraries to do I/O, number conversions, graphics and more - convenience abstractions for low level aspects such as ZeroPage handling, program startup, explicit memory addresses - inline assembly allows you to have full control when every cycle or byte matters diff --git a/codeCore/src/prog8/code/core/BuiltinFunctions.kt b/codeCore/src/prog8/code/core/BuiltinFunctions.kt index 0ffec21ea..afd27e11c 100644 --- a/codeCore/src/prog8/code/core/BuiltinFunctions.kt +++ b/codeCore/src/prog8/code/core/BuiltinFunctions.kt @@ -97,8 +97,6 @@ val BuiltinFunctions: Map = mapOf( "divmod" to FSignature(false, listOf(FParam("dividend", arrayOf(DataType.UBYTE, DataType.UWORD)), FParam("divisor", arrayOf(DataType.UBYTE, DataType.UWORD)), FParam("quotient", arrayOf(DataType.UBYTE, DataType.UWORD)), FParam("remainder", arrayOf(DataType.UBYTE, DataType.UWORD))), null), "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), - "any" to FSignature(true, listOf(FParam("values", ArrayDatatypes)), DataType.BOOL), - "all" to FSignature(true, listOf(FParam("values", ArrayDatatypes)), DataType.BOOL), "lsb" to FSignature(true, listOf(FParam("value", arrayOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE), "msb" to FSignature(true, listOf(FParam("value", arrayOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE), "mkword" to FSignature(true, listOf(FParam("msb", arrayOf(DataType.UBYTE)), FParam("lsb", arrayOf(DataType.UBYTE))), DataType.UWORD), diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index a89c226dc..3dd1d321b 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -33,7 +33,6 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, "min__byte", "min__ubyte", "min__word", "min__uword" -> funcMin(fcall, resultRegister) "max__byte", "max__ubyte", "max__word", "max__uword" -> funcMax(fcall, resultRegister) "abs__byte", "abs__word", "abs__float" -> funcAbs(fcall, resultRegister, sscope) - "any", "all" -> funcAnyAll(fcall, resultRegister, sscope) "sgn" -> funcSgn(fcall, resultRegister, sscope) "sqrt__ubyte", "sqrt__uword", "sqrt__float" -> funcSqrt(fcall, resultRegister, sscope) "divmod__ubyte" -> funcDivmod(fcall) @@ -726,63 +725,6 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, true, true) } - private fun funcAnyAll(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) { - val dt = fcall.args.single().type - val array = fcall.args[0] as PtIdentifier - when (dt) { - DataType.ARRAY_B, DataType.ARRAY_UB, DataType.STR -> { - outputAddressAndLengthOfArray(array) - asmgen.out(" jsr prog8_lib.func_${fcall.name}_b_into_A") - } - DataType.ARRAY_UW, DataType.ARRAY_W -> { - outputAddressAndLengthOfArray(array) - asmgen.out(" jsr prog8_lib.func_${fcall.name}_w_into_A") - } - DataType.ARRAY_F -> { - outputAddressAndLengthOfArray(array) - asmgen.out(" jsr floats.func_${fcall.name}_f_into_A") - } - in SplitWordArrayTypes -> { - val numElements = (asmgen.symbolTable.lookup(array.name) as StStaticVariable).length - when(fcall.name) { - "any" -> { - // any(lsb-array) or any(msb-array) - val arrayName = asmgen.asmVariableName(array) - asmgen.out(""" - lda #<${arrayName}_lsb - ldy #>${arrayName}_lsb - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - lda #$numElements - """) - asmgen.out(" jsr prog8_lib.func_${fcall.name}_b_into_A") - asmgen.out(" bne +") // shortcircuit - asmgen.out(""" - pha - lda #<${arrayName}_msb - ldy #>${arrayName}_msb - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - lda #$numElements - """) - asmgen.out(" jsr prog8_lib.func_${fcall.name}_b_into_A") - asmgen.out(""" - sta P8ZP_SCRATCH_REG - pla - ora P8ZP_SCRATCH_REG -+""") - } - "all" -> { - TODO("split words all") - } - else -> throw AssemblyError("weird call") - } - } - else -> throw AssemblyError("weird type $dt") - } - assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, dt in SignedDatatypes, true) - } - private fun funcAbs(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) { translateArguments(fcall, scope) val dt = fcall.args.single().type diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt index 6f27c7f8f..556e6111f 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt @@ -9,8 +9,6 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe fun translate(call: PtBuiltinFunctionCall): ExpressionCodeResult { return when(call.name) { - "any" -> funcAny(call) - "all" -> funcAll(call) "abs__byte", "abs__word", "abs__float" -> funcAbs(call) "cmp" -> funcCmp(call) "sgn" -> funcSgn(call) @@ -202,79 +200,6 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe return ExpressionCodeResult(result, dt, leftTr.resultReg, -1) } - private fun funcAny(call: PtBuiltinFunctionCall): ExpressionCodeResult { - val arrayName = call.args[0] as PtIdentifier - val arrayLength = codeGen.symbolTable.getLength(arrayName.name) - val result = mutableListOf() - val lengthReg = codeGen.registers.nextFree() - - if(arrayName.type in SplitWordArrayTypes) { - // any(lsb-array) or any(msb-array) - addInstr(result, IRInstruction(Opcode.PREPARECALL, immediate = 2), null) - val trLsb = exprGen.translateExpression(PtIdentifier(arrayName.name+"_lsb", DataType.ARRAY_UB, call.position)) - addToResult(result, trLsb, trLsb.resultReg, -1) - addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = lengthReg, immediate = arrayLength), null) - result += codeGen.makeSyscall(IMSyscall.ANY_BYTE, listOf(IRDataType.WORD to trLsb.resultReg, IRDataType.BYTE to lengthReg), IRDataType.BYTE to trLsb.resultReg) - val shortcircuitLabel = codeGen.createLabelName() - result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1 = trLsb.resultReg, immediate = 0) - it += IRInstruction(Opcode.BSTNE, labelSymbol = shortcircuitLabel) - it += IRInstruction(Opcode.PREPARECALL, immediate = 2) - } - val trMsb = exprGen.translateExpression(PtIdentifier(arrayName.name+"_msb", DataType.ARRAY_UB, call.position)) - addToResult(result, trMsb, trMsb.resultReg, -1) - addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = lengthReg, immediate = arrayLength), null) - result += codeGen.makeSyscall(IMSyscall.ANY_BYTE, listOf(IRDataType.WORD to trMsb.resultReg, IRDataType.BYTE to lengthReg), IRDataType.BYTE to trMsb.resultReg) - addInstr(result, IRInstruction(Opcode.ORR, IRDataType.BYTE, reg1=trLsb.resultReg, reg2=trMsb.resultReg), null) - result += IRCodeChunk(shortcircuitLabel, null) - return ExpressionCodeResult(result, IRDataType.BYTE, trLsb.resultReg, -1) - } - - val syscall = - when (arrayName.type) { - DataType.ARRAY_UB, - DataType.ARRAY_B -> IMSyscall.ANY_BYTE - DataType.ARRAY_UW, - DataType.ARRAY_W -> IMSyscall.ANY_WORD - DataType.ARRAY_F -> IMSyscall.ANY_FLOAT - else -> throw IllegalArgumentException("weird type") - } - addInstr(result, IRInstruction(Opcode.PREPARECALL, immediate = 2), null) - val tr = exprGen.translateExpression(arrayName) - addToResult(result, tr, tr.resultReg, -1) - addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = lengthReg, immediate = arrayLength!! and 255), null) - result += codeGen.makeSyscall(syscall, listOf(IRDataType.WORD to tr.resultReg, IRDataType.BYTE to lengthReg), IRDataType.BYTE to tr.resultReg) - return ExpressionCodeResult(result, IRDataType.BYTE, tr.resultReg, -1) - } - - private fun funcAll(call: PtBuiltinFunctionCall): ExpressionCodeResult { - val arrayName = call.args[0] as PtIdentifier - val arrayLength = codeGen.symbolTable.getLength(arrayName.name) - - if(arrayName.type in SplitWordArrayTypes) { - // this is a bit complicated to calculate.... have to check all recombined (lsb,msb) words for $0000 - TODO("all(split words $arrayName)") - } - - val syscall = - when(arrayName.type) { - DataType.ARRAY_UB, - DataType.ARRAY_B -> IMSyscall.ALL_BYTE - DataType.ARRAY_UW, - DataType.ARRAY_W -> IMSyscall.ALL_WORD - DataType.ARRAY_F -> IMSyscall.ALL_FLOAT - else -> throw IllegalArgumentException("weird type") - } - val result = mutableListOf() - addInstr(result, IRInstruction(Opcode.PREPARECALL, immediate = 2), null) - val tr = exprGen.translateExpression(arrayName) - addToResult(result, tr, tr.resultReg, -1) - val lengthReg = codeGen.registers.nextFree() - addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = lengthReg, immediate = arrayLength!! and 255), null) - result += codeGen.makeSyscall(syscall, listOf(IRDataType.WORD to tr.resultReg, IRDataType.BYTE to lengthReg), IRDataType.BYTE to tr.resultReg) - return ExpressionCodeResult(result, IRDataType.BYTE, tr.resultReg, -1) - } - private fun funcAbs(call: PtBuiltinFunctionCall): ExpressionCodeResult { val sourceDt = call.args.single().type val result = mutableListOf() diff --git a/compiler/res/prog8lib/anyall.p8 b/compiler/res/prog8lib/anyall.p8 new file mode 100644 index 000000000..39cbcb40d --- /dev/null +++ b/compiler/res/prog8lib/anyall.p8 @@ -0,0 +1,81 @@ +; any() and all() checks on arrays/memory buffers + +%option no_symbol_prefixing, ignore_unused + +anyall { + sub any(uword arrayptr, uword num_elements) -> bool { + ; -- returns true if any byte in the array is not zero. + cx16.r1 = arrayptr + if msb(num_elements)==0 { + for cx16.r0L in 0 to lsb(num_elements)-1 { + if cx16.r1[cx16.r0L]!=0 + return true + } + return false + } + repeat num_elements { + if @(cx16.r1)!=0 + return true + cx16.r1++ + } + return false + } + + sub all(uword arrayptr, uword num_elements) -> bool { + ; -- returns true if all bytes in the array are not zero. + cx16.r1 = arrayptr + if msb(num_elements)==0 { + for cx16.r0L in 0 to lsb(num_elements)-1 { + if cx16.r1[cx16.r0L]==0 + return false + } + return true + } + repeat num_elements { + if @(cx16.r1)==0 + return false + cx16.r1++ + } + return true + } + + sub anyw(uword arrayptr, uword num_elements) -> bool { + ; -- returns true if any word in the array is not zero. + ; doesn't work on @split arrays. + cx16.r1 = arrayptr + if msb(num_elements)==0 { + repeat lsb(num_elements) { + if peekw(cx16.r1)!=0 + return true + cx16.r1+=2 + } + return false + } + repeat num_elements { + if peekw(cx16.r1)!=0 + return true + cx16.r1+=2 + } + return false + } + + sub allw(uword arrayptr, uword num_elements) -> bool { + ; -- returns true if all words in the array are not zero. + ; doesn't work on @split arrays. + cx16.r1 = arrayptr + if msb(num_elements)==0 { + repeat lsb(num_elements) { + if peekw(cx16.r1)==0 + return false + cx16.r1+=2 + } + return true + } + repeat num_elements { + if peekw(cx16.r1)==0 + return false + cx16.r1+=2 + } + return true + } +} diff --git a/compiler/res/prog8lib/buffers.p8 b/compiler/res/prog8lib/buffers.p8 index d4a800256..fa8783573 100644 --- a/compiler/res/prog8lib/buffers.p8 +++ b/compiler/res/prog8lib/buffers.p8 @@ -1,5 +1,7 @@ ; experimental buffer data structures +%option no_symbol_prefixing, ignore_unused + smallringbuffer { ; -- A ringbuffer (FIFO queue) that occupies a single page in memory, containing 255 bytes maximum. ; You can store and retrieve words too. diff --git a/compiler/res/prog8lib/c64/floats_funcs.asm b/compiler/res/prog8lib/c64/floats_funcs.asm index aed00d25a..c4f0aba2b 100644 --- a/compiler/res/prog8lib/c64/floats_funcs.asm +++ b/compiler/res/prog8lib/c64/floats_funcs.asm @@ -16,26 +16,6 @@ a_times_5 .proc rts .pend -func_any_f_into_A .proc - jsr a_times_5 - jmp prog8_lib.func_any_b_into_A - .pend - -func_all_f_into_A .proc - jsr a_times_5 - jmp prog8_lib.func_all_b_into_A - .pend - -func_any_f_stack .proc - jsr a_times_5 - jmp prog8_lib.func_any_b_stack - .pend - -func_all_f_stack .proc - jsr a_times_5 - jmp prog8_lib.func_all_b_stack - .pend - func_abs_f_into_FAC1 .proc jsr MOVFM jmp ABS diff --git a/compiler/res/prog8lib/prog8_funcs.asm b/compiler/res/prog8lib/prog8_funcs.asm index 9cd58fb7e..f5796e0a4 100644 --- a/compiler/res/prog8lib/prog8_funcs.asm +++ b/compiler/res/prog8lib/prog8_funcs.asm @@ -1,60 +1,5 @@ ; ---- builtin functions - -func_any_b_into_A .proc - ; -- any(array), array in P8ZP_SCRATCH_W1, num bytes in A - sta _cmp_mod+1 ; self-modifying code - ldy #0 -- lda (P8ZP_SCRATCH_W1),y - bne _got_any - iny -_cmp_mod cpy #255 ; modified - bne - - lda #0 - rts -_got_any lda #1 - rts - .pend - - -func_all_b_into_A .proc - ; -- all(array), array in P8ZP_SCRATCH_W1, num bytes in A - sta _cmp_mod+1 ; self-modifying code - ldy #0 -- lda (P8ZP_SCRATCH_W1),y - beq _got_not_all - iny -_cmp_mod cpy #255 ; modified - bne - - lda #1 -_got_not_all rts - .pend - -func_any_w_into_A .proc - asl a - jmp func_any_b_into_A - .pend - -func_all_w_into_A .proc - ; -- all(warray), array in P8ZP_SCRATCH_W1, num bytes in A - asl a ; times 2 because of word - sta _cmp_mod+1 ; self-modifying code - ldy #0 -- lda (P8ZP_SCRATCH_W1),y - bne + - iny - lda (P8ZP_SCRATCH_W1),y - bne ++ - lda #0 - rts -+ iny -+ iny -_cmp_mod cpy #255 ; modified - bne - - lda #1 - rts - .pend - abs_b_into_A .proc ; -- A = abs(A) cmp #0 diff --git a/compiler/res/prog8lib/virtual/diskio.p8 b/compiler/res/prog8lib/virtual/diskio.p8 index 753145308..61a1d681d 100644 --- a/compiler/res/prog8lib/virtual/diskio.p8 +++ b/compiler/res/prog8lib/virtual/diskio.p8 @@ -11,7 +11,7 @@ diskio { %ir {{ loadm.w r65534,diskio.load.filenameptr loadm.w r65535,diskio.load.address_override - syscall 61 (): r0.b + syscall 48 (): r0.b returnr.b r0 }} } @@ -157,7 +157,7 @@ diskio { loadm.w r65533,diskio.save.filenameptr loadm.w r65534,diskio.save.start_address loadm.w r65535,diskio.save.savesize - syscall 58 (r65532.b, r65533.w, r65534.w, r65535.w): r0.b + syscall 45 (r65532.b, r65533.w, r65534.w, r65535.w): r0.b returnr.b r0 }} } @@ -169,7 +169,7 @@ diskio { loadm.w r65533,diskio.save.filenameptr loadm.w r65534,diskio.save.start_address loadm.w r65535,diskio.save.savesize - syscall 58 (r65532.b, r65533.w, r65534.w, r65535.w): r0.b + syscall 45 (r65532.b, r65533.w, r65534.w, r65535.w): r0.b returnr.b r0 }} } @@ -184,7 +184,7 @@ diskio { %ir {{ loadm.w r65534,diskio.load.filenameptr loadm.w r65535,diskio.load.address_override - syscall 56 (r65534.w, r65535.w): r0.w + syscall 43 (r65534.w, r65535.w): r0.w returnr.w r0 }} } @@ -196,7 +196,7 @@ diskio { %ir {{ loadm.w r65534,diskio.load_raw.filenameptr loadm.w r65535,diskio.load_raw.start_address - syscall 57 (r65534.w, r65535.w): r0.w + syscall 44 (r65534.w, r65535.w): r0.w returnr.w r0 }} } @@ -205,7 +205,7 @@ diskio { ; -- delete a file on the drive %ir {{ loadm.w r65535,diskio.delete.filenameptr - syscall 59 (r65535.w) + syscall 46 (r65535.w) }} } @@ -214,7 +214,7 @@ diskio { %ir {{ loadm.w r65534,diskio.rename.oldfileptr loadm.w r65535,diskio.rename.newfileptr - syscall 60 (r65534.w, r65535.w) + syscall 47 (r65534.w, r65535.w) }} } } diff --git a/compiler/res/prog8lib/virtual/floats.p8 b/compiler/res/prog8lib/virtual/floats.p8 index 882e4295b..29676b9a4 100644 --- a/compiler/res/prog8lib/virtual/floats.p8 +++ b/compiler/res/prog8lib/virtual/floats.p8 @@ -13,7 +13,7 @@ sub print(float value) { ; ---- prints the floating point value (without a newline and no leading spaces). %ir {{ loadm.f fr65535,floats.print.value - syscall 25 (fr65535.f) + syscall 15 (fr65535.f) return }} } @@ -24,7 +24,7 @@ sub tostr(float value) -> str { %ir {{ load.w r65535,floats.tostr.buffer loadm.f fr65535,floats.tostr.value - syscall 47 (r65535.w, fr65535.f) + syscall 34 (r65535.w, fr65535.f) load.w r0,floats.tostr.buffer returnr.w r0 }} @@ -34,7 +34,7 @@ sub parse(str value) -> float { ; -- parse a string value of a number to float %ir {{ loadm.w r65535,floats.parse.value - syscall 45 (r65535.w): fr0.f + syscall 32 (r65535.w): fr0.f returnr.f fr0 }} } @@ -147,7 +147,7 @@ sub ceil(float value) -> float { sub rnd() -> float { %ir {{ - syscall 35 () : fr0.f + syscall 22 () : fr0.f returnr.f fr0 }} } @@ -155,7 +155,7 @@ sub rnd() -> float { sub rndseed(float seed) { %ir {{ loadm.f fr65535,floats.rndseed.seed - syscall 32 (fr65535.f) + syscall 19 (fr65535.f) return }} } diff --git a/compiler/res/prog8lib/virtual/math.p8 b/compiler/res/prog8lib/virtual/math.p8 index e7087710b..ba7cd9c9f 100644 --- a/compiler/res/prog8lib/virtual/math.p8 +++ b/compiler/res/prog8lib/virtual/math.p8 @@ -164,14 +164,14 @@ math { sub rnd() -> ubyte { %ir {{ - syscall 33 (): r0.b + syscall 20 (): r0.b returnr.b r0 }} } sub rndw() -> uword { %ir {{ - syscall 34 (): r0.w + syscall 21 (): r0.w returnr.w r0 }} } @@ -199,7 +199,7 @@ math { %ir {{ loadm.w r65534,math.rndseed.seed1 loadm.w r65535,math.rndseed.seed2 - syscall 31 (r65534.w, r65535.w) + syscall 19 (r65534.w, r65535.w) return }} } @@ -280,7 +280,7 @@ math { loadm.b r65533,math.atan2.y1 loadm.b r65534,math.atan2.x2 loadm.b r65535,math.atan2.y2 - syscall 44 (r65532.b, r65533.b, r65534.b, r65535.b): r0.b + syscall 31 (r65532.b, r65533.b, r65534.b, r65535.b): r0.b returnr.b r0 }} } @@ -294,7 +294,7 @@ math { ; - not all multiplications in the source code result in an actual multiplication call: ; some simpler multiplications will be optimized away into faster routines. These will not set the upper 16 bits at all! %ir {{ - syscall 46 (): r0.w + syscall 33 (): r0.w returnr.w r0 }} } diff --git a/compiler/res/prog8lib/virtual/string.p8 b/compiler/res/prog8lib/virtual/string.p8 index cc71e3433..3079004ac 100644 --- a/compiler/res/prog8lib/virtual/string.p8 +++ b/compiler/res/prog8lib/virtual/string.p8 @@ -83,7 +83,7 @@ string { %ir {{ loadm.w r65534,string.copy.source loadm.w r65535,string.copy.target - syscall 52 (r65534.w, r65535.w): r0.b + syscall 39 (r65534.w, r65535.w): r0.b returnr.b r0 }} } @@ -103,7 +103,7 @@ string { %ir {{ loadm.w r65534,string.compare.st1 loadm.w r65535,string.compare.st2 - syscall 29 (r65534.w, r65535.w) : r0.b + syscall 16 (r65534.w, r65535.w) : r0.b returnr.b r0 }} } diff --git a/compiler/res/prog8lib/virtual/syslib.p8 b/compiler/res/prog8lib/virtual/syslib.p8 index 257884240..7640ecfbd 100644 --- a/compiler/res/prog8lib/virtual/syslib.p8 +++ b/compiler/res/prog8lib/virtual/syslib.p8 @@ -34,7 +34,7 @@ sys { %ir {{ loadm.w r65534,sys.internal_stringcopy.source loadm.w r65535,sys.internal_stringcopy.tgt - syscall 52 (r65534.w, r65535.w): r0.b + syscall 39 (r65534.w, r65535.w): r0.b }} } @@ -43,7 +43,7 @@ sys { loadm.w r65533,sys.memcopy.source loadm.w r65534,sys.memcopy.tgt loadm.w r65535,sys.memcopy.count - syscall 49 (r65533.w, r65534.w, r65535.w) + syscall 36 (r65533.w, r65534.w, r65535.w) }} } @@ -52,7 +52,7 @@ sys { loadm.w r65533,sys.memset.mem loadm.w r65534,sys.memset.numbytes loadm.b r65535,sys.memset.value - syscall 50 (r65533.w, r65534.w, r65535.b) + syscall 37 (r65533.w, r65534.w, r65535.b) }} } @@ -61,7 +61,7 @@ sys { loadm.w r65533,sys.memsetw.mem loadm.w r65534,sys.memsetw.numwords loadm.w r65535,sys.memsetw.value - syscall 51 (r65533.w, r65534.w, r65535.w) + syscall 38 (r65533.w, r65534.w, r65535.w) }} } @@ -128,7 +128,7 @@ sys { %ir {{ loadm.w r65534,sys.gfx_getpixel.xx loadm.w r65535,sys.gfx_getpixel.yy - syscall 30 (r65534.w, r65535.w): r0.b + syscall 17 (r65534.w, r65535.w): r0.b returnr.b r0 }} } diff --git a/compiler/res/prog8lib/virtual/textio.p8 b/compiler/res/prog8lib/virtual/textio.p8 index 650e594bf..a6dc17d6a 100644 --- a/compiler/res/prog8lib/virtual/textio.p8 +++ b/compiler/res/prog8lib/virtual/textio.p8 @@ -7,14 +7,14 @@ txt { sub width() -> ubyte { %ir {{ - syscall 62 (): r0.w + syscall 49 (): r0.w returnr.b r0 }} } sub height() -> ubyte { %ir {{ - syscall 62 (): r0.w + syscall 49 (): r0.w msig.b r1,r0 returnr.b r1 }} diff --git a/compiler/src/prog8/compiler/BuiltinFunctions.kt b/compiler/src/prog8/compiler/BuiltinFunctions.kt index f202b516c..d67cfd2d1 100644 --- a/compiler/src/prog8/compiler/BuiltinFunctions.kt +++ b/compiler/src/prog8/compiler/BuiltinFunctions.kt @@ -19,8 +19,6 @@ internal val constEvaluatorsForBuiltinFuncs: Map "sqrt__ubyte" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, false) { sqrt(it.toDouble()) } }, "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) } }, - "any" to { a, p, prg -> collectionArgBoolResult(a, p, prg) { array->array.any { it!=0.0 } } }, - "all" to { a, p, prg -> collectionArgBoolResult(a, p, prg) { array->array.all { it!=0.0 } } }, "lsb" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, true) { x: Int -> (x and 255).toDouble() } }, "msb" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, true) { x: Int -> (x ushr 8 and 255).toDouble()} }, "mkword" to ::builtinMkword, diff --git a/compiler/test/vm/TestCompilerVirtual.kt b/compiler/test/vm/TestCompilerVirtual.kt index 724644b67..7b4cf065d 100644 --- a/compiler/test/vm/TestCompilerVirtual.kt +++ b/compiler/test/vm/TestCompilerVirtual.kt @@ -20,23 +20,6 @@ import prog8tests.helpers.compileText import kotlin.io.path.readText class TestCompilerVirtual: FunSpec({ - test("compile virtual: any all builtin funcs") { - val src = """ -main { - - sub start() { - uword[] words = [1111,2222,0,4444,3333] - bool result = all(words) - cx16.r0++ - result = any(words) - } -}""" - val target = VMTarget() - val result = compileText(target, true, src, writeAssembly = true)!! - val virtfile = result.compilationOptions.outputDir.resolve(result.compilerAst.name + ".p8ir") - VmRunner().runProgram(virtfile.readText()) - } - test("compile virtual: array with pointers") { val src = """ main { diff --git a/docs/source/index.rst b/docs/source/index.rst index fd886a06b..44ee4c0a9 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -85,7 +85,7 @@ Features - Conditional branches for status flags that map 1:1 to processor branch instructions for optimal efficiency - ``when`` statement to avoid if-else chains - ``in`` expression for concise and efficient multi-value/containment test -- Several powerful built-in functions, such as ``lsb``, ``msb``, ``min``, ``max``, ``rol``, ``ror`` +- Several specialized built-in functions, such as ``lsb``, ``msb``, ``min``, ``max``, ``rol``, ``ror`` - Variable data types include signed and unsigned bytes and words, arrays, strings. - Various powerful built-in libraries to do I/O, number conversions, graphics and more - Floating point math is supported on select compiler targets. diff --git a/docs/source/libraries.rst b/docs/source/libraries.rst index 686742157..6710b07b8 100644 --- a/docs/source/libraries.rst +++ b/docs/source/libraries.rst @@ -73,12 +73,6 @@ divmod (dividend, divisor, quotient, remainder) Array operations ^^^^^^^^^^^^^^^^ -any (x) - true if any of the values in the array value x is 'true' (not zero), else false. - -all (x) - true if all of the values in the array value x are 'true' (not zero), else false. - len (x) Number of values in the array value x, or the number of characters in a string (excluding the 0-byte). Note: this can be different from the number of *bytes* in memory if the datatype isn't a byte. See sizeof(). @@ -369,6 +363,25 @@ sys (part of syslib) Low-level function that should normally not be used. +anyall +------ +Routines to check if any or all values in an array or memory buffer are not zero. + +``any (arrayptr, num_elements)`` + true if any of the byte values in the array is not zero, else false. + +``all (arrayptr, num_elements)`` + true if all of the byte values in the array are not zero, else false. + +``anyw (arrayptr, num_elements)`` + true if any of the word values in the array is not zero, else false. + Doesn't work on split arrays. + +``allw (arrayptr, num_elements)`` + true if all of the word values in the array are not zero, else false. + Doesn't work on split arrays. + + conv ---- Routines to convert strings to numbers or vice versa. diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 1ced69847..bb2f88d02 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,8 +1,6 @@ TODO ==== -Get rid of any() and all() as builtin functions? Replace them with regular subroutines in buffer.p8 for example? - See open issues on github. IR: add SEC and CLC instructions in place of call to sys.set_carry() and sys.clear_carry(). (check more inline sub calls that should be a single instruction?) diff --git a/examples/test.p8 b/examples/test.p8 index bfad393c5..1eed0a327 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,20 +1,66 @@ %import textio -%import buffers -%zeropage basicsafe +%import anyall + %option no_sysinit main { + byte[256] barray + word[128] warray + uword large_barray=memory("bytes", 1000, 0) + uword large_warray=memory("words", 1000, 0) + + sub check() { + txt.print_bool(anyall.all(barray, 256)) + txt.spc() + txt.print_bool(anyall.any(barray, 256)) + txt.nl() + txt.print_bool(anyall.allw(warray, 128)) + txt.spc() + txt.print_bool(anyall.anyw(warray, 128)) + txt.nl() + txt.print_bool(anyall.all(large_barray, 1000)) + txt.spc() + txt.print_bool(anyall.any(large_barray, 1000)) + txt.nl() + txt.print_bool(anyall.allw(large_warray, 500)) + txt.spc() + txt.print_bool(anyall.anyw(large_warray, 500)) + txt.nl() + txt.nl() + } + sub start() { - smallringbuffer.init() + sys.memset(large_barray, 1000, 0) + sys.memset(large_warray, 1000, 0) - smallringbuffer.put(123) - txt.print_ub(smallringbuffer.get()) - txt.nl() + check() + barray[250] = 99 + warray[100] = $0100 + large_barray[900] = 99 + large_warray[900] = 99 + check() + sys.memset(barray, 255, 1) + sys.memset(warray, 254, 1) + sys.memset(large_barray, 999, 1) + sys.memset(large_warray, 998, 1) + check() + barray[255]=1 + warray[127]=1 + @(large_barray+999)=1 + @(large_warray+999)=1 + check() + repeat {} - smallringbuffer.putw(12345) - txt.print_uw(smallringbuffer.getw()) - txt.nl() +; smallringbuffer.init() +; +; smallringbuffer.put(123) +; txt.print_ub(smallringbuffer.get()) +; txt.nl() +; +; smallringbuffer.putw(12345) +; txt.print_uw(smallringbuffer.getw()) +; txt.nl() } } diff --git a/intermediate/src/prog8/intermediate/IMSyscall.kt b/intermediate/src/prog8/intermediate/IMSyscall.kt index 8c992a6af..ab6f4417d 100644 --- a/intermediate/src/prog8/intermediate/IMSyscall.kt +++ b/intermediate/src/prog8/intermediate/IMSyscall.kt @@ -5,19 +5,6 @@ package prog8.intermediate // Note that in the VM these are translated into whatever the corresponding Syscall number in the VM is. enum class IMSyscall(val number: Int) { - SORT_UBYTE(0x1000), - SORT_BYTE(0x1001), - SORT_UWORD(0x1002), - SORT_WORD(0x1003), - ANY_BYTE(0x1004), - ANY_WORD(0x1005), - ANY_FLOAT(0x1006), - ALL_BYTE(0x1007), - ALL_WORD(0x1008), - ALL_FLOAT(0x1009), - REVERSE_BYTES(0x100a), - REVERSE_WORDS(0x100b), - REVERSE_FLOATS(0x100c), COMPARE_STRINGS(0x100d), STRING_CONTAINS(0x100e), BYTEARRAY_CONTAINS(0x100f), diff --git a/syntax-files/IDEA/Prog8.xml b/syntax-files/IDEA/Prog8.xml index d83c99057..b0b633718 100644 --- a/syntax-files/IDEA/Prog8.xml +++ b/syntax-files/IDEA/Prog8.xml @@ -14,7 +14,7 @@ - + diff --git a/syntax-files/NotepadPlusPlus/Prog8.xml b/syntax-files/NotepadPlusPlus/Prog8.xml index eb5d1131d..bb0b86953 100644 --- a/syntax-files/NotepadPlusPlus/Prog8.xml +++ b/syntax-files/NotepadPlusPlus/Prog8.xml @@ -27,7 +27,7 @@ void const str byte ubyte bool word uword float zp shared split requirezp nozp %address %asm %ir %asmbinary %asminclude %breakpoint %encoding %import %launcher %option %output %zeropage %zpreserved %zpallowed inline sub asmsub romsub clobbers asm if when else if_cc if_cs if_eq if_mi if_neg if_nz if_pl if_pos if_vc if_vs if_z for in step do while repeat unroll break continue return goto - abs all any call callfar clamp cmp divmod len lsb lsl lsr memory mkword min max msb peek peekw peekf poke pokew pokef rsave rsavex rrestore rrestorex rnd rndw rol rol2 ror ror2 setlsb setmsb sgn sizeof sqrtw + abs call callfar clamp cmp divmod len lsb lsl lsr memory mkword min max msb peek peekw peekf poke pokew pokef rsave rsavex rrestore rrestorex rnd rndw rol rol2 ror ror2 setlsb setmsb sgn sizeof sqrtw true false not and or xor as to downto |> diff --git a/syntax-files/Vim/prog8_builtins.vim b/syntax-files/Vim/prog8_builtins.vim index 54e954254..47a399927 100644 --- a/syntax-files/Vim/prog8_builtins.vim +++ b/syntax-files/Vim/prog8_builtins.vim @@ -10,7 +10,7 @@ syn keyword prog8BuiltInFunc sgn sqrtw " Array functions -syn keyword prog8BuiltInFunc any all len +syn keyword prog8BuiltInFunc len " Miscellaneous functions syn keyword prog8BuiltInFunc cmp divmod lsb msb mkword min max peek peekw peekf poke pokew pokef rsave rsavex rrestore rrestorex diff --git a/virtualmachine/src/prog8/vm/SysCalls.kt b/virtualmachine/src/prog8/vm/SysCalls.kt index d54b06f64..0747d35bb 100644 --- a/virtualmachine/src/prog8/vm/SysCalls.kt +++ b/virtualmachine/src/prog8/vm/SysCalls.kt @@ -25,54 +25,41 @@ SYSCALLS: 12 = decimal string to word (signed) 13 = wait ; wait certain amount of jiffies (1/60 sec) 14 = waitvsync ; wait on vsync -15 = sort_ubyte array -16 = sort_byte array -17 = sort_uword array -18 = sort_word array -19 = any_byte array -20 = any_word array -21 = any_float array -22 = all_byte array -23 = all_word array -24 = all_float array -25 = print_f (floating point value in fp reg 0) -26 = reverse_bytes array -27 = reverse_words array -28 = reverse_floats array -29 = compare strings -30 = gfx_getpixel ; get byte pixel value at coordinates r0.w/r1.w -31 = rndseed -32 = rndfseed -33 = RND -34 = RNDW -35 = RNDF -36 = STRING_CONTAINS -37 = BYTEARRAY_CONTAINS -38 = WORDARRAY_CONTAINS -39 = CLAMP_BYTE -40 = CLAMP_UBYTE -41 = CLAMP_WORD -42 = CLAMP_UWORD -43 = CLAMP_FLOAT -44 = ATAN -45 = str to float -46 = MUL16_LAST_UPPER -47 = float to str -48 = FLOATARRAY_CONTAINS -49 = memcopy -50 = memset -51 = memsetw -52 = stringcopy -53 = ARRAYCOPY_SPLITW_TO_NORMAL -54 = ARRAYCOPY_NORMAL_TO_SPLITW -55 = memcopy_small -56 = load -57 = load_raw -58 = save -59 = delete -60 = rename -61 = directory -62 = getconsolesize +15 = print_f (floating point value in fp reg 0) +16 = compare strings +17 = gfx_getpixel ; get byte pixel value at coordinates r0.w/r1.w +18 = rndseed +19 = rndfseed +20 = RND +21 = RNDW +22 = RNDF +23 = STRING_CONTAINS +24 = BYTEARRAY_CONTAINS +25 = WORDARRAY_CONTAINS +26 = CLAMP_BYTE +27 = CLAMP_UBYTE +28 = CLAMP_WORD +29 = CLAMP_UWORD +30 = CLAMP_FLOAT +31 = ATAN +32 = str to float +33 = MUL16_LAST_UPPER +34 = float to str +35 = FLOATARRAY_CONTAINS +36 = memcopy +37 = memset +38 = memsetw +39 = stringcopy +40 = ARRAYCOPY_SPLITW_TO_NORMAL +41 = ARRAYCOPY_NORMAL_TO_SPLITW +42 = memcopy_small +43 = load +44 = load_raw +45 = save +46 = delete +47 = rename +48 = directory +49 = getconsolesize */ enum class Syscall { @@ -91,20 +78,7 @@ enum class Syscall { STR_TO_WORD, WAIT, WAITVSYNC, - SORT_UBYTE, - SORT_BYTE, - SORT_UWORD, - SORT_WORD, - ANY_BYTE, - ANY_WORD, - ANY_FLOAT, - ALL_BYTE, - ALL_WORD, - ALL_FLOAT, PRINT_F, - REVERSE_BYTES, - REVERSE_WORDS, - REVERSE_FLOATS, COMPARE_STRINGS, GFX_GETPIXEL, RNDSEED, @@ -243,149 +217,6 @@ object SysCalls { Thread.sleep(time.toLong() * 1000/60) } Syscall.WAITVSYNC -> vm.waitvsync() - Syscall.SORT_UBYTE -> { - val (addressV, lengthV) = getArgValues(callspec.arguments, vm) - val address = (addressV as UShort).toInt() - val length = (lengthV as UByte).toInt() - val array = IntProgression.fromClosedRange(address, address+length-1, 1).map { - vm.memory.getUB(it) - }.sorted() - array.withIndex().forEach { (index, value)-> - vm.memory.setUB(address+index, value) - } - } - Syscall.SORT_BYTE -> { - val (addressV, lengthV) = getArgValues(callspec.arguments, vm) - val address = (addressV as UShort).toInt() - val length = (lengthV as UByte).toInt() - val array = IntProgression.fromClosedRange(address, address+length-1, 1).map { - vm.memory.getSB(it) - }.sorted() - array.withIndex().forEach { (index, value)-> - vm.memory.setSB(address+index, value) - } - } - Syscall.SORT_UWORD -> { - val (addressV, lengthV) = getArgValues(callspec.arguments, vm) - val address = (addressV as UShort).toInt() - val length = (lengthV as UByte).toInt() - val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map { - vm.memory.getUW(it) - }.sorted() - array.withIndex().forEach { (index, value)-> - vm.memory.setUW(address+index*2, value) - } - } - Syscall.SORT_WORD -> { - val (addressV, lengthV) = getArgValues(callspec.arguments, vm) - val address = (addressV as UShort).toInt() - val length = (lengthV as UByte).toInt() - val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map { - vm.memory.getSW(it) - }.sorted() - array.withIndex().forEach { (index, value)-> - vm.memory.setSW(address+index*2, value) - } - } - Syscall.REVERSE_BYTES -> { - val (addressV, lengthV) = getArgValues(callspec.arguments, vm) - val address = (addressV as UShort).toInt() - val length = (lengthV as UByte).toInt() - val array = IntProgression.fromClosedRange(address, address+length-1, 1).map { - vm.memory.getUB(it) - }.reversed() - array.withIndex().forEach { (index, value)-> - vm.memory.setUB(address+index, value) - } - } - Syscall.REVERSE_WORDS -> { - val (addressV, lengthV) = getArgValues(callspec.arguments, vm) - val address = (addressV as UShort).toInt() - val length = (lengthV as UByte).toInt() - val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map { - vm.memory.getUW(it) - }.reversed() - array.withIndex().forEach { (index, value)-> - vm.memory.setUW(address+index*2, value) - } - } - Syscall.REVERSE_FLOATS -> { - val (addressV, lengthV) = getArgValues(callspec.arguments, vm) - val address = (addressV as UShort).toInt() - val length = (lengthV as UByte).toInt() - val array = IntProgression.fromClosedRange(address, address+length*4-2, 4).map { - vm.memory.getFloat(it) - }.reversed() - array.withIndex().forEach { (index, value)-> - vm.memory.setFloat(address+index*4, value) - } - } - Syscall.ANY_BYTE -> { - val (addressV, lengthV) = getArgValues(callspec.arguments, vm) - val address = (addressV as UShort).toInt() - val length = (lengthV as UByte).toInt() - val endAddressExcl = address + if(length==0) 256 else length - val addresses = IntProgression.fromClosedRange(address, endAddressExcl-1, 1) - if(addresses.any { vm.memory.getUB(it).toInt()!=0 }) - returnValue(callspec.returns.single(), 1, vm) - else - returnValue(callspec.returns.single(), 0, vm) - } - Syscall.ANY_WORD -> { - val (addressV, lengthV) = getArgValues(callspec.arguments, vm) - val address = (addressV as UShort).toInt() - val length = (lengthV as UByte).toInt() - val endAddressExcl = address + if(length==0) 256*2 else length*2 - val addresses = IntProgression.fromClosedRange(address, endAddressExcl-2, 2) - if(addresses.any { vm.memory.getUW(it).toInt()!=0 }) - returnValue(callspec.returns.single(), 1, vm) - else - returnValue(callspec.returns.single(), 0, vm) - } - Syscall.ANY_FLOAT -> { - val (addressV, lengthV) = getArgValues(callspec.arguments, vm) - val address = (addressV as UShort).toInt() - val length = (lengthV as UByte).toInt() - val endAddressExcl = address + (if(length==0) 256*vm.machinedef.FLOAT_MEM_SIZE else length*vm.machinedef.FLOAT_MEM_SIZE) - val addresses = IntProgression.fromClosedRange(address, endAddressExcl-vm.machinedef.FLOAT_MEM_SIZE, 4) - if(addresses.any { vm.memory.getFloat(it).toInt()!=0 }) - returnValue(callspec.returns.single(), 1, vm) - else - returnValue(callspec.returns.single(), 0, vm) - } - Syscall.ALL_BYTE -> { - val (addressV, lengthV) = getArgValues(callspec.arguments, vm) - val address = (addressV as UShort).toInt() - val length = (lengthV as UByte).toInt() - val endAddressExcl = address + if(length==0) 256 else length - val addresses = IntProgression.fromClosedRange(address, endAddressExcl-1, 1) - if(addresses.all { vm.memory.getUB(it).toInt()!=0 }) - returnValue(callspec.returns.single(), 1, vm) - else - returnValue(callspec.returns.single(), 0, vm) - } - Syscall.ALL_WORD -> { - val (addressV, lengthV) = getArgValues(callspec.arguments, vm) - val address = (addressV as UShort).toInt() - val length = (lengthV as UByte).toInt() - val endAddressExcl = address + if(length==0) 256*2 else length*2 - val addresses = IntProgression.fromClosedRange(address, endAddressExcl-2, 2) - if(addresses.all { vm.memory.getUW(it).toInt()!=0 }) - returnValue(callspec.returns.single(), 1, vm) - else - returnValue(callspec.returns.single(), 0, vm) - } - Syscall.ALL_FLOAT -> { - val (addressV, lengthV) = getArgValues(callspec.arguments, vm) - val address = (addressV as UShort).toInt() - val length = (lengthV as UByte).toInt() - val endAddressExcl = address + (if(length==0) 256*vm.machinedef.FLOAT_MEM_SIZE else length*vm.machinedef.FLOAT_MEM_SIZE) - val addresses = IntProgression.fromClosedRange(address, endAddressExcl-vm.machinedef.FLOAT_MEM_SIZE, 4) - if(addresses.all { vm.memory.getFloat(it).toInt()!=0 }) - returnValue(callspec.returns.single(), 1, vm) - else - returnValue(callspec.returns.single(), 0, vm) - } Syscall.PRINT_F -> { val value = getArgValues(callspec.arguments, vm).single() as Double if(value.toInt().toDouble()==value) diff --git a/virtualmachine/src/prog8/vm/VmProgramLoader.kt b/virtualmachine/src/prog8/vm/VmProgramLoader.kt index 021acf3ad..b05b7637e 100644 --- a/virtualmachine/src/prog8/vm/VmProgramLoader.kt +++ b/virtualmachine/src/prog8/vm/VmProgramLoader.kt @@ -103,19 +103,6 @@ class VmProgramLoader { if(ins.opcode == Opcode.SYSCALL) { // convert IR Syscall to VM Syscall val vmSyscall = when(ins.immediate!!) { - IMSyscall.SORT_UBYTE.number -> Syscall.SORT_UBYTE - IMSyscall.SORT_BYTE.number -> Syscall.SORT_BYTE - IMSyscall.SORT_UWORD.number -> Syscall.SORT_UWORD - IMSyscall.SORT_WORD.number -> Syscall.SORT_WORD - IMSyscall.ANY_BYTE.number -> Syscall.ANY_BYTE - IMSyscall.ANY_WORD.number -> Syscall.ANY_WORD - IMSyscall.ANY_FLOAT.number -> Syscall.ANY_FLOAT - IMSyscall.ALL_BYTE.number -> Syscall.ALL_BYTE - IMSyscall.ALL_WORD.number -> Syscall.ALL_WORD - IMSyscall.ALL_FLOAT.number -> Syscall.ALL_FLOAT - IMSyscall.REVERSE_BYTES.number -> Syscall.REVERSE_BYTES - IMSyscall.REVERSE_WORDS.number -> Syscall.REVERSE_WORDS - IMSyscall.REVERSE_FLOATS.number -> Syscall.REVERSE_FLOATS IMSyscall.COMPARE_STRINGS.number -> Syscall.COMPARE_STRINGS IMSyscall.STRING_CONTAINS.number -> Syscall.STRING_CONTAINS IMSyscall.BYTEARRAY_CONTAINS.number -> Syscall.BYTEARRAY_CONTAINS