initial import
[picodrive.git] / platform / gp2x / 940init.s
diff --git a/platform/gp2x/940init.s b/platform/gp2x/940init.s
new file mode 100644 (file)
index 0000000..e28b453
--- /dev/null
@@ -0,0 +1,174 @@
+.global code940\r
+\r
+code940:                          @ interrupt table:\r
+    b .b_reset                    @ reset\r
+    b .b_undef                    @ undefined instructions\r
+    b .b_swi                      @ software interrupt\r
+    b .b_pabort                   @ prefetch abort\r
+    b .b_dabort                   @ data abort\r
+    b .b_reserved                 @ reserved\r
+    b .b_irq                      @ IRQ\r
+    b .b_fiq                      @ FIQ\r
+\r
+@ test\r
+.b_reset:\r
+    mov     r12, #0\r
+    b       .Begin\r
+.b_undef:\r
+    mov     r12, #1\r
+    b       .Begin\r
+.b_swi:\r
+    mov     r12, #2\r
+    b       .Begin\r
+.b_pabort:\r
+    mov     r12, #3\r
+    b       .Begin\r
+.b_dabort:\r
+    mov     r12, #4\r
+    b       .Begin\r
+.b_reserved:\r
+    mov     r12, #5\r
+    b       .Begin\r
+.b_irq:\r
+    mov     r12, #6\r
+       mov     sp, #0x100000       @ reset stack\r
+       sub     sp, sp, #4\r
+    mov     r1, #0xbd000000     @ assume we live @ 0x3000000 bank\r
+    orr     r2, r1, #0x3B00\r
+    orr     r2, r2, #0x0046\r
+    mvn     r3, #0\r
+    strh    r3, [r2]            @ clear any pending interrupts from the DUALCPU unit\r
+    orr     r2, r1, #0x4500\r
+    str     r3, [r2]            @ clear all pending interrupts in irq controller's SRCPND register\r
+    orr     r2, r2, #0x0010\r
+    str     r3, [r2]            @ clear all pending interrupts in irq controller's INTPND register\r
+    b       .Enter\r
+.b_fiq:\r
+    mov     r12, #7\r
+    b       .Begin\r
+\r
+.Begin:\r
+       mov sp, #0x100000           @ set the stack top (1M)\r
+       sub sp, sp, #4              @ minus 4\r
+\r
+       @ set up memory region 0 -- the whole 4GB address space\r
+       mov r0, #(0x1f<<1)|1        @ region data\r
+       mcr p15, 0, r0, c6, c0, 0   @ opcode2 ~ data/instr\r
+       mcr p15, 0, r0, c6, c0, 1\r
+\r
+    @ set up region 1 which is the first 2 megabytes.\r
+       mov r0, #(0x14<<1)|1        @ region data\r
+       mcr p15, 0, r0, c6, c1, 0\r
+       mcr p15, 0, r0, c6, c1, 1\r
+\r
+    @ set up region 2: 64k 0x200000-0x210000\r
+       mov r0, #(0x0f<<1)|1\r
+    orr r0, r0, #0x200000\r
+       mcr p15, 0, r0, c6, c2, 0\r
+       mcr p15, 0, r0, c6, c2, 1\r
+\r
+    @ set up region 3: 64k 0xbd000000-0xbd010000 (hw control registers)\r
+       mov r0, #(0x0f<<1)|1\r
+    orr r0, r0, #0xbd000000\r
+       mcr p15, 0, r0, c6, c3, 0\r
+       mcr p15, 0, r0, c6, c3, 1\r
+\r
+    @ set region 1 to be cacheable (so the first 2M will be cacheable)\r
+       mov r0, #2\r
+       mcr p15, 0, r0, c2, c0, 0\r
+       mcr p15, 0, r0, c2, c0, 1\r
+\r
+    @ set region 1 to be bufferable too (only data)\r
+       mcr p15, 0, r0, c3, c0, 0\r
+\r
+    @ set protection, allow accsess only to regions 1 and 2\r
+       mov r0, #(3<<6)|(3<<4)|(3<<2)|(0)  @ data: [full, full, full, no access] for regions [3 2 1 0]\r
+       mcr p15, 0, r0, c5, c0, 0\r
+       mov r0, #(0<<6)|(0<<4)|(3<<2)|(0)  @ instructions: [no access, no, full, no]\r
+       mcr p15, 0, r0, c5, c0, 1\r
+\r
+       mrc p15, 0, r0, c1, c0, 0   @ fetch current control reg\r
+       orr r0, r0, #1              @ 0x00000001: enable protection unit\r
+       orr r0, r0, #4              @ 0x00000004: enable D cache\r
+       orr r0, r0, #0x1000         @ 0x00001000: enable I cache\r
+       orr r0, r0, #0xC0000000     @ 0xC0000000: async+fastbus\r
+       mcr p15, 0, r0, c1, c0, 0   @ set control reg\r
+\r
+    @ flush (invalidate) the cache (just in case)\r
+    mov r0, #0\r
+    mcr p15, 0, r0, c7, c6, 0\r
+\r
+.Enter:\r
+    mov r0, r12\r
+    bl Main940\r
+\r
+    @ we should never get here\r
+.b_deadloop:\r
+    b .b_deadloop\r
+\r
+\r
+\r
+@ so asm utils are also defined here:\r
+.global spend_cycles @ c\r
+\r
+spend_cycles:\r
+    mov     r0, r0, lsr #2  @ 4 cycles/iteration\r
+    sub     r0, r0, #2      @ entry/exit/init\r
+.sc_loop:\r
+    subs    r0, r0, #1\r
+    bpl     .sc_loop\r
+\r
+    bx      lr\r
+\r
+\r
+@ clean-flush function from ARM940T technical reference manual\r
+.global cache_clean_flush\r
+\r
+cache_clean_flush:\r
+    mov     r1, #0                  @ init line counter\r
+ccf_outer_loop:\r
+    mov     r0, #0                  @ segment counter\r
+ccf_inner_loop:\r
+    orr     r2, r1, r0              @ make segment and line address\r
+    mcr     p15, 0, r2, c7, c14, 2  @ clean and flush that line\r
+    add     r0, r0, #0x10           @ incremet secment counter\r
+    cmp     r0, #0x40               @ complete all 4 segments?\r
+    bne     ccf_inner_loop\r
+    add     r1, r1, #0x04000000     @ increment line counter\r
+    cmp     r1, #0                  @ complete all lines?\r
+    bne     ccf_outer_loop\r
+    bx      lr\r
+\r
+\r
+@ clean-only version\r
+.global cache_clean\r
+\r
+cache_clean:\r
+    mov     r1, #0                  @ init line counter\r
+cf_outer_loop:\r
+    mov     r0, #0                  @ segment counter\r
+cf_inner_loop:\r
+    orr     r2, r1, r0              @ make segment and line address\r
+    mcr     p15, 0, r2, c7, c10, 2  @ clean that line\r
+    add     r0, r0, #0x10           @ incremet secment counter\r
+    cmp     r0, #0x40               @ complete all 4 segments?\r
+    bne     cf_inner_loop\r
+    add     r1, r1, #0x04000000     @ increment line counter\r
+    cmp     r1, #0                  @ complete all lines?\r
+    bne     cf_outer_loop\r
+    bx      lr\r
+\r
+\r
+.global wait_irq\r
+\r
+wait_irq:\r
+    mrs     r0, cpsr\r
+    bic     r0, r0, #0x80\r
+    msr     cpsr_c, r0               @ enable interrupts\r
+\r
+    mov     r0, #0\r
+    mcr     p15, 0, r0, c7, c0, 4   @ wait for IRQ\r
+@    mcr     p15, 0, r0, c15, c8, 2\r
+    b       .b_reserved\r
+\r
+.pool\r