//  *********************************************************************************************
//  Description      : Assembly instructions for prime factors program
//  Project Version  : v1.0
//  Project          : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
//  -----
//  Copyright (c)    : 2025 Fraunhofer IIS, Department IDS
//  Created          : 15.Oct.2025  by Hussein Elzomor
//  Last Modified    : 21.Oct.2025  by Hussein Elzomor
//  -----
//  HISTORY          : Date         By         Comments
//                     -----------  ---------  -------------------------------------------------
//  *********************************************************************************************



# GNU C23 (crosstool-NG UNKNOWN) version 15.2.0 (riscv32-unknown-linux-gnu)
#       compiled by GNU C version 16.0.0 20250802 (experimental), GMP version 6.3.0, MPFR version 4.2.1, MPC version 1.3.1, isl version isl-0.24-GMP

# GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
# options passed: -mabi=ilp32d -misa-spec=20191213 -mtls-dialect=trad -march=rv32imafdc_zicsr_zifencei_zmmul_zaamo_zalrsc_zca_zcd_zcf -g
_start:
        lui     sp, 0x2                 # Initialize stack pointer value to size of memory (0x00002000)
        addi    sp, sp -4               # Subtract stack pointer value by 4 to point to the last memory address (0x00001FFC)
        jal     main                    # Jump to main and save return address to ra
halt:
        j       halt                    # Get stuck here in a loop forever
main:
        addi    sp,sp,-48               # Reserve some space on the stack
        sw      ra,44(sp)               # Save the return address on the stack
        sw      s0,40(sp)               # Save the caller frame pointer value on the stack
        addi    s0,sp,48                # Store the callee frame pointer value in s0 (end address of the stack frame)
                                        # primeFactors.c:6:   Number = 39;                                            // Set initial value for Number to be factorized
        li      a5,39                   # tmp137,39                                                                   # Change the Number (39) to different values to test the program
        mv      a6, a5                  # ,tmp137                                                                     # Used for printing in the TB upon change
        sw      a5,-40(s0)              # tmp137, Number
                                        # primeFactors.c:7:   Prime = 0;                                              // Set initial value for Prime to be printed
        sw      zero,-44(s0)            #, Prime
loop_i_init:
                                        # primeFactors.c:8:   for (i = 2; i <= Number; i++)                           // Iterate over i from 2 to Number, all possible numbers excluding 1 & 0
        li      a5,2                    # tmp138,
        sw      a5,-20(s0)              # tmp138, i
                                        # primeFactors.c:8:   for (i = 2; i <= Number; i++)                           // Iterate over i from 2 to Number, all possible numbers excluding 1 & 0
        j       loop_i_check            #
num_mod_set:
                                        # primeFactors.c:10:     NumberModulo = Number;
        lw      a5,-40(s0)              # tmp139, Number
        sw      a5,-32(s0)              # tmp139, NumberModulo
                                        # primeFactors.c:11:     while (NumberModulo > 0)                             // Calculate Number % i using subtraction and store in NumberModulo
        j       num_mod_loop            #
num_mod_sub_i:
                                        # primeFactors.c:13:       NumberModulo -= i;
        lw      a4,-32(s0)              # tmp141, NumberModulo
        lw      a5,-20(s0)              # tmp142, i
        sub     a5,a4,a5                # NumberModulo_21, tmp141, tmp142
        sw      a5,-32(s0)              # NumberModulo_21, NumberModulo
num_mod_loop:
                                        # primeFactors.c:11:     while (NumberModulo > 0)                             // Calculate Number % i using subtraction and store in NumberModulo
        lw      a5,-32(s0)              # tmp143, NumberModulo
        bgt     a5,zero,num_mod_sub_i   #, tmp143,,
num_mod_check:
                                        # primeFactors.c:15:     if (NumberModulo == 0)                               // If Number % i == 0, it is possible that it's a prime number
        lw      a5,-32(s0)              # tmp144, NumberModulo
        bne     a5,zero,loop_i_inc      #, tmp144,,

                                        # primeFactors.c:17:       isPrime = 1;
        li      a5,1                    # tmp145,
        sw      a5,-36(s0)              # tmp145, isPrime
loop_j_init:
                                        # primeFactors.c:18:       for (j = 2; j <= i / 2; j++)                       // Iterate over j from 2 to i/2
        li      a5,2                    # tmp146,
        sw      a5,-28(s0)              # tmp146, j
                                        # primeFactors.c:18:       for (j = 2; j <= i / 2; j++)                       // Iterate over j from 2 to i/2
        j       loop_j_check            #
