summaryrefslogblamecommitdiffstats
path: root/private/ntos/fw/mips/x4trap.s
blob: f567e29d3db7bf7fe4063e63a7b9284768306021 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































                                                                                 
#if defined(JAZZ) && defined(R4000)

//      TITLE("Interrupt and Exception Processing")
//++
//
// Copyright (c) 1991  Microsoft Corporation
//
// Module Name:
//
//    j4trap.s
//
// Abstract:
//
//    This module implements the code necessary to field and process MIPS
//    interrupt and exception conditions during bootstrap.
//
// Author:
//
//    David N. Cutler (davec) 21-Apr-1991
//
// Environment:
//
//    Kernel mode only.
//
// Revision History:
//
//--

#include "ksmips.h"

        SBTTL("Constant Value Definitions")
//++
//
// The following are definitions of constants used in this module.
//
//--

#define PSR_MASK (~((0x3 << PSR_KSU) | (1 << PSR_EXL))) // PSR exception mask

//++
//
// Define dummy data allocation.
//
//--

        .data
        .space  4                   //
SavedK1Address:
        .space  4                   // address where to save k1 to return to fw.

        SBTTL("General Exception Vector Routine")
//++
//
// Routine Description:
//
//    This routine is entered as the result of a general exception. The reason
//    for the exception is contained in the cause register. When this routine
//    is entered, interrupts are disabled.
//
//    All exception that occur during the bootstrap process are treated as
//    if a breakpoint had occurred. This ultimately causes either the kernel
//    debugger or a stub routine provided by the bootstrap itself to be
//    invoked.
//
//    The address of this routine is copied to the GEV in the SPB
//    so that the firmware jumps to this routine when a GeneralException
//    occurres. This routine must return to the address pointed by k1.
//    and leave the address where the firmware must return from the
//    exception in k0.
//
//
//
// Arguments:
//
//    None.
//
// Return Value:
//
//    None.
//
//--

        LEAF_ENTRY(KiGeneralException)
        //
        // No TLB Miss is supposed to occurr during the boot process
        // The TbMiss handler is just the same general exception handler.
        //
        ALTERNATE_ENTRY(KiTbMiss)
        START_REGION(KiGeneralExceptionStartAddress)

        .set    noreorder
        .set    noat
        la      k0,10f                  // transfer immediately to physical
        j       k0                      //
        nop                             //

10:     subu    k0,sp,TrapFrameLength   // allocate trap frame
        sw      sp,TrIntSp(k0)          // save integer register sp
        move    sp,k0                   // set new stack pointer
        la      k0,SavedK1Address       // get address of where to save k1
        sw      k1,0(k0)                // save firmware return address
        sw      gp,TrIntGp(sp)          // save integer register gp
        sw      s8,TrIntS8(sp)          // save integer register s8
        sw      ra,TrIntRa(sp)          // save integer register ra
        mfc0    s8,cause                // get cause of exception
        mfc0    k0,psr                  // get current processor status
        mfc0    k1,epc                  // get exception PC
        sw      k0,TrPsr(sp)            // save current PSR
        sw      k1,TrFir(sp)            // save exception PC
        bgez    s8,20f                  // if gez, exception not in delay slot
        move    s8,sp                   // set address of trap frame
        addu    k1,k1,4                 // compute address of exception
20:     j       KiBreakpointException   // finish in breakpoint code
        nop                             // fill delay slot
        .set    at
        .set    reorder

        END_REGION(KiGeneralExceptionEndAddress)

        .end    KiGeneralException

        SBTTL("Breakpoint Dispatch")
//++
//
// Routine Description:
//
//    The following code is never executed. Its purpose is to allow the
//    kernel debugger to walk call frames backwards through an exception,
//    to support unwinding through exceptions for system services, and to
//    support get/set user context.
//
//--

        NESTED_ENTRY(KiBreakpointDispatch, TrapFrameLength, zero);

        .set    noreorder
        .set    noat
        sw      sp,TrIntSp(sp)          // save stack pointer
        sw      ra,TrIntRa(sp)          // save return address
        sw      ra,TrFir(sp)            // save return address
        sw      s8,TrIntS8(sp)          // save frame pointer
        sw      gp,TrIntGp(sp)          // save general pointer
        move    s8,sp                   // set frame pointer
        .set    at
        .set    reorder

        PROLOGUE_END

