]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/sgi/l.s
devarch: restrict i/o port access to 64K, disallow msr 32-bit wrap arround (thanks...
[plan9front.git] / sys / src / 9 / sgi / l.s
1 #include "mem.h"
2
3 #define SP      R29
4
5 #define NOOP            NOR R0, R0, R0
6 #define WAIT            NOOP; NOOP
7 #define RETURN          RET; NOOP
8 #define CONST(i, v)     MOVW $((i) & 0xffff0000), v; OR $((i) & 0xffff), v;
9 #define GETMACH(r)      CONST(MACHADDR, r)
10
11 /*
12  *  R4000 instructions
13  */
14 #define ERET            WORD    $0x42000018
15 #define LL(base, rt)    WORD    $((060<<26)|((base)<<21)|((rt)<<16))
16 #define SC(base, rt)    WORD    $((070<<26)|((base)<<21)|((rt)<<16))
17
18 #define MFC0(src,sel,dst) WORD $(0x40000000|((src)<<11)|((dst)<<16)|(sel))
19 #define MTC0(src,dst,sel) WORD $(0x40800000|((dst)<<11)|((src)<<16)|(sel))
20 #define RDHWR(hwr, r)   WORD $(0x7c00003b|((hwr)<<11)|((r)<<16))
21
22 /*
23  *  cache manipulation
24  */
25 #define CACHE   BREAK           /* overloaded op-code */
26
27 #define PI      R((0            /* primary I cache */
28 #define PD      R((1            /* primary D cache */
29 #define SD      R((3            /* secondary combined I/D cache */
30
31 #define IWBI    (0<<2)))        /* index write-back invalidate */
32 #define ILT     (1<<2)))        /* index load tag */
33 #define IST     (2<<2)))        /* index store tag */
34 #define CDE     (3<<2)))        /* create dirty exclusive */
35 #define HINV    (4<<2)))        /* hit invalidate */
36 #define HWBI    (5<<2)))        /* hit write back invalidate */
37 #define HWB     (6<<2)))        /* hit write back */
38 #define HSV     (7<<2)))        /* hit set virtual */
39
40         NOSCHED
41
42 /*
43  * Boot only processor
44  */
45
46 TEXT    start(SB), $-4
47         MOVW    $setR30(SB), R30
48
49         MOVW    $CU1, R1
50         MOVW    R1, M(STATUS)
51         WAIT
52
53         MOVW    $(0x1C<<7), R1
54         MOVW    R1, FCR31       /* permit only inexact and underflow */
55         NOOP
56         MOVD    $0.5, F26
57         SUBD    F26, F26, F24
58         ADDD    F26, F26, F28
59         ADDD    F28, F28, F30
60
61         MOVD    F24, F0
62         MOVD    F24, F2
63         MOVD    F24, F4
64         MOVD    F24, F6
65         MOVD    F24, F8
66         MOVD    F24, F10
67         MOVD    F24, F12
68         MOVD    F24, F14
69         MOVD    F24, F16
70         MOVD    F24, F18
71         MOVD    F24, F20
72         MOVD    F24, F22
73
74         MOVW    $MACHADDR, R(MACH)
75         ADDU    $(MACHSIZE-BY2V), R(MACH), SP
76
77         MOVW    R(MACH), R1
78 clrmach:
79         MOVW    R0, (R1)
80         ADDU    $BY2WD, R1
81         BNE     R1, SP, clrmach
82         NOOP
83
84         MOVW    $edata(SB), R1
85         MOVW    $end(SB), R2
86 clrbss:
87         MOVB    R0, (R1)
88         ADDU    $1, R1
89         BNE     R1, R2, clrbss
90         NOOP
91
92         MOVW    R0, 0(R(MACH))                  /* m->machno = 0 */
93         MOVW    R0, R(USER)                     /* up = nil */
94
95         JAL     main(SB)
96         NOOP
97
98 TEXT    arcs(SB), $256
99         MOVW    R24, 0x80(SP)
100         MOVW    R25, 0x84(SP)
101         MOVW    R26, 0x88(SP)
102         MOVW    R27, 0x8C(SP)
103
104         MOVW    $SPBADDR, R4
105         MOVW    0x20(R4), R5
106         ADDU    R1, R5
107         MOVW    (R5), R2
108
109         MOVW    16(FP), R7
110         MOVW    12(FP), R6
111         MOVW    8(FP), R5
112         MOVW    4(FP), R4
113
114         JAL     (R2)
115         NOOP
116
117         MOVW    $setR30(SB), R30
118
119         MOVW    0x80(SP), R24
120         MOVW    0x84(SP), R25
121         MOVW    0x88(SP), R26
122         MOVW    0x8C(SP), R27
123
124         MOVW    R2, R1
125         RETURN
126
127 /*
128  * Take first processor into user mode
129  *      - argument is stack pointer to user
130  */
131
132 TEXT    touser(SB), $-4
133         MOVW    M(STATUS), R4
134         MOVW    $(UTZERO+32), R2        /* header appears in text */
135         MOVW    R2, M(EPC)
136         MOVW    R1, SP
137         AND     $(~KMODEMASK), R4
138         OR      $(KUSER|IE|EXL), R4     /* switch to user mode, intrs on, exc */
139         MOVW    R4, M(STATUS)           /* " */
140         WAIT
141         ERET                            /* clears EXL */
142         NOOP
143
144 /*
145  * manipulate interrupts
146  */
147
148 /* enable an interrupt; bit is in R1 */
149 TEXT    intron(SB), $0
150         MOVW    M(STATUS), R2
151         WAIT
152         OR      R1, R2
153         MOVW    R2, M(STATUS)
154         WAIT
155         RETURN
156
157 /* disable an interrupt; bit is in R1 */
158 TEXT    introff(SB), $0
159         MOVW    M(STATUS), R2
160         WAIT
161         XOR     $-1, R1
162         AND     R1, R2
163         MOVW    R2, M(STATUS)
164         WAIT
165         RETURN
166
167 TEXT    splhi(SB), $0
168         MOVW    R31, 12(R(MACH))        /* save PC in m->splpc */
169         MOVW    M(STATUS), R1
170         WAIT
171         AND     $~IE, R1, R2
172         MOVW    R2, M(STATUS)
173         WAIT
174         RETURN
175
176 TEXT    splx(SB), $0
177         MOVW    R31, 12(R(MACH))        /* save PC in m->splpc */
178         MOVW    M(STATUS), R2
179         WAIT
180         AND     $IE, R1
181         AND     $~IE, R2
182         OR      R2, R1
183         MOVW    R1, M(STATUS)
184         WAIT
185         RETURN
186
187 TEXT    spllo(SB), $0
188         MOVW    M(STATUS), R1
189         WAIT
190         OR      $IE, R1, R2
191         MOVW    R2, M(STATUS)
192         WAIT
193         RETURN
194
195 TEXT    spldone(SB), $0
196         RETURN
197
198 TEXT    islo(SB), $0
199         MOVW    M(STATUS), R1
200         WAIT
201         AND     $IE, R1
202         RETURN
203
204 TEXT    coherence(SB), $-4
205         RETURN
206
207 /*
208  * process switching
209  */
210
211 TEXT    setlabel(SB), $-4
212         MOVW    SP, 0(R1)
213         MOVW    R31, 4(R1)
214         MOVW    R0, R1
215         RETURN
216
217 TEXT    gotolabel(SB), $-4
218         MOVW    0(R1), SP
219         MOVW    4(R1), R31
220         MOVW    $1, R1
221         RETURN
222
223 /*
224  * the tlb routines need to be called at splhi.
225  */
226
227 TEXT    getwired(SB),$0
228         MOVW    M(WIRED), R1
229         RETURN
230
231 TEXT    setwired(SB),$0
232         MOVW    R1, M(WIRED)
233         RETURN
234
235 TEXT    getrandom(SB),$0
236         MOVW    M(RANDOM), R1
237         RETURN
238
239 TEXT    getpagemask(SB),$0
240         MOVW    M(PAGEMASK), R1
241         RETURN
242
243 TEXT    setpagemask(SB),$0
244         MOVW    R1, M(PAGEMASK)
245         MOVW    R0, R1                  /* prevent accidents */
246         RETURN
247
248 TEXT    puttlbx(SB), $0 /* puttlbx(index, virt, phys0, phys1, pagemask) */
249         MOVW    4(FP), R2
250         MOVW    8(FP), R3
251         MOVW    12(FP), R4
252         MOVW    $((2*BY2PG-1) & ~0x1fff), R5
253         MOVW    R2, M(TLBVIRT)
254         MOVW    R3, M(TLBPHYS0)
255         MOVW    R4, M(TLBPHYS1)
256         MOVW    R5, M(PAGEMASK)
257         MOVW    R1, M(INDEX)
258         NOOP
259         NOOP
260         TLBWI
261         NOOP
262         RETURN
263
264 TEXT    tlbvirt(SB), $0
265         MOVW    M(TLBVIRT), R1
266         NOOP
267         RETURN
268
269 TEXT    gettlbx(SB), $0                 /* gettlbx(index, &entry) */
270         MOVW    4(FP), R4
271         MOVW    R1, M(INDEX)
272         NOOP
273         NOOP
274         TLBR
275         NOOP
276         NOOP
277         NOOP
278         MOVW    M(TLBVIRT), R1
279         MOVW    M(TLBPHYS0), R2
280         MOVW    M(TLBPHYS1), R3
281         NOOP
282         MOVW    R1, 0(R4)
283         MOVW    R2, 4(R4)
284         MOVW    R3, 8(R4)
285         RETURN
286
287 TEXT    gettlbp(SB), $0                 /* gettlbp(tlbvirt, &entry) */
288         MOVW    4(FP), R5
289         MOVW    R1, M(TLBVIRT)
290         NOOP
291         NOOP
292         NOOP
293         TLBP
294         NOOP
295         NOOP
296         MOVW    M(INDEX), R1
297         NOOP
298         BLTZ    R1, gettlbp1
299         TLBR
300         NOOP
301         NOOP
302         NOOP
303         MOVW    M(TLBVIRT), R2
304         MOVW    M(TLBPHYS0), R3
305         MOVW    M(TLBPHYS1), R4
306         NOOP
307         MOVW    R2, 0(R5)
308         MOVW    R3, 4(R5)
309         MOVW    R4, 8(R5)
310 gettlbp1:
311         RETURN
312
313 TEXT    gettlbvirt(SB), $0              /* gettlbvirt(index) */
314         MOVW    R1, M(INDEX)
315         NOOP
316         NOOP
317         TLBR
318         NOOP
319         NOOP
320         NOOP
321         MOVW    M(TLBVIRT), R1
322         NOOP
323         RETURN
324
325 /*
326  * compute stlb hash index.
327  *
328  * M(TLBVIRT) [page & asid] in arg, result in arg.
329  * stir in swizzled asid; we get best results with asid in both high & low bits.
330  */
331 #define STLBHASH(arg, tmp)              \
332         AND     $0xFF, arg, tmp;        \
333         SRL     $(PGSHIFT+1), arg;      \
334         XOR     tmp, arg;               \
335         SLL     $(STLBLOG-8), tmp;      \
336         XOR     tmp, arg;               \
337         CONST   (STLBSIZE-1, tmp);      \
338         AND     tmp, arg
339
340 TEXT    stlbhash(SB), $0                /* for mmu.c */
341         STLBHASH(R1, R2)
342         RETURN
343
344 TEXT    utlbmiss(SB), $-4
345         GETMACH (R26)
346         MOVW    R27, 12(R26)            /* m->splpc = R27 */
347
348         MOVW    16(R26), R27
349         ADDU    $1, R27
350         MOVW    R27,16(R26)             /* m->tlbfault++ */
351
352         MOVW    M(TLBVIRT), R27
353         NOOP
354         STLBHASH(R27, R26)
355
356         /* scale to a byte index (multiply by 12) */
357         SLL     $1, R27, R26            /* Ã— 2 */
358         ADDU    R26, R27                /* Ã— 3 */
359         SLL     $2, R27                 /* Ã— 12 */
360
361         GETMACH (R26)
362         MOVW    4(R26), R26
363         ADDU    R26, R27                /* R27 = &m->stb[hash] */
364
365         MOVW    M(BADVADDR), R26
366         NOOP
367         AND     $BY2PG, R26
368
369         BNE     R26, utlbodd            /* odd page? */
370         NOOP
371
372 utlbeven:
373         MOVW    4(R27), R26             /* R26 = m->stb[hash].phys0 */
374         BEQ     R26, stlbm              /* nothing cached? do it the hard way */
375         NOOP
376         MOVW    R26, M(TLBPHYS0)
377         MOVW    8(R27), R26             /* R26 = m->stb[hash].phys1 */
378         JMP     utlbcom
379         MOVW    R26, M(TLBPHYS1)        /* branch delay slot */
380
381 utlbodd:
382         MOVW    8(R27), R26             /* R26 = m->stb[hash].phys1 */
383         BEQ     R26, stlbm              /* nothing cached? do it the hard way */
384         NOOP
385         MOVW    R26, M(TLBPHYS1)
386         MOVW    4(R27), R26             /* R26 = m->stb[hash].phys0 */
387         MOVW    R26, M(TLBPHYS0)
388
389 utlbcom:
390         WAIT
391         MOVW    M(TLBVIRT), R26
392         MOVW    0(R27), R27             /* R27 = m->stb[hash].virt */
393         BEQ     R27, stlbm              /* nothing cached? do it the hard way */
394         NOOP
395         /* is the stlb entry for the right virtual address? */
396         BNE     R26, R27, stlbm         /* M(TLBVIRT) != m->stb[hash].virt? */
397         NOOP
398
399         /* if an entry exists, overwrite it, else write a random one */
400         CONST   (PGSZ, R27)
401         MOVW    R27, M(PAGEMASK)        /* select page size */
402         TLBP                            /* probe tlb */
403         NOOP
404         NOOP
405         MOVW    M(INDEX), R26
406         NOOP
407         BGEZ    R26, utlbindex          /* if tlb entry found, rewrite it */
408         NOOP
409         MOVW    M(RANDOM), R26
410         MOVW    R26, M(INDEX)
411 utlbindex:
412         NOOP
413         NOOP
414         TLBWI                           /* write indexed tlb entry */
415         NOOP
416
417 utlbret:
418         GETMACH (R26)
419         MOVW    12(R26), R27            /* R27 = m->splpc */
420         MOVW    M(EPC), R26
421         JMP     (R27)
422         NOOP
423
424 stlbm:
425         GETMACH (R26)
426         MOVW    12(R26), R27            /* R27 = m->splpc */
427
428         /* fall through */
429
430 TEXT    gevector(SB), $-4
431         MOVW    M(STATUS), R26
432         WAIT
433         AND     $KUSER, R26
434
435         BNE     R26, wasuser
436         MOVW    SP, R26                 /* delay slot, old SP in R26 */
437
438 waskernel:
439         JMP     dosave
440         SUBU    $UREGSIZE, SP           /* delay slot, allocate frame on kernel stack */
441
442 wasuser:                                /* get kernel stack for this user process */
443         GETMACH (SP)
444         MOVW    8(SP), SP               /*  m->proc */
445         MOVW    8(SP), SP               /*  m->proc->kstack */
446         ADDU    $(KSTACK-UREGSIZE), SP
447
448 dosave:
449         MOVW    R31, 0x28(SP)
450
451         JAL     saveregs(SB)
452         MOVW    R26, 0x10(SP)           /* delay slot, save old SP */
453
454         GETMACH (R(MACH))
455         MOVW    8(R(MACH)), R(USER)     /* R24 = m->proc */
456         MOVW    $setR30(SB), R30
457
458         BEQ     R26, dosys              /* set by saveregs() */
459         NOOP
460
461 dotrap:
462         MOVW    $forkret(SB), R31
463         JMP     trap(SB)
464         MOVW    4(SP), R1               /* delay slot, first arg to trap() */
465
466 dosys:
467         JAL     syscall(SB)
468         MOVW    4(SP), R1               /* delay slot, first arg to syscall() */
469
470         /* fall through */
471
472 TEXT    forkret(SB), $-4
473         JAL     restregs(SB)            /* restores old PC in R26 */
474         MOVW    0x14(SP), R1            /* delay slot, CAUSE */
475
476         MOVW    0x28(SP), R31
477
478         JMP     (R27)
479         MOVW    0x10(SP), SP            /* delay slot */
480
481 /*
482  * SP-> 0x00    --- (spill R31)
483  *      0x04    --- (trap()/syscall() arg1)
484  *      0x08    status
485  *      0x0C    pc
486  *      0x10    sp/usp
487  *      0x14    cause
488  *      0x18    badvaddr
489  *      0x1C    tlbvirt
490  *      0x20    hi
491  *      0x24    lo
492  *      0x28    r31
493  *      .....
494  *      0x9c    r1
495  */
496
497 TEXT    saveregs(SB), $-4
498         MOVW    R1, 0x9C(SP)
499         MOVW    R2, 0x98(SP)
500         MOVW    M(STATUS), R2
501         ADDU    $8, SP, R1
502         MOVW    R1, 0x04(SP)            /* arg to base of regs */
503         MOVW    $~KMODEMASK, R1
504         AND     R2, R1
505         MOVW    R1, M(STATUS)           /* so we can take another trap */
506         MOVW    R2, 0x08(SP)
507         MOVW    M(EPC), R2
508         MOVW    M(CAUSE), R1
509         MOVW    R2, 0x0C(SP)
510         MOVW    R1, 0x14(SP)
511         AND     $(EXCMASK<<2), R1
512         SUBU    $(CSYS<<2), R1, R26
513
514         BEQ     R26, notsaved           /* is syscall? */
515         MOVW    R27, 0x34(SP)           /* delay slot */
516
517         MOVW    M(BADVADDR), R1
518         MOVW    M(TLBVIRT), R2
519         MOVW    R1, 0x18(SP)
520         MOVW    R2, 0x1C(SP)
521
522         MOVW    HI, R1
523         MOVW    LO, R2
524         MOVW    R1, 0x20(SP)
525         MOVW    R2, 0x24(SP)
526
527         MOVW    R25, 0x3C(SP)
528         MOVW    R24, 0x40(SP)
529         MOVW    R23, 0x44(SP)
530         MOVW    R22, 0x48(SP)
531         MOVW    R21, 0x4C(SP)
532         MOVW    R20, 0x50(SP)
533         MOVW    R19, 0x54(SP)
534         MOVW    R18, 0x58(SP)
535         MOVW    R17, 0x5C(SP)
536         MOVW    R16, 0x60(SP)
537         MOVW    R15, 0x64(SP)
538         MOVW    R14, 0x68(SP)
539         MOVW    R13, 0x6C(SP)
540         MOVW    R12, 0x70(SP)
541         MOVW    R11, 0x74(SP)
542         MOVW    R10, 0x78(SP)
543         MOVW    R9, 0x7C(SP)
544         MOVW    R8, 0x80(SP)
545         MOVW    R7, 0x84(SP)
546         MOVW    R6, 0x88(SP)
547         MOVW    R5, 0x8C(SP)
548         MOVW    R4, 0x90(SP)
549         MOVW    R3, 0x94(SP)
550
551 notsaved:
552         MOVW    R30, 0x2C(SP)
553
554         RET
555         MOVW    R28, 0x30(SP)           /* delay slot */
556
557 TEXT    restregs(SB), $-4
558         AND     $(EXCMASK<<2), R1
559         SUBU    $(CSYS<<2), R1, R26
560
561         BEQ     R26, notrestored        /* is syscall? */
562         MOVW    0x34(SP), R27           /* delay slot */
563
564         MOVW    0x3C(SP), R25
565         MOVW    0x40(SP), R24
566         MOVW    0x44(SP), R23
567         MOVW    0x48(SP), R22
568         MOVW    0x4C(SP), R21
569         MOVW    0x50(SP), R20
570         MOVW    0x54(SP), R19
571         MOVW    0x58(SP), R18
572         MOVW    0x5C(SP), R17
573         MOVW    0x60(SP), R16
574         MOVW    0x64(SP), R15
575         MOVW    0x68(SP), R14
576         MOVW    0x6C(SP), R13
577         MOVW    0x70(SP), R12
578         MOVW    0x74(SP), R11
579         MOVW    0x78(SP), R10
580         MOVW    0x7C(SP), R9
581         MOVW    0x80(SP), R8
582         MOVW    0x84(SP), R7
583         MOVW    0x88(SP), R6
584         MOVW    0x8C(SP), R5
585         MOVW    0x90(SP), R4
586         MOVW    0x94(SP), R3
587
588         MOVW    0x24(SP), R2
589         MOVW    0x20(SP), R1
590         MOVW    R2, LO
591         MOVW    R1, HI
592
593         MOVW    0x98(SP), R2
594
595 notrestored:
596         MOVW    0x08(SP), R1
597         MOVW    R1, M(STATUS)
598         MOVW    0x0C(SP), R26           /* old PC */
599         MOVW    R26, M(EPC)
600
601         MOVW    0x30(SP), R28
602         MOVW    0x2C(SP), R30
603
604         RET
605         MOVW    0x9C(SP), R1            /* delay slot */
606
607 /*
608  * hardware interrupt vectors
609  */
610
611 TEXT    vector0(SB), $-4
612         WAIT
613         CONST   (SPBADDR+0x18, R26)
614         MOVW    $eret(SB), R27
615         MOVW    (R26), R26
616         JMP     (R26)
617         NOOP
618
619 TEXT    vector180(SB), $-4
620         WAIT
621         CONST   (SPBADDR+0x14, R26)
622         MOVW    $eret(SB), R27
623         MOVW    (R26), R26
624         JMP     (R26)
625         NOOP
626
627 TEXT    eret(SB), $-4           
628         ERET
629         NOOP
630
631 /*
632  *  floating-point stuff
633  */
634
635 TEXT    clrfpintr(SB), $0
636         MOVW    M(STATUS), R3
637         WAIT
638         OR      $CU1, R3
639         MOVW    R3, M(STATUS)
640         NOOP
641         NOOP
642         NOOP
643
644         MOVW    FCR31, R1
645         MOVW    R1, R2
646         AND     $~(0x3F<<12), R2
647         MOVW    R2, FCR31
648
649         AND     $~CU1, R3
650         MOVW    R3, M(STATUS)
651         WAIT
652         RETURN
653
654 TEXT    savefpregs(SB), $0
655         MOVW    FCR31, R2
656         MOVW    M(STATUS), R3
657         WAIT
658         AND     $~(0x3F<<12), R2, R4
659         MOVW    R4, FCR31
660
661         MOVD    F0, 0x00(R1)
662         MOVD    F2, 0x08(R1)
663         MOVD    F4, 0x10(R1)
664         MOVD    F6, 0x18(R1)
665         MOVD    F8, 0x20(R1)
666         MOVD    F10, 0x28(R1)
667         MOVD    F12, 0x30(R1)
668         MOVD    F14, 0x38(R1)
669         MOVD    F16, 0x40(R1)
670         MOVD    F18, 0x48(R1)
671         MOVD    F20, 0x50(R1)
672         MOVD    F22, 0x58(R1)
673         MOVD    F24, 0x60(R1)
674         MOVD    F26, 0x68(R1)
675         MOVD    F28, 0x70(R1)
676         MOVD    F30, 0x78(R1)
677
678         MOVW    R2, 0x80(R1)
679         AND     $~CU1, R3
680         MOVW    R3, M(STATUS)
681         WAIT
682         RETURN
683
684 TEXT    restfpregs(SB), $0
685         MOVW    M(STATUS), R3
686         WAIT
687         OR      $CU1, R3
688         MOVW    R3, M(STATUS)
689         WAIT
690         MOVW    fpstat+4(FP), R2
691         NOOP
692
693         MOVD    0x00(R1), F0
694         MOVD    0x08(R1), F2
695         MOVD    0x10(R1), F4
696         MOVD    0x18(R1), F6
697         MOVD    0x20(R1), F8
698         MOVD    0x28(R1), F10
699         MOVD    0x30(R1), F12
700         MOVD    0x38(R1), F14
701         MOVD    0x40(R1), F16
702         MOVD    0x48(R1), F18
703         MOVD    0x50(R1), F20
704         MOVD    0x58(R1), F22
705         MOVD    0x60(R1), F24
706         MOVD    0x68(R1), F26
707         MOVD    0x70(R1), F28
708         MOVD    0x78(R1), F30
709
710         MOVW    R2, FCR31
711         AND     $~CU1, R3
712         MOVW    R3, M(STATUS)
713         WAIT
714         RETURN
715
716 TEXT    fcr31(SB), $0                   /* fp csr */
717         MOVW    FCR31, R1
718         RETURN
719
720 /*
721  * Emulate 68020 test and set: load linked / store conditional
722  */
723
724 TEXT    tas(SB), $0
725 TEXT    _tas(SB), $0
726         MOVW    R1, R2          /* address of key */
727 tas1:
728         MOVW    $1, R3
729         LL(2, 1)
730         NOOP
731         SC(2, 3)
732         NOOP
733         BEQ     R3, tas1
734         NOOP
735         RETURN
736
737 /* used by the semaphore implementation */
738 TEXT cmpswap(SB), $0
739         MOVW    R1, R2          /* address of key */
740         MOVW    old+4(FP), R3   /* old value */
741         MOVW    new+8(FP), R4   /* new value */
742         LL(2, 1)                /* R1 = (R2) */
743         NOOP
744         BNE     R1, R3, fail
745         NOOP
746         MOVW    R4, R1
747         SC(2, 1)        /* (R2) = R1 if (R2) hasn't changed; R1 = success */
748         NOOP
749         RETURN
750 fail:
751         MOVW    R0, R1
752         RETURN
753
754 /*
755  *  cache manipulation
756  */
757
758 TEXT    icflush(SB), $-4                        /* icflush(virtaddr, count) */
759         MOVW    M(STATUS), R10
760         WAIT
761         MOVW    4(FP), R9
762         MOVW    $0, M(STATUS)
763         WAIT
764         ADDU    R1, R9                  /* R9 = last address */
765         MOVW    $(~0x3f), R8
766         AND     R1, R8                  /* R8 = first address, rounded down */
767         ADDU    $0x3f, R9
768         AND     $(~0x3f), R9            /* round last address up */
769         SUBU    R8, R9                  /* R9 = revised count */
770 icflush1:                       /* primary cache line size is 16 bytes */
771         CACHE   PD+HWB, 0x00(R8)
772         CACHE   PI+HINV, 0x00(R8)
773         CACHE   PD+HWB, 0x10(R8)
774         CACHE   PI+HINV, 0x10(R8)
775         CACHE   PD+HWB, 0x20(R8)
776         CACHE   PI+HINV, 0x20(R8)
777         CACHE   PD+HWB, 0x30(R8)
778         CACHE   PI+HINV, 0x30(R8)
779         SUBU    $0x40, R9
780         ADDU    $0x40, R8
781         BGTZ    R9, icflush1
782         MOVW    R10, M(STATUS)
783         WAIT
784         RETURN
785
786 TEXT    dcflush(SB), $-4                        /* dcflush(virtaddr, count) */
787         MOVW    M(STATUS), R10
788         WAIT
789         MOVW    4(FP), R9
790         MOVW    $0, M(STATUS)
791         WAIT
792         ADDU    R1, R9                  /* R9 = last address */
793         MOVW    $(~0x3f), R8
794         AND     R1, R8                  /* R8 = first address, rounded down */
795         ADDU    $0x3f, R9
796         AND     $(~0x3f), R9            /* round last address up */
797         SUBU    R8, R9                  /* R9 = revised count */
798 dcflush1:                       /* primary cache line size is 16 bytes */
799         CACHE   PD+HWB, 0x00(R8)
800         CACHE   PD+HWB, 0x10(R8)
801         CACHE   PD+HWB, 0x20(R8)
802         CACHE   PD+HWB, 0x30(R8)
803         SUBU    $0x40, R9
804         ADDU    $0x40, R8
805         BGTZ    R9, dcflush1
806         MOVW    R10, M(STATUS)
807         WAIT
808         RETURN
809
810 TEXT    outl(SB), $0
811         MOVW    4(FP), R2
812         MOVW    8(FP), R3
813         SLL     $2, R3
814         ADDU    R2, R3
815 outl1:
816         BEQ     R2, R3, outl2
817         MOVW    (R2), R4
818         MOVW    R4, (R1)
819         JMP     outl1
820         ADDU    $4, R2
821 outl2:
822         RETURN
823
824 /*
825  * access to CP0 registers
826  */
827
828 TEXT    prid(SB), $0
829         MOVW    M(PRID), R1
830         WAIT
831         RETURN
832
833 TEXT    rdcount(SB), $0
834         MOVW    M(COUNT), R1
835         RETURN
836
837 TEXT    wrcount(SB), $0
838         MOVW    R1, M(COUNT)
839         RETURN
840
841 TEXT    wrcompare(SB), $0
842         MOVW    R1, M(COMPARE)
843         RETURN
844
845 TEXT    rdcompare(SB), $0
846         MOVW    M(COMPARE), R1
847         RETURN
848
849         SCHED