.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