.global _is_alpha, _is_digit, _is_alnum, _is_upper, _is_lower .global _write_out, _read_file, _memcmp, _write_error, _put_char, _printi .global _divide_by_zero_error, _exit .section .rodata .equ SYS_READ, 63 .equ SYS_WRITE, 64 .equ SYS_EXIT, 93 .equ STDIN, 0 .equ STDOUT, 1 .equ STDERR, 2 new_line: .ascii "\n" .section .text # Write the current token to stderr. # a0 - String pointer. # a1 - String length. .type _write_error, @function _write_error: mv t0, a0 mv t1, a1 li a0, STDERR mv a1, t0 mv a2, t1 li a7, SYS_WRITE ecall li a0, STDERR la a1, new_line li a2, 1 li a7, SYS_WRITE ecall ret # a0 - First pointer. # a1 - Second pointer. # a2 - The length to compare. # # Returns 0 in a0 if memory regions are equal. .type _memcmp, @function _memcmp: mv t0, a0 li a0, 0 .Lmemcmp_loop: beqz a2, .Lmemcmp_end lbu t1, (t0) lbu t2, (a1) sub a0, t1, t2 bnez a0, .Lmemcmp_end addi t0, t0, 1 addi a1, a1, 1 addi a2, a2, -1 j .Lmemcmp_loop .Lmemcmp_end: ret # Detects if a0 is an uppercase character. Sets a0 to 1 if so, otherwise to 0. .type _is_upper, @function _is_upper: li t0, 'A' - 1 sltu t1, t0, a0 # t1 = a0 >= 'A' sltiu t2, a0, 'Z' + 1 # t2 = a0 <= 'Z' and a0, t1, t2 # t1 = a0 >= 'A' & a0 <= 'Z' ret # Detects if a0 is an lowercase character. Sets a0 to 1 if so, otherwise to 0. .type _is_lower, @function _is_lower: li t0, 'a' - 1 sltu t2, t0, a0 # t2 = a0 >= 'a' sltiu t3, a0, 'z' + 1 # t3 = a0 <= 'z' and a0, t2, t3 # t2 = a0 >= 'a' & a0 <= 'z' ret # Detects if the passed character is a 7-bit alpha character or an underscore. # The character is passed in a0. # Sets a0 to 1 if the character is an alpha character or underscore, sets it to 0 otherwise. .type _is_alpha, @function _is_alpha: # Prologue. addi sp, sp, -16 sw ra, 12(sp) sw s0, 8(sp) addi s0, sp, 16 sw a0, 4(sp) call _is_upper sw a0, 0(sp) lw a0, 4(sp) call _is_lower lw t0, 4(sp) xori t1, t0, '_' seqz t1, t1 lw t0, 0(sp) or a0, a0, t0 or a0, a0, t1 # Epilogue. lw ra, 12(sp) lw s0, 8(sp) addi sp, sp, 16 ret # Detects whether the passed character is a digit # (a value between 0 and 9). # # Parameters: # a0 - Exemined value. # # Sets a0 to 1 if it is a digit, to 0 otherwise. .type _is_digit, @function _is_digit: li t0, '0' - 1 sltu t1, t0, a0 # t1 = a0 >= '0' sltiu t2, a0, '9' + 1 # t2 = a0 <= '9' and a0, t1, t2 ret .type _is_alnum, @function _is_alnum: # Prologue. addi sp, sp, -16 sw ra, 12(sp) sw s0, 8(sp) addi s0, sp, 16 sw a0, 4(sp) call _is_alpha sw a0, 0(sp) lw a0, 4(sp) call _is_digit lw a1, 0(sp) or a0, a0, a1 # Epilogue. lw ra, 12(sp) lw s0, 8(sp) addi sp, sp, 16 ret .type _write_out, @function _write_out: # Prologue. addi sp, sp, -8 sw ra, 4(sp) sw s0, 0(sp) addi s0, sp, 8 mv a2, a1 mv a1, a0 li a0, STDOUT li a7, SYS_WRITE ecall # Epilogue. lw ra, 4(sp) lw s0, 0(sp) addi sp, sp, 8 ret # Reads standard input into a buffer. # a0 - Buffer pointer. # a1 - Buffer size. # # Returns the result in a0. .type _read_file, @function _read_file: # Prologue. addi sp, sp, -8 sw ra, 4(sp) sw s0, 0(sp) addi s0, sp, 8 mv a2, a1 mv a1, a0 li a0, STDIN li a7, SYS_READ ecall # Epilogue. lw ra, 4(sp) lw s0, 0(sp) addi sp, sp, 8 ret # Terminates the program. a0 contains the return code. # # Parameters: # a0 - Status code. .type _exit, @function _exit: li a7, SYS_EXIT ecall # ret .type _divide_by_zero_error, @function _divide_by_zero_error: addi a7, zero, 172 # getpid ecall addi a1, zero, 8 # SIGFPE addi a7, zero, 129 # kill ecall ret # a0 - Whole number. # t1 - Constant 10. # a1 - Local buffer. # t2 - Current character. # t3 - Whether the number is negative. .type printi, @function _printi: addi sp, sp, -16 sw s0, 0(sp) sw ra, 4(sp) addi s0, sp, 16 addi t1, zero, 10 addi a1, s0, -1 addi t3, zero, 0 bge a0, zero, .digit10 addi t3, zero, 1 sub a0, zero, a0 .digit10: rem t2, a0, t1 addi t2, t2, '0' sb t2, 0(a1) div a0, a0, t1 addi a1, a1, -1 bne zero, a0, .digit10 beq zero, t3, .write_call addi t2, zero, '-' sb t2, 0(a1) addi a1, a1, -1 .write_call: addi a0, zero, 1 addi a1, a1, 1 sub a2, s0, a1 addi a7, zero, 64 # write ecall lw s0, 0(sp) lw ra, 4(sp) addi sp, sp, 16 ret # Writes a character from a0 into the standard output. .type _put_char, @function _put_char: # Prologue addi sp, sp, -16 sw ra, 12(sp) sw s0, 8(sp) addi s0, sp, 16 sb a0, 4(sp) li a0, STDOUT addi a1, sp, 4 li a2, 1 li a7, SYS_WRITE ecall # Epilogue. lw ra, 12(sp) lw s0, 8(sp) add sp, sp, 16 ret