#********************************************************************** # CSSE 232 - Tests for GCD and relPrime # Rose-Hulman Institute of Technology # # This file contains a test procedure for the RISCV assembly language # implementation of gcd. # # 2024 - Sid Stamm #********************************************************************** .globl runtests .data # set this to 1 if you want to test gcd TEST_GCD: .word 1 # set this to 1 if you want to test relPrime TEST_RELPRIME: .word 1 # You can add more GCD tests by extending the arrays below. # Since gcd() takes two arguments, the inputs are in the # same array (a0, b0, a1, b1, ...). The test loads them # two at a time. # note: Values are tested in REVERSE order (right to left) gcd_input_pairs: .word 12,8, 1,5, 310,24 gcd_expected_results: .word 4, 1, 2 gcd_num_tests: .word 3 # You can add more relPrime tests by extending the arrays below. # note: Values are tested in REVERSE order (right to left) relprime_inputs: .word 30030, 5040, 2, 1 relprime_expected_results: .word 17, 11, 3, 2 relprime_num_tests: .word 4 # These are strings for printing. g_gcdtestmsg: .asciz "testing gcd with values " g_relprimemsg: .asciz "testing relprime with value " g_comma: .asciz "," g_dots: .asciz "... " g_passmsg: .asciz " -> pass\n" g_failmsg: .asciz " -> FAIL\n" g_sreg_notpres: .asciz "ERROR: one of the callee-saves registers was not preserved. Ending execution so you can debug (look for callee-saves register without value -1).\n" .text ### ### This is the main subroutine that runs GCD and relPrime tests. ### runtests: ###################################################### # do we want to test GCD? la t0, TEST_GCD lw t0, 0(t0) addi t0, t0, -1 bne t0, x0 _nogcd la t0, gcd_num_tests lw t0, 0(t0) #number of tests addi sp, sp, -4 sw t0, 0(sp) #save num tests on stack _test_gcd_next: # wipe everything jal ra, wipeTRegisters jal ra, wipeSRegisters # get test num off the stack lw t0, 0(sp) bge x0, t0 _test_gcd_done #if num tests left is <= 0, stop. addi t0, t0, -1 sw t0, 0(sp) # set arguments a, b la t1, gcd_input_pairs slli t0, t0, 3 add t0, t0, t1 #base plus offset lw a0, 0(t0) lw a1, 4(t0) jal ra, printGCDmsg ##################################################### #### CALL TO GCD PROCEDURE (the one we're testing) ## jal ra, gcd ##################################################### # print return value addi a7, x0, 1 ecall # get test num off the stack (is num-1 for zero-indexing) lw t0, 0(sp) la t1, gcd_expected_results slli t0, t0, 2 add t0, t0, t1 #base plus offset lw t0, 0(t0) # check return value bne a0, t0, _fail_gcd _pass_gcd: la a0, g_passmsg addi a7, x0, 4 ecall beq x0, x0, _test_gcd_looptrailer _fail_gcd: la a0, g_failmsg addi a7, x0, 4 ecall _test_gcd_looptrailer: # check s registers were saved jal ra, verifySRegisters # re-run the loop beq x0, x0, _test_gcd_next _test_gcd_done: addi sp, sp, 4 # give back space _nogcd: ###################################################### # do we want to test RELPRIME? la t0, TEST_RELPRIME lw t0, 0(t0) addi t0, t0, -1 bne t0, x0 _norelprime la t0, relprime_num_tests lw t0, 0(t0) #number of tests addi sp, sp, -4 sw t0, 0(sp) #save num tests on stack _test_rp_next: # wipe everything jal ra, wipeTRegisters jal ra, wipeSRegisters # get test num off the stack lw t0, 0(sp) bge x0, t0 _test_rp_done #if num tests left is <= 0, stop. addi t0, t0, -1 sw t0, 0(sp) # set argument n la t1, relprime_inputs slli t0, t0, 2 add t0, t0, t1 #base plus offset lw a0, 0(t0) jal ra, printRelPrimeMsg ########################################################### #### CALL TO RELPRIME PROCEDURE (the one we're testing) ## jal ra, relPrime ########################################################### # print return value addi a7, x0, 1 ecall # get test num off the stack (is num-1 for zero-indexing) lw t0, 0(sp) la t1, relprime_expected_results slli t0, t0, 2 add t0, t0, t1 #base plus offset lw t0, 0(t0) # check return value bne a0, t0, _fail_rp _pass_rp: la a0, g_passmsg addi a7, x0, 4 ecall beq x0, x0, _test_rp_looptrailer _fail_rp: la a0, g_failmsg addi a7, x0, 4 ecall _test_rp_looptrailer: # check s registers were saved jal ra, verifySRegisters # re-run the loop beq x0, x0, _test_rp_next _test_rp_done: addi sp, sp, 4 # give back space _norelprime: # halt addi a7, x0, 10 ecall # prints "testing gcd a,b..." (a=a0, b=a1) printGCDmsg: addi t0, a0, 0 #stash a0/a1 (ecalls don't mess with t regs) addi t1, a1, 0 la a0, g_gcdtestmsg # print testing message addi a7, x0, 4 #print str ecall add a0, x0, t0 addi a7, x0, 1 #print int ecall la a0, g_comma addi a7, x0, 4 #print str ecall add a0, x0, t1 addi a7, x0, 1 #print int ecall la a0, g_dots addi a7, x0, 4 #print str ecall # put a0/a1 back addi a0, t0, 0 addi a1, t1, 0 jalr x0, 0(ra) # prints "testing relPrime n..." (n=a0) printRelPrimeMsg: addi t0, a0, 0 #stash a0 (ecalls don't mess with t regs) la a0, g_relprimemsg # print testing message addi a7, x0, 4 #print str ecall add a0, x0, t0 addi a7, x0, 1 #print int ecall la a0, g_dots addi a7, x0, 4 #print str ecall # put a0/a1 back addi a0, t0, 0 jalr x0, 0(ra) # subroutine to wipe all temp registers (NOT A PROCEDURE) wipeTRegisters: addi a0, x0, -1 addi a1, x0, -1 addi a2, x0, -1 addi a3, x0, -1 addi a4, x0, -1 addi a5, x0, -1 addi a6, x0, -1 addi a7, x0, -1 addi t0, x0, -1 addi t1, x0, -1 addi t2, x0, -1 addi t3, x0, -1 addi t4, x0, -1 addi t5, x0, -1 jalr x0, 0(ra) # subroutine to wipe all saved registers (NOT A PROCEDURE) wipeSRegisters: addi s0, x0, -1 addi s1, x0, -1 addi s2, x0, -1 addi s3, x0, -1 addi s4, x0, -1 addi s5, x0, -1 addi s6, x0, -1 addi s7, x0, -1 addi s8, x0, -1 addi s9, x0, -1 addi s10, x0, -1 addi s11, x0, -1 jalr x0, 0(ra) saveSRegisters: addi sp, sp, -52 sw s0, 0(sp) sw s1, 4(sp) sw s2, 8(sp) sw s3, 12(sp) sw s4, 16(sp) sw s5, 20(sp) sw s6, 24(sp) sw s7, 28(sp) sw s8, 32(sp) sw s9, 36(sp) sw s10,40(sp) sw s11,44(sp) sw ra, 48(sp) jalr x0, 0(ra) verifySRegisters: addi x31, x0, -1 bne s0, x31, _vs_FAIL bne s1, x31, _vs_FAIL bne s2, x31, _vs_FAIL bne s3, x31, _vs_FAIL bne s4, x31, _vs_FAIL bne s5, x31, _vs_FAIL bne s6, x31, _vs_FAIL bne s7, x31, _vs_FAIL bne s8, x31, _vs_FAIL bne s9, x31, _vs_FAIL bne s10, x31, _vs_FAIL bne s11, x31, _vs_FAIL jalr x0, 0(ra) _vs_FAIL: la a0, g_sreg_notpres #error message addi a1, x0, 0 addi a7, x0, 55 # error dialog ecall # HALT for debugging addi a7, x0, 10 #exit ecall restoreSRegisters: lw s0, 0(sp) lw s1, 4(sp) lw s2, 8(sp) lw s3, 12(sp) lw s4, 16(sp) lw s5, 20(sp) lw s6, 24(sp) lw s7, 28(sp) lw s8, 32(sp) lw s9, 36(sp) lw s10,40(sp) lw s11,44(sp) lw ra, 48(sp) addi sp, sp, 52 jalr x0, 0(ra)