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