# RISC-V assembly program implementing a calculator.

.org 0
# Provide program starting address to linker
.global _start

/* newlib system calls */
.set SYSEXIT,  93
.set SYSWRITE, 64

.section .rodata
str: .ascii "Hello World!\n"
     .set str_size, .-str
str2: .ascii "regdump\n"
      .set str2_size, .-str2


.section .bss
buf: .skip 20        # room for 20 byte string
                     # x10: ABCDEFG\n is 23 chars

.section .data
buflen: .byte 0      # length of buf string


.text
_start:
    li t1, 0
    li t2, 5

    # dummy test for jal instruction
.L1:
    jal x0, .L2
.L2:
    nop

loop:
    beq t1, t2, end

    li t0, SYSWRITE     # "write" syscall
    li a0, 1            # 1 = standard output (stdout)
    la a1, str          # load address of hello string
    li a2, str_size     # length of hello string
    ecall               # invoke syscall to print the string
    addi t1, t1, 1
    j loop

end:
    # do some adding
    li a0, 0x80000000   # 0.5
    li a1, 1            # 1
    li a2, 0x80000000   # 0.5
    li a3, 1            # 1
    jal add64
    #add t1, a0, 0       # copy a0 to t0 as end with overwrite it
    jal regdump

    li t0, SYSEXIT      # "exit" syscall
    add a0, x0, 0       # Use 0 return code
    ecall               # invoke syscall to terminate the program

# 64-bit integer addition
#   arguments:
#       a0: x lower 32 bits
#       a1: x upper 32 bits
#       a2: y lower 32 bits
#       a3: y upper 32 bits
#   return:
#       a0: x+y lower 32 bits
#       a1: x+y upper 32 bits
#
add64:
    add  a0, a0, a2  # add lower 32 bits
    add  t0, a1, a3  # add upper 32 bits
    sltu t1, a0, a2  # if lower 32-bit sum < a2 then set t1=1 (carry bit)
    add  a1, t0, t1  # upper 32 bits of answer (upper sum + carry bit)
    ret


# Print values of all registers (in hex)
# write syscall uses t0, a0, a1, a2
regdump:
    addi sp, sp, -16 # allocate stack space
    sw a0, 12(sp)    # save contents of a0
    sw a1, 8(sp)     # save contents of a0
    sw a2, 4(sp)     # save contents of a0
    sw t0, 0(sp)     # save contents of a0

    li t0, SYSWRITE     # "write" syscall
    li a0, 1            # 1 = standard output (stdout)
    la a1, str2         # load address of hello string
    li a2, str2_size    # length of other string
    ecall               # invoke syscall to print the string

    # as a test load something into buf and print it
    la a1, buf          # load address of buf into a1
    li a0, 'h
    sb a0, 0(a1)
    li a0, '\n
    sb a0, 1(a1)
    li a2, 2            # length of buf

    li t0, SYSWRITE     # "write" syscall
    li a0, 1            # 1 = standard output (stdout)
    # li a2, buflen       # length of hello string
    ecall               # invoke syscall to print the string

    addi sp, sp, 16   # deallocate stack space
    ret