riscv-utils/hexdump.s

176 lines
3.5 KiB
ArmAsm

.globl _start
.option rvc # enable compressed instructions
.data
writebuf: .ascii "00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................\n"
.equ hexstart, 10
.equ hexend, hexstart+3*16
.equ charstart, hexend+3
.equ linelen, (. - writebuf)
.equ readlen, 16
readbuf: .zero readlen
.text
_start:
# set up the gp register so that relaxed loads work
.option push
.option norelax
la gp, __global_pointer$
.option pop
# fd in s6
# data offset in s7
li s6, 0
li s7, 0 #0xabad1dea
loop:
li a7, 63 # sys_read
mv a0, s6 # fd
la a1, readbuf # pointer to buffer
li a2, readlen # 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
li t5, 10
la s0, writebuf
.macro hexnibble src, shift, dest
slli t1, \src, (64-\shift-4) # put high nibble of s7 in t1
srli t1, t1, 64-4
addi t2, t1, 0x30 # convert to decimal digit
bgt t5, t1, 0f # if digit >= 10, use switch to alpha
addi t2, t1, 0x61-10
0:
# copy digit to writebuf
sb t2, \dest
.endm
.macro hexbyte src, shift, dest
hexnibble \src, (\shift+4), \dest
hexnibble \src, \shift, 1+\dest
.endm
hexbyte s7, 24, 0(s0)
hexbyte s7, 16, 2(s0)
hexbyte s7, 8, 4(s0)
hexbyte s7, 0, 6(s0)
la s1, readbuf
# it's perfectly fine to process more
# bytes than we read here, since the buffer
# sizes are both fixed
.macro inpbyte srcindex, dstindex
lbu t0, \srcindex(s1)
hexbyte t0, 0, \dstindex(s0)
.endm
# TODO: load 8 bytes at a time
# (need a way to check endianness)
inpbyte 0, 10
inpbyte 1, 13
inpbyte 2, 16
inpbyte 3, 19
inpbyte 4, 22
inpbyte 5, 25
inpbyte 6, 28
inpbyte 7, 31
inpbyte 8, 35
inpbyte 9, 38
inpbyte 10, 41
inpbyte 11, 44
inpbyte 12, 47
inpbyte 13, 50
inpbyte 14, 53
inpbyte 15, 56
li t0, 0
li t4, 0x7e-0x20
# the ascii printable range is 0x20-0x7e
#
# 0123456789ABCDEF
# 20 !"#$%&'()*+,-./
# 30 0123456789:;<=>?
# 40 @ABCDEFGHIJKLMNO
# 50 PQRSTUVWXYZ[\]^_
# 60 `abcdefghijklmno
# 70 pqrstuvwxyz{|}~
printable_loop:
add t1, s1, t0
lbu t2, 0(t1)
addi t3, t2, -0x20
bleu t3, t4, 0f
li t2, 0x2e # '.'
0:
add t1, s0, t0
sb t2, 61(t1)
addi t0, t0, 1
blt t0, a0, printable_loop
li t0, readlen
blt a0, t0, fixup
mv s0, a0 # save length read
add s7, s7, s0 # file offset += s0
li a7, 64 # sys_write
li a0, 1 # fd = stdout
la a1, writebuf # pointer to string
li a2, linelen # size of data
ecall
bltz a0, error
j loop
fixup:
# we read <16 bytes, so we need to
# 1) replace the hex bytes >a0 with spaces
# 2) adjust the line length
# 3) print it
add t0, a0, a0 # t0 = len*3
add t0, t0, a0
addi t0, t0, hexstart
add t0, s0, t0
addi t1, s0, hexend
li t2, 0x20
1:
sb t2, 0(t0)
addi t0, t0, 1
blt t0, t1, 1b
addi t0, a0, charstart
add t1, t0, s0
li t2, 0xa # \n
sb t2, 0(t1)
li a7, 64 # sys_write
li a0, 1 # fd = stdout
la a1, writebuf # pointer to string
addi a2, t0, 1 # size of data
ecall
bltz a0, error
j done
error:
li a7, 93 # exit
li a0, 1
ecall
done:
li a7, 93 # exit
li a0, 0
ecall