Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / qemu-palcode / pal.S
1 /* QEMU Emulation PALcode.
2
3    Copyright (C) 2011 Richard Henderson
4
5    This file is part of QEMU PALcode.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the text
15    of the GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; see the file COPYING.  If not see
19    <http://www.gnu.org/licenses/>.  */
20
21         .set            noat
22         .set            nomacro
23         .text
24
25 #include "pal.h"
26 #include "osf.h"
27 #include SYSTEM_H
28
29 /*
30  * Create a standard kernel entry stack frame.
31  */
32
33 .macro  STACK_FRAME save_ps, save_pc, temp, do_ps
34         // Test if we're currently in user mode
35         and     \save_ps, PS_M_CM, \temp
36         beq     \temp, 0f
37         // Switch to kernel mode
38 .ifne \do_ps
39         mtpr    $31, qemu_ps
40 .endif
41         mtpr    $sp, qemu_usp
42         mfpr    $sp, ptKsp
43         // Allocate the stack frame
44 0:      lda     $sp, -FRM_K_SIZE($sp)
45         stq     \save_ps, FRM_Q_PS($sp)
46         stq     \save_pc, FRM_Q_PC($sp)
47         stq     $gp, FRM_Q_GP($sp)
48         stq     a0, FRM_Q_A0($sp)
49         stq     a1, FRM_Q_A1($sp)
50         stq     a2, FRM_Q_A2($sp)
51 .endm
52
53 /*
54  * Allocate a 1 page stack for use by the console.
55  */
56 #define STACK_SIZE      8192
57
58 /*
59  * QEMU emulator "hardware" entry points.
60  */
61
62 /*
63  * Reset
64  * 
65  * INPUT PARAMETERS:
66  * 
67  *      trap_arg0 = Memory size
68  *      trap_arg1 = Kernel entry (if loaded)
69  */ 
70         .org    0x0000
71         .globl  __start
72 __start:
73         // Initialize GP.
74         br      $gp, .+4
75         ldah    $gp, 0($gp)                     !gpdisp!1
76         lda     $gp, 0($gp)                     !gpdisp!1
77         mtpr    $gp, ptPgp
78
79         // Disable interrupts; kernel mode
80         lda     t0, IPL_K_HIGH
81         mtpr    t0, qemu_ps
82
83         // Initialize Stack.
84         SYS_WHAMI a0
85         lda     t0, STACK_SIZE
86         addq    a0, 1, t1
87         mull    t0, t1, t0
88         ldah    t1, stack($gp)                  !gprelhigh
89         lda     t1, stack(t1)                   !gprellow
90         addq    t0, t1, $sp
91
92         // Do any necessary system setup required for PALmode,
93         // e.g. setting up ptSys[01].
94         bsr     $26, Sys_Setup
95
96         // Non-boot CPUs can go wait now.
97         bne     a0, 1f
98
99         // Load boot arguments
100         mfpr    a0, qemu_trap_arg0
101         mfpr    a1, qemu_trap_arg1
102         mfpr    a2, qemu_trap_arg2
103
104         // Continue in do_start, outside PALmode.
105         ldah    $27, do_start($gp)              !gprelhigh
106         lda     $27, do_start($27)              !gprellow
107         hw_ret  ($27)
108
109 1:      ldah    $27, do_start_wait($gp)         !gprelhigh
110         lda     $27, do_start_wait($27)         !gprellow
111         hw_ret  ($27)
112 ENDFN   __start
113
114 /*
115  * Machine Check
116  *
117  * INPUT PARAMETERS:
118  * 
119  *      trap_arg0 = 
120  *      trap_arg1 = 
121  *      trap_arg2 = 
122  */
123         .org    0x0080
124 Pal_Mchk:
125         halt
126 ENDFN   Pal_Mchk
127
128 /*
129  * Interprocessor Interrupt
130  *
131  * INPUT PARAMETERS:
132  *
133  *      trap_arg0 = 
134  *      trap_arg1 =
135  *      trap_arg2 =
136  *
137  * The interprocessor interrupt is special, in that PALcode is supposed
138  * to clear the interupt and not wait for the OS to do it.
139  */
140         .org    0x0100
141 Pal_Smp_Interrupt:
142         mfpr    p6, qemu_exc_addr
143
144         SYS_ACK_SMP p0, p1, p2
145
146         mfpr    p0, qemu_ps
147
148         STACK_FRAME p0, p6, p2, 0
149
150         mov     IPL_K_IP, p0            // Raise IPL
151         mtpr    p0, qemu_ps
152
153         mfpr    p6, ptEntInt
154         mfpr    $gp, ptKgp
155         lda     a0, INT_K_IP
156         lda     a1, 0
157         lda     a2, 0
158
159         hw_ret  (p6)
160 ENDFN   Pal_Smp_Interrupt
161
162 /*
163  * Clock Interrupt
164  *
165  * INPUT PARAMETERS:
166  *
167  *      trap_arg0 = 
168  *      trap_arg1 =
169  *      trap_arg2 =
170  *
171  * The clock interrupt is special, in that PALcode is supposed
172  * to clear the interupt and not wait for the OS to do it.
173  */
174         .org    0x0180
175 Pal_Clk_Interrupt:
176         mfpr    p6, qemu_exc_addr
177
178         SYS_ACK_CLK p0, p1, p2
179
180         mfpr    p0, qemu_ps
181
182         STACK_FRAME p0, p6, p2, 0
183
184         mov     IPL_K_CLK, p0           // Raise IPL
185         mtpr    p0, qemu_ps
186
187         mfpr    p6, ptEntInt
188         mfpr    $gp, ptKgp
189         lda     a0, INT_K_CLK
190         lda     a1, 0
191         lda     a2, 0
192
193 9:      hw_ret  (p6)
194 ENDFN   Pal_Clk_Interrupt
195
196 /*
197  * Device Interrupt
198  *
199  * INPUT PARAMETERS:
200  *
201  *      trap_arg0 = 
202  *      trap_arg1 =
203  *      trap_arg2 =
204  */ 
205         .org    0x0200
206 Pal_Dev_Interrupt:
207         mfpr    p6, qemu_exc_addr
208         mfpr    p0, qemu_ps
209
210         STACK_FRAME p0, p6, p2, 0
211
212         mov     IPL_K_DEV1, p0          // Raise IPL
213         mtpr    p0, qemu_ps
214
215         bsr     p7, Sys_Dev_Vector
216
217         mfpr    p7, ptEntInt
218         mfpr    $gp, ptKgp
219         lda     a0, INT_K_DEV
220         lda     a2, 0
221         hw_ret  (p7)
222 ENDFN   Pal_Dev_Interrupt
223
224 /*
225  * Memory Fault
226  *
227  * INPUT PARAMETERS:
228  *
229  *      trap_arg0 = faulting address
230  *      trap_arg1 = fault type (TNV, ACV, FOR, FOW, FOE)
231  *      trap_arg2 = access type (exec=-1, read=0, write=1)
232  */ 
233         .org    0x0280
234 Pal_MMFault:
235         mfpr    p0, qemu_ps
236         mfpr    p6, qemu_exc_addr
237         blbs    p6, MchkBugCheck
238
239         STACK_FRAME p0, p6, p2, 1
240
241         mfpr    p0, ptEntMM
242         mfpr    $gp, ptKgp
243         mfpr    a0, qemu_trap_arg0
244         mfpr    a1, qemu_trap_arg1
245         mfpr    a2, qemu_trap_arg2
246         hw_ret  (p0)
247 ENDFN   Pal_MMFault
248
249 /*
250  * Unaligned Data
251  * 
252  * INPUT PARAMETERS:
253  *
254  *      trap_arg0 = faulting address
255  *      trap_arg1 = opcode of faulting insn
256  *      trap_arg2 = src/dst register number
257  */ 
258         .org    0x0300
259 Pal_Unalign:
260         mfpr    p0, qemu_ps
261         mfpr    p6, qemu_exc_addr
262         addq    p6, 4, p1               // increment past the faulting insn
263         blbs    p6, MchkBugCheck
264
265         STACK_FRAME p0, p1, p2, 1
266
267         mfpr    p0, ptEntUna
268         mfpr    $gp, ptKgp
269         mfpr    a0, qemu_trap_arg0
270         mfpr    a1, qemu_trap_arg1
271         mfpr    a2, qemu_trap_arg2
272         hw_ret  (p0)
273 ENDFN   Pal_Unalign
274
275 /*
276  * Illegal Opcode
277  *
278  * INPUT PARAMETERS:
279  *
280  *      trap_arg0 = UNDEFINED
281  *      trap_arg1 = UNDEFINED
282  *      trap_arg2 = UNDEFINED
283  *
284  * OUTPUT PARAMETERS:
285  *
286  *      r16 (a0) = Instruction fault code
287  *      r17 (a1) = UNPREDICTABLE
288  *      r18 (a2) = UNPREDICTABLE
289  */ 
290         .org    0x0380
291 Pal_OpcDec:
292         mfpr    p0, qemu_ps
293         mfpr    p6, qemu_exc_addr
294         addq    p6, 4, p1               // increment past the faulting insn
295         blbs    p6, MchkBugCheck
296
297         STACK_FRAME p0, p1, p2, 1
298
299         mfpr    p0, ptEntIF
300         mfpr    $gp, ptKgp
301         mov     IF_K_OPCDEC, a0
302         hw_ret  (p0)
303 ENDFN   Pal_OpcDec
304
305 /*
306  * Arithmetic Trap
307  *
308  * INPUT PARAMETERS:
309  *
310  *      trap_arg0 = exception type
311  *      trap_arg1 = register modification mask
312  *      trap_arg2 = UNDEFINED
313  */
314         .org    0x0400
315 Pal_Arith:
316         mfpr    p0, qemu_ps
317         mfpr    p6, qemu_exc_addr
318         blbs    p6, MchkBugCheck
319
320         STACK_FRAME p0, p6, p2, 1
321
322         mfpr    p0, ptEntArith
323         mfpr    $gp, ptKgp
324         mfpr    a0, qemu_trap_arg0
325         mfpr    a1, qemu_trap_arg1
326         hw_ret  (p0)
327 ENDFN   Pal_Arith
328
329 /*
330  * Floating Point Disabled
331  *
332  * INPUT PARAMETERS:
333  *
334  *      trap_arg0 = UNDEFINED
335  *      trap_arg1 = UNDEFINED
336  *      trap_arg2 = UNDEFINED
337  *
338  * OUTPUT PARAMETERS:
339  *
340  *      r16 (a0) = Instruction fault code
341  *      r17 (a1) = UNPREDICTABLE
342  *      r18 (a2) = UNPREDICTABLE
343  */ 
344         .org    0x0480
345 Pal_Fen:
346         mfpr    p0, qemu_ps
347         mfpr    p6, qemu_exc_addr
348         blbs    p6, MchkBugCheck
349
350         STACK_FRAME p0, p6, p2, 1
351
352         mfpr    p0, ptEntIF
353         mfpr    $gp, ptKgp
354         mov     IF_K_FEN, a0
355         hw_ret  (p0)
356 ENDFN   Pal_Fen
357 \f
358 /*
359  * OSF/1 Privileged CALL_PAL Entry Points
360  */
361
362 #define ORG_CALL_PAL_PRIV(X)    .org    0x1000+64*X
363
364 /*
365  * Halt
366  *
367  * SIDE EFFECTS:
368  *
369  *      We either power down the system or re-enter the console.
370  *      But given that we're not returning to the kernel, there's
371  *      no reason to continue processing in assembler.  Go to C.
372  */
373         ORG_CALL_PAL_PRIV(0x00)
374 CallPal_Halt:
375         bsr     p7, UpdatePCB           // Save kernel data
376         lda     v0, HLT_K_SW_HALT       // FIXME store this somewhere.
377
378         mtpr    $31, qemu_halt
379
380         br      Sys_EnterConsole
381 ENDFN   CallPal_Halt
382
383 /*
384  * Cache Flush
385  *
386  * For QEMU, this is of course a no-op.
387  */
388         ORG_CALL_PAL_PRIV(0x01)
389 CallPal_Cflush:
390         hw_rei
391 ENDFN   CallPal_Cflush
392
393 /*
394  * Drain Aborts
395  *
396  * For QEMU, this is of course a no-op.
397  */
398         ORG_CALL_PAL_PRIV(0x02)
399 CallPal_Draina:
400         hw_rei
401 ENDFN   CallPal_Draina
402
403         ORG_CALL_PAL_PRIV(0x03)
404 CallPal_OpcDec03:
405         br      CallPal_OpcDec
406 ENDFN   CallPal_OpcDec03
407
408         ORG_CALL_PAL_PRIV(0x04)
409 CallPal_OpcDec04:
410         br      CallPal_OpcDec
411 ENDFN   CallPal_OpcDec04
412
413         ORG_CALL_PAL_PRIV(0x05)
414 CallPal_OpcDec05:
415         br      CallPal_OpcDec
416 ENDFN   CallPal_OpcDec05
417
418         ORG_CALL_PAL_PRIV(0x06)
419 CallPal_OpcDec06:
420         br      CallPal_OpcDec
421 ENDFN   CallPal_OpcDec06
422
423         ORG_CALL_PAL_PRIV(0x07)
424 CallPal_OpcDec07:
425         br      CallPal_OpcDec
426 ENDFN   CallPal_OpcDec07
427
428         ORG_CALL_PAL_PRIV(0x08)
429 CallPal_OpcDec08:
430         br      CallPal_OpcDec
431 ENDFN   CallPal_OpcDec08
432
433 /*
434  * Console Service
435  * 
436  * INPUT PARAMETERS:
437  * 
438  *      r16 (a0)          = Option selector
439  *      r17..r21 (a1..a5) = Implementation specific entry parameters
440  *
441  * SIDE EFFECTS:
442  *
443  *      Registers a0..a5, and v0 are UNPREDICTABLE upon return.
444  */ 
445         ORG_CALL_PAL_PRIV(0x09)
446 CallPal_Cserve:
447         // Most of the entries are densely clustered around 0.
448         mov     0, v0
449         cmpule  a0, 7, p0
450         cmovne  p0, a0, v0
451         br      p0, 1f
452 1:      lda     p0, Cserve_Table-1b(p0)
453         s8addq  v0, p0, p0
454         jmp     $31, (p0), 0
455 ENDFN   CallPal_Cserve
456
457         .text   1
458         .align  3
459 /* Note that the entries in the following table are all 2 insns.
460    The first entry is unused, and is also where all out-of-range
461    commands are vectored.  */
462 Cserve_Table:
463         br      CallPal_Cserve_Cont
464         nop
465 Cserve_Ldqp:
466         ldq_p   v0, 0(a1)
467         hw_rei
468 ENDFN   Cserve_Ldqp
469 Cserve_Stqp:
470         stq_p   a2, 0(a1)
471         hw_rei
472 ENDFN   Cserve_Stqp
473 Cserve_Get_Wall_Time:
474         mfpr    v0, qemu_walltime
475         hw_rei
476 ENDFN   Cserve_Get_Wall_Time
477 Cserve_Get_Alarm:
478         mfpr    v0, qemu_alarm
479         hw_rei
480 ENDFN   Cserve_Get_Alarm
481 Cserve_Set_Alarm_Rel:
482         // Cheating here: create the absolute time and fall thru.
483         mfpr    p0, qemu_vmtime
484         addq    p0, a1, a1
485 ENDFN   Cserve_Set_Alarm_Rel
486 Cserve_Set_Alarm_Abs:
487         mtpr    a1, qemu_alarm
488         hw_rei
489 ENDFN   Cserve_Set_Alarm_Abs
490 Cserve_Get_VM_Time:
491         mfpr    v0, qemu_vmtime
492         hw_rei
493 ENDFN   Cserve_Get_VM_Time
494
495
496 CallPal_Cserve_Cont:
497         // ??? For SRM compatibility and their use within Linux, use 52/53
498         // for these.  Anyone know what other "standard" SRM Cserve entry
499         // points are?  Certainly we don't want to be compatible with MILO,
500         // which puts the selector at A2.
501         cmpeq   a0, 52, v0
502         bne     v0, Cserve_Ena
503         cmpeq   a0, 53, v0
504         bne     v0, Cserve_Dis
505         hw_rei
506 ENDFN   CallPal_Cserve_Cont
507         .previous
508
509 /*
510  * Swap PALcode
511  *
512  * FUNCTIONAL DESCRIPTION:
513  *
514  *      The swap PALcode (swppal) function replaces the current 
515  *      (active) PALcode by the specified new PALcode image.  
516  *      This function is intended for use by operating systems 
517  *      only during bootstraps and restarts, or during transitions 
518  *      to console I/O mode.
519  * 
520  *      The PALcode descriptor passed in a0 is interpreted as
521  *      either a PALcode variant or the base physical address
522  *      of the new PALcode image.  If a variant, the PALcode
523  *      image must have been previously loaded.  No PALcode
524  *      loading occurs as a result of this function. 
525  *
526  *      NOTE:
527  *      This implementation of SWPPAL does not support PALcode
528  *      variants.  If a variant is specified in a0, a check is
529  *      performed to determine whether the variant is OSF/1 or
530  *      not and the returned status is either unknown variant
531  *      (if not OSF/1) or variant not loaded.
532  *
533  * INPUT PARAMETERS:
534  *
535  *      r16 (a0) = New PALcode variant or base physical address
536  *      r17 (a1) = New PC
537  *      r18 (a2) = New PCB
538  *      r19 (a3) = New VptPtr
539  * 
540  * OUTPUT PARAMETERS:
541  *
542  *      r0 (v0) = Returned status indicating:
543  *                      0 - Success (PALcode was switched)
544  *                      1 - Unknown PALcode variant
545  *                      2 - Known PALcode variant, but PALcode not loaded
546  *
547  *      r26 (ra) = r27 (pv) = New PC
548  *              Note that this is non-architected, but is relied on by
549  *              the usage of SwpPal within our own console code in order
550  *              to simplify its use within C code.
551  *
552  */
553         ORG_CALL_PAL_PRIV(0x0A)
554 CallPal_SwpPal:
555         // Save a copy of the return address in case of machine check.
556         mfpr    p6, qemu_exc_addr
557
558         // Accept swapping to OSF PALcode.  The side effect here is to
559         // load the other parameters for the kernel.
560         cmpeq   a0, 2, v0
561         bne     v0, CallPal_SwpPal_Cont
562
563         // Return as an unknown PALcode variant
564         mov     1, v0
565         hw_rei
566 ENDFN   CallPal_SwpPal
567
568         .text   1
569 CallPal_SwpPal_Cont:
570         rpcc    p0
571         mtpr    a2, ptPcbb
572         mtpr    a3, qemu_vptptr
573
574         ldq_p   $sp, PCB_Q_KSP(a2)
575         ldq_p   t0, PCB_Q_USP(a2)
576         ldq_p   t1, PCB_Q_PTBR(a2)
577         ldl_p   t2, PCB_L_PCC(a2)
578         ldq_p   t3, PCB_Q_UNIQUE(a2)
579         ldq_p   t4, PCB_Q_FEN(a2)
580
581         mtpr    t0, qemu_usp
582
583         sll     t1, VA_S_OFF, t1
584         mtpr    t1, qemu_ptbr
585
586         subl    t2, p0, t2
587         mtpr    t2, qemu_pcc_ofs
588
589         mtpr    t3, qemu_unique
590
591         and     t4, 1, t4
592         mtpr    t4, qemu_fen
593
594         mtpr    $31, qemu_tbia          // Flush TLB for new PTBR
595
596         mov     a1, $26
597         mov     a1, $27
598         hw_ret  (a1)
599 ENDFN   CallPal_SwpPal_Cont
600         .previous
601
602         ORG_CALL_PAL_PRIV(0x0B)
603 CallPal_OpcDec0B:
604         br      CallPal_OpcDec
605 ENDFN   CallPal_OpcDec0B
606
607         ORG_CALL_PAL_PRIV(0x0C)
608 CallPal_OpcDec0C:
609         br      CallPal_OpcDec
610 ENDFN   CallPal_OpcDec0C
611
612 /*
613  * Write Interprocessor Interrupt Request
614  *
615  * INPUT PARAMETERS:
616  *
617  *      r16 (a0) = target processor number 
618  * 
619  * OUTPUT PARAMETERS:
620  *
621  * SIDE EFFECTS:
622  * 
623  */ 
624         ORG_CALL_PAL_PRIV(0x0D)
625 CallPal_WrIpir:
626         // Save a copy of the return address in case of machine check.
627         mfpr    p6, qemu_exc_addr
628
629         SYS_WRIPIR      a0, p0, p1, p2
630
631         hw_rei
632 ENDFN   CallPal_WrIpir
633
634         ORG_CALL_PAL_PRIV(0x0E)
635 CallPal_OpcDec0E:
636         br      CallPal_OpcDec
637 ENDFN   CallPal_OpcDec0E
638
639         ORG_CALL_PAL_PRIV(0x0F)
640 CallPal_OpcDec0F:
641         br      CallPal_OpcDec
642 ENDFN   CallPal_OpcDec0F
643
644 /*
645  * Read Machine Check Error Summary
646  *
647  * INPUT PARAMETERS:
648  * 
649  * OUTPUT PARAMETERS:
650  *
651  *      r0 (v0) = returned MCES value
652  * 
653  * SIDE EFFECTS:
654  *
655  */ 
656         ORG_CALL_PAL_PRIV(0x10)
657 CallPal_RdMces:
658         mfpr    v0, ptMces              // Get current MCES value
659         and     v0, MCES_M_ALL, v0      // Clear all other bits
660         hw_rei
661 ENDFN   CallPal_RdMces
662
663 /*
664  * Write Machine Check Error Summary
665  *
666  * INPUT PARAMETERS:
667  * 
668  *      r16 (a0) = MCES<DPC> <- a0<3>,  MCES<DSC> <- a0<4>
669  * 
670  * OUTPUT PARAMETERS:
671  *
672  * SIDE EFFECTS:
673  *
674  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
675  */ 
676         ORG_CALL_PAL_PRIV(0x11)
677 CallPal_WrMces:
678         // Clear MIP, SCE, PCE
679         and     a0, (MCES_M_MIP | MCES_M_SCE | MCES_M_PCE), p0
680         mfpr    p1, ptMces
681         bic     p1, p0, p1
682
683         // Copy DPC and DSC
684         and     a0, (MCES_M_DPC | MCES_M_DSC), p0
685         bic     p1, (MCES_M_DPC | MCES_M_DSC), p1
686         or      p1, p0, p1
687
688         mtpr    p1, ptMces
689         hw_rei
690 ENDFN   CallPal_WrMces
691
692         ORG_CALL_PAL_PRIV(0x12)
693 CallPal_OpcDec12:
694         br      CallPal_OpcDec
695 ENDFN   CallPal_OpcDec12
696
697         ORG_CALL_PAL_PRIV(0x13)
698 CallPal_OpcDec13:
699         br      CallPal_OpcDec
700 ENDFN   CallPal_OpcDec13
701
702         ORG_CALL_PAL_PRIV(0x14)
703 CallPal_OpcDec14:
704         br      CallPal_OpcDec
705 ENDFN   CallPal_OpcDec14
706
707         ORG_CALL_PAL_PRIV(0x15)
708 CallPal_OpcDec15:
709         br      CallPal_OpcDec
710 ENDFN   CallPal_OpcDec15
711
712         ORG_CALL_PAL_PRIV(0x16)
713 CallPal_OpcDec16:
714         br      CallPal_OpcDec
715 ENDFN   CallPal_OpcDec16
716
717         ORG_CALL_PAL_PRIV(0x17)
718 CallPal_OpcDec17:
719         br      CallPal_OpcDec
720 ENDFN   CallPal_OpcDec17
721
722         ORG_CALL_PAL_PRIV(0x18)
723 CallPal_OpcDec18:
724         br      CallPal_OpcDec
725 ENDFN   CallPal_OpcDec18
726
727         ORG_CALL_PAL_PRIV(0x19)
728 CallPal_OpcDec19:
729         br      CallPal_OpcDec
730 ENDFN   CallPal_OpcDec19
731
732         ORG_CALL_PAL_PRIV(0x1A)
733 CallPal_OpcDec1A:
734         br      CallPal_OpcDec
735 ENDFN   CallPal_OpcDec1A
736
737         ORG_CALL_PAL_PRIV(0x1B)
738 CallPal_OpcDec1B:
739         br      CallPal_OpcDec
740 ENDFN   CallPal_OpcDec1B
741
742         ORG_CALL_PAL_PRIV(0x1C)
743 CallPal_OpcDec1C:
744         br      CallPal_OpcDec
745 ENDFN   CallPal_OpcDec1C
746
747         ORG_CALL_PAL_PRIV(0x1D)
748 CallPal_OpcDec1D:
749         br      CallPal_OpcDec
750 ENDFN   CallPal_OpcDec1D
751
752         ORG_CALL_PAL_PRIV(0x1E)
753 CallPal_OpcDec1E:
754         br      CallPal_OpcDec
755 ENDFN   CallPal_OpcDec1E
756
757         ORG_CALL_PAL_PRIV(0x1F)
758 CallPal_OpcDec1F:
759         br      CallPal_OpcDec
760 ENDFN   CallPal_OpcDec1F
761
762         ORG_CALL_PAL_PRIV(0x20)
763 CallPal_OpcDec20:
764         br      CallPal_OpcDec
765 ENDFN   CallPal_OpcDec20
766
767         ORG_CALL_PAL_PRIV(0x21)
768 CallPal_OpcDec21:
769         br      CallPal_OpcDec
770 ENDFN   CallPal_OpcDec21
771
772         ORG_CALL_PAL_PRIV(0x22)
773 CallPal_OpcDec22:
774         br      CallPal_OpcDec
775 ENDFN   CallPal_OpcDec22
776
777         ORG_CALL_PAL_PRIV(0x23)
778 CallPal_OpcDec23:
779         br      CallPal_OpcDec
780 ENDFN   CallPal_OpcDec23
781
782         ORG_CALL_PAL_PRIV(0x24)
783 CallPal_OpcDec24:
784         br      CallPal_OpcDec
785 ENDFN   CallPal_OpcDec24
786
787         ORG_CALL_PAL_PRIV(0x25)
788 CallPal_OpcDec25:
789         br      CallPal_OpcDec
790 ENDFN   CallPal_OpcDec25
791
792         ORG_CALL_PAL_PRIV(0x26)
793 CallPal_OpcDec26:
794         br      CallPal_OpcDec
795 ENDFN   CallPal_OpcDec26
796
797         ORG_CALL_PAL_PRIV(0x27)
798 CallPal_OpcDec27:
799         br      CallPal_OpcDec
800 ENDFN   CallPal_OpcDec27
801
802         ORG_CALL_PAL_PRIV(0x28)
803 CallPal_OpcDec28:
804         br      CallPal_OpcDec
805 ENDFN   CallPal_OpcDec28
806
807         ORG_CALL_PAL_PRIV(0x29)
808 CallPal_OpcDec29:
809         br      CallPal_OpcDec
810 ENDFN   CallPal_OpcDec29
811
812         ORG_CALL_PAL_PRIV(0x2A)
813 CallPal_OpcDec2A:
814         br      CallPal_OpcDec
815 ENDFN   CallPal_OpcDec2A
816
817 /*
818  * Write Floating Point Enable
819  *
820  * INPUT PARAMETERS:
821  * 
822  *      r16 (a0) = ICSR<FPE> <- a0<0>
823  * 
824  * SIDE EFFECTS:
825  *
826  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
827  */ 
828         ORG_CALL_PAL_PRIV(0x2B)
829 CallPal_WrFen:
830         mfpr    p0, ptPcbb              // Get PCBB
831         and     a0, 1, a0               // Clean new FEN value to single bit
832         mtpr    a0, qemu_fen
833         stl_p   a0, PCB_Q_FEN(p0)       // Write new PCB<FEN>
834         hw_rei
835 ENDFN   CallPal_WrFen
836
837         ORG_CALL_PAL_PRIV(0x2C)
838 CallPal_OpcDec2C:
839         br      CallPal_OpcDec
840 ENDFN   CallPal_OpcDec2C
841
842 /*
843  * Write Virtual Page Table Pointer
844  *
845  * INPUT PARAMETERS:
846  *
847  *      r16 (a0) = New virtual page table pointer 
848  *
849  * SIDE EFFECTS:
850  *
851  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
852  */ 
853         ORG_CALL_PAL_PRIV(0x2D)
854 CallPal_WrVptPtr:
855         mtpr    a0, qemu_vptptr
856         hw_rei
857 ENDFN   CallPal_WrVptPtr
858
859         ORG_CALL_PAL_PRIV(0x2E)
860 CallPal_OpcDec2E:
861         br      CallPal_OpcDec
862 ENDFN   CallPal_OpcDec2E
863
864         ORG_CALL_PAL_PRIV(0x2F)
865 CallPal_OpcDec2F:
866         br      CallPal_OpcDec
867 ENDFN   CallPal_OpcDec2F
868
869 /*
870  * Swap Process Context
871  *
872  * FUNCTIONAL DESCRIPTION:
873  *
874  *      The swap process context (swpctx) function saves 
875  *      the current process data in the current PCB, then 
876  *      switches to the PCB passed in a0 and loads the
877  *      new process context.  The old PCB is returned in v0.    
878  * 
879  * INPUT PARAMETERS:
880  * 
881  *      r16 (a0) = New PCBB 
882  * 
883  * OUTPUT PARAMETERS:
884  *
885  *      r0  (v0) = Old PCBB
886  * 
887  * SIDE EFFECTS:
888  *
889  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
890  */ 
891         ORG_CALL_PAL_PRIV(0x30)
892 CallPal_SwpCtx:
893         rpcc    p5                      // Get cycle counter
894         mfpr    p6, qemu_exc_addr       // Save exc_addr for machine check
895
896         mfpr    v0, ptPcbb              // Get current PCBB
897         mtpr    a0, ptPcbb              // Save new PCBB
898         srl     p5, 32, p7              // Move CC<OFFSET> to low longword
899
900         addl    p5, p7, p7              // Accumulate time for old pcb
901         stl_p   p7, PCB_L_PCC(v0)
902
903         ldl_p   t9, PCB_L_PCC(a0)       // Get new PCC
904         subl    t9, p5, p5              // Generate and ...
905         mtpr    p5, qemu_pcc_ofs        // .. set new CC<OFFSET> bits
906
907         stq_p   $sp, PCB_Q_KSP(v0)      // Store old kernel stack pointer
908         mfpr    t10, qemu_usp           // Save old user stack pointer
909         stq_p   t10, PCB_Q_USP(v0)
910
911         br      CallPal_SwpCtx_Cont
912 ENDFN   CallPal_SwpCtx
913
914         .text   1
915 CallPal_SwpCtx_Cont:
916         ldq_p   $sp, PCB_Q_KSP(a0)      // Install new stack pointers
917         ldq_p   t10, PCB_Q_USP(a0)
918         mtpr    t10, qemu_usp
919
920         mfpr    t10, qemu_unique        // Save old unique value
921         stq_p   t10, PCB_Q_UNIQUE(v0)
922         ldq_p   t10, PCB_Q_UNIQUE(a0)   // Install new unique value
923         mtpr    t10, qemu_unique
924
925         ldq_p   t8, PCB_Q_FEN(a0)       // Install new FEN
926         and     t8, 1, t8
927         mtpr    t8, qemu_fen
928
929         // QEMU does not implement an ASN; skip that.
930
931         ldq_p   t10, PCB_Q_PTBR(a0)     // Install new page tables
932         sll     t10, VA_S_OFF, t10
933         mtpr    t10, qemu_ptbr
934         mtpr    $31, qemu_tbia          // Flush TLB, since we don't do ASNs
935
936         hw_rei
937 ENDFN   CallPal_SwpCtx_Cont
938         .previous
939
940 /*
941  * Write System Value
942  *
943  * INPUT PARAMETERS:
944  *
945  *      r16 (a0) = New system value 
946  * 
947  * SIDE EFFECTS:
948  *
949  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
950  */ 
951         ORG_CALL_PAL_PRIV(0x31)
952 CallPal_WrVal:
953         mtpr    a0, qemu_sysval
954         hw_rei
955 ENDFN   CallPal_WrVal
956
957 /*
958  * Read System Value
959  *
960  * OUTPUT PARAMETERS:
961  *
962  *      r0 (v0) = Returned system value
963  * 
964  * SIDE EFFECTS:
965  *
966  *      Registers t0 and t8..t11 are UNPREDICTABLE upon return.
967  */ 
968         ORG_CALL_PAL_PRIV(0x32)
969 CallPal_RdVal:
970         mfpr    v0, qemu_sysval
971         hw_rei
972 ENDFN   CallPal_RdVal
973
974 /*
975  * Translation Buffer Invalidate
976  * 
977  * INPUT PARAMETERS:
978  * 
979  *      r16 (a0) = tbi selector type:
980  *
981  *              -2 - Flush all TB entries (tbia)
982  *              -1 - Invalidate all TB entries with ASM=0 (tbiap)
983  *               1 - Invalidate ITB entry for va=a1 (tbisi)
984  *               2 - Invalidate DTB entry for va=a1 (tbisd)
985  *               3 - Invalidate both ITB and DTB entry for va=a1 (tbis)
986  *
987  *      r17 (a1) = VA for TBISx types
988  *
989  * Qemu does not implement ASNs or split I/D tlbs.  Therefore these
990  * collapse to tbia and tbis.
991  * 
992  * SIDE EFFECTS:
993  *
994  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
995  */ 
996         ORG_CALL_PAL_PRIV(0x33)
997 CallPal_Tbi:
998         bge     a0, 1f
999
1000         mtpr    $31, qemu_tbia
1001         hw_rei
1002
1003 1:      mtpr    a1, qemu_tbis
1004         hw_rei
1005 ENDFN   CallPal_Tbi
1006
1007 /*
1008  * Write System Entry Address
1009  *
1010  * INPUT PARAMETERS:
1011  *
1012  *      r16 (a0) = VA of system entry point
1013  *      r17 (a1) = System entry point selector 
1014  * 
1015  * SIDE EFFECTS:
1016  *
1017  *      Registers t0, t8..t11, and a0..a1 are UNPREDICTABLE
1018  *      upon return.
1019  */ 
1020         ORG_CALL_PAL_PRIV(0x34)
1021 CallPal_WrEnt:
1022         andnot  a0, 3, a0               // Clean PC<1:0>
1023
1024         cmpult  a1, 6, t8               // Bound the input
1025         cmoveq  t8, 6, a1
1026
1027         br      t0, 1f
1028 1:      lda     t0, WrEnt_Table-1b(t0)
1029         s8addq  a1, t0, t0
1030         jmp     $31, (t0), 0
1031 ENDFN   CallPal_WrEnt
1032
1033         .text   1
1034 WrEnt_Table:
1035 0:      mtpr    a0, ptEntInt
1036         hw_rei
1037 1:      mtpr    a0, ptEntArith
1038         hw_rei
1039 2:      mtpr    a0, ptEntMM
1040         hw_rei
1041 3:      mtpr    a0, ptEntIF
1042         hw_rei
1043 4:      mtpr    a0, ptEntUna
1044         hw_rei
1045 5:      mtpr    a0, ptEntSys
1046         hw_rei
1047 6:      nop
1048         hw_rei
1049 ENDFN   WrEnt_Table
1050         .previous
1051
1052 /*
1053  * Swap Interrupt Priority Level
1054  * 
1055  * INPUT PARAMETERS:
1056  * 
1057  *      r16 (a0) = New IPL
1058  * 
1059  * OUTPUT PARAMETERS:
1060  *
1061  *      r0  (v0) = Old IPL
1062  * 
1063  * SIDE EFFECTS:
1064  *
1065  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1066  */ 
1067         ORG_CALL_PAL_PRIV(0x35)
1068 CallPal_SwpIpl:
1069         mfpr    v0, qemu_ps
1070         and     a0, PS_M_IPL, a0
1071         and     v0, PS_M_IPL, v0
1072         mtpr    a0, qemu_ps
1073         hw_rei
1074 ENDFN   CallPal_SwpIpl
1075
1076 /*
1077  * Read Processor Status
1078  *
1079  * OUTPUT PARAMETERS:
1080  *
1081  *      r0 (v0) = Current PS
1082  * 
1083  * SIDE EFFECTS:
1084  *
1085  *      Registers t0, t8..t11 are UNPREDICTABLE upon return.
1086  */ 
1087         ORG_CALL_PAL_PRIV(0x36)
1088 CallPal_RdPs:
1089         mfpr    v0, qemu_ps
1090         hw_rei
1091 ENDFN   CallPal_RdPs
1092
1093 /*
1094  * Write Kernel Global Pointer
1095  *
1096  * INPUT PARAMETERS:
1097  * 
1098  *      r16 (a0) = New KGP value
1099  *
1100  * SIDE EFFECTS:
1101  *
1102  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1103  */ 
1104         ORG_CALL_PAL_PRIV(0x37)
1105 CallPal_WrKgp:
1106         mtpr    a0, ptKgp
1107         hw_rei
1108 ENDFN   CallPal_WrKgp
1109
1110 /*
1111  * Write User Stack Pointer
1112  * 
1113  * INPUT PARAMETERS:
1114  * 
1115  *      r16 (a0) = New user stack pointer value
1116  * 
1117  * SIDE EFFECTS:
1118  *
1119  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1120  */ 
1121         ORG_CALL_PAL_PRIV(0x38)
1122 CallPal_WrUsp:
1123         mtpr    a0, qemu_usp
1124         hw_rei
1125 ENDFN   CallPal_WrUsp
1126
1127 /*
1128  * Write Performance Monitor
1129  *
1130  * INPUT PARAMETERS:
1131  * 
1132  *      r16 (a0) = New user stack pointer value
1133  * 
1134  * SIDE EFFECTS:
1135  *
1136  *      Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1137  */
1138         ORG_CALL_PAL_PRIV(0x39)
1139 CallPal_WrPerfMon:
1140         // Not implemented
1141         hw_rei
1142 ENDFN   CallPal_WrPerfMon
1143
1144 /*
1145  * Read User Stack Pointer
1146  * 
1147  * OUTPUT PARAMETERS:
1148  *
1149  *      r0 (v0) = User stack pointer value
1150  * 
1151  * SIDE EFFECTS:
1152  *
1153  *      Registers t0, and t8..t11 are UNPREDICTABLE upon return.
1154  */ 
1155         ORG_CALL_PAL_PRIV(0x3A)
1156 CallPal_RdUsp:
1157         mfpr    v0, qemu_usp
1158         hw_rei
1159 ENDFN   CallPal_RdUsp
1160
1161         ORG_CALL_PAL_PRIV(0x3B)
1162 CallPal_OpcDec3B:
1163         br      CallPal_OpcDec
1164 ENDFN   CallPal_OpcDec3B
1165
1166 /*
1167  * Who Am I
1168  * 
1169  * OUTPUT PARAMETERS:
1170  *
1171  *      r0 (v0) = Current processor number
1172  * 
1173  * SIDE EFFECTS:
1174  *
1175  *      Registers t0 and t8..t11 are UNPREDICTABLE upon return.
1176  */ 
1177         ORG_CALL_PAL_PRIV(0x3C)
1178 CallPal_Whami:
1179         SYS_WHAMI v0
1180         hw_rei
1181 ENDFN   CallPal_Whami
1182
1183 /*
1184  * Return From System Call
1185  *
1186  * INPUT PARAMETERS:
1187  * 
1188  *      r30 (sp) = Pointer to the top of the kernel stack
1189  * 
1190  * OUTPUT PARAMETERS:
1191  *
1192  *      r29 (gp) = Restored user mode global pointer
1193  *      r30 (sp) = User stack pointer
1194  * 
1195  * SIDE EFFECTS:
1196  *
1197  *      Registers t0 and t8..t11 are UNPREDICTABLE upon return.
1198  */ 
1199         ORG_CALL_PAL_PRIV(0x3D)
1200 CallPal_RetSys:
1201         ldq     t9, FRM_Q_PC($sp)       // Pop the return address
1202         ldq     $gp, FRM_Q_GP($sp)      // Get the user mode global pointer
1203         lda     t8, FRM_K_SIZE($sp)
1204         mtpr    t8, ptKsp
1205
1206         mov     PS_K_USER, t8           // Set new mode to user
1207         mtpr    t8, qemu_ps
1208
1209         mfpr    $sp, qemu_usp           // Get the user stack pointer
1210
1211         andnot  t9, 3, t9               // Clean return PC<1:0>
1212         hw_ret  (t9)
1213 ENDFN   CallPal_RetSys
1214
1215 /*
1216  * Wait For Interrupt
1217  *
1218  * FUNCTIONAL DESCRIPTION:
1219  *
1220  *      If possible, wait for the first of either of the following
1221  *      conditions before returning: any interrupt other than a clock
1222  *      tick; or the first clock tick after a specified number of clock
1223  *      ticks have bbeen skipped.
1224  *
1225  * INPUT PARAMETERS:
1226  * 
1227  *      r16 (a0) = Maximum number of clock ticks to skip
1228  * 
1229  * OUTPUT PARAMETERS:
1230  *
1231  *      r0 (v0) = Number of clock ticks actually skipped.
1232  */
1233         ORG_CALL_PAL_PRIV(0x3E)
1234 CallPal_WtInt:
1235         mtpr    $31, qemu_wait
1236         mov     0, v0
1237         hw_rei
1238 ENDFN   CallPal_WtInt
1239
1240 /*
1241  * Return From Trap, Fault, or Interrupt
1242  *
1243  * INPUT PARAMETERS:
1244  * 
1245  *      r30 (sp) = Pointer to the top of the kernel stack
1246  * 
1247  * OUTPUT PARAMETERS:
1248  *
1249  *      ps       <- (sp+00)
1250  *      pc       <- (sp+08)
1251  *      r29 (gp) <- (sp+16)
1252  *      r16 (a0) <- (sp+24)
1253  *      r17 (a1) <- (sp+32)
1254  *      r18 (a2) <- (sp+40)
1255  */ 
1256         ORG_CALL_PAL_PRIV(0x3F)
1257         .globl  CallPal_Rti
1258 CallPal_Rti:
1259         mfpr    p6, qemu_exc_addr       // Save exc_addr for machine check
1260
1261         ldq     p4, FRM_Q_PS($sp)       // Get the PS
1262         ldq     p5, FRM_Q_PC($sp)       // Get the return PC
1263         ldq     $gp, FRM_Q_GP($sp)      // Get gp
1264         ldq     a0, FRM_Q_A0($sp)       // Get a0
1265         ldq     a1, FRM_Q_A1($sp)       // Get a1
1266         ldq     a2, FRM_Q_A2($sp)       // Get a2
1267         lda     $sp, FRM_K_SIZE($sp)    // Pop the stack
1268
1269         andnot  p5, 3, p5               // Clean return PC<1:0>
1270
1271         and     p4, PS_M_CM, p3
1272         bne     p3, CallPal_Rti_ToUser
1273
1274         and     p4, PS_M_IPL, p4
1275         mtpr    p4, qemu_ps
1276         hw_ret  (p5)
1277 ENDFN   CallPal_Rti
1278
1279         .text   1
1280 CallPal_Rti_ToUser:
1281         mtpr    p3, qemu_ps
1282         mtpr    $sp, ptKsp
1283         mfpr    $sp, qemu_usp
1284         hw_ret  (p5)
1285 ENDFN   CallPal_Rti_ToUser
1286         .previous
1287 \f
1288 /*
1289  * OSF/1 Unprivileged CALL_PAL Entry Points
1290  */
1291
1292 #define ORG_CALL_PAL_UNPRIV(X)  .org    0x2000+64*(X-0x80)
1293
1294 /*
1295  * A helper routine for the unprivaledged kernel entry points, since the
1296  * actual stack frame setup code is just a tad too large to fit inline.
1297  *
1298  * INPUT PARAMETERS:
1299  *
1300  *      p5 = ps
1301  *      p6 = exc_addr
1302  *      p7 = return address
1303  *
1304  * SIDE EFFECTS:
1305  *
1306  *      p0 is clobbered
1307  *
1308  */
1309         .text   1
1310 CallPal_Stack_Frame:
1311         // Test if we're currently in user mode
1312         and     p5, PS_M_CM, p0
1313         beq     p0, 0f
1314 CallPal_Stack_Frame_FromUser:
1315         // Switch to kernel mode
1316         mtpr    $31, qemu_ps
1317         mtpr    $sp, qemu_usp
1318         mfpr    $sp, ptKsp
1319 0:
1320         // Allocate the stack frame
1321         lda     $sp, -FRM_K_SIZE($sp)
1322         stq     p5, FRM_Q_PS($sp)
1323         stq     p6, FRM_Q_PC($sp)
1324         stq     $gp, FRM_Q_GP($sp)
1325         stq     a0, FRM_Q_A0($sp)
1326         stq     a1, FRM_Q_A1($sp)
1327         stq     a2, FRM_Q_A2($sp)
1328         ret     $31, (p7), 0
1329 ENDFN   CallPal_Stack_Frame
1330         .previous
1331
1332 /*
1333  * Breakpoint Trap
1334  *
1335  * OUTPUT PARAMETERS:
1336  *
1337  *      r16 (a0) = Code for bpt (0)
1338  *      r17 (a1) = UNPREDICTABLE
1339  *      r18 (a2) = UNPREDICTABLE
1340  */ 
1341         ORG_CALL_PAL_UNPRIV(0x80)
1342 CallPal_Bpt:
1343         mfpr    p5, qemu_ps
1344         mfpr    p6, qemu_exc_addr
1345         bsr     p7, CallPal_Stack_Frame
1346
1347         mfpr    p0, ptEntIF
1348         mfpr    $gp, ptKgp
1349         mov     IF_K_BPT, a0
1350         hw_ret  (p0)
1351 ENDFN   CallPal_Bpt
1352
1353 /*
1354  * Bugcheck Trap
1355  * 
1356  * OUTPUT PARAMETERS:
1357  *
1358  *      r16 (a0) = Code for bugchk (1)
1359  *      r17 (a1) = UNPREDICTABLE
1360  *      r18 (a2) = UNPREDICTABLE
1361  */ 
1362         ORG_CALL_PAL_UNPRIV(0x81)
1363 CallPal_BugChk:
1364         mfpr    p5, qemu_ps
1365         mfpr    p6, qemu_exc_addr
1366         bsr     p7, CallPal_Stack_Frame
1367
1368         mfpr    p0, ptEntIF
1369         mfpr    $gp, ptKgp
1370         mov     IF_K_BUGCHK, a0
1371         hw_ret  (p0)
1372 ENDFN   CallPal_BugChk
1373
1374
1375         ORG_CALL_PAL_UNPRIV(0x82)
1376 CallPal_OpcDec82:
1377         br      CallPal_OpcDec
1378 ENDFN   CallPal_OpcDec82
1379
1380 /*
1381  * System Call
1382  */ 
1383         ORG_CALL_PAL_UNPRIV(0x83)
1384 CallPal_CallSys:
1385         mfpr    p5, qemu_ps
1386         mfpr    p6, qemu_exc_addr
1387
1388         and     p5, PS_M_CM, p0
1389         beq     p0, 0f
1390
1391         bsr     p7, CallPal_Stack_Frame_FromUser
1392
1393         mfpr    p0, ptEntSys
1394         mfpr    $gp, ptKgp
1395         hw_ret  (p0)
1396
1397 0:      subq    p6, 4, p6               // Get PC of CALL_PAL insn
1398         br      MchkOSBugCheck
1399 ENDFN   CallPal_CallSys
1400
1401         ORG_CALL_PAL_UNPRIV(0x84)
1402 CallPal_OpcDec84:
1403         br      CallPal_OpcDec
1404 ENDFN   CallPal_OpcDec84
1405
1406         ORG_CALL_PAL_UNPRIV(0x85)
1407 CallPal_OpcDec85:
1408         br      CallPal_OpcDec
1409 ENDFN   CallPal_OpcDec85
1410
1411 \f
1412 /*
1413  * I-Stream Memory Barrier
1414  *
1415  * For QEMU, this is of course a no-op.
1416  */ 
1417         ORG_CALL_PAL_UNPRIV(0x86)
1418 CallPal_Imb:
1419         hw_rei
1420 ENDFN   CallPal_Imb
1421
1422
1423         ORG_CALL_PAL_UNPRIV(0x87)
1424 CallPal_OpcDec87:
1425         br      CallPal_OpcDec
1426 ENDFN   CallPal_OpcDec87
1427
1428         ORG_CALL_PAL_UNPRIV(0x88)
1429 CallPal_OpcDec88:
1430         br      CallPal_OpcDec
1431 ENDFN   CallPal_OpcDec88
1432
1433         ORG_CALL_PAL_UNPRIV(0x89)
1434 CallPal_OpcDec89:
1435         br      CallPal_OpcDec
1436 ENDFN   CallPal_OpcDec89
1437
1438         ORG_CALL_PAL_UNPRIV(0x8A)
1439 CallPal_OpcDec8A:
1440         br      CallPal_OpcDec
1441 ENDFN   CallPal_OpcDec8A
1442
1443         ORG_CALL_PAL_UNPRIV(0x8B)
1444 CallPal_OpcDec8B:
1445         br      CallPal_OpcDec
1446 ENDFN   CallPal_OpcDec8B
1447
1448         ORG_CALL_PAL_UNPRIV(0x8C)
1449 CallPal_OpcDec8C:
1450         br      CallPal_OpcDec
1451 ENDFN   CallPal_OpcDec8C
1452
1453         ORG_CALL_PAL_UNPRIV(0x8D)
1454 CallPal_OpcDec8D:
1455         br      CallPal_OpcDec
1456 ENDFN   CallPal_OpcDec8D
1457
1458         ORG_CALL_PAL_UNPRIV(0x8E)
1459 CallPal_OpcDec8E:
1460         br      CallPal_OpcDec
1461 ENDFN   CallPal_OpcDec8E
1462
1463         ORG_CALL_PAL_UNPRIV(0x8F)
1464 CallPal_OpcDec8F:
1465         br      CallPal_OpcDec
1466 ENDFN   CallPal_OpcDec8F
1467
1468         ORG_CALL_PAL_UNPRIV(0x90)
1469 CallPal_OpcDec90:
1470         br      CallPal_OpcDec
1471 ENDFN   CallPal_OpcDec90
1472
1473         ORG_CALL_PAL_UNPRIV(0x91)
1474 CallPal_OpcDec91:
1475         br      CallPal_OpcDec
1476 ENDFN   CallPal_OpcDec91
1477
1478         ORG_CALL_PAL_UNPRIV(0x92)
1479 CallPal_OpcDec92:
1480         br      CallPal_OpcDec
1481 ENDFN   CallPal_OpcDec92
1482
1483         ORG_CALL_PAL_UNPRIV(0x93)
1484 CallPal_OpcDec93:
1485         br      CallPal_OpcDec
1486 ENDFN   CallPal_OpcDec93
1487
1488         ORG_CALL_PAL_UNPRIV(0x94)
1489 CallPal_OpcDec94:
1490         br      CallPal_OpcDec
1491 ENDFN   CallPal_OpcDec94
1492
1493         ORG_CALL_PAL_UNPRIV(0x95)
1494 CallPal_OpcDec95:
1495         br      CallPal_OpcDec
1496 ENDFN   CallPal_OpcDec95
1497
1498         ORG_CALL_PAL_UNPRIV(0x96)
1499 CallPal_OpcDec96:
1500         br      CallPal_OpcDec
1501 ENDFN   CallPal_OpcDec96
1502
1503         ORG_CALL_PAL_UNPRIV(0x97)
1504 CallPal_OpcDec97:
1505         br      CallPal_OpcDec
1506 ENDFN   CallPal_OpcDec97
1507
1508         ORG_CALL_PAL_UNPRIV(0x98)
1509 CallPal_OpcDec98:
1510         br      CallPal_OpcDec
1511 ENDFN   CallPal_OpcDec98
1512
1513         ORG_CALL_PAL_UNPRIV(0x99)
1514 CallPal_OpcDec99:
1515         br      CallPal_OpcDec
1516 ENDFN   CallPal_OpcDec99
1517
1518         ORG_CALL_PAL_UNPRIV(0x9A)
1519 CallPal_OpcDec9A:
1520         br      CallPal_OpcDec
1521 ENDFN   CallPal_OpcDec9A
1522
1523         ORG_CALL_PAL_UNPRIV(0x9B)
1524 CallPal_OpcDec9B:
1525         br      CallPal_OpcDec
1526 ENDFN   CallPal_OpcDec9B
1527
1528         ORG_CALL_PAL_UNPRIV(0x9C)
1529 CallPal_OpcDec9C:
1530         br      CallPal_OpcDec
1531 ENDFN   CallPal_OpcDec9C
1532
1533         ORG_CALL_PAL_UNPRIV(0x9D)
1534 CallPal_OpcDec9D:
1535         br      CallPal_OpcDec
1536 ENDFN   CallPal_OpcDec9D
1537
1538 /*
1539  * Read Unique Value
1540  * 
1541  * OUTPUT PARAMETERS:
1542  *
1543  *      r0 (v0) = Returned process unique value
1544 */ 
1545         ORG_CALL_PAL_UNPRIV(0x9E)
1546 CallPal_RdUnique:
1547         mfpr    v0, qemu_unique
1548         hw_rei
1549 ENDFN   CallPal_RdUnique
1550
1551 /*
1552  * Write Unique Value
1553  * 
1554  * INPUT PARAMETERS:
1555  * 
1556  *      r16 (a0) = New process unique value
1557  */ 
1558         ORG_CALL_PAL_UNPRIV(0x9F)
1559 CallPal_WrUnique:
1560         mtpr    a0, qemu_unique
1561         hw_rei
1562 ENDFN   CallPal_WrUnique
1563
1564         ORG_CALL_PAL_UNPRIV(0xA0)
1565 CallPal_OpcDecA0:
1566         br      CallPal_OpcDec
1567 ENDFN   CallPal_OpcDecA0
1568
1569         ORG_CALL_PAL_UNPRIV(0xA1)
1570 CallPal_OpcDecA1:
1571         br      CallPal_OpcDec
1572 ENDFN   CallPal_OpcDecA1
1573
1574         ORG_CALL_PAL_UNPRIV(0xA2)
1575 CallPal_OpcDecA2:
1576         br      CallPal_OpcDec
1577 ENDFN   CallPal_OpcDecA2
1578
1579         ORG_CALL_PAL_UNPRIV(0xA3)
1580 CallPal_OpcDecA3:
1581         br      CallPal_OpcDec
1582 ENDFN   CallPal_OpcDecA3
1583
1584         ORG_CALL_PAL_UNPRIV(0xA4)
1585 CallPal_OpcDecA4:
1586         br      CallPal_OpcDec
1587 ENDFN   CallPal_OpcDecA4
1588
1589         ORG_CALL_PAL_UNPRIV(0xA5)
1590 CallPal_OpcDecA5:
1591         br      CallPal_OpcDec
1592 ENDFN   CallPal_OpcDecA5
1593
1594         ORG_CALL_PAL_UNPRIV(0xA6)
1595 CallPal_OpcDecA6:
1596         br      CallPal_OpcDec
1597 ENDFN   CallPal_OpcDecA6
1598
1599         ORG_CALL_PAL_UNPRIV(0xA7)
1600 CallPal_OpcDecA7:
1601         br      CallPal_OpcDec
1602 ENDFN   CallPal_OpcDecA7
1603
1604         ORG_CALL_PAL_UNPRIV(0xA8)
1605 CallPal_OpcDecA8:
1606         br      CallPal_OpcDec
1607 ENDFN   CallPal_OpcDecA8
1608
1609         ORG_CALL_PAL_UNPRIV(0xA9)
1610 CallPal_OpcDecA9:
1611         br      CallPal_OpcDec
1612 ENDFN   CallPal_OpcDecA9
1613
1614 /*
1615  * Generate Trap
1616  *
1617  * OUTPUT PARAMETERS:
1618  *
1619  *      r16 (a0) = Code for gentrap (2)
1620  *      r17 (a1) = UNPREDICTABLE
1621  *      r18 (a2) = UNPREDICTABLE
1622  */ 
1623         ORG_CALL_PAL_UNPRIV(0xAA)
1624 CallPal_GenTrap:
1625         mfpr    p5, qemu_ps
1626         mfpr    p6, qemu_exc_addr
1627         bsr     p7, CallPal_Stack_Frame
1628
1629         mfpr    p0, ptEntIF
1630         mfpr    $gp, ptKgp
1631         mov     IF_K_GENTRAP, a0
1632         hw_ret  (p0)
1633 ENDFN   CallPal_GenTrap
1634
1635         ORG_CALL_PAL_UNPRIV(0xAB)
1636 CallPal_OpcDecAB:
1637         br      CallPal_OpcDec
1638 ENDFN   CallPal_OpcDecAB
1639
1640         ORG_CALL_PAL_UNPRIV(0xAC)
1641 CallPal_OpcDecAC:
1642         br      CallPal_OpcDec
1643 ENDFN   CallPal_OpcDecAC
1644
1645         ORG_CALL_PAL_UNPRIV(0xAD)
1646 CallPal_OpcDecAD:
1647         br      CallPal_OpcDec
1648 ENDFN   CallPal_OpcDecAD
1649
1650         ORG_CALL_PAL_UNPRIV(0xAE)
1651 CallPal_OpcDecAE:
1652         br      CallPal_OpcDec
1653 ENDFN   CallPal_OpcDecAE
1654
1655         ORG_CALL_PAL_UNPRIV(0xAF)
1656 CallPal_OpcDecAF:
1657         br      CallPal_OpcDec
1658 ENDFN   CallPal_OpcDecAF
1659
1660         ORG_CALL_PAL_UNPRIV(0xB0)
1661 CallPal_OpcDecB0:
1662         br      CallPal_OpcDec
1663 ENDFN   CallPal_OpcDecB0
1664
1665         ORG_CALL_PAL_UNPRIV(0xB1)
1666 CallPal_OpcDecB1:
1667         br      CallPal_OpcDec
1668 ENDFN   CallPal_OpcDecB1
1669
1670         ORG_CALL_PAL_UNPRIV(0xB2)
1671 CallPal_OpcDecB2:
1672         br      CallPal_OpcDec
1673 ENDFN   CallPal_OpcDecB2
1674
1675         ORG_CALL_PAL_UNPRIV(0xB3)
1676 CallPal_OpcDecB3:
1677         br      CallPal_OpcDec
1678 ENDFN   CallPal_OpcDecB3
1679
1680         ORG_CALL_PAL_UNPRIV(0xB4)
1681 CallPal_OpcDecB4:
1682         br      CallPal_OpcDec
1683 ENDFN   CallPal_OpcDecB4
1684
1685         ORG_CALL_PAL_UNPRIV(0xB5)
1686 CallPal_OpcDecB5:
1687         br      CallPal_OpcDec
1688 ENDFN   CallPal_OpcDecB5
1689
1690         ORG_CALL_PAL_UNPRIV(0xB6)
1691 CallPal_OpcDecB6:
1692         br      CallPal_OpcDec
1693 ENDFN   CallPal_OpcDecB6
1694
1695         ORG_CALL_PAL_UNPRIV(0xB7)
1696 CallPal_OpcDecB7:
1697         br      CallPal_OpcDec
1698 ENDFN   CallPal_OpcDecB7
1699
1700         ORG_CALL_PAL_UNPRIV(0xB8)
1701 CallPal_OpcDecB8:
1702         br      CallPal_OpcDec
1703 ENDFN   CallPal_OpcDecB8
1704
1705         ORG_CALL_PAL_UNPRIV(0xB9)
1706 CallPal_OpcDecB9:
1707         br      CallPal_OpcDec
1708 ENDFN   CallPal_OpcDecB9
1709
1710         ORG_CALL_PAL_UNPRIV(0xBA)
1711 CallPal_OpcDecBA:
1712         br      CallPal_OpcDec
1713 ENDFN   CallPal_OpcDecBA
1714
1715         ORG_CALL_PAL_UNPRIV(0xBB)
1716 CallPal_OpcDecBB:
1717         br      CallPal_OpcDec
1718 ENDFN   CallPal_OpcDecBB
1719
1720         ORG_CALL_PAL_UNPRIV(0xBC)
1721 CallPal_OpcDecBC:
1722         br      CallPal_OpcDec
1723 ENDFN   CallPal_OpcDecBC
1724
1725         ORG_CALL_PAL_UNPRIV(0xBD)
1726 CallPal_OpcDecBD:
1727         br      CallPal_OpcDec
1728 ENDFN   CallPal_OpcDecBD
1729
1730         ORG_CALL_PAL_UNPRIV(0xBE)
1731 CallPal_OpcDecBE:
1732         br      CallPal_OpcDec
1733 ENDFN   CallPal_OpcDecBE
1734
1735         ORG_CALL_PAL_UNPRIV(0xBF)
1736 CallPal_OpcDec:
1737         mfpr    p5, qemu_ps
1738         mfpr    p6, qemu_exc_addr
1739         bsr     p7, CallPal_Stack_Frame
1740
1741         mfpr    p0, ptEntIF
1742         mfpr    $gp, ptKgp
1743         mov     IF_K_OPCDEC, a0
1744         hw_ret  (p0)
1745 ENDFN   CallPal_OpcDec
1746
1747         .org    0x3000
1748         .text   1
1749 /*
1750  * PALcode detected processor machine check handler.
1751  *
1752  *      The PALcode-detected machine check handler loads a code
1753  *      indicating the type of machine check error, loads 
1754  *      the System Control Block (SCB) vector for the 
1755  *      processor machine check service routine, sets the 
1756  *      Machine-Check-In-Progress (MIP) flag in the Machine
1757  *      Check Error Summary register (MCES), and merges
1758  *      with the common machine check flow.
1759  *
1760  *      If a second processor machine check error condition 
1761  *      is detected while the MIP flag is set, the processor 
1762  *      is forced into console I/O mode indicating "double 
1763  *      error abort encountered" as the reason for the halt. 
1764  * 
1765  * CALLING SEQUENCE:
1766  * 
1767  *      Called when an internal processor error is detected
1768  *      that cannot be successfully corrected by hardware or
1769  *      PALcode.
1770  * 
1771  * INPUT PARAMETERS:
1772  *
1773  *      r14 (p6) = Exception address 
1774  * 
1775  * OUTPUT PARAMETERS:
1776  *
1777  *      ptMchk0         = saved v0
1778  *      ptMchk1         = saved t0
1779  *      ptMchk2         = saved t3
1780  *      ptMchk3         = saved t4
1781  *      ptMchk4         = saved t5
1782  *      ptMchk5         = saved exc_addr
1783  *      ptMisc<47:32>   = MCHK code
1784  *      ptMisc<31:16>   = SCB vector
1785  *      ptMces<MIP>     = Set
1786  * 
1787  * SIDE EFFECTS:
1788  *
1789  *      r0 (v0), r1 (t0), and r4..r6 (t3..t5) are saved in
1790  *      PAL temporaries and are available for use as scratch
1791  *      registers by the system specific machine check 
1792  *      handler.
1793  */
1794
1795 MchkBugCheck:
1796 MchkOSBugCheck:
1797         halt
1798 ENDFN   MchkBugCheck
1799
1800 /*
1801  * Common Machine Check Handler
1802  *
1803  * INPUT STATE:
1804  *
1805  *      ptMchk0         Saved v0
1806  *      ptMchk1         Saved t0
1807  *      ptMchk2         Saved t3
1808  *      ptMchk3         Saved t4
1809  *      ptMchk4         Saved t5
1810  *      ptMchk5         Saved exc_addr
1811  *      ptMisc<47:32>   MCHK code
1812  *      ptMisc<31:16>   SCB vector
1813  *      ptMces<MIP>     Set
1814  *
1815  * Registers v0, t0, and t3 .. t5 are available for use, in
1816  * addition to the shadow registers.
1817  */
1818
1819 MchkCommon:
1820         halt
1821 ENDFN   MchkCommon
1822
1823 /*
1824  * Build Machine Check Logout Frame
1825  *
1826  *      This portion of the  machine check handler builds a logout frame
1827  *      in the PAL impure scratch area, builds a stack frame on the kernel
1828  *      stack (already built if there was an interrupt machine check),
1829  *      loads the GP with the KGP, loads the machine check entry 
1830  *      code in a0, loads a platform-specific interrupt vector 
1831  *      (typically the same value as the SCB offset) in a1, loads 
1832  *      the kseg address of the logout area in a2, and dispatches 
1833  *      to the kernel interrupt handler pointed to by the entInt 
1834  *      operating system entry point.
1835  *
1836  * OUTPUT PARAMETERS:
1837  * 
1838  *      a0 (r16) = Machine check entry type
1839  *      a1 (r17) = Platform-specific interrupt vector
1840  *      a2 (r18) = Pointer to logout area
1841  */
1842
1843 .macro  STORE_IPR       which, offset, base
1844         mfpr    v0, \which
1845         stq_p   v0, \offset(\base)
1846 .endm
1847
1848 MchkLogOut:
1849         halt
1850 ENDFN   MchkLogOut
1851
1852 MchkDouble:
1853         bsr     p7, UpdatePCB
1854         lda     v0, HLT_K_DBL_MCHK
1855         br      Sys_EnterConsole
1856 ENDFN   MchkDouble
1857
1858 MchkFromPal:
1859         bsr     p7, UpdatePCB
1860         lda     v0, HLT_K_MCHK_FROM_PAL
1861         br      Sys_EnterConsole
1862 ENDFN   MchkFromPal
1863
1864 MchkKspInvalid:
1865         bsr     p7, UpdatePCB
1866         lda     v0, HLT_K_KSP_INVAL
1867         br      Sys_EnterConsole
1868 ENDFN   MchkKspInvalid
1869
1870 /*
1871  * Update the current PCB with new SP and CC info.
1872  *
1873  * INPUT PARAMETERS:
1874  *
1875  *      p7      = return linkage
1876  */
1877
1878 UpdatePCB:
1879         rpcc    p5
1880         mfpr    p4, ptPcbb
1881
1882         mfpr    p3, qemu_ps             // Check current mode
1883         and     p3, PS_M_CM, p3
1884         beq     p3, 1f
1885
1886         mtpr    $sp, qemu_usp           // Save user stack pointer
1887         stq_p   $sp, PCB_Q_USP(p4)
1888         br      2f
1889
1890 1:      mtpr    $sp, ptKsp              // Save kernel stack pointer
1891         stq_p   $sp, PCB_Q_KSP(p4)
1892
1893 2:      srl     p5, 32, p3              // Merge for new time
1894         addl    p5, p3, p3
1895         stl_p   p3, PCB_L_PCC(p4)       // Store new time
1896
1897         mfpr    p5, qemu_unique         // Save unique
1898         stq_p   p5, PCB_Q_UNIQUE(p4)
1899
1900         ret     $31, (p7), 0
1901 ENDFN   UpdatePCB
1902
1903 /*
1904  * FIXME
1905  */
1906 Sys_EnterConsole:
1907         halt
1908
1909 /*
1910  * Allocate the initial bootup stack.
1911  */
1912
1913         .section .bss.stack
1914         .align 3
1915         .globl  stack
1916         .type   stack,@object
1917         .size   stack,STACK_SIZE
1918 stack:  .skip   STACK_SIZE