; ttyStart: Initializes the terminal for input and output.
ttyStart    MOV R3, #0xF2000000   ; load DBGU base address 0xFFFFF200 into R3
            MOV R3, R3, ASR #16
            MOV R0, #0x50         ; enable DBGU receipt and transmission
            STR R0, [R3, #0x0]
            MOV PC, LR
            
; getChar: Reads and returns in R0 a single character from the user.
; Program should have already called ttyStart.
; (Subroutine changes R0 and R3.)
getChar     MOV R3, #0xF2000000   ; load DBGU base address 0xFFFFF200 into R3
            MOV R3, R3, ASR #16
            LDR R0, [R3, #0x14]   ; wait until DBGU has received character
            TST R0, #0x1
            BEQ getChar
            LDR R0, [R3, #0x18]   ; now accept it from DBGU
            MOV PC, LR

; printChar: Displays a single character whose ASCII value is in R0.
; Program should have already called ttyStart.
; (Subroutine changes R1 and R3.)
printChar   MOV R3, #0xF2000000   ; load DBGU base address 0xFFFFF200 into R3
            MOV R3, R3, ASR #16
            LDR R1, [R3, #0x14]   ; wait until DBGU ready to transmit
            TST R1, #0x2
            BEQ printChar
            STR R0, [R3, #0x1C]   ; send character for DBGU transmission
            MOV PC, LR

; getInt: Reads and returns in R0 a nonnegative base-10 integer typed by
; the user. Continues reading digits until user enters a non-digit
; character.  The terminating non-digit character is consumed from the
; input. Program should have already called ttyStart.
getInt      STMDB SP!, { LR }
            MOV R1, #0
            MOV R2, #0             ; R2 accumulates integer typed
            B getInt_get           ; go to retrieving first character
getInt_loop ADD R1, R1, #1
            ADD R2, R2, R2, LSL #2 ; R2 = 10 * R2 + digit in R0
            ADD R2, R0, R2, LSL #1
getInt_get  BL getChar             ; retrieve character, repeat if is digit
            SUB R0, R0, #'0'
            CMP R0, #10
            BLO getInt_loop
            CMN R0, #3   ; check whether '-' was typed (-3 = '-' - '0')
            CMPEQ R1, #0 ; if so, check whether this is the first digit
            MVNEQ R1, #0xFF ; and if it is, set R1 to very negative
            BEQ getInt_get  ; and repeat looking for first character
            MOV R0, R2
            TST R1, R1      ; negate return value if R1 < 0
            RSBLT R0, R0, #0
            LDMIA SP!, { PC }

; printStr: Displays a NUL-terminated string whose first character's
; address is found in R0. Program should have already called ttyStart.
printStr    STMDB SP!, { LR }     ; save LR on stack, since BL changes LR
            MOV R2, R0            ; R2 holds address of current char
printStr_0  LDRB R0, [R2], #1  ; load str[i] into R0, increment R2
            CMP R0, #0            ; if it is '\0', return
            LDMEQIA SP!, { PC }
            BL printChar          ; display str[i]
            B printStr_0

; printHex: Displays the value found in R0 as unsigned integer in base 16.
; Program should have already called ttyStart.
printHex    STMDB SP!, { R4, LR }
            MOV R2, R0
            MOV R4, #0
printHex_1  ADD R4, R4, #4
            MOVS R0, R2, LSR R4
            BNE printHex_1
            SUB R4, R4, #4
printHex_2  MOV R0, R2, LSR R4
            AND R0, R0, #0xF
            CMP R0, #10
            ADDLT R0, R0, #'0'
            ADDGE R0, R0, #87
            BL printChar
printHex_3  SUBS R4, R4, #4
            BGE printHex_2
            LDMIA SP!, { R4, PC }

; printInt: Displays the value found in R0 as signed integer in base 10.
; Program should have already called ttyStart.
printInt    STMDB SP!, { LR }
            SUB SP, SP, #12         ; reserve 12 bytes on stack for digits
            CMP R0, #0
            BGE printInt_0
            RSB R2, R0, #0          ; R0 is negative - print '-' and negate
            MOV R0, #'-'
            BL printChar
            MOV R0, R2
printInt_0  MOV R2, SP              ; load digits into array
            MOV R3, #0x19000000     ;   starting with 1's digit
            ORR R3, R3, #0x990000
            ORR R3, R3, #0x9900
            ORR R3, R3, #0x9A
printInt_1  UMULL R12, R1, R0, R3
            ADD R12, R1, R1, LSL #2
            SUB R12, R0, R12, LSL #1
            ADD R12, R12, #'0'
            STRB R12, [R2], #1
            MOVS R0, R1
            BGT printInt_1

printInt_2  LDRB R0, [R2, #-1]!     ; go through array in reverse
            BL printChar            ; displaying digits
            CMP R2, SP
            BGT printInt_2

            ADD SP, SP, #12
            LDMIA SP!, { PC }
