-.global code940\r
+@ vim:filetype=armasm:\r
+\r
+@ ARM940 initialization.\r
+@ Based on ogg940 code by Dzz.\r
+@ (c) Copyright 2007, Grazvydas "notaz" Ignotas\r
+\r
+.equ mmsp2_regs, (0xc0000000-0x02000000) @ assume we live @ 0x2000000 bank\r
+.equ shared_ctl, 0x00200000 @ this is where shared_ctl struncture is located\r
\r
-code940: @ interrupt table:\r
+\r
+@ exception table:\r
+.global code940\r
+code940:\r
b .b_reset @ reset\r
b .b_undef @ undefined instructions\r
b .b_swi @ software interrupt\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, #0xbe000000 @ assume we live @ 0x2000000 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
+ mov r0, #shared_ctl @ remember where we were when interrupt happened\r
+ add r0, r0, #0x20\r
+ str lr, [r0]\r
+ mov r0, #shared_ctl @ increment exception counter (for debug)\r
+ add r0, r0, #(6*4)\r
+ ldr r1, [r0]\r
+ add r1, r1, #1\r
+ str r1, [r0]\r
+\r
+ bl Main940\r
+\r
+ @ we should never get here\r
+ b .b_reserved\r
+\r
+\r
.b_fiq:\r
mov r12, #7\r
b .Begin\r
\r
@ set up region 3: 64k 0xbe000000-0xbe010000 (hw control registers)\r
mov r0, #(0x0f<<1)|1\r
- orr r0, r0, #0xbe000000\r
+ orr r0, r0, #mmsp2_regs\r
mcr p15, 0, r0, c6, c3, 0\r
mcr p15, 0, r0, c6, c3, 1\r
\r
- @ set up region 4: 16M 0x01000000-0x02000000 (mp3 area)\r
- mov r0, #(0x17<<1)|1\r
- orr r0, r0, #0x01000000\r
+ @ region 4: 4K 0x00000000-0x00001000 (boot code protection region)\r
+ mov r0, #(0x0b<<1)|1\r
mcr p15, 0, r0, c6, c4, 0\r
mcr p15, 0, r0, c6, c4, 1\r
\r
- @ set regions 1 and 4 to be cacheable (so the first 2M and mp3 area will be cacheable)\r
- mov r0, #(1<<1)|(1<<4)\r
+ @ region 5: 4M 0x00400000-0x00800000 (mp3 area part1)\r
+ mov r0, #(0x15<<1)|1\r
+ orr r0, r0, #0x00400000\r
+ mcr p15, 0, r0, c6, c5, 0\r
+ mcr p15, 0, r0, c6, c5, 1\r
+\r
+ @ region 6: 8M 0x00800000-0x01000000 (mp3 area part2)\r
+ mov r0, #(0x16<<1)|1\r
+ orr r0, r0, #0x00800000\r
+ mcr p15, 0, r0, c6, c6, 0\r
+ mcr p15, 0, r0, c6, c6, 1\r
+\r
+ @ set regions 1, 4, 5 and 6 to be cacheable (so the first 2M and mp3 area will be cacheable)\r
+ mov r0, #(1<<1)|(1<<4)|(1<<5)|(1<<6)\r
mcr p15, 0, r0, c2, c0, 0\r
mcr p15, 0, r0, c2, c0, 1\r
\r
mov r0, #(1<<1)\r
mcr p15, 0, r0, c3, c0, 0\r
\r
- @ set protection, allow accsess only to regions 1 and 2\r
- mov r0, #(3<<8)|(3<<6)|(3<<4)|(3<<2)|(0) @ data: [full, full, full, full, no access] for regions [4 3 2 1 0]\r
+ @ set access protection\r
+ @ data: [full, full, no, full, full, full, no access] for regions [6 5 4 3 2 1 0]\r
+ mov r0, # (3<<12)|(3<<10)|(0<<8)\r
+ orr r0, r0, #(3<<6)|(3<< 4)|(3<< 2)|(0<<0)\r
mcr p15, 0, r0, c5, c0, 0\r
- mov r0, #(0<<8)|(0<<6)|(0<<4)|(3<<2)|(0) @ instructions: [no access, no, no, full, no]\r
+ @ instructions: [no, no, full, no, no, full, no]\r
+ mov r0, # (0<<12)|(0<<10)|(3<<8)\r
+ orr r0, r0, #(0<<6)|(0<< 4)|(3<< 2)|(0<<0)\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
- bic r0, r0, #0xC0000000\r
- orr r0, r0, #0x40000000 @ 0x40000000: synchronous, faster?\r
-@ orr r0, r0, #0xC0000000 @ 0xC0000000: async\r
+@ bic r0, r0, #0xC0000000\r
+@ orr r0, r0, #0x40000000 @ 0x40000000: synchronous, faster?\r
+ orr r0, r0, #0xC0000000 @ 0xC0000000: async\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
+ @ remember which exception vector we came from (increment counter for debug)\r
+ mov r0, #shared_ctl\r
+ add r0, r0, r12, lsl #2\r
+ ldr r1, [r0]\r
+ add r1, r1, #1\r
+ str r1, [r0]\r
+ \r
+ @ remember last lr (for debug)\r
+ mov r0, #shared_ctl\r
+ add r0, r0, #0x20\r
+ str lr, [r0]\r
+\r
+ @ ready to take first job-interrupt\r
+wait_for_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
+ nop\r
+ nop\r
+ b .b_reserved\r
+\r
\r
- @ we should never get here\r
-.b_deadloop:\r
- b .b_deadloop\r
\r
+@ next job getter\r
+.global wait_get_job @ int oldjob\r
\r
+wait_get_job:\r
+ mov r3, #mmsp2_regs\r
+ orr r2, r3, #0x3B00\r
+ orr r2, r2, #0x0046 @ DUALPEND940 register\r
+ ldrh r12,[r2]\r
\r
-@ so asm utils are also defined here:\r
+ tst r0, r0\r
+ beq wgj_no_old\r
+ sub r0, r0, #1\r
+ mov r1, #1\r
+ mov r1, r1, lsl r0\r
+ strh r1, [r2] @ clear finished job's pending bit\r
+ bic r12,r12,r1\r
+\r
+wgj_no_old:\r
+ tst r12,r12\r
+ beq wgj_no_jobs\r
+ mov r0, #0\r
+wgj_loop:\r
+ add r0, r0, #1\r
+ movs r12,r12,lsr #1\r
+ bxcs lr\r
+ b wgj_loop\r
+\r
+wgj_no_jobs:\r
+ mvn r0, #0\r
+ orr r2, r3, #0x4500\r
+ str r0, [r2] @ clear all pending interrupts in irq controller's SRCPND register\r
+ orr r2, r2, #0x0010\r
+ str r0, [r2] @ clear all pending interrupts in irq controller's INTPND register\r
+ b wait_for_irq\r
+\r
+.pool\r
+\r
+\r
+\r
+\r
+@ some asm utils are also defined here:\r
.global spend_cycles @ c\r
\r
spend_cycles:\r
\r
\r
@ clean-flush function from ARM940T technical reference manual\r
-.global cache_clean_flush\r
+.global dcache_clean_flush\r
\r
-cache_clean_flush:\r
+dcache_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
+ add r0, r0, #0x10 @ incremet segment counter\r
cmp r0, #0x40 @ complete all 4 segments?\r
bne ccf_inner_loop\r
add r1, r1, #0x04000000 @ increment line counter\r
bx lr\r
\r
\r
+\r
@ clean-only version\r
-.global cache_clean\r
+.global dcache_clean\r
\r
-cache_clean:\r
+dcache_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
+ add r0, r0, #0x10 @ incremet segment counter\r
cmp r0, #0x40 @ complete all 4 segments?\r
bne cf_inner_loop\r
add r1, r1, #0x04000000 @ increment line counter\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
+@ drain write buffer\r
+.global drain_wb\r
\r
+drain_wb:\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
+ mcr p15, 0, r0, c7, c10, 4\r
+ bx lr\r
\r
-.pool\r
\r
-@ vim:filetype=armasm:\r
+.global set_if_not_changed @ int *val, int oldval, int newval\r
+\r
+set_if_not_changed:\r
+ swp r3, r2, [r0]\r
+ cmp r1, r3\r
+ bxeq lr\r
+ strne r3, [r0] @ restore value which was changed there by other core\r
+ bx lr\r
+\r
+\r
+\r
+@ pad the protected region.\r
+.rept 1024\r
+.long 0\r
+.endr\r
+\r