//++
//
// Routine Description:
//
//    Control reaches here when a breakpoint exception code is read from the
//    cause register. When this routine is entered, interrupts are disabled.
//
//    The function of this routine is to raise a breakpoint exception.
//
//    N.B. Integer register v1 is not usuable in the first instuction of the
//       routine.
//
// Arguments:
//
//    k0 - Supplies the current PSR with the EXL bit set.
//    k1 - Supplies the address of the faulting instruction.
//    gp - Supplies a pointer to the system short data area.
//    s8 - Supplies a pointer to the trap frame.
//
// Return Value:
//
//    None.
//
//--

        ALTERNATE_ENTRY(KiBreakpointException)

        GENERATE_TRAP_FRAME             // save volatile machine state

        addu    a0,s8,TrExceptionRecord // compute exception record address
        sw      k1,ErExceptionAddress(a0) // save address of exception
        lw      t0,0(k1)                // get actual breakpoint instruction

        .set    noreorder
        .set    noat
        mfc0    k0,cause                // get cause of exception
        .set    at
        .set    reorder

        li      t1,XCODE_BREAKPOINT     // get exception code for breakpoint
        li      t2,STATUS_BREAKPOINT    // set exception status code
        and     k0,k0,R4000_XCODE_MASK  // isolate exception code
        beq     k0,t1,10f               // if eq, breakpoint
        move    t2,k0                   // set status to cause value
10:     sw      t0,ErExceptionInformation(a0) // save breakpoint instruction
        sw      t2,ErExceptionCode(a0)  //
        sw      zero,ErExceptionFlags(a0) // set exception flags
        sw      zero,ErExceptionRecord(a0) // set associated record
        sw      zero,ErNumberParameters(a0) // set number of parameters
        jal     KiExceptionDispatch     // join common code
        b       10b                     // dummy

        .end    KiBreakpointDispatch

        SBTTL("Exception Dispatch")
//++
//
// Routine Desription:
//
//    Control is transfered to this routine to call the exception
//    dispatcher to resolve an exception.
//
// Arguments:
//
//    a0 - Supplies a pointer to an exception record.
//
//    s8 - Supplies a pointer to a trap frame.
//
// Return Value:
//
//    There is no return from this routine.
//
//--

        NESTED_ENTRY(KiExceptionDispatch, ExceptionFrameLength, zero)

        subu    sp,sp,ExceptionFrameLength // allocate exception frame
        sw      ra,ExIntRa(sp)          // save return address
        sw      s0,ExIntS0(sp)          // save integer registers s0 - s7
        sw      s1,ExIntS1(sp)          //
        sw      s2,ExIntS2(sp)          //
        sw      s3,ExIntS3(sp)          //
        sw      s4,ExIntS4(sp)          //
        sw      s5,ExIntS5(sp)          //
        sw      s6,ExIntS6(sp)          //
        sw      s7,ExIntS7(sp)          //
        sdc1    f20,ExFltF20(sp)        // save floating registers f20 - f31
        sdc1    f22,ExFltF22(sp)        //
        sdc1    f24,ExFltF24(sp)        //
        sdc1    f26,ExFltF26(sp)        //
        sdc1    f28,ExFltF28(sp)        //
        sdc1    f30,ExFltF30(sp)        //

        PROLOGUE_END

//
// Call the exception dispatcher.
//

        move    a1,sp                   // set exception frame address
        move    a2,s8                   // set trap frame address
        move    a3,zero                 // set previous processor mode
        li      t0,TRUE                 // set first chance TRUE
        sw      t0,ExArgs + (4 * 4)(sp) //
        jal     KiDispatchException     // call exception dispatcher

