osfpal.S revision 8026:680f5c014bed
1/*
2 * Copyright (c) 2003, 2004, 2005, 2006
3 * The Regents of The University of Michigan
4 * All Rights Reserved
5 *
6 * This code is part of the M5 simulator.
7 *
8 * Permission is granted to use, copy, create derivative works and
9 * redistribute this software and such derivative works for any
10 * purpose, so long as the copyright notice above, this grant of
11 * permission, and the disclaimer below appear in all copies made; and
12 * so long as the name of The University of Michigan is not used in
13 * any advertising or publicity pertaining to the use or distribution
14 * of this software without specific, written prior authorization.
15 *
16 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
17 * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND
18 * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER
19 * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE
22 * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT,
23 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM
24 * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
25 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH
26 * DAMAGES.
27 *
28 * Modified for M5 by: Ali G. Saidi
29 *                     Nathan L. Binkert
30 */
31
32/*
33 * Copyright 1992, 1993, 1994, 1995 Hewlett-Packard Development
34 * Company, L.P.
35 *
36 * Permission is hereby granted, free of charge, to any person
37 * obtaining a copy of this software and associated documentation
38 * files (the "Software"), to deal in the Software without
39 * restriction, including without limitation the rights to use, copy,
40 * modify, merge, publish, distribute, sublicense, and/or sell copies
41 * of the Software, and to permit persons to whom the Software is
42 * furnished to do so, subject to the following conditions:
43 *
44 * The above copyright notice and this permission notice shall be
45 * included in all copies or substantial portions of the Software.
46 *
47 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
48 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
49 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
50 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
51 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
52 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
53 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
54 * SOFTWARE.
55 */
56
57// modified to use the Hudson style "impure.h" instead of ev5_impure.sdl
58// since we don't have a mechanism to expand the data structures.... pb Nov/95
59#include "ev5_defs.h"
60#include "ev5_impure.h"
61#include "ev5_alpha_defs.h"
62#include "ev5_paldef.h"
63#include "ev5_osfalpha_defs.h"
64#include "fromHudsonMacros.h"
65#include "fromHudsonOsf.h"
66#include "dc21164FromGasSources.h"
67
68#define DEBUGSTORE(c) nop
69
70#define DEBUG_EXC_ADDR()\
71        bsr	r25, put_exc_addr; \
72        DEBUGSTORE(13)		; \
73        DEBUGSTORE(10)
74
75// This is the fix for the user-mode super page references causing the
76// machine to crash.
77#define hw_rei_spe	hw_rei
78
79#define vmaj 1
80#define vmin 18
81#define vms_pal 1
82#define osf_pal 2
83#define pal_type osf_pal
84#define osfpal_version_l ((pal_type<<16) | (vmaj<<8) | (vmin<<0))
85
86
87///////////////////////////
88// PALtemp register usage
89///////////////////////////
90
91//  The EV5 Ibox holds 24 PALtemp registers.  This maps the OSF PAL usage
92//  for these PALtemps:
93//
94//	pt0   local scratch
95//	pt1   local scratch
96//	pt2   entUna					pt_entUna
97//	pt3   CPU specific impure area pointer		pt_impure
98//	pt4   memory management temp
99//	pt5   memory management temp
100//	pt6   memory management temp
101//	pt7   entIF					pt_entIF
102//	pt8   intmask					pt_intmask
103//	pt9   entSys					pt_entSys
104//	pt10
105//	pt11  entInt					pt_entInt
106//	pt12  entArith					pt_entArith
107//	pt13  reserved for system specific PAL
108//	pt14  reserved for system specific PAL
109//	pt15  reserved for system specific PAL
110//	pt16  MISC: scratch ! WHAMI<7:0> ! 0 0 0 MCES<4:0> pt_misc, pt_whami,
111//                pt_mces
112//	pt17  sysval					pt_sysval
113//	pt18  usp					pt_usp
114//	pt19  ksp					pt_ksp
115//	pt20  PTBR					pt_ptbr
116//	pt21  entMM					pt_entMM
117//	pt22  kgp					pt_kgp
118//	pt23  PCBB					pt_pcbb
119//
120//
121
122
123/////////////////////////////
124// PALshadow register usage
125/////////////////////////////
126
127//
128// EV5 shadows R8-R14 and R25 when in PALmode and ICSR<shadow_enable> = 1.
129// This maps the OSF PAL usage of R8 - R14 and R25:
130//
131// 	r8    ITBmiss/DTBmiss scratch
132// 	r9    ITBmiss/DTBmiss scratch
133// 	r10   ITBmiss/DTBmiss scratch
134//	r11   PS
135//	r12   local scratch
136//	r13   local scratch
137//	r14   local scratch
138//	r25   local scratch
139//
140
141
142
143// .sbttl	"PALcode configuration options"
144
145// There are a number of options that may be assembled into this version of
146// PALcode. They should be adjusted in a prefix assembly file (i.e. do not edit
147// the following). The options that can be adjusted cause the resultant PALcode
148// to reflect the desired target system.
149
150// multiprocessor support can be enabled for a max of n processors by
151// setting the following to the number of processors on the system.
152// Note that this is really the max cpuid.
153
154#define max_cpuid 1
155#ifndef max_cpuid
156#define max_cpuid 8
157#endif
158
159#define osf_svmin 1
160#define osfpal_version_h ((max_cpuid<<16) | (osf_svmin<<0))
161
162//
163// RESET	-  Reset Trap Entry Point
164//
165// RESET - offset 0000
166// Entry:
167//	Vectored into via hardware trap on reset, or branched to
168//	on swppal.
169//
170//	r0 = whami
171//	r1 = pal_base
172//	r2 = base of scratch area
173//	r3 = halt code
174//
175//
176// Function:
177//
178//
179
180        .text	0
181        . = 0x0000
182        .globl _start
183        .globl Pal_Base
184_start:
185Pal_Base:
186        HDW_VECTOR(PAL_RESET_ENTRY)
187Trap_Reset:
188        nop
189        /*
190         * store into r1
191         */
192        br r1,sys_reset
193
194        // Specify PAL version info as a constant
195        // at a known location (reset + 8).
196
197        .long osfpal_version_l		// <pal_type@16> ! <vmaj@8> ! <vmin@0>
198        .long osfpal_version_h		// <max_cpuid@16> ! <osf_svmin@0>
199        .long 0
200        .long 0
201pal_impure_start:
202        .quad 0
203pal_debug_ptr:
204        .quad 0				// reserved for debug pointer ; 20
205
206
207//
208// IACCVIO - Istream Access Violation Trap Entry Point
209//
210// IACCVIO - offset 0080
211// Entry:
212//	Vectored into via hardware trap on Istream access violation or sign check error on PC.
213//
214// Function:
215//	Build stack frame
216//	a0 <- Faulting VA
217//	a1 <- MMCSR  (1 for ACV)
218//	a2 <- -1 (for ifetch fault)
219//	vector via entMM
220//
221
222        HDW_VECTOR(PAL_IACCVIO_ENTRY)
223Trap_Iaccvio:
224        DEBUGSTORE(0x42)
225        sll	r11, 63-osfps_v_mode, r25 // Shift mode up to MS bit
226        mtpr	r31, ev5__ps		// Set Ibox current mode to kernel
227
228        bis	r11, r31, r12		// Save PS
229        bge	r25, TRAP_IACCVIO_10_		// no stack swap needed if cm=kern
230
231
232        mtpr	r31, ev5__dtb_cm	// Set Mbox current mode to kernel -
233                                        //     no virt ref for next 2 cycles
234        mtpr	r30, pt_usp		// save user stack
235
236        bis	r31, r31, r12		// Set new PS
237        mfpr	r30, pt_ksp
238
239TRAP_IACCVIO_10_:
240        lda	sp, 0-osfsf_c_size(sp)// allocate stack space
241        mfpr	r14, exc_addr		// get pc
242
243        stq	r16, osfsf_a0(sp)	// save regs
244        bic	r14, 3, r16		// pass pc/va as a0
245
246        stq	r17, osfsf_a1(sp)	// a1
247        or	r31, mmcsr_c_acv, r17	// pass mm_csr as a1
248
249        stq	r18, osfsf_a2(sp) 	// a2
250        mfpr	r13, pt_entmm		// get entry point
251
252        stq	r11, osfsf_ps(sp)	// save old ps
253        bis	r12, r31, r11		// update ps
254
255        stq	r16, osfsf_pc(sp)	// save pc
256        stq	r29, osfsf_gp(sp) 	// save gp
257
258        mtpr	r13, exc_addr		// load exc_addr with entMM
259                                        // 1 cycle to hw_rei
260        mfpr	r29, pt_kgp		// get the kgp
261
262        subq	r31, 1, r18		// pass flag of istream, as a2
263        hw_rei_spe
264
265
266//
267// INTERRUPT - Interrupt Trap Entry Point
268//
269// INTERRUPT - offset 0100
270// Entry:
271//	Vectored into via trap on hardware interrupt
272//
273// Function:
274//	check for halt interrupt
275//	check for passive release (current ipl geq requestor)
276//	if necessary, switch to kernel mode push stack frame,
277//      update ps (including current mode and ipl copies), sp, and gp
278//	pass the interrupt info to the system module
279//
280//
281        HDW_VECTOR(PAL_INTERRUPT_ENTRY)
282Trap_Interrupt:
283        mfpr    r13, ev5__intid         // Fetch level of interruptor
284        mfpr    r25, ev5__isr           // Fetch interrupt summary register
285
286        srl     r25, isr_v_hlt, r9     // Get HLT bit
287        mfpr	r14, ev5__ipl
288
289        mtpr	r31, ev5__dtb_cm	// Set Mbox current mode to kern
290        blbs    r9, sys_halt_interrupt	// halt_interrupt if HLT bit set
291
292        cmple   r13, r14, r8            // R8 = 1 if intid .less than or eql. ipl
293        bne     r8, sys_passive_release // Passive release is current rupt is lt or eq ipl
294
295        and	r11, osfps_m_mode, r10 // get mode bit
296        beq	r10, TRAP_INTERRUPT_10_		// Skip stack swap in kernel
297
298        mtpr	r30, pt_usp		// save user stack
299        mfpr	r30, pt_ksp		// get kern stack
300
301TRAP_INTERRUPT_10_:
302        lda	sp, (0-osfsf_c_size)(sp)// allocate stack space
303        mfpr	r14, exc_addr		// get pc
304
305        stq	r11, osfsf_ps(sp) 	// save ps
306        stq	r14, osfsf_pc(sp) 	// save pc
307
308        stq     r29, osfsf_gp(sp)       // push gp
309        stq	r16, osfsf_a0(sp)	// a0
310
311//	pvc_violate 354			// ps is cleared anyway,  if store to stack faults.
312        mtpr    r31, ev5__ps            // Set Ibox current mode to kernel
313        stq	r17, osfsf_a1(sp)	// a1
314
315        stq	r18, osfsf_a2(sp) 	// a2
316        subq	r13, 0x11, r12		// Start to translate from EV5IPL->OSFIPL
317
318        srl	r12, 1, r8		// 1d, 1e: ipl 6.  1f: ipl 7.
319        subq	r13, 0x1d, r9		// Check for 1d, 1e, 1f
320
321        cmovge	r9, r8, r12		// if .ge. 1d, then take shifted value
322        bis	r12, r31, r11		// set new ps
323
324        mfpr	r12, pt_intmask
325        and	r11, osfps_m_ipl, r14	// Isolate just new ipl (not really needed, since all non-ipl bits zeroed already)
326
327        /*
328         * Lance had space problems. We don't.
329         */
330        extbl	r12, r14, r14		// Translate new OSFIPL->EV5IPL
331        mfpr	r29, pt_kgp		// update gp
332        mtpr	r14, ev5__ipl		// load the new IPL into Ibox
333        br	r31, sys_interrupt	// Go handle interrupt
334
335
336
337//
338// ITBMISS - Istream TBmiss Trap Entry Point
339//
340// ITBMISS - offset 0180
341// Entry:
342//	Vectored into via hardware trap on Istream translation buffer miss.
343//
344// Function:
345//       Do a virtual fetch of the PTE, and fill the ITB if the PTE is valid.
346//       Can trap into DTBMISS_DOUBLE.
347//       This routine can use the PALshadow registers r8, r9, and r10
348//
349//
350
351        HDW_VECTOR(PAL_ITB_MISS_ENTRY)
352Trap_Itbmiss:
353        // Real MM mapping
354        nop
355        mfpr	r8, ev5__ifault_va_form // Get virtual address of PTE.
356
357        nop
358        mfpr    r10, exc_addr           // Get PC of faulting instruction in case of DTBmiss.
359
360pal_itb_ldq:
361        ld_vpte r8, 0(r8)             	// Get PTE, traps to DTBMISS_DOUBLE in case of TBmiss
362        mtpr	r10, exc_addr		// Restore exc_address if there was a trap.
363
364        mfpr	r31, ev5__va		// Unlock VA in case there was a double miss
365        nop
366
367        and	r8, osfpte_m_foe, r25 	// Look for FOE set.
368        blbc	r8, invalid_ipte_handler // PTE not valid.
369
370        nop
371        bne	r25, foe_ipte_handler	// FOE is set
372
373        nop
374        mtpr	r8, ev5__itb_pte	// Ibox remembers the VA, load the PTE into the ITB.
375
376        hw_rei_stall			//
377
378
379//
380// DTBMISS_SINGLE - Dstream Single TBmiss Trap Entry Point
381//
382// DTBMISS_SINGLE - offset 0200
383// Entry:
384//	Vectored into via hardware trap on Dstream single translation
385//      buffer miss.
386//
387// Function:
388//	Do a virtual fetch of the PTE, and fill the DTB if the PTE is valid.
389//	Can trap into DTBMISS_DOUBLE.
390//	This routine can use the PALshadow registers r8, r9, and r10
391//
392
393        HDW_VECTOR(PAL_DTB_MISS_ENTRY)
394Trap_Dtbmiss_Single:
395        mfpr	r8, ev5__va_form      	// Get virtual address of PTE - 1 cycle delay.  E0.
396        mfpr    r10, exc_addr           // Get PC of faulting instruction in case of error.  E1.
397
398//	DEBUGSTORE(0x45)
399//	DEBUG_EXC_ADDR()
400                                        // Real MM mapping
401        mfpr    r9, ev5__mm_stat	// Get read/write bit.  E0.
402        mtpr	r10, pt6		// Stash exc_addr away
403
404pal_dtb_ldq:
405        ld_vpte r8, 0(r8)             	// Get PTE, traps to DTBMISS_DOUBLE in case of TBmiss
406        nop				// Pad MF VA
407
408        mfpr	r10, ev5__va            // Get original faulting VA for TB load.  E0.
409        nop
410
411        mtpr    r8, ev5__dtb_pte       	// Write DTB PTE part.   E0.
412        blbc    r8, invalid_dpte_handler    // Handle invalid PTE
413
414        mtpr    r10, ev5__dtb_tag      	// Write DTB TAG part, completes DTB load.  No virt ref for 3 cycles.
415        mfpr	r10, pt6
416
417                                        // Following 2 instructions take 2 cycles
418        mtpr    r10, exc_addr           // Return linkage in case we trapped.  E1.
419        mfpr	r31,  pt0		// Pad the write to dtb_tag
420
421        hw_rei                          // Done, return
422
423
424//
425// DTBMISS_DOUBLE - Dstream Double TBmiss Trap Entry Point
426//
427//
428// DTBMISS_DOUBLE - offset 0280
429// Entry:
430//	Vectored into via hardware trap on Double TBmiss from single
431//      miss flows.
432//
433//	r8   - faulting VA
434//	r9   - original MMstat
435//	r10 - original exc_addr (both itb,dtb miss)
436//	pt6 - original exc_addr (dtb miss flow only)
437//	VA IPR - locked with original faulting VA
438//
439// Function:
440// 	Get PTE, if valid load TB and return.
441//	If not valid then take TNV/ACV exception.
442//
443//	pt4 and pt5 are reserved for this flow.
444//
445//
446//
447
448        HDW_VECTOR(PAL_DOUBLE_MISS_ENTRY)
449Trap_Dtbmiss_double:
450        mtpr 	r8, pt4			// save r8 to do exc_addr check
451        mfpr	r8, exc_addr
452        blbc	r8, Trap_Dtbmiss_Single	//if not in palmode, should be in the single routine, dummy!
453        mfpr	r8, pt4			// restore r8
454        nop
455        mtpr	r22, pt5		// Get some scratch space. E1.
456                                        // Due to virtual scheme, we can skip the first lookup and go
457                                        // right to fetch of level 2 PTE
458        sll     r8, (64-((2*page_seg_size_bits)+page_offset_size_bits)), r22  // Clean off upper bits of VA
459        mtpr	r21, pt4		// Get some scratch space. E1.
460
461        srl    	r22, 61-page_seg_size_bits, r22 // Get Va<seg1>*8
462        mfpr	r21, pt_ptbr		// Get physical address of the page table.
463
464        nop
465        addq    r21, r22, r21           // Index into page table for level 2 PTE.
466
467        sll    	r8, (64-((1*page_seg_size_bits)+page_offset_size_bits)), r22  // Clean off upper bits of VA
468        ldq_p   	r21, 0(r21)            	// Get level 2 PTE (addr<2:0> ignored)
469
470        srl    	r22, 61-page_seg_size_bits, r22	// Get Va<seg1>*8
471        blbc 	r21, double_pte_inv		// Check for Invalid PTE.
472
473        srl    	r21, 32, r21			// extract PFN from PTE
474        sll     r21, page_offset_size_bits, r21	// get PFN * 2^13 for add to <seg3>*8
475
476        addq    r21, r22, r21           // Index into page table for level 3 PTE.
477        nop
478
479        ldq_p   	r21, 0(r21)            	// Get level 3 PTE (addr<2:0> ignored)
480        blbc	r21, double_pte_inv	// Check for invalid PTE.
481
482        mtpr	r21, ev5__dtb_pte	// Write the PTE.  E0.
483        mfpr	r22, pt5		// Restore scratch register
484
485        mtpr	r8, ev5__dtb_tag	// Write the TAG. E0.  No virtual references in subsequent 3 cycles.
486        mfpr	r21, pt4		// Restore scratch register
487
488        nop				// Pad write to tag.
489        nop
490
491        nop				// Pad write to tag.
492        nop
493
494        hw_rei
495
496
497
498//
499// UNALIGN -- Dstream unalign trap
500//
501// UNALIGN - offset 0300
502// Entry:
503//	Vectored into via hardware trap on unaligned Dstream reference.
504//
505// Function:
506//	Build stack frame
507//	a0 <- Faulting VA
508//	a1 <- Opcode
509//	a2 <- src/dst register number
510//	vector via entUna
511//
512
513        HDW_VECTOR(PAL_UNALIGN_ENTRY)
514Trap_Unalign:
515/*	DEBUGSTORE(0x47)*/
516        sll	r11, 63-osfps_v_mode, r25 // Shift mode up to MS bit
517        mtpr	r31, ev5__ps		// Set Ibox current mode to kernel
518
519        mfpr	r8, ev5__mm_stat	// Get mmstat --ok to use r8, no tbmiss
520        mfpr	r14, exc_addr		// get pc
521
522        srl	r8, mm_stat_v_ra, r13	// Shift Ra field to ls bits
523        blbs	r14, pal_pal_bug_check  // Bugcheck if unaligned in PAL
524
525        blbs	r8, UNALIGN_NO_DISMISS // lsb only set on store or fetch_m
526                                        // not set, must be a load
527        and	r13, 0x1F, r8		// isolate ra
528
529        cmpeq   r8, 0x1F, r8		// check for r31/F31
530        bne     r8, dfault_fetch_ldr31_err // if its a load to r31 or f31 -- dismiss the fault
531
532UNALIGN_NO_DISMISS:
533        bis	r11, r31, r12		// Save PS
534        bge	r25, UNALIGN_NO_DISMISS_10_		// no stack swap needed if cm=kern
535
536
537        mtpr	r31, ev5__dtb_cm	// Set Mbox current mode to kernel -
538                                        //     no virt ref for next 2 cycles
539        mtpr	r30, pt_usp		// save user stack
540
541        bis	r31, r31, r12		// Set new PS
542        mfpr	r30, pt_ksp
543
544UNALIGN_NO_DISMISS_10_:
545        mfpr	r25, ev5__va		// Unlock VA
546        lda	sp, 0-osfsf_c_size(sp)// allocate stack space
547
548        mtpr	r25, pt0		// Stash VA
549        stq	r18, osfsf_a2(sp) 	// a2
550
551        stq	r11, osfsf_ps(sp)	// save old ps
552        srl	r13, mm_stat_v_opcode-mm_stat_v_ra, r25// Isolate opcode
553
554        stq	r29, osfsf_gp(sp) 	// save gp
555        addq	r14, 4, r14		// inc PC past the ld/st
556
557        stq	r17, osfsf_a1(sp)	// a1
558        and	r25, mm_stat_m_opcode, r17// Clean opocde for a1
559
560        stq	r16, osfsf_a0(sp)	// save regs
561        mfpr	r16, pt0		// a0 <- va/unlock
562
563        stq	r14, osfsf_pc(sp)	// save pc
564        mfpr	r25, pt_entuna		// get entry point
565
566
567        bis	r12, r31, r11		// update ps
568        br 	r31, unalign_trap_cont
569
570
571//
572// DFAULT	- Dstream Fault Trap Entry Point
573//
574// DFAULT - offset 0380
575// Entry:
576//	Vectored into via hardware trap on dstream fault or sign check
577//      error on DVA.
578//
579// Function:
580//	Ignore faults on FETCH/FETCH_M
581//	Check for DFAULT in PAL
582//	Build stack frame
583//	a0 <- Faulting VA
584//	a1 <- MMCSR (1 for ACV, 2 for FOR, 4 for FOW)
585//	a2 <- R/W
586//	vector via entMM
587//
588//
589        HDW_VECTOR(PAL_D_FAULT_ENTRY)
590Trap_Dfault:
591//	DEBUGSTORE(0x48)
592        sll	r11, 63-osfps_v_mode, r25 // Shift mode up to MS bit
593        mtpr	r31, ev5__ps		// Set Ibox current mode to kernel
594
595        mfpr	r13, ev5__mm_stat	// Get mmstat
596        mfpr	r8, exc_addr		// get pc, preserve r14
597
598        srl	r13, mm_stat_v_opcode, r9 // Shift opcode field to ls bits
599        blbs	r8, dfault_in_pal
600
601        bis	r8, r31, r14		// move exc_addr to correct place
602        bis	r11, r31, r12		// Save PS
603
604        mtpr	r31, ev5__dtb_cm	// Set Mbox current mode to kernel -
605                                        //     no virt ref for next 2 cycles
606        and	r9, mm_stat_m_opcode, r9 // Clean all but opcode
607
608        cmpeq   r9, evx_opc_sync, r9 	// Is the opcode fetch/fetchm?
609        bne     r9, dfault_fetch_ldr31_err   // Yes, dismiss the fault
610
611        //dismiss exception if load to r31/f31
612        blbs	r13, dfault_no_dismiss	// mm_stat<0> set on store or fetchm
613
614                                        // not a store or fetch, must be a load
615        srl	r13, mm_stat_v_ra, r9	// Shift rnum to low bits
616
617        and	r9, 0x1F, r9		// isolate rnum
618        nop
619
620        cmpeq   r9, 0x1F, r9   	// Is the rnum r31 or f31?
621        bne     r9, dfault_fetch_ldr31_err    // Yes, dismiss the fault
622
623dfault_no_dismiss:
624        and	r13, 0xf, r13	// Clean extra bits in mm_stat
625        bge	r25, dfault_trap_cont	// no stack swap needed if cm=kern
626
627
628        mtpr	r30, pt_usp		// save user stack
629        bis	r31, r31, r12		// Set new PS
630
631        mfpr	r30, pt_ksp
632        br	r31, dfault_trap_cont
633
634
635//
636// MCHK	-  Machine Check Trap Entry Point
637//
638// MCHK - offset 0400
639// Entry:
640//	Vectored into via hardware trap on machine check.
641//
642// Function:
643//
644//
645
646        HDW_VECTOR(PAL_MCHK_ENTRY)
647Trap_Mchk:
648        DEBUGSTORE(0x49)
649        mtpr    r31, ic_flush_ctl       // Flush the Icache
650        br      r31, sys_machine_check
651
652
653//
654// OPCDEC	-  Illegal Opcode Trap Entry Point
655//
656// OPCDEC - offset 0480
657// Entry:
658//	Vectored into via hardware trap on illegal opcode.
659//
660//	Build stack frame
661//	a0 <- code
662//	a1 <- unpred
663//	a2 <- unpred
664//	vector via entIF
665//
666//
667
668        HDW_VECTOR(PAL_OPCDEC_ENTRY)
669Trap_Opcdec:
670        DEBUGSTORE(0x4a)
671//simos	DEBUG_EXC_ADDR()
672        sll	r11, 63-osfps_v_mode, r25 // Shift mode up to MS bit
673        mtpr	r31, ev5__ps		// Set Ibox current mode to kernel
674
675        mfpr	r14, exc_addr		// get pc
676        blbs	r14, pal_pal_bug_check	// check opcdec in palmode
677
678        bis	r11, r31, r12		// Save PS
679        bge	r25, TRAP_OPCDEC_10_		// no stack swap needed if cm=kern
680
681
682        mtpr	r31, ev5__dtb_cm	// Set Mbox current mode to kernel -
683                                        //     no virt ref for next 2 cycles
684        mtpr	r30, pt_usp		// save user stack
685
686        bis	r31, r31, r12		// Set new PS
687        mfpr	r30, pt_ksp
688
689TRAP_OPCDEC_10_:
690        lda	sp, 0-osfsf_c_size(sp)// allocate stack space
691        addq	r14, 4, r14		// inc pc
692
693        stq	r16, osfsf_a0(sp)	// save regs
694        bis	r31, osf_a0_opdec, r16	// set a0
695
696        stq	r11, osfsf_ps(sp)	// save old ps
697        mfpr	r13, pt_entif		// get entry point
698
699        stq	r18, osfsf_a2(sp) 	// a2
700        stq	r17, osfsf_a1(sp)	// a1
701
702        stq	r29, osfsf_gp(sp) 	// save gp
703        stq	r14, osfsf_pc(sp)	// save pc
704
705        bis	r12, r31, r11		// update ps
706        mtpr	r13, exc_addr		// load exc_addr with entIF
707                                        // 1 cycle to hw_rei, E1
708
709        mfpr	r29, pt_kgp		// get the kgp, E1
710
711        hw_rei_spe			// done, E1
712
713
714//
715// ARITH	-  Arithmetic Exception Trap Entry Point
716//
717// ARITH - offset 0500
718// Entry:
719//	Vectored into via hardware trap on arithmetic excpetion.
720//
721// Function:
722//	Build stack frame
723//	a0 <- exc_sum
724//	a1 <- exc_mask
725//	a2 <- unpred
726//	vector via entArith
727//
728//
729        HDW_VECTOR(PAL_ARITH_ENTRY)
730Trap_Arith:
731        DEBUGSTORE(0x4b)
732        and	r11, osfps_m_mode, r12 // get mode bit
733        mfpr	r31, ev5__va		// unlock mbox
734
735        bis	r11, r31, r25		// save ps
736        mfpr	r14, exc_addr		// get pc
737
738        nop
739        blbs	r14, pal_pal_bug_check	// arith trap from PAL
740
741        mtpr    r31, ev5__dtb_cm        // Set Mbox current mode to kernel -
742                                        //     no virt ref for next 2 cycles
743        beq	r12, TRAP_ARITH_10_		// if zero we are in kern now
744
745        bis	r31, r31, r25		// set the new ps
746        mtpr	r30, pt_usp		// save user stack
747
748        nop
749        mfpr	r30, pt_ksp		// get kern stack
750
751TRAP_ARITH_10_: 	lda	sp, 0-osfsf_c_size(sp)	// allocate stack space
752        mtpr	r31, ev5__ps		// Set Ibox current mode to kernel
753
754        nop				// Pad current mode write and stq
755        mfpr	r13, ev5__exc_sum	// get the exc_sum
756
757        mfpr	r12, pt_entarith
758        stq	r14, osfsf_pc(sp)	// save pc
759
760        stq	r17, osfsf_a1(sp)
761        mfpr    r17, ev5__exc_mask      // Get exception register mask IPR - no mtpr exc_sum in next cycle
762
763        stq	r11, osfsf_ps(sp)	// save ps
764        bis	r25, r31, r11		// set new ps
765
766        stq	r16, osfsf_a0(sp)	// save regs
767        srl	r13, exc_sum_v_swc, r16	// shift data to correct position
768
769        stq	r18, osfsf_a2(sp)
770//	pvc_violate 354			// ok, but make sure reads of exc_mask/sum are not in same trap shadow
771        mtpr	r31, ev5__exc_sum	// Unlock exc_sum and exc_mask
772
773        stq	r29, osfsf_gp(sp)
774        mtpr	r12, exc_addr		// Set new PC - 1 bubble to hw_rei - E1
775
776        mfpr	r29, pt_kgp		// get the kern gp - E1
777        hw_rei_spe			// done - E1
778
779
780//
781// FEN	-  Illegal Floating Point Operation Trap Entry Point
782//
783// FEN - offset 0580
784// Entry:
785//	Vectored into via hardware trap on illegal FP op.
786//
787// Function:
788//	Build stack frame
789//	a0 <- code
790//	a1 <- unpred
791//	a2 <- unpred
792//	vector via entIF
793//
794//
795
796        HDW_VECTOR(PAL_FEN_ENTRY)
797Trap_Fen:
798        sll	r11, 63-osfps_v_mode, r25 // Shift mode up to MS bit
799        mtpr	r31, ev5__ps		// Set Ibox current mode to kernel
800
801        mfpr	r14, exc_addr		// get pc
802        blbs	r14, pal_pal_bug_check	// check opcdec in palmode
803
804        mfpr	r13, ev5__icsr
805        nop
806
807        bis	r11, r31, r12		// Save PS
808        bge	r25, TRAP_FEN_10_		// no stack swap needed if cm=kern
809
810        mtpr	r31, ev5__dtb_cm	// Set Mbox current mode to kernel -
811                                        //     no virt ref for next 2 cycles
812        mtpr	r30, pt_usp		// save user stack
813
814        bis	r31, r31, r12		// Set new PS
815        mfpr	r30, pt_ksp
816
817TRAP_FEN_10_:
818        lda	sp, 0-osfsf_c_size(sp)// allocate stack space
819        srl     r13, icsr_v_fpe, r25   // Shift FP enable to bit 0
820
821
822        stq	r16, osfsf_a0(sp)	// save regs
823        mfpr	r13, pt_entif		// get entry point
824
825        stq	r18, osfsf_a2(sp) 	// a2
826        stq	r11, osfsf_ps(sp)	// save old ps
827
828        stq	r29, osfsf_gp(sp) 	// save gp
829        bis	r12, r31, r11		// set new ps
830
831        stq	r17, osfsf_a1(sp)	// a1
832        blbs	r25,fen_to_opcdec	// If FP is enabled, this is really OPCDEC.
833
834        bis	r31, osf_a0_fen, r16	// set a0
835        stq	r14, osfsf_pc(sp)	// save pc
836
837        mtpr	r13, exc_addr		// load exc_addr with entIF
838                                        // 1 cycle to hw_rei -E1
839
840        mfpr	r29, pt_kgp		// get the kgp -E1
841
842        hw_rei_spe			// done -E1
843
844//	FEN trap was taken, but the fault is really opcdec.
845        ALIGN_BRANCH
846fen_to_opcdec:
847        addq	r14, 4, r14		// save PC+4
848        bis	r31, osf_a0_opdec, r16	// set a0
849
850        stq	r14, osfsf_pc(sp)	// save pc
851        mtpr	r13, exc_addr		// load exc_addr with entIF
852                                        // 1 cycle to hw_rei
853
854        mfpr	r29, pt_kgp		// get the kgp
855        hw_rei_spe			// done
856
857
858
859//////////////////////////////////////////////////////////////////////////////
860// Misc handlers - Start area for misc code.
861//////////////////////////////////////////////////////////////////////////////
862
863//
864// dfault_trap_cont
865//	A dfault trap has been taken.  The sp has been updated if necessary.
866//	Push a stack frame a vector via entMM.
867//
868//	Current state:
869//		r12 - new PS
870//		r13 - MMstat
871//		VA - locked
872//
873//
874        ALIGN_BLOCK
875dfault_trap_cont:
876        lda	sp, 0-osfsf_c_size(sp)// allocate stack space
877        mfpr	r25, ev5__va		// Fetch VA/unlock
878
879        stq	r18, osfsf_a2(sp) 	// a2
880        and	r13, 1, r18		// Clean r/w bit for a2
881
882        stq	r16, osfsf_a0(sp)	// save regs
883        bis	r25, r31, r16		// a0 <- va
884
885        stq	r17, osfsf_a1(sp)	// a1
886        srl	r13, 1, r17		// shift fault bits to right position
887
888        stq	r11, osfsf_ps(sp)	// save old ps
889        bis	r12, r31, r11		// update ps
890
891        stq	r14, osfsf_pc(sp)	// save pc
892        mfpr	r25, pt_entmm		// get entry point
893
894        stq	r29, osfsf_gp(sp) 	// save gp
895        cmovlbs	r17, 1, r17		// a2. acv overrides fox.
896
897        mtpr	r25, exc_addr		// load exc_addr with entMM
898                                        // 1 cycle to hw_rei
899        mfpr	r29, pt_kgp		// get the kgp
900
901        hw_rei_spe			// done
902
903//
904//unalign_trap_cont
905//	An unalign trap has been taken.  Just need to finish up a few things.
906//
907//	Current state:
908//		r25 - entUna
909//		r13 - shifted MMstat
910//
911//
912        ALIGN_BLOCK
913unalign_trap_cont:
914        mtpr	r25, exc_addr		// load exc_addr with entUna
915                                        // 1 cycle to hw_rei
916
917
918        mfpr	r29, pt_kgp		// get the kgp
919        and	r13, mm_stat_m_ra, r18	// Clean Ra for a2
920
921        hw_rei_spe			// done
922
923
924
925//
926// dfault_in_pal
927//	Dfault trap was taken, exc_addr points to a PAL PC.
928//	r9 - mmstat<opcode> right justified
929//	r8 - exception address
930//
931//	These are the cases:
932//		opcode was STQ -- from a stack builder, KSP not valid halt
933//			r14 - original exc_addr
934//			r11 - original PS
935//		opcode was STL_C  -- rti or retsys clear lock_flag by stack write,
936//					KSP not valid halt
937//			r11 - original PS
938//			r14 - original exc_addr
939//		opcode was LDQ -- retsys or rti stack read, KSP not valid halt
940//			r11 - original PS
941//			r14 - original exc_addr
942//		opcode was HW_LD -- itbmiss or dtbmiss, bugcheck due to fault on page tables
943//			r10 - original exc_addr
944//			r11 - original PS
945//
946//
947//
948        ALIGN_BLOCK
949dfault_in_pal:
950        DEBUGSTORE(0x50)
951        bic     r8, 3, r8            // Clean PC
952        mfpr	r9, pal_base
953
954        mfpr	r31, va			// unlock VA
955
956        // if not real_mm, should never get here from miss flows
957
958        subq    r9, r8, r8            // pal_base - offset
959
960        lda     r9, pal_itb_ldq-pal_base(r8)
961        nop
962
963        beq 	r9, dfault_do_bugcheck
964        lda     r9, pal_dtb_ldq-pal_base(r8)
965
966        beq 	r9, dfault_do_bugcheck
967
968//
969// KSP invalid halt case --
970ksp_inval_halt:
971        DEBUGSTORE(76)
972        bic	r11, osfps_m_mode, r11	// set ps to kernel mode
973        mtpr    r0, pt0
974
975        mtpr	r31, dtb_cm		// Make sure that the CM IPRs are all kernel mode
976        mtpr	r31, ips
977
978        mtpr	r14, exc_addr		// Set PC to instruction that caused trouble
979        bsr     r0, pal_update_pcb      // update the pcb
980
981        lda     r0, hlt_c_ksp_inval(r31)  // set halt code to hw halt
982        br      r31, sys_enter_console  // enter the console
983
984        ALIGN_BRANCH
985dfault_do_bugcheck:
986        bis	r10, r31, r14		// bugcheck expects exc_addr in r14
987        br	r31, pal_pal_bug_check
988
989
990//
991// dfault_fetch_ldr31_err - ignore faults on fetch(m) and loads to r31/f31
992//	On entry -
993//		r14 - exc_addr
994//		VA is locked
995//
996//
997        ALIGN_BLOCK
998dfault_fetch_ldr31_err:
999        mtpr	r11, ev5__dtb_cm
1000        mtpr	r11, ev5__ps		// Make sure ps hasn't changed
1001
1002        mfpr	r31, va			// unlock the mbox
1003        addq	r14, 4, r14		// inc the pc to skip the fetch
1004
1005        mtpr	r14, exc_addr		// give ibox new PC
1006        mfpr	r31, pt0		// pad exc_addr write
1007
1008        hw_rei
1009
1010
1011
1012        ALIGN_BLOCK
1013//
1014// sys_from_kern
1015//	callsys from kernel mode - OS bugcheck machine check
1016//
1017//
1018sys_from_kern:
1019        mfpr	r14, exc_addr			// PC points to call_pal
1020        subq	r14, 4, r14
1021
1022        lda	r25, mchk_c_os_bugcheck(r31)    // fetch mchk code
1023        br      r31, pal_pal_mchk
1024
1025
1026// Continuation of long call_pal flows
1027//
1028// wrent_tbl
1029//	Table to write *int in paltemps.
1030//	4 instructions/entry
1031//	r16 has new value
1032//
1033//
1034        ALIGN_BLOCK
1035wrent_tbl:
1036//orig	pvc_jsr	wrent, dest=1
1037        nop
1038        mtpr	r16, pt_entint
1039
1040        mfpr	r31, pt0		// Pad for mt->mf paltemp rule
1041        hw_rei
1042
1043
1044//orig	pvc_jsr	wrent, dest=1
1045        nop
1046        mtpr	r16, pt_entarith
1047
1048        mfpr    r31, pt0                // Pad for mt->mf paltemp rule
1049        hw_rei
1050
1051
1052//orig	pvc_jsr	wrent, dest=1
1053        nop
1054        mtpr	r16, pt_entmm
1055
1056        mfpr    r31, pt0                // Pad for mt->mf paltemp rule
1057        hw_rei
1058
1059
1060//orig	pvc_jsr	wrent, dest=1
1061        nop
1062        mtpr	r16, pt_entif
1063
1064        mfpr    r31, pt0                // Pad for mt->mf paltemp rule
1065        hw_rei
1066
1067
1068//orig	pvc_jsr	wrent, dest=1
1069        nop
1070        mtpr	r16, pt_entuna
1071
1072        mfpr    r31, pt0                // Pad for mt->mf paltemp rule
1073        hw_rei
1074
1075
1076//orig	pvc_jsr	wrent, dest=1
1077        nop
1078        mtpr	r16, pt_entsys
1079
1080        mfpr    r31, pt0                // Pad for mt->mf paltemp rule
1081        hw_rei
1082
1083        ALIGN_BLOCK
1084//
1085// tbi_tbl
1086//	Table to do tbi instructions
1087//	4 instructions per entry
1088//
1089tbi_tbl:
1090        // -2 tbia
1091//orig	pvc_jsr tbi, dest=1
1092        mtpr	r31, ev5__dtb_ia	// Flush DTB
1093        mtpr	r31, ev5__itb_ia	// Flush ITB
1094
1095        hw_rei_stall
1096
1097        nop				// Pad table
1098
1099        // -1 tbiap
1100//orig	pvc_jsr tbi, dest=1
1101        mtpr	r31, ev5__dtb_iap	// Flush DTB
1102        mtpr	r31, ev5__itb_iap	// Flush ITB
1103
1104        hw_rei_stall
1105
1106        nop				// Pad table
1107
1108
1109        // 0 unused
1110//orig	pvc_jsr tbi, dest=1
1111        hw_rei				// Pad table
1112        nop
1113        nop
1114        nop
1115
1116
1117        // 1 tbisi
1118//orig	pvc_jsr tbi, dest=1
1119
1120        nop
1121        nop
1122        mtpr	r17, ev5__itb_is	// Flush ITB
1123        hw_rei_stall
1124
1125        // 2 tbisd
1126//orig	pvc_jsr tbi, dest=1
1127        mtpr	r17, ev5__dtb_is	// Flush DTB.
1128        nop
1129
1130        nop
1131        hw_rei_stall
1132
1133
1134        // 3 tbis
1135//orig	pvc_jsr tbi, dest=1
1136        mtpr	r17, ev5__dtb_is	// Flush DTB
1137        br	r31, tbi_finish
1138        ALIGN_BRANCH
1139tbi_finish:
1140        mtpr	r17, ev5__itb_is	// Flush ITB
1141        hw_rei_stall
1142
1143
1144
1145        ALIGN_BLOCK
1146//
1147// bpt_bchk_common:
1148//	Finish up the bpt/bchk instructions
1149//
1150bpt_bchk_common:
1151        stq	r18, osfsf_a2(sp) 	// a2
1152        mfpr	r13, pt_entif		// get entry point
1153
1154        stq	r12, osfsf_ps(sp)	// save old ps
1155        stq	r14, osfsf_pc(sp)	// save pc
1156
1157        stq	r29, osfsf_gp(sp) 	// save gp
1158        mtpr	r13, exc_addr		// load exc_addr with entIF
1159                                        // 1 cycle to hw_rei
1160
1161        mfpr	r29, pt_kgp		// get the kgp
1162
1163
1164        hw_rei_spe			// done
1165
1166
1167        ALIGN_BLOCK
1168//
1169// rti_to_user
1170//	Finish up the rti instruction
1171//
1172rti_to_user:
1173        mtpr	r11, ev5__dtb_cm	// set Mbox current mode - no virt ref for 2 cycles
1174        mtpr	r11, ev5__ps		// set Ibox current mode - 2 bubble to hw_rei
1175
1176        mtpr	r31, ev5__ipl		// set the ipl. No hw_rei for 2 cycles
1177        mtpr	r25, pt_ksp		// save off incase RTI to user
1178
1179        mfpr	r30, pt_usp
1180        hw_rei_spe			// and back
1181
1182
1183        ALIGN_BLOCK
1184//
1185// rti_to_kern
1186//	Finish up the rti instruction
1187//
1188rti_to_kern:
1189        and	r12, osfps_m_ipl, r11	// clean ps
1190        mfpr	r12, pt_intmask		// get int mask
1191
1192        extbl	r12, r11, r12		// get mask for this ipl
1193        mtpr	r25, pt_ksp		// save off incase RTI to user
1194
1195        mtpr	r12, ev5__ipl		// set the new ipl.
1196        or	r25, r31, sp		// sp
1197
1198//	pvc_violate 217			// possible hidden mt->mf ipl not a problem in callpals
1199        hw_rei
1200
1201        ALIGN_BLOCK
1202//
1203// swpctx_cont
1204//	Finish up the swpctx instruction
1205//
1206
1207swpctx_cont:
1208
1209        bic	r25, r24, r25		// clean icsr<FPE,PMP>
1210        sll	r12, icsr_v_fpe, r12	// shift new fen to pos
1211
1212        ldq_p	r14, osfpcb_q_mmptr(r16)// get new mmptr
1213        srl	r22, osfpcb_v_pme, r22	// get pme down to bit 0
1214
1215        or	r25, r12, r25		// icsr with new fen
1216        srl	r23, 32, r24		// move asn to low asn pos
1217
1218        and	r22, 1, r22
1219        sll	r24, itb_asn_v_asn, r12
1220
1221        sll	r22, icsr_v_pmp, r22
1222        nop
1223
1224        or	r25, r22, r25		// icsr with new pme
1225
1226        sll	r24, dtb_asn_v_asn, r24
1227
1228        subl	r23, r13, r13		// gen new cc offset
1229        mtpr	r12, itb_asn		// no hw_rei_stall in 0,1,2,3,4
1230
1231        mtpr	r24, dtb_asn		// Load up new ASN
1232        mtpr	r25, icsr		// write the icsr
1233
1234        sll	r14, page_offset_size_bits, r14 // Move PTBR into internal position.
1235        ldq_p	r25, osfpcb_q_usp(r16)	// get new usp
1236
1237        insll	r13, 4, r13		// >> 32
1238//	pvc_violate 379			// ldq_p can't trap except replay.  only problem if mf same ipr in same shadow
1239        mtpr	r14, pt_ptbr		// load the new ptbr
1240
1241        mtpr	r13, cc			// set new offset
1242        ldq_p	r30, osfpcb_q_ksp(r16)	// get new ksp
1243
1244//	pvc_violate 379			// ldq_p can't trap except replay.  only problem if mf same ipr in same shadow
1245        mtpr	r25, pt_usp		// save usp
1246
1247no_pm_change_10_:	hw_rei_stall			// back we go
1248
1249        ALIGN_BLOCK
1250//
1251// swppal_cont - finish up the swppal call_pal
1252//
1253
1254swppal_cont:
1255        mfpr	r2, pt_misc		// get misc bits
1256        sll	r0, pt_misc_v_switch, r0 // get the "I've switched" bit
1257        or	r2, r0, r2		// set the bit
1258        mtpr	r31, ev5__alt_mode	// ensure alt_mode set to 0 (kernel)
1259        mtpr	r2, pt_misc		// update the chip
1260
1261        or	r3, r31, r4
1262        mfpr	r3, pt_impure		// pass pointer to the impure area in r3
1263//orig	fix_impure_ipr	r3		// adjust impure pointer for ipr read
1264//orig	restore_reg1	bc_ctl, r1, r3, ipr=1		// pass cns_bc_ctl in r1
1265//orig	restore_reg1	bc_config, r2, r3, ipr=1	// pass cns_bc_config in r2
1266//orig	unfix_impure_ipr r3		// restore impure pointer
1267        lda	r3, CNS_Q_IPR(r3)
1268        RESTORE_SHADOW(r1,CNS_Q_BC_CTL,r3);
1269        RESTORE_SHADOW(r1,CNS_Q_BC_CFG,r3);
1270        lda	r3, -CNS_Q_IPR(r3)
1271
1272        or	r31, r31, r0		// set status to success
1273//	pvc_violate	1007
1274        jmp	r31, (r4)		// and call our friend, it's her problem now
1275
1276
1277swppal_fail:
1278        addq	r0, 1, r0		// set unknown pal or not loaded
1279        hw_rei				// and return
1280
1281
1282// .sbttl	"Memory management"
1283
1284        ALIGN_BLOCK
1285//
1286//foe_ipte_handler
1287// IFOE detected on level 3 pte, sort out FOE vs ACV
1288//
1289// on entry:
1290//	with
1291//	R8	 = pte
1292//	R10	 = pc
1293//
1294// Function
1295//	Determine TNV vs ACV vs FOE. Build stack and dispatch
1296//	Will not be here if TNV.
1297//
1298
1299foe_ipte_handler:
1300        sll	r11, 63-osfps_v_mode, r25 // Shift mode up to MS bit
1301        mtpr	r31, ev5__ps		// Set Ibox current mode to kernel
1302
1303        bis	r11, r31, r12		// Save PS for stack write
1304        bge	r25, foe_ipte_handler_10_		// no stack swap needed if cm=kern
1305
1306
1307        mtpr	r31, ev5__dtb_cm	// Set Mbox current mode to kernel -
1308                                        //     no virt ref for next 2 cycles
1309        mtpr	r30, pt_usp		// save user stack
1310
1311        bis	r31, r31, r11		// Set new PS
1312        mfpr	r30, pt_ksp
1313
1314        srl	r8, osfpte_v_ure-osfpte_v_kre, r8 // move pte user bits to kern
1315        nop
1316
1317foe_ipte_handler_10_:	srl	r8, osfpte_v_kre, r25	// get kre to <0>
1318        lda	sp, 0-osfsf_c_size(sp)// allocate stack space
1319
1320        or	r10, r31, r14		// Save pc/va in case TBmiss or fault on stack
1321        mfpr	r13, pt_entmm		// get entry point
1322
1323        stq	r16, osfsf_a0(sp)	// a0
1324        or	r14, r31, r16		// pass pc/va as a0
1325
1326        stq	r17, osfsf_a1(sp)	// a1
1327        nop
1328
1329        stq	r18, osfsf_a2(sp) 	// a2
1330        lda	r17, mmcsr_c_acv(r31)	// assume ACV
1331
1332        stq	r16, osfsf_pc(sp)	// save pc
1333        cmovlbs r25, mmcsr_c_foe, r17	// otherwise FOE
1334
1335        stq	r12, osfsf_ps(sp)	// save ps
1336        subq	r31, 1, r18		// pass flag of istream as a2
1337
1338        stq	r29, osfsf_gp(sp)
1339        mtpr	r13, exc_addr		// set vector address
1340
1341        mfpr	r29, pt_kgp		// load kgp
1342        hw_rei_spe			// out to exec
1343
1344        ALIGN_BLOCK
1345//
1346//invalid_ipte_handler
1347// TNV detected on level 3 pte, sort out TNV vs ACV
1348//
1349// on entry:
1350//	with
1351//	R8	 = pte
1352//	R10	 = pc
1353//
1354// Function
1355//	Determine TNV vs ACV. Build stack and dispatch.
1356//
1357
1358invalid_ipte_handler:
1359        sll	r11, 63-osfps_v_mode, r25 // Shift mode up to MS bit
1360        mtpr	r31, ev5__ps		// Set Ibox current mode to kernel
1361
1362        bis	r11, r31, r12		// Save PS for stack write
1363        bge	r25, invalid_ipte_handler_10_		// no stack swap needed if cm=kern
1364
1365
1366        mtpr	r31, ev5__dtb_cm	// Set Mbox current mode to kernel -
1367                                        //     no virt ref for next 2 cycles
1368        mtpr	r30, pt_usp		// save user stack
1369
1370        bis	r31, r31, r11		// Set new PS
1371        mfpr	r30, pt_ksp
1372
1373        srl	r8, osfpte_v_ure-osfpte_v_kre, r8 // move pte user bits to kern
1374        nop
1375
1376invalid_ipte_handler_10_:	srl	r8, osfpte_v_kre, r25	// get kre to <0>
1377        lda	sp, 0-osfsf_c_size(sp)// allocate stack space
1378
1379        or	r10, r31, r14		// Save pc/va in case TBmiss on stack
1380        mfpr	r13, pt_entmm		// get entry point
1381
1382        stq	r16, osfsf_a0(sp)	// a0
1383        or	r14, r31, r16		// pass pc/va as a0
1384
1385        stq	r17, osfsf_a1(sp)	// a1
1386        nop
1387
1388        stq	r18, osfsf_a2(sp) 	// a2
1389        and	r25, 1, r17		// Isolate kre
1390
1391        stq	r16, osfsf_pc(sp)	// save pc
1392        xor	r17, 1, r17		// map to acv/tnv as a1
1393
1394        stq	r12, osfsf_ps(sp)	// save ps
1395        subq	r31, 1, r18		// pass flag of istream as a2
1396
1397        stq	r29, osfsf_gp(sp)
1398        mtpr	r13, exc_addr		// set vector address
1399
1400        mfpr	r29, pt_kgp		// load kgp
1401        hw_rei_spe			// out to exec
1402
1403
1404
1405
1406        ALIGN_BLOCK
1407//
1408//invalid_dpte_handler
1409// INVALID detected on level 3 pte, sort out TNV vs ACV
1410//
1411// on entry:
1412//	with
1413//	R10	 = va
1414//	R8	 = pte
1415//	R9	 = mm_stat
1416//	PT6	 = pc
1417//
1418// Function
1419//	Determine TNV vs ACV. Build stack and dispatch
1420//
1421
1422
1423invalid_dpte_handler:
1424        mfpr	r12, pt6
1425        blbs	r12, tnv_in_pal		// Special handler if original faulting reference was in PALmode
1426
1427        bis	r12, r31, r14		// save PC in case of tbmiss or fault
1428        srl	r9, mm_stat_v_opcode, r25	// shift opc to <0>
1429
1430        mtpr	r11, pt0		// Save PS for stack write
1431        and 	r25, mm_stat_m_opcode, r25	// isolate opcode
1432
1433        cmpeq	r25, evx_opc_sync, r25	// is it FETCH/FETCH_M?
1434        blbs	r25, nmiss_fetch_ldr31_err	// yes
1435
1436        //dismiss exception if load to r31/f31
1437        blbs	r9, invalid_dpte_no_dismiss	// mm_stat<0> set on store or fetchm
1438
1439                                        // not a store or fetch, must be a load
1440        srl	r9, mm_stat_v_ra, r25	// Shift rnum to low bits
1441
1442        and	r25, 0x1F, r25		// isolate rnum
1443        nop
1444
1445        cmpeq   r25, 0x1F, r25  	// Is the rnum r31 or f31?
1446        bne     r25, nmiss_fetch_ldr31_err    // Yes, dismiss the fault
1447
1448invalid_dpte_no_dismiss:
1449        sll	r11, 63-osfps_v_mode, r25 // Shift mode up to MS bit
1450        mtpr	r31, ev5__ps		// Set Ibox current mode to kernel
1451
1452        mtpr	r31, ev5__dtb_cm	// Set Mbox current mode to kernel -
1453                                        //     no virt ref for next 2 cycles
1454        bge	r25, invalid_dpte_no_dismiss_10_		// no stack swap needed if cm=kern
1455
1456        srl	r8, osfpte_v_ure-osfpte_v_kre, r8 // move pte user bits to kern
1457        mtpr	r30, pt_usp		// save user stack
1458
1459        bis	r31, r31, r11		// Set new PS
1460        mfpr	r30, pt_ksp
1461
1462invalid_dpte_no_dismiss_10_:	srl	r8, osfpte_v_kre, r12	// get kre to <0>
1463        lda	sp, 0-osfsf_c_size(sp)// allocate stack space
1464
1465        or	r10, r31, r25		// Save va in case TBmiss on stack
1466        and	r9, 1, r13		// save r/w flag
1467
1468        stq	r16, osfsf_a0(sp)	// a0
1469        or	r25, r31, r16		// pass va as a0
1470
1471        stq	r17, osfsf_a1(sp)	// a1
1472        or	r31, mmcsr_c_acv, r17 	// assume acv
1473
1474        srl	r12, osfpte_v_kwe-osfpte_v_kre, r25 // get write enable to <0>
1475        stq	r29, osfsf_gp(sp)
1476
1477        stq	r18, osfsf_a2(sp) 	// a2
1478        cmovlbs r13, r25, r12		// if write access move acv based on write enable
1479
1480        or	r13, r31, r18		// pass flag of dstream access and read vs write
1481        mfpr	r25, pt0		// get ps
1482
1483        stq	r14, osfsf_pc(sp)	// save pc
1484        mfpr	r13, pt_entmm		// get entry point
1485
1486        stq	r25, osfsf_ps(sp)	// save ps
1487        mtpr	r13, exc_addr		// set vector address
1488
1489        mfpr	r29, pt_kgp		// load kgp
1490        cmovlbs	r12, mmcsr_c_tnv, r17 	// make p2 be tnv if access ok else acv
1491
1492        hw_rei_spe			// out to exec
1493
1494//
1495//
1496// We come here if we are erring on a dtb_miss, and the instr is a
1497// fetch, fetch_m, of load to r31/f31.
1498// The PC is incremented, and we return to the program.
1499// essentially ignoring the instruction and error.
1500//
1501//
1502        ALIGN_BLOCK
1503nmiss_fetch_ldr31_err:
1504        mfpr	r12, pt6
1505        addq	r12, 4, r12		// bump pc to pc+4
1506
1507        mtpr	r12, exc_addr		// and set entry point
1508        mfpr	r31, pt0		// pad exc_addr write
1509
1510        hw_rei				//
1511
1512        ALIGN_BLOCK
1513//
1514// double_pte_inv
1515//	We had a single tbmiss which turned into a double tbmiss which found
1516//	an invalid PTE.  Return to single miss with a fake pte, and the invalid
1517//	single miss flow will report the error.
1518//
1519// on entry:
1520//	r21  	PTE
1521//	r22	available
1522//	VA IPR	locked with original fault VA
1523//       pt4  	saved r21
1524//	pt5  	saved r22
1525//	pt6	original exc_addr
1526//
1527// on return to tbmiss flow:
1528//	r8	fake PTE
1529//
1530//
1531//
1532double_pte_inv:
1533        srl	r21, osfpte_v_kre, r21	// get the kre bit to <0>
1534        mfpr	r22, exc_addr		// get the pc
1535
1536        lda	r22, 4(r22)		// inc the pc
1537        lda	r8, osfpte_m_prot(r31)	 // make a fake pte with xre and xwe set
1538
1539        cmovlbc r21, r31, r8		// set to all 0 for acv if pte<kre> is 0
1540        mtpr	r22, exc_addr		// set for rei
1541
1542        mfpr	r21, pt4		// restore regs
1543        mfpr	r22, pt5		// restore regs
1544
1545        hw_rei				// back to tb miss
1546
1547        ALIGN_BLOCK
1548//
1549//tnv_in_pal
1550//	The only places in pal that ld or store are the
1551// 	stack builders, rti or retsys.  Any of these mean we
1552//	need to take a ksp not valid halt.
1553//
1554//
1555tnv_in_pal:
1556
1557
1558        br	r31, ksp_inval_halt
1559
1560
1561// .sbttl	"Icache flush routines"
1562
1563        ALIGN_BLOCK
1564//
1565// Common Icache flush routine.
1566//
1567//
1568//
1569pal_ic_flush:
1570        nop
1571        mtpr	r31, ev5__ic_flush_ctl		// Icache flush - E1
1572        nop
1573        nop
1574
1575// Now, do 44 NOPs.  3RFB prefetches (24) + IC buffer,IB,slot,issue (20)
1576        nop
1577        nop
1578        nop
1579        nop
1580
1581        nop
1582        nop
1583        nop
1584        nop
1585
1586        nop
1587        nop		// 10
1588
1589        nop
1590        nop
1591        nop
1592        nop
1593
1594        nop
1595        nop
1596        nop
1597        nop
1598
1599        nop
1600        nop		// 20
1601
1602        nop
1603        nop
1604        nop
1605        nop
1606
1607        nop
1608        nop
1609        nop
1610        nop
1611
1612        nop
1613        nop		// 30
1614        nop
1615        nop
1616        nop
1617        nop
1618
1619        nop
1620        nop
1621        nop
1622        nop
1623
1624        nop
1625        nop		// 40
1626
1627        nop
1628        nop
1629
1630one_cycle_and_hw_rei:
1631        nop
1632        nop
1633
1634        hw_rei_stall
1635
1636        ALIGN_BLOCK
1637//
1638//osfpal_calpal_opcdec
1639//  Here for all opcdec CALL_PALs
1640//
1641//	Build stack frame
1642//	a0 <- code
1643//	a1 <- unpred
1644//	a2 <- unpred
1645//	vector via entIF
1646//
1647//
1648
1649osfpal_calpal_opcdec:
1650        sll	r11, 63-osfps_v_mode, r25 // Shift mode up to MS bit
1651        mtpr	r31, ev5__ps		// Set Ibox current mode to kernel
1652
1653        mfpr	r14, exc_addr		// get pc
1654        nop
1655
1656        bis	r11, r31, r12		// Save PS for stack write
1657        bge	r25, osfpal_calpal_opcdec_10_		// no stack swap needed if cm=kern
1658
1659
1660        mtpr	r31, ev5__dtb_cm	// Set Mbox current mode to kernel -
1661                                        //     no virt ref for next 2 cycles
1662        mtpr	r30, pt_usp		// save user stack
1663
1664        bis	r31, r31, r11		// Set new PS
1665        mfpr	r30, pt_ksp
1666
1667osfpal_calpal_opcdec_10_:
1668        lda	sp, 0-osfsf_c_size(sp)// allocate stack space
1669        nop
1670
1671        stq	r16, osfsf_a0(sp)	// save regs
1672        bis	r31, osf_a0_opdec, r16	// set a0
1673
1674        stq	r18, osfsf_a2(sp) 	// a2
1675        mfpr	r13, pt_entif		// get entry point
1676
1677        stq	r12, osfsf_ps(sp)	// save old ps
1678        stq	r17, osfsf_a1(sp)	// a1
1679
1680        stq	r14, osfsf_pc(sp)	// save pc
1681        nop
1682
1683        stq	r29, osfsf_gp(sp) 	// save gp
1684        mtpr	r13, exc_addr		// load exc_addr with entIF
1685                                        // 1 cycle to hw_rei
1686
1687        mfpr	r29, pt_kgp		// get the kgp
1688
1689
1690        hw_rei_spe			// done
1691
1692
1693
1694
1695
1696//
1697//pal_update_pcb
1698//	Update the PCB with the current SP, AST, and CC info
1699//
1700//	r0 - return linkage
1701//
1702        ALIGN_BLOCK
1703
1704pal_update_pcb:
1705        mfpr	r12, pt_pcbb		// get pcbb
1706        and	r11, osfps_m_mode, r25	// get mode
1707        beq	r25, pal_update_pcb_10_		// in kern? no need to update user sp
1708        mtpr	r30, pt_usp		// save user stack
1709        stq_p	r30, osfpcb_q_usp(r12)	// store usp
1710        br	r31, pal_update_pcb_20_		// join common
1711pal_update_pcb_10_:	stq_p	r30, osfpcb_q_ksp(r12)	// store ksp
1712pal_update_pcb_20_:	rpcc	r13			// get cyccounter
1713        srl	r13, 32, r14		// move offset
1714        addl	r13, r14, r14		// merge for new time
1715        stl_p	r14, osfpcb_l_cc(r12)	// save time
1716
1717//orig	pvc_jsr	updpcb, bsr=1, dest=1
1718        ret	r31, (r0)
1719
1720
1721//
1722// pal_save_state
1723//
1724//	Function
1725//		All chip state saved, all PT's, SR's FR's, IPR's
1726//
1727//
1728// Regs' on entry...
1729//
1730//	R0 	= halt code
1731//	pt0	= r0
1732//	R1	= pointer to impure
1733//	pt4	= r1
1734//	R3	= return addr
1735//	pt5	= r3
1736//
1737//	register usage:
1738//		r0 = halt_code
1739//		r1 = addr of impure area
1740//		r3 = return_address
1741//		r4 = scratch
1742//
1743//
1744
1745        ALIGN_BLOCK
1746        .globl pal_save_state
1747pal_save_state:
1748//
1749//
1750// start of implementation independent save routine
1751//
1752// 		the impure area is larger than the addressibility of hw_ld and hw_st
1753//		therefore, we need to play some games:  The impure area
1754//		is informally divided into the "machine independent" part and the
1755//		"machine dependent" part.  The state that will be saved in the
1756//    		"machine independent" part are gpr's, fpr's, hlt, flag, mchkflag (use  (un)fix_impure_gpr macros).
1757//		All others will be in the "machine dependent" part (use (un)fix_impure_ipr macros).
1758//		The impure pointer will need to be adjusted by a different offset for each.  The store/restore_reg
1759//		macros will automagically adjust the offset correctly.
1760//
1761
1762// The distributed code is commented out and followed by corresponding SRC code.
1763// Beware: SAVE_IPR and RESTORE_IPR blow away r0(v0)
1764
1765//orig	fix_impure_gpr	r1		// adjust impure area pointer for stores to "gpr" part of impure area
1766        lda	r1, 0x200(r1)		// Point to center of CPU segment
1767//orig	store_reg1 flag, r31, r1, ipr=1	// clear dump area flag
1768        SAVE_GPR(r31,CNS_Q_FLAG,r1)	// Clear the valid flag
1769//orig	store_reg1 hlt, r0, r1, ipr=1
1770        SAVE_GPR(r0,CNS_Q_HALT,r1)	// Save the halt code
1771
1772        mfpr	r0, pt0			// get r0 back			//orig
1773//orig	store_reg1 0, r0, r1		// save r0
1774        SAVE_GPR(r0,CNS_Q_GPR+0x00,r1)	// Save r0
1775
1776        mfpr	r0, pt4			// get r1 back			//orig
1777//orig	store_reg1 1, r0, r1		// save r1
1778        SAVE_GPR(r0,CNS_Q_GPR+0x08,r1)	// Save r1
1779
1780//orig	store_reg 2			// save r2
1781        SAVE_GPR(r2,CNS_Q_GPR+0x10,r1)	// Save r2
1782
1783        mfpr	r0, pt5			// get r3 back			//orig
1784//orig	store_reg1 3, r0, r1		// save r3
1785        SAVE_GPR(r0,CNS_Q_GPR+0x18,r1)	// Save r3
1786
1787        // reason code has been saved
1788        // r0 has been saved
1789        // r1 has been saved
1790        // r2 has been saved
1791        // r3 has been saved
1792        // pt0, pt4, pt5 have been lost
1793
1794        //
1795        // Get out of shadow mode
1796        //
1797
1798        mfpr	r2, icsr		// Get icsr
1799        ldah	r0, (1<<(icsr_v_sde-16))(r31)
1800        bic	r2, r0, r0		// ICSR with SDE clear
1801        mtpr	r0, icsr		// Turn off SDE
1802
1803        mfpr	r31, pt0		// SDE bubble cycle 1
1804        mfpr	r31, pt0		// SDE bubble cycle 2
1805        mfpr	r31, pt0		// SDE bubble cycle 3
1806        nop
1807
1808
1809        // save integer regs R4-r31
1810        SAVE_GPR(r4,CNS_Q_GPR+0x20,r1)
1811        SAVE_GPR(r5,CNS_Q_GPR+0x28,r1)
1812        SAVE_GPR(r6,CNS_Q_GPR+0x30,r1)
1813        SAVE_GPR(r7,CNS_Q_GPR+0x38,r1)
1814        SAVE_GPR(r8,CNS_Q_GPR+0x40,r1)
1815        SAVE_GPR(r9,CNS_Q_GPR+0x48,r1)
1816        SAVE_GPR(r10,CNS_Q_GPR+0x50,r1)
1817        SAVE_GPR(r11,CNS_Q_GPR+0x58,r1)
1818        SAVE_GPR(r12,CNS_Q_GPR+0x60,r1)
1819        SAVE_GPR(r13,CNS_Q_GPR+0x68,r1)
1820        SAVE_GPR(r14,CNS_Q_GPR+0x70,r1)
1821        SAVE_GPR(r15,CNS_Q_GPR+0x78,r1)
1822        SAVE_GPR(r16,CNS_Q_GPR+0x80,r1)
1823        SAVE_GPR(r17,CNS_Q_GPR+0x88,r1)
1824        SAVE_GPR(r18,CNS_Q_GPR+0x90,r1)
1825        SAVE_GPR(r19,CNS_Q_GPR+0x98,r1)
1826        SAVE_GPR(r20,CNS_Q_GPR+0xA0,r1)
1827        SAVE_GPR(r21,CNS_Q_GPR+0xA8,r1)
1828        SAVE_GPR(r22,CNS_Q_GPR+0xB0,r1)
1829        SAVE_GPR(r23,CNS_Q_GPR+0xB8,r1)
1830        SAVE_GPR(r24,CNS_Q_GPR+0xC0,r1)
1831        SAVE_GPR(r25,CNS_Q_GPR+0xC8,r1)
1832        SAVE_GPR(r26,CNS_Q_GPR+0xD0,r1)
1833        SAVE_GPR(r27,CNS_Q_GPR+0xD8,r1)
1834        SAVE_GPR(r28,CNS_Q_GPR+0xE0,r1)
1835        SAVE_GPR(r29,CNS_Q_GPR+0xE8,r1)
1836        SAVE_GPR(r30,CNS_Q_GPR+0xF0,r1)
1837        SAVE_GPR(r31,CNS_Q_GPR+0xF8,r1)
1838
1839        // save all paltemp regs except pt0
1840
1841//orig	unfix_impure_gpr	r1		// adjust impure area pointer for gpr stores
1842//orig	fix_impure_ipr	r1			// adjust impure area pointer for pt stores
1843
1844        lda	r1, -0x200(r1)		// Restore the impure base address.
1845        lda	r1, CNS_Q_IPR(r1)	// Point to the base of IPR area.
1846        SAVE_IPR(pt0,CNS_Q_PT+0x00,r1)		// the osf code didn't save/restore palTemp 0 ?? pboyle
1847        SAVE_IPR(pt1,CNS_Q_PT+0x08,r1)
1848        SAVE_IPR(pt2,CNS_Q_PT+0x10,r1)
1849        SAVE_IPR(pt3,CNS_Q_PT+0x18,r1)
1850        SAVE_IPR(pt4,CNS_Q_PT+0x20,r1)
1851        SAVE_IPR(pt5,CNS_Q_PT+0x28,r1)
1852        SAVE_IPR(pt6,CNS_Q_PT+0x30,r1)
1853        SAVE_IPR(pt7,CNS_Q_PT+0x38,r1)
1854        SAVE_IPR(pt8,CNS_Q_PT+0x40,r1)
1855        SAVE_IPR(pt9,CNS_Q_PT+0x48,r1)
1856        SAVE_IPR(pt10,CNS_Q_PT+0x50,r1)
1857        SAVE_IPR(pt11,CNS_Q_PT+0x58,r1)
1858        SAVE_IPR(pt12,CNS_Q_PT+0x60,r1)
1859        SAVE_IPR(pt13,CNS_Q_PT+0x68,r1)
1860        SAVE_IPR(pt14,CNS_Q_PT+0x70,r1)
1861        SAVE_IPR(pt15,CNS_Q_PT+0x78,r1)
1862        SAVE_IPR(pt16,CNS_Q_PT+0x80,r1)
1863        SAVE_IPR(pt17,CNS_Q_PT+0x88,r1)
1864        SAVE_IPR(pt18,CNS_Q_PT+0x90,r1)
1865        SAVE_IPR(pt19,CNS_Q_PT+0x98,r1)
1866        SAVE_IPR(pt20,CNS_Q_PT+0xA0,r1)
1867        SAVE_IPR(pt21,CNS_Q_PT+0xA8,r1)
1868        SAVE_IPR(pt22,CNS_Q_PT+0xB0,r1)
1869        SAVE_IPR(pt23,CNS_Q_PT+0xB8,r1)
1870
1871        // Restore shadow mode
1872        mfpr	r31, pt0		// pad write to icsr out of shadow of store (trap does not abort write)
1873        mfpr	r31, pt0
1874        mtpr	r2, icsr		// Restore original ICSR
1875
1876        mfpr	r31, pt0		// SDE bubble cycle 1
1877        mfpr	r31, pt0		// SDE bubble cycle 2
1878        mfpr	r31, pt0		// SDE bubble cycle 3
1879        nop
1880
1881        // save all integer shadow regs
1882        SAVE_SHADOW( r8,CNS_Q_SHADOW+0x00,r1)	// also called p0...p7 in the Hudson code
1883        SAVE_SHADOW( r9,CNS_Q_SHADOW+0x08,r1)
1884        SAVE_SHADOW(r10,CNS_Q_SHADOW+0x10,r1)
1885        SAVE_SHADOW(r11,CNS_Q_SHADOW+0x18,r1)
1886        SAVE_SHADOW(r12,CNS_Q_SHADOW+0x20,r1)
1887        SAVE_SHADOW(r13,CNS_Q_SHADOW+0x28,r1)
1888        SAVE_SHADOW(r14,CNS_Q_SHADOW+0x30,r1)
1889        SAVE_SHADOW(r25,CNS_Q_SHADOW+0x38,r1)
1890
1891        SAVE_IPR(excAddr,CNS_Q_EXC_ADDR,r1)
1892        SAVE_IPR(palBase,CNS_Q_PAL_BASE,r1)
1893        SAVE_IPR(mmStat,CNS_Q_MM_STAT,r1)
1894        SAVE_IPR(va,CNS_Q_VA,r1)
1895        SAVE_IPR(icsr,CNS_Q_ICSR,r1)
1896        SAVE_IPR(ipl,CNS_Q_IPL,r1)
1897        SAVE_IPR(ips,CNS_Q_IPS,r1)
1898        SAVE_IPR(itbAsn,CNS_Q_ITB_ASN,r1)
1899        SAVE_IPR(aster,CNS_Q_ASTER,r1)
1900        SAVE_IPR(astrr,CNS_Q_ASTRR,r1)
1901        SAVE_IPR(sirr,CNS_Q_SIRR,r1)
1902        SAVE_IPR(isr,CNS_Q_ISR,r1)
1903        SAVE_IPR(iVptBr,CNS_Q_IVPTBR,r1)
1904        SAVE_IPR(mcsr,CNS_Q_MCSR,r1)
1905        SAVE_IPR(dcMode,CNS_Q_DC_MODE,r1)
1906
1907//orig	pvc_violate 379			// mf maf_mode after a store ok (pvc doesn't distinguish ld from st)
1908//orig	store_reg maf_mode,	ipr=1	// save ipr -- no mbox instructions for
1909//orig                                  // PVC violation applies only to
1910pvc$osf35$379:				    // loads. HW_ST ok here, so ignore
1911        SAVE_IPR(mafMode,CNS_Q_MAF_MODE,r1) // MBOX INST->MF MAF_MODE IN 0,1,2
1912
1913
1914        //the following iprs are informational only -- will not be restored
1915
1916        SAVE_IPR(icPerr,CNS_Q_ICPERR_STAT,r1)
1917        SAVE_IPR(PmCtr,CNS_Q_PM_CTR,r1)
1918        SAVE_IPR(intId,CNS_Q_INT_ID,r1)
1919        SAVE_IPR(excSum,CNS_Q_EXC_SUM,r1)
1920        SAVE_IPR(excMask,CNS_Q_EXC_MASK,r1)
1921        ldah	r14, 0xFFF0(zero)
1922        zap	r14, 0xE0, r14		// Get base address of CBOX IPRs
1923        NOP				// Pad mfpr dcPerr out of shadow of
1924        NOP				// last store
1925        NOP
1926        SAVE_IPR(dcPerr,CNS_Q_DCPERR_STAT,r1)
1927
1928        // read cbox ipr state
1929
1930        mb
1931        ldq_p	r2, scCtl(r14)
1932        ldq_p	r13, ldLock(r14)
1933        ldq_p	r4, scAddr(r14)
1934        ldq_p	r5, eiAddr(r14)
1935        ldq_p	r6, bcTagAddr(r14)
1936        ldq_p	r7, fillSyn(r14)
1937        bis	r5, r4, zero		// Make sure all loads complete before
1938        bis	r7, r6, zero		// reading registers that unlock them.
1939        ldq_p	r8, scStat(r14)		// Unlocks scAddr.
1940        ldq_p	r9, eiStat(r14)		// Unlocks eiAddr, bcTagAddr, fillSyn.
1941        ldq_p	zero, eiStat(r14)	// Make sure it is really unlocked.
1942        mb
1943
1944        // save cbox ipr state
1945        SAVE_SHADOW(r2,CNS_Q_SC_CTL,r1);
1946        SAVE_SHADOW(r13,CNS_Q_LD_LOCK,r1);
1947        SAVE_SHADOW(r4,CNS_Q_SC_ADDR,r1);
1948        SAVE_SHADOW(r5,CNS_Q_EI_ADDR,r1);
1949        SAVE_SHADOW(r6,CNS_Q_BC_TAG_ADDR,r1);
1950        SAVE_SHADOW(r7,CNS_Q_FILL_SYN,r1);
1951        SAVE_SHADOW(r8,CNS_Q_SC_STAT,r1);
1952        SAVE_SHADOW(r9,CNS_Q_EI_STAT,r1);
1953        //bc_config? sl_rcv?
1954
1955// restore impure base
1956//orig	unfix_impure_ipr r1
1957        lda	r1, -CNS_Q_IPR(r1)
1958
1959// save all floating regs
1960        mfpr	r0, icsr		// get icsr
1961        or	r31, 1, r2		// get a one
1962        sll	r2, icsr_v_fpe, r2	// Shift it into ICSR<FPE> position
1963        or	r2, r0, r0		// set FEN on
1964        mtpr	r0, icsr		// write to icsr, enabling FEN
1965
1966// map the save area virtually
1967        mtpr	r31, dtbIa		// Clear all DTB entries
1968        srl	r1, va_s_off, r0	// Clean off byte-within-page offset
1969        sll	r0, pte_v_pfn, r0	// Shift to form PFN
1970        lda	r0, pte_m_prot(r0)	// Set all read/write enable bits
1971        mtpr	r0, dtbPte		// Load the PTE and set valid
1972        mtpr	r1, dtbTag		// Write the PTE and tag into the DTB
1973
1974
1975// map the next page too - in case the impure area crosses a page boundary
1976        lda	r4, (1<<va_s_off)(r1)	// Generate address for next page
1977        srl	r4, va_s_off, r0	// Clean off byte-within-page offset
1978        sll	r0, pte_v_pfn, r0	// Shift to form PFN
1979        lda	r0, pte_m_prot(r0)	// Set all read/write enable bits
1980        mtpr	r0, dtbPte		// Load the PTE and set valid
1981        mtpr	r4, dtbTag		// Write the PTE and tag into the DTB
1982
1983        sll	r31, 0, r31		// stall cycle 1
1984        sll	r31, 0, r31		// stall cycle 2
1985        sll	r31, 0, r31		// stall cycle 3
1986        nop
1987
1988// add offset for saving fpr regs
1989//orig	fix_impure_gpr r1
1990        lda	r1, 0x200(r1)		// Point to center of CPU segment
1991
1992// now save the regs - F0-F31
1993        mf_fpcr  f0			// original
1994
1995        SAVE_FPR(f0,CNS_Q_FPR+0x00,r1)
1996        SAVE_FPR(f1,CNS_Q_FPR+0x08,r1)
1997        SAVE_FPR(f2,CNS_Q_FPR+0x10,r1)
1998        SAVE_FPR(f3,CNS_Q_FPR+0x18,r1)
1999        SAVE_FPR(f4,CNS_Q_FPR+0x20,r1)
2000        SAVE_FPR(f5,CNS_Q_FPR+0x28,r1)
2001        SAVE_FPR(f6,CNS_Q_FPR+0x30,r1)
2002        SAVE_FPR(f7,CNS_Q_FPR+0x38,r1)
2003        SAVE_FPR(f8,CNS_Q_FPR+0x40,r1)
2004        SAVE_FPR(f9,CNS_Q_FPR+0x48,r1)
2005        SAVE_FPR(f10,CNS_Q_FPR+0x50,r1)
2006        SAVE_FPR(f11,CNS_Q_FPR+0x58,r1)
2007        SAVE_FPR(f12,CNS_Q_FPR+0x60,r1)
2008        SAVE_FPR(f13,CNS_Q_FPR+0x68,r1)
2009        SAVE_FPR(f14,CNS_Q_FPR+0x70,r1)
2010        SAVE_FPR(f15,CNS_Q_FPR+0x78,r1)
2011        SAVE_FPR(f16,CNS_Q_FPR+0x80,r1)
2012        SAVE_FPR(f17,CNS_Q_FPR+0x88,r1)
2013        SAVE_FPR(f18,CNS_Q_FPR+0x90,r1)
2014        SAVE_FPR(f19,CNS_Q_FPR+0x98,r1)
2015        SAVE_FPR(f20,CNS_Q_FPR+0xA0,r1)
2016        SAVE_FPR(f21,CNS_Q_FPR+0xA8,r1)
2017        SAVE_FPR(f22,CNS_Q_FPR+0xB0,r1)
2018        SAVE_FPR(f23,CNS_Q_FPR+0xB8,r1)
2019        SAVE_FPR(f24,CNS_Q_FPR+0xC0,r1)
2020        SAVE_FPR(f25,CNS_Q_FPR+0xC8,r1)
2021        SAVE_FPR(f26,CNS_Q_FPR+0xD0,r1)
2022        SAVE_FPR(f27,CNS_Q_FPR+0xD8,r1)
2023        SAVE_FPR(f28,CNS_Q_FPR+0xE0,r1)
2024        SAVE_FPR(f29,CNS_Q_FPR+0xE8,r1)
2025        SAVE_FPR(f30,CNS_Q_FPR+0xF0,r1)
2026        SAVE_FPR(f31,CNS_Q_FPR+0xF8,r1)
2027
2028//switch impure offset from gpr to ipr---
2029//orig	unfix_impure_gpr	r1
2030//orig	fix_impure_ipr	r1
2031//orig	store_reg1 fpcsr, f0, r1, fpcsr=1
2032
2033        SAVE_FPR(f0,CNS_Q_FPCSR,r1)	// fpcsr loaded above into f0 -- can it reach
2034        lda	r1, -0x200(r1)		// Restore the impure base address
2035
2036// and back to gpr ---
2037//orig	unfix_impure_ipr	r1
2038//orig	fix_impure_gpr	r1
2039
2040//orig	lda	r0, cns_mchksize(r31)	// get size of mchk area
2041//orig	store_reg1 mchkflag, r0, r1, ipr=1
2042//orig	mb
2043
2044        lda	r1, CNS_Q_IPR(r1)	// Point to base of IPR area again
2045        // save this using the IPR base (it is closer) not the GRP base as they used...pb
2046        lda	r0, MACHINE_CHECK_SIZE(r31)	// get size of mchk area
2047        SAVE_SHADOW(r0,CNS_Q_MCHK,r1);
2048        mb
2049
2050//orig	or	r31, 1, r0		// get a one
2051//orig	store_reg1 flag, r0, r1, ipr=1	// set dump area flag
2052//orig	mb
2053
2054        lda	r1, -CNS_Q_IPR(r1)	// back to the base
2055        lda	r1, 0x200(r1)		// Point to center of CPU segment
2056        or	r31, 1, r0		// get a one
2057        SAVE_GPR(r0,CNS_Q_FLAG,r1)	// // set dump area valid flag
2058        mb
2059
2060        // restore impure area base
2061//orig	unfix_impure_gpr r1
2062        lda	r1, -0x200(r1)		// Point to center of CPU segment
2063
2064        mtpr	r31, dtb_ia		// clear the dtb
2065        mtpr	r31, itb_ia		// clear the itb
2066
2067//orig	pvc_jsr	savsta, bsr=1, dest=1
2068        ret	r31, (r3)		// and back we go
2069
2070
2071
2072// .sbttl  "PAL_RESTORE_STATE"
2073//
2074//
2075//	Pal_restore_state
2076//
2077//
2078//	register usage:
2079//		r1 = addr of impure area
2080//		r3 = return_address
2081//		all other regs are scratchable, as they are about to
2082//		be reloaded from ram.
2083//
2084//	Function:
2085//		All chip state restored, all SRs, FRs, PTs, IPRs
2086//					*** except R1, R3, PT0, PT4, PT5 ***
2087//
2088//
2089        ALIGN_BLOCK
2090pal_restore_state:
2091
2092//need to restore sc_ctl,bc_ctl,bc_config??? if so, need to figure out a safe way to do so.
2093
2094// map the console io area virtually
2095        mtpr	r31, dtbIa		// Clear all DTB entries
2096        srl	r1, va_s_off, r0	// Clean off byte-within-page offset
2097        sll	r0, pte_v_pfn, r0	// Shift to form PFN
2098        lda	r0, pte_m_prot(r0)	// Set all read/write enable bits
2099        mtpr	r0, dtbPte		// Load the PTE and set valid
2100        mtpr	r1, dtbTag		// Write the PTE and tag into the DTB
2101
2102
2103// map the next page too, in case impure area crosses page boundary
2104        lda	r4, (1<<VA_S_OFF)(r1)	// Generate address for next page
2105        srl	r4, va_s_off, r0	// Clean off byte-within-page offset
2106        sll	r0, pte_v_pfn, r0	// Shift to form PFN
2107        lda	r0, pte_m_prot(r0)	// Set all read/write enable bits
2108        mtpr	r0, dtbPte		// Load the PTE and set valid
2109        mtpr	r4, dtbTag		// Write the PTE and tag into the DTB
2110
2111// save all floating regs
2112        mfpr	r0, icsr		// Get current ICSR
2113        bis	zero, 1, r2		// Get a '1'
2114        or	r2, (1<<(icsr_v_sde-icsr_v_fpe)), r2
2115        sll	r2, icsr_v_fpe, r2	// Shift bits into position
2116        bis	r2, r2, r0		// Set ICSR<SDE> and ICSR<FPE>
2117        mtpr	r0, icsr		// Update the chip
2118
2119        mfpr	r31, pt0		// FPE bubble cycle 1		//orig
2120        mfpr	r31, pt0		// FPE bubble cycle 2		//orig
2121        mfpr	r31, pt0		// FPE bubble cycle 3		//orig
2122
2123//orig	fix_impure_ipr r1
2124//orig	restore_reg1 fpcsr, f0, r1, fpcsr=1
2125//orig	mt_fpcr  f0
2126//orig
2127//orig	unfix_impure_ipr r1
2128//orig	fix_impure_gpr r1		// adjust impure pointer offset for gpr access
2129        lda	r1, 200(r1)	// Point to base of IPR area again
2130        RESTORE_FPR(f0,CNS_Q_FPCSR,r1)		// can it reach?? pb
2131        mt_fpcr  f0			// original
2132
2133        lda	r1, 0x200(r1)		// point to center of CPU segment
2134
2135// restore all floating regs
2136        RESTORE_FPR(f0,CNS_Q_FPR+0x00,r1)
2137        RESTORE_FPR(f1,CNS_Q_FPR+0x08,r1)
2138        RESTORE_FPR(f2,CNS_Q_FPR+0x10,r1)
2139        RESTORE_FPR(f3,CNS_Q_FPR+0x18,r1)
2140        RESTORE_FPR(f4,CNS_Q_FPR+0x20,r1)
2141        RESTORE_FPR(f5,CNS_Q_FPR+0x28,r1)
2142        RESTORE_FPR(f6,CNS_Q_FPR+0x30,r1)
2143        RESTORE_FPR(f7,CNS_Q_FPR+0x38,r1)
2144        RESTORE_FPR(f8,CNS_Q_FPR+0x40,r1)
2145        RESTORE_FPR(f9,CNS_Q_FPR+0x48,r1)
2146        RESTORE_FPR(f10,CNS_Q_FPR+0x50,r1)
2147        RESTORE_FPR(f11,CNS_Q_FPR+0x58,r1)
2148        RESTORE_FPR(f12,CNS_Q_FPR+0x60,r1)
2149        RESTORE_FPR(f13,CNS_Q_FPR+0x68,r1)
2150        RESTORE_FPR(f14,CNS_Q_FPR+0x70,r1)
2151        RESTORE_FPR(f15,CNS_Q_FPR+0x78,r1)
2152        RESTORE_FPR(f16,CNS_Q_FPR+0x80,r1)
2153        RESTORE_FPR(f17,CNS_Q_FPR+0x88,r1)
2154        RESTORE_FPR(f18,CNS_Q_FPR+0x90,r1)
2155        RESTORE_FPR(f19,CNS_Q_FPR+0x98,r1)
2156        RESTORE_FPR(f20,CNS_Q_FPR+0xA0,r1)
2157        RESTORE_FPR(f21,CNS_Q_FPR+0xA8,r1)
2158        RESTORE_FPR(f22,CNS_Q_FPR+0xB0,r1)
2159        RESTORE_FPR(f23,CNS_Q_FPR+0xB8,r1)
2160        RESTORE_FPR(f24,CNS_Q_FPR+0xC0,r1)
2161        RESTORE_FPR(f25,CNS_Q_FPR+0xC8,r1)
2162        RESTORE_FPR(f26,CNS_Q_FPR+0xD0,r1)
2163        RESTORE_FPR(f27,CNS_Q_FPR+0xD8,r1)
2164        RESTORE_FPR(f28,CNS_Q_FPR+0xE0,r1)
2165        RESTORE_FPR(f29,CNS_Q_FPR+0xE8,r1)
2166        RESTORE_FPR(f30,CNS_Q_FPR+0xF0,r1)
2167        RESTORE_FPR(f31,CNS_Q_FPR+0xF8,r1)
2168
2169// switch impure pointer from gpr to ipr area --
2170//orig	unfix_impure_gpr r1
2171//orig	fix_impure_ipr r1
2172        lda	r1, -0x200(r1)		// Restore base address of impure area.
2173        lda	r1, CNS_Q_IPR(r1)	// Point to base of IPR area.
2174
2175// restore all pal regs
2176        RESTORE_IPR(pt0,CNS_Q_PT+0x00,r1)		// the osf code didn't save/restore palTemp 0 ?? pboyle
2177        RESTORE_IPR(pt1,CNS_Q_PT+0x08,r1)
2178        RESTORE_IPR(pt2,CNS_Q_PT+0x10,r1)
2179        RESTORE_IPR(pt3,CNS_Q_PT+0x18,r1)
2180        RESTORE_IPR(pt4,CNS_Q_PT+0x20,r1)
2181        RESTORE_IPR(pt5,CNS_Q_PT+0x28,r1)
2182        RESTORE_IPR(pt6,CNS_Q_PT+0x30,r1)
2183        RESTORE_IPR(pt7,CNS_Q_PT+0x38,r1)
2184        RESTORE_IPR(pt8,CNS_Q_PT+0x40,r1)
2185        RESTORE_IPR(pt9,CNS_Q_PT+0x48,r1)
2186        RESTORE_IPR(pt10,CNS_Q_PT+0x50,r1)
2187        RESTORE_IPR(pt11,CNS_Q_PT+0x58,r1)
2188        RESTORE_IPR(pt12,CNS_Q_PT+0x60,r1)
2189        RESTORE_IPR(pt13,CNS_Q_PT+0x68,r1)
2190        RESTORE_IPR(pt14,CNS_Q_PT+0x70,r1)
2191        RESTORE_IPR(pt15,CNS_Q_PT+0x78,r1)
2192        RESTORE_IPR(pt16,CNS_Q_PT+0x80,r1)
2193        RESTORE_IPR(pt17,CNS_Q_PT+0x88,r1)
2194        RESTORE_IPR(pt18,CNS_Q_PT+0x90,r1)
2195        RESTORE_IPR(pt19,CNS_Q_PT+0x98,r1)
2196        RESTORE_IPR(pt20,CNS_Q_PT+0xA0,r1)
2197        RESTORE_IPR(pt21,CNS_Q_PT+0xA8,r1)
2198        RESTORE_IPR(pt22,CNS_Q_PT+0xB0,r1)
2199        RESTORE_IPR(pt23,CNS_Q_PT+0xB8,r1)
2200
2201
2202//orig	restore_reg exc_addr,	ipr=1	// restore ipr
2203//orig	restore_reg pal_base,	ipr=1	// restore ipr
2204//orig	restore_reg ipl,	ipr=1	// restore ipr
2205//orig	restore_reg ps,		ipr=1	// restore ipr
2206//orig	mtpr	r0, dtb_cm		// set current mode in mbox too
2207//orig	restore_reg itb_asn,	ipr=1
2208//orig	srl	r0, itb_asn_v_asn, r0
2209//orig	sll	r0, dtb_asn_v_asn, r0
2210//orig	mtpr	r0, dtb_asn		// set ASN in Mbox too
2211//orig	restore_reg ivptbr,	ipr=1
2212//orig	mtpr	r0, mvptbr			// use ivptbr value to restore mvptbr
2213//orig	restore_reg mcsr,	ipr=1
2214//orig	restore_reg aster,	ipr=1
2215//orig	restore_reg astrr,	ipr=1
2216//orig	restore_reg sirr,	ipr=1
2217//orig	restore_reg maf_mode, 	ipr=1		// no mbox instruction for 3 cycles
2218//orig	mfpr	r31, pt0			// (may issue with mt maf_mode)
2219//orig	mfpr	r31, pt0			// bubble cycle 1
2220//orig	mfpr	r31, pt0                        // bubble cycle 2
2221//orig	mfpr	r31, pt0                        // bubble cycle 3
2222//orig	mfpr	r31, pt0			// (may issue with following ld)
2223
2224        // r0 gets the value of RESTORE_IPR in the macro and this code uses this side effect (gag)
2225        RESTORE_IPR(excAddr,CNS_Q_EXC_ADDR,r1)
2226        RESTORE_IPR(palBase,CNS_Q_PAL_BASE,r1)
2227        RESTORE_IPR(ipl,CNS_Q_IPL,r1)
2228        RESTORE_IPR(ips,CNS_Q_IPS,r1)
2229        mtpr	r0, dtbCm			// Set Mbox current mode too.
2230        RESTORE_IPR(itbAsn,CNS_Q_ITB_ASN,r1)
2231        srl	r0, 4, r0
2232        sll	r0, 57, r0
2233        mtpr	r0, dtbAsn			// Set Mbox ASN too
2234        RESTORE_IPR(iVptBr,CNS_Q_IVPTBR,r1)
2235        mtpr	r0, mVptBr			// Set Mbox VptBr too
2236        RESTORE_IPR(mcsr,CNS_Q_MCSR,r1)
2237        RESTORE_IPR(aster,CNS_Q_ASTER,r1)
2238        RESTORE_IPR(astrr,CNS_Q_ASTRR,r1)
2239        RESTORE_IPR(sirr,CNS_Q_SIRR,r1)
2240        RESTORE_IPR(mafMode,CNS_Q_MAF_MODE,r1)
2241        STALL
2242        STALL
2243        STALL
2244        STALL
2245        STALL
2246
2247
2248        // restore all integer shadow regs
2249        RESTORE_SHADOW( r8,CNS_Q_SHADOW+0x00,r1)	// also called p0...p7 in the Hudson code
2250        RESTORE_SHADOW( r9,CNS_Q_SHADOW+0x08,r1)
2251        RESTORE_SHADOW(r10,CNS_Q_SHADOW+0x10,r1)
2252        RESTORE_SHADOW(r11,CNS_Q_SHADOW+0x18,r1)
2253        RESTORE_SHADOW(r12,CNS_Q_SHADOW+0x20,r1)
2254        RESTORE_SHADOW(r13,CNS_Q_SHADOW+0x28,r1)
2255        RESTORE_SHADOW(r14,CNS_Q_SHADOW+0x30,r1)
2256        RESTORE_SHADOW(r25,CNS_Q_SHADOW+0x38,r1)
2257        RESTORE_IPR(dcMode,CNS_Q_DC_MODE,r1)
2258
2259        //
2260        // Get out of shadow mode
2261        //
2262
2263        mfpr	r31, pt0		// pad last load to icsr write (in case of replay, icsr will be written anyway)
2264        mfpr	r31, pt0		// ""
2265        mfpr	r0, icsr		// Get icsr
2266        ldah	r2,  (1<<(ICSR_V_SDE-16))(r31)	// Get a one in SHADOW_ENABLE bit location
2267        bic	r0, r2, r2		// ICSR with SDE clear
2268        mtpr	r2, icsr		// Turn off SDE - no palshadow rd/wr for 3 bubble cycles
2269
2270        mfpr	r31, pt0		// SDE bubble cycle 1
2271        mfpr	r31, pt0		// SDE bubble cycle 2
2272        mfpr	r31, pt0		// SDE bubble cycle 3
2273        nop
2274
2275// switch impure pointer from ipr to gpr area --
2276//orig	unfix_impure_ipr	r1
2277//orig	fix_impure_gpr	r1
2278
2279// Restore GPRs (r0, r2 are restored later, r1 and r3 are trashed) ...
2280
2281        lda	r1, -CNS_Q_IPR(r1)	// Restore base address of impure area
2282        lda	r1, 0x200(r1)		// Point to center of CPU segment
2283
2284        // restore all integer regs
2285        RESTORE_GPR(r4,CNS_Q_GPR+0x20,r1)
2286        RESTORE_GPR(r5,CNS_Q_GPR+0x28,r1)
2287        RESTORE_GPR(r6,CNS_Q_GPR+0x30,r1)
2288        RESTORE_GPR(r7,CNS_Q_GPR+0x38,r1)
2289        RESTORE_GPR(r8,CNS_Q_GPR+0x40,r1)
2290        RESTORE_GPR(r9,CNS_Q_GPR+0x48,r1)
2291        RESTORE_GPR(r10,CNS_Q_GPR+0x50,r1)
2292        RESTORE_GPR(r11,CNS_Q_GPR+0x58,r1)
2293        RESTORE_GPR(r12,CNS_Q_GPR+0x60,r1)
2294        RESTORE_GPR(r13,CNS_Q_GPR+0x68,r1)
2295        RESTORE_GPR(r14,CNS_Q_GPR+0x70,r1)
2296        RESTORE_GPR(r15,CNS_Q_GPR+0x78,r1)
2297        RESTORE_GPR(r16,CNS_Q_GPR+0x80,r1)
2298        RESTORE_GPR(r17,CNS_Q_GPR+0x88,r1)
2299        RESTORE_GPR(r18,CNS_Q_GPR+0x90,r1)
2300        RESTORE_GPR(r19,CNS_Q_GPR+0x98,r1)
2301        RESTORE_GPR(r20,CNS_Q_GPR+0xA0,r1)
2302        RESTORE_GPR(r21,CNS_Q_GPR+0xA8,r1)
2303        RESTORE_GPR(r22,CNS_Q_GPR+0xB0,r1)
2304        RESTORE_GPR(r23,CNS_Q_GPR+0xB8,r1)
2305        RESTORE_GPR(r24,CNS_Q_GPR+0xC0,r1)
2306        RESTORE_GPR(r25,CNS_Q_GPR+0xC8,r1)
2307        RESTORE_GPR(r26,CNS_Q_GPR+0xD0,r1)
2308        RESTORE_GPR(r27,CNS_Q_GPR+0xD8,r1)
2309        RESTORE_GPR(r28,CNS_Q_GPR+0xE0,r1)
2310        RESTORE_GPR(r29,CNS_Q_GPR+0xE8,r1)
2311        RESTORE_GPR(r30,CNS_Q_GPR+0xF0,r1)
2312        RESTORE_GPR(r31,CNS_Q_GPR+0xF8,r1)
2313
2314//orig	// switch impure pointer from gpr to ipr area --
2315//orig	unfix_impure_gpr	r1
2316//orig	fix_impure_ipr	r1
2317//orig	restore_reg icsr, ipr=1		// restore original icsr- 4 bubbles to hw_rei
2318
2319        lda	t0, -0x200(t0)		// Restore base address of impure area.
2320        lda	t0, CNS_Q_IPR(t0)	// Point to base of IPR area again.
2321        RESTORE_IPR(icsr,CNS_Q_ICSR,r1)
2322
2323//orig	// and back again --
2324//orig	unfix_impure_ipr	r1
2325//orig	fix_impure_gpr	r1
2326//orig	store_reg1 	flag, r31, r1, ipr=1 // clear dump area valid flag
2327//orig	mb
2328
2329        lda	t0, -CNS_Q_IPR(t0)	// Back to base of impure area again,
2330        lda	t0, 0x200(t0)		// and back to center of CPU segment
2331        SAVE_GPR(r31,CNS_Q_FLAG,r1)	// Clear the dump area valid flag
2332        mb
2333
2334//orig	// and back we go
2335//orig//	restore_reg 3
2336//orig	restore_reg 2
2337//orig//	restore_reg 1
2338//orig	restore_reg 0
2339//orig	// restore impure area base
2340//orig	unfix_impure_gpr r1
2341
2342        RESTORE_GPR(r2,CNS_Q_GPR+0x10,r1)
2343        RESTORE_GPR(r0,CNS_Q_GPR+0x00,r1)
2344        lda	r1, -0x200(r1)		// Restore impure base address
2345
2346        mfpr	r31, pt0		// stall for ldq_p above		//orig
2347
2348        mtpr	r31, dtb_ia		// clear the tb			//orig
2349        mtpr	r31, itb_ia		// clear the itb		//orig
2350
2351//orig	pvc_jsr	rststa, bsr=1, dest=1
2352        ret	r31, (r3)		// back we go			//orig
2353
2354
2355//
2356// pal_pal_bug_check -- code has found a bugcheck situation.
2357//	Set things up and join common machine check flow.
2358//
2359// Input:
2360//	r14 	- exc_addr
2361//
2362// On exit:
2363//	pt0	- saved r0
2364//	pt1	- saved	r1
2365//	pt4	- saved r4
2366//	pt5	- saved r5
2367//	pt6	- saved r6
2368//	pt10	- saved exc_addr
2369//       pt_misc<47:32> - mchk code
2370//       pt_misc<31:16> - scb vector
2371//	r14	- base of Cbox IPRs in IO space
2372//	MCES<mchk> is set
2373//
2374
2375                ALIGN_BLOCK
2376        .globl pal_pal_bug_check_from_int
2377pal_pal_bug_check_from_int:
2378        DEBUGSTORE(0x79)
2379//simos	DEBUG_EXC_ADDR()
2380        DEBUGSTORE(0x20)
2381//simos	bsr	r25, put_hex
2382        lda	r25, mchk_c_bugcheck(r31)
2383        addq	r25, 1, r25			// set flag indicating we came from interrupt and stack is already pushed
2384        br	r31, pal_pal_mchk
2385        nop
2386
2387pal_pal_bug_check:
2388        lda     r25, mchk_c_bugcheck(r31)
2389
2390pal_pal_mchk:
2391        sll	r25, 32, r25			// Move mchk code to position
2392
2393        mtpr	r14, pt10			// Stash exc_addr
2394        mtpr	r14, exc_addr
2395
2396        mfpr	r12, pt_misc			// Get MCES and scratch
2397        zap	r12, 0x3c, r12
2398
2399        or	r12, r25, r12			// Combine mchk code
2400        lda	r25, scb_v_procmchk(r31)	// Get SCB vector
2401
2402        sll	r25, 16, r25			// Move SCBv to position
2403        or	r12, r25, r25			// Combine SCBv
2404
2405        mtpr	r0, pt0				// Stash for scratch
2406        bis	r25, mces_m_mchk, r25	// Set MCES<MCHK> bit
2407
2408        mtpr	r25, pt_misc			// Save mchk code!scbv!whami!mces
2409        ldah	r14, 0xfff0(r31)
2410
2411        mtpr	r1, pt1				// Stash for scratch
2412        zap	r14, 0xE0, r14			// Get Cbox IPR base
2413
2414        mtpr	r4, pt4
2415        mtpr	r5, pt5
2416
2417        mtpr	r6, pt6
2418        blbs	r12, sys_double_machine_check   // MCHK halt if double machine check
2419
2420        br	r31, sys_mchk_collect_iprs	// Join common machine check flow
2421
2422
2423
2424//	align_to_call_pal_section
2425//      Align to address of first call_pal entry point - 2000
2426
2427//
2428// HALT	- PALcode for HALT instruction
2429//
2430// Entry:
2431//	Vectored into via hardware PALcode instruction dispatch.
2432//
2433// Function:
2434//	GO to console code
2435//
2436//
2437
2438        .text	1
2439//	. = 0x2000
2440       CALL_PAL_PRIV(PAL_HALT_ENTRY)
2441call_pal_halt:
2442        mfpr	r31, pt0		// Pad exc_addr read
2443        mfpr	r31, pt0
2444
2445        mfpr	r12, exc_addr		// get PC
2446        subq	r12, 4, r12		// Point to the HALT
2447
2448        mtpr	r12, exc_addr
2449        mtpr	r0, pt0
2450
2451//orig	pvc_jsr updpcb, bsr=1
2452        bsr    r0, pal_update_pcb      	// update the pcb
2453        lda    r0, hlt_c_sw_halt(r31)  	// set halt code to sw halt
2454        br     r31, sys_enter_console  	// enter the console
2455
2456//
2457// CFLUSH - PALcode for CFLUSH instruction
2458//
2459// Entry:
2460//	Vectored into via hardware PALcode instruction dispatch.
2461//
2462//	R16 - contains the PFN of the page to be flushed
2463//
2464// Function:
2465//	Flush all Dstream caches of 1 entire page
2466//	The CFLUSH routine is in the system specific module.
2467//
2468//
2469
2470        CALL_PAL_PRIV(PAL_CFLUSH_ENTRY)
2471Call_Pal_Cflush:
2472        br	r31, sys_cflush
2473
2474//
2475// DRAINA	- PALcode for DRAINA instruction
2476//
2477// Entry:
2478//	Vectored into via hardware PALcode instruction dispatch.
2479//	Implicit TRAPB performed by hardware.
2480//
2481// Function:
2482//	Stall instruction issue until all prior instructions are guaranteed to
2483//	complete without incurring aborts.  For the EV5 implementation, this
2484//	means waiting until all pending DREADS are returned.
2485//
2486//
2487
2488        CALL_PAL_PRIV(PAL_DRAINA_ENTRY)
2489Call_Pal_Draina:
2490        ldah	r14, 0x100(r31)		// Init counter.  Value?
2491        nop
2492
2493DRAINA_LOOP:
2494        subq	r14, 1, r14		// Decrement counter
2495        mfpr	r13, ev5__maf_mode	// Fetch status bit
2496
2497        srl	r13, maf_mode_v_dread_pending, r13
2498        ble	r14, DRAINA_LOOP_TOO_LONG
2499
2500        nop
2501        blbs	r13, DRAINA_LOOP	// Wait until all DREADS clear
2502
2503        hw_rei
2504
2505DRAINA_LOOP_TOO_LONG:
2506        br	r31, call_pal_halt
2507
2508// CALL_PAL OPCDECs
2509
2510        CALL_PAL_PRIV(0x0003)
2511CallPal_OpcDec03:
2512        br	r31, osfpal_calpal_opcdec
2513
2514        CALL_PAL_PRIV(0x0004)
2515CallPal_OpcDec04:
2516        br	r31, osfpal_calpal_opcdec
2517
2518        CALL_PAL_PRIV(0x0005)
2519CallPal_OpcDec05:
2520        br	r31, osfpal_calpal_opcdec
2521
2522        CALL_PAL_PRIV(0x0006)
2523CallPal_OpcDec06:
2524        br	r31, osfpal_calpal_opcdec
2525
2526        CALL_PAL_PRIV(0x0007)
2527CallPal_OpcDec07:
2528        br	r31, osfpal_calpal_opcdec
2529
2530        CALL_PAL_PRIV(0x0008)
2531CallPal_OpcDec08:
2532        br	r31, osfpal_calpal_opcdec
2533
2534//
2535// CSERVE - PALcode for CSERVE instruction
2536//
2537// Entry:
2538//	Vectored into via hardware PALcode instruction dispatch.
2539//
2540// Function:
2541//       Various functions for private use of console software
2542//
2543//       option selector in r0
2544//       arguments in r16....
2545//	The CSERVE routine is in the system specific module.
2546//
2547//
2548
2549        CALL_PAL_PRIV(PAL_CSERVE_ENTRY)
2550Call_Pal_Cserve:
2551        br	r31, sys_cserve
2552
2553//
2554// swppal - PALcode for swppal instruction
2555//
2556// Entry:
2557//	Vectored into via hardware PALcode instruction dispatch.
2558//       Vectored into via hardware PALcode instruction dispatch.
2559//               R16 contains the new PAL identifier
2560//               R17:R21 contain implementation-specific entry parameters
2561//
2562//               R0  receives status:
2563//                0 success (PAL was switched)
2564//                1 unknown PAL variant
2565//                2 known PAL variant, but PAL not loaded
2566//
2567//
2568// Function:
2569//       Swap control to another PAL.
2570//
2571
2572        CALL_PAL_PRIV(PAL_SWPPAL_ENTRY)
2573Call_Pal_Swppal:
2574        cmpule	r16, 255, r0		// see if a kibble was passed
2575        cmoveq  r16, r16, r0            // if r16=0 then a valid address (ECO 59)
2576
2577        or	r16, r31, r3		// set r3 incase this is a address
2578        blbc	r0, swppal_cont		// nope, try it as an address
2579
2580        cmpeq	r16, 2, r0		// is it our friend OSF?
2581        blbc	r0, swppal_fail		// nope, don't know this fellow
2582
2583        br	r2, CALL_PAL_SWPPAL_10_			// tis our buddy OSF
2584
2585//	.global	osfpal_hw_entry_reset
2586//	.weak	osfpal_hw_entry_reset
2587//	.long	<osfpal_hw_entry_reset-pal_start>
2588//orig	halt				// don't know how to get the address here - kludge ok, load pal at 0
2589        .long	0			// ?? hack upon hack...pb
2590
2591CALL_PAL_SWPPAL_10_: 	ldl_p	r3, 0(r2)		// fetch target addr
2592//	ble	r3, swppal_fail		; if OSF not linked in say not loaded.
2593        mfpr	r2, pal_base		// fetch pal base
2594
2595        addq	r2, r3, r3		// add pal base
2596        lda	r2, 0x3FFF(r31)		// get pal base checker mask
2597
2598        and	r3, r2, r2		// any funky bits set?
2599        cmpeq	r2, 0, r0		//
2600
2601        blbc	r0, swppal_fail		// return unknown if bad bit set.
2602        br	r31, swppal_cont
2603
2604// .sbttl	"CALL_PAL OPCDECs"
2605
2606        CALL_PAL_PRIV(0x000B)
2607CallPal_OpcDec0B:
2608        br	r31, osfpal_calpal_opcdec
2609
2610        CALL_PAL_PRIV(0x000C)
2611CallPal_OpcDec0C:
2612        br	r31, osfpal_calpal_opcdec
2613
2614//
2615// wripir - PALcode for wripir instruction
2616//
2617// Entry:
2618//	Vectored into via hardware PALcode instruction dispatch.
2619//	r16 = processor number to interrupt
2620//
2621// Function:
2622//	IPIR	<- R16
2623//	Handled in system-specific code
2624//
2625// Exit:
2626//	interprocessor interrupt is recorded on the target processor
2627//	and is initiated when the proper enabling conditions are present.
2628//
2629
2630        CALL_PAL_PRIV(PAL_WRIPIR_ENTRY)
2631Call_Pal_Wrpir:
2632        br	r31, sys_wripir
2633
2634// .sbttl	"CALL_PAL OPCDECs"
2635
2636        CALL_PAL_PRIV(0x000E)
2637CallPal_OpcDec0E:
2638        br	r31, osfpal_calpal_opcdec
2639
2640        CALL_PAL_PRIV(0x000F)
2641CallPal_OpcDec0F:
2642        br	r31, osfpal_calpal_opcdec
2643
2644//
2645// rdmces - PALcode for rdmces instruction
2646//
2647// Entry:
2648//	Vectored into via hardware PALcode instruction dispatch.
2649//
2650// Function:
2651//	R0 <- ZEXT(MCES)
2652//
2653
2654        CALL_PAL_PRIV(PAL_RDMCES_ENTRY)
2655Call_Pal_Rdmces:
2656        mfpr	r0, pt_mces		// Read from PALtemp
2657        and	r0, mces_m_all, r0	// Clear other bits
2658
2659        hw_rei
2660
2661//
2662// wrmces - PALcode for wrmces instruction
2663//
2664// Entry:
2665//	Vectored into via hardware PALcode instruction dispatch.
2666//
2667// Function:
2668//	If {R16<0> EQ 1} then MCES<0> <- 0 (MCHK)
2669//	If {R16<1> EQ 1} then MCES<1> <- 0 (SCE)
2670//	If {R16<2> EQ 1} then MCES<2> <- 0 (PCE)
2671//	MCES<3> <- R16<3>		   (DPC)
2672//	MCES<4> <- R16<4>		   (DSC)
2673//
2674//
2675
2676        CALL_PAL_PRIV(PAL_WRMCES_ENTRY)
2677Call_Pal_Wrmces:
2678        and	r16, ((1<<mces_v_mchk) | (1<<mces_v_sce) | (1<<mces_v_pce)), r13	// Isolate MCHK, SCE, PCE
2679        mfpr	r14, pt_mces		// Get current value
2680
2681        ornot	r31, r13, r13		// Flip all the bits
2682        and	r16, ((1<<mces_v_dpc) | (1<<mces_v_dsc)), r17
2683
2684        and	r14, r13, r1		// Update MCHK, SCE, PCE
2685        bic	r1, ((1<<mces_v_dpc) | (1<<mces_v_dsc)), r1	// Clear old DPC, DSC
2686
2687        or	r1, r17, r1		// Update DPC and DSC
2688        mtpr	r1, pt_mces		// Write MCES back
2689
2690        nop				// Pad to fix PT write->read restriction
2691
2692        nop
2693        hw_rei
2694
2695
2696
2697// CALL_PAL OPCDECs
2698
2699        CALL_PAL_PRIV(0x0012)
2700CallPal_OpcDec12:
2701        br	r31, osfpal_calpal_opcdec
2702
2703        CALL_PAL_PRIV(0x0013)
2704CallPal_OpcDec13:
2705        br	r31, osfpal_calpal_opcdec
2706
2707        CALL_PAL_PRIV(0x0014)
2708CallPal_OpcDec14:
2709        br	r31, osfpal_calpal_opcdec
2710
2711        CALL_PAL_PRIV(0x0015)
2712CallPal_OpcDec15:
2713        br	r31, osfpal_calpal_opcdec
2714
2715        CALL_PAL_PRIV(0x0016)
2716CallPal_OpcDec16:
2717        br	r31, osfpal_calpal_opcdec
2718
2719        CALL_PAL_PRIV(0x0017)
2720CallPal_OpcDec17:
2721        br	r31, osfpal_calpal_opcdec
2722
2723        CALL_PAL_PRIV(0x0018)
2724CallPal_OpcDec18:
2725        br	r31, osfpal_calpal_opcdec
2726
2727        CALL_PAL_PRIV(0x0019)
2728CallPal_OpcDec19:
2729        br	r31, osfpal_calpal_opcdec
2730
2731        CALL_PAL_PRIV(0x001A)
2732CallPal_OpcDec1A:
2733        br	r31, osfpal_calpal_opcdec
2734
2735        CALL_PAL_PRIV(0x001B)
2736CallPal_OpcDec1B:
2737        br	r31, osfpal_calpal_opcdec
2738
2739        CALL_PAL_PRIV(0x001C)
2740CallPal_OpcDec1C:
2741        br	r31, osfpal_calpal_opcdec
2742
2743        CALL_PAL_PRIV(0x001D)
2744CallPal_OpcDec1D:
2745        br	r31, osfpal_calpal_opcdec
2746
2747        CALL_PAL_PRIV(0x001E)
2748CallPal_OpcDec1E:
2749        br	r31, osfpal_calpal_opcdec
2750
2751        CALL_PAL_PRIV(0x001F)
2752CallPal_OpcDec1F:
2753        br	r31, osfpal_calpal_opcdec
2754
2755        CALL_PAL_PRIV(0x0020)
2756CallPal_OpcDec20:
2757        br	r31, osfpal_calpal_opcdec
2758
2759        CALL_PAL_PRIV(0x0021)
2760CallPal_OpcDec21:
2761        br	r31, osfpal_calpal_opcdec
2762
2763        CALL_PAL_PRIV(0x0022)
2764CallPal_OpcDec22:
2765        br	r31, osfpal_calpal_opcdec
2766
2767        CALL_PAL_PRIV(0x0023)
2768CallPal_OpcDec23:
2769        br	r31, osfpal_calpal_opcdec
2770
2771        CALL_PAL_PRIV(0x0024)
2772CallPal_OpcDec24:
2773        br	r31, osfpal_calpal_opcdec
2774
2775        CALL_PAL_PRIV(0x0025)
2776CallPal_OpcDec25:
2777        br	r31, osfpal_calpal_opcdec
2778
2779        CALL_PAL_PRIV(0x0026)
2780CallPal_OpcDec26:
2781        br	r31, osfpal_calpal_opcdec
2782
2783        CALL_PAL_PRIV(0x0027)
2784CallPal_OpcDec27:
2785        br	r31, osfpal_calpal_opcdec
2786
2787        CALL_PAL_PRIV(0x0028)
2788CallPal_OpcDec28:
2789        br	r31, osfpal_calpal_opcdec
2790
2791        CALL_PAL_PRIV(0x0029)
2792CallPal_OpcDec29:
2793        br	r31, osfpal_calpal_opcdec
2794
2795        CALL_PAL_PRIV(0x002A)
2796CallPal_OpcDec2A:
2797        br	r31, osfpal_calpal_opcdec
2798
2799//
2800// wrfen - PALcode for wrfen instruction
2801//
2802// Entry:
2803//	Vectored into via hardware PALcode instruction dispatch.
2804//
2805// Function:
2806//	a0<0> -> ICSR<FPE>
2807//	Store new FEN in PCB
2808//	Final value of t0 (r1), t8..t10 (r22..r24) and a0 (r16)
2809//          are UNPREDICTABLE
2810//
2811// Issue: What about pending FP loads when FEN goes from on->off????
2812//
2813
2814        CALL_PAL_PRIV(PAL_WRFEN_ENTRY)
2815Call_Pal_Wrfen:
2816        or	r31, 1, r13		// Get a one
2817        mfpr	r1, ev5__icsr		// Get current FPE
2818
2819        sll	r13, icsr_v_fpe, r13	// shift 1 to icsr<fpe> spot, e0
2820        and	r16, 1, r16		// clean new fen
2821
2822        sll	r16, icsr_v_fpe, r12	// shift new fen to correct bit position
2823        bic	r1, r13, r1		// zero icsr<fpe>
2824
2825        or	r1, r12, r1		// Or new FEN into ICSR
2826        mfpr	r12, pt_pcbb		// Get PCBB - E1
2827
2828        mtpr	r1, ev5__icsr		// write new ICSR.  3 Bubble cycles to HW_REI
2829        stl_p	r16, osfpcb_q_fen(r12)	// Store FEN in PCB.
2830
2831        mfpr	r31, pt0		// Pad ICSR<FPE> write.
2832        mfpr	r31, pt0
2833
2834        mfpr	r31, pt0
2835//	pvc_violate 	225		// cuz PVC can't distinguish which bits changed
2836        hw_rei
2837
2838
2839        CALL_PAL_PRIV(0x002C)
2840CallPal_OpcDec2C:
2841        br	r31, osfpal_calpal_opcdec
2842
2843//
2844// wrvptpr - PALcode for wrvptpr instruction
2845//
2846// Entry:
2847//	Vectored into via hardware PALcode instruction dispatch.
2848//
2849// Function:
2850//	vptptr <- a0 (r16)
2851//
2852
2853        CALL_PAL_PRIV(PAL_WRVPTPTR_ENTRY)
2854Call_Pal_Wrvptptr:
2855        mtpr    r16, ev5__mvptbr                // Load Mbox copy
2856        mtpr    r16, ev5__ivptbr                // Load Ibox copy
2857        nop                                     // Pad IPR write
2858        nop
2859        hw_rei
2860
2861        CALL_PAL_PRIV(0x002E)
2862CallPal_OpcDec2E:
2863        br	r31, osfpal_calpal_opcdec
2864
2865        CALL_PAL_PRIV(0x002F)
2866CallPal_OpcDec2F:
2867        br	r31, osfpal_calpal_opcdec
2868
2869
2870//
2871// swpctx - PALcode for swpctx instruction
2872//
2873// Entry:
2874//       hardware dispatch via callPal instruction
2875//       R16 -> new pcb
2876//
2877// Function:
2878//       dynamic state moved to old pcb
2879//       new state loaded from new pcb
2880//       pcbb pointer set
2881//       old pcbb returned in R0
2882//
2883//  Note: need to add perf monitor stuff
2884//
2885
2886        CALL_PAL_PRIV(PAL_SWPCTX_ENTRY)
2887Call_Pal_Swpctx:
2888        rpcc	r13			// get cyccounter
2889        mfpr	r0, pt_pcbb		// get pcbb
2890
2891        ldq_p	r22, osfpcb_q_fen(r16)	// get new fen/pme
2892        ldq_p	r23, osfpcb_l_cc(r16)	// get new asn
2893
2894        srl	r13, 32, r25		// move offset
2895        mfpr	r24, pt_usp		// get usp
2896
2897        stq_p	r30, osfpcb_q_ksp(r0)	// store old ksp
2898//	pvc_violate 379			// stq_p can't trap except replay.  only problem if mf same ipr in same shadow.
2899        mtpr	r16, pt_pcbb		// set new pcbb
2900
2901        stq_p	r24, osfpcb_q_usp(r0)	// store usp
2902        addl	r13, r25, r25		// merge for new time
2903
2904        stl_p	r25, osfpcb_l_cc(r0)	// save time
2905        ldah	r24, (1<<(icsr_v_fpe-16))(r31)
2906
2907        and	r22, 1, r12		// isolate fen
2908        mfpr	r25, icsr		// get current icsr
2909
2910        lda	r24, (1<<icsr_v_pmp)(r24)
2911        br	r31, swpctx_cont
2912
2913//
2914// wrval - PALcode for wrval instruction
2915//
2916// Entry:
2917//	Vectored into via hardware PALcode instruction dispatch.
2918//
2919// Function:
2920//	sysvalue <- a0 (r16)
2921//
2922
2923        CALL_PAL_PRIV(PAL_WRVAL_ENTRY)
2924Call_Pal_Wrval:
2925        nop
2926        mtpr	r16, pt_sysval		// Pad paltemp write
2927        nop
2928        nop
2929        hw_rei
2930
2931//
2932// rdval - PALcode for rdval instruction
2933//
2934// Entry:
2935//	Vectored into via hardware PALcode instruction dispatch.
2936//
2937// Function:
2938//	v0 (r0) <- sysvalue
2939//
2940
2941        CALL_PAL_PRIV(PAL_RDVAL_ENTRY)
2942Call_Pal_Rdval:
2943        nop
2944        mfpr	r0, pt_sysval
2945        nop
2946        hw_rei
2947
2948//
2949// tbi - PALcode for tbi instruction
2950//
2951// Entry:
2952//	Vectored into via hardware PALcode instruction dispatch.
2953//
2954// Function:
2955//	TB invalidate
2956//       r16/a0 = TBI type
2957//       r17/a1 = Va for TBISx instructions
2958//
2959
2960        CALL_PAL_PRIV(PAL_TBI_ENTRY)
2961Call_Pal_Tbi:
2962        addq	r16, 2, r16			// change range to 0-2
2963        br	r23, CALL_PAL_tbi_10_		// get our address
2964
2965CALL_PAL_tbi_10_: cmpult	r16, 6, r22		// see if in range
2966        lda	r23, tbi_tbl-CALL_PAL_tbi_10_(r23)	// set base to start of table
2967        sll	r16, 4, r16		// * 16
2968        blbc	r22, CALL_PAL_tbi_30_		// go rei, if not
2969
2970        addq	r23, r16, r23		// addr of our code
2971//orig	pvc_jsr	tbi
2972        jmp	r31, (r23)		// and go do it
2973
2974CALL_PAL_tbi_30_:
2975        hw_rei
2976        nop
2977
2978//
2979// wrent - PALcode for wrent instruction
2980//
2981// Entry:
2982//	Vectored into via hardware PALcode instruction dispatch.
2983//
2984// Function:
2985//	Update ent* in paltemps
2986//       r16/a0 = Address of entry routine
2987//       r17/a1 = Entry Number 0..5
2988//
2989//       r22, r23 trashed
2990//
2991
2992        CALL_PAL_PRIV(PAL_WRENT_ENTRY)
2993Call_Pal_Wrent:
2994        cmpult	r17, 6, r22			// see if in range
2995        br	r23, CALL_PAL_wrent_10_		// get our address
2996
2997CALL_PAL_wrent_10_:	bic	r16, 3, r16	// clean pc
2998        blbc	r22, CALL_PAL_wrent_30_		// go rei, if not in range
2999
3000        lda	r23, wrent_tbl-CALL_PAL_wrent_10_(r23)	// set base to start of table
3001        sll	r17, 4, r17				// *16
3002
3003        addq  	r17, r23, r23		// Get address in table
3004//orig	pvc_jsr	wrent
3005        jmp	r31, (r23)		// and go do it
3006
3007CALL_PAL_wrent_30_:
3008        hw_rei				// out of range, just return
3009
3010//
3011// swpipl - PALcode for swpipl instruction
3012//
3013// Entry:
3014//	Vectored into via hardware PALcode instruction dispatch.
3015//
3016// Function:
3017//	v0 (r0)  <- PS<IPL>
3018//	PS<IPL>  <- a0<2:0>  (r16)
3019//
3020//	t8 (r22) is scratch
3021//
3022
3023        CALL_PAL_PRIV(PAL_SWPIPL_ENTRY)
3024Call_Pal_Swpipl:
3025        and	r16, osfps_m_ipl, r16	// clean New ipl
3026        mfpr	r22, pt_intmask		// get int mask
3027
3028        extbl	r22, r16, r22		// get mask for this ipl
3029        bis	r11, r31, r0		// return old ipl
3030
3031        bis	r16, r31, r11		// set new ps
3032        mtpr	r22, ev5__ipl		// set new mask
3033
3034        mfpr	r31, pt0		// pad ipl write
3035        mfpr	r31, pt0		// pad ipl write
3036
3037        hw_rei				// back
3038
3039//
3040// rdps - PALcode for rdps instruction
3041//
3042// Entry:
3043//	Vectored into via hardware PALcode instruction dispatch.
3044//
3045// Function:
3046//	v0 (r0) <- ps
3047//
3048
3049        CALL_PAL_PRIV(PAL_RDPS_ENTRY)
3050Call_Pal_Rdps:
3051        bis	r11, r31, r0		// Fetch PALshadow PS
3052        nop				// Must be 2 cycles long
3053        hw_rei
3054
3055//
3056// wrkgp - PALcode for wrkgp instruction
3057//
3058// Entry:
3059//	Vectored into via hardware PALcode instruction dispatch.
3060//
3061// Function:
3062//	kgp <- a0 (r16)
3063//
3064
3065        CALL_PAL_PRIV(PAL_WRKGP_ENTRY)
3066Call_Pal_Wrkgp:
3067        nop
3068        mtpr	r16, pt_kgp
3069        nop				// Pad for pt write->read restriction
3070        nop
3071        hw_rei
3072
3073//
3074// wrusp - PALcode for wrusp instruction
3075//
3076// Entry:
3077//	Vectored into via hardware PALcode instruction dispatch.
3078//
3079// Function:
3080//       usp <- a0 (r16)
3081//
3082
3083        CALL_PAL_PRIV(PAL_WRUSP_ENTRY)
3084Call_Pal_Wrusp:
3085        nop
3086        mtpr	r16, pt_usp
3087        nop				// Pad possible pt write->read restriction
3088        nop
3089        hw_rei
3090
3091//
3092// wrperfmon - PALcode for wrperfmon instruction
3093//
3094// Entry:
3095//	Vectored into via hardware PALcode instruction dispatch.
3096//
3097//
3098// Function:
3099//	Various control functions for the onchip performance counters
3100//
3101//	option selector in r16
3102//	option argument in r17
3103//	returned status in r0
3104//
3105//
3106//	r16 = 0	Disable performance monitoring for one or more cpu's
3107//	  r17 = 0		disable no counters
3108//	  r17 = bitmask		disable counters specified in bit mask (1=disable)
3109//
3110//	r16 = 1	Enable performance monitoring for one or more cpu's
3111//	  r17 = 0		enable no counters
3112//	  r17 = bitmask		enable counters specified in bit mask (1=enable)
3113//
3114//	r16 = 2	Mux select for one or more cpu's
3115//	  r17 = Mux selection (cpu specific)
3116//    		<24:19>  	 bc_ctl<pm_mux_sel> field (see spec)
3117//		<31>,<7:4>,<3:0> pmctr <sel0>,<sel1>,<sel2> fields (see spec)
3118//
3119//	r16 = 3	Options
3120//	  r17 = (cpu specific)
3121//		<0> = 0 	log all processes
3122//		<0> = 1		log only selected processes
3123//		<30,9,8> 		mode select - ku,kp,kk
3124//
3125//	r16 = 4	Interrupt frequency select
3126//	  r17 = (cpu specific)	indicates interrupt frequencies desired for each
3127//				counter, with "zero interrupts" being an option
3128//				frequency info in r17 bits as defined by PMCTR_CTL<FRQx> below
3129//
3130//	r16 = 5	Read Counters
3131//	  r17 = na
3132//	  r0  = value (same format as ev5 pmctr)
3133//	        <0> = 0		Read failed
3134//	        <0> = 1		Read succeeded
3135//
3136//	r16 = 6	Write Counters
3137//	  r17 = value (same format as ev5 pmctr; all counters written simultaneously)
3138//
3139//	r16 = 7	Enable performance monitoring for one or more cpu's and reset counter to 0
3140//	  r17 = 0		enable no counters
3141//	  r17 = bitmask		enable & clear counters specified in bit mask (1=enable & clear)
3142//
3143//=============================================================================
3144//Assumptions:
3145//PMCTR_CTL:
3146//
3147//       <15:14>         CTL0 -- encoded frequency select and enable - CTR0
3148//       <13:12>         CTL1 --			"		   - CTR1
3149//       <11:10>         CTL2 --			"		   - CTR2
3150//
3151//       <9:8>           FRQ0 -- frequency select for CTR0 (no enable info)
3152//       <7:6>           FRQ1 -- frequency select for CTR1
3153//       <5:4>           FRQ2 -- frequency select for CTR2
3154//
3155//       <0>		all vs. select processes (0=all,1=select)
3156//
3157//     where
3158//	FRQx<1:0>
3159//	     0 1	disable interrupt
3160//	     1 0	frequency = 65536 (16384 for ctr2)
3161//	     1 1	frequency = 256
3162//	note:  FRQx<1:0> = 00 will keep counters from ever being enabled.
3163//
3164//=============================================================================
3165//
3166        CALL_PAL_PRIV(0x0039)
3167// unsupported in Hudson code .. pboyle Nov/95
3168CALL_PAL_Wrperfmon:
3169        // "real" performance monitoring code
3170        cmpeq	r16, 1, r0		// check for enable
3171        bne	r0, perfmon_en		// br if requested to enable
3172
3173        cmpeq	r16, 2, r0		// check for mux ctl
3174        bne	r0, perfmon_muxctl	// br if request to set mux controls
3175
3176        cmpeq	r16, 3, r0		// check for options
3177        bne	r0, perfmon_ctl		// br if request to set options
3178
3179        cmpeq	r16, 4, r0		// check for interrupt frequency select
3180        bne	r0, perfmon_freq	// br if request to change frequency select
3181
3182        cmpeq	r16, 5, r0		// check for counter read request
3183        bne	r0, perfmon_rd		// br if request to read counters
3184
3185        cmpeq	r16, 6, r0		// check for counter write request
3186        bne	r0, perfmon_wr		// br if request to write counters
3187
3188        cmpeq	r16, 7, r0		// check for counter clear/enable request
3189        bne	r0, perfmon_enclr	// br if request to clear/enable counters
3190
3191        beq	r16, perfmon_dis	// br if requested to disable (r16=0)
3192        br	r31, perfmon_unknown	// br if unknown request
3193
3194//
3195// rdusp - PALcode for rdusp instruction
3196//
3197// Entry:
3198//	Vectored into via hardware PALcode instruction dispatch.
3199//
3200// Function:
3201//	v0 (r0) <- usp
3202//
3203
3204        CALL_PAL_PRIV(PAL_RDUSP_ENTRY)
3205Call_Pal_Rdusp:
3206        nop
3207        mfpr	r0, pt_usp
3208        hw_rei
3209
3210
3211        CALL_PAL_PRIV(0x003B)
3212CallPal_OpcDec3B:
3213        br	r31, osfpal_calpal_opcdec
3214
3215//
3216// whami - PALcode for whami instruction
3217//
3218// Entry:
3219//	Vectored into via hardware PALcode instruction dispatch.
3220//
3221// Function:
3222//	v0 (r0) <- whami
3223//
3224        CALL_PAL_PRIV(PAL_WHAMI_ENTRY)
3225Call_Pal_Whami:
3226        nop
3227        mfpr    r0, pt_whami            // Get Whami
3228        extbl	r0, 1, r0		// Isolate just whami bits
3229        hw_rei
3230
3231//
3232// retsys - PALcode for retsys instruction
3233//
3234// Entry:
3235//	Vectored into via hardware PALcode instruction dispatch.
3236//       00(sp) contains return pc
3237//       08(sp) contains r29
3238//
3239// Function:
3240//	Return from system call.
3241//       mode switched from kern to user.
3242//       stacks swapped, ugp, upc restored.
3243//       r23, r25 junked
3244//
3245
3246        CALL_PAL_PRIV(PAL_RETSYS_ENTRY)
3247Call_Pal_Retsys:
3248        lda	r25, osfsf_c_size(sp) 	// pop stack
3249        bis	r25, r31, r14		// touch r25 & r14 to stall mf exc_addr
3250
3251        mfpr	r14, exc_addr		// save exc_addr in case of fault
3252        ldq	r23, osfsf_pc(sp) 	// get pc
3253
3254        ldq	r29, osfsf_gp(sp) 	// get gp
3255        stl_c	r31, -4(sp)		// clear lock_flag
3256
3257        lda	r11, 1<<osfps_v_mode(r31)// new PS:mode=user
3258        mfpr	r30, pt_usp		// get users stack
3259
3260        bic	r23, 3, r23		// clean return pc
3261        mtpr	r31, ev5__ipl		// zero ibox IPL - 2 bubbles to hw_rei
3262
3263        mtpr	r11, ev5__dtb_cm	// set Mbox current mode - no virt ref for 2 cycles
3264        mtpr	r11, ev5__ps		// set Ibox current mode - 2 bubble to hw_rei
3265
3266        mtpr	r23, exc_addr		// set return address - 1 bubble to hw_rei
3267        mtpr	r25, pt_ksp		// save kern stack
3268
3269        rc	r31			// clear inter_flag
3270//	pvc_violate 248			// possible hidden mt->mf pt violation ok in callpal
3271        hw_rei_spe			// and back
3272
3273
3274        CALL_PAL_PRIV(0x003E)
3275CallPal_OpcDec3E:
3276        br	r31, osfpal_calpal_opcdec
3277
3278//
3279// rti - PALcode for rti instruction
3280//
3281// Entry:
3282//	Vectored into via hardware PALcode instruction dispatch.
3283//
3284// Function:
3285//	00(sp) -> ps
3286//	08(sp) -> pc
3287//	16(sp) -> r29 (gp)
3288//	24(sp) -> r16 (a0)
3289//	32(sp) -> r17 (a1)
3290//	40(sp) -> r18 (a3)
3291//
3292
3293        CALL_PAL_PRIV(PAL_RTI_ENTRY)
3294        /* called once by platform_tlaser */
3295        .globl Call_Pal_Rti
3296Call_Pal_Rti:
3297        lda	r25, osfsf_c_size(sp)	// get updated sp
3298        bis	r25, r31, r14		// touch r14,r25 to stall mf exc_addr
3299
3300        mfpr	r14, exc_addr		// save PC in case of fault
3301        rc	r31			// clear intr_flag
3302
3303        ldq	r12, -6*8(r25)		// get ps
3304        ldq	r13, -5*8(r25)		// pc
3305
3306        ldq	r18, -1*8(r25)		// a2
3307        ldq	r17, -2*8(r25)		// a1
3308
3309        ldq	r16, -3*8(r25)		// a0
3310        ldq	r29, -4*8(r25)		// gp
3311
3312        bic	r13, 3, r13		// clean return pc
3313        stl_c	r31, -4(r25)		// clear lock_flag
3314
3315        and	r12, osfps_m_mode, r11	// get mode
3316        mtpr	r13, exc_addr		// set return address
3317
3318        beq	r11, rti_to_kern	// br if rti to Kern
3319        br	r31, rti_to_user	// out of call_pal space
3320
3321
3322///////////////////////////////////////////////////
3323// Start the Unprivileged CALL_PAL Entry Points
3324///////////////////////////////////////////////////
3325
3326//
3327// bpt - PALcode for bpt instruction
3328//
3329// Entry:
3330//	Vectored into via hardware PALcode instruction dispatch.
3331//
3332// Function:
3333//	Build stack frame
3334//	a0 <- code
3335//	a1 <- unpred
3336//	a2 <- unpred
3337//	vector via entIF
3338//
3339//
3340//
3341        .text	1
3342//	. = 0x3000
3343        CALL_PAL_UNPRIV(PAL_BPT_ENTRY)
3344Call_Pal_Bpt:
3345        sll	r11, 63-osfps_v_mode, r25 // Shift mode up to MS bit
3346        mtpr	r31, ev5__ps		// Set Ibox current mode to kernel
3347
3348        bis	r11, r31, r12		// Save PS for stack write
3349        bge	r25, CALL_PAL_bpt_10_		// no stack swap needed if cm=kern
3350
3351        mtpr	r31, ev5__dtb_cm	// Set Mbox current mode to kernel -
3352                                        //     no virt ref for next 2 cycles
3353        mtpr	r30, pt_usp		// save user stack
3354
3355        bis	r31, r31, r11		// Set new PS
3356        mfpr	r30, pt_ksp
3357
3358CALL_PAL_bpt_10_:
3359        lda	sp, 0-osfsf_c_size(sp)// allocate stack space
3360        mfpr	r14, exc_addr		// get pc
3361
3362        stq	r16, osfsf_a0(sp)	// save regs
3363        bis	r31, osf_a0_bpt, r16	// set a0
3364
3365        stq	r17, osfsf_a1(sp)	// a1
3366        br	r31, bpt_bchk_common	// out of call_pal space
3367
3368
3369//
3370// bugchk - PALcode for bugchk instruction
3371//
3372// Entry:
3373//	Vectored into via hardware PALcode instruction dispatch.
3374//
3375// Function:
3376//	Build stack frame
3377//	a0 <- code
3378//	a1 <- unpred
3379//	a2 <- unpred
3380//	vector via entIF
3381//
3382//
3383//
3384        CALL_PAL_UNPRIV(PAL_BUGCHK_ENTRY)
3385Call_Pal_Bugchk:
3386        sll	r11, 63-osfps_v_mode, r25 // Shift mode up to MS bit
3387        mtpr	r31, ev5__ps		// Set Ibox current mode to kernel
3388
3389        bis	r11, r31, r12		// Save PS for stack write
3390        bge	r25, CALL_PAL_bugchk_10_		// no stack swap needed if cm=kern
3391
3392        mtpr	r31, ev5__dtb_cm	// Set Mbox current mode to kernel -
3393                                        //     no virt ref for next 2 cycles
3394        mtpr	r30, pt_usp		// save user stack
3395
3396        bis	r31, r31, r11		// Set new PS
3397        mfpr	r30, pt_ksp
3398
3399CALL_PAL_bugchk_10_:
3400        lda	sp, 0-osfsf_c_size(sp)// allocate stack space
3401        mfpr	r14, exc_addr		// get pc
3402
3403        stq	r16, osfsf_a0(sp)	// save regs
3404        bis	r31, osf_a0_bugchk, r16	// set a0
3405
3406        stq	r17, osfsf_a1(sp)	// a1
3407        br	r31, bpt_bchk_common	// out of call_pal space
3408
3409
3410        CALL_PAL_UNPRIV(0x0082)
3411CallPal_OpcDec82:
3412        br	r31, osfpal_calpal_opcdec
3413
3414//
3415// callsys - PALcode for callsys instruction
3416//
3417// Entry:
3418//	Vectored into via hardware PALcode instruction dispatch.
3419//
3420// Function:
3421// 	Switch mode to kernel and build a callsys stack frame.
3422//       sp = ksp
3423//       gp = kgp
3424//	t8 - t10 (r22-r24) trashed
3425//
3426//
3427//
3428        CALL_PAL_UNPRIV(PAL_CALLSYS_ENTRY)
3429Call_Pal_Callsys:
3430
3431        and	r11, osfps_m_mode, r24	// get mode
3432        mfpr	r22, pt_ksp		// get ksp
3433
3434        beq	r24, sys_from_kern 	// sysCall from kern is not allowed
3435        mfpr	r12, pt_entsys		// get address of callSys routine
3436
3437//
3438// from here on we know we are in user going to Kern
3439//
3440        mtpr	r31, ev5__dtb_cm	// set Mbox current mode - no virt ref for 2 cycles
3441        mtpr	r31, ev5__ps		// set Ibox current mode - 2 bubble to hw_rei
3442
3443        bis	r31, r31, r11		// PS=0 (mode=kern)
3444        mfpr	r23, exc_addr		// get pc
3445
3446        mtpr	r30, pt_usp		// save usp
3447        lda	sp, 0-osfsf_c_size(r22)// set new sp
3448
3449        stq	r29, osfsf_gp(sp)	// save user gp/r29
3450        stq	r24, osfsf_ps(sp)	// save ps
3451
3452        stq	r23, osfsf_pc(sp)	// save pc
3453        mtpr	r12, exc_addr		// set address
3454                                        // 1 cycle to hw_rei
3455
3456        mfpr	r29, pt_kgp		// get the kern gp/r29
3457
3458        hw_rei_spe			// and off we go!
3459
3460
3461        CALL_PAL_UNPRIV(0x0084)
3462CallPal_OpcDec84:
3463        br	r31, osfpal_calpal_opcdec
3464
3465        CALL_PAL_UNPRIV(0x0085)
3466CallPal_OpcDec85:
3467        br	r31, osfpal_calpal_opcdec
3468
3469//
3470// imb - PALcode for imb instruction
3471//
3472// Entry:
3473//	Vectored into via hardware PALcode instruction dispatch.
3474//
3475// Function:
3476//       Flush the writebuffer and flush the Icache
3477//
3478//
3479//
3480        CALL_PAL_UNPRIV(PAL_IMB_ENTRY)
3481Call_Pal_Imb:
3482        mb                              // Clear the writebuffer
3483        mfpr    r31, ev5__mcsr          // Sync with clear
3484        nop
3485        nop
3486        br      r31, pal_ic_flush           // Flush Icache
3487
3488
3489// CALL_PAL OPCDECs
3490
3491        CALL_PAL_UNPRIV(0x0087)
3492CallPal_OpcDec87:
3493        br	r31, osfpal_calpal_opcdec
3494
3495        CALL_PAL_UNPRIV(0x0088)
3496CallPal_OpcDec88:
3497        br	r31, osfpal_calpal_opcdec
3498
3499        CALL_PAL_UNPRIV(0x0089)
3500CallPal_OpcDec89:
3501        br	r31, osfpal_calpal_opcdec
3502
3503        CALL_PAL_UNPRIV(0x008A)
3504CallPal_OpcDec8A:
3505        br	r31, osfpal_calpal_opcdec
3506
3507        CALL_PAL_UNPRIV(0x008B)
3508CallPal_OpcDec8B:
3509        br	r31, osfpal_calpal_opcdec
3510
3511        CALL_PAL_UNPRIV(0x008C)
3512CallPal_OpcDec8C:
3513        br	r31, osfpal_calpal_opcdec
3514
3515        CALL_PAL_UNPRIV(0x008D)
3516CallPal_OpcDec8D:
3517        br	r31, osfpal_calpal_opcdec
3518
3519        CALL_PAL_UNPRIV(0x008E)
3520CallPal_OpcDec8E:
3521        br	r31, osfpal_calpal_opcdec
3522
3523        CALL_PAL_UNPRIV(0x008F)
3524CallPal_OpcDec8F:
3525        br	r31, osfpal_calpal_opcdec
3526
3527        CALL_PAL_UNPRIV(0x0090)
3528CallPal_OpcDec90:
3529        br	r31, osfpal_calpal_opcdec
3530
3531        CALL_PAL_UNPRIV(0x0091)
3532CallPal_OpcDec91:
3533        br	r31, osfpal_calpal_opcdec
3534
3535        CALL_PAL_UNPRIV(0x0092)
3536CallPal_OpcDec92:
3537        br	r31, osfpal_calpal_opcdec
3538
3539        CALL_PAL_UNPRIV(0x0093)
3540CallPal_OpcDec93:
3541        br	r31, osfpal_calpal_opcdec
3542
3543        CALL_PAL_UNPRIV(0x0094)
3544CallPal_OpcDec94:
3545        br	r31, osfpal_calpal_opcdec
3546
3547        CALL_PAL_UNPRIV(0x0095)
3548CallPal_OpcDec95:
3549        br	r31, osfpal_calpal_opcdec
3550
3551        CALL_PAL_UNPRIV(0x0096)
3552CallPal_OpcDec96:
3553        br	r31, osfpal_calpal_opcdec
3554
3555        CALL_PAL_UNPRIV(0x0097)
3556CallPal_OpcDec97:
3557        br	r31, osfpal_calpal_opcdec
3558
3559        CALL_PAL_UNPRIV(0x0098)
3560CallPal_OpcDec98:
3561        br	r31, osfpal_calpal_opcdec
3562
3563        CALL_PAL_UNPRIV(0x0099)
3564CallPal_OpcDec99:
3565        br	r31, osfpal_calpal_opcdec
3566
3567        CALL_PAL_UNPRIV(0x009A)
3568CallPal_OpcDec9A:
3569        br	r31, osfpal_calpal_opcdec
3570
3571        CALL_PAL_UNPRIV(0x009B)
3572CallPal_OpcDec9B:
3573        br	r31, osfpal_calpal_opcdec
3574
3575        CALL_PAL_UNPRIV(0x009C)
3576CallPal_OpcDec9C:
3577        br	r31, osfpal_calpal_opcdec
3578
3579        CALL_PAL_UNPRIV(0x009D)
3580CallPal_OpcDec9D:
3581        br	r31, osfpal_calpal_opcdec
3582
3583//
3584// rdunique - PALcode for rdunique instruction
3585//
3586// Entry:
3587//	Vectored into via hardware PALcode instruction dispatch.
3588//
3589// Function:
3590//	v0 (r0) <- unique
3591//
3592//
3593//
3594        CALL_PAL_UNPRIV(PAL_RDUNIQUE_ENTRY)
3595CALL_PALrdunique_:
3596        mfpr	r0, pt_pcbb		// get pcb pointer
3597        ldq_p	r0, osfpcb_q_unique(r0) // get new value
3598
3599        hw_rei
3600
3601//
3602// wrunique - PALcode for wrunique instruction
3603//
3604// Entry:
3605//	Vectored into via hardware PALcode instruction dispatch.
3606//
3607// Function:
3608//	unique <- a0 (r16)
3609//
3610//
3611//
3612CALL_PAL_UNPRIV(PAL_WRUNIQUE_ENTRY)
3613CALL_PAL_Wrunique:
3614        nop
3615        mfpr	r12, pt_pcbb		// get pcb pointer
3616        stq_p	r16, osfpcb_q_unique(r12)// get new value
3617        nop				// Pad palshadow write
3618        hw_rei				// back
3619
3620// CALL_PAL OPCDECs
3621
3622        CALL_PAL_UNPRIV(0x00A0)
3623CallPal_OpcDecA0:
3624        br	r31, osfpal_calpal_opcdec
3625
3626        CALL_PAL_UNPRIV(0x00A1)
3627CallPal_OpcDecA1:
3628        br	r31, osfpal_calpal_opcdec
3629
3630        CALL_PAL_UNPRIV(0x00A2)
3631CallPal_OpcDecA2:
3632        br	r31, osfpal_calpal_opcdec
3633
3634        CALL_PAL_UNPRIV(0x00A3)
3635CallPal_OpcDecA3:
3636        br	r31, osfpal_calpal_opcdec
3637
3638        CALL_PAL_UNPRIV(0x00A4)
3639CallPal_OpcDecA4:
3640        br	r31, osfpal_calpal_opcdec
3641
3642        CALL_PAL_UNPRIV(0x00A5)
3643CallPal_OpcDecA5:
3644        br	r31, osfpal_calpal_opcdec
3645
3646        CALL_PAL_UNPRIV(0x00A6)
3647CallPal_OpcDecA6:
3648        br	r31, osfpal_calpal_opcdec
3649
3650        CALL_PAL_UNPRIV(0x00A7)
3651CallPal_OpcDecA7:
3652        br	r31, osfpal_calpal_opcdec
3653
3654        CALL_PAL_UNPRIV(0x00A8)
3655CallPal_OpcDecA8:
3656        br	r31, osfpal_calpal_opcdec
3657
3658        CALL_PAL_UNPRIV(0x00A9)
3659CallPal_OpcDecA9:
3660        br	r31, osfpal_calpal_opcdec
3661
3662
3663//
3664// gentrap - PALcode for gentrap instruction
3665//
3666// CALL_PAL_gentrap:
3667// Entry:
3668//	Vectored into via hardware PALcode instruction dispatch.
3669//
3670// Function:
3671//	Build stack frame
3672//	a0 <- code
3673//	a1 <- unpred
3674//	a2 <- unpred
3675//	vector via entIF
3676//
3677//
3678
3679        CALL_PAL_UNPRIV(0x00AA)
3680// unsupported in Hudson code .. pboyle Nov/95
3681CALL_PAL_gentrap:
3682        sll	r11, 63-osfps_v_mode, r25 // Shift mode up to MS bit
3683        mtpr	r31, ev5__ps		// Set Ibox current mode to kernel
3684
3685        bis	r11, r31, r12			// Save PS for stack write
3686        bge	r25, CALL_PAL_gentrap_10_	// no stack swap needed if cm=kern
3687
3688        mtpr	r31, ev5__dtb_cm	// Set Mbox current mode to kernel -
3689                                        //     no virt ref for next 2 cycles
3690        mtpr	r30, pt_usp		// save user stack
3691
3692        bis	r31, r31, r11		// Set new PS
3693        mfpr	r30, pt_ksp
3694
3695CALL_PAL_gentrap_10_:
3696        lda	sp, 0-osfsf_c_size(sp)// allocate stack space
3697        mfpr	r14, exc_addr		// get pc
3698
3699        stq	r16, osfsf_a0(sp)	// save regs
3700        bis	r31, osf_a0_gentrap, r16// set a0
3701
3702        stq	r17, osfsf_a1(sp)	// a1
3703        br	r31, bpt_bchk_common	// out of call_pal space
3704
3705
3706// CALL_PAL OPCDECs
3707
3708        CALL_PAL_UNPRIV(0x00AB)
3709CallPal_OpcDecAB:
3710        br	r31, osfpal_calpal_opcdec
3711
3712        CALL_PAL_UNPRIV(0x00AC)
3713CallPal_OpcDecAC:
3714        br	r31, osfpal_calpal_opcdec
3715
3716        CALL_PAL_UNPRIV(0x00AD)
3717CallPal_OpcDecAD:
3718        br	r31, osfpal_calpal_opcdec
3719
3720        CALL_PAL_UNPRIV(0x00AE)
3721CallPal_OpcDecAE:
3722        br	r31, osfpal_calpal_opcdec
3723
3724        CALL_PAL_UNPRIV(0x00AF)
3725CallPal_OpcDecAF:
3726        br	r31, osfpal_calpal_opcdec
3727
3728        CALL_PAL_UNPRIV(0x00B0)
3729CallPal_OpcDecB0:
3730        br	r31, osfpal_calpal_opcdec
3731
3732        CALL_PAL_UNPRIV(0x00B1)
3733CallPal_OpcDecB1:
3734        br	r31, osfpal_calpal_opcdec
3735
3736        CALL_PAL_UNPRIV(0x00B2)
3737CallPal_OpcDecB2:
3738        br	r31, osfpal_calpal_opcdec
3739
3740        CALL_PAL_UNPRIV(0x00B3)
3741CallPal_OpcDecB3:
3742        br	r31, osfpal_calpal_opcdec
3743
3744        CALL_PAL_UNPRIV(0x00B4)
3745CallPal_OpcDecB4:
3746        br	r31, osfpal_calpal_opcdec
3747
3748        CALL_PAL_UNPRIV(0x00B5)
3749CallPal_OpcDecB5:
3750        br	r31, osfpal_calpal_opcdec
3751
3752        CALL_PAL_UNPRIV(0x00B6)
3753CallPal_OpcDecB6:
3754        br	r31, osfpal_calpal_opcdec
3755
3756        CALL_PAL_UNPRIV(0x00B7)
3757CallPal_OpcDecB7:
3758        br	r31, osfpal_calpal_opcdec
3759
3760        CALL_PAL_UNPRIV(0x00B8)
3761CallPal_OpcDecB8:
3762        br	r31, osfpal_calpal_opcdec
3763
3764        CALL_PAL_UNPRIV(0x00B9)
3765CallPal_OpcDecB9:
3766        br	r31, osfpal_calpal_opcdec
3767
3768        CALL_PAL_UNPRIV(0x00BA)
3769CallPal_OpcDecBA:
3770        br	r31, osfpal_calpal_opcdec
3771
3772        CALL_PAL_UNPRIV(0x00BB)
3773CallPal_OpcDecBB:
3774        br	r31, osfpal_calpal_opcdec
3775
3776        CALL_PAL_UNPRIV(0x00BC)
3777CallPal_OpcDecBC:
3778        br	r31, osfpal_calpal_opcdec
3779
3780        CALL_PAL_UNPRIV(0x00BD)
3781CallPal_OpcDecBD:
3782        br	r31, osfpal_calpal_opcdec
3783
3784        CALL_PAL_UNPRIV(0x00BE)
3785CallPal_OpcDecBE:
3786        br	r31, osfpal_calpal_opcdec
3787
3788        CALL_PAL_UNPRIV(0x00BF)
3789CallPal_OpcDecBF:
3790        // MODIFIED BY EGH 2/25/04
3791        br	r31, copypal_impl
3792
3793
3794/*======================================================================*/
3795/*                   OSF/1 CALL_PAL CONTINUATION AREA                   */
3796/*======================================================================*/
3797
3798        .text	2
3799
3800        . = 0x4000
3801
3802
3803// Continuation of MTPR_PERFMON
3804        ALIGN_BLOCK
3805          // "real" performance monitoring code
3806// mux ctl
3807perfmon_muxctl:
3808        lda     r8, 1(r31) 			// get a 1
3809        sll     r8, pmctr_v_sel0, r8		// move to sel0 position
3810        or      r8, ((0xf<<pmctr_v_sel1) | (0xf<<pmctr_v_sel2)), r8	// build mux select mask
3811        and	r17, r8, r25			// isolate pmctr mux select bits
3812        mfpr	r0, ev5__pmctr
3813        bic	r0, r8, r0			// clear old mux select bits
3814        or	r0,r25, r25			// or in new mux select bits
3815        mtpr	r25, ev5__pmctr
3816
3817        // ok, now tackle cbox mux selects
3818        ldah    r14, 0xfff0(r31)
3819        zap     r14, 0xE0, r14                 // Get Cbox IPR base
3820//orig	get_bc_ctl_shadow	r16		// bc_ctl returned in lower longword
3821// adapted from ev5_pal_macros.mar
3822        mfpr	r16, pt_impure
3823        lda	r16, CNS_Q_IPR(r16)
3824        RESTORE_SHADOW(r16,CNS_Q_BC_CTL,r16);
3825
3826        lda	r8, 0x3F(r31)			// build mux select mask
3827        sll	r8, bc_ctl_v_pm_mux_sel, r8
3828
3829        and	r17, r8, r25			// isolate bc_ctl mux select bits
3830        bic	r16, r8, r16			// isolate old mux select bits
3831        or	r16, r25, r25			// create new bc_ctl
3832        mb					// clear out cbox for future ipr write
3833        stq_p	r25, ev5__bc_ctl(r14)		// store to cbox ipr
3834        mb					// clear out cbox for future ipr write
3835
3836//orig	update_bc_ctl_shadow	r25, r16	// r25=value, r16-overwritten with adjusted impure ptr
3837// adapted from ev5_pal_macros.mar
3838        mfpr	r16, pt_impure
3839        lda	r16, CNS_Q_IPR(r16)
3840        SAVE_SHADOW(r25,CNS_Q_BC_CTL,r16);
3841
3842        br 	r31, perfmon_success
3843
3844
3845// requested to disable perf monitoring
3846perfmon_dis:
3847        mfpr	r14, ev5__pmctr		// read ibox pmctr ipr
3848perfmon_dis_ctr0:			// and begin with ctr0
3849        blbc	r17, perfmon_dis_ctr1	// do not disable ctr0
3850        lda 	r8, 3(r31)
3851        sll	r8, pmctr_v_ctl0, r8
3852        bic	r14, r8, r14		// disable ctr0
3853perfmon_dis_ctr1:
3854        srl	r17, 1, r17
3855        blbc	r17, perfmon_dis_ctr2	// do not disable ctr1
3856        lda 	r8, 3(r31)
3857        sll	r8, pmctr_v_ctl1, r8
3858        bic	r14, r8, r14		// disable ctr1
3859perfmon_dis_ctr2:
3860        srl	r17, 1, r17
3861        blbc	r17, perfmon_dis_update	// do not disable ctr2
3862        lda 	r8, 3(r31)
3863        sll	r8, pmctr_v_ctl2, r8
3864        bic	r14, r8, r14		// disable ctr2
3865perfmon_dis_update:
3866        mtpr	r14, ev5__pmctr		// update pmctr ipr
3867//;the following code is not needed for ev5 pass2 and later, but doesn't hurt anything to leave in
3868// adapted from ev5_pal_macros.mar
3869//orig	get_pmctr_ctl	r8, r25		// pmctr_ctl bit in r8.  adjusted impure pointer in r25
3870        mfpr	r25, pt_impure
3871        lda	r25, CNS_Q_IPR(r25)
3872        RESTORE_SHADOW(r8,CNS_Q_PM_CTL,r25);
3873
3874        lda	r17, 0x3F(r31)		// build mask
3875        sll	r17, pmctr_v_ctl2, r17 // shift mask to correct position
3876        and 	r14, r17, r14		// isolate ctl bits
3877        bic	r8, r17, r8		// clear out old ctl bits
3878        or	r14, r8, r14		// create shadow ctl bits
3879//orig	store_reg1 pmctr_ctl, r14, r25, ipr=1	// update pmctr_ctl register
3880//adjusted impure pointer still in r25
3881        SAVE_SHADOW(r14,CNS_Q_PM_CTL,r25);
3882
3883        br 	r31, perfmon_success
3884
3885
3886// requested to enable perf monitoring
3887//;the following code can be greatly simplified for pass2, but should work fine as is.
3888
3889
3890perfmon_enclr:
3891        lda	r9, 1(r31)		// set enclr flag
3892        br perfmon_en_cont
3893
3894perfmon_en:
3895        bis	r31, r31, r9		// clear enclr flag
3896
3897perfmon_en_cont:
3898        mfpr	r8, pt_pcbb		// get PCB base
3899//orig	get_pmctr_ctl r25, r25
3900        mfpr	r25, pt_impure
3901        lda	r25, CNS_Q_IPR(r25)
3902        RESTORE_SHADOW(r25,CNS_Q_PM_CTL,r25);
3903
3904        ldq_p	r16, osfpcb_q_fen(r8)	// read DAT/PME/FEN quadword
3905        mfpr	r14, ev5__pmctr		// read ibox pmctr ipr
3906        srl 	r16, osfpcb_v_pme, r16	// get pme bit
3907        mfpr	r13, icsr
3908        and	r16,  1, r16		// isolate pme bit
3909
3910        // this code only needed in pass2 and later
3911        lda	r12, 1<<icsr_v_pmp(r31)		// pb
3912        bic	r13, r12, r13		// clear pmp bit
3913        sll	r16, icsr_v_pmp, r12	// move pme bit to icsr<pmp> position
3914        or	r12, r13, r13		// new icsr with icsr<pmp> bit set/clear
3915        mtpr	r13, icsr		// update icsr
3916
3917        bis	r31, 1, r16		// set r16<0> on pass2 to update pmctr always (icsr provides real enable)
3918
3919        sll	r25, 6, r25		// shift frequency bits into pmctr_v_ctl positions
3920        bis	r14, r31, r13		// copy pmctr
3921
3922perfmon_en_ctr0:			// and begin with ctr0
3923        blbc	r17, perfmon_en_ctr1	// do not enable ctr0
3924
3925        blbc	r9, perfmon_en_noclr0	// enclr flag set, clear ctr0 field
3926        lda	r8, 0xffff(r31)
3927        zapnot  r8, 3, r8		// ctr0<15:0> mask
3928        sll	r8, pmctr_v_ctr0, r8
3929        bic	r14, r8, r14		// clear ctr bits
3930        bic	r13, r8, r13		// clear ctr bits
3931
3932perfmon_en_noclr0:
3933//orig	get_addr r8, 3<<pmctr_v_ctl0, r31
3934        LDLI(r8, (3<<pmctr_v_ctl0))
3935        and 	r25, r8, r12		//isolate frequency select bits for ctr0
3936        bic	r14, r8, r14		// clear ctl0 bits in preparation for enabling
3937        or	r14,r12,r14		// or in new ctl0 bits
3938
3939perfmon_en_ctr1:			// enable ctr1
3940        srl	r17, 1, r17		// get ctr1 enable
3941        blbc	r17, perfmon_en_ctr2	// do not enable ctr1
3942
3943        blbc	r9, perfmon_en_noclr1   // if enclr flag set, clear ctr1 field
3944        lda	r8, 0xffff(r31)
3945        zapnot  r8, 3, r8		// ctr1<15:0> mask
3946        sll	r8, pmctr_v_ctr1, r8
3947        bic	r14, r8, r14		// clear ctr bits
3948        bic	r13, r8, r13		// clear ctr bits
3949
3950perfmon_en_noclr1:
3951//orig	get_addr r8, 3<<pmctr_v_ctl1, r31
3952        LDLI(r8, (3<<pmctr_v_ctl1))
3953        and 	r25, r8, r12		//isolate frequency select bits for ctr1
3954        bic	r14, r8, r14		// clear ctl1 bits in preparation for enabling
3955        or	r14,r12,r14		// or in new ctl1 bits
3956
3957perfmon_en_ctr2:			// enable ctr2
3958        srl	r17, 1, r17		// get ctr2 enable
3959        blbc	r17, perfmon_en_return	// do not enable ctr2 - return
3960
3961        blbc	r9, perfmon_en_noclr2	// if enclr flag set, clear ctr2 field
3962        lda	r8, 0x3FFF(r31)		// ctr2<13:0> mask
3963        sll	r8, pmctr_v_ctr2, r8
3964        bic	r14, r8, r14		// clear ctr bits
3965        bic	r13, r8, r13		// clear ctr bits
3966
3967perfmon_en_noclr2:
3968//orig	get_addr r8, 3<<pmctr_v_ctl2, r31
3969        LDLI(r8, (3<<pmctr_v_ctl2))
3970        and 	r25, r8, r12		//isolate frequency select bits for ctr2
3971        bic	r14, r8, r14		// clear ctl2 bits in preparation for enabling
3972        or	r14,r12,r14		// or in new ctl2 bits
3973
3974perfmon_en_return:
3975        cmovlbs	r16, r14, r13		// if pme enabled, move enables into pmctr
3976                                        // else only do the counter clears
3977        mtpr	r13, ev5__pmctr		// update pmctr ipr
3978
3979//;this code not needed for pass2 and later, but does not hurt to leave it in
3980        lda	r8, 0x3F(r31)
3981//orig	get_pmctr_ctl r25, r12         	// read pmctr ctl; r12=adjusted impure pointer
3982        mfpr	r12, pt_impure
3983        lda	r12, CNS_Q_IPR(r12)
3984        RESTORE_SHADOW(r25,CNS_Q_PM_CTL,r12);
3985
3986        sll	r8, pmctr_v_ctl2, r8	// build ctl mask
3987        and	r8, r14, r14		// isolate new ctl bits
3988        bic	r25, r8, r25		// clear out old ctl value
3989        or	r25, r14, r14		// create new pmctr_ctl
3990//orig	store_reg1 pmctr_ctl, r14, r12, ipr=1
3991        SAVE_SHADOW(r14,CNS_Q_PM_CTL,r12); // r12 still has the adjusted impure ptr
3992
3993        br 	r31, perfmon_success
3994
3995
3996// options...
3997perfmon_ctl:
3998
3999// set mode
4000//orig	get_pmctr_ctl r14, r12         	// read shadow pmctr ctl; r12=adjusted impure pointer
4001        mfpr	r12, pt_impure
4002        lda	r12, CNS_Q_IPR(r12)
4003        RESTORE_SHADOW(r14,CNS_Q_PM_CTL,r12);
4004
4005        // build mode mask for pmctr register
4006        LDLI(r8, ((1<<pmctr_v_killu) | (1<<pmctr_v_killp) | (1<<pmctr_v_killk)))
4007        mfpr	r0, ev5__pmctr
4008        and	r17, r8, r25			// isolate pmctr mode bits
4009        bic	r0, r8, r0			// clear old mode bits
4010        or	r0, r25, r25			// or in new mode bits
4011        mtpr	r25, ev5__pmctr
4012
4013        // the following code will only be used in pass2, but should
4014        // not hurt anything if run in pass1.
4015        mfpr	r8, icsr
4016        lda	r25, 1<<icsr_v_pma(r31)		// set icsr<pma> if r17<0>=0
4017        bic 	r8, r25, r8			// clear old pma bit
4018        cmovlbs r17, r31, r25			// and clear icsr<pma> if r17<0>=1
4019        or	r8, r25, r8
4020        mtpr	r8, icsr		// 4 bubbles to hw_rei
4021        mfpr	r31, pt0			// pad icsr write
4022        mfpr	r31, pt0			// pad icsr write
4023
4024        // the following code not needed for pass2 and later, but
4025        // should work anyway.
4026        bis     r14, 1, r14       		// set for select processes
4027        blbs	r17, perfmon_sp			// branch if select processes
4028        bic	r14, 1, r14			// all processes
4029perfmon_sp:
4030//orig	store_reg1 pmctr_ctl, r14, r12, ipr=1   // update pmctr_ctl register
4031        SAVE_SHADOW(r14,CNS_Q_PM_CTL,r12); // r12 still has the adjusted impure ptr
4032        br 	r31, perfmon_success
4033
4034// counter frequency select
4035perfmon_freq:
4036//orig	get_pmctr_ctl r14, r12         	// read shadow pmctr ctl; r12=adjusted impure pointer
4037        mfpr	r12, pt_impure
4038        lda	r12, CNS_Q_IPR(r12)
4039        RESTORE_SHADOW(r14,CNS_Q_PM_CTL,r12);
4040
4041        lda	r8, 0x3F(r31)
4042//orig	sll	r8, pmctr_ctl_v_frq2, r8		// build mask for frequency select field
4043// I guess this should be a shift of 4 bits from the above control register structure
4044#define	pmctr_ctl_v_frq2_SHIFT 4
4045        sll	r8, pmctr_ctl_v_frq2_SHIFT, r8		// build mask for frequency select field
4046
4047        and 	r8, r17, r17
4048        bic 	r14, r8, r14				// clear out old frequency select bits
4049
4050        or 	r17, r14, r14				// or in new frequency select info
4051//orig	store_reg1 pmctr_ctl, r14, r12, ipr=1   // update pmctr_ctl register
4052        SAVE_SHADOW(r14,CNS_Q_PM_CTL,r12); // r12 still has the adjusted impure ptr
4053
4054        br 	r31, perfmon_success
4055
4056// read counters
4057perfmon_rd:
4058        mfpr	r0, ev5__pmctr
4059        or	r0, 1, r0	// or in return status
4060        hw_rei			// back to user
4061
4062// write counters
4063perfmon_wr:
4064        mfpr	r14, ev5__pmctr
4065        lda	r8, 0x3FFF(r31)		// ctr2<13:0> mask
4066        sll	r8, pmctr_v_ctr2, r8
4067
4068        LDLI(r9, (0xFFFFFFFF))		// ctr2<15:0>,ctr1<15:0> mask
4069        sll	r9, pmctr_v_ctr1, r9
4070        or	r8, r9, r8		// or ctr2, ctr1, ctr0 mask
4071        bic	r14, r8, r14		// clear ctr fields
4072        and	r17, r8, r25		// clear all but ctr  fields
4073        or	r25, r14, r14		// write ctr fields
4074        mtpr	r14, ev5__pmctr		// update pmctr ipr
4075
4076        mfpr	r31, pt0		// pad pmctr write (needed only to keep PVC happy)
4077
4078perfmon_success:
4079        or      r31, 1, r0                     // set success
4080        hw_rei					// back to user
4081
4082perfmon_unknown:
4083        or	r31, r31, r0		// set fail
4084        hw_rei				// back to user
4085
4086
4087//////////////////////////////////////////////////////////
4088// Copy code
4089//////////////////////////////////////////////////////////
4090
4091copypal_impl:
4092        mov r16, r0
4093#ifdef CACHE_COPY
4094#ifndef CACHE_COPY_UNALIGNED
4095        and r16, 63, r8
4096        and r17, 63, r9
4097        bis r8, r9, r8
4098        bne r8, cache_copy_done
4099#endif
4100        bic r18, 63, r8
4101        and r18, 63, r18
4102        beq r8, cache_copy_done
4103cache_loop:
4104        ldf f17, 0(r16)
4105        stf f17, 0(r16)
4106        addq r17, 64, r17
4107        addq r16, 64, r16
4108        subq r8, 64, r8
4109        bne r8, cache_loop
4110cache_copy_done:
4111#endif
4112        ble r18, finished	// if len <=0 we are finished
4113        ldq_u r8, 0(r17)
4114        xor r17, r16, r9
4115        and r9, 7, r9
4116        and r16, 7, r10
4117        bne r9, unaligned
4118        beq r10, aligned
4119        ldq_u r9, 0(r16)
4120        addq r18, r10, r18
4121        mskqh r8, r17, r8
4122        mskql r9, r17, r9
4123        bis r8, r9, r8
4124aligned:
4125        subq r18, 1, r10
4126        bic r10, 7, r10
4127        and r18, 7, r18
4128        beq r10, aligned_done
4129loop:
4130        stq_u r8, 0(r16)
4131        ldq_u r8, 8(r17)
4132        subq r10, 8, r10
4133        lda r16,8(r16)
4134        lda r17,8(r17)
4135        bne r10, loop
4136aligned_done:
4137        bne r18, few_left
4138        stq_u r8, 0(r16)
4139        br r31, finished
4140        few_left:
4141        mskql r8, r18, r10
4142        ldq_u r9, 0(r16)
4143        mskqh r9, r18, r9
4144        bis r10, r9, r10
4145        stq_u r10, 0(r16)
4146        br r31, finished
4147unaligned:
4148        addq r17, r18, r25
4149        cmpule r18, 8, r9
4150        bne r9, unaligned_few_left
4151        beq r10, unaligned_dest_aligned
4152        and r16, 7, r10
4153        subq r31, r10, r10
4154        addq r10, 8, r10
4155        ldq_u r9, 7(r17)
4156        extql r8, r17, r8
4157        extqh r9, r17, r9
4158        bis r8, r9, r12
4159        insql r12, r16, r12
4160        ldq_u r13, 0(r16)
4161        mskql r13, r16, r13
4162        bis r12, r13, r12
4163        stq_u r12, 0(r16)
4164        addq r16, r10, r16
4165        addq r17, r10, r17
4166        subq r18, r10, r18
4167        ldq_u r8, 0(r17)
4168unaligned_dest_aligned:
4169        subq r18, 1, r10
4170        bic r10, 7, r10
4171        and r18, 7, r18
4172        beq r10, unaligned_partial_left
4173unaligned_loop:
4174        ldq_u r9, 7(r17)
4175        lda r17, 8(r17)
4176        extql r8, r17, r12
4177        extqh r9, r17, r13
4178        subq r10, 8, r10
4179        bis r12, r13, r13
4180        stq r13, 0(r16)
4181        lda r16, 8(r16)
4182        beq r10, unaligned_second_partial_left
4183        ldq_u r8, 7(r17)
4184        lda r17, 8(r17)
4185        extql r9, r17, r12
4186        extqh r8, r17, r13
4187        bis r12, r13, r13
4188        subq r10, 8, r10
4189        stq r13, 0(r16)
4190        lda r16, 8(r16)
4191        bne r10, unaligned_loop
4192unaligned_partial_left:
4193        mov r8, r9
4194unaligned_second_partial_left:
4195        ldq_u r8, -1(r25)
4196        extql r9, r17, r9
4197        extqh r8, r17, r8
4198        bis r8, r9, r8
4199        bne r18, few_left
4200        stq_u r8, 0(r16)
4201        br r31, finished
4202unaligned_few_left:
4203        ldq_u r9, -1(r25)
4204        extql r8, r17, r8
4205        extqh r9, r17, r9
4206        bis r8, r9, r8
4207        insqh r8, r16, r9
4208        insql r8, r16, r8
4209        lda r12, -1(r31)
4210        mskql r12, r18, r13
4211        cmovne r13, r13, r12
4212        insqh r12, r16, r13
4213        insql r12, r16, r12
4214        addq r16, r18, r10
4215        ldq_u r14, 0(r16)
4216        ldq_u r25, -1(r10)
4217        bic r14, r12, r14
4218        bic r25, r13, r25
4219        and r8, r12, r8
4220        and r9, r13, r9
4221        bis r8, r14, r8
4222        bis r9, r25, r9
4223        stq_u r9, -1(r10)
4224        stq_u r8, 0(r16)
4225finished:
4226        hw_rei
4227