diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index 9bbbcd8df..266e93a15 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -43,7 +43,6 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, "abs" -> funcAbs(fcall, func, resultToStack, resultRegister, sscope) "any", "all" -> funcAnyAll(fcall, func, resultToStack, resultRegister, sscope) "sgn" -> funcSgn(fcall, func, resultToStack, resultRegister, sscope) - "rnd", "rndw" -> funcRnd(func, resultToStack, resultRegister, sscope) "sqrt16" -> funcSqrt16(fcall, func, resultToStack, resultRegister, sscope) "rol" -> funcRol(fcall) "rol2" -> funcRol2(fcall) @@ -687,28 +686,6 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, } } - private fun funcRnd(func: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: Subroutine?) { - when(func.name) { - "rnd" -> { - if(resultToStack) - asmgen.out(" jsr prog8_lib.func_rnd_stack") - else { - asmgen.out(" jsr math.randbyte") - assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, scope, asmgen), CpuRegister.A) - } - } - "rndw" -> { - if(resultToStack) - asmgen.out(" jsr prog8_lib.func_rndw_stack") - else { - asmgen.out(" jsr math.randword") - assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, scope, asmgen), RegisterOrPair.AY) - } - } - else -> throw AssemblyError("wrong func") - } - } - private fun funcPokeW(fcall: IFunctionCall) { when(val addrExpr = fcall.args[0]) { is NumericLiteral -> { diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt index 903feb67b..a420ccf5b 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt @@ -26,8 +26,6 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe "rsavex", "rrestore", "rrestorex" -> IRCodeChunk(call.position) // vm doesn't have registers to save/restore - "rnd" -> funcRnd(resultRegister, call.position) - "rndw" -> funcRndw(resultRegister, call.position) "callfar" -> throw AssemblyError("callfar() is for cx16 target only") "callrom" -> throw AssemblyError("callrom() is for cx16 target only") "msb" -> funcMsb(call, resultRegister) @@ -309,18 +307,6 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe return code } - private fun funcRnd(resultRegister: Int, position: Position): IRCodeChunk { - val code = IRCodeChunk(position) - code += IRInstruction(Opcode.RND, IRDataType.BYTE, reg1=resultRegister) - return code - } - - private fun funcRndw(resultRegister: Int, position: Position): IRCodeChunk { - val code = IRCodeChunk(position) - code += IRInstruction(Opcode.RND, IRDataType.WORD, reg1=resultRegister) - return code - } - private fun funcMemory(call: PtBuiltinFunctionCall, resultRegister: Int): IRCodeChunk { val name = (call.args[0] as PtString).value val code = IRCodeChunk(call.position) diff --git a/compiler/res/prog8lib/math.p8 b/compiler/res/prog8lib/math.p8 index d30469d66..028c3a786 100644 --- a/compiler/res/prog8lib/math.p8 +++ b/compiler/res/prog8lib/math.p8 @@ -71,6 +71,18 @@ _sinecosR8 .char trunc(127.0 * sin(range(180+45) * rad(360.0/180.0))) }} } + asmsub rnd() -> ubyte @A { + %asm {{ + jmp math.randbyte + }} + } + + asmsub rndw() -> uword @AY { + %asm {{ + jmp math.randword + }} + } + asmsub rndseed(uword seed1 @AY, uword seed2 @R0) clobbers(A,Y) { ; -- reset the pseudo RNG's seed values. Defaults are: $a55a, $7653. %asm {{ diff --git a/compiler/res/prog8lib/prog8_funcs.asm b/compiler/res/prog8lib/prog8_funcs.asm index 1d7c2f26f..5728d0bc1 100644 --- a/compiler/res/prog8lib/prog8_funcs.asm +++ b/compiler/res/prog8lib/prog8_funcs.asm @@ -244,24 +244,6 @@ func_sqrt16_into_A .proc rts .pend -func_rnd_stack .proc - ; -- put a random ubyte on the estack - jsr math.randbyte - sta P8ESTACK_LO,x - dex - rts - .pend - -func_rndw_stack .proc - ; -- put a random uword on the estack - jsr math.randword - sta P8ESTACK_LO,x - tya - sta P8ESTACK_HI,x - dex - rts - .pend - func_sort_ub .proc ; 8bit unsigned sort diff --git a/compiler/res/prog8lib/virtual/math.p8 b/compiler/res/prog8lib/virtual/math.p8 index ce51e0f56..76782ccde 100644 --- a/compiler/res/prog8lib/virtual/math.p8 +++ b/compiler/res/prog8lib/virtual/math.p8 @@ -159,6 +159,19 @@ math { return costab[radians] as byte } + sub rnd() -> ubyte { + %ir {{ + rnd.b r0 + return + }} + } + + sub rndw() -> uword { + %ir {{ + rnd.w r0 + return + }} + } sub rndseed(uword seed1, uword seed2) { ; -- reset the pseudo RNG's seed values. Defaults are: $a55a, $7653. @@ -166,6 +179,7 @@ math { loadm.w r0,math.rndseed.seed1 loadm.w r1,math.rndseed.seed2 syscall 31 + return }} } } diff --git a/compiler/test/TestBuiltinFunctions.kt b/compiler/test/TestBuiltinFunctions.kt index f59699599..f7fc4fa36 100644 --- a/compiler/test/TestBuiltinFunctions.kt +++ b/compiler/test/TestBuiltinFunctions.kt @@ -44,18 +44,18 @@ class TestBuiltinFunctions: FunSpec({ conv.returns.reg shouldBe RegisterOrPair.A } - test("not-pure func with fixed type") { - val func = BuiltinFunctions.getValue("rnd") - func.name shouldBe "rnd" - func.parameters.size shouldBe 0 + test("not-pure func with varying result value type") { + val func = BuiltinFunctions.getValue("cmp") + func.name shouldBe "cmp" + func.parameters.size shouldBe 2 func.pure shouldBe false - func.returnType shouldBe DataType.UBYTE + func.returnType shouldBe null - val conv = func.callConvention(emptyList()) - conv.params.size shouldBe 0 - conv.returns.dt shouldBe DataType.UBYTE + val conv = func.callConvention(listOf(DataType.UWORD, DataType.UWORD)) + conv.params.size shouldBe 2 + conv.returns.dt shouldBe null conv.returns.floatFac1 shouldBe false - conv.returns.reg shouldBe RegisterOrPair.A + conv.returns.reg shouldBe null } test("func without return type") { diff --git a/compiler/test/TestSubroutines.kt b/compiler/test/TestSubroutines.kt index 07d24ac81..cf4cc3c30 100644 --- a/compiler/test/TestSubroutines.kt +++ b/compiler/test/TestSubroutines.kt @@ -258,8 +258,8 @@ class TestSubroutines: FunSpec({ sub start() { label() label(1) - void rnd() - void rnd(1) + void cmp(22,44) + void cmp(11) } } """ diff --git a/compiler/test/arithmetic/builtins.p8 b/compiler/test/arithmetic/builtins.p8 index dc44f6870..f8b6737c6 100644 --- a/compiler/test/arithmetic/builtins.p8 +++ b/compiler/test/arithmetic/builtins.p8 @@ -2,6 +2,7 @@ %import floats %import string %import syslib +%import math %import test_stack %zeropage basicsafe @@ -281,17 +282,17 @@ main { txt.nl() - ub = rnd() + ub = math.rnd() txt.print_ub(ub) txt.nl() - ub = zero+rnd()*1+zero + ub = zero+math.rnd()*1+zero txt.print_ub(ub) txt.nl() - uw = rndw() + uw = math.rndw() txt.print_uw(uw) txt.nl() - uw = zero+rndw()*1+zero + uw = zero+math.rndw()*1+zero txt.print_uw(uw) txt.nl() diff --git a/compilerAst/src/prog8/compiler/BuiltinFunctions.kt b/compilerAst/src/prog8/compiler/BuiltinFunctions.kt index d8139549e..353f2fc9f 100644 --- a/compilerAst/src/prog8/compiler/BuiltinFunctions.kt +++ b/compilerAst/src/prog8/compiler/BuiltinFunctions.kt @@ -119,8 +119,6 @@ private val functionSignatures: List = listOf( FSignature("rsavex" , false, emptyList(), null), FSignature("rrestore" , false, emptyList(), null), FSignature("rrestorex" , false, emptyList(), null), - 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("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), diff --git a/docs/source/index.rst b/docs/source/index.rst index c1bc165be..84e1331bf 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -71,7 +71,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``, ``sort`` and ``reverse`` +- Many built-in functions, such as ``sin``, ``cos``, ``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/libraries.rst b/docs/source/libraries.rst index 858416ea5..fc9f2beb0 100644 --- a/docs/source/libraries.rst +++ b/docs/source/libraries.rst @@ -257,7 +257,13 @@ tan(x) Tangent. rndf() - returns a pseudo-random float between 0.0 and 1.0 + returns the next random float between 0.0 and 1.0 from the Pseudo RNG sequence. + +rndseedf(ubyte s1, ubyte s2, ubyte s3) + Sets a new seed for the float pseudo-RNG sequence. The seed consists of a three byte value. + + .. attention:: + The rndseedf and maybe the rndf routines may change a bit in the future. graphics @@ -276,12 +282,21 @@ Use the ``gfx2`` library if you want full-screen graphics or non-monochrome draw math ---- -Low level math routines. You should not normally have to bother with this directly. -The compiler needs it to implement most of the math operations in your programs. +Low level integer math routines (which you usually don't have to bother with directly, but they are used by the compiler internally). +Pseudo-Random number generators (byte and word). +Various 8-bit integer trig functions that use lookup tables to quickly calculate sine and cosines. +Usually a custom lookup table is the way to go if your application needs these, +but perhaps the provided ones can be of service too. -However there's a bunch of 8-bit integer trig functions in here too that use lookup tables -to quickly calculate sine and cosines. Usually a custom lookup table is the way to go if your -application needs this, but perhaps the provided ones can be of service too: + +rnd() + Returns next random byte 0-255 from the pseudo-RNG sequence. + +rndw() + Returns next random word 0-65535 from the pseudo-RNG sequence. + +rndseed(uword seed1, uword seed2) + Sets a new seed for the pseudo-RNG sequence (both rnd and rndw). The seed consists of two words. sin8u(x) Fast 8-bit ubyte sine of angle 0..255, result is in range 0..255 diff --git a/docs/source/programming.rst b/docs/source/programming.rst index e3770b8dd..c7525302e 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -858,12 +858,6 @@ popw(value) pops a 16-bit word value off the CPU hardware stack into the given variable. Only variables can be used. Lowlevel function that should normally not be used. -rnd() - returns a pseudo-random byte from 0..255 - -rndw() - returns a pseudo-random word from 0..65535 - rol(x) Rotate the bits in x (byte or word) one position to the left. This uses the CPU's rotate semantics: bit 0 will be set to the current value of the Carry flag, diff --git a/docs/source/todo.rst b/docs/source/todo.rst index f7d0792f2..45653dffd 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,9 +3,8 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- replace rnd() builtin functions by regular functions in math and in floats -- update docs for rnd() and rndseed() functions - ir: replace RND opcodes by syscalls +- optimizer: check that simple trampoline asmsub gets optimized away (such as math.rnd) - ir: asmsub contents remains blank in IR file ... diff --git a/examples/balloonflight.p8 b/examples/balloonflight.p8 index a2a8edf29..2ed090114 100644 --- a/examples/balloonflight.p8 +++ b/examples/balloonflight.p8 @@ -1,5 +1,6 @@ %import syslib %import textio +%import math %import test_stack %zeropage basicsafe @@ -41,7 +42,7 @@ main { active_height-- upwards = false } else { - target_height = 8 + rnd() % 16 + target_height = 8 + math.rnd() % 16 if upwards mountain = 233 else @@ -56,7 +57,7 @@ main { txt.scroll_left(true) ; float the balloon - if rnd() & %10000 + if math.rnd() & %10000 c64.SPXY[1] ++ else c64.SPXY[1] -- @@ -70,10 +71,10 @@ main { txt.setcc(39, yy, 160, 8) ; draw mountain } - yy = rnd() + yy = math.rnd() if yy > 100 { ; draw a star - txt.setcc(39, yy % (active_height-1), '.', rnd()) + txt.setcc(39, yy % (active_height-1), '.', math.rnd()) } if yy > 200 { @@ -84,7 +85,7 @@ main { tree = 88 else if yy & %00100000 != 0 tree = 65 - if rnd() > 130 + if math.rnd() > 130 treecolor = 13 txt.setcc(39, active_height, tree, treecolor) } diff --git a/examples/balls.p8 b/examples/balls.p8 index fb5f51a40..14081c0af 100644 --- a/examples/balls.p8 +++ b/examples/balls.p8 @@ -1,4 +1,5 @@ %import textio +%import math %zeropage basicsafe ; Note: this program is compatible with C64 and CX16. @@ -22,11 +23,11 @@ main { ; Setup Starting Ball Positions ubyte lp for lp in 0 to ballCount-1 { - BX[lp] = rnd() % txt.DEFAULT_WIDTH - BY[lp] = rnd() % txt.DEFAULT_HEIGHT - BC[lp] = rnd() & 15 - DX[lp] = rnd() & 1 - DY[lp] = rnd() & 1 + BX[lp] = math.rnd() % txt.DEFAULT_WIDTH + BY[lp] = math.rnd() % txt.DEFAULT_HEIGHT + BC[lp] = math.rnd() & 15 + DX[lp] = math.rnd() & 1 + DY[lp] = math.rnd() & 1 } ; display balls diff --git a/examples/cx16/circles.p8 b/examples/cx16/circles.p8 index eb3c49adb..3a69424c2 100644 --- a/examples/cx16/circles.p8 +++ b/examples/cx16/circles.p8 @@ -1,4 +1,5 @@ %import graphics +%import math ; note: this program is tuned for the CX16, but with some minor modifications can run on other systems too. @@ -15,7 +16,7 @@ main { graphics.enable_bitmap_mode() repeat { - background_color = rnd() + background_color = math.rnd() graphics.clear_screen(0, background_color) num_circles = 0 draw_circles() @@ -28,14 +29,14 @@ main { ubyte @zp radius while num_circles s { + if math.rnd() > s { b |= bittab[ii] } } diff --git a/examples/sprites.p8 b/examples/sprites.p8 index b15f92efd..f5e6e55c2 100644 --- a/examples/sprites.p8 +++ b/examples/sprites.p8 @@ -1,5 +1,6 @@ %import textio %import syslib +%import math %zeropage basicsafe @@ -41,7 +42,7 @@ main { for i in 0 to 7 { c64.SPRPTR[i] = $0a00 / 64 c64.SPXY[i*2] = 50+25*i - c64.SPXY[i*2+1] = rnd() + c64.SPXY[i*2+1] = math.rnd() } c64.SPENA = 255 ; enable all sprites @@ -59,7 +60,7 @@ irq { ubyte @zp i for i in 0 to 14 step 2 { c64.SPXY[i+1]-- - ubyte @zp r = rnd() + ubyte @zp r = math.rnd() if r>200 c64.SPXY[i]++ else if r<40 diff --git a/examples/tehtriz.p8 b/examples/tehtriz.p8 index 65c0b2b3a..fc9067e4c 100644 --- a/examples/tehtriz.p8 +++ b/examples/tehtriz.p8 @@ -10,6 +10,7 @@ %import syslib %import textio +%import math %import test_stack @@ -261,7 +262,7 @@ waitkey: xpos = startXpos ypos = startYpos speedlevel = 1 - nextBlock = rnd() % 7 + nextBlock = math.rnd() % 7 holding = 255 holdingAllowed = true } @@ -276,7 +277,7 @@ waitkey: sub spawnNextBlock() { swapBlock(nextBlock) - nextBlock = (rnd() + c64.RASTER) % 7 + nextBlock = (math.rnd() + c64.RASTER) % 7 drawNextBlock() holdingAllowed = true } diff --git a/examples/test.p8 b/examples/test.p8 index 41d0dbafb..cef336627 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -6,17 +6,17 @@ main { sub printnumbers() { - txt.print_ub(rnd()) + txt.print_ub(math.rnd()) txt.spc() - txt.print_ub(rnd()) + txt.print_ub(math.rnd()) txt.spc() - txt.print_ub(rnd()) + txt.print_ub(math.rnd()) txt.nl() - txt.print_uw(rndw()) + txt.print_uw(math.rndw()) txt.spc() - txt.print_uw(rndw()) + txt.print_uw(math.rndw()) txt.spc() - txt.print_uw(rndw()) + txt.print_uw(math.rndw()) txt.nl() floats.print_f(floats.rndf()) txt.spc() diff --git a/examples/vm/bouncegfx.p8 b/examples/vm/bouncegfx.p8 index 38c3865f5..ecf946eda 100644 --- a/examples/vm/bouncegfx.p8 +++ b/examples/vm/bouncegfx.p8 @@ -1,5 +1,7 @@ ; NOTE: meant to test to virtual machine output target (use -target virtual) +%import math + main { sub start() { @@ -10,10 +12,10 @@ main { ubyte pi for pi in 0 to 127 { - particleX[pi] = rndw() % 319 as word - particleY[pi] = rndw() % 240 as word - particleDX[pi] = (rnd() & 1)*2 as byte - 1 - particleDY[pi] = (rnd() & 1)*2 as byte - 1 + particleX[pi] = math.rndw() % 319 as word + particleY[pi] = math.rndw() % 240 as word + particleDX[pi] = (math.rnd() & 1)*2 as byte - 1 + particleDY[pi] = (math.rnd() & 1)*2 as byte - 1 } sys.gfx_enable(0) ; enable lo res screen diff --git a/syntax-files/IDEA/Prog8.xml b/syntax-files/IDEA/Prog8.xml index ecb77cdc9..ad2c0ed76 100644 --- a/syntax-files/IDEA/Prog8.xml +++ b/syntax-files/IDEA/Prog8.xml @@ -12,12 +12,12 @@