]> git.lizzy.rs Git - plan9front.git/blob - sys/src/boot/bitsy/l.s
merge
[plan9front.git] / sys / src / boot / bitsy / l.s
1 #include "mem.h"
2
3 /*
4  * Entered here from Compaq's bootldr with MMU disabled.
5  */
6 TEXT _start(SB), $-4
7         MOVW    $setR12(SB), R12                /* load the SB */
8 _main:
9         /* SVC mode, interrupts disabled */
10         MOVW    $(PsrDirq|PsrDfiq|PsrMsvc), R1
11         MOVW    R1, CPSR
12
13         /* disable the MMU */
14         MOVW    $0x130, R1
15         MCR     CpMMU, 0, R1, C(CpControl), C(0x0)
16
17         /* flush caches */
18         MCR     CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
19         /* drain prefetch */
20         MOVW    R0,R0                                           
21         MOVW    R0,R0
22         MOVW    R0,R0
23         MOVW    R0,R0
24
25         /* drain write buffer */
26         MCR     CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
27
28         MOVW    $(MACHADDR+BY2PG), R13          /* stack */
29         SUB     $4, R13                         /* link */
30         BL      main(SB)
31         BL      exit(SB)
32         /* we shouldn't get here */
33 _mainloop:
34         B       _mainloop
35         BL      _div(SB)                        /* hack to get _div etc loaded */
36
37 /* flush tlb's */
38 TEXT mmuinvalidate(SB), $-4
39         MCR     CpMMU, 0, R0, C(CpTLBFlush), C(0x7)
40         RET
41
42 /* flush tlb's */
43 TEXT mmuinvalidateaddr(SB), $-4
44         MCR     CpMMU, 0, R0, C(CpTLBFlush), C(0x6), 1
45         RET
46
47 /* write back and invalidate i and d caches */
48 TEXT cacheflush(SB), $-4
49         /* write back any dirty data */
50         MOVW    $0xe0000000,R0
51         ADD     $(8*1024),R0,R1
52 _cfloop:
53         MOVW.P  32(R0),R2
54         CMP.S   R0,R1
55         BNE     _cfloop
56         
57         /* drain write buffer and invalidate i&d cache contents */
58         MCR     CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
59         MCR     CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
60
61         /* drain prefetch */
62         MOVW    R0,R0                                           
63         MOVW    R0,R0
64         MOVW    R0,R0
65         MOVW    R0,R0
66         RET
67
68 /* write back d cache */
69 TEXT cachewb(SB), $-4
70         /* write back any dirty data */
71 _cachewb:
72         MOVW    $0xe0000000,R0
73         ADD     $(8*1024),R0,R1
74 _cwbloop:
75         MOVW.P  32(R0),R2
76         CMP.S   R0,R1
77         BNE     _cwbloop
78         
79         /* drain write buffer */
80         MCR     CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
81         RET
82
83 /* write back a single cache line */
84 TEXT cachewbaddr(SB), $-4
85         BIC     $31,R0
86         MCR     CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
87         B       _wbflush
88
89 /* write back a region of cache lines */
90 TEXT cachewbregion(SB), $-4
91         MOVW    4(FP),R1
92         CMP.S   $(4*1024),R1
93         BGT     _cachewb
94         ADD     R0,R1
95         BIC     $31,R0
96 _cwbrloop:
97         MCR     CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
98         ADD     $32,R0
99         CMP.S   R0,R1
100         BGT     _cwbrloop
101         B       _wbflush
102
103 /* invalidate the dcache */
104 TEXT dcacheinvalidate(SB), $-4
105         MCR     CpMMU, 0, R0, C(CpCacheFlush), C(0x6)
106         RET
107
108 /* invalidate the icache */
109 TEXT icacheinvalidate(SB), $-4
110         MCR     CpMMU, 0, R0, C(CpCacheFlush), C(0x9)
111         RET
112
113 /* drain write buffer */
114 TEXT wbflush(SB), $-4
115 _wbflush:
116         MCR     CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
117         RET
118
119 /* return cpu id */
120 TEXT getcpuid(SB), $-4
121         MRC     CpMMU, 0, R0, C(CpCPUID), C(0x0)
122         RET
123
124 /* return fault status */
125 TEXT getfsr(SB), $-4
126         MRC     CpMMU, 0, R0, C(CpFSR), C(0x0)
127         RET
128
129 /* return fault address */
130 TEXT getfar(SB), $-4
131         MRC     CpMMU, 0, R0, C(CpFAR), C(0x0)
132         RET
133
134 /* return fault address */
135 TEXT putfar(SB), $-4
136         MRC     CpMMU, 0, R0, C(CpFAR), C(0x0)
137         RET
138
139 /* set the translation table base */
140 TEXT putttb(SB), $-4
141         MCR     CpMMU, 0, R0, C(CpTTB), C(0x0)
142         RET
143
144 /*
145  *  enable mmu, i and d caches
146  */
147 TEXT mmuenable(SB), $-4
148         MRC     CpMMU, 0, R0, C(CpControl), C(0x0)
149         ORR     $(CpCmmuena|CpCdcache|CpCicache|CpCwb), R0
150         MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
151         RET
152
153 TEXT mmudisable(SB), $-4
154         MRC     CpMMU, 0, R0, C(CpControl), C(0x0)
155         BIC     $(CpCmmuena|CpCdcache|CpCicache|CpCwb|CpCvivec), R0
156         MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
157         RET
158
159 /*
160  *  use exception vectors at 0xffff0000
161  */
162 TEXT mappedIvecEnable(SB), $-4
163         MRC     CpMMU, 0, R0, C(CpControl), C(0x0)
164         ORR     $(CpCvivec), R0
165         MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
166         RET
167 TEXT mappedIvecDisable(SB), $-4
168         MRC     CpMMU, 0, R0, C(CpControl), C(0x0)
169         BIC     $(CpCvivec), R0
170         MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
171         RET
172
173 /* set the translation table base */
174 TEXT putdac(SB), $-4
175         MCR     CpMMU, 0, R0, C(CpDAC), C(0x0)
176         RET
177
178 /* set address translation pid */
179 TEXT putpid(SB), $-4
180         MCR     CpMMU, 0, R0, C(CpPID), C(0x0)
181         RET
182
183 /*
184  *  set the stack value for the mode passed in R0
185  */
186 TEXT setr13(SB), $-4
187         MOVW    4(FP), R1
188
189         MOVW    CPSR, R2
190         BIC     $PsrMask, R2, R3
191         ORR     R0, R3
192         MOVW    R3, CPSR
193
194         MOVW    R13, R0
195         MOVW    R1, R13
196
197         MOVW    R2, CPSR
198         RET
199
200 /*
201  *  exception vectors, copied by trapinit() to somewhere useful
202  */
203
204 TEXT vectors(SB), $-4
205         MOVW    0x18(R15), R15                  /* reset */
206         MOVW    0x18(R15), R15                  /* undefined */
207         MOVW    0x18(R15), R15                  /* SWI */
208         MOVW    0x18(R15), R15                  /* prefetch abort */
209         MOVW    0x18(R15), R15                  /* data abort */
210         MOVW    0x18(R15), R15                  /* reserved */
211         MOVW    0x18(R15), R15                  /* IRQ */
212         MOVW    0x18(R15), R15                  /* FIQ */
213
214 TEXT vtable(SB), $-4
215         WORD    $_vsvc(SB)                      /* reset, in svc mode already */
216         WORD    $_vund(SB)                      /* undefined, switch to svc mode */
217         WORD    $_vsvc(SB)                      /* swi, in svc mode already */
218         WORD    $_vpabt(SB)                     /* prefetch abort, switch to svc mode */
219         WORD    $_vdabt(SB)                     /* data abort, switch to svc mode */
220         WORD    $_vsvc(SB)                      /* reserved */
221         WORD    $_virq(SB)                      /* IRQ, switch to svc mode */
222         WORD    $_vfiq(SB)                      /* FIQ, switch to svc mode */
223
224 TEXT _vrst(SB), $-4
225         BL      resettrap(SB)
226
227 TEXT _vsvc(SB), $-4                     /* SWI */
228         MOVW.W  R14, -4(R13)            /* ureg->pc = interupted PC */
229         MOVW    SPSR, R14               /* ureg->psr = SPSR */
230         MOVW.W  R14, -4(R13)            /* ... */
231         MOVW    $PsrMsvc, R14           /* ureg->type = PsrMsvc */
232         MOVW.W  R14, -4(R13)            /* ... */
233         MOVM.DB.W.S [R0-R14], (R13)     /* save user level registers, at end r13 points to ureg */
234         MOVW    $setR12(SB), R12        /* Make sure we've got the kernel's SB loaded */
235         MOVW    R13, R0                 /* first arg is pointer to ureg */
236         SUB     $8, R13                 /* space for argument+link */
237
238         BL      syscall(SB)
239
240         ADD     $(8+4*15), R13          /* make r13 point to ureg->type */
241         MOVW    8(R13), R14             /* restore link */
242         MOVW    4(R13), R0              /* restore SPSR */
243         MOVW    R0, SPSR                /* ... */
244         MOVM.DB.S (R13), [R0-R14]       /* restore registers */
245         ADD     $8, R13                 /* pop past ureg->{type+psr} */
246         RFE                             /* MOVM.IA.S.W (R13), [R15] */
247
248 TEXT _vund(SB), $-4                     /* undefined */
249         MOVM.IA [R0-R4], (R13)          /* free some working space */
250         MOVW    $PsrMund, R0
251         B       _vswitch
252
253 TEXT _vpabt(SB), $-4                    /* prefetch abort */
254         MOVM.IA [R0-R4], (R13)          /* free some working space */
255         MOVW    $PsrMabt, R0            /* r0 = type */
256         B       _vswitch
257
258 TEXT _vdabt(SB), $-4                    /* prefetch abort */
259         MOVM.IA [R0-R4], (R13)          /* free some working space */
260         MOVW    $(PsrMabt+1), R0                /* r0 = type */
261         B       _vswitch
262
263 TEXT _virq(SB), $-4                     /* IRQ */
264         MOVM.IA [R0-R4], (R13)          /* free some working space */
265         MOVW    $PsrMirq, R0            /* r0 = type */
266         B       _vswitch
267
268         /*
269          *  come here with type in R0 and R13 pointing above saved [r0-r4]
270          *  and type in r0.  we'll switch to SVC mode and then call trap.
271          */
272 _vswitch:
273         MOVW    SPSR, R1                /* save SPSR for ureg */
274         MOVW    R14, R2                 /* save interrupted pc for ureg */
275         MOVW    R13, R3                 /* save pointer to where the original [R0-R3] are */
276
277         /* switch to svc mode */
278         MOVW    CPSR, R14
279         BIC     $PsrMask, R14
280         ORR     $(PsrDirq|PsrDfiq|PsrMsvc), R14
281         MOVW    R14, CPSR
282
283         /* interupted code kernel or user? */
284         AND.S   $0xf, R1, R4
285         BEQ     _userexcep
286
287         /* here for trap from SVC mode */
288         MOVM.DB.W [R0-R2], (R13)        /* set ureg->{type, psr, pc}; r13 points to ureg->type  */
289         MOVM.IA   (R3), [R0-R4]         /* restore [R0-R4] from previous mode's stack */
290         MOVM.DB.W [R0-R14], (R13)       /* save kernel level registers, at end r13 points to ureg */
291         MOVW    $setR12(SB), R12        /* Make sure we've got the kernel's SB loaded */
292         MOVW    R13, R0                 /* first arg is pointer to ureg */
293         SUB     $8, R13                 /* space for argument+link (for debugger) */
294         MOVW    $0xdeaddead,R11         /* marker */
295
296         BL      trap(SB)
297
298         ADD     $(8+4*15), R13          /* make r13 point to ureg->type */
299         MOVW    8(R13), R14             /* restore link */
300         MOVW    4(R13), R0              /* restore SPSR */
301         MOVW    R0, SPSR                /* ... */
302         MOVM.DB (R13), [R0-R14] /* restore registers */
303         ADD     $8, R13                 /* pop past ureg->{type+psr} */
304         RFE                             /* MOVM.IA.S.W (R13), [R15] */
305
306         /* here for trap from USER mode */
307 _userexcep:
308         MOVM.DB.W [R0-R2], (R13)        /* set ureg->{type, psr, pc}; r13 points to ureg->type  */
309         MOVM.IA   (R3), [R0-R4]         /* restore [R0-R4] from previous mode's stack */
310         MOVM.DB.W.S [R0-R14], (R13)     /* save kernel level registers, at end r13 points to ureg */
311         MOVW    $setR12(SB), R12        /* Make sure we've got the kernel's SB loaded */
312         MOVW    R13, R0                 /* first arg is pointer to ureg */
313         SUB     $8, R13                 /* space for argument+link (for debugger) */
314
315         BL      trap(SB)
316
317         ADD     $(8+4*15), R13          /* make r13 point to ureg->type */
318         MOVW    8(R13), R14             /* restore link */
319         MOVW    4(R13), R0              /* restore SPSR */
320         MOVW    R0, SPSR                /* ... */
321         MOVM.DB.S (R13), [R0-R14]       /* restore registers */
322         ADD     $8, R13                 /* pop past ureg->{type+psr} */
323         RFE                             /* MOVM.IA.S.W (R13), [R15] */
324
325 TEXT _vfiq(SB), $-4                     /* FIQ */
326         RFE                             /* FIQ is special, ignore it for now */
327
328 /*
329  *  This is the first jump from kernel to user mode.
330  *  Fake a return from interrupt.
331  *
332  *  Enter with R0 containing the user stack pointer.
333  *  UTZERO + 0x20 is always the entry point.
334  *  
335  */
336 TEXT touser(SB),$-4
337         /* store the user stack pointer into the USR_r13 */
338         MOVM.DB.W [R0], (R13)
339         MOVM.S.IA.W (R13),[R13]
340
341         /* set up a PSR for user level */
342         MOVW    $(PsrMusr), R0
343         MOVW    R0,SPSR
344
345         /* save the PC on the stack */
346         MOVW    $(UTZERO+0x20), R0
347         MOVM.DB.W [R0],(R13)
348
349         /* return from interrupt */
350         RFE                             /* MOVM.IA.S.W (R13), [R15] */
351         
352 /*
353  *  here to jump to a newly forked process
354  */
355 TEXT forkret(SB),$-4
356         ADD     $(4*15), R13            /* make r13 point to ureg->type */
357         MOVW    8(R13), R14             /* restore link */
358         MOVW    4(R13), R0              /* restore SPSR */
359         MOVW    R0, SPSR                /* ... */
360         MOVM.DB.S (R13), [R0-R14]       /* restore registers */
361         ADD     $8, R13                 /* pop past ureg->{type+psr} */
362         RFE                             /* MOVM.IA.S.W (R13), [R15] */
363
364 TEXT splhi(SB), $-4
365         /* save caller pc in Mach */
366         MOVW    $(MACHADDR+0x04),R2
367         MOVW    R14,0(R2)
368         /* turn off interrupts */
369         MOVW    CPSR, R0
370         ORR     $(PsrDfiq|PsrDirq), R0, R1
371         MOVW    R1, CPSR
372         RET
373
374 TEXT spllo(SB), $-4
375         MOVW    CPSR, R0
376         BIC     $(PsrDfiq|PsrDirq), R0, R1
377         MOVW    R1, CPSR
378         RET
379
380 TEXT splx(SB), $-4
381         /* save caller pc in Mach */
382         MOVW    $(MACHADDR+0x04),R2
383         MOVW    R14,0(R2)
384         /* reset interrupt level */
385         MOVW    R0, R1
386         MOVW    CPSR, R0
387         MOVW    R1, CPSR
388         RET
389
390 TEXT splxpc(SB), $-4                            /* for iunlock */
391         MOVW    R0, R1
392         MOVW    CPSR, R0
393         MOVW    R1, CPSR
394         RET
395
396 TEXT spldone(SB), $0
397         RET
398
399 TEXT islo(SB), $-4
400         MOVW    CPSR, R0
401         AND     $(PsrDfiq|PsrDirq), R0
402         EOR     $(PsrDfiq|PsrDirq), R0
403         RET
404
405 TEXT cpsrr(SB), $-4
406         MOVW    CPSR, R0
407         RET
408
409 TEXT spsrr(SB), $-4
410         MOVW    SPSR, R0
411         RET
412
413 TEXT getcallerpc(SB), $-4
414         MOVW    0(R13), R0
415         RET
416
417 TEXT tas(SB), $-4
418         MOVW    R0, R1
419         MOVW    $0xDEADDEAD, R2
420         SWPW    R2, (R1), R0
421         RET
422
423 TEXT setlabel(SB), $-4
424         MOVW    R13, 0(R0)                      /* sp */
425         MOVW    R14, 4(R0)                      /* pc */
426         MOVW    $0, R0
427         RET
428
429 TEXT gotolabel(SB), $-4
430         MOVW    0(R0), R13                      /* sp */
431         MOVW    4(R0), R14                      /* pc */
432         MOVW    $1, R0
433         RET
434
435
436 /* The first MCR instruction of this function needs to be on a cache-line
437  * boundary; to make this happen, it will be copied (in trap.c).
438  *
439  * Doze puts the machine into idle mode.  Any interrupt will get it out
440  * at the next instruction (the RET, to be precise).
441  */
442 TEXT _doze(SB), $-4
443         MOVW    $UCDRAMZERO, R1
444         MOVW    R0,R0
445         MOVW    R0,R0
446         MOVW    R0,R0
447         MOVW    R0,R0
448         MOVW    R0,R0
449         MOVW    R0,R0
450         MOVW    R0,R0
451         MCR     CpPWR, 0, R0, C(CpTest), C(0x2), 2
452         MOVW    (R1), R0
453         MCR     CpPWR, 0, R0, C(CpTest), C(0x8), 2
454         RET