i_mod_set:
                                        # primeFactors.c:20:         iModulo = i;
        lw      a5,-20(s0)              # tmp147, i
        sw      a5,-24(s0)              # tmp147, iModulo
                                        # primeFactors.c:21:         while (iModulo > 0)                              // Calculate i % j using subtraction and store in iModulo
        j       i_mod_loop              #
i_mod_sub_j:
                                        # primeFactors.c:23:           iModulo -= j;
        lw      a4,-24(s0)              # tmp149, iModulo
        lw      a5,-28(s0)              # tmp150, j
        sub     a5,a4,a5                # iModulo_18, tmp149, tmp150
        sw      a5,-24(s0)              # iModulo_18, iModulo
i_mod_loop:
                                        # primeFactors.c:21:         while (iModulo > 0)                              // Calculate i % j using subtraction and store in iModulo
        lw      a5,-24(s0)              # tmp151, iModulo
        bgt     a5,zero,i_mod_sub_j     #, tmp151,,
i_mod_check:
                                        # primeFactors.c:25:         if (iModulo == 0)                                // If i % j == 0, it is not a prime number
        lw      a5,-24(s0)              # tmp152, iModulo
        bne     a5,zero,loop_j_inc      #, tmp152,,
                                        # primeFactors.c:27:           isPrime = 0;
        sw      zero,-36(s0)            #, isPrime
                                        # primeFactors.c:28:           break;
        j       prime_check             #
loop_j_inc:
                                        # primeFactors.c:18:       for (j = 2; j <= i / 2; j++)                       // Iterate over j from 2 to i/2
        lw      a5,-28(s0)              # tmp154, j
        addi    a5,a5,1                 #, j_16, tmp154
        sw      a5,-28(s0)              # j_16, j
loop_j_check:
                                        # primeFactors.c:18:       for (j = 2; j <= i / 2; j++)                       // Iterate over j from 2 to i/2
        lw      a5,-20(s0)              # tmp155, i
        srli    a4,a5,31                #, tmp156, tmp155
        add     a5,a4,a5                # tmp155, tmp157, tmp156
        srai    a5,a5,1                 #, _1, tmp157
        mv      a4,a5                   # _1, _1
                                        # primeFactors.c:18:       for (j = 2; j <= i / 2; j++)                       // Iterate over j from 2 to i/2
        lw      a5,-28(s0)              # tmp159, j
        ble     a5,a4,i_mod_set         #, tmp159, _1,
prime_check:
                                        # primeFactors.c:31:       if (isPrime == 1)                                  // Print i if i is a prime number
        lw      a4,-36(s0)              # tmp160, isPrime
        li      a5,1                    # tmp161,
        bne     a4,a5,loop_i_inc        #, tmp160, tmp161,
prime_set:
                                        # primeFactors.c:33:         Prime = i;                                       // Set variable Prime to the prime number. Used for printing in the TB upon change
        lw      a7,-20(s0)              # tmp162, i
        sw      a7,-44(s0)              # tmp162, Prime
loop_i_inc:
                                        # primeFactors.c:8:   for (i = 2; i <= Number; i++)                           // Iterate over i from 2 to Number, all possible numbers excluding 1 & 0
        lw      a5,-20(s0)              # tmp164, i
        addi    a5,a5,1                 #, i_20, tmp164
        sw      a5,-20(s0)              # i_20, i
loop_i_check:
                                        # primeFactors.c:8:   for (i = 2; i <= Number; i++)                           // Iterate over i from 2 to Number, all possible numbers excluding 1 & 0
        lw      a4,-20(s0)              # tmp165, i
        lw      a5,-40(s0)              # tmp166, Number
        ble     a4,a5,num_mod_set       #, tmp165, tmp166,
return:
                                        # primeFactors.c:37:   return 0;                                              // return the main function and return 0 on success
        li      a5,0                    # _10,
                                        # primeFactors.c:38: }
        mv      a0,a5                   #, <retval>
        lw      ra,44(sp)               # Load the return address from the stack and store it in ra
        lw      s0,40(sp)               # Load the caller frame pointer value from the stack and store it in s0
        addi    sp,sp,48                # Free the allocated stack space for the function call
        jr      ra                      # Return to address stored in ra
