diff --git a/compiler/res/prog8lib/math.p8 b/compiler/res/prog8lib/math.p8 index baba47785..50d44ddc2 100644 --- a/compiler/res/prog8lib/math.p8 +++ b/compiler/res/prog8lib/math.p8 @@ -98,6 +98,47 @@ _sinecosR8 .char trunc(127.0 * sin(range(180+45) * rad(360.0/180.0))) }} } + asmsub log2(ubyte value @A) -> ubyte @Y { + %asm {{ + ldy #$80 + sty P8ZP_SCRATCH_B1 + ldy #7 +- bit P8ZP_SCRATCH_B1 + beq + + rts ++ dey + bne + + rts ++ lsr P8ZP_SCRATCH_B1 + bne - + }} + } + + asmsub log2w(uword value @AY) -> ubyte @Y { + %asm {{ + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + lda #<$8000 + sta cx16.r0 + lda #>$8000 + sta cx16.r0+1 + ldy #15 +- lda P8ZP_SCRATCH_W1 + and cx16.r0 + sta P8ZP_SCRATCH_B1 + lda P8ZP_SCRATCH_W1+1 + and cx16.r0+1 + ora P8ZP_SCRATCH_B1 + beq + + rts ++ dey + bne + + rts ++ lsr cx16.r0+1 + ror cx16.r0 + jmp - + }} + } sub direction_sc(byte x1, byte y1, byte x2, byte y2) -> ubyte { ; From a pair of signed coordinates around the origin, calculate discrete direction between 0 and 23 into A. diff --git a/compiler/res/prog8lib/virtual/math.p8 b/compiler/res/prog8lib/virtual/math.p8 index 84c3893b0..5b6885389 100644 --- a/compiler/res/prog8lib/virtual/math.p8 +++ b/compiler/res/prog8lib/virtual/math.p8 @@ -183,6 +183,31 @@ math { }} } + sub log2(ubyte value) -> ubyte { + ubyte result = 7 + ubyte compare = $80 + repeat { + if value&compare + return result + result-- + if_z + return 0 + compare >>= 1 + } + } + + sub log2w(uword value) -> ubyte { + ubyte result = 15 + uword compare = $8000 + repeat { + if value&compare + return result + result-- + if_z + return 0 + compare >>= 1 + } + } sub direction(ubyte x1, ubyte y1, ubyte x2, ubyte y2) -> ubyte { ; From a pair of positive coordinates, calculate discrete direction between 0 and 23 into A. diff --git a/docs/source/libraries.rst b/docs/source/libraries.rst index 2b0d2ec7a..937e5d221 100644 --- a/docs/source/libraries.rst +++ b/docs/source/libraries.rst @@ -343,6 +343,11 @@ Various 8-bit integer trig functions that use lookup tables to quickly calculate 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. +``log2 (ubyte v)`` + Returns the 2-Log of the byte value v. + +``log2w (uword v)`` + Returns the 2-Log of the word value v. ``rnd ()`` Returns next random byte 0-255 from the pseudo-RNG sequence. diff --git a/docs/source/todo.rst b/docs/source/todo.rst index be4d1d011..13dd33b97 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,5 +1,7 @@ TODO ==== +- optimize assembly output for if word1 & word2 ... (no need for stack pushes) + - prefix prog8 subroutines with p8s_ instead of p8_ to not let them clash with variables in the asm? - allow 'chained' array indexing for expressions: value = ptrarray[0][0]