.global sort # a0 = pointer to array to be sorted # a1 = length of array (signed) # a2 = element size (unsigned) # a3 - comparison function # a4 - context sort: # insertion sort # for i = 0 to n-1 # for j = i downto 0 # if a[j-1] > a[j] # swap a[j-1], a[j] # i = 0 # for n-1 downto 0 # i += esize # j = i # while j > 0: # if cmp(j-esize, j) > 0 # swap(j-esize, j) # else # break # j -= esize # # bail early if n <= 1 li t0, 1 bgt a1, t0, 0f li a0, 0 ret 0: # check if n*esize overflows or is negative mulhu t1, a1, a2 beqz t1, 0f li a0, -1 ret 0: sd ra, -1*8(sp) sd s0, -2*8(sp) sd s1, -3*8(sp) sd s2, -4*8(sp) sd s3, -5*8(sp) sd s4, -6*8(sp) sd s5, -7*8(sp) sd s6, -8*8(sp) addi sp, sp, -8*8 mv s0, a2 # pointer to element i - base # s1 is pointer to element j - base mv s2, a0 # base pointer mv s3, a1 # array len mv s4, a2 # element size mv s5, a3 # cmp mv s6, a4 # context # we know we have at least 2 elements, # so no check necessary at the top of the loop addi s3, s3, -1 .Louter.top: # i += esize # j = i add s0, s0, s4 mv s1, s0 .Linner.top: add a1, s1, s2 # create pointers sub a0, a1, s4 mv a2, s6 jalr s5 # cmp #li a0, 1 blez a0, .Lcmp.less .Lcmp.greater: .Lswap: add a1, s1, s2 sub a0, a1, s4 mv a2, s4 call swap .Linner.step: sub s1, s1, s4 bnez s1, .Linner.top .Lcmp.less: .Louter.step: addi s3, s3, -1 # n -= 1 bnez s3, .Louter.top .Lreturn: addi sp, sp, 8*8 ld ra, -1*8(sp) ld s0, -2*8(sp) ld s1, -3*8(sp) ld s2, -4*8(sp) ld s3, -5*8(sp) ld s4, -6*8(sp) ld s5, -7*8(sp) ld s6, -8*8(sp) ret .Lerror: li a0, -1 j .Lreturn swap: # TODO: larger things li t0, 8 bgtu a2, t0, bigswap beq a2, t0, swap8 li t0, 4 beq a2, t0, swap4 li t0, 2 beq a2, t0, swap2 li t0, 1 beq a2, t0, swap1 beqz a2, .Lret # TODO: weird size: 0, 3, 5, 6, 7 .Lret: ret swap8: ld t0, (a0) ld t1, (a1) sd t1, (a0) sd t0, (a1) ret swap4: lwu t0, (a0) lwu t1, (a1) sw t1, (a0) sw t0, (a1) ret swap2: lhu t0, (a0) lhu t1, (a1) sh t1, (a0) sh t0, (a1) ret swap1: lbu t0, (a0) lbu t1, (a1) sb t1, (a0) sb t0, (a1) ret bigswap: # TODO ret