//  *********************************************************************************************
//  Description      : Assembly instructions for hello world 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 C++17 (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=rv32ifd_zicsr -g
        .set DataMem,0x1                # Start of Data Memory 0x1000 (translates to 0x400 due to 4 bytes adressing system)
_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
storeChar:
        addi    sp,sp,-32               # Reserve some space on the stack
        sw      ra,28(sp)               # Save the return address on the stack
        sw      s0,24(sp)               # Save the caller frame pointer value on the stack
        addi    s0,sp,32                # Store the callee frame pointer value in s0 (end address of the stack frame)
        sw      a1,-24(s0)              # arg1, location
        sb      a0,-17(s0)              # arg0, c
                                        # helloWorld.c:8:     *location = c;
        lw      a5,-24(s0)              # tmp136, location
        lbu     a4,-17(s0)              # tmp137, c
        sb      a4,0(a5)                # tmp137, *location_2(D)
                                        # helloWorld.c:9: }
        lw      ra,28(sp)               # Load the return address from the stack and store it in ra
        lw      s0,24(sp)               # Load the caller frame pointer value from the stack and store it in s0
        addi    sp,sp,32                # Free the allocated stack space for the function call
        jr      ra                      # Return to address stored in ra
main:
        addi    sp,sp,-16               # Reserve some space on the stack
        sw      ra,12(sp)               # Save the return address on the stack
        sw      s0,8(sp)                # Save the caller frame pointer value on the stack
        addi    s0,sp,16                # Store the callee frame pointer value in s0 (end address of the stack frame)
                                        # helloWorld.c:15:   storeChar('h', &mem[0]);
        lui     a1,DataMem              # tmp136, DataMem
        addi    a1,a1,0                 # arg1, tmp136 + 0
        li      a0,104                  # arg0, 'h'
        call    storeChar                 #
                                        # helloWorld.c:16:   storeChar('e', &mem[1]);
        lui     a1,DataMem              # tmp137, DataMem
        addi    a1,a1,1                 # arg1, tmp137 + 1
        li      a0,101                  # arg0, 'e'
        call    storeChar                 #
                                        # helloWorld.c:17:   storeChar('l', &mem[2]);
        lui     a1,DataMem              # tmp138, DataMem
        addi    a1,a1,2                 # arg1, tmp138 + 2
        li      a0,108                  # arg0, 'l'
        call    storeChar                 #
                                        # helloWorld.c:18:   storeChar('l', &mem[3]);
        lui     a1,DataMem              # tmp139, DataMem
        addi    a1,a1,3                 # arg1, tmp139 + 3
        li      a0,108                  # arg0, 'l'
        call    storeChar                 #
                                        # helloWorld.c:19:   storeChar('o', &mem[4]);
        lui     a1,DataMem              # tmp140, DataMem
        addi    a1,a1,4                 # arg1, tmp140 + 4
        li      a0,111                  # arg0, 'o'
        call    storeChar                 #
                                        # helloWorld.c:20:   storeChar(' ', &mem[5]);
        lui     a1,DataMem              # tmp141, DataMem
        addi    a1,a1,5                 # arg1, tmp141 + 5
        li      a0,32                   # arg0, ' '
        call    storeChar                 #
                                        # helloWorld.c:21:   storeChar('w', &mem[6]);
        lui     a1,DataMem              # tmp142, DataMem
        addi    a1,a1,6                 # arg1, tmp142 + 6
        li      a0,119                  # arg0, 'w'
        call    storeChar                 #
                                        # helloWorld.c:22:   storeChar('o', &mem[7]);
        lui     a1,DataMem              # tmp143, DataMem
        addi    a1,a1,7                 # arg1, tmp143 + 7
        li      a0,111                  # arg0, 'o'
        call    storeChar                 #
                                        # helloWorld.c:23:   storeChar('r', &mem[8]);
        lui     a1,DataMem              # tmp144, DataMem
        addi    a1,a1,8                 # arg1, tmp144 + 8
        li      a0,114                  # arg0, 'r'
        call    storeChar                 #
                                        # helloWorld.c:24:   storeChar('l', &mem[9]);
        lui     a1,DataMem              # tmp145, DataMem
        addi    a1,a1,9                 # arg1, tmp145 + 9
        li      a0,108                  # arg0, 'l'
        call    storeChar                 #
                                        # helloWorld.c:25:   storeChar('d', &mem[10]);
        lui     a1,DataMem              # tmp146, DataMem
        addi    a1,a1,10                # arg1, tmp146 + 10
        li      a0,100                  # arg0, 'd'
        call    storeChar                 #
                                        # helloWorld.c:26:   storeChar('!', &mem[11]);
        lui     a1,DataMem              # tmp147, DataMem
        addi    a1,a1,11                # arg1, tmp147 + 11
        li      a0,33                   # arg0, '!'
        call    storeChar                 #
                                        # helloWorld.c:27:   storeChar('\0', &mem[12]); // Don't forget the null terminator!
        lui     a1,DataMem              # tmp148, DataMem
        addi    a1,a1,12                # arg1, tmp148 + 12
        li      a0,0                    # arg0, '\0
        call    storeChar                 #
                                        # helloWorld.c:29:   return 0;                                                // End the main function and return 0 on success
        li      a5,0                    # _16,
                                        # helloWorld.c:30: }
        mv      a0,a5                   #, <retval>
        lw      ra,12(sp)               # Load the return address from the stack and store it in ra
        lw      s0,8(sp)                # Load the caller frame pointer value from the stack and store it in s0
        addi    sp,sp,16                # Free the allocated stack space for the function call
        jr      ra                      # Return to address stored in ra
