added math.crc16() and math.crc32()

This commit is contained in:
Irmen de Jong 2023-12-29 07:00:14 +01:00
parent 779a5606a7
commit 01bd648cb2
12 changed files with 130 additions and 275 deletions

View File

@ -484,4 +484,49 @@ log2_tab
}} }}
} }
sub crc16(uword data, uword length) -> uword {
; calculates the CRC16 (XMODEM) checksum of the buffer.
cx16.r1 = data ; make sure pointer is in zp (on cx16)
cx16.r0 = 0 ; the crc value
repeat length {
cx16.r0H ^= @(cx16.r1)
repeat 8 {
if cx16.r0H & $80 {
cx16.r0 <<= 1
cx16.r0 ^= $1021
}
else
cx16.r0<<=1
}
cx16.r1++
}
return cx16.r0
}
sub crc32(uword data, uword length) {
; Calculates the CRC-32 (POSIX) checksum of the buffer.
; because prog8 doesn't have 32 bits integers, we have to split up the calculation over 2 words.
; result stored in cx16.r0 (low word) and cx16.r1 (high word)
cx16.r2 = data ; make sure pointer is in zp (on cx16)
cx16.r1 = 0
cx16.r0 = 0
repeat length {
cx16.r1H ^= @(cx16.r2)
repeat 8 {
if cx16.r1H & $80 {
cx16.r0 <<= 1
rol(cx16.r1)
cx16.r1 ^= $04c1
cx16.r0 ^= $1db7
}
else {
cx16.r0 <<= 1
rol(cx16.r1)
}
}
cx16.r2++
}
cx16.r1 ^= $ffff
cx16.r0 ^= $ffff
}
} }

View File

@ -293,4 +293,45 @@ math {
return w2-w1 return w2-w1
} }
sub crc16(uword data, uword length) -> uword {
; calculates the CRC16 (XMODEM) checksum of the buffer.
cx16.r0 = 0 ; the crc value
repeat length {
cx16.r0H ^= @(data)
repeat 8 {
if cx16.r0H & $80
cx16.r0 = (cx16.r0<<1)^$1021
else
cx16.r0<<=1
}
data++
}
return cx16.r0
}
sub crc32(uword data, uword length) {
; Calculates the CRC-32 (POSIX) checksum of the buffer.
; because prog8 doesn't have 32 bits integers, we have to split up the calculation over 2 words.
; result stored in cx16.r0 (low word) and cx16.r1 (high word)
cx16.r1 = 0
cx16.r0 = 0
repeat length {
cx16.r1H ^= @(data)
repeat 8 {
if cx16.r1H & $80 {
cx16.r0 <<= 1
rol(cx16.r1)
cx16.r1 ^= $04c1
cx16.r0 ^= $1db7
}
else {
cx16.r0 <<= 1
rol(cx16.r1)
}
}
data++
}
cx16.r1 ^= $ffff
cx16.r0 ^= $ffff
}
} }

View File

@ -491,6 +491,15 @@ but perhaps the provided ones can be of service too.
It does not work for the verafx multiplication routines on the Commander X16! It does not work for the verafx multiplication routines on the Commander X16!
These have a different way to obtain the upper 16 bits of the result: just read cx16.r0. These have a different way to obtain the upper 16 bits of the result: just read cx16.r0.
``crc16 (uword data, uword length) -> uword``
Returns a CRC-16 (XMODEM) checksum over the given data buffer.
Note: on the Commander X16, there is a CRC-16 routine in the kernal: cx16.memory_crc().
That one is faster, but yields different results. It is unclear what flavour of crc it is calculating.
``crc32 (uword data, uword length)``
Calculates a CRC-32 (POSIX) checksum over the given data buffer.
The 32 bits result is stored in cx16.r0 (low word) and cx16.r1 (high word).
cx16logo cx16logo
-------- --------

View File

@ -2,8 +2,6 @@
TODO TODO
==== ====
- add crc8 and crc16 and crc32 to math
- fix crc* bench routines to no longer depend on the kernal rom version (use a bin file)
- make internalCast() not complain anymore about signed <-> unsigned conversions - make internalCast() not complain anymore about signed <-> unsigned conversions
- fix bitshift.p8 - fix bitshift.p8

