aboutsummaryrefslogtreecommitdiff
path: root/src/boot.S
diff options
context:
space:
mode:
Diffstat (limited to 'src/boot.S')
-rw-r--r--src/boot.S135
1 files changed, 135 insertions, 0 deletions
diff --git a/src/boot.S b/src/boot.S
new file mode 100644
index 0000000..f0caebc
--- /dev/null
+++ b/src/boot.S
@@ -0,0 +1,135 @@
+// To keep this in the first portion of the binary.
+.section ".text.boot"
+
+// Make _start global.
+.globl _start
+
+_start:
+reset:
+ // disable core0,1,2.
+ mrc p15, #0, r1, c0, c0, #5
+ and r1, r1, #3
+ cmp r1, #0
+ bne io_halt
+
+ // set vector address.
+ ldr r0, =vector
+ mcR P15, 0, r0, c12, c0, 0
+
+ // save cpsr.
+ mrs r0, cpsr
+
+ // setup sp in IRQ mode.
+ bic r1, r0, #0x1f
+ orr r1, r1, #0x12
+ msr cpsr_c,r1
+ mov sp,#0x4000
+
+ // restore cpsr.
+ msr cpsr_c, r0
+
+ // setup the stack in SVC mode.
+ mov sp, #0x8000
+
+ // Clear out bss.
+ ldr r4, =__bss_start
+ ldr r9, =__bss_end
+ mov r5, #0
+ mov r6, #0
+ mov r7, #0
+ mov r8, #0
+ b 2f
+
+1:
+ // store multiple at r4.
+ stmia r4!, {r5-r8}
+
+ // If we are still below bss_end, loop.
+2:
+ cmp r4, r9
+ blo 1b
+
+ // Call kernel_main
+ ldr r3, =kernel_main
+ blx r3
+
+irq:
+ push {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
+ bl a_irq_handler
+ pop {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
+ subs pc, lr, #4
+
+.globl io_halt
+io_halt:
+ wfi
+ b io_halt
+
+.globl enable_irq
+enable_irq:
+ cpsie i
+ bx lr
+
+.globl disable_irq
+disable_irq:
+ cpsid i
+ bx lr
+
+.align 5
+vector:
+ ldr pc, reset_handler
+ ldr pc, undefined_handler
+ ldr pc, swi_handler
+ ldr pc, prefetch_handler
+ ldr pc, data_handler
+ ldr pc, unused_handler
+ ldr pc, irq_handler
+ ldr pc, fiq_handler
+
+reset_handler: .word reset
+undefined_handler: .word io_halt
+swi_handler: .word io_halt
+prefetch_handler: .word io_halt
+data_handler: .word io_halt
+unused_handler: .word io_halt
+irq_handler: .word irq
+fiq_handler: .word io_halt
+
+.global a_irq_handler
+a_irq_handler:
+ push {lr}
+ bl disable_irq
+ // r2 = CORE0_INTERRUPT_SOURCE
+ // if r2 & 0b100000000
+ mov r2, #0x40000000
+ ldr r3, [r2, #0x60]
+ tst r3, #256
+ beq a_irq_handler.exit
+ // r2 = IRQ_PEND2
+ // r2 & 1 << 25
+ mov r2, #0xB208
+ movt r2, #0x3F00
+ ldr r3, [r2]
+ tst r3, #0x2000000
+ beq a_irq_handler.exit
+ mov r2, #0x1040
+ movt r2, #0x3F20
+ ldr r3, [r2]
+ tst r3, #16
+ beq a_irq_handler.exit
+ mov r2, #0x1000
+ movt r2, #0x3F20
+ ldrb r0, [r2]
+ push {r0}
+ bl enable_irq
+ pop {r0}
+ bl uart_char
+ ldr r0, =amsg
+ bl uart_string
+ pop {pc}
+a_irq_handler.exit:
+ bl enable_irq
+ pop {pc}
+
+.section ".data"
+amsg:
+ .asciz " a_irq_handler\n"