PCM sound, refactored code940
[picodrive.git] / platform / gp2x / code940 / 940init.s
1 .global code940\r
2 \r
3 .equ mmsp2_regs, (0xc0000000-0x02000000) @ assume we live @ 0x2000000 bank\r
4 \r
5 code940:                          @ interrupt table:\r
6     b .b_reset                    @ reset\r
7     b .b_undef                    @ undefined instructions\r
8     b .b_swi                      @ software interrupt\r
9     b .b_pabort                   @ prefetch abort\r
10     b .b_dabort                   @ data abort\r
11     b .b_reserved                 @ reserved\r
12     b .b_irq                      @ IRQ\r
13     b .b_fiq                      @ FIQ\r
14 \r
15 @ test\r
16 .b_reset:\r
17     mov     r12, #0\r
18     b       .Begin\r
19 .b_undef:\r
20     mov     r12, #1\r
21     b       .Begin\r
22 .b_swi:\r
23     mov     r12, #2\r
24     b       .Begin\r
25 .b_pabort:\r
26     mov     r12, #3\r
27     b       .Begin\r
28 .b_dabort:\r
29     mov     r12, #4\r
30     b       .Begin\r
31 .b_reserved:\r
32     mov     r12, #5\r
33     b       .Begin\r
34 .b_irq:\r
35     mov     r12, #6\r
36     mov     sp, #0x100000       @ reset stack\r
37     sub     sp, sp, #4\r
38     mov     r1, #mmsp2_regs\r
39     orr     r2, r1, #0x3B00\r
40     orr     r2, r2, #0x0046\r
41     mvn     r3, #0\r
42     strh    r3, [r2]            @ clear any pending interrupts from the DUALCPU unit\r
43     orr     r2, r1, #0x4500\r
44     str     r3, [r2]            @ clear all pending interrupts in irq controller's SRCPND register\r
45     orr     r2, r2, #0x0010\r
46     str     r3, [r2]            @ clear all pending interrupts in irq controller's INTPND register\r
47     b       .Enter\r
48 .b_fiq:\r
49     mov     r12, #7\r
50     b       .Begin\r
51 \r
52 .Begin:\r
53     mov sp, #0x100000           @ set the stack top (1M)\r
54     sub sp, sp, #4              @ minus 4\r
55 \r
56     @ set up memory region 0 -- the whole 4GB address space\r
57     mov r0, #(0x1f<<1)|1        @ region data\r
58     mcr p15, 0, r0, c6, c0, 0   @ opcode2 ~ data/instr\r
59     mcr p15, 0, r0, c6, c0, 1\r
60 \r
61     @ set up region 1 which is the first 2 megabytes.\r
62     mov r0, #(0x14<<1)|1        @ region data\r
63     mcr p15, 0, r0, c6, c1, 0\r
64     mcr p15, 0, r0, c6, c1, 1\r
65 \r
66     @ set up region 2: 64k 0x200000-0x210000\r
67     mov r0, #(0x0f<<1)|1\r
68     orr r0, r0, #0x200000\r
69     mcr p15, 0, r0, c6, c2, 0\r
70     mcr p15, 0, r0, c6, c2, 1\r
71 \r
72     @ set up region 3: 64k 0xbe000000-0xbe010000 (hw control registers)\r
73     mov r0, #(0x0f<<1)|1\r
74     orr r0, r0, #mmsp2_regs\r
75     mcr p15, 0, r0, c6, c3, 0\r
76     mcr p15, 0, r0, c6, c3, 1\r
77 \r
78     @ set up region 4: 16M 0x01000000-0x02000000 (mp3 area)\r
79     mov r0, #(0x17<<1)|1\r
80     orr r0, r0, #0x01000000\r
81     mcr p15, 0, r0, c6, c4, 0\r
82     mcr p15, 0, r0, c6, c4, 1\r
83 \r
84     @ set regions 1 and 4 to be cacheable (so the first 2M and mp3 area will be cacheable)\r
85     mov r0, #(1<<1)|(1<<4)\r
86     mcr p15, 0, r0, c2, c0, 0\r
87     mcr p15, 0, r0, c2, c0, 1\r
88 \r
89     @ set region 1 to be bufferable too (only data)\r
90     mov r0, #(1<<1)\r
91     mcr p15, 0, r0, c3, c0, 0\r
92 \r
93     @ set protection, allow access only to regions 1 and 2\r
94     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
95     mcr p15, 0, r0, c5, c0, 0\r
96     mov r0, #(0<<8)|(0<<6)|(0<<4)|(3<<2)|(0)  @ instructions: [no access, no, no, full, no]\r
97     mcr p15, 0, r0, c5, c0, 1\r
98 \r
99     mrc p15, 0, r0, c1, c0, 0   @ fetch current control reg\r
100     orr r0, r0, #1              @ 0x00000001: enable protection unit\r
101     orr r0, r0, #4              @ 0x00000004: enable D cache\r
102     orr r0, r0, #0x1000         @ 0x00001000: enable I cache\r
103 @    bic r0, r0, #0xC0000000\r
104 @    orr r0, r0, #0x40000000     @ 0x40000000: synchronous, faster?\r
105     orr r0, r0, #0xC0000000     @ 0xC0000000: async\r
106     mcr p15, 0, r0, c1, c0, 0   @ set control reg\r
107 \r
108     @ flush (invalidate) the cache (just in case)\r
109     mov r0, #0\r
110     mcr p15, 0, r0, c7, c6, 0\r
111 \r
112 .Enter:\r
113     mov r0, r12\r
114     mov r1, lr\r
115     bl Main940\r
116 \r
117     @ we should never get here\r
118 @.b_deadloop:\r
119 @    b .b_deadloop\r
120     b .b_reserved\r
121 \r
122 \r
123 \r
124 @ so asm utils are also defined here:\r
125 .global spend_cycles @ c\r
126 \r
127 spend_cycles:\r
128     mov     r0, r0, lsr #2  @ 4 cycles/iteration\r
129     sub     r0, r0, #2      @ entry/exit/init\r
130 .sc_loop:\r
131     subs    r0, r0, #1\r
132     bpl     .sc_loop\r
133 \r
134     bx      lr\r
135 \r
136 \r
137 @ clean-flush function from ARM940T technical reference manual\r
138 .global cache_clean_flush\r
139 \r
140 cache_clean_flush:\r
141     mov     r1, #0                  @ init line counter\r
142 ccf_outer_loop:\r
143     mov     r0, #0                  @ segment counter\r
144 ccf_inner_loop:\r
145     orr     r2, r1, r0              @ make segment and line address\r
146     mcr     p15, 0, r2, c7, c14, 2  @ clean and flush that line\r
147     add     r0, r0, #0x10           @ incremet secment counter\r
148     cmp     r0, #0x40               @ complete all 4 segments?\r
149     bne     ccf_inner_loop\r
150     add     r1, r1, #0x04000000     @ increment line counter\r
151     cmp     r1, #0                  @ complete all lines?\r
152     bne     ccf_outer_loop\r
153     bx      lr\r
154 \r
155 \r
156 @ clean-only version\r
157 .global cache_clean\r
158 \r
159 cache_clean:\r
160     mov     r1, #0                  @ init line counter\r
161 cf_outer_loop:\r
162     mov     r0, #0                  @ segment counter\r
163 cf_inner_loop:\r
164     orr     r2, r1, r0              @ make segment and line address\r
165     mcr     p15, 0, r2, c7, c10, 2  @ clean that line\r
166     add     r0, r0, #0x10           @ incremet secment counter\r
167     cmp     r0, #0x40               @ complete all 4 segments?\r
168     bne     cf_inner_loop\r
169     add     r1, r1, #0x04000000     @ increment line counter\r
170     cmp     r1, #0                  @ complete all lines?\r
171     bne     cf_outer_loop\r
172     bx      lr\r
173 \r
174 \r
175 .global wait_irq\r
176 \r
177 wait_irq:\r
178     mov     r0, #mmsp2_regs\r
179     orr     r0, r0, #0x3B00\r
180     orr     r1, r0, #0x0042\r
181     mov     r3, #0\r
182     strh    r3, [r1]                @ disable interrupts\r
183     orr     r2, r0, #0x003E\r
184     strh    r3, [r2]                @ remove busy flag\r
185     mov     r3, #1\r
186     strh    r3, [r1]                @ enable interrupts\r
187 \r
188     mrs     r0, cpsr\r
189     bic     r0, r0, #0x80\r
190     msr     cpsr_c, r0              @ enable interrupts\r
191 \r
192     mov     r0, #0\r
193     mcr     p15, 0, r0, c7, c0, 4   @ wait for IRQ\r
194 @    mcr     p15, 0, r0, c15, c8, 2\r
195     nop\r
196     nop\r
197     b       .b_reserved\r
198 \r
199 .pool\r
200 \r
201 \r
202 .global set_if_not_changed @ int *val, int oldval, int newval\r
203 \r
204 set_if_not_changed:\r
205     swp    r3, r2, [r0]\r
206     cmp    r1, r3\r
207     bxeq   lr\r
208     strne  r3, [r0] @ restore value which was changed there by other core\r
209     bx     lr\r
210 \r
211 @ vim:filetype=armasm:\r