View File

@ -1,32 +0,0 @@
%import textio
%import floats
main {
sub crc16(uword data, uword length) -> uword {
uword crc = 0
repeat length {
crc ^= mkword(@(data), 0)
repeat 8 {
if crc & $8000
crc = (crc<<1)^$1021
else
crc<<=1
}
data++
}
return crc
}
sub start() {
txt.print("calculating (expecting $ffd0)...\n")
txt.print(" if mismatch: first check if kernal is maybe updated?\n")
cbm.SETTIM(0,0,0)
uword crc = crc16($e000, $2000)
txt.print_uwhex(crc, true)
txt.nl()
floats.print(cbm.RDTIM16() / 60.0)
txt.print(" seconds")
sys.wait(9999)
}
}

View File

@ -1,44 +0,0 @@
%import textio
%import floats
main {
sub crc32(uword data, uword length) {
; because prog8 doesn't have 32 bits integers, we have to split up the calucation over 2 words.
; result in cx16.r0 (high word) and cx1.r1 (low word).
cx16.r0 = 0
cx16.r1 = 0
repeat length {
cx16.r0 ^= mkword(@(data), 0)
repeat 8 {
if cx16.r0 & $8000 {
sys.clear_carry()
rol(cx16.r1)
rol(cx16.r0)
cx16.r0 ^= $04c1
cx16.r1 ^= $1db7
}
else {
sys.clear_carry()
rol(cx16.r1)
rol(cx16.r0)
}
}
data++
}
cx16.r0 ^= $ffff
cx16.r1 ^= $ffff
}
sub start() {
txt.print("calculating (expecting $e1fa84c6)...\n")
txt.print(" if mismatch: first check if kernal is maybe updated?\n")
cbm.SETTIM(0,0,0)
crc32($e000, $2000)
txt.print_uwhex(cx16.r0, true)
txt.print_uwhex(cx16.r1, false)
txt.nl()
floats.print(cbm.RDTIM16() / 60.0)
txt.print(" seconds")
sys.wait(9999)
}
}

View File

@ -1,32 +0,0 @@
%import textio
%import floats
main {
sub crc8(uword data, uword length) -> ubyte {
ubyte crc = 0
repeat length {
crc ^= @(data)
repeat 8 {
if crc & $80
crc = (crc<<1)^$1d
else
crc<<=1
}
data++
}
return crc
}
sub start() {
txt.print("calculating (expecting $a2)...\n")
txt.print(" if mismatch: first check if kernal is maybe updated?\n")
cbm.SETTIM(0,0,0)
ubyte crc = crc8($e000, $2000)
txt.print_ubhex(crc, true)
txt.nl()
floats.print(cbm.RDTIM16() / 60.0)
txt.print(" seconds")
sys.wait(9999)
}
}

View File

@ -1,42 +0,0 @@
%import textio
%import floats
main {
const ubyte N_ITER = 10
const ubyte SIZE = 32
float[SIZE] array = 0.0
sub testpow(float x, uword y) -> float {
float tmp = x
if y==0
return 1
repeat y-1 {
tmp *= x
}
return tmp
}
sub start() {
txt.print("calculating (expecting 3.614007e+12)...\n")
cbm.SETTIM(0,0,0)
float res=0.0
uword i
ubyte j
for i in 0 to N_ITER-1 {
for j in 0 to SIZE-1 {
array[j] += testpow(2.5/(i+1.0), j)
}
}
for j in 0 to SIZE-1 {
res += array[j]
}
floats.print(res)
txt.nl()
floats.print(cbm.RDTIM16() / 60.0)
txt.print(" seconds")
sys.wait(9999)
}
}

View File

@ -1 +0,0 @@
Contains several benchmarks from https://gglabs.us/node/2293 ported to prog8.

View File