//
// Restore the nonvolatile registers.
//

        lw      s0,ExIntS0(sp)          // restore integer registers s0 - s7
        lw      s1,ExIntS1(sp)          //
        lw      s2,ExIntS2(sp)          //
        lw      s3,ExIntS3(sp)          //
        lw      s4,ExIntS4(sp)          //
        lw      s5,ExIntS5(sp)          //
        lw      s6,ExIntS6(sp)          //
        lw      s7,ExIntS7(sp)          //
        ldc1    f20,ExFltF20(sp)        // restore floating registers f20 - f31
        ldc1    f22,ExFltF22(sp)        //
        ldc1    f24,ExFltF24(sp)        //
        ldc1    f26,ExFltF26(sp)        //
        ldc1    f28,ExFltF28(sp)        //
        ldc1    f30,ExFltF30(sp)        //

//
// Exit from the exception.
//

        lw      t0,TrPsr(s8)            // get previous processor status
        lw      gp,TrIntGp(s8)          // restore integer register gp
        li      t3,(1 << PSR_CU1) | (1 << PSR_EXL) // ****** r4000 errata

        .set    noreorder
        .set    noat
        mtc0    t3,psr                  // ****** r4000 errata
        nop                             // ****** r4000 errata
        nop                             // ****** r4000 errata
        nop                             // ****** r4000 errata
        mtc0    t0,psr                  // disable interrupts
        nop                             // ****** r4000 errata
        jal     KiRestoreTrapFrame      // restore volatile state
        lw      AT,TrIntAt(s8)          // restore integer register at
        move    sp,s8                   // trim stack to trap frame
        la      k0,SavedK1Address       // get address of where to save k1
        lw      k1,(k0)                 // save firmware return address
        lw      k0,TrFir(sp)            // get continuation address
        lw      s8,TrIntS8(sp)          // restore integer register s8
        lw      ra,TrIntRa(sp)          // restore return address
        j       k1                      // return to firmware
        lw      sp,TrIntSp(sp)          // restore stack pointer
        .set    at
        .set    reorder

        .end    KiExceptionDispatch

        SBTTL("Fill Fixed Translation Buffer Entry")
//++
//
// VOID
// KeFillFixedEntryTb (
//    IN HARDWARE_PTE Pte[],
//    IN PVOID Virtual,
//    IN ULONG Index
//    )
//
// Routine Description:
//
//    This function fills a fixed translation buffer entry.
//
// Arguments:
//
//    Pte (a0) - Supplies a pointer to the page table entries that are to be
//       written into the TB.
//
//    Virtual (a1) - Supplies the virtual address of the entry that is to
//       be filled in the translation buffer.
//
//    Index (a2) - Supplies the index where the TB entry is to be written.
//
// Return Value:
//
//    None.
//
//--

        LEAF_ENTRY(KeFillFixedEntryTb)

        lw      t0,0(a0)                // get first PTE value
        lw      t1,4(a0)                // get second PTE value

        DISABLE_INTERRUPTS(t2)          // disable interrupts

        .set    noreorder
        .set    noat
        mfc0    t3,entryhi              // get current PID and VPN2
        srl     a1,a1,ENTRYHI_VPN2      // isolate VPN2 of virtual address
        sll     a1,a1,ENTRYHI_VPN2      //
        and     t3,t3,0xff << ENTRYHI_PID // isolate current PID
        or      a1,t3,a1                // merge PID with VPN2 of virtual address
        mtc0    a1,entryhi              // set VPN2 and PID for probe
        mtc0    t0,entrylo0             // set first PTE value
        mtc0    t1,entrylo1             // set second PTE value
        mtc0    a2,index                // set TB entry index
        nop                             // 1 cycle hazzard
        tlbwi                           // overwrite indexed TB entry
        nop                             // 3 cycle hazzard
        .set    at
        .set    reorder

        ENABLE_INTERRUPTS(t2)           // enable interrupts

        j       ra                      // return

        .end    KeFillFixedEntryTb

        SBTTL("Flush Entire Translation Buffer")
//++
//
// VOID
// KiFlushEntireTb (
//    )
//
// Routine Description:
//
//    This function flushes the random part of the translation buffer.
//
// Arguments:
//
//    None.
//
// Return Value:
//
//    None.
//
//--

        LEAF_ENTRY(KiFlushEntireTb)

        b       KiFlushRandomTb         // execute common code

        .end    KiFlushEntireTb

        SBTTL("Flush Fixed Translation Buffer Entries")
