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, p1, 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 *
570 * OUTPUT PARAMETERS:
571 *
572 *	r0 (v0) = Returned status indicating:
573 *			0 - Success (PALcode was switched)
574 *			1 - Unknown PALcode variant
575 *			2 - Known PALcode variant, but PALcode not loaded
576 *
577 *	r26 (ra) = r27 (pv) = New PC
578 *		Note that this is non-architected, but is relied on by
579 *		the usage of SwpPal within our own console code in order
580 *		to simplify its use within C code.
581 *
582 */
583	ORG_CALL_PAL_PRIV(0x0A)
584CallPal_SwpPal:
585	// Save a copy of the return address in case of machine check.
586	mfpr	p6, qemu_exc_addr
587
588	// Accept swapping to OSF PALcode.  The side effect here is to
589	// load the other parameters for the kernel.
590	cmpeq	a0, 2, v0
591	bne	v0, CallPal_SwpPal_Cont
592
593	// Return as an unknown PALcode variant
594	mov	1, v0
595	hw_rei
596ENDFN	CallPal_SwpPal
597
598	.text	1
599CallPal_SwpPal_Cont:
600	rpcc	p0
601	mtpr	a2, ptPcbb
602	mtpr	a3, qemu_vptptr
603
604	ldq_p	$sp, PCB_Q_KSP(a2)
605	ldq_p	t0, PCB_Q_USP(a2)
606	ldq_p	t1, PCB_Q_PTBR(a2)
607	ldl_p	t2, PCB_L_PCC(a2)
608	ldq_p	t3, PCB_Q_UNIQUE(a2)
609	ldq_p	t4, PCB_Q_FEN(a2)
610
611	mtpr	t0, qemu_usp
612
613	sll	t1, VA_S_OFF, t1
614	mtpr	t1, qemu_ptbr
615
616	subl	t2, p0, t2
617	mtpr	t2, qemu_pcc_ofs
618
619	mtpr	t3, qemu_unique
620
621	and	t4, 1, t4
622	mtpr	t4, qemu_fen
623
624	mtpr	$31, qemu_tbia		// Flush TLB for new PTBR
625
626	mov	a1, $26
627	mov	a1, $27
628	hw_ret	(a1)
629ENDFN	CallPal_SwpPal_Cont
630	.previous
631
632	ORG_CALL_PAL_PRIV(0x0B)
633CallPal_OpcDec0B:
634	br	CallPal_OpcDec
635ENDFN	CallPal_OpcDec0B
636
637	ORG_CALL_PAL_PRIV(0x0C)
638CallPal_OpcDec0C:
639	br	CallPal_OpcDec
640ENDFN	CallPal_OpcDec0C
641
642/*
643 * Write Interprocessor Interrupt Request
644 *
645 * INPUT PARAMETERS:
646 *
647 *	r16 (a0) = target processor number
648 *
649 * OUTPUT PARAMETERS:
650 *
651 * SIDE EFFECTS:
652 *
653 */
654        ORG_CALL_PAL_PRIV(0x0D)
655CallPal_WrIpir:
656	// Save a copy of the return address in case of machine check.
657	mfpr	p6, qemu_exc_addr
658
659	SYS_WRIPIR	a0, p0, p1, p2
660
661	hw_rei
662ENDFN	CallPal_WrIpir
663
664	ORG_CALL_PAL_PRIV(0x0E)
665CallPal_OpcDec0E:
666	br	CallPal_OpcDec
667ENDFN	CallPal_OpcDec0E
668
669	ORG_CALL_PAL_PRIV(0x0F)
670CallPal_OpcDec0F:
671	br	CallPal_OpcDec
672ENDFN	CallPal_OpcDec0F
673
674/*
675 * Read Machine Check Error Summary
676 *
677 * INPUT PARAMETERS:
678 *
679 * OUTPUT PARAMETERS:
680 *
681 *	r0 (v0) = returned MCES value
682 *
683 * SIDE EFFECTS:
684 *
685 */
686        ORG_CALL_PAL_PRIV(0x10)
687CallPal_RdMces:
688	mfpr	v0, ptMces		// Get current MCES value
689	and	v0, MCES_M_ALL, v0	// Clear all other bits
690	hw_rei
691ENDFN	CallPal_RdMces
692
693/*
694 * Write Machine Check Error Summary
695 *
696 * INPUT PARAMETERS:
697 *
698 *	r16 (a0) = MCES<DPC> <- a0<3>,  MCES<DSC> <- a0<4>
699 *
700 * OUTPUT PARAMETERS:
701 *
702 * SIDE EFFECTS:
703 *
704 *	Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
705 */
706        ORG_CALL_PAL_PRIV(0x11)
707CallPal_WrMces:
708	// Clear MIP, SCE, PCE
709	and	a0, (MCES_M_MIP | MCES_M_SCE | MCES_M_PCE), p0
710	mfpr	p1, ptMces
711	bic	p1, p0, p1
712
713	// Copy DPC and DSC
714	and	a0, (MCES_M_DPC | MCES_M_DSC), p0
715	bic	p1, (MCES_M_DPC | MCES_M_DSC), p1
716	or	p1, p0, p1
717
718	mtpr	p1, ptMces
719	hw_rei
720ENDFN	CallPal_WrMces
721
722	ORG_CALL_PAL_PRIV(0x12)
723CallPal_OpcDec12:
724	br	CallPal_OpcDec
725ENDFN	CallPal_OpcDec12
726
727	ORG_CALL_PAL_PRIV(0x13)
728CallPal_OpcDec13:
729	br	CallPal_OpcDec
730ENDFN	CallPal_OpcDec13
731
732	ORG_CALL_PAL_PRIV(0x14)
733CallPal_OpcDec14:
734	br	CallPal_OpcDec
735ENDFN	CallPal_OpcDec14
736
737	ORG_CALL_PAL_PRIV(0x15)
738CallPal_OpcDec15:
739	br	CallPal_OpcDec
740ENDFN	CallPal_OpcDec15
741
742	ORG_CALL_PAL_PRIV(0x16)
743CallPal_OpcDec16:
744	br	CallPal_OpcDec
745ENDFN	CallPal_OpcDec16
746
747	ORG_CALL_PAL_PRIV(0x17)
748CallPal_OpcDec17:
749	br	CallPal_OpcDec
750ENDFN	CallPal_OpcDec17
751
752	ORG_CALL_PAL_PRIV(0x18)
753CallPal_OpcDec18:
754	br	CallPal_OpcDec
755ENDFN	CallPal_OpcDec18
756
757	ORG_CALL_PAL_PRIV(0x19)
758CallPal_OpcDec19:
759	br	CallPal_OpcDec
760ENDFN	CallPal_OpcDec19
761
762	ORG_CALL_PAL_PRIV(0x1A)
763CallPal_OpcDec1A:
764	br	CallPal_OpcDec
765ENDFN	CallPal_OpcDec1A
766
767	ORG_CALL_PAL_PRIV(0x1B)
768CallPal_OpcDec1B:
769	br	CallPal_OpcDec
770ENDFN	CallPal_OpcDec1B
771
772	ORG_CALL_PAL_PRIV(0x1C)
773CallPal_OpcDec1C:
774	br	CallPal_OpcDec
775ENDFN	CallPal_OpcDec1C
776
777	ORG_CALL_PAL_PRIV(0x1D)
778CallPal_OpcDec1D:
779	br	CallPal_OpcDec
780ENDFN	CallPal_OpcDec1D
781
782	ORG_CALL_PAL_PRIV(0x1E)
783CallPal_OpcDec1E:
784	br	CallPal_OpcDec
785ENDFN	CallPal_OpcDec1E
786
787	ORG_CALL_PAL_PRIV(0x1F)
788CallPal_OpcDec1F:
789	br	CallPal_OpcDec
790ENDFN	CallPal_OpcDec1F
791
792	ORG_CALL_PAL_PRIV(0x20)
793CallPal_OpcDec20:
794	br	CallPal_OpcDec
795ENDFN	CallPal_OpcDec20
796
797	ORG_CALL_PAL_PRIV(0x21)
798CallPal_OpcDec21:
799	br	CallPal_OpcDec
800ENDFN	CallPal_OpcDec21
801
802	ORG_CALL_PAL_PRIV(0x22)
803CallPal_OpcDec22:
804	br	CallPal_OpcDec
805ENDFN	CallPal_OpcDec22
806
807	ORG_CALL_PAL_PRIV(0x23)
808CallPal_OpcDec23:
809	br	CallPal_OpcDec
810ENDFN	CallPal_OpcDec23
811
812	ORG_CALL_PAL_PRIV(0x24)
813CallPal_OpcDec24:
814	br	CallPal_OpcDec
815ENDFN	CallPal_OpcDec24
816
817	ORG_CALL_PAL_PRIV(0x25)
818CallPal_OpcDec25:
819	br	CallPal_OpcDec
820ENDFN	CallPal_OpcDec25
821
822	ORG_CALL_PAL_PRIV(0x26)
823CallPal_OpcDec26:
824	br	CallPal_OpcDec
825ENDFN	CallPal_OpcDec26
826
827	ORG_CALL_PAL_PRIV(0x27)
828CallPal_OpcDec27:
829	br	CallPal_OpcDec
830ENDFN	CallPal_OpcDec27
831
832	ORG_CALL_PAL_PRIV(0x28)
833CallPal_OpcDec28:
834	br	CallPal_OpcDec
835ENDFN	CallPal_OpcDec28
836
837	ORG_CALL_PAL_PRIV(0x29)
838CallPal_OpcDec29:
839	br	CallPal_OpcDec
840ENDFN	CallPal_OpcDec29
841
842	ORG_CALL_PAL_PRIV(0x2A)
843CallPal_OpcDec2A:
844	br	CallPal_OpcDec
845ENDFN	CallPal_OpcDec2A
846
847/*
848 * Write Floating Point Enable
849 *
850 * INPUT PARAMETERS:
851 *
852 *	r16 (a0) = ICSR<FPE> <- a0<0>
853 *
854 * SIDE EFFECTS:
855 *
856 *	Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
857 */
858        ORG_CALL_PAL_PRIV(0x2B)
859CallPal_WrFen:
860	mfpr	p0, ptPcbb		// Get PCBB
861	and	a0, 1, a0		// Clean new FEN value to single bit
862	mtpr	a0, qemu_fen
863	stl_p	a0, PCB_Q_FEN(p0)	// Write new PCB<FEN>
864	hw_rei
865ENDFN	CallPal_WrFen
866
867	ORG_CALL_PAL_PRIV(0x2C)
868CallPal_OpcDec2C:
869	br	CallPal_OpcDec
870ENDFN	CallPal_OpcDec2C
871
872/*
873 * Write Virtual Page Table Pointer
874 *
875 * INPUT PARAMETERS:
876 *
877 *	r16 (a0) = New virtual page table pointer
878 *
879 * SIDE EFFECTS:
880 *
881 *	Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
882 */
883        ORG_CALL_PAL_PRIV(0x2D)
884CallPal_WrVptPtr:
885	mtpr	a0, qemu_vptptr
886	hw_rei
887ENDFN	CallPal_WrVptPtr
888
889	ORG_CALL_PAL_PRIV(0x2E)
890CallPal_OpcDec2E:
891	br	CallPal_OpcDec
892ENDFN	CallPal_OpcDec2E
893
894	ORG_CALL_PAL_PRIV(0x2F)
895CallPal_OpcDec2F:
896	br	CallPal_OpcDec
897ENDFN	CallPal_OpcDec2F
898
899/*
900 * Swap Process Context
901 *
902 * FUNCTIONAL DESCRIPTION:
903 *
904 *	The swap process context (swpctx) function saves
905 *	the current process data in the current PCB, then
906 *	switches to the PCB passed in a0 and loads the
907 *	new process context.  The old PCB is returned in v0.
908 *
909 * INPUT PARAMETERS:
910 *
911 *	r16 (a0) = New PCBB
912 *
913 * OUTPUT PARAMETERS:
914 *
915 *	r0  (v0) = Old PCBB
916 *
917 * SIDE EFFECTS:
918 *
919 *	Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
920 */
921	ORG_CALL_PAL_PRIV(0x30)
922CallPal_SwpCtx:
923	rpcc	p5			// Get cycle counter
924	mfpr	p6, qemu_exc_addr	// Save exc_addr for machine check
925
926	mfpr	v0, ptPcbb		// Get current PCBB
927	mtpr	a0, ptPcbb		// Save new PCBB
928	srl	p5, 32, p7		// Move CC<OFFSET> to low longword
929
930	addl	p5, p7, p7		// Accumulate time for old pcb
931	stl_p	p7, PCB_L_PCC(v0)
932
933	ldl_p	t9, PCB_L_PCC(a0)	// Get new PCC
934	subl	t9, p5, p5		// Generate and ...
935	mtpr	p5, qemu_pcc_ofs	// .. set new CC<OFFSET> bits
936
937	stq_p	$sp, PCB_Q_KSP(v0)	// Store old kernel stack pointer
938	mfpr	t10, qemu_usp		// Save old user stack pointer
939	stq_p	t10, PCB_Q_USP(v0)
940
941	br	CallPal_SwpCtx_Cont
942ENDFN	CallPal_SwpCtx
943
944	.text	1
945CallPal_SwpCtx_Cont:
946	ldq_p	$sp, PCB_Q_KSP(a0)	// Install new stack pointers
947	ldq_p	t10, PCB_Q_USP(a0)
948	mtpr	t10, qemu_usp
949
950	mfpr	t10, qemu_unique	// Save old unique value
951	stq_p	t10, PCB_Q_UNIQUE(v0)
952	ldq_p	t10, PCB_Q_UNIQUE(a0)	// Install new unique value
953	mtpr	t10, qemu_unique
954
955	ldq_p	t8, PCB_Q_FEN(a0)	// Install new FEN
956	and	t8, 1, t8
957	mtpr	t8, qemu_fen
958
959	// QEMU does not implement an ASN; skip that.
960
961	ldq_p	t10, PCB_Q_PTBR(a0)	// Install new page tables
962	sll	t10, VA_S_OFF, t10
963	mtpr	t10, qemu_ptbr
964	mtpr	$31, qemu_tbia		// Flush TLB, since we don't do ASNs
965
966	hw_rei
967ENDFN	CallPal_SwpCtx_Cont
968	.previous
969
970/*
971 * Write System Value
972 *
973 * INPUT PARAMETERS:
974 *
975 *	r16 (a0) = New system value
976 *
977 * SIDE EFFECTS:
978 *
979 *	Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
980 */
981        ORG_CALL_PAL_PRIV(0x31)
982CallPal_WrVal:
983	mtpr	a0, qemu_sysval
984	hw_rei
985ENDFN	CallPal_WrVal
986
987/*
988 * Read System Value
989 *
990 * OUTPUT PARAMETERS:
991 *
992 *	r0 (v0) = Returned system value
993 *
994 * SIDE EFFECTS:
995 *
996 *	Registers t0 and t8..t11 are UNPREDICTABLE upon return.
997 */
998        ORG_CALL_PAL_PRIV(0x32)
999CallPal_RdVal:
1000	mfpr	v0, qemu_sysval
1001	hw_rei
1002ENDFN	CallPal_RdVal
1003
1004/*
1005 * Translation Buffer Invalidate
1006 *
1007 * INPUT PARAMETERS:
1008 *
1009 *	r16 (a0) = tbi selector type:
1010 *
1011 *		-2 - Flush all TB entries (tbia)
1012 *		-1 - Invalidate all TB entries with ASM=0 (tbiap)
1013 *		 1 - Invalidate ITB entry for va=a1 (tbisi)
1014 *		 2 - Invalidate DTB entry for va=a1 (tbisd)
1015 *		 3 - Invalidate both ITB and DTB entry for va=a1 (tbis)
1016 *
1017 *	r17 (a1) = VA for TBISx types
1018 *
1019 * Qemu does not implement ASNs or split I/D tlbs.  Therefore these
1020 * collapse to tbia and tbis.
1021 *
1022 * SIDE EFFECTS:
1023 *
1024 *	Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1025 */
1026        ORG_CALL_PAL_PRIV(0x33)
1027CallPal_Tbi:
1028	bge	a0, 1f
1029
1030	mtpr	$31, qemu_tbia
1031	hw_rei
1032
10331:	mtpr	a1, qemu_tbis
1034	hw_rei
1035ENDFN	CallPal_Tbi
1036
1037/*
1038 * Write System Entry Address
1039 *
1040 * INPUT PARAMETERS:
1041 *
1042 *	r16 (a0) = VA of system entry point
1043 *	r17 (a1) = System entry point selector
1044 *
1045 * SIDE EFFECTS:
1046 *
1047 *	Registers t0, t8..t11, and a0..a1 are UNPREDICTABLE
1048 *	upon return.
1049 */
1050        ORG_CALL_PAL_PRIV(0x34)
1051CallPal_WrEnt:
1052	andnot	a0, 3, a0		// Clean PC<1:0>
1053
1054	cmpult	a1, 6, t8		// Bound the input
1055	cmoveq	t8, 6, a1
1056
1057	br	t0, 1f
10581:	lda	t0, WrEnt_Table-1b(t0)
1059	s8addq	a1, t0, t0
1060	jmp	$31, (t0), 0
1061ENDFN	CallPal_WrEnt
1062
1063	.text	1
1064WrEnt_Table:
10650:	mtpr	a0, ptEntInt
1066	hw_rei
10671:	mtpr	a0, ptEntArith
1068	hw_rei
10692:	mtpr	a0, ptEntMM
1070	hw_rei
10713:	mtpr	a0, ptEntIF
1072	hw_rei
10734:	mtpr	a0, ptEntUna
1074	hw_rei
10755:	mtpr	a0, ptEntSys
1076	hw_rei
10776:	nop
1078	hw_rei
1079ENDFN	WrEnt_Table
1080	.previous
1081
1082/*
1083 * Swap Interrupt Priority Level
1084 *
1085 * INPUT PARAMETERS:
1086 *
1087 *	r16 (a0) = New IPL
1088 *
1089 * OUTPUT PARAMETERS:
1090 *
1091 *	r0  (v0) = Old IPL
1092 *
1093 * SIDE EFFECTS:
1094 *
1095 *	Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1096 */
1097        ORG_CALL_PAL_PRIV(0x35)
1098CallPal_SwpIpl:
1099	mfpr	v0, qemu_ps
1100	and	a0, PS_M_IPL, a0
1101	and	v0, PS_M_IPL, v0
1102	mtpr	a0, qemu_ps
1103	hw_rei
1104ENDFN	CallPal_SwpIpl
1105
1106/*
1107 * Read Processor Status
1108 *
1109 * OUTPUT PARAMETERS:
1110 *
1111 *	r0 (v0) = Current PS
1112 *
1113 * SIDE EFFECTS:
1114 *
1115 *	Registers t0, t8..t11 are UNPREDICTABLE upon return.
1116 */
1117        ORG_CALL_PAL_PRIV(0x36)
1118CallPal_RdPs:
1119	mfpr	v0, qemu_ps
1120	hw_rei
1121ENDFN	CallPal_RdPs
1122
1123/*
1124 * Write Kernel Global Pointer
1125 *
1126 * INPUT PARAMETERS:
1127 *
1128 *	r16 (a0) = New KGP value
1129 *
1130 * SIDE EFFECTS:
1131 *
1132 *	Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1133 */
1134        ORG_CALL_PAL_PRIV(0x37)
1135CallPal_WrKgp:
1136	mtpr	a0, ptKgp
1137	hw_rei
1138ENDFN	CallPal_WrKgp
1139
1140/*
1141 * Write User Stack Pointer
1142 *
1143 * INPUT PARAMETERS:
1144 *
1145 *	r16 (a0) = New user stack pointer value
1146 *
1147 * SIDE EFFECTS:
1148 *
1149 *	Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1150 */
1151        ORG_CALL_PAL_PRIV(0x38)
1152CallPal_WrUsp:
1153	mtpr	a0, qemu_usp
1154	hw_rei
1155ENDFN	CallPal_WrUsp
1156
1157/*
1158 * Write Performance Monitor
1159 *
1160 * INPUT PARAMETERS:
1161 *
1162 *	r16 (a0) = New user stack pointer value
1163 *
1164 * SIDE EFFECTS:
1165 *
1166 *	Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
1167 */
1168	ORG_CALL_PAL_PRIV(0x39)
1169CallPal_WrPerfMon:
1170	// Not implemented
1171	hw_rei
1172ENDFN	CallPal_WrPerfMon
1173
1174/*
1175 * Read User Stack Pointer
1176 *
1177 * OUTPUT PARAMETERS:
1178 *
1179 *	r0 (v0) = User stack pointer value
1180 *
1181 * SIDE EFFECTS:
1182 *
1183 *	Registers t0, and t8..t11 are UNPREDICTABLE upon return.
1184 */
1185        ORG_CALL_PAL_PRIV(0x3A)
1186CallPal_RdUsp:
1187	mfpr	v0, qemu_usp
1188	hw_rei
1189ENDFN	CallPal_RdUsp
1190
1191	ORG_CALL_PAL_PRIV(0x3B)
1192CallPal_OpcDec3B:
1193	br	CallPal_OpcDec
1194ENDFN	CallPal_OpcDec3B
1195
1196/*
1197 * Who Am I
1198 *
1199 * OUTPUT PARAMETERS:
1200 *
1201 *	r0 (v0) = Current processor number
1202 *
1203 * SIDE EFFECTS:
1204 *
1205 *	Registers t0 and t8..t11 are UNPREDICTABLE upon return.
1206 */
1207        ORG_CALL_PAL_PRIV(0x3C)
1208CallPal_Whami:
1209	SYS_WHAMI v0
1210	hw_rei
1211ENDFN	CallPal_Whami
1212
1213/*
1214 * Return From System Call
1215 *
1216 * INPUT PARAMETERS:
1217 *
1218 *	r30 (sp) = Pointer to the top of the kernel stack
1219 *
1220 * OUTPUT PARAMETERS:
1221 *
1222 *	r29 (gp) = Restored user mode global pointer
1223 *	r30 (sp) = User stack pointer
1224 *
1225 * SIDE EFFECTS:
1226 *
1227 *	Registers t0 and t8..t11 are UNPREDICTABLE upon return.
1228 */
1229        ORG_CALL_PAL_PRIV(0x3D)
1230CallPal_RetSys:
1231	ldq	t9, FRM_Q_PC($sp)	// Pop the return address
1232	ldq	$gp, FRM_Q_GP($sp)	// Get the user mode global pointer
1233	lda	t8, FRM_K_SIZE($sp)
1234	mtpr	t8, ptKsp
1235
1236	mov	PS_K_USER, t8		// Set new mode to user
1237	mtpr	t8, qemu_ps
1238
1239	mfpr	$sp, qemu_usp		// Get the user stack pointer
1240
1241	andnot	t9, 3, t9		// Clean return PC<1:0>
1242	hw_ret	(t9)
1243ENDFN	CallPal_RetSys
1244
1245/*
1246 * Wait For Interrupt
1247 *
1248 * FUNCTIONAL DESCRIPTION:
1249 *
1250 *	If possible, wait for the first of either of the following
1251 *	conditions before returning: any interrupt other than a clock
1252 *	tick; or the first clock tick after a specified number of clock
1253 *	ticks have bbeen skipped.
1254 *
1255 * INPUT PARAMETERS:
1256 *
1257 *	r16 (a0) = Maximum number of clock ticks to skip
1258 *
1259 * OUTPUT PARAMETERS:
1260 *
1261 *	r0 (v0) = Number of clock ticks actually skipped.
1262 */
1263	ORG_CALL_PAL_PRIV(0x3E)
1264CallPal_WtInt:
1265	mtpr	$31, qemu_wait
1266	mov	0, v0
1267	hw_rei
1268ENDFN	CallPal_WtInt
1269
1270/*
1271 * Return From Trap, Fault, or Interrupt
1272 *
1273 * INPUT PARAMETERS:
1274 *
1275 *	r30 (sp) = Pointer to the top of the kernel stack
1276 *
1277 * OUTPUT PARAMETERS:
1278 *
1279 *	ps       <- (sp+00)
1280 *	pc       <- (sp+08)
1281 *	r29 (gp) <- (sp+16)
1282 *	r16 (a0) <- (sp+24)
1283 *	r17 (a1) <- (sp+32)
1284 *	r18 (a2) <- (sp+40)
1285 */
1286        ORG_CALL_PAL_PRIV(0x3F)
1287	.globl	CallPal_Rti
1288CallPal_Rti:
1289	mfpr	p6, qemu_exc_addr	// Save exc_addr for machine check
1290
1291	ldq	p4, FRM_Q_PS($sp)	// Get the PS
1292	ldq	p5, FRM_Q_PC($sp)	// Get the return PC
1293	ldq	$gp, FRM_Q_GP($sp)	// Get gp
1294	ldq	a0, FRM_Q_A0($sp)	// Get a0
1295	ldq	a1, FRM_Q_A1($sp)	// Get a1
1296	ldq	a2, FRM_Q_A2($sp)	// Get a2
1297	lda	$sp, FRM_K_SIZE($sp)	// Pop the stack
1298
1299	andnot	p5, 3, p5		// Clean return PC<1:0>
1300
1301	and	p4, PS_M_CM, p3
1302	bne	p3, CallPal_Rti_ToUser
1303
1304	and	p4, PS_M_IPL, p4
1305	mtpr	p4, qemu_ps
1306	hw_ret	(p5)
1307ENDFN	CallPal_Rti
1308
1309	.text	1
1310CallPal_Rti_ToUser:
1311	mtpr	p3, qemu_ps
1312	mtpr	$sp, ptKsp
1313	mfpr	$sp, qemu_usp
1314	hw_ret	(p5)
1315ENDFN	CallPal_Rti_ToUser
1316	.previous
1317
1318/*
1319 * OSF/1 Unprivileged CALL_PAL Entry Points
1320 */
1321
1322#define ORG_CALL_PAL_UNPRIV(X)	.org	0x2000+64*(X-0x80)
1323
1324/*
1325 * A helper routine for the unprivaledged kernel entry points, since the
1326 * actual stack frame setup code is just a tad too large to fit inline.
1327 *
1328 * INPUT PARAMETERS:
1329 *
1330 *	p5 = ps
1331 *	p6 = exc_addr
1332 *	p7 = return address
1333 *
1334 * SIDE EFFECTS:
1335 *
1336 *	p0 is clobbered
1337 *
1338 */
1339	.text	1
1340CallPal_Stack_Frame:
1341	// Test if we're currently in user mode
1342	and	p5, PS_M_CM, p0
1343	beq	p0, 0f
1344CallPal_Stack_Frame_FromUser:
1345	// Switch to kernel mode
1346	mtpr	$31, qemu_ps
1347	mtpr	$sp, qemu_usp
1348	mfpr	$sp, ptKsp
13490:
1350	// Allocate the stack frame
1351	lda	$sp, -FRM_K_SIZE($sp)
1352	stq	p5, FRM_Q_PS($sp)
1353	stq	p6, FRM_Q_PC($sp)
1354	stq	$gp, FRM_Q_GP($sp)
1355	stq	a0, FRM_Q_A0($sp)
1356	stq	a1, FRM_Q_A1($sp)
1357	stq	a2, FRM_Q_A2($sp)
1358	ret	$31, (p7), 0
1359ENDFN	CallPal_Stack_Frame
1360	.previous
1361
1362/*
1363 * Breakpoint Trap
1364 *
1365 * OUTPUT PARAMETERS:
1366 *
1367 *	r16 (a0) = Code for bpt (0)
1368 *	r17 (a1) = UNPREDICTABLE
1369 *	r18 (a2) = UNPREDICTABLE
1370 */
1371        ORG_CALL_PAL_UNPRIV(0x80)
1372CallPal_Bpt:
1373	mfpr	p5, qemu_ps
1374	mfpr	p6, qemu_exc_addr
1375	bsr	p7, CallPal_Stack_Frame
1376
1377	mfpr	p0, ptEntIF
1378	mfpr	$gp, ptKgp
1379	mov	IF_K_BPT, a0
1380	hw_ret	(p0)
1381ENDFN	CallPal_Bpt
1382
1383/*
1384 * Bugcheck Trap
1385 *
1386 * OUTPUT PARAMETERS:
1387 *
1388 *	r16 (a0) = Code for bugchk (1)
1389 *	r17 (a1) = UNPREDICTABLE
1390 *	r18 (a2) = UNPREDICTABLE
1391 */
1392        ORG_CALL_PAL_UNPRIV(0x81)
1393CallPal_BugChk:
1394	mfpr	p5, qemu_ps
1395	mfpr	p6, qemu_exc_addr
1396	bsr	p7, CallPal_Stack_Frame
1397
1398	mfpr	p0, ptEntIF
1399	mfpr	$gp, ptKgp
1400	mov	IF_K_BUGCHK, a0
1401	hw_ret	(p0)
1402ENDFN	CallPal_BugChk
1403
1404
1405	ORG_CALL_PAL_UNPRIV(0x82)
1406CallPal_OpcDec82:
1407	br	CallPal_OpcDec
1408ENDFN	CallPal_OpcDec82
1409
1410/*
1411 * System Call
1412 */
1413        ORG_CALL_PAL_UNPRIV(0x83)
1414CallPal_CallSys:
1415	mfpr	p5, qemu_ps
1416	mfpr	p6, qemu_exc_addr
1417
1418	and	p5, PS_M_CM, p0
1419	beq	p0, 0f
1420
1421	bsr	p7, CallPal_Stack_Frame_FromUser
1422
1423	mfpr	p0, ptEntSys
1424	mfpr	$gp, ptKgp
1425	hw_ret	(p0)
1426
14270:	subq	p6, 4, p6		// Get PC of CALL_PAL insn
1428	lda	p0, MCHK_K_OS_BUGCHECK
1429	br	MchkLogOut
1430ENDFN	CallPal_CallSys
1431
1432	ORG_CALL_PAL_UNPRIV(0x84)
1433CallPal_OpcDec84:
1434	br	CallPal_OpcDec
1435ENDFN	CallPal_OpcDec84
1436
1437	ORG_CALL_PAL_UNPRIV(0x85)
1438CallPal_OpcDec85:
1439	br	CallPal_OpcDec
1440ENDFN	CallPal_OpcDec85
1441
1442
1443/*
1444 * I-Stream Memory Barrier
1445 *
1446 * For QEMU, this is of course a no-op.
1447 */
1448        ORG_CALL_PAL_UNPRIV(0x86)
1449CallPal_Imb:
1450	mb
1451	hw_rei
1452ENDFN	CallPal_Imb
1453
1454
1455	ORG_CALL_PAL_UNPRIV(0x87)
1456CallPal_OpcDec87:
1457	br	CallPal_OpcDec
1458ENDFN	CallPal_OpcDec87
1459
1460	ORG_CALL_PAL_UNPRIV(0x88)
1461CallPal_OpcDec88:
1462	br	CallPal_OpcDec
1463ENDFN	CallPal_OpcDec88
1464
1465	ORG_CALL_PAL_UNPRIV(0x89)
1466CallPal_OpcDec89:
1467	br	CallPal_OpcDec
1468ENDFN	CallPal_OpcDec89
1469
1470	ORG_CALL_PAL_UNPRIV(0x8A)
1471CallPal_OpcDec8A:
1472	br	CallPal_OpcDec
1473ENDFN	CallPal_OpcDec8A
1474
1475	ORG_CALL_PAL_UNPRIV(0x8B)
1476CallPal_OpcDec8B:
1477	br	CallPal_OpcDec
1478ENDFN	CallPal_OpcDec8B
1479
1480	ORG_CALL_PAL_UNPRIV(0x8C)
1481CallPal_OpcDec8C:
1482	br	CallPal_OpcDec
1483ENDFN	CallPal_OpcDec8C
1484
1485	ORG_CALL_PAL_UNPRIV(0x8D)
1486CallPal_OpcDec8D:
1487	br	CallPal_OpcDec
1488ENDFN	CallPal_OpcDec8D
1489
1490	ORG_CALL_PAL_UNPRIV(0x8E)
1491CallPal_OpcDec8E:
1492	br	CallPal_OpcDec
1493ENDFN	CallPal_OpcDec8E
1494
1495	ORG_CALL_PAL_UNPRIV(0x8F)
1496CallPal_OpcDec8F:
1497	br	CallPal_OpcDec
1498ENDFN	CallPal_OpcDec8F
1499
1500	ORG_CALL_PAL_UNPRIV(0x90)
1501CallPal_OpcDec90:
1502	br	CallPal_OpcDec
1503ENDFN	CallPal_OpcDec90
1504
1505	ORG_CALL_PAL_UNPRIV(0x91)
1506CallPal_OpcDec91:
1507	br	CallPal_OpcDec
1508ENDFN	CallPal_OpcDec91
1509
1510	ORG_CALL_PAL_UNPRIV(0x92)
1511CallPal_OpcDec92:
1512	br	CallPal_OpcDec
1513ENDFN	CallPal_OpcDec92
1514
1515	ORG_CALL_PAL_UNPRIV(0x93)
1516CallPal_OpcDec93:
1517	br	CallPal_OpcDec
1518ENDFN	CallPal_OpcDec93
1519
1520	ORG_CALL_PAL_UNPRIV(0x94)
1521CallPal_OpcDec94:
1522	br	CallPal_OpcDec
1523ENDFN	CallPal_OpcDec94
1524
1525	ORG_CALL_PAL_UNPRIV(0x95)
1526CallPal_OpcDec95:
1527	br	CallPal_OpcDec
1528ENDFN	CallPal_OpcDec95
1529
1530	ORG_CALL_PAL_UNPRIV(0x96)
1531CallPal_OpcDec96:
1532	br	CallPal_OpcDec
1533ENDFN	CallPal_OpcDec96
1534
1535	ORG_CALL_PAL_UNPRIV(0x97)
1536CallPal_OpcDec97:
1537	br	CallPal_OpcDec
1538ENDFN	CallPal_OpcDec97
1539
1540	ORG_CALL_PAL_UNPRIV(0x98)
1541CallPal_OpcDec98:
1542	br	CallPal_OpcDec
1543ENDFN	CallPal_OpcDec98
1544
1545	ORG_CALL_PAL_UNPRIV(0x99)
1546CallPal_OpcDec99:
1547	br	CallPal_OpcDec
1548ENDFN	CallPal_OpcDec99
1549
1550	ORG_CALL_PAL_UNPRIV(0x9A)
1551CallPal_OpcDec9A:
1552	br	CallPal_OpcDec
1553ENDFN	CallPal_OpcDec9A
1554
1555	ORG_CALL_PAL_UNPRIV(0x9B)
1556CallPal_OpcDec9B:
1557	br	CallPal_OpcDec
1558ENDFN	CallPal_OpcDec9B
1559
1560	ORG_CALL_PAL_UNPRIV(0x9C)
1561CallPal_OpcDec9C:
1562	br	CallPal_OpcDec
1563ENDFN	CallPal_OpcDec9C
1564
1565	ORG_CALL_PAL_UNPRIV(0x9D)
1566CallPal_OpcDec9D:
1567	br	CallPal_OpcDec
1568ENDFN	CallPal_OpcDec9D
1569
1570/*
1571 * Read Unique Value
1572 *
1573 * OUTPUT PARAMETERS:
1574 *
1575 *	r0 (v0) = Returned process unique value
1576*/
1577        ORG_CALL_PAL_UNPRIV(0x9E)
1578CallPal_RdUnique:
1579	mfpr	v0, qemu_unique
1580	hw_rei
1581ENDFN	CallPal_RdUnique
1582
1583/*
1584 * Write Unique Value
1585 *
1586 * INPUT PARAMETERS:
1587 *
1588 *	r16 (a0) = New process unique value
1589 */
1590        ORG_CALL_PAL_UNPRIV(0x9F)
1591CallPal_WrUnique:
1592	mtpr	a0, qemu_unique
1593	hw_rei
1594ENDFN	CallPal_WrUnique
1595
1596	ORG_CALL_PAL_UNPRIV(0xA0)
1597CallPal_OpcDecA0:
1598	br	CallPal_OpcDec
1599ENDFN	CallPal_OpcDecA0
1600
1601	ORG_CALL_PAL_UNPRIV(0xA1)
1602CallPal_OpcDecA1:
1603	br	CallPal_OpcDec
1604ENDFN	CallPal_OpcDecA1
1605
1606	ORG_CALL_PAL_UNPRIV(0xA2)
1607CallPal_OpcDecA2:
1608	br	CallPal_OpcDec
1609ENDFN	CallPal_OpcDecA2
1610
1611	ORG_CALL_PAL_UNPRIV(0xA3)
1612CallPal_OpcDecA3:
1613	br	CallPal_OpcDec
1614ENDFN	CallPal_OpcDecA3
1615
1616	ORG_CALL_PAL_UNPRIV(0xA4)
1617CallPal_OpcDecA4:
1618	br	CallPal_OpcDec
1619ENDFN	CallPal_OpcDecA4
1620
1621	ORG_CALL_PAL_UNPRIV(0xA5)
1622CallPal_OpcDecA5:
1623	br	CallPal_OpcDec
1624ENDFN	CallPal_OpcDecA5
1625
1626	ORG_CALL_PAL_UNPRIV(0xA6)
1627CallPal_OpcDecA6:
1628	br	CallPal_OpcDec
1629ENDFN	CallPal_OpcDecA6
1630
1631	ORG_CALL_PAL_UNPRIV(0xA7)
1632CallPal_OpcDecA7:
1633	br	CallPal_OpcDec
1634ENDFN	CallPal_OpcDecA7
1635
1636	ORG_CALL_PAL_UNPRIV(0xA8)
1637CallPal_OpcDecA8:
1638	br	CallPal_OpcDec
1639ENDFN	CallPal_OpcDecA8
1640
1641	ORG_CALL_PAL_UNPRIV(0xA9)
1642CallPal_OpcDecA9:
1643	br	CallPal_OpcDec
1644ENDFN	CallPal_OpcDecA9
1645
1646/*
1647 * Generate Trap
1648 *
1649 * OUTPUT PARAMETERS:
1650 *
1651 *	r16 (a0) = Code for gentrap (2)
1652 *	r17 (a1) = UNPREDICTABLE
1653 *	r18 (a2) = UNPREDICTABLE
1654 */
1655        ORG_CALL_PAL_UNPRIV(0xAA)
1656CallPal_GenTrap:
1657	mfpr	p5, qemu_ps
1658	mfpr	p6, qemu_exc_addr
1659	bsr	p7, CallPal_Stack_Frame
1660
1661	mfpr	p0, ptEntIF
1662	mfpr	$gp, ptKgp
1663	mov	IF_K_GENTRAP, a0
1664	hw_ret	(p0)
1665ENDFN	CallPal_GenTrap
1666
1667	ORG_CALL_PAL_UNPRIV(0xAB)
1668CallPal_OpcDecAB:
1669	br	CallPal_OpcDec
1670ENDFN	CallPal_OpcDecAB
1671
1672	ORG_CALL_PAL_UNPRIV(0xAC)
1673CallPal_OpcDecAC:
1674	br	CallPal_OpcDec
1675ENDFN	CallPal_OpcDecAC
1676
1677	ORG_CALL_PAL_UNPRIV(0xAD)
1678CallPal_OpcDecAD:
1679	br	CallPal_OpcDec
1680ENDFN	CallPal_OpcDecAD
1681
1682	ORG_CALL_PAL_UNPRIV(0xAE)
1683CallPal_OpcDecAE:
1684	br	CallPal_OpcDec
1685ENDFN	CallPal_OpcDecAE
1686
1687	ORG_CALL_PAL_UNPRIV(0xAF)
1688CallPal_OpcDecAF:
1689	br	CallPal_OpcDec
1690ENDFN	CallPal_OpcDecAF
1691
1692	ORG_CALL_PAL_UNPRIV(0xB0)
1693CallPal_OpcDecB0:
1694	br	CallPal_OpcDec
1695ENDFN	CallPal_OpcDecB0
1696
1697	ORG_CALL_PAL_UNPRIV(0xB1)
1698CallPal_OpcDecB1:
1699	br	CallPal_OpcDec
1700ENDFN	CallPal_OpcDecB1
1701
1702	ORG_CALL_PAL_UNPRIV(0xB2)
1703CallPal_OpcDecB2:
1704	br	CallPal_OpcDec
1705ENDFN	CallPal_OpcDecB2
1706
1707	ORG_CALL_PAL_UNPRIV(0xB3)
1708CallPal_OpcDecB3:
1709	br	CallPal_OpcDec
1710ENDFN	CallPal_OpcDecB3
1711
1712	ORG_CALL_PAL_UNPRIV(0xB4)
1713CallPal_OpcDecB4:
1714	br	CallPal_OpcDec
1715ENDFN	CallPal_OpcDecB4
1716
1717	ORG_CALL_PAL_UNPRIV(0xB5)
1718CallPal_OpcDecB5:
1719	br	CallPal_OpcDec
1720ENDFN	CallPal_OpcDecB5
1721
1722	ORG_CALL_PAL_UNPRIV(0xB6)
1723CallPal_OpcDecB6:
1724	br	CallPal_OpcDec
1725ENDFN	CallPal_OpcDecB6
1726
1727	ORG_CALL_PAL_UNPRIV(0xB7)
1728CallPal_OpcDecB7:
1729	br	CallPal_OpcDec
1730ENDFN	CallPal_OpcDecB7
1731
1732	ORG_CALL_PAL_UNPRIV(0xB8)
1733CallPal_OpcDecB8:
1734	br	CallPal_OpcDec
1735ENDFN	CallPal_OpcDecB8
1736
1737	ORG_CALL_PAL_UNPRIV(0xB9)
1738CallPal_OpcDecB9:
1739	br	CallPal_OpcDec
1740ENDFN	CallPal_OpcDecB9
1741
1742	ORG_CALL_PAL_UNPRIV(0xBA)
1743CallPal_OpcDecBA:
1744	br	CallPal_OpcDec
1745ENDFN	CallPal_OpcDecBA
1746
1747	ORG_CALL_PAL_UNPRIV(0xBB)
1748CallPal_OpcDecBB:
1749	br	CallPal_OpcDec
1750ENDFN	CallPal_OpcDecBB
1751
1752	ORG_CALL_PAL_UNPRIV(0xBC)
1753CallPal_OpcDecBC:
1754	br	CallPal_OpcDec
1755ENDFN	CallPal_OpcDecBC
1756
1757	ORG_CALL_PAL_UNPRIV(0xBD)
1758CallPal_OpcDecBD:
1759	br	CallPal_OpcDec
1760ENDFN	CallPal_OpcDecBD
1761
1762	ORG_CALL_PAL_UNPRIV(0xBE)
1763CallPal_OpcDecBE:
1764	br	CallPal_OpcDec
1765ENDFN	CallPal_OpcDecBE
1766
1767	ORG_CALL_PAL_UNPRIV(0xBF)
1768CallPal_OpcDec:
1769	mfpr	p5, qemu_ps
1770	mfpr	p6, qemu_exc_addr
1771	bsr	p7, CallPal_Stack_Frame
1772
1773	mfpr	p0, ptEntIF
1774	mfpr	$gp, ptKgp
1775	mov	IF_K_OPCDEC, a0
1776	hw_ret	(p0)
1777ENDFN	CallPal_OpcDec
1778
1779	.org	0x3000
1780	.text	1
1781/*
1782 * Build Machine Check Logout Frame
1783 *
1784 *      This portion of the  machine check handler builds a logout frame
1785 *      in the PAL impure scratch area, builds a stack frame on the kernel
1786 *      stack (already built if there was an interrupt machine check),
1787 *      loads the GP with the KGP, loads the machine check entry
1788 *      code in a0, loads a platform-specific interrupt vector
1789 *      (typically the same value as the SCB offset) in a1, loads
1790 *      the kseg address of the logout area in a2, and dispatches
1791 *      to the kernel interrupt handler pointed to by the entInt
1792 *      operating system entry point.
1793 *
1794 * INPUT PARAMETERS:
1795 *
1796 *      r8  (p0) = Machine check reason
1797 *      r14 (p6) = Exception address
1798 *
1799 * OUTPUT PARAMETERS:
1800 *
1801 *      a0 (r16) = Machine check entry type
1802 *      a1 (r17) = Platform-specific interrupt vector
1803 *      a2 (r18) = Pointer to logout area
1804 */
1805
1806#define MCHK_COMMON_SIZE  24
1807#define MCHK_LOGOUT_SIZE  144
1808
1809MchkLogOut:
1810	mfpr	p1, qemu_ps
1811
1812	// ??? Apparently we skip the insn that caused the mchk.
1813	// ??? This is used by the kernel for mcheck_expected.
1814	addq	p6, 4, p6
1815
1816	STACK_FRAME p1, p6, p2, 0
1817
1818	// Restore the real EXC_ADDR for the logout frame.
1819	subq	p6, 4, p6
1820
1821	// Locate logout frame
1822	br	$gp, .+4
1823	ldah	$gp, 0($gp)			!gpdisp!2
1824	lda	$gp, 0($gp)			!gpdisp!2
1825	ldah	p1, mchk_logout($gp)		!gprelhigh
1826	lda	p1, mchk_logout(p1)		!gprellow
1827
1828	SYS_WHAMI p2
1829	mull	p2, MCHK_LOGOUT_SIZE, p2
1830	addq	p2, p1, a2
1831
1832	// Populate the minimal logout frame
1833	lda	p2, MCHK_LOGOUT_SIZE
1834	stl	p2, 0(a2)			// size
1835	stl	$31, 4(a2)			// flags
1836	lda	p1, MCHK_COMMON_SIZE
1837	stl	p1, 8(a2)			// proc_offset
1838	stl	p2, 12(a2)			// sys_offset
1839	stl	p0, 16(a2)			// mchk_code
1840	stl	$31, 20(a2)			// frame_rev
1841
1842	// EV6 portion, format copied from Linux kernel
1843	// although there's not much we can fill in.
1844	stq	$31, 24(a2)			// I_STAT
1845	stq	$31, 32(a2)			// DC_STAT
1846	stq	$31, 40(a2)			// C_ADDR
1847	stq	$31, 48(a2)			// DC1_SYNDROME
1848	stq	$31, 56(a2)			// DC0_SYNDROME
1849	stq	$31, 64(a2)			// C_STAT
1850	stq	$31, 72(a2)			// C_STS
1851	stq	$31, 80(a2)			// MM_STAT
1852	stq	p6, 88(a2)			// EXC_ADDR
1853	stq	$31, 96(a2)			// IER_CM
1854	stq	$31, 104(a2)			// ISUM
1855	stq	$31, 112(a2)			// RESERVED0
1856	mfpr	p2, qemu_palbr
1857	stq	p2, 120(a2)			// PAL_BASE
1858	stq	$31, 128(a2)			// I_CTL
1859	stq	$31, 136(a2)			// PCTX
1860
1861	mov	IPL_K_MCHK, p1			// Raise IPL
1862	mtpr	p1, qemu_ps
1863
1864	mfpr	p6, ptEntInt
1865	mfpr	$gp, ptKgp
1866	lda	a0, INT_K_MCHK
1867	lda	a1, 0				// "vector"
1868
1869	hw_ret	(p6)
1870ENDFN	MchkLogOut
1871
1872MchkDouble:
1873	bsr	p7, UpdatePCB
1874	lda	v0, HLT_K_DBL_MCHK
1875	br	Sys_EnterConsole
1876ENDFN	MchkDouble
1877
1878MchkBugCheck:
1879MchkFromPal:
1880	bsr	p7, UpdatePCB
1881	lda	v0, HLT_K_MCHK_FROM_PAL
1882	br	Sys_EnterConsole
1883ENDFN	MchkFromPal
1884
1885MchkKspInvalid:
1886	bsr	p7, UpdatePCB
1887	lda	v0, HLT_K_KSP_INVAL
1888	br	Sys_EnterConsole
1889ENDFN	MchkKspInvalid
1890
1891/*
1892 * Update the current PCB with new SP and CC info.
1893 *
1894 * INPUT PARAMETERS:
1895 *
1896 *	p7	= return linkage
1897 */
1898
1899UpdatePCB:
1900	rpcc	p5
1901	mfpr	p4, ptPcbb
1902
1903	mfpr	p3, qemu_ps		// Check current mode
1904	and	p3, PS_M_CM, p3
1905	beq	p3, 1f
1906
1907	mtpr	$sp, qemu_usp		// Save user stack pointer
1908	stq_p	$sp, PCB_Q_USP(p4)
1909	br	2f
1910
19111:	mtpr	$sp, ptKsp		// Save kernel stack pointer
1912	stq_p	$sp, PCB_Q_KSP(p4)
1913
19142:	srl	p5, 32, p3		// Merge for new time
1915	addl	p5, p3, p3
1916	stl_p	p3, PCB_L_PCC(p4)	// Store new time
1917
1918	mfpr	p5, qemu_unique		// Save unique
1919	stq_p	p5, PCB_Q_UNIQUE(p4)
1920
1921	ret	$31, (p7), 0
1922ENDFN	UpdatePCB
1923
1924/*
1925 * FIXME
1926 */
1927Sys_EnterConsole:
1928	halt
1929
1930/*
1931 * Allocate the initial bootup stack.
1932 */
1933
1934	.section .bss.stack
1935	.align 3
1936	.globl	stack
1937	.type	stack,@object
1938	.size	stack,STACK_SIZE * 4
1939stack:	.skip	STACK_SIZE * 4
1940
1941	.globl	mchk_logout
1942	.type	mchk_logout,@object
1943	.size	mchk_logout,MCHK_LOGOUT_SIZE * 4
1944mchk_logout:
1945	.skip	MCHK_LOGOUT_SIZE * 4
1946