@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@
@ Program part 0: initial declarations
@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

.globl _start

.equ RXFE, 0x10
.equ TXFF, 0x20

.equ OFFSET_FR, 0x018
.equ IO_ADDRESS, 0x101f1000

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@
@ Program part 1: definition of main.
@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@


@main program
_start:        
	mov sp,#0x100000		@ set up stack

	@ program preamble
	push {r0, r1, r2, r3, r4}	
	
	@ program main body
	ldr r4,=IO_ADDRESS		@ r4 := 0x 101f 1000
	ldr r0, =input_buffer
	
main_loop:	
	bl get_line
	bl print_string
	bl newline
	
	@ quit if q found
	ldrb r1, [r0]
	cmp r1,#'q'
	ldreq r0,=string_quit
	bleq print_string
	beq program_exit

	@ else, repeat
	b main_loop

program_exit:
	@ program wrap-up
	pop {r0, r1, r2, r3, r4}
	bl print_end
the_end:
	b the_end


@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@
@ Program part 2: definition of functions
@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@ author: Brandon Lawrence
@
@ div: computes result of integer division r0/r1
@
@ results: r0 = r0/r1
@          r1 = r0 mod r1
	
div:
@preamble
	push {r2, r3, r4, r5, r6, r7, r8, lr}

div_main:
	@r0 holds numerator
	@r1 holds denominator

	mov r4, #1
	mov r5, #-1
	
	cmp r1, #0
	moveq r3, #0
	beq div_exit
	mullt r6, r4, r5
	movlt r4, r6
	mullt r6, r1, r5
	movlt r1, r6
	
	cmp r0, #0
	mullt r6, r4, r5
	movlt r4, r6
	mullt r6, r0, r5
	movlt r0, r6
	
	mov r7, r0
	mov r8, r1
	
	mov r3,#0
	mov r2,r1


div_counter:		@sets r2 to the largest multiple
	cmp r2,r0	@of 2 smaller than r0
	lsrgt r2,r2,#1	
	bge div_loop
	lsl r2,r2,#1
	b div_counter

div_loop:		
	cmp r2,r1
	blt div_exit
	
	lsl r3,r3,#1	@r3 stores result
	cmp r0,r2
	subge r0,r0,r2
	addge r3,r3,#1
	
	lsr r2,r2,#1
	b div_loop

div_exit:
	mul r0,r3,r4
	mul r6, r3, r8
	sub r1, r7, r6
	
@wrap-up
	pop {r2, r3, r4, r5, r6, r7, r8, lr}
	bx lr

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@ r0 should be a buffer that can receive the data. 
@ The buffer should have size at least 1000 bytes.
get_line:
	@preamble
	push {r0, r4, r5, r6, r7, lr}
	
	@ main body
	ldr r4, =IO_ADDRESS
	mov r5, r0
	mov r6, #0
	mov r7, #1000

get_line_loop:
	cmp r6, r7
	beq get_line_exit

	bl get_char
	cmp r0, #'\r'
	beq get_line_exit
	
	str r0, [r4]
	strb r0, [r5, r6]
	add r6, r6, #1
	b get_line_loop
	
get_line_exit:
	bl newline
	mov r7, #0
	strb r7, [r5, r6]
	
	@ wrap-up
	pop {r0, r4, r5, r6, r7, lr}
	bx lr

	
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

get_char:
	@preamble
	push {r2, r3, r4, lr}

	@ main body
	ldr r4,=IO_ADDRESS		@ r4 := 0x 101f 1000

