riscv-utils/crc32.s
Andrew Ekstedt cc18d535a5 crc32: add notw macro
instead of materializing a constant 0xffffffff, do a NOT and then
zero-extend the result. my qemu doesn't support the zext.w instruction,
so we have to do two shifts instead. these can potentially be fused
into a single instruction by the processor.
2024-08-23 23:14:51 -07:00

185 lines
3.1 KiB
ArmAsm

.globl _start
.option rvc # enable compressed instructions
.option norelax
.data
sigaction_ignore:
.dword 1 # sa_handler = SIG_IGN
.dword 0 # sa_flags
.dword 0 # sa_mask
.bss
.equ bufsize, 4<<10
buf: .zero bufsize
.bss
crc_table: .zero 256*4
.text
_start:
# ignore SIGPIPE
li a7, 134 # sys_rt_sigaction
li a0, 13 # SIGPIPE
la a1, sigaction_ignore # action
li a2, 0 # oldact = NULL
# if this is a non-null pointer the kernel will
# return a copy of the old action to us, but we don't care
li a3, 8 # signal set size (bytes)
ecall
# TODO: error messages
call init_table
li s1, 0 # CRC
loop:
li a7, 63 # sys_read
li a0, 0 # fd = stdin
la a1, buf # pointer to buffer
li a2, bufsize # size of buffer
ecall
#li a0, 0
# return in a0
# negative => error code
# positive => number of byte read
# zero => end of input
bltz a0, error
beqz a0, done
mv s0, a0
# loop over buffer and update crc
mv a0, s1
la a1, buf
mv a2, s0 # buf size
call crc_update
mv s1, a0
bnez s0, loop # loop if not end of input
error:
li a7, 93 # sys_exit
li a0, 1 # status code = failure
ecall
done:
#la a0, crc_table
#addi a0, a0, 4*0x80
#lwu a0, (a0)
#mv s1, a0
# encode crc
la a0, buf
mv a1, s1
call u32hex
# add newline
la a1, buf
li t0, 10 # '\n'
sb t0, 8(a1)
# write crc
li a7, 64 # sys_write
li a0, 1 # fd = stdout
li a2, 9 # size of data
ecall
#mv s0, a0
# check for EPIPE
li t0, -32
beq a0, t0, ok # EPIPE
bltz a0, error
ok:
li a7, 93 # sys_exit
li a0, 0 # status code = success
ecall
#............................................
.equ poly, 0xEDB88320
.text
init_table:
la s0, crc_table
li t6, 256
li a0, poly
iloop:
addi t6, t6, -1
mv t0, t6
li t2, 8
iloop2:
andi t1, t0, 1
srli t0, t0, 1
beqz t1, 0f
xor t0, t0, a0
0:
addi t2, t2, -1
bnez t2, iloop2
slli t1, t6, 2
add t1, t1, s0
sw t0, (t1)
bnez t6, iloop
ret
#............................................
.macro notw rd, rs
not \rd, \rs
#zext.w \rd, \rd
#add.uw \rd, \rs, 0
slli \rd, \rd, 32
srli \rd, \rd, 32
.endm
# inputs:
# a0: crc
# a1: buf
# a2: buf size
#
# returns:
# a0 - new crc
#
# clobbers: t0, t1, t2, t3
.text
crc_update:
mv t1, s0
mv t2, s1
mv t3, s2
# invert crc
notw a0, a0
mv s0, a0 # crc
mv s1, a1 # buffer
la s2, crc_table
beqz a2, udone
uloop:
lbu a1, (s1) # load byte
andi t0, a0, 0xff # a1 = crc&0xff ^ byte
xor a1, a1, t0
srli a0, a0, 8 # crc >>= 8
slli a1, a1, 2 # convert a1 to table address
add a1, a1, s2
lwu a1, (a1) # load crc table entry
xor a0, a0, a1 # crc ^= table entry
addi s1, s1, 1
addi a2, a2, -1
bnez a2, uloop
udone:
# restore saved registers
mv s0, t1
mv s1, t2
mv s2, t3
# invert crc
#li t0, -1
#srli t0, t0, 32
notw a0, a0
ret