@ -1,64 +0,0 @@
%import textio
%import floats
main {
const ubyte N_ITER = 4
const uword SIZE = 16000
uword @zp flags_ptr = memory("flags", SIZE/8+1, $100)
ubyte[] bitv = [ $01, $02, $04, $08, $10, $20, $40, $80 ]
sub start() {
txt.print_ub(N_ITER)
txt.print(" iterations, calculating... (expecting 3431)\n")
cbm.SETTIM(0, 0, 0)
uword prime_count
repeat N_ITER {
prime_count = sieve()
}
txt.print_uw(prime_count)
txt.print(" primes\n")
float time = cbm.RDTIM16() as float / 60.0
floats.print(time)
txt.print(" sec total = ")
floats.print(time/N_ITER)
txt.print(" sec per iteration\n")
sys.wait(9999)
}
sub check_flag(uword idx) -> ubyte
{
return flags_ptr[idx/8] & bitv[lsb(idx)&7]
}
sub clear_flag(uword idx)
{
flags_ptr[idx/8] &= ~bitv[lsb(idx)&7]
}
sub sieve() -> uword {
uword prime
uword k
uword count=0
uword i
sys.memset(flags_ptr, SIZE/8+1, $ff)
for i in 0 to SIZE-1 {
if check_flag(i) {
prime = i*2 + 3
k = i + prime
while k < SIZE {
clear_flag(k)
k += prime
}
; txt.print_uw(prime)
; txt.spc()
count++
}
}
return count
}
}

View File

@ -1,52 +0,0 @@
%import textio
%import floats
; The "Byte Sieve" test. https://en.wikipedia.org/wiki/Byte_Sieve
; Note: this program can be compiled for multiple target systems.
main {
sub start() {
const ubyte ITERS = 10
uword count
uword i
uword prime
uword k
const uword SIZEPL = 8191
uword @zp flags_ptr = memory("flags", SIZEPL, $100)
txt.print_ub(ITERS)
txt.print(" iterations, calculating...\n")
cbm.SETTIM(0, 0, 0)
repeat ITERS {
sys.memset(flags_ptr, SIZEPL, 1)
count = 0
for i in 0 to SIZEPL-1 {
if flags_ptr[i] {
prime = i*2 + 3
k = i + prime
while k < SIZEPL {
flags_ptr[k] = false
k += prime
}
; txt.print_uw(prime)
; txt.spc()
count++
}
}
}
txt.print_uw(count)
txt.print(" primes\n")
float time = cbm.RDTIM16() as float / 60.0
floats.print(time)
txt.print(" sec total = ")
floats.print(time/ITERS)
txt.print(" sec per iteration\n")
sys.wait(9999)
}
}

View File

@ -1,12 +1,41 @@
%import floats
%import math %import math
%import string %import textio
%zeropage basicsafe %zeropage dontuse
main { main {
sub start() { sub start() {
float fl = 1.2 ; no other assignments str poem_data = iso:"Once upon a midnight dreary, while I pondered, weak and weary,"+
cx16.r0L = string.isdigit(math.diff(119, floats.floor(floats.deg(fl)) as ubyte)) iso:"Over many a quaint and curious volume of forgotten lore-"+
cx16.r1L = string.isletter(math.diff(119, floats.floor(floats.deg(1.2)) as ubyte)) iso:"While I nodded, nearly napping, suddenly there came a tapping,"+
iso:"As of some one gently rapping, rapping at my chamber door. ..."
uword size = len(poem_data)
cbm.SETTIM(0,0,0)
repeat 20 {
cx16.r9 = math.crc16(poem_data, size)
}
txt.print_uwhex(cx16.r9, true)
txt.spc()
txt.print_uw(cbm.RDTIM16())
txt.nl()
cbm.SETTIM(0,0,0)
repeat 20 {
cx16.r9 = cx16.memory_crc(poem_data, size) ; faster but I can't figure out the flavour of crc algorithm it uses, it's not any on https://crccalc.com/
}
txt.print_uwhex(cx16.r9, true)
txt.spc()
txt.print_uw(cbm.RDTIM16())
txt.nl()
cbm.SETTIM(0,0,0)
repeat 20 {
math.crc32(poem_data, size)
}
txt.print_uwhex(cx16.r1, true)
txt.print_uwhex(cx16.r0, false)
txt.spc()
txt.print_uw(cbm.RDTIM16())
txt.nl()
} }
} }