get_char_wait:
	ldr r2,[r4,#OFFSET_FR]		@ load IO flag register to r2
	and r3,r2,#RXFE			@ mask non receive fifo empty bits
	cmp r3, #0			@ r3 == 0?
	bne get_char_wait			@ wait until ready
	
	ldr r0,[r4]

	@ wrap-up
	pop {r2, r3, r4, lr}
	bx lr
	
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

print_end:
	@ preamble
	push {r1, r4, lr}

	@ main body
	ldr r4,=IO_ADDRESS		@ r4 := 0x 101f 1000
	mov r1, #13
	str r1, [r4]		
	mov r1, #10		
	str r1, [r4]		
	mov r1, #'E'		
	str r1, [r4]		
	mov r1, #'N'		
	str r1, [r4]		
	mov r1, #'D'		
	str r1, [r4]		

	@ wrap-up
	pop {r1, r4, lr}
	bx lr

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

newline:
	@ preamble
	push {r2, r4, lr}

	@ main body
	ldr r4,=IO_ADDRESS		@ r4 := 0x 101f 1000
	mov r2, #'\n'
	str r2,[r4]
	mov r2, #'\r'
	str r2,[r4]

	@ wrap-up
	pop {r2, r4, lr}
	bx lr


@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@ r0 should be address of first character of string to display
print_string:
	@preamble
	push {r0,r4,r5,lr}

	@ main body
	ldr r4,=IO_ADDRESS		@ r0 := 0x 101f 1000

str_out:
	ldrb r5,[r0]
	cmp r5,#0x00	@ '\0' = 0x00: null character?
	beq str_done	@ if yes, quit
	str r5,[r4]		@ otherwise, write character
	add r0,r0,#1	@ go to next character
	b str_out		@ repeat

	@ wrap-up
str_done:
	pop {r0,r4,r5,lr}
	bx lr


@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
	
div10:	
	@ div10 preamble
	sub sp, sp, #36
	str lr, [sp, #0]
	str r4, [sp, #4]
	str r5, [sp, #8]
	str r6, [sp, #12]
	str r7, [sp, #16]
	str r8, [sp, #20]
	str r9, [sp, #24]
	str r10, [sp, #28]
	str r11, [sp, #32]

	
	@ div10 main body	
	mov r4, r0		@ r4 = arg
	
	lsr r5, r4, #4		@ r5: lower bound
	lsr r6, r4, #3		@ r6: upper bound
	mov r7, r6		@ r7: current guess, initialized to upper bound
	mov r9, #10		@ r9: constant 10.

div10_loop:
	mul r8, r7, r9		@ r8 = current guess * 10
	cmp r8, #0		@ check for overflow
	movlt r6, r7		@ if overflow, set upper bound = guess.
	blt div10_next_guess

	cmp r8, r4		
	mov r10, #0
	movle r10, #1		@ r10 = (10 * current guess <= arg)
	
	mov r11, #0
	add r8, r8, #9		@ r8 = 10 * current guess + 9
	cmp r8, #0		@ check for overflow
	movlt r11, #1		@ if overflow, it means that
				@ (10 * current guess + 9 >= arg)
	blt div10_check
	
	cmp r8, r4
	movge r11, #1		@ r11 = (10 * current guess + 9 >= arg)

div10_check:	
	add r11, r11, r10	@ r11 = 2 if (10*guess <= arg <= 10*guess + 9)
	cmp r11, #2		@ if r11 == 2, we are done
	moveq r0, r7		@ arg/10 is r7, store at r0
	mul r8, r7, r9		@ r8 = current guess * 10
	subeq r1, r4, r8	@ r1 = remainder of arg/10
	beq div10_exit		@ exit, we have computed the results


	cmp r8, r4		@ compare 10*guess with arg
	movgt r6, r7		@ if 10>guess > arg, set upper_bound = guess
	movlt r5, r7		@ else set lower bound = guess

div10_next_guess:	
	add r7, r5, r6		@ guess = (lower bound + upper bound)
	lsr r7, r7, #1		@ guess = (lower bound + upper bound) / 2
	b div10_loop
	
div10_exit:
	@ div10 wrap-up
	ldr lr, [sp, #0]
	ldr r4, [sp, #4]
	ldr r5, [sp, #8]
	ldr r6, [sp, #12]
	ldr r7, [sp, #16]
	ldr r8, [sp, #20]
	ldr r9, [sp, #24]
	ldr r10, [sp, #28]
	ldr r11, [sp, #32]
	add sp, sp, #36
	bx lr

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

print10:	
	@ print10 preamble
	sub sp, sp, #28
	str lr, [sp, #0]
	str r0, [sp, #4]
	str r1, [sp, #8]
	str r4, [sp, #12]
	str r5, [sp, #16]
	str r6, [sp, #20]
	str r7, [sp, #24]

	@ print10 main body
	ldr r4,=0x101f1000	
	@ ASCII codes stored 
	@ at [r4] get printed

	mov r5, r0
	cmp r5, #0
	movlt r6, #'-'
	strlt r6, [r4]
	movlt r7, #-1
	mullt r0, r5, r7
	
	bl print10_helper

	@ print newline
	mov r5, #13
	str r5, [r4]		
	mov r5, #10		
	str r5, [r4]		

	@ print_number wrap-up
	ldr lr, [sp, #0]
	ldr r0, [sp, #4]
	ldr r1, [sp, #8]
	ldr r4, [sp, #12]
	ldr r5, [sp, #16]
	ldr r6, [sp, #20]
	ldr r7, [sp, #24]

	add sp, sp, #28
	bx lr
	
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

print10_helper:	
	@ print10_helper preamble
	sub sp, sp, #28
	str lr, [sp, #0]
	str r0, [sp, #4]
	str r1, [sp, #8]
	str r4, [sp, #12]
	str r5, [sp, #16]
	str r6, [sp, #20]
	str r7, [sp, #24]

	@ print10_helper main body
	ldr r4,=0x101f1000	
	@ ASCII codes stored 
	@ at [r4] get printed

	cmp r0, #10
	addlt r6, r0, #'0'
	strlt r6, [r4]
	blt print10_helper_exit
	
	bl div10
	bl print10_helper
	add r6, r1, #'0'
	str r6, [r4]

print10_helper_exit:
	@ print10_helper wrap-up
	ldr lr, [sp, #0]
	ldr r0, [sp, #4]
	ldr r1, [sp, #8]
	ldr r4, [sp, #12]
	ldr r5, [sp, #16]
	ldr r6, [sp, #20]
	ldr r7, [sp, #24]

	add sp, sp, #28
	bx lr
	
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
	
print_digit:	
	@ print_digit preamble
	sub sp, sp, #12
	str lr, [sp, #0]
	str r4, [sp, #4]
	str r5, [sp, #8]

	@ print_digit main body
	ldr r4,=0x101f1000	
	@ ASCII codes stored 
	@ at [r4] get printed
	
	cmp r0, #10
	addlt r5, r0, #48
	addge r5, r0, #55
	str r5, [r4]

	@ print_digit wrap-up
	ldr lr, [sp, #0]
	ldr r4, [sp, #4]
	ldr r5, [sp, #8]
	add sp, sp, #12
	bx lr

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
	
print_number:	
	@ print_number preamble
	sub sp, sp, #24
	str lr, [sp, #0]
	str r0, [sp, #4]
	str r4, [sp, #8]
	str r5, [sp, #12]
	str r6, [sp, #16]
	str r7, [sp, #20]

	@ print_number main body
	ldr r4,=0x101f1000	
	@ ASCII codes stored 
	@ at [r4] get printed

	mov r5, #28
	mov r6, r0
	
print_number_loop:	
	cmp r5, #0
	blt print_number_exit

	lsr r7, r6, r5
	and r7, r7, #0x0000000f

	mov r0, r7
	bl print_digit

	sub r5, r5, #4
	b print_number_loop

print_number_exit:
	@ print newline
	mov r5, #13
	str r5, [r4]		
	mov r5, #10		
	str r5, [r4]		

	@ print_number wrap-up
	ldr lr, [sp, #0]
	ldr r0, [sp, #4]
	ldr r4, [sp, #8]
	ldr r5, [sp, #12]
	ldr r6, [sp, #16]
	ldr r7, [sp, #20]

	add sp, sp, #24
	bx lr
	


@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@
@ Program part 3: data
@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
	

string_start:
	.asciz "Starting echo program\n\r"

input_buffer:
	.space 1005

input_buffer2:
	.space 1005

string_quit:
	.ascii "exiting echo program\n\r"
	.word 0x00