//++
//
// VOID
// KiFlushFixedTb (
//    )
//
// Routine Description:
//
//    This function is called to flush all the fixed entries from the
//    translation buffer.
//
// Arguments:
//
//    None.
//
// Return Value:
//
//    None.
//
//--

        LEAF_ENTRY(KiFlushFixedTb)

        li      t0,FIXED_BASE           // set base index of fixed TB entries
        li      t3,FIXED_ENTRIES        // set number of fixed TB entries
        b       KiFlushTb               //

        .end    KiFlushFixedTb

        SBTTL("Flush Random Translation Buffer Entries")
//++
//
// VOID
// KiFlushRandomTb (
//    )
//
// Routine Description:
//
//    This function is called to flush all the random entries from the TB.
//
// Arguments:
//
//    None.
//
// Return Value:
//
//    None.
//
//--

        LEAF_ENTRY(KiFlushRandomTb)

        li      t0,FIXED_ENTRIES        // set base index of random TB entries
        li      t3,(48 - FIXED_ENTRIES) // set number of random TB entries

        ALTERNATE_ENTRY(KiFlushTb)

        li      t4,KSEG0_BASE           // set high part of TB entry

        DISABLE_INTERRUPTS(t2)          // disable interrupts

        .set    noreorder
        .set    noat
        addu    t3,t0,t3                // set index of highest entry + 1
        sll     t0,t0,INDEX_INDEX       // shift starting index into position
        sll     t3,t3,INDEX_INDEX       // shift ending index into position
        mfc0    t1,entryhi              // save contents of entryhi
        mtc0    zero,entrylo0           // set low part of TB entry
        mtc0    zero,entrylo1           //
        mtc0    t4,entryhi              //
        mtc0    t0,index                // set TB entry index
10:     addu    t0,t0,1                 //
        nop                             // ****** r4000 errata
        nop                             // ****** r4000 errata
        nop                             // ****** r4000 errata
        nop                             // ****** r4000 errata
        tlbwi                           // write TB entry
        bne     t0,t3,10b               // if ne, more entries to flush
        mtc0    t0,index                // set TB entry index
        nop                             // ****** r4000 errata
        nop                             // ****** r4000 errata
        nop                             // ****** r4000 errata
        mtc0    t1,entryhi              // restore contents of entryhi
        nop                             // ****** r4000 errata
        nop                             // ****** r4000 errata
        nop                             // ****** r4000 errata
        .set    at
        .set    reorder

        ENABLE_INTERRUPTS(t2)           // enable interrupts

        j       ra                      // return

        .end    KiFlushRandomTb

        SBTTL("Flush Single Translation Buffer Entry")
//++
//
// VOID
// KiFlushSingleTb (
//    IN BOOLEAN Invalid,
//    IN PVOID Virtual
//    )
//
// Routine Description:
//
//    This function flushes a single entry from the translation buffer.
//
// Arguments:
//
//    Invalid (a0) - Supplies a boolean variable that determines the reason
//       that the TB entry is being flushed.
//
//    Virtual (a1) - Supplies the virtual address of the entry that is to
//       be flushed from the translation buffer.
//
// Return Value:
//
//    None.
//
//--

        LEAF_ENTRY(KiFlushSingleTb)

        DISABLE_INTERRUPTS(t0)          // disable interrupts

        .set    noreorder
        .set    noat
        srl     t1,a1,ENTRYHI_VPN2      // clear all but VPN2 of virtual address
        mfc0    t2,entryhi              // get current PID and VPN2
        sll     t1,t1,ENTRYHI_VPN2      //
        and     t2,t2,0xff << ENTRYHI_PID // isolate current PID
        or      t1,t1,t2                // merge PID with VPN2 of virtual address
        mtc0    t1,entryhi              // set VPN2 and PID for probe
        nop                             // 3 cycle hazzard
        nop                             //
        nop                             //
        nop                             // ****** r4000 errata
        nop                             // ****** r4000 errata
        tlbp                            // probe for entry in TB
        nop                             // 2 cycle hazzard
        nop                             //
        mfc0    t3,index                // read result of probe
        nop                             // 1 cycle hazzard
        bltz    t3,30f                  // if ltz, entry is not in TB
        sll     t1,a1,0x1f - (ENTRYHI_VPN2 - 1) // shift low bit of VPN into sign
        bltzl   t1,10f                  // if ltz, invalidate second PTE
        mtc0    zero,entrylo1           // clear second PTE for flush
        mtc0    zero,entrylo0           // clear first PTE for flush
