reset:
    br always >main
    nop

hardfault:
    reti
    nop

memfault:
    reti
    nop

timer_interrupt:
    br >timer_interrupt_handler
    nop

.align
led_addr: .word 0x000F0000
timer_counter_addr: .word 0x000F0008
timer_status_addr: .word 0x000F000C
dmem_start_addr: .word 0x00000400
dmem_end_addr: .word 0x000004FC
priority_mask: .word 0xFFFFFF03
xor_mask: .word 0xFFFFFFFF

main:
    // Initialize stack pointer to the end of the data memory
    ldr r12, >dmem_end_addr

    // Set runtime priority
    ldr r0, >priority_mask
    and r14, r0, r14

    ldr r0,>led_addr                // LED addr
    ldr r1,>timer_status_addr      // Timer addr

    // Init
    clr r9 // 0 if we are currently filling, 1 if we are currently flushing
    clr r8 // shift register
    clr r5 // shift counter
    clr r4 // shift counter top constant
    addi r4, 10

    // Enable the timer...
    clr r2
    addi r2, 0x3 // enable and repeat bit set
    st32 r1, r2

loop:
    br >loop
    nop

timer_interrupt_handler:
     clr r10
     addi r10, 1
     cmp eq r9, r10
     br true >flush
     nop
     br always >fill
     nop

rst_fill:
     clr r5
fill:
     clr r9

     // When shift register full, jump to flush
     addi r5, 1
     cmp eq r5, r4
     br true >rst_flush
     nop

     lsh r8, r8, 1
     addi r8, 1
     st08 r0, r8

     reti
     nop

rst_flush:
     clr r5
flush:
     clr r9
     addi r9, 1

     // When shift register empty, jump to fill
     addi r5, 1
     cmp eq r5, r4
     br true >rst_fill
     nop

     lsh r8, r8, 1
     st08 r0, r8

     reti
     nop

