# Technische Informatik 1, SoSe 2023 (Universität Bremen)
# Übungsblatt 2, Aufgabe 5
#
# Testbench, mit der die zu implementierende Methode zur Berechnung der Collatz Folge getestet werden kann.
# Fügt Euren Code am Ende dieser Datei ein (beim Label myCollatz). 
# 
# ACHTUNG: schickt bitte NICHT diese Testbench, sondern nur Euren Code als Abgabe per Mail nach den Spezifikationen auf dem Zettel. 

.data
a: .word 7	# Hier Wert für a0 eintragen
collatz_n: .word 14		# Hier das erwartete Ergebnis eintragen

strCalc: .string "Berechne Collatz-Eintrittsindex von "
strErg: .string ". Das Ergebnis "
strIs: .string " ist "
strKorr: .string "korrekt. "	# Ripes bug: If %4 == 0, no zero byte is added
strFals: .string "falsch."

start_str:     .string " = ["
div_str:       .string ","
end_str:       .string "] "



.text
main:

    # Ausgabe des ersten Strings "Berechne Collatz-Eintrittsindex von " (Adresse steht in a0) per ecall.
	# Dafür muss a7=4 sein.
    la a0, strCalc
    li a7, 4
    ecall


	# Lade Wert für a0 in Register a0
    lw a0, a

    # Ausgabe der Zahl aus a0. Dafür muss a7=1 sein.
    li a7, 1
    ecall

	jal myCollatz	# Aufruf der von Euch implementierten Prozedur

	la a0, strErg
    li a7, 4
    ecall

	mv a0, a1
    li a7, 1
    ecall

	la a0, strIs
    li a7, 4
	ecall

	# Hier geht es nach der Berechnung mit der Auswertung weiter
	lw t1, collatz_n

	beq a1, t1, correct_result # überprüfe, ob das Ergebnis korrekt ist

wrong_result:
	la a0, strFals
	ecall
	j exit

correct_result: 
	la a0, strKorr
	ecall
	j exit


exit:
    li a7, 10  # Beende das Programm ordnungsgemäß
    ecall


########## Hier kommt Eure Berechnung des Collatz-Folgen-Eintrittswertes. 
########## Parameter a_0 ist in Register a0, Rückgabewert n* wird in Register a1 abgespeichert.

# a_0 / a_n is a0
# n* is a1
# temp is t0
# four is t1

myCollatz:        
                                # // Init n* with 0
    addi a1, x0, 0              # int n* = 0
    
                                # // Init four with 4. We do this so 
                                # // because it is not possible to do 
                                # // a Branch check an imidiate. 
    addi t1, x0, 4              # int four = 4
    
                                # // If a_n is all ready 4 then we 
                                # // return immediately.
    beq a0, t1, return          # if a_n == 4 { goto return } 
    
    addi t0, a0, 0              # Print Left Bracet
    la a0, start_str           
    addi a7, x0, 4                    
    ecall
    addi a0, t0, 0       
    
main_loop: 
    li a7, 1                    # Print a_n
    ecall                        
    
    addi t0, a0, 0              # Print Divider
    la a0, div_str              
    addi a7, x0, 4                   
    ecall                       
    addi a0, t0, 0      
    
                                # // Create a temp with the result of 
                                # // a_n mod 2.
    andi t0, a0, 1              # int temp = a_n % 2 
    
                                # // Check if a_n % 2 is != 0.
    bne t0, x0, else            # if temp != 0 { goto else }
    
                                # // Divide a_n by two.
                                # // This can be done by bit shifting
                                # // a_n one to the rigth.
    srli a0, a0, 1              # a_n = a_n / 2
    
                                # // Jump after the else Block.
    jal, x0, end                # goto end      
else: 

                                # // Perform a_n = 3 * a_n + 1
                                # // Adding a_n togther three times.
                                # // And adding one to the result.
    add t0, a0, a0              # temp = a_n + a_n
    add t0, t0, a0              # temp += a_n
    addi a0, t0, 1              # a_n = temp + 1
    
end:
                                # Incement n* by one.
    addi, a1, a1, 1             # n* += 1
return:                            
                                # // Check if we need to loop again.
    bne a0, t1, main_loop       # if a_n != 4 { goto main_loop }  
    
    
    li a7, 1                    # Print a_n
    ecall     
    
    la a0, end_str              # Print Rigth Bracket
    addi a7, x0, 4                    
    ecall
    
                                # // Else return n*.
    jalr x0, ra, 0              # return n*
      
                                # x is a1                

    