10:     nop                             // 1 cycle hazzard
        nop                             // ****** r4000 errata
        nop                             // ****** r4000 errata
        nop                             // ****** r4000 errata
        nop                             // ****** r4000 errata
        tlbwi                           // overwrite index TB entry
        nop                             // 3 cycle hazzard
        nop                             // ****** r4000 errata
        nop                             // ****** r4000 errata
        .set    at
        .set    reorder

30:     ENABLE_INTERRUPTS(t0)           // enable interrupts

        j       ra                      // return

        .end    KiFlushSingleTb

        SBTTL("Probe Tb Entry")
//++
//
// ULONG
// KiProbeEntryTb (
//     IN PVOID VirtualAddress
//     )
//
// Routine Description:
//
//    This function is called to determine if a specified entry is valid
///   and within the fixed portion of the TB.
//
// Arguments:
//
//    VirtualAddress - Supplies the virtual address to probe.
//
// Return Value:
//
//    A value of TRUE is returned if the specified entry is valid and within
//    the fixed part of the TB. Otherwise, a value of FALSE is returned.
//
//--

        LEAF_ENTRY(KiProbeEntryTb)

        DISABLE_INTERRUPTS(t0)          // disable interrupts


        .set    noreorder
        .set    noat
        srl     t1,a0,ENTRYHI_VPN2      // clear all but VPN2 of virtual address
        mfc0    t2,entryhi              // get current PID and VPN2
        sll     t1,t1,ENTRYHI_VPN2      //
        and     t2,t2,0xff << ENTRYHI_PID // isolate current PID
        or      t1,t1,t2                // merge PID with VPN2 of virtual address
        mtc0    t1,entryhi              // set VPN2 and PID for probe
        nop                             // 3 cycle hazzard
        nop                             //
        nop                             //
        nop                             // ****** r4000 errata
        nop                             // ****** r4000 errata
        tlbp                            // probe for entry in TB
        nop                             // 2 cycle hazzard
        nop                             //
        mfc0    t2,index                // read result of probe
        nop                             // 1 cycle hazzard
        bltz    t2,20f                  // if ltz, entry is not in TB
        li      v0,FALSE                // set to return failure
        tlbr                            // read entry from TB
        nop                             // 3 cycle hazzard
        nop                             //
        nop                             //
        nop                             // ****** r4000 errata
        nop                             // ****** r4000 errata
        sll     t1,a0,0x1f - (ENTRYHI_VPN2 - 1) // shift low bit of VPN into sign
        bltzl   t1,10f                  // if ltz, check second PTE
        mfc0    t1,entrylo1             // get second PTE for probe
        mfc0    t1,entrylo0             // get first PTE for probe
10:     nop                             // 1 cycle hazzard
        sll     t1,t1,0x1f - ENTRYLO_V  // shift valid bit into sign position
        bgez    t1,20f                  // if geq, entry is not valid
        srl     t2,INDEX_INDEX          // isolate index
        and     t2,t2,0x3f              //
        sltu    v0,t2,FIXED_ENTRIES     // check if entry in fixed part of TB
        .set    at
        .set    reorder

20:     ENABLE_INTERRUPTS(t0)           // enable interrupts

        .end    KiProbeEntryTb

        SBTTL("Read Tb Entry")
