added sqrt16() integer square root

This commit is contained in:
Irmen de Jong 2019-03-16 19:25:47 +01:00
parent 191707cd37
commit 0820716e7b
6 changed files with 74 additions and 34 deletions

View File

@ -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

View File

@ -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
}
}

View File

@ -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) },

View File

@ -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 -> {

View File

@ -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.

View File

@ -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
}
}