mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
added math.crc16() and math.crc32()
This commit is contained in:
parent
779a5606a7
commit
01bd648cb2
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -293,4 +293,45 @@ math {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -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!
|
||||
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
|
||||
--------
|
||||
|
@ -2,8 +2,6 @@
|
||||
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
|
||||
- fix bitshift.p8
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
Contains several benchmarks from https://gglabs.us/node/2293 ported to prog8.
|
@ -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
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -1,12 +1,41 @@
|
||||
%import floats
|
||||
%import math
|
||||
%import string
|
||||
%zeropage basicsafe
|
||||
%import textio
|
||||
%zeropage dontuse
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
float fl = 1.2 ; no other assignments
|
||||
cx16.r0L = string.isdigit(math.diff(119, floats.floor(floats.deg(fl)) as ubyte))
|
||||
cx16.r1L = string.isletter(math.diff(119, floats.floor(floats.deg(1.2)) as ubyte))
|
||||
str poem_data = iso:"Once upon a midnight dreary, while I pondered, weak and weary,"+
|
||||
iso:"Over many a quaint and curious volume of forgotten lore-"+
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user