//++
//
// VOID
// KiReadEntryTb (
//     IN ULONG Index,
//     OUT PULONG EntryLo[],
//     OUT PULONG EntryHi
//     )
//
// Routine Description:
//
//    This function is called to read an entry from the TB.
//
// Arguments:
//
//    Index - Supplies the index of the entry to read.
//
//    entrylo - Supplies a pointer to a array that receives the first and
//       second TB entry values.
//
//    EntryHi - Supplies a pointer to a variable that receives the high
//       part of the TB entry.
//
// Return Value:
//
//    None.
//
//--

        LEAF_ENTRY(KiReadEntryTb)

        DISABLE_INTERRUPTS(t0)          // disable interrupts

        .set    noreorder
        .set    noat
        sll     a0,INDEX_INDEX          // shift index into position
        mfc0    t1,entryhi              // save entry high register
        mtc0    a0,index                // set TB entry index
        nop                             //
        nop                             // ****** r4000 errate
        nop                             // ****** r4000 errate
        nop                             // ****** r4000 errate
        nop                             // ****** r4000 errate
        tlbr                            // read entry from TB
        nop                             // 3 cycle hazzard
        nop                             //
        nop                             //
        nop                             // ****** r4000 errate
        nop                             // ****** r4000 errate
        mfc0    t2,entrylo0             // save first PTE value
        mfc0    t3,entrylo1             // save second PTE value
        mfc0    t4,entryhi              // save entry high register
        mtc0    t1,entryhi              // restore entry high register
        nop                             // ****** r4000 errate
        nop                             // ****** r4000 errate
        nop                             // ****** r4000 errate
        nop                             // ****** r4000 errate
        nop                             // ****** r4000 errate
        .set    at
        .set    reorder

        ENABLE_INTERRUPTS(t0)           // enable interrupts

        sw      t2,0(a1)                // set first PTE value
        sw      t3,4(a1)                // set second PTE value
        sw      t4,0(a2)                // set entry high register value
        j       ra                      // return

        .end    KiReadEntryTb

        SBTTL("Flush Write Buffer")
//++
//
// VOID
// KeFlushWriteBuffer (
//    VOID
//    )
//
// Routine Description:
//
//    This function flushes the write buffer on the current processor.
//
// Arguments:
//
//    None.
//
// Return Value:
//
//    None.
//
//--

        LEAF_ENTRY(KeFlushWriteBuffer)

        j       ra                      // return

        .end    KeFlushWritebuffer

//++
//
// BOOLEAN
// KiDisableInterrupts (
//    VOID
//    )
//
// Routine Description:
//
//    This function disables interrupts and returns whether interrupts
//    were previously enabled.
//
// Arguments:
//
//    None.
//
// Return Value:
//
//    A boolean value that determines whether interrupts were previously
//    enabled (TRUE) or disabled(FALSE).
//
//--

        LEAF_ENTRY(KiDisableInterrupts)

        .set    noreorder
        .set    noat

        mfc0    t0,psr                  // get current processor status
        li      t1,~(1 << PSR_IE)       // set interrupt enable mask
        and     t2,t1,t0                // clear interrupt enable
        mtc0    t2,psr                  // disable interrupts
        and     v0,t0,1 << PSR_IE       // iosolate current interrupt enable
        srl     v0,v0,PSR_IE            //

        .set    at
        .set    reorder

        j       ra                      // return

        .end    KiDisableInterrupts

        SBTTL("Restore Interrupts")
//++
//
// VOID
// KiRestoreInterrupts (
//    IN BOOLEAN Enable
//    )
//
// Routine Description:
//
//    This function restores the interrupt enable that was returned by
//    the disable interrupts function.
//
// Arguments:
//
//    Enable (a0) - Supplies the interrupt enable value.
//
// Return Value:
//
//    None.
//
//--

        LEAF_ENTRY(KiRestoreInterrupts)

        .set    noreorder
        .set    noat

        mfc0    t0,psr                  // get current processor status
        sll     t1,a0,PSR_IE            // shift previous enable into position
        or      t1,t1,t0                // merge previous enable
        mtc0    t1,psr                  // restore previous interrupt enable
        nop                             //

        .set    at
        .set    reorder

        j       ra                      // return

        .end    KiRestoreInterrupts


        SBTTL("Generate Trap Frame")
