diff --git a/compiler/res/prog8lib/prog8lib.asm b/compiler/res/prog8lib/prog8lib.asm index 0138c041b..28495f685 100644 --- a/compiler/res/prog8lib/prog8lib.asm +++ b/compiler/res/prog8lib/prog8lib.asm @@ -649,7 +649,57 @@ func_read_flags .proc rts .pend + +func_sqrt16 .proc + lda c64.ESTACK_LO+1,x + sta c64.SCRATCH_ZPWORD2 + lda c64.ESTACK_HI+1,x + sta c64.SCRATCH_ZPWORD2+1 + stx c64.SCRATCH_ZPREGX + ldy #$00 ; r = 0 + ldx #$07 + clc ; clear bit 16 of m +_loop + tya + ora _stab-1,x + sta c64.SCRATCH_ZPB1 ; (r asl 8) | (d asl 7) + lda c64.SCRATCH_ZPWORD2+1 + bcs _skip0 ; m >= 65536? then t <= m is always true + cmp c64.SCRATCH_ZPB1 + bcc _skip1 ; t <= m +_skip0 + sbc c64.SCRATCH_ZPB1 + sta c64.SCRATCH_ZPWORD2+1 ; m = m - t + tya + ora _stab,x + tay ; r = r or d +_skip1 + asl c64.SCRATCH_ZPWORD2 + rol c64.SCRATCH_ZPWORD2+1 ; m = m asl 1 + dex + bne _loop + ; last iteration + bcs _skip2 + sty c64.SCRATCH_ZPB1 + lda c64.SCRATCH_ZPWORD2 + cmp #$80 + lda c64.SCRATCH_ZPWORD2+1 + sbc c64.SCRATCH_ZPB1 + bcc _skip3 +_skip2 + iny ; r = r or d (d is 1 here) +_skip3 + ldx c64.SCRATCH_ZPREGX + tya + sta c64.ESTACK_LO+1,x + lda #0 + sta c64.ESTACK_HI+1,x + rts +_stab .byte $01,$02,$04,$08,$10,$20,$40,$80 + .pend + + func_sin8 .proc ldy c64.ESTACK_LO+1,x lda _sinecos8,y diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt index e6e0b0ec9..ea94110db 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -1255,9 +1255,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, Opcode.ROR2_WORD -> { AsmFragment(" lsr $variable+1 | ror $variable | bcc + | lda $variable+1 | ora #\$80 | sta $variable+1 |+", 30) } -// Opcode.SYSCALL -> { -// TODO("optimize SYSCALL $ins in-place on variable $variable") -// } else -> null } } diff --git a/compiler/src/prog8/functions/BuiltinFunctions.kt b/compiler/src/prog8/functions/BuiltinFunctions.kt index 1c33e7528..45c918a59 100644 --- a/compiler/src/prog8/functions/BuiltinFunctions.kt +++ b/compiler/src/prog8/functions/BuiltinFunctions.kt @@ -46,7 +46,7 @@ val BuiltinFunctions = mapOf( "atan" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::atan) }, "ln" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::log) }, "log2" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, ::log2) }, - // TODO: sqrt() should have integer versions too + "sqrt16" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.UWORD))), DataType.UBYTE) { a, p, n, h -> oneIntArgOutputInt(a, p, n, h) { Math.sqrt(it.toDouble()).toInt() } }, "sqrt" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::sqrt) }, "rad" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::toRadians) }, "deg" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::toDegrees) }, diff --git a/compiler/src/prog8/stackvm/StackVm.kt b/compiler/src/prog8/stackvm/StackVm.kt index 665b7acbc..afbb5cc12 100644 --- a/compiler/src/prog8/stackvm/StackVm.kt +++ b/compiler/src/prog8/stackvm/StackVm.kt @@ -40,6 +40,7 @@ enum class Syscall(val callNr: Short) { FUNC_ATAN(72), FUNC_LN(73), FUNC_LOG2(74), + FUNC_SQRT16(75), FUNC_SQRT(76), FUNC_RAD(77), FUNC_DEG(78), @@ -2064,6 +2065,7 @@ class StackVm(private var traceOutputFile: String?) { Syscall.FUNC_LN -> evalstack.push(Value(DataType.FLOAT, ln(evalstack.pop().numericValue().toDouble()))) Syscall.FUNC_LOG2 -> evalstack.push(Value(DataType.FLOAT, log2(evalstack.pop().numericValue().toDouble()))) Syscall.FUNC_SQRT -> evalstack.push(Value(DataType.FLOAT, sqrt(evalstack.pop().numericValue().toDouble()))) + Syscall.FUNC_SQRT16 -> evalstack.push(Value(DataType.UBYTE, sqrt(evalstack.pop().numericValue().toDouble()).toInt())) Syscall.FUNC_RAD -> evalstack.push(Value(DataType.FLOAT, Math.toRadians(evalstack.pop().numericValue().toDouble()))) Syscall.FUNC_DEG -> evalstack.push(Value(DataType.FLOAT, Math.toDegrees(evalstack.pop().numericValue().toDouble()))) Syscall.FUNC_FLOOR -> { diff --git a/docs/source/programming.rst b/docs/source/programming.rst index a891f9f57..3d86b97d7 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -604,8 +604,11 @@ ln(x) log2(x) Base 2 logarithm. +sqrt16(w) + 16 bit unsigned integer Square root. Result is unsigned byte. + sqrt(x) - Square root. + Floating point Square root. round(x) Rounds the floating point to the closest integer. diff --git a/examples/test.p8 b/examples/test.p8 index 88769a1cb..7068560f8 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -6,47 +6,35 @@ ; @todo see problem in looplabelproblem.p8 sub start() { + uword z2 = sqrt16(50000) - uword z = c64utils.str2uword(" 1 2 3 4 5 ") - c64scr.print_uw(c64utils.str2uword(" ")) + c64scr.print_ub(sqrt16(0)) c64.CHROUT('\n') - c64scr.print_uw(c64utils.str2uword(" 222 ")) + c64scr.print_ub(sqrt16(200)) c64.CHROUT('\n') - c64scr.print_uw(c64utils.str2uword("1234 567")) + c64scr.print_ub(sqrt16(20000)) c64.CHROUT('\n') - c64scr.print_uw(c64utils.str2uword("1234x567")) + c64scr.print_ub(sqrt16(63333)) c64.CHROUT('\n') - c64scr.print_uw(c64utils.str2uword("+1234x567")) - c64.CHROUT('\n') - c64scr.print_uw(c64utils.str2uword("00065534")) - c64.CHROUT('\n') - c64scr.print_uw(c64utils.str2uword("0006553x4")) + c64scr.print_ub(sqrt16(65535)) c64.CHROUT('\n') c64.CHROUT('\n') - - word z2 = c64utils.str2word(" 1 2 3 4 5 ") - c64scr.print_w(c64utils.str2word(" ")) + z2=0 + c64scr.print_ub(sqrt16(z2)) c64.CHROUT('\n') - c64scr.print_w(c64utils.str2word("0000000")) + z2=200 + c64scr.print_ub(sqrt16(z2)) c64.CHROUT('\n') - c64scr.print_w(c64utils.str2word("12345")) + z2=20000 + c64scr.print_ub(sqrt16(z2)) c64.CHROUT('\n') - c64scr.print_w(c64utils.str2word("64444")) + z2=63333 + c64scr.print_ub(sqrt16(z2)) c64.CHROUT('\n') - c64scr.print_w(c64utils.str2word(" 12345")) - c64.CHROUT('\n') - c64scr.print_w(c64utils.str2word("-12345")) - c64.CHROUT('\n') - c64scr.print_w(c64utils.str2word(" - 123 45")) - c64.CHROUT('\n') - c64scr.print_w(c64utils.str2word("+1234 567 ")) - c64.CHROUT('\n') - c64scr.print_w(c64utils.str2word("-1234 567 ")) - c64.CHROUT('\n') - c64scr.print_w(c64utils.str2word("-31999")) - c64.CHROUT('\n') - c64scr.print_w(c64utils.str2word("31999")) + z2=65535 + c64scr.print_ub(sqrt16(z2)) c64.CHROUT('\n') + A=99 } }