summaryrefslogtreecommitdiffstats
path: root/qemu/roms/qemu-palcode/pal.S
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/qemu-palcode/pal.S')
-rw-r--r--qemu/roms/qemu-palcode/pal.S1918
1 files changed, 1918 insertions, 0 deletions
diff --git a/qemu/roms/qemu-palcode/pal.S b/qemu/roms/qemu-palcode/pal.S
new file mode 100644
index 000000000..1befc9f4a
--- /dev/null
+++ b/qemu/roms/qemu-palcode/pal.S
@@ -0,0 +1,1918 @@
+/* QEMU Emulation PALcode.
+
+ Copyright (C) 2011 Richard Henderson
+
+ This file is part of QEMU PALcode.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text
+ of the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not see
+ <http://www.gnu.org/licenses/>. */
+
+ .set noat
+ .set nomacro
+ .text
+
+#include "pal.h"
+#include "osf.h"
+#include SYSTEM_H
+
+/*
+ * Create a standard kernel entry stack frame.
+ */
+
+.macro STACK_FRAME save_ps, save_pc, temp, do_ps
+ // Test if we're currently in user mode
+ and \save_ps, PS_M_CM, \temp
+ beq \temp, 0f
+ // Switch to kernel mode
+.ifne \do_ps
+ mtpr $31, qemu_ps
+.endif
+ mtpr $sp, qemu_usp
+ mfpr $sp, ptKsp
+ // Allocate the stack frame
+0: lda $sp, -FRM_K_SIZE($sp)
+ stq \save_ps, FRM_Q_PS($sp)
+ stq \save_pc, FRM_Q_PC($sp)
+ stq $gp, FRM_Q_GP($sp)
+ stq a0, FRM_Q_A0($sp)
+ stq a1, FRM_Q_A1($sp)
+ stq a2, FRM_Q_A2($sp)
+.endm
+
+/*
+ * Allocate a 1 page stack for use by the console.
+ */
+#define STACK_SIZE 8192
+
+/*
+ * QEMU emulator "hardware" entry points.
+ */
+
+/*
+ * Reset
+ *
+ * INPUT PARAMETERS:
+ *
+ * trap_arg0 = Memory size
+ * trap_arg1 = Kernel entry (if loaded)
+ */
+ .org 0x0000
+ .globl __start
+__start:
+ // Initialize GP.
+ br $gp, .+4
+ ldah $gp, 0($gp) !gpdisp!1
+ lda $gp, 0($gp) !gpdisp!1
+ mtpr $gp, ptPgp
+
+ // Disable interrupts; kernel mode
+ lda t0, IPL_K_HIGH
+ mtpr t0, qemu_ps
+
+ // Initialize Stack.
+ SYS_WHAMI a0
+ lda t0, STACK_SIZE
+ addq a0, 1, t1
+ mull t0, t1, t0
+ ldah t1, stack($gp) !gprelhigh
+ lda t1, stack(t1) !gprellow
+ addq t0, t1, $sp
+
+ // Do any necessary system setup required for PALmode,
+ // e.g. setting up ptSys[01].
+ bsr $26, Sys_Setup
+
+ // Non-boot CPUs can go wait now.
+ bne a0, 1f
+
+ // Load boot arguments
+ mfpr a0, qemu_trap_arg0
+ mfpr a1, qemu_trap_arg1
+ mfpr a2, qemu_trap_arg2
+
+ // Continue in do_start, outside PALmode.
+ ldah $27, do_start($gp) !gprelhigh
+ lda $27, do_start($27) !gprellow
+ hw_ret ($27)
+
+1: ldah $27, do_start_wait($gp) !gprelhigh
+ lda $27, do_start_wait($27) !gprellow
+ hw_ret ($27)
+ENDFN __start
+
+/*
+ * Machine Check
+ *
+ * INPUT PARAMETERS:
+ *
+ * trap_arg0 =
+ * trap_arg1 =
+ * trap_arg2 =
+ */
+ .org 0x0080
+Pal_Mchk:
+ halt
+ENDFN Pal_Mchk
+
+/*
+ * Interprocessor Interrupt
+ *
+ * INPUT PARAMETERS:
+ *
+ * trap_arg0 =
+ * trap_arg1 =
+ * trap_arg2 =
+ *
+ * The interprocessor interrupt is special, in that PALcode is supposed
+ * to clear the interupt and not wait for the OS to do it.
+ */
+ .org 0x0100
+Pal_Smp_Interrupt:
+ mfpr p6, qemu_exc_addr
+
+ SYS_ACK_SMP p0, p1, p2
+
+ mfpr p0, qemu_ps
+
+ STACK_FRAME p0, p6, p2, 0
+
+ mov IPL_K_IP, p0 // Raise IPL
+ mtpr p0, qemu_ps
+
+ mfpr p6, ptEntInt
+ mfpr $gp, ptKgp
+ lda a0, INT_K_IP
+ lda a1, 0
+ lda a2, 0
+
+ hw_ret (p6)
+ENDFN Pal_Smp_Interrupt
+
+/*
+ * Clock Interrupt
+ *
+ * INPUT PARAMETERS:
+ *
+ * trap_arg0 =
+ * trap_arg1 =
+ * trap_arg2 =
+ *
+ * The clock interrupt is special, in that PALcode is supposed
+ * to clear the interupt and not wait for the OS to do it.
+ */
+ .org 0x0180
+Pal_Clk_Interrupt:
+ mfpr p6, qemu_exc_addr
+
+ SYS_ACK_CLK p0, p1, p2
+
+ mfpr p0, qemu_ps
+
+ STACK_FRAME p0, p6, p2, 0
+
+ mov IPL_K_CLK, p0 // Raise IPL
+ mtpr p0, qemu_ps
+
+ mfpr p6, ptEntInt
+ mfpr $gp, ptKgp
+ lda a0, INT_K_CLK
+ lda a1, 0
+ lda a2, 0
+
+9: hw_ret (p6)
+ENDFN Pal_Clk_Interrupt
+
+/*
+ * Device Interrupt
+ *
+ * INPUT PARAMETERS:
+ *
+ * trap_arg0 =
+ * trap_arg1 =
+ * trap_arg2 =
+ */
+ .org 0x0200
+Pal_Dev_Interrupt:
+ mfpr p6, qemu_exc_addr
+ mfpr p0, qemu_ps
+
+ STACK_FRAME p0, p6, p2, 0
+
+ mov IPL_K_DEV1, p0 // Raise IPL
+ mtpr p0, qemu_ps
+
+ bsr p7, Sys_Dev_Vector
+
+ mfpr p7, ptEntInt
+ mfpr $gp, ptKgp
+ lda a0, INT_K_DEV
+ lda a2, 0
+ hw_ret (p7)
+ENDFN Pal_Dev_Interrupt
+
+/*
+ * Memory Fault
+ *
+ * INPUT PARAMETERS:
+ *
+ * trap_arg0 = faulting address
+ * trap_arg1 = fault type (TNV, ACV, FOR, FOW, FOE)
+ * trap_arg2 = access type (exec=-1, read=0, write=1)
+ */
+ .org 0x0280
+Pal_MMFault:
+ mfpr p0, qemu_ps
+ mfpr p6, qemu_exc_addr
+ blbs p6, MchkBugCheck
+
+ STACK_FRAME p0, p6, p2, 1
+
+ mfpr p0, ptEntMM
+ mfpr $gp, ptKgp
+ mfpr a0, qemu_trap_arg0
+ mfpr a1, qemu_trap_arg1
+ mfpr a2, qemu_trap_arg2
+ hw_ret (p0)
+ENDFN Pal_MMFault
+
+/*
+ * Unaligned Data
+ *
+ * INPUT PARAMETERS:
+ *
+ * trap_arg0 = faulting address
+ * trap_arg1 = opcode of faulting insn
+ * trap_arg2 = src/dst register number
+ */
+ .org 0x0300
+Pal_Unalign:
+ mfpr p0, qemu_ps
+ mfpr p6, qemu_exc_addr
+ addq p6, 4, p1 // increment past the faulting insn
+ blbs p6, MchkBugCheck
+
+ STACK_FRAME p0, p1, p2, 1
+
+ mfpr p0, ptEntUna
+ mfpr $gp, ptKgp
+ mfpr a0, qemu_trap_arg0
+ mfpr a1, qemu_trap_arg1
+ mfpr a2, qemu_trap_arg2
+ hw_ret (p0)
+ENDFN Pal_Unalign
+
+/*
+ * Illegal Opcode
+ *
+ * INPUT PARAMETERS:
+ *
+ * trap_arg0 = UNDEFINED
+ * trap_arg1 = UNDEFINED
+ * trap_arg2 = UNDEFINED
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * r16 (a0) = Instruction fault code
+ * r17 (a1) = UNPREDICTABLE
+ * r18 (a2) = UNPREDICTABLE
+ */
+ .org 0x0380
+Pal_OpcDec:
+ mfpr p0, qemu_ps
+ mfpr p6, qemu_exc_addr
+ addq p6, 4, p1 // increment past the faulting insn
+ blbs p6, MchkBugCheck
+
+ STACK_FRAME p0, p1, p2, 1
+
+ mfpr p0, ptEntIF
+ mfpr $gp, ptKgp
+ mov IF_K_OPCDEC, a0
+ hw_ret (p0)
+ENDFN Pal_OpcDec
+
+/*
+ * Arithmetic Trap
+ *
+ * INPUT PARAMETERS:
+ *
+ * trap_arg0 = exception type
+ * trap_arg1 = register modification mask
+ * trap_arg2 = UNDEFINED
+ */
+ .org 0x0400
+Pal_Arith:
+ mfpr p0, qemu_ps
+ mfpr p6, qemu_exc_addr
+ blbs p6, MchkBugCheck
+
+ STACK_FRAME p0, p6, p2, 1
+
+ mfpr p0, ptEntArith
+ mfpr $gp, ptKgp
+ mfpr a0, qemu_trap_arg0
+ mfpr a1, qemu_trap_arg1
+ hw_ret (p0)
+ENDFN Pal_Arith
+
+/*
+ * Floating Point Disabled
+ *
+ * INPUT PARAMETERS:
+ *
+ * trap_arg0 = UNDEFINED
+ * trap_arg1 = UNDEFINED
+ * trap_arg2 = UNDEFINED
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * r16 (a0) = Instruction fault code
+ * r17 (a1) = UNPREDICTABLE
+ * r18 (a2) = UNPREDICTABLE
+ */
+ .org 0x0480
+Pal_Fen:
+ mfpr p0, qemu_ps
+ mfpr p6, qemu_exc_addr
+ blbs p6, MchkBugCheck
+
+ STACK_FRAME p0, p6, p2, 1
+
+ mfpr p0, ptEntIF
+ mfpr $gp, ptKgp
+ mov IF_K_FEN, a0
+ hw_ret (p0)
+ENDFN Pal_Fen
+
+/*
+ * OSF/1 Privileged CALL_PAL Entry Points
+ */
+
+#define ORG_CALL_PAL_PRIV(X) .org 0x1000+64*X
+
+/*
+ * Halt
+ *
+ * SIDE EFFECTS:
+ *
+ * We either power down the system or re-enter the console.
+ * But given that we're not returning to the kernel, there's
+ * no reason to continue processing in assembler. Go to C.
+ */
+ ORG_CALL_PAL_PRIV(0x00)
+CallPal_Halt:
+ bsr p7, UpdatePCB // Save kernel data
+ lda v0, HLT_K_SW_HALT // FIXME store this somewhere.
+
+ mtpr $31, qemu_halt
+
+ br Sys_EnterConsole
+ENDFN CallPal_Halt
+
+/*
+ * Cache Flush
+ *
+ * For QEMU, this is of course a no-op.
+ */
+ ORG_CALL_PAL_PRIV(0x01)
+CallPal_Cflush:
+ hw_rei
+ENDFN CallPal_Cflush
+
+/*
+ * Drain Aborts
+ *
+ * For QEMU, this is of course a no-op.
+ */
+ ORG_CALL_PAL_PRIV(0x02)
+CallPal_Draina:
+ hw_rei
+ENDFN CallPal_Draina
+
+ ORG_CALL_PAL_PRIV(0x03)
+CallPal_OpcDec03:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec03
+
+ ORG_CALL_PAL_PRIV(0x04)
+CallPal_OpcDec04:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec04
+
+ ORG_CALL_PAL_PRIV(0x05)
+CallPal_OpcDec05:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec05
+
+ ORG_CALL_PAL_PRIV(0x06)
+CallPal_OpcDec06:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec06
+
+ ORG_CALL_PAL_PRIV(0x07)
+CallPal_OpcDec07:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec07
+
+ ORG_CALL_PAL_PRIV(0x08)
+CallPal_OpcDec08:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec08
+
+/*
+ * Console Service
+ *
+ * INPUT PARAMETERS:
+ *
+ * r16 (a0) = Option selector
+ * r17..r21 (a1..a5) = Implementation specific entry parameters
+ *
+ * SIDE EFFECTS:
+ *
+ * Registers a0..a5, and v0 are UNPREDICTABLE upon return.
+ */
+ ORG_CALL_PAL_PRIV(0x09)
+CallPal_Cserve:
+ // Most of the entries are densely clustered around 0.
+ mov 0, v0
+ cmpule a0, 7, p0
+ cmovne p0, a0, v0
+ br p0, 1f
+1: lda p0, Cserve_Table-1b(p0)
+ s8addq v0, p0, p0
+ jmp $31, (p0), 0
+ENDFN CallPal_Cserve
+
+ .text 1
+ .align 3
+/* Note that the entries in the following table are all 2 insns.
+ The first entry is unused, and is also where all out-of-range
+ commands are vectored. */
+Cserve_Table:
+ br CallPal_Cserve_Cont
+ nop
+Cserve_Ldqp:
+ ldq_p v0, 0(a1)
+ hw_rei
+ENDFN Cserve_Ldqp
+Cserve_Stqp:
+ stq_p a2, 0(a1)
+ hw_rei
+ENDFN Cserve_Stqp
+Cserve_Get_Wall_Time:
+ mfpr v0, qemu_walltime
+ hw_rei
+ENDFN Cserve_Get_Wall_Time
+Cserve_Get_Alarm:
+ mfpr v0, qemu_alarm
+ hw_rei
+ENDFN Cserve_Get_Alarm
+Cserve_Set_Alarm_Rel:
+ // Cheating here: create the absolute time and fall thru.
+ mfpr p0, qemu_vmtime
+ addq p0, a1, a1
+ENDFN Cserve_Set_Alarm_Rel
+Cserve_Set_Alarm_Abs:
+ mtpr a1, qemu_alarm
+ hw_rei
+ENDFN Cserve_Set_Alarm_Abs
+Cserve_Get_VM_Time:
+ mfpr v0, qemu_vmtime
+ hw_rei
+ENDFN Cserve_Get_VM_Time
+
+
+CallPal_Cserve_Cont:
+ // ??? For SRM compatibility and their use within Linux, use 52/53
+ // for these. Anyone know what other "standard" SRM Cserve entry
+ // points are? Certainly we don't want to be compatible with MILO,
+ // which puts the selector at A2.
+ cmpeq a0, 52, v0
+ bne v0, Cserve_Ena
+ cmpeq a0, 53, v0
+ bne v0, Cserve_Dis
+ hw_rei
+ENDFN CallPal_Cserve_Cont
+ .previous
+
+/*
+ * Swap PALcode
+ *
+ * FUNCTIONAL DESCRIPTION:
+ *
+ * The swap PALcode (swppal) function replaces the current
+ * (active) PALcode by the specified new PALcode image.
+ * This function is intended for use by operating systems
+ * only during bootstraps and restarts, or during transitions
+ * to console I/O mode.
+ *
+ * The PALcode descriptor passed in a0 is interpreted as
+ * either a PALcode variant or the base physical address
+ * of the new PALcode image. If a variant, the PALcode
+ * image must have been previously loaded. No PALcode
+ * loading occurs as a result of this function.
+ *
+ * NOTE:
+ * This implementation of SWPPAL does not support PALcode
+ * variants. If a variant is specified in a0, a check is
+ * performed to determine whether the variant is OSF/1 or
+ * not and the returned status is either unknown variant
+ * (if not OSF/1) or variant not loaded.
+ *
+ * INPUT PARAMETERS:
+ *
+ * r16 (a0) = New PALcode variant or base physical address
+ * r17 (a1) = New PC
+ * r18 (a2) = New PCB
+ * r19 (a3) = New VptPtr
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * r0 (v0) = Returned status indicating:
+ * 0 - Success (PALcode was switched)
+ * 1 - Unknown PALcode variant
+ * 2 - Known PALcode variant, but PALcode not loaded
+ *
+ * r26 (ra) = r27 (pv) = New PC
+ * Note that this is non-architected, but is relied on by
+ * the usage of SwpPal within our own console code in order
+ * to simplify its use within C code.
+ *
+ */
+ ORG_CALL_PAL_PRIV(0x0A)
+CallPal_SwpPal:
+ // Save a copy of the return address in case of machine check.
+ mfpr p6, qemu_exc_addr
+
+ // Accept swapping to OSF PALcode. The side effect here is to
+ // load the other parameters for the kernel.
+ cmpeq a0, 2, v0
+ bne v0, CallPal_SwpPal_Cont
+
+ // Return as an unknown PALcode variant
+ mov 1, v0
+ hw_rei
+ENDFN CallPal_SwpPal
+
+ .text 1
+CallPal_SwpPal_Cont:
+ rpcc p0
+ mtpr a2, ptPcbb
+ mtpr a3, qemu_vptptr
+
+ ldq_p $sp, PCB_Q_KSP(a2)
+ ldq_p t0, PCB_Q_USP(a2)
+ ldq_p t1, PCB_Q_PTBR(a2)
+ ldl_p t2, PCB_L_PCC(a2)
+ ldq_p t3, PCB_Q_UNIQUE(a2)
+ ldq_p t4, PCB_Q_FEN(a2)
+
+ mtpr t0, qemu_usp
+
+ sll t1, VA_S_OFF, t1
+ mtpr t1, qemu_ptbr
+
+ subl t2, p0, t2
+ mtpr t2, qemu_pcc_ofs
+
+ mtpr t3, qemu_unique
+
+ and t4, 1, t4
+ mtpr t4, qemu_fen
+
+ mtpr $31, qemu_tbia // Flush TLB for new PTBR
+
+ mov a1, $26
+ mov a1, $27
+ hw_ret (a1)
+ENDFN CallPal_SwpPal_Cont
+ .previous
+
+ ORG_CALL_PAL_PRIV(0x0B)
+CallPal_OpcDec0B:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec0B
+
+ ORG_CALL_PAL_PRIV(0x0C)
+CallPal_OpcDec0C:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec0C
+
+/*
+ * Write Interprocessor Interrupt Request
+ *
+ * INPUT PARAMETERS:
+ *
+ * r16 (a0) = target processor number
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * SIDE EFFECTS:
+ *
+ */
+ ORG_CALL_PAL_PRIV(0x0D)
+CallPal_WrIpir:
+ // Save a copy of the return address in case of machine check.
+ mfpr p6, qemu_exc_addr
+
+ SYS_WRIPIR a0, p0, p1, p2
+
+ hw_rei
+ENDFN CallPal_WrIpir
+
+ ORG_CALL_PAL_PRIV(0x0E)
+CallPal_OpcDec0E:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec0E
+
+ ORG_CALL_PAL_PRIV(0x0F)
+CallPal_OpcDec0F:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec0F
+
+/*
+ * Read Machine Check Error Summary
+ *
+ * INPUT PARAMETERS:
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * r0 (v0) = returned MCES value
+ *
+ * SIDE EFFECTS:
+ *
+ */
+ ORG_CALL_PAL_PRIV(0x10)
+CallPal_RdMces:
+ mfpr v0, ptMces // Get current MCES value
+ and v0, MCES_M_ALL, v0 // Clear all other bits
+ hw_rei
+ENDFN CallPal_RdMces
+
+/*
+ * Write Machine Check Error Summary
+ *
+ * INPUT PARAMETERS:
+ *
+ * r16 (a0) = MCES<DPC> <- a0<3>, MCES<DSC> <- a0<4>
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * SIDE EFFECTS:
+ *
+ * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
+ */
+ ORG_CALL_PAL_PRIV(0x11)
+CallPal_WrMces:
+ // Clear MIP, SCE, PCE
+ and a0, (MCES_M_MIP | MCES_M_SCE | MCES_M_PCE), p0
+ mfpr p1, ptMces
+ bic p1, p0, p1
+
+ // Copy DPC and DSC
+ and a0, (MCES_M_DPC | MCES_M_DSC), p0
+ bic p1, (MCES_M_DPC | MCES_M_DSC), p1
+ or p1, p0, p1
+
+ mtpr p1, ptMces
+ hw_rei
+ENDFN CallPal_WrMces
+
+ ORG_CALL_PAL_PRIV(0x12)
+CallPal_OpcDec12:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec12
+
+ ORG_CALL_PAL_PRIV(0x13)
+CallPal_OpcDec13:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec13
+
+ ORG_CALL_PAL_PRIV(0x14)
+CallPal_OpcDec14:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec14
+
+ ORG_CALL_PAL_PRIV(0x15)
+CallPal_OpcDec15:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec15
+
+ ORG_CALL_PAL_PRIV(0x16)
+CallPal_OpcDec16:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec16
+
+ ORG_CALL_PAL_PRIV(0x17)
+CallPal_OpcDec17:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec17
+
+ ORG_CALL_PAL_PRIV(0x18)
+CallPal_OpcDec18:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec18
+
+ ORG_CALL_PAL_PRIV(0x19)
+CallPal_OpcDec19:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec19
+
+ ORG_CALL_PAL_PRIV(0x1A)
+CallPal_OpcDec1A:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec1A
+
+ ORG_CALL_PAL_PRIV(0x1B)
+CallPal_OpcDec1B:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec1B
+
+ ORG_CALL_PAL_PRIV(0x1C)
+CallPal_OpcDec1C:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec1C
+
+ ORG_CALL_PAL_PRIV(0x1D)
+CallPal_OpcDec1D:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec1D
+
+ ORG_CALL_PAL_PRIV(0x1E)
+CallPal_OpcDec1E:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec1E
+
+ ORG_CALL_PAL_PRIV(0x1F)
+CallPal_OpcDec1F:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec1F
+
+ ORG_CALL_PAL_PRIV(0x20)
+CallPal_OpcDec20:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec20
+
+ ORG_CALL_PAL_PRIV(0x21)
+CallPal_OpcDec21:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec21
+
+ ORG_CALL_PAL_PRIV(0x22)
+CallPal_OpcDec22:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec22
+
+ ORG_CALL_PAL_PRIV(0x23)
+CallPal_OpcDec23:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec23
+
+ ORG_CALL_PAL_PRIV(0x24)
+CallPal_OpcDec24:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec24
+
+ ORG_CALL_PAL_PRIV(0x25)
+CallPal_OpcDec25:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec25
+
+ ORG_CALL_PAL_PRIV(0x26)
+CallPal_OpcDec26:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec26
+
+ ORG_CALL_PAL_PRIV(0x27)
+CallPal_OpcDec27:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec27
+
+ ORG_CALL_PAL_PRIV(0x28)
+CallPal_OpcDec28:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec28
+
+ ORG_CALL_PAL_PRIV(0x29)
+CallPal_OpcDec29:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec29
+
+ ORG_CALL_PAL_PRIV(0x2A)
+CallPal_OpcDec2A:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec2A
+
+/*
+ * Write Floating Point Enable
+ *
+ * INPUT PARAMETERS:
+ *
+ * r16 (a0) = ICSR<FPE> <- a0<0>
+ *
+ * SIDE EFFECTS:
+ *
+ * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
+ */
+ ORG_CALL_PAL_PRIV(0x2B)
+CallPal_WrFen:
+ mfpr p0, ptPcbb // Get PCBB
+ and a0, 1, a0 // Clean new FEN value to single bit
+ mtpr a0, qemu_fen
+ stl_p a0, PCB_Q_FEN(p0) // Write new PCB<FEN>
+ hw_rei
+ENDFN CallPal_WrFen
+
+ ORG_CALL_PAL_PRIV(0x2C)
+CallPal_OpcDec2C:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec2C
+
+/*
+ * Write Virtual Page Table Pointer
+ *
+ * INPUT PARAMETERS:
+ *
+ * r16 (a0) = New virtual page table pointer
+ *
+ * SIDE EFFECTS:
+ *
+ * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
+ */
+ ORG_CALL_PAL_PRIV(0x2D)
+CallPal_WrVptPtr:
+ mtpr a0, qemu_vptptr
+ hw_rei
+ENDFN CallPal_WrVptPtr
+
+ ORG_CALL_PAL_PRIV(0x2E)
+CallPal_OpcDec2E:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec2E
+
+ ORG_CALL_PAL_PRIV(0x2F)
+CallPal_OpcDec2F:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec2F
+
+/*
+ * Swap Process Context
+ *
+ * FUNCTIONAL DESCRIPTION:
+ *
+ * The swap process context (swpctx) function saves
+ * the current process data in the current PCB, then
+ * switches to the PCB passed in a0 and loads the
+ * new process context. The old PCB is returned in v0.
+ *
+ * INPUT PARAMETERS:
+ *
+ * r16 (a0) = New PCBB
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * r0 (v0) = Old PCBB
+ *
+ * SIDE EFFECTS:
+ *
+ * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
+ */
+ ORG_CALL_PAL_PRIV(0x30)
+CallPal_SwpCtx:
+ rpcc p5 // Get cycle counter
+ mfpr p6, qemu_exc_addr // Save exc_addr for machine check
+
+ mfpr v0, ptPcbb // Get current PCBB
+ mtpr a0, ptPcbb // Save new PCBB
+ srl p5, 32, p7 // Move CC<OFFSET> to low longword
+
+ addl p5, p7, p7 // Accumulate time for old pcb
+ stl_p p7, PCB_L_PCC(v0)
+
+ ldl_p t9, PCB_L_PCC(a0) // Get new PCC
+ subl t9, p5, p5 // Generate and ...
+ mtpr p5, qemu_pcc_ofs // .. set new CC<OFFSET> bits
+
+ stq_p $sp, PCB_Q_KSP(v0) // Store old kernel stack pointer
+ mfpr t10, qemu_usp // Save old user stack pointer
+ stq_p t10, PCB_Q_USP(v0)
+
+ br CallPal_SwpCtx_Cont
+ENDFN CallPal_SwpCtx
+
+ .text 1
+CallPal_SwpCtx_Cont:
+ ldq_p $sp, PCB_Q_KSP(a0) // Install new stack pointers
+ ldq_p t10, PCB_Q_USP(a0)
+ mtpr t10, qemu_usp
+
+ mfpr t10, qemu_unique // Save old unique value
+ stq_p t10, PCB_Q_UNIQUE(v0)
+ ldq_p t10, PCB_Q_UNIQUE(a0) // Install new unique value
+ mtpr t10, qemu_unique
+
+ ldq_p t8, PCB_Q_FEN(a0) // Install new FEN
+ and t8, 1, t8
+ mtpr t8, qemu_fen
+
+ // QEMU does not implement an ASN; skip that.
+
+ ldq_p t10, PCB_Q_PTBR(a0) // Install new page tables
+ sll t10, VA_S_OFF, t10
+ mtpr t10, qemu_ptbr
+ mtpr $31, qemu_tbia // Flush TLB, since we don't do ASNs
+
+ hw_rei
+ENDFN CallPal_SwpCtx_Cont
+ .previous
+
+/*
+ * Write System Value
+ *
+ * INPUT PARAMETERS:
+ *
+ * r16 (a0) = New system value
+ *
+ * SIDE EFFECTS:
+ *
+ * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
+ */
+ ORG_CALL_PAL_PRIV(0x31)
+CallPal_WrVal:
+ mtpr a0, qemu_sysval
+ hw_rei
+ENDFN CallPal_WrVal
+
+/*
+ * Read System Value
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * r0 (v0) = Returned system value
+ *
+ * SIDE EFFECTS:
+ *
+ * Registers t0 and t8..t11 are UNPREDICTABLE upon return.
+ */
+ ORG_CALL_PAL_PRIV(0x32)
+CallPal_RdVal:
+ mfpr v0, qemu_sysval
+ hw_rei
+ENDFN CallPal_RdVal
+
+/*
+ * Translation Buffer Invalidate
+ *
+ * INPUT PARAMETERS:
+ *
+ * r16 (a0) = tbi selector type:
+ *
+ * -2 - Flush all TB entries (tbia)
+ * -1 - Invalidate all TB entries with ASM=0 (tbiap)
+ * 1 - Invalidate ITB entry for va=a1 (tbisi)
+ * 2 - Invalidate DTB entry for va=a1 (tbisd)
+ * 3 - Invalidate both ITB and DTB entry for va=a1 (tbis)
+ *
+ * r17 (a1) = VA for TBISx types
+ *
+ * Qemu does not implement ASNs or split I/D tlbs. Therefore these
+ * collapse to tbia and tbis.
+ *
+ * SIDE EFFECTS:
+ *
+ * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
+ */
+ ORG_CALL_PAL_PRIV(0x33)
+CallPal_Tbi:
+ bge a0, 1f
+
+ mtpr $31, qemu_tbia
+ hw_rei
+
+1: mtpr a1, qemu_tbis
+ hw_rei
+ENDFN CallPal_Tbi
+
+/*
+ * Write System Entry Address
+ *
+ * INPUT PARAMETERS:
+ *
+ * r16 (a0) = VA of system entry point
+ * r17 (a1) = System entry point selector
+ *
+ * SIDE EFFECTS:
+ *
+ * Registers t0, t8..t11, and a0..a1 are UNPREDICTABLE
+ * upon return.
+ */
+ ORG_CALL_PAL_PRIV(0x34)
+CallPal_WrEnt:
+ andnot a0, 3, a0 // Clean PC<1:0>
+
+ cmpult a1, 6, t8 // Bound the input
+ cmoveq t8, 6, a1
+
+ br t0, 1f
+1: lda t0, WrEnt_Table-1b(t0)
+ s8addq a1, t0, t0
+ jmp $31, (t0), 0
+ENDFN CallPal_WrEnt
+
+ .text 1
+WrEnt_Table:
+0: mtpr a0, ptEntInt
+ hw_rei
+1: mtpr a0, ptEntArith
+ hw_rei
+2: mtpr a0, ptEntMM
+ hw_rei
+3: mtpr a0, ptEntIF
+ hw_rei
+4: mtpr a0, ptEntUna
+ hw_rei
+5: mtpr a0, ptEntSys
+ hw_rei
+6: nop
+ hw_rei
+ENDFN WrEnt_Table
+ .previous
+
+/*
+ * Swap Interrupt Priority Level
+ *
+ * INPUT PARAMETERS:
+ *
+ * r16 (a0) = New IPL
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * r0 (v0) = Old IPL
+ *
+ * SIDE EFFECTS:
+ *
+ * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
+ */
+ ORG_CALL_PAL_PRIV(0x35)
+CallPal_SwpIpl:
+ mfpr v0, qemu_ps
+ and a0, PS_M_IPL, a0
+ and v0, PS_M_IPL, v0
+ mtpr a0, qemu_ps
+ hw_rei
+ENDFN CallPal_SwpIpl
+
+/*
+ * Read Processor Status
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * r0 (v0) = Current PS
+ *
+ * SIDE EFFECTS:
+ *
+ * Registers t0, t8..t11 are UNPREDICTABLE upon return.
+ */
+ ORG_CALL_PAL_PRIV(0x36)
+CallPal_RdPs:
+ mfpr v0, qemu_ps
+ hw_rei
+ENDFN CallPal_RdPs
+
+/*
+ * Write Kernel Global Pointer
+ *
+ * INPUT PARAMETERS:
+ *
+ * r16 (a0) = New KGP value
+ *
+ * SIDE EFFECTS:
+ *
+ * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
+ */
+ ORG_CALL_PAL_PRIV(0x37)
+CallPal_WrKgp:
+ mtpr a0, ptKgp
+ hw_rei
+ENDFN CallPal_WrKgp
+
+/*
+ * Write User Stack Pointer
+ *
+ * INPUT PARAMETERS:
+ *
+ * r16 (a0) = New user stack pointer value
+ *
+ * SIDE EFFECTS:
+ *
+ * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
+ */
+ ORG_CALL_PAL_PRIV(0x38)
+CallPal_WrUsp:
+ mtpr a0, qemu_usp
+ hw_rei
+ENDFN CallPal_WrUsp
+
+/*
+ * Write Performance Monitor
+ *
+ * INPUT PARAMETERS:
+ *
+ * r16 (a0) = New user stack pointer value
+ *
+ * SIDE EFFECTS:
+ *
+ * Registers t0, t8..t11, and a0 are UNPREDICTABLE upon return.
+ */
+ ORG_CALL_PAL_PRIV(0x39)
+CallPal_WrPerfMon:
+ // Not implemented
+ hw_rei
+ENDFN CallPal_WrPerfMon
+
+/*
+ * Read User Stack Pointer
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * r0 (v0) = User stack pointer value
+ *
+ * SIDE EFFECTS:
+ *
+ * Registers t0, and t8..t11 are UNPREDICTABLE upon return.
+ */
+ ORG_CALL_PAL_PRIV(0x3A)
+CallPal_RdUsp:
+ mfpr v0, qemu_usp
+ hw_rei
+ENDFN CallPal_RdUsp
+
+ ORG_CALL_PAL_PRIV(0x3B)
+CallPal_OpcDec3B:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec3B
+
+/*
+ * Who Am I
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * r0 (v0) = Current processor number
+ *
+ * SIDE EFFECTS:
+ *
+ * Registers t0 and t8..t11 are UNPREDICTABLE upon return.
+ */
+ ORG_CALL_PAL_PRIV(0x3C)
+CallPal_Whami:
+ SYS_WHAMI v0
+ hw_rei
+ENDFN CallPal_Whami
+
+/*
+ * Return From System Call
+ *
+ * INPUT PARAMETERS:
+ *
+ * r30 (sp) = Pointer to the top of the kernel stack
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * r29 (gp) = Restored user mode global pointer
+ * r30 (sp) = User stack pointer
+ *
+ * SIDE EFFECTS:
+ *
+ * Registers t0 and t8..t11 are UNPREDICTABLE upon return.
+ */
+ ORG_CALL_PAL_PRIV(0x3D)
+CallPal_RetSys:
+ ldq t9, FRM_Q_PC($sp) // Pop the return address
+ ldq $gp, FRM_Q_GP($sp) // Get the user mode global pointer
+ lda t8, FRM_K_SIZE($sp)
+ mtpr t8, ptKsp
+
+ mov PS_K_USER, t8 // Set new mode to user
+ mtpr t8, qemu_ps
+
+ mfpr $sp, qemu_usp // Get the user stack pointer
+
+ andnot t9, 3, t9 // Clean return PC<1:0>
+ hw_ret (t9)
+ENDFN CallPal_RetSys
+
+/*
+ * Wait For Interrupt
+ *
+ * FUNCTIONAL DESCRIPTION:
+ *
+ * If possible, wait for the first of either of the following
+ * conditions before returning: any interrupt other than a clock
+ * tick; or the first clock tick after a specified number of clock
+ * ticks have bbeen skipped.
+ *
+ * INPUT PARAMETERS:
+ *
+ * r16 (a0) = Maximum number of clock ticks to skip
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * r0 (v0) = Number of clock ticks actually skipped.
+ */
+ ORG_CALL_PAL_PRIV(0x3E)
+CallPal_WtInt:
+ mtpr $31, qemu_wait
+ mov 0, v0
+ hw_rei
+ENDFN CallPal_WtInt
+
+/*
+ * Return From Trap, Fault, or Interrupt
+ *
+ * INPUT PARAMETERS:
+ *
+ * r30 (sp) = Pointer to the top of the kernel stack
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * ps <- (sp+00)
+ * pc <- (sp+08)
+ * r29 (gp) <- (sp+16)
+ * r16 (a0) <- (sp+24)
+ * r17 (a1) <- (sp+32)
+ * r18 (a2) <- (sp+40)
+ */
+ ORG_CALL_PAL_PRIV(0x3F)
+ .globl CallPal_Rti
+CallPal_Rti:
+ mfpr p6, qemu_exc_addr // Save exc_addr for machine check
+
+ ldq p4, FRM_Q_PS($sp) // Get the PS
+ ldq p5, FRM_Q_PC($sp) // Get the return PC
+ ldq $gp, FRM_Q_GP($sp) // Get gp
+ ldq a0, FRM_Q_A0($sp) // Get a0
+ ldq a1, FRM_Q_A1($sp) // Get a1
+ ldq a2, FRM_Q_A2($sp) // Get a2
+ lda $sp, FRM_K_SIZE($sp) // Pop the stack
+
+ andnot p5, 3, p5 // Clean return PC<1:0>
+
+ and p4, PS_M_CM, p3
+ bne p3, CallPal_Rti_ToUser
+
+ and p4, PS_M_IPL, p4
+ mtpr p4, qemu_ps
+ hw_ret (p5)
+ENDFN CallPal_Rti
+
+ .text 1
+CallPal_Rti_ToUser:
+ mtpr p3, qemu_ps
+ mtpr $sp, ptKsp
+ mfpr $sp, qemu_usp
+ hw_ret (p5)
+ENDFN CallPal_Rti_ToUser
+ .previous
+
+/*
+ * OSF/1 Unprivileged CALL_PAL Entry Points
+ */
+
+#define ORG_CALL_PAL_UNPRIV(X) .org 0x2000+64*(X-0x80)
+
+/*
+ * A helper routine for the unprivaledged kernel entry points, since the
+ * actual stack frame setup code is just a tad too large to fit inline.
+ *
+ * INPUT PARAMETERS:
+ *
+ * p5 = ps
+ * p6 = exc_addr
+ * p7 = return address
+ *
+ * SIDE EFFECTS:
+ *
+ * p0 is clobbered
+ *
+ */
+ .text 1
+CallPal_Stack_Frame:
+ // Test if we're currently in user mode
+ and p5, PS_M_CM, p0
+ beq p0, 0f
+CallPal_Stack_Frame_FromUser:
+ // Switch to kernel mode
+ mtpr $31, qemu_ps
+ mtpr $sp, qemu_usp
+ mfpr $sp, ptKsp
+0:
+ // Allocate the stack frame
+ lda $sp, -FRM_K_SIZE($sp)
+ stq p5, FRM_Q_PS($sp)
+ stq p6, FRM_Q_PC($sp)
+ stq $gp, FRM_Q_GP($sp)
+ stq a0, FRM_Q_A0($sp)
+ stq a1, FRM_Q_A1($sp)
+ stq a2, FRM_Q_A2($sp)
+ ret $31, (p7), 0
+ENDFN CallPal_Stack_Frame
+ .previous
+
+/*
+ * Breakpoint Trap
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * r16 (a0) = Code for bpt (0)
+ * r17 (a1) = UNPREDICTABLE
+ * r18 (a2) = UNPREDICTABLE
+ */
+ ORG_CALL_PAL_UNPRIV(0x80)
+CallPal_Bpt:
+ mfpr p5, qemu_ps
+ mfpr p6, qemu_exc_addr
+ bsr p7, CallPal_Stack_Frame
+
+ mfpr p0, ptEntIF
+ mfpr $gp, ptKgp
+ mov IF_K_BPT, a0
+ hw_ret (p0)
+ENDFN CallPal_Bpt
+
+/*
+ * Bugcheck Trap
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * r16 (a0) = Code for bugchk (1)
+ * r17 (a1) = UNPREDICTABLE
+ * r18 (a2) = UNPREDICTABLE
+ */
+ ORG_CALL_PAL_UNPRIV(0x81)
+CallPal_BugChk:
+ mfpr p5, qemu_ps
+ mfpr p6, qemu_exc_addr
+ bsr p7, CallPal_Stack_Frame
+
+ mfpr p0, ptEntIF
+ mfpr $gp, ptKgp
+ mov IF_K_BUGCHK, a0
+ hw_ret (p0)
+ENDFN CallPal_BugChk
+
+
+ ORG_CALL_PAL_UNPRIV(0x82)
+CallPal_OpcDec82:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec82
+
+/*
+ * System Call
+ */
+ ORG_CALL_PAL_UNPRIV(0x83)
+CallPal_CallSys:
+ mfpr p5, qemu_ps
+ mfpr p6, qemu_exc_addr
+
+ and p5, PS_M_CM, p0
+ beq p0, 0f
+
+ bsr p7, CallPal_Stack_Frame_FromUser
+
+ mfpr p0, ptEntSys
+ mfpr $gp, ptKgp
+ hw_ret (p0)
+
+0: subq p6, 4, p6 // Get PC of CALL_PAL insn
+ br MchkOSBugCheck
+ENDFN CallPal_CallSys
+
+ ORG_CALL_PAL_UNPRIV(0x84)
+CallPal_OpcDec84:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec84
+
+ ORG_CALL_PAL_UNPRIV(0x85)
+CallPal_OpcDec85:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec85
+
+
+/*
+ * I-Stream Memory Barrier
+ *
+ * For QEMU, this is of course a no-op.
+ */
+ ORG_CALL_PAL_UNPRIV(0x86)
+CallPal_Imb:
+ hw_rei
+ENDFN CallPal_Imb
+
+
+ ORG_CALL_PAL_UNPRIV(0x87)
+CallPal_OpcDec87:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec87
+
+ ORG_CALL_PAL_UNPRIV(0x88)
+CallPal_OpcDec88:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec88
+
+ ORG_CALL_PAL_UNPRIV(0x89)
+CallPal_OpcDec89:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec89
+
+ ORG_CALL_PAL_UNPRIV(0x8A)
+CallPal_OpcDec8A:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec8A
+
+ ORG_CALL_PAL_UNPRIV(0x8B)
+CallPal_OpcDec8B:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec8B
+
+ ORG_CALL_PAL_UNPRIV(0x8C)
+CallPal_OpcDec8C:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec8C
+
+ ORG_CALL_PAL_UNPRIV(0x8D)
+CallPal_OpcDec8D:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec8D
+
+ ORG_CALL_PAL_UNPRIV(0x8E)
+CallPal_OpcDec8E:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec8E
+
+ ORG_CALL_PAL_UNPRIV(0x8F)
+CallPal_OpcDec8F:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec8F
+
+ ORG_CALL_PAL_UNPRIV(0x90)
+CallPal_OpcDec90:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec90
+
+ ORG_CALL_PAL_UNPRIV(0x91)
+CallPal_OpcDec91:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec91
+
+ ORG_CALL_PAL_UNPRIV(0x92)
+CallPal_OpcDec92:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec92
+
+ ORG_CALL_PAL_UNPRIV(0x93)
+CallPal_OpcDec93:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec93
+
+ ORG_CALL_PAL_UNPRIV(0x94)
+CallPal_OpcDec94:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec94
+
+ ORG_CALL_PAL_UNPRIV(0x95)
+CallPal_OpcDec95:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec95
+
+ ORG_CALL_PAL_UNPRIV(0x96)
+CallPal_OpcDec96:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec96
+
+ ORG_CALL_PAL_UNPRIV(0x97)
+CallPal_OpcDec97:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec97
+
+ ORG_CALL_PAL_UNPRIV(0x98)
+CallPal_OpcDec98:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec98
+
+ ORG_CALL_PAL_UNPRIV(0x99)
+CallPal_OpcDec99:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec99
+
+ ORG_CALL_PAL_UNPRIV(0x9A)
+CallPal_OpcDec9A:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec9A
+
+ ORG_CALL_PAL_UNPRIV(0x9B)
+CallPal_OpcDec9B:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec9B
+
+ ORG_CALL_PAL_UNPRIV(0x9C)
+CallPal_OpcDec9C:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec9C
+
+ ORG_CALL_PAL_UNPRIV(0x9D)
+CallPal_OpcDec9D:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDec9D
+
+/*
+ * Read Unique Value
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * r0 (v0) = Returned process unique value
+*/
+ ORG_CALL_PAL_UNPRIV(0x9E)
+CallPal_RdUnique:
+ mfpr v0, qemu_unique
+ hw_rei
+ENDFN CallPal_RdUnique
+
+/*
+ * Write Unique Value
+ *
+ * INPUT PARAMETERS:
+ *
+ * r16 (a0) = New process unique value
+ */
+ ORG_CALL_PAL_UNPRIV(0x9F)
+CallPal_WrUnique:
+ mtpr a0, qemu_unique
+ hw_rei
+ENDFN CallPal_WrUnique
+
+ ORG_CALL_PAL_UNPRIV(0xA0)
+CallPal_OpcDecA0:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecA0
+
+ ORG_CALL_PAL_UNPRIV(0xA1)
+CallPal_OpcDecA1:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecA1
+
+ ORG_CALL_PAL_UNPRIV(0xA2)
+CallPal_OpcDecA2:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecA2
+
+ ORG_CALL_PAL_UNPRIV(0xA3)
+CallPal_OpcDecA3:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecA3
+
+ ORG_CALL_PAL_UNPRIV(0xA4)
+CallPal_OpcDecA4:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecA4
+
+ ORG_CALL_PAL_UNPRIV(0xA5)
+CallPal_OpcDecA5:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecA5
+
+ ORG_CALL_PAL_UNPRIV(0xA6)
+CallPal_OpcDecA6:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecA6
+
+ ORG_CALL_PAL_UNPRIV(0xA7)
+CallPal_OpcDecA7:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecA7
+
+ ORG_CALL_PAL_UNPRIV(0xA8)
+CallPal_OpcDecA8:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecA8
+
+ ORG_CALL_PAL_UNPRIV(0xA9)
+CallPal_OpcDecA9:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecA9
+
+/*
+ * Generate Trap
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * r16 (a0) = Code for gentrap (2)
+ * r17 (a1) = UNPREDICTABLE
+ * r18 (a2) = UNPREDICTABLE
+ */
+ ORG_CALL_PAL_UNPRIV(0xAA)
+CallPal_GenTrap:
+ mfpr p5, qemu_ps
+ mfpr p6, qemu_exc_addr
+ bsr p7, CallPal_Stack_Frame
+
+ mfpr p0, ptEntIF
+ mfpr $gp, ptKgp
+ mov IF_K_GENTRAP, a0
+ hw_ret (p0)
+ENDFN CallPal_GenTrap
+
+ ORG_CALL_PAL_UNPRIV(0xAB)
+CallPal_OpcDecAB:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecAB
+
+ ORG_CALL_PAL_UNPRIV(0xAC)
+CallPal_OpcDecAC:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecAC
+
+ ORG_CALL_PAL_UNPRIV(0xAD)
+CallPal_OpcDecAD:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecAD
+
+ ORG_CALL_PAL_UNPRIV(0xAE)
+CallPal_OpcDecAE:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecAE
+
+ ORG_CALL_PAL_UNPRIV(0xAF)
+CallPal_OpcDecAF:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecAF
+
+ ORG_CALL_PAL_UNPRIV(0xB0)
+CallPal_OpcDecB0:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecB0
+
+ ORG_CALL_PAL_UNPRIV(0xB1)
+CallPal_OpcDecB1:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecB1
+
+ ORG_CALL_PAL_UNPRIV(0xB2)
+CallPal_OpcDecB2:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecB2
+
+ ORG_CALL_PAL_UNPRIV(0xB3)
+CallPal_OpcDecB3:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecB3
+
+ ORG_CALL_PAL_UNPRIV(0xB4)
+CallPal_OpcDecB4:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecB4
+
+ ORG_CALL_PAL_UNPRIV(0xB5)
+CallPal_OpcDecB5:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecB5
+
+ ORG_CALL_PAL_UNPRIV(0xB6)
+CallPal_OpcDecB6:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecB6
+
+ ORG_CALL_PAL_UNPRIV(0xB7)
+CallPal_OpcDecB7:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecB7
+
+ ORG_CALL_PAL_UNPRIV(0xB8)
+CallPal_OpcDecB8:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecB8
+
+ ORG_CALL_PAL_UNPRIV(0xB9)
+CallPal_OpcDecB9:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecB9
+
+ ORG_CALL_PAL_UNPRIV(0xBA)
+CallPal_OpcDecBA:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecBA
+
+ ORG_CALL_PAL_UNPRIV(0xBB)
+CallPal_OpcDecBB:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecBB
+
+ ORG_CALL_PAL_UNPRIV(0xBC)
+CallPal_OpcDecBC:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecBC
+
+ ORG_CALL_PAL_UNPRIV(0xBD)
+CallPal_OpcDecBD:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecBD
+
+ ORG_CALL_PAL_UNPRIV(0xBE)
+CallPal_OpcDecBE:
+ br CallPal_OpcDec
+ENDFN CallPal_OpcDecBE
+
+ ORG_CALL_PAL_UNPRIV(0xBF)
+CallPal_OpcDec:
+ mfpr p5, qemu_ps
+ mfpr p6, qemu_exc_addr
+ bsr p7, CallPal_Stack_Frame
+
+ mfpr p0, ptEntIF
+ mfpr $gp, ptKgp
+ mov IF_K_OPCDEC, a0
+ hw_ret (p0)
+ENDFN CallPal_OpcDec
+
+ .org 0x3000
+ .text 1
+/*
+ * PALcode detected processor machine check handler.
+ *
+ * The PALcode-detected machine check handler loads a code
+ * indicating the type of machine check error, loads
+ * the System Control Block (SCB) vector for the
+ * processor machine check service routine, sets the
+ * Machine-Check-In-Progress (MIP) flag in the Machine
+ * Check Error Summary register (MCES), and merges
+ * with the common machine check flow.
+ *
+ * If a second processor machine check error condition
+ * is detected while the MIP flag is set, the processor
+ * is forced into console I/O mode indicating "double
+ * error abort encountered" as the reason for the halt.
+ *
+ * CALLING SEQUENCE:
+ *
+ * Called when an internal processor error is detected
+ * that cannot be successfully corrected by hardware or
+ * PALcode.
+ *
+ * INPUT PARAMETERS:
+ *
+ * r14 (p6) = Exception address
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * ptMchk0 = saved v0
+ * ptMchk1 = saved t0
+ * ptMchk2 = saved t3
+ * ptMchk3 = saved t4
+ * ptMchk4 = saved t5
+ * ptMchk5 = saved exc_addr
+ * ptMisc<47:32> = MCHK code
+ * ptMisc<31:16> = SCB vector
+ * ptMces<MIP> = Set
+ *
+ * SIDE EFFECTS:
+ *
+ * r0 (v0), r1 (t0), and r4..r6 (t3..t5) are saved in
+ * PAL temporaries and are available for use as scratch
+ * registers by the system specific machine check
+ * handler.
+ */
+
+MchkBugCheck:
+MchkOSBugCheck:
+ halt
+ENDFN MchkBugCheck
+
+/*
+ * Common Machine Check Handler
+ *
+ * INPUT STATE:
+ *
+ * ptMchk0 Saved v0
+ * ptMchk1 Saved t0
+ * ptMchk2 Saved t3
+ * ptMchk3 Saved t4
+ * ptMchk4 Saved t5
+ * ptMchk5 Saved exc_addr
+ * ptMisc<47:32> MCHK code
+ * ptMisc<31:16> SCB vector
+ * ptMces<MIP> Set
+ *
+ * Registers v0, t0, and t3 .. t5 are available for use, in
+ * addition to the shadow registers.
+ */
+
+MchkCommon:
+ halt
+ENDFN MchkCommon
+
+/*
+ * Build Machine Check Logout Frame
+ *
+ * This portion of the machine check handler builds a logout frame
+ * in the PAL impure scratch area, builds a stack frame on the kernel
+ * stack (already built if there was an interrupt machine check),
+ * loads the GP with the KGP, loads the machine check entry
+ * code in a0, loads a platform-specific interrupt vector
+ * (typically the same value as the SCB offset) in a1, loads
+ * the kseg address of the logout area in a2, and dispatches
+ * to the kernel interrupt handler pointed to by the entInt
+ * operating system entry point.
+ *
+ * OUTPUT PARAMETERS:
+ *
+ * a0 (r16) = Machine check entry type
+ * a1 (r17) = Platform-specific interrupt vector
+ * a2 (r18) = Pointer to logout area
+ */
+
+.macro STORE_IPR which, offset, base
+ mfpr v0, \which
+ stq_p v0, \offset(\base)
+.endm
+
+MchkLogOut:
+ halt
+ENDFN MchkLogOut
+
+MchkDouble:
+ bsr p7, UpdatePCB
+ lda v0, HLT_K_DBL_MCHK
+ br Sys_EnterConsole
+ENDFN MchkDouble
+
+MchkFromPal:
+ bsr p7, UpdatePCB
+ lda v0, HLT_K_MCHK_FROM_PAL
+ br Sys_EnterConsole
+ENDFN MchkFromPal
+
+MchkKspInvalid:
+ bsr p7, UpdatePCB
+ lda v0, HLT_K_KSP_INVAL
+ br Sys_EnterConsole
+ENDFN MchkKspInvalid
+
+/*
+ * Update the current PCB with new SP and CC info.
+ *
+ * INPUT PARAMETERS:
+ *
+ * p7 = return linkage
+ */
+
+UpdatePCB:
+ rpcc p5
+ mfpr p4, ptPcbb
+
+ mfpr p3, qemu_ps // Check current mode
+ and p3, PS_M_CM, p3
+ beq p3, 1f
+
+ mtpr $sp, qemu_usp // Save user stack pointer
+ stq_p $sp, PCB_Q_USP(p4)
+ br 2f
+
+1: mtpr $sp, ptKsp // Save kernel stack pointer
+ stq_p $sp, PCB_Q_KSP(p4)
+
+2: srl p5, 32, p3 // Merge for new time
+ addl p5, p3, p3
+ stl_p p3, PCB_L_PCC(p4) // Store new time
+
+ mfpr p5, qemu_unique // Save unique
+ stq_p p5, PCB_Q_UNIQUE(p4)
+
+ ret $31, (p7), 0
+ENDFN UpdatePCB
+
+/*
+ * FIXME
+ */
+Sys_EnterConsole:
+ halt
+
+/*
+ * Allocate the initial bootup stack.
+ */
+
+ .section .bss.stack
+ .align 3
+ .globl stack
+ .type stack,@object
+ .size stack,STACK_SIZE
+stack: .skip STACK_SIZE