//++
//
// Routine Desription:
//
//    This routine is called to save the volatile integer and floating
//    registers in a trap frame.
//
//    N.B. This routine uses a special argument passing mechanism and destroys
//       no registers. It is assumed that integer register AT is saved by the
//       caller.
//
// Arguments:
//
//    s8 - Supplies a pointer to the base of an trap frame.
//
// Return Value:
//
//    None.
//
//--

        LEAF_ENTRY(KiGenerateTrapFrame)

        sw      v0,TrIntV0(s8)          // save integer register v0
        sw      v1,TrIntV1(s8)          // save integer register v1
        mflo    v1                      // save lo integer register
        sw      v1,TrIntLo(s8)          //
        mfhi    v1                      // save hi integer register
        sw      v1,TrIntHi(s8)          //
        lw      v1,TrIntV1(s8)          // restore integer register v1
        sw      a0,TrIntA0(s8)          // save integer registers a0 - a3
        sw      a1,TrIntA1(s8)          //
        sw      a2,TrIntA2(s8)          //
        sw      a3,TrIntA3(s8)          //
        sw      t0,TrIntT0(s8)          // save integer registers t0 - t9
        sw      t1,TrIntT1(s8)          //
        sw      t2,TrIntT2(s8)          //
        sw      t3,TrIntT3(s8)          //
        sw      t4,TrIntT4(s8)          //
        sw      t5,TrIntT5(s8)          //
        sw      t6,TrIntT6(s8)          //
        sw      t7,TrIntT7(s8)          //
        sw      t8,TrIntT8(s8)          //
        sw      t9,TrIntT9(s8)          //

#if defined(R3000)

        swc1    f0,TrFltF0(s8)          // save floating register f0

#endif

#if defined(R4000)

        sdc1    f0,TrFltF0(s8)          // save floating register f0

#endif

        b       KiSaveVolatileFloatState // save remainder of state

        .end    KiGenerateTrapFrame

        SBTTL("Restore Trap Frame")
//++
//
// Routine Description:
//
//    This routine is called to restore the volatile integer and floating
//    registers from a trap frame.
//
//    N.B. This routine uses a special argument passing mechanism and destroys
//       no registers. It is assumed that integer register AT is restored by
//       the caller.
//
// Arguments:
//
//    sp - Supplies a pointer to an exception frame.
//
// Return Value:
//
//    None.
//
//--

        LEAF_ENTRY(KiRestoreTrapFrame)

        lw      v0,TrIntV0(s8)          // restore integer register v0
        lw      v1,TrIntV1(s8)          // restore integer register v1
        lw      a0,TrIntA0(s8)          // restore integer registers a0 - a3
        lw      a1,TrIntA1(s8)          //
        lw      a2,TrIntA2(s8)          //
        lw      a3,TrIntA3(s8)          //
        lw      t0,TrIntLo(s8)          // restore lo and hi integer registers
        lw      t1,TrIntHi(s8)          //
        mtlo    t0                      //
        mthi    t1                      //
        lw      t0,TrIntT0(s8)          // restore integer registers t0 - t9
        lw      t1,TrIntT1(s8)          //
        lw      t2,TrIntT2(s8)          //
        lw      t3,TrIntT3(s8)          //
        lw      t4,TrIntT4(s8)          //
        lw      t5,TrIntT5(s8)          //
        lw      t6,TrIntT6(s8)          //
        lw      t7,TrIntT7(s8)          //
        lw      t8,TrIntT8(s8)          //
        lw      t9,TrIntT9(s8)          //

#if defined(R3000)

        lwc1    f0,TrFltF0(s8)          // restore floating register f0

#endif

#if defined(R4000)

        ldc1    f0,TrFltF0(s8)          // restore floating register f0

#endif

        b       KiRestoreVolatileFloatState // restore remainder of state

        .end    KiRestoreTrapFrame


        SBTTL("Save Volatile Floating Registers")
//++
//
// Routine Desription:
//
//    This routine is called to save the volatile floating registers.
//
//    N.B. This routine uses a special argument passing mechanism and destroys
//       no registers. It is assumed that floating register f0 is saved by the
//       caller.
//
// Arguments:
//
//    s8 - Supplies a pointer to a trap frame.
//
// Return Value:
//
//    None.
//
//--

        LEAF_ENTRY(KiSaveVolatileFloatState)

