idiv:
        stmfd   sp!, {fp, lr}
        add     fp, sp, $4

        mov     r3, r1
        cmp     r3, r0, lsr $1
.Lloop2:
        movls   r3, r3, lsl $1
        cmp     r3, r0, lsr $1
        bls     .Lloop2

        mov     r2, $0

.Lloop3:
        cmp     r0, r3
        subhs   r0, r0, r3
        adc     r2, r2, r2

        mov     r3, r3, lsr $1
        cmp     r3, r1
        bhs     .Lloop3

        ldmfd   sp!, {fp, pc}
.ltorg

_print_character:
        stmfd sp!, {fp, lr}
        add   fp, sp, $4
        PUTCHAR
        ldmfd sp!, {fp, pc}
.ltorg

write_packed_char_n:
        stmfd sp!, {fp, lr}
        add   fp, sp, $4
        mov   r2, r4, lsr $2
        mov   r5, r2
        mov   r2, r2, lsl $2
        sub   r4, r4, r2
        mov   r6, r4 @ r6 = count - ((count >> 2) << 2
        mov   r4, r5 @ r4 = count >> 2

        cmp   r6, $0
        beq   .WP_L1
        sub   r3, r3, $4
        ldr   r5, [r3] @ r5 = top of stack
        mov   r2, r5
        and   r2, r2, $255
        bl    _print_character
        cmp   r6, $1
        ble   .WP_L1
        mov   r5, r5, lsr $8
        mov   r2, r5
        and   r2, r2, $255
        bl    _print_character
        cmp   r6, $2
        ble   .WP_L1
        mov   r5, r5, lsr $8
        mov   r2, r5
        and   r2, r2, $255
        bl    _print_character

.WP_L1:
        cmp   r4, $0
        beq   .WP_L2
        sub   r4, r4, $1
        sub   r3, r3, $4
        ldr   r5, [r3]
        mov   r2, r5
        and   r2, r2, $255
        bl    _print_character
        mov   r5, r5, lsr $8
        mov   r2, r5
        and   r2, r2, $255
        bl    _print_character
        mov   r5, r5, lsr $8
        mov   r2, r5
        and   r2, r2, $255
        bl    _print_character
        mov   r5, r5, lsr $8
        mov   r2, r5
        and   r2, r2, $255
        bl    _print_character
        b     .WP_L1

.WP_L2:
        ldmfd sp!, {fp, pc}
.ltorg

print_integer:
        stmfd sp!, {fp, lr}
        add   fp, sp, $4

@ ( n == $80000000 ) 
        mov   r1, $8
        mov   r1, r1, ror $4
        cmp   r0, r1
        bne   .LL_P_I_0

        @ print negative maximum 32 bit integer

        mov   r2, $45
        bl    _print_character
        mov   r2, $50
        bl    _print_character
        mov   r2, $49
        bl    _print_character
        mov   r2, $52
        bl    _print_character
        mov   r2, $55
        bl    _print_character
        mov   r2, $52
        bl    _print_character
        mov   r2, $56
        bl    _print_character
        mov   r2, $51
        bl    _print_character
        mov   r2, $54
        bl    _print_character
        mov   r2, $52
        bl    _print_character
        mov   r2, $56
        bl    _print_character

        b     .LL_P_I_8

.ltorg
.LL_P_I_0:
@ ( n < 0 ) 
        cmp   r0, $0
        bge   .LL_P_I_2
@ putchar ( 45 ) 
        mov   r5, r0 @ save
        mov   r2, $45
        PUTCHAR
        mov   r0, r5 @ restore

@ n = #NEG n 
        mov   r1, $0
        sub   r0, r1, r0

.LL_P_I_2:
@ string_size = 0 
        mov   r1, $0
@ n_temp = n 
        mov   r4, r0

.LL_P_I_3:
@ string_size = string_size + 1 
        add   r1, r1, $1
@ n_temp = n_temp / 10 
        mov   r5, r0 @ save
        mov   r6, r1 @ save
        mov   r0, r4
        mov   r1, $10
        bl    signed_quotient
        mov   r4, r0
        mov   r0, r5 @ restore
        mov   r1, r6 @ restore

@ ( ! ( n_temp == 0 ) ) 
        cmp   r4, $0
        bne   .LL_P_I_3

.LL_P_I_4:
@ string_idx = string_size 
        mov   r2, r1
.LL_P_I_5:
@ string_idx > 0 
        cmp   r2, $0
        ble   .LL_P_I_6

@ string [ string_idx - 1 ] = n % 10 + 48 
        mov   r5, r0 @ save
        mov   r6, r1 @ save
        mov   r1, $10
        bl    signed_remainder
        mov   r9, r0
        mov   r0, r5 @ restore
        mov   r1, r6 @ restore
        add   r9, r9, $48
        sub   r6, r2, $1
        ldr   r5, =buf
        str   r9, [r5, r6, lsl $2]

@ n = n / 10 
        mov   r6, r1 @ save
        mov   r1, $10
        bl    signed_quotient
        mov   r1, r6 @ restore

@ string_idx = string_idx - 1 
        sub   r2, r2, $1
        b     .LL_P_I_5

.LL_P_I_6:
@ string_idx = 0 
        mov   r2, $0

        ldr   r9, =buf
.LL_P_I_7:
@ string_idx < string_size 
@ (lt)
        cmp   r2, r1
        bge   .LL_P_I_8

@ putchar ( string [ string_idx ] ) 
        mov   r5, r1 @ save
        mov   r6, r2 @ save
        ldr   r2, [r9, r2, lsl $2]
        PUTCHAR
        mov   r1, r5 @ restore
        mov   r2, r6 @ restore

@ string_idx = string_idx + 1 
        add   r2, r2, $1

        b     .LL_P_I_7

.LL_P_I_8:
@ (return)
        ldmfd sp!, {fp, pc}
.ltorg

_read_char:
        stmfd  sp!, {r2, r7, fp, lr}
        add    fp, sp, $4
@ (= eof_reached FALSE)
        ldr    r1, =eof_reached
        ldr    r0, [r1]
        cmp    r0, $0
        bne    .L0
@ (my_read)
        GETCHAR
@ (= read_length 0)
        cmp    r0, $0
        bne    .L1
@ (set! in_ch -1)
        mov    r1, $0
        mvn    r1, r1 @ r1 = -1
        ldr    r0, =in_ch
        str    r1, [r0]
@ (set! eof_reached TRUE)
        mov    r1, $1
        ldr    r0, =eof_reached
        str    r1, [r0]
.L1:
.L0:
        ldmfd  sp!, {r2, r7, fp, pc}
.ltorg

signed_quotient:
        @ input r0 - numerator
        @ input r1 - denominator
        @ output r0 - quotient
        stmfd  sp!, {r2, r3, fp, lr}
        add    fp, sp, $4
@ (< N 0)
        cmp    r0, $0
        bge    .L2
@ (< D 0)
        cmp    r1, $0
        bge    .L4
@ (set! N (negate N 0))
        mov    r2, $0
        sub    r0, r2, r0
@ (set! D (negate D 0))
        sub    r1, r2, r1
@ (set! Q (quotient N D))
        bl     idiv
        mov    r0, r2
        b      .L5
.L4:
@ (set! N (negate N 0))
        mov    r2, $0
        sub    r0, r2, r0
@ (set! Q (quotient N D))
        bl     idiv
        mov    r0, r2 @ ???? can remove
@ (set! Q (negate Q 0))
        mov    r2, $0
        sub    r0, r2, r0
.L5:
        b      .L3
.L2:
@ (< D 0)
        cmp    r1, $0
        bge    .L6
@ (set! D (negate D 0))
        mov    r2, $0
        sub    r1, r2, r1
@ (set! Q (quotient N D))
        bl     idiv
        mov    r0, r2 @ ???? can remove
@ (set! Q (negate Q 0))
        mov    r2, $0
        sub    r0, r2, r0
        b      .L7
.L6:
@ (set! Q (quotient N D))
        bl     idiv
        mov    r0, r2
.L7:
.L3:
        ldmfd  sp!, {r2, r3, fp, pc}
.ltorg

signed_remainder:
        @ input r0 - numerator
        @ input r1 - denominator
        @ output r0 - remainder
        stmfd  sp!, {r2, r3, fp, lr}
        add    fp, sp, $4
@ (set! R (remainder N D))
        bl     idiv
        ldmfd  sp!, {r2, r3, fp, pc}
.ltorg

@ TODO delete all this code
@skip_blanks:
@        stmfd  sp!, {fp, lr}
@        add    fp, sp, $4
@skip_blanks_loop:
@@ (= in_ch 32)
@        ldr    r0, =in_ch
@        ldr    r1, [r0]
@        cmp    r1, $32
@        bne    .L13
@@ (read_char)
@        bl     _read_char
@@ (skip_blanks_loop)
@        b      skip_blanks_loop
@.L13:
@@ (= in_ch 10)
@        cmp    r1, $10
@        bne    .L15
@@ (read_char)
@        bl     _read_char
@@ (skip_blanks_loop)
@        b      skip_blanks_loop
@.L15:
@@ (= in_ch 13)
@        cmp    r1, $13
@        bne    .L17
@@ (read_char)
@        bl     _read_char
@@ (skip_blanks_loop)
@        b      skip_blanks_loop
@.L17:
@        ldmfd  sp!, {fp, pc}
@.ltorg
@
@my_scan_int:
@        stmfd  sp!, {r2, fp, lr}
@        add    fp, sp, $4
@@ (set! read_t1 0)
@        ldr    r0, =read_t1
@        mov    r1, $0
@        str    r1, [r0]
@@ (set! read_t2 0)
@        ldr    r0, =read_t2
@        mov    r1, $0
@        str    r1, [r0]
@@ (skip_blanks)
@        bl     skip_blanks
@@ (= in_ch 45)
@        ldr    r0, =in_ch
@        ldr    r1, [r0]
@        cmp    r1, $45
@        bne    .L18
@@ (set! read_t2 1)
@        ldr    r0, =read_t2
@        mov    r1, $1
@        str    r1, [r0]
@@ (read_char)
@        bl     _read_char
@.L18:
@skip_int_loop:
@@ (>= in_ch 48)
@        ldr    r0, =in_ch
@        ldr    r1, [r0]
@        cmp    r1, $48
@        blt    .L19
@@ (<= in_ch 57)
@        ldr    r0, =in_ch
@        ldr    r1, [r0]
@        cmp    r1, $57
@        bgt    .L20
@@ (set! read_t0 (* read_t1 10))
@        ldr    r0, =read_t1
@        ldr    r1, [r0]
@        mov    r0, $10
@        mul    r2, r0, r1
@        mov    r0, r2
@        ldr    r1, =read_t0
@        str    r0, [r1]
@@ (set! read_t0 (+ read_t0 in_ch))
@        ldr    r0, =read_t0
@        ldr    r1, [r0]
@        ldr    r0, =in_ch
@        ldr    r0, [r0]
@        add    r0, r0, r1
@        ldr    r1, =read_t0
@        str    r0, [r1]
@@ (set! read_t1 (- read_t0 48))
@        ldr    r0, =read_t0
@        ldr    r1, [r0]
@        mov    r0, $48
@        sub    r0, r1, r0
@        ldr    r1, =read_t1
@        str    r0, [r1]
@@ (read_char)
@        bl     _read_char
@@ (skip_int_loop)
@        b      skip_int_loop
@.L20:
@.L19:
@@ (= read_t2 1)
@        ldr    r0, =read_t2
@        ldr    r1, [r0]
@        cmp    r1, $1
@        bne    .L21
@@ (set! t0 (negate read_t1 0))
@        ldr    r0, =read_t1
@        ldr    r1, [r0]
@        mov    r0, $0
@        sub    r0, r0, r1
@        ldr    r1, =t0
@        str    r0, [r1]
@        b      .L22
@.L21:
@@ (set! t0 read_t1)
@        ldr    r0, =read_t1
@        ldr    r1, [r0]
@        ldr    r0, =t0
@        str    r1, [r0]
@.L22:
@        ldmfd  sp!, {r2, fp, pc}
@.ltorg

@ for debugging purposes

check_stack_overflow:
        stmfd  sp!, {r2, fp, lr}
        add    fp, sp, $4
        sub    r1, r3, r8
        mov    r1, r1, asr $2 @ divide by 4
        ldr    r2, =STACK_SIZE
        ldr    r2, [r2]
        cmp    r1, r2
        blt    .no_overflow
@       mov    r0, r2
@       bl     print_integer
@       mov    r2, $10 @ newline
@       bl     _print_character
        mov    r2, $115 @ s
        bl     _print_character
        mov    r2, $116 @ t
        bl     _print_character
        mov    r2, $97 @ a
        bl     _print_character
        mov    r2, $99 @ c
        bl     _print_character
        mov    r2, $107 @ k
        bl     _print_character
        mov    r2, $32
        bl     _print_character
        mov    r2, $111 @ o
        bl     _print_character
        mov    r2, $118 @ v
        bl     _print_character
        mov    r2, $101 @ e
        bl     _print_character
        mov    r2, $114 @ r
        bl     _print_character
        mov    r2, $102 @ f
        bl     _print_character
        mov    r2, $108 @ l
        bl     _print_character
        mov    r2, $111 @ o
        bl     _print_character
        mov    r2, $119 @ w
        bl     _print_character
        mov    r2, $10 @ newline
        bl     _print_character
@ (exit 0)
        EXIT_
.no_overflow:
        ldmfd  sp!, {r2, fp, pc}