#if defined(R3000)

        swc1    f1,TrFltF1(s8)          // save floating register f1 - f19
        swc1    f2,TrFltF2(s8)          //
        swc1    f3,TrFltF3(s8)          //
        swc1    f4,TrFltF4(s8)          //
        swc1    f5,TrFltF5(s8)          //
        swc1    f6,TrFltF6(s8)          //
        swc1    f7,TrFltF7(s8)          //
        swc1    f8,TrFltF8(s8)          //
        swc1    f9,TrFltF9(s8)          //
        swc1    f10,TrFltF10(s8)        //
        swc1    f11,TrFltF11(s8)        //
        swc1    f12,TrFltF12(s8)        //
        swc1    f13,TrFltF13(s8)        //
        swc1    f14,TrFltF14(s8)        //
        swc1    f15,TrFltF15(s8)        //
        swc1    f16,TrFltF16(s8)        //
        swc1    f17,TrFltF17(s8)        //
        swc1    f18,TrFltF18(s8)        //
        swc1    f19,TrFltF19(s8)        //

#endif

#if defined(R4000)

        sdc1    f2,TrFltF2(s8)          // save floating register f2 - f19
        sdc1    f4,TrFltF4(s8)          //
        sdc1    f6,TrFltF6(s8)          //
        sdc1    f8,TrFltF8(s8)          //
        sdc1    f10,TrFltF10(s8)        //
        sdc1    f12,TrFltF12(s8)        //
        sdc1    f14,TrFltF14(s8)        //
        sdc1    f16,TrFltF16(s8)        //
        sdc1    f18,TrFltF18(s8)        //

#endif

        j       ra                      // return

        .end    KiSaveVolatileFloatState)

        SBTTL("Restore Volatile Floating Registers")
//++
//
// Routine Desription:
//
//    This routine is called to restore the volatile floating registers.
//
//    N.B. This routine uses a special argument passing mechanism and destroys
//       no registers. It is assumed that floating register f0 is restored by
//       the caller.
//
// Arguments:
//
//    s8 - Supplies a pointer to a trap frame.
//
// Return Value:
//
//    None.
//
//--

        LEAF_ENTRY(KiRestoreVolatileFloatState)

#if defined(R3000)

        lwc1    f1,TrFltF1(s8)          // restore floating registers f1 - f19
        lwc1    f2,TrFltF2(s8)          //
        lwc1    f3,TrFltF3(s8)          //
        lwc1    f4,TrFltF4(s8)          //
        lwc1    f5,TrFltF5(s8)          //
        lwc1    f6,TrFltF6(s8)          //
        lwc1    f7,TrFltF7(s8)          //
        lwc1    f8,TrFltF8(s8)          //
        lwc1    f9,TrFltF9(s8)          //
        lwc1    f10,TrFltF10(s8)        //
        lwc1    f11,TrFltF11(s8)        //
        lwc1    f12,TrFltF12(s8)        //
        lwc1    f13,TrFltF13(s8)        //
        lwc1    f14,TrFltF14(s8)        //
        lwc1    f15,TrFltF15(s8)        //
        lwc1    f16,TrFltF16(s8)        //
        lwc1    f17,TrFltF17(s8)        //
        lwc1    f18,TrFltF18(s8)        //
        lwc1    f19,TrFltF19(s8)        //

#endif

#if defined(R4000)

        ldc1    f2,TrFltF2(s8)          // restore floating registers f2 - f19
        ldc1    f4,TrFltF4(s8)          //
        ldc1    f6,TrFltF6(s8)          //
        ldc1    f8,TrFltF8(s8)          //
        ldc1    f10,TrFltF10(s8)        //
        ldc1    f12,TrFltF12(s8)        //
        ldc1    f14,TrFltF14(s8)        //
        ldc1    f16,TrFltF16(s8)        //
        ldc1    f18,TrFltF18(s8)        //

#endif

        j       ra                      // return

        .end    KiRestoreVolatileFloatState
#endif