NT4/private/ntos/fw/mips/x4trap.s
2020-09-30 17:12:29 +02:00

1069 lines
33 KiB
ArmAsm
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#if defined(JAZZ) && defined(R4000)
// TITLE("Interrupt and Exception Processing")
//++
//
// Copyright (c) 1991 Microsoft Corporation
//
// Module Name:
//
// j4trap.s
//
// Abstract:
//
// This module implements the code necessary to field and process MIPS
// interrupt and exception conditions during bootstrap.
//
// Author:
//
// David N. Cutler (davec) 21-Apr-1991
//
// Environment:
//
// Kernel mode only.
//
// Revision History:
//
//--
#include "ksmips.h"
SBTTL("Constant Value Definitions")
//++
//
// The following are definitions of constants used in this module.
//
//--
#define PSR_MASK (~((0x3 << PSR_KSU) | (1 << PSR_EXL))) // PSR exception mask
//++
//
// Define dummy data allocation.
//
//--
.data
.space 4 //
SavedK1Address:
.space 4 // address where to save k1 to return to fw.
SBTTL("General Exception Vector Routine")
//++
//
// Routine Description:
//
// This routine is entered as the result of a general exception. The reason
// for the exception is contained in the cause register. When this routine
// is entered, interrupts are disabled.
//
// All exception that occur during the bootstrap process are treated as
// if a breakpoint had occurred. This ultimately causes either the kernel
// debugger or a stub routine provided by the bootstrap itself to be
// invoked.
//
// The address of this routine is copied to the GEV in the SPB
// so that the firmware jumps to this routine when a GeneralException
// occurres. This routine must return to the address pointed by k1.
// and leave the address where the firmware must return from the
// exception in k0.
//
//
//
// Arguments:
//
// None.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiGeneralException)
//
// No TLB Miss is supposed to occurr during the boot process
// The TbMiss handler is just the same general exception handler.
//
ALTERNATE_ENTRY(KiTbMiss)
START_REGION(KiGeneralExceptionStartAddress)
.set noreorder
.set noat
la k0,10f // transfer immediately to physical
j k0 //
nop //
10: subu k0,sp,TrapFrameLength // allocate trap frame
sw sp,TrIntSp(k0) // save integer register sp
move sp,k0 // set new stack pointer
la k0,SavedK1Address // get address of where to save k1
sw k1,0(k0) // save firmware return address
sw gp,TrIntGp(sp) // save integer register gp
sw s8,TrIntS8(sp) // save integer register s8
sw ra,TrIntRa(sp) // save integer register ra
mfc0 s8,cause // get cause of exception
mfc0 k0,psr // get current processor status
mfc0 k1,epc // get exception PC
sw k0,TrPsr(sp) // save current PSR
sw k1,TrFir(sp) // save exception PC
bgez s8,20f // if gez, exception not in delay slot
move s8,sp // set address of trap frame
addu k1,k1,4 // compute address of exception
20: j KiBreakpointException // finish in breakpoint code
nop // fill delay slot
.set at
.set reorder
END_REGION(KiGeneralExceptionEndAddress)
.end KiGeneralException
SBTTL("Breakpoint Dispatch")
//++
//
// Routine Description:
//
// The following code is never executed. Its purpose is to allow the
// kernel debugger to walk call frames backwards through an exception,
// to support unwinding through exceptions for system services, and to
// support get/set user context.
//
//--
NESTED_ENTRY(KiBreakpointDispatch, TrapFrameLength, zero);
.set noreorder
.set noat
sw sp,TrIntSp(sp) // save stack pointer
sw ra,TrIntRa(sp) // save return address
sw ra,TrFir(sp) // save return address
sw s8,TrIntS8(sp) // save frame pointer
sw gp,TrIntGp(sp) // save general pointer
move s8,sp // set frame pointer
.set at
.set reorder
PROLOGUE_END
//++
//
// Routine Description:
//
// Control reaches here when a breakpoint exception code is read from the
// cause register. When this routine is entered, interrupts are disabled.
//
// The function of this routine is to raise a breakpoint exception.
//
// N.B. Integer register v1 is not usuable in the first instuction of the
// routine.
//
// Arguments:
//
// k0 - Supplies the current PSR with the EXL bit set.
// k1 - Supplies the address of the faulting instruction.
// gp - Supplies a pointer to the system short data area.
// s8 - Supplies a pointer to the trap frame.
//
// Return Value:
//
// None.
//
//--
ALTERNATE_ENTRY(KiBreakpointException)
GENERATE_TRAP_FRAME // save volatile machine state
addu a0,s8,TrExceptionRecord // compute exception record address
sw k1,ErExceptionAddress(a0) // save address of exception
lw t0,0(k1) // get actual breakpoint instruction
.set noreorder
.set noat
mfc0 k0,cause // get cause of exception
.set at
.set reorder
li t1,XCODE_BREAKPOINT // get exception code for breakpoint
li t2,STATUS_BREAKPOINT // set exception status code
and k0,k0,R4000_XCODE_MASK // isolate exception code
beq k0,t1,10f // if eq, breakpoint
move t2,k0 // set status to cause value
10: sw t0,ErExceptionInformation(a0) // save breakpoint instruction
sw t2,ErExceptionCode(a0) //
sw zero,ErExceptionFlags(a0) // set exception flags
sw zero,ErExceptionRecord(a0) // set associated record
sw zero,ErNumberParameters(a0) // set number of parameters
jal KiExceptionDispatch // join common code
b 10b // dummy
.end KiBreakpointDispatch
SBTTL("Exception Dispatch")
//++
//
// Routine Desription:
//
// Control is transfered to this routine to call the exception
// dispatcher to resolve an exception.
//
// Arguments:
//
// a0 - Supplies a pointer to an exception record.
//
// s8 - Supplies a pointer to a trap frame.
//
// Return Value:
//
// There is no return from this routine.
//
//--
NESTED_ENTRY(KiExceptionDispatch, ExceptionFrameLength, zero)
subu sp,sp,ExceptionFrameLength // allocate exception frame
sw ra,ExIntRa(sp) // save return address
sw s0,ExIntS0(sp) // save integer registers s0 - s7
sw s1,ExIntS1(sp) //
sw s2,ExIntS2(sp) //
sw s3,ExIntS3(sp) //
sw s4,ExIntS4(sp) //
sw s5,ExIntS5(sp) //
sw s6,ExIntS6(sp) //
sw s7,ExIntS7(sp) //
sdc1 f20,ExFltF20(sp) // save floating registers f20 - f31
sdc1 f22,ExFltF22(sp) //
sdc1 f24,ExFltF24(sp) //
sdc1 f26,ExFltF26(sp) //
sdc1 f28,ExFltF28(sp) //
sdc1 f30,ExFltF30(sp) //
PROLOGUE_END
//
// Call the exception dispatcher.
//
move a1,sp // set exception frame address
move a2,s8 // set trap frame address
move a3,zero // set previous processor mode
li t0,TRUE // set first chance TRUE
sw t0,ExArgs + (4 * 4)(sp) //
jal KiDispatchException // call exception dispatcher
//
// Restore the nonvolatile registers.
//
lw s0,ExIntS0(sp) // restore integer registers s0 - s7
lw s1,ExIntS1(sp) //
lw s2,ExIntS2(sp) //
lw s3,ExIntS3(sp) //
lw s4,ExIntS4(sp) //
lw s5,ExIntS5(sp) //
lw s6,ExIntS6(sp) //
lw s7,ExIntS7(sp) //
ldc1 f20,ExFltF20(sp) // restore floating registers f20 - f31
ldc1 f22,ExFltF22(sp) //
ldc1 f24,ExFltF24(sp) //
ldc1 f26,ExFltF26(sp) //
ldc1 f28,ExFltF28(sp) //
ldc1 f30,ExFltF30(sp) //
//
// Exit from the exception.
//
lw t0,TrPsr(s8) // get previous processor status
lw gp,TrIntGp(s8) // restore integer register gp
li t3,(1 << PSR_CU1) | (1 << PSR_EXL) // ****** r4000 errata
.set noreorder
.set noat
mtc0 t3,psr // ****** r4000 errata
nop // ****** r4000 errata
nop // ****** r4000 errata
nop // ****** r4000 errata
mtc0 t0,psr // disable interrupts
nop // ****** r4000 errata
jal KiRestoreTrapFrame // restore volatile state
lw AT,TrIntAt(s8) // restore integer register at
move sp,s8 // trim stack to trap frame
la k0,SavedK1Address // get address of where to save k1
lw k1,(k0) // save firmware return address
lw k0,TrFir(sp) // get continuation address
lw s8,TrIntS8(sp) // restore integer register s8
lw ra,TrIntRa(sp) // restore return address
j k1 // return to firmware
lw sp,TrIntSp(sp) // restore stack pointer
.set at
.set reorder
.end KiExceptionDispatch
SBTTL("Fill Fixed Translation Buffer Entry")
//++
//
// VOID
// KeFillFixedEntryTb (
// IN HARDWARE_PTE Pte[],
// IN PVOID Virtual,
// IN ULONG Index
// )
//
// Routine Description:
//
// This function fills a fixed translation buffer entry.
//
// Arguments:
//
// Pte (a0) - Supplies a pointer to the page table entries that are to be
// written into the TB.
//
// Virtual (a1) - Supplies the virtual address of the entry that is to
// be filled in the translation buffer.
//
// Index (a2) - Supplies the index where the TB entry is to be written.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KeFillFixedEntryTb)
lw t0,0(a0) // get first PTE value
lw t1,4(a0) // get second PTE value
DISABLE_INTERRUPTS(t2) // disable interrupts
.set noreorder
.set noat
mfc0 t3,entryhi // get current PID and VPN2
srl a1,a1,ENTRYHI_VPN2 // isolate VPN2 of virtual address
sll a1,a1,ENTRYHI_VPN2 //
and t3,t3,0xff << ENTRYHI_PID // isolate current PID
or a1,t3,a1 // merge PID with VPN2 of virtual address
mtc0 a1,entryhi // set VPN2 and PID for probe
mtc0 t0,entrylo0 // set first PTE value
mtc0 t1,entrylo1 // set second PTE value
mtc0 a2,index // set TB entry index
nop // 1 cycle hazzard
tlbwi // overwrite indexed TB entry
nop // 3 cycle hazzard
.set at
.set reorder
ENABLE_INTERRUPTS(t2) // enable interrupts
j ra // return
.end KeFillFixedEntryTb
SBTTL("Flush Entire Translation Buffer")
//++
//
// VOID
// KiFlushEntireTb (
// )
//
// Routine Description:
//
// This function flushes the random part of the translation buffer.
//
// Arguments:
//
// None.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiFlushEntireTb)
b KiFlushRandomTb // execute common code
.end KiFlushEntireTb
SBTTL("Flush Fixed Translation Buffer Entries")
//++
//
// VOID
// KiFlushFixedTb (
// )
//
// Routine Description:
//
// This function is called to flush all the fixed entries from the
// translation buffer.
//
// Arguments:
//
// None.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiFlushFixedTb)
li t0,FIXED_BASE // set base index of fixed TB entries
li t3,FIXED_ENTRIES // set number of fixed TB entries
b KiFlushTb //
.end KiFlushFixedTb
SBTTL("Flush Random Translation Buffer Entries")
//++
//
// VOID
// KiFlushRandomTb (
// )
//
// Routine Description:
//
// This function is called to flush all the random entries from the TB.
//
// Arguments:
//
// None.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiFlushRandomTb)
li t0,FIXED_ENTRIES // set base index of random TB entries
li t3,(48 - FIXED_ENTRIES) // set number of random TB entries
ALTERNATE_ENTRY(KiFlushTb)
li t4,KSEG0_BASE // set high part of TB entry
DISABLE_INTERRUPTS(t2) // disable interrupts
.set noreorder
.set noat
addu t3,t0,t3 // set index of highest entry + 1
sll t0,t0,INDEX_INDEX // shift starting index into position
sll t3,t3,INDEX_INDEX // shift ending index into position
mfc0 t1,entryhi // save contents of entryhi
mtc0 zero,entrylo0 // set low part of TB entry
mtc0 zero,entrylo1 //
mtc0 t4,entryhi //
mtc0 t0,index // set TB entry index
10: addu t0,t0,1 //
nop // ****** r4000 errata
nop // ****** r4000 errata
nop // ****** r4000 errata
nop // ****** r4000 errata
tlbwi // write TB entry
bne t0,t3,10b // if ne, more entries to flush
mtc0 t0,index // set TB entry index
nop // ****** r4000 errata
nop // ****** r4000 errata
nop // ****** r4000 errata
mtc0 t1,entryhi // restore contents of entryhi
nop // ****** r4000 errata
nop // ****** r4000 errata
nop // ****** r4000 errata
.set at
.set reorder
ENABLE_INTERRUPTS(t2) // enable interrupts
j ra // return
.end KiFlushRandomTb
SBTTL("Flush Single Translation Buffer Entry")
//++
//
// VOID
// KiFlushSingleTb (
// IN BOOLEAN Invalid,
// IN PVOID Virtual
// )
//
// Routine Description:
//
// This function flushes a single entry from the translation buffer.
//
// Arguments:
//
// Invalid (a0) - Supplies a boolean variable that determines the reason
// that the TB entry is being flushed.
//
// Virtual (a1) - Supplies the virtual address of the entry that is to
// be flushed from the translation buffer.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiFlushSingleTb)
DISABLE_INTERRUPTS(t0) // disable interrupts
.set noreorder
.set noat
srl t1,a1,ENTRYHI_VPN2 // clear all but VPN2 of virtual address
mfc0 t2,entryhi // get current PID and VPN2
sll t1,t1,ENTRYHI_VPN2 //
and t2,t2,0xff << ENTRYHI_PID // isolate current PID
or t1,t1,t2 // merge PID with VPN2 of virtual address
mtc0 t1,entryhi // set VPN2 and PID for probe
nop // 3 cycle hazzard
nop //
nop //
nop // ****** r4000 errata
nop // ****** r4000 errata
tlbp // probe for entry in TB
nop // 2 cycle hazzard
nop //
mfc0 t3,index // read result of probe
nop // 1 cycle hazzard
bltz t3,30f // if ltz, entry is not in TB
sll t1,a1,0x1f - (ENTRYHI_VPN2 - 1) // shift low bit of VPN into sign
bltzl t1,10f // if ltz, invalidate second PTE
mtc0 zero,entrylo1 // clear second PTE for flush
mtc0 zero,entrylo0 // clear first PTE for flush
10: nop // 1 cycle hazzard
nop // ****** r4000 errata
nop // ****** r4000 errata
nop // ****** r4000 errata
nop // ****** r4000 errata
tlbwi // overwrite index TB entry
nop // 3 cycle hazzard
nop // ****** r4000 errata
nop // ****** r4000 errata
.set at
.set reorder
30: ENABLE_INTERRUPTS(t0) // enable interrupts
j ra // return
.end KiFlushSingleTb
SBTTL("Probe Tb Entry")
//++
//
// ULONG
// KiProbeEntryTb (
// IN PVOID VirtualAddress
// )
//
// Routine Description:
//
// This function is called to determine if a specified entry is valid
/// and within the fixed portion of the TB.
//
// Arguments:
//
// VirtualAddress - Supplies the virtual address to probe.
//
// Return Value:
//
// A value of TRUE is returned if the specified entry is valid and within
// the fixed part of the TB. Otherwise, a value of FALSE is returned.
//
//--
LEAF_ENTRY(KiProbeEntryTb)
DISABLE_INTERRUPTS(t0) // disable interrupts
.set noreorder
.set noat
srl t1,a0,ENTRYHI_VPN2 // clear all but VPN2 of virtual address
mfc0 t2,entryhi // get current PID and VPN2
sll t1,t1,ENTRYHI_VPN2 //
and t2,t2,0xff << ENTRYHI_PID // isolate current PID
or t1,t1,t2 // merge PID with VPN2 of virtual address
mtc0 t1,entryhi // set VPN2 and PID for probe
nop // 3 cycle hazzard
nop //
nop //
nop // ****** r4000 errata
nop // ****** r4000 errata
tlbp // probe for entry in TB
nop // 2 cycle hazzard
nop //
mfc0 t2,index // read result of probe
nop // 1 cycle hazzard
bltz t2,20f // if ltz, entry is not in TB
li v0,FALSE // set to return failure
tlbr // read entry from TB
nop // 3 cycle hazzard
nop //
nop //
nop // ****** r4000 errata
nop // ****** r4000 errata
sll t1,a0,0x1f - (ENTRYHI_VPN2 - 1) // shift low bit of VPN into sign
bltzl t1,10f // if ltz, check second PTE
mfc0 t1,entrylo1 // get second PTE for probe
mfc0 t1,entrylo0 // get first PTE for probe
10: nop // 1 cycle hazzard
sll t1,t1,0x1f - ENTRYLO_V // shift valid bit into sign position
bgez t1,20f // if geq, entry is not valid
srl t2,INDEX_INDEX // isolate index
and t2,t2,0x3f //
sltu v0,t2,FIXED_ENTRIES // check if entry in fixed part of TB
.set at
.set reorder
20: ENABLE_INTERRUPTS(t0) // enable interrupts
.end KiProbeEntryTb
SBTTL("Read Tb Entry")
//++
//
// VOID
// KiReadEntryTb (
// IN ULONG Index,
// OUT PULONG EntryLo[],
// OUT PULONG EntryHi
// )
//
// Routine Description:
//
// This function is called to read an entry from the TB.
//
// Arguments:
//
// Index - Supplies the index of the entry to read.
//
// entrylo - Supplies a pointer to a array that receives the first and
// second TB entry values.
//
// EntryHi - Supplies a pointer to a variable that receives the high
// part of the TB entry.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiReadEntryTb)
DISABLE_INTERRUPTS(t0) // disable interrupts
.set noreorder
.set noat
sll a0,INDEX_INDEX // shift index into position
mfc0 t1,entryhi // save entry high register
mtc0 a0,index // set TB entry index
nop //
nop // ****** r4000 errate
nop // ****** r4000 errate
nop // ****** r4000 errate
nop // ****** r4000 errate
tlbr // read entry from TB
nop // 3 cycle hazzard
nop //
nop //
nop // ****** r4000 errate
nop // ****** r4000 errate
mfc0 t2,entrylo0 // save first PTE value
mfc0 t3,entrylo1 // save second PTE value
mfc0 t4,entryhi // save entry high register
mtc0 t1,entryhi // restore entry high register
nop // ****** r4000 errate
nop // ****** r4000 errate
nop // ****** r4000 errate
nop // ****** r4000 errate
nop // ****** r4000 errate
.set at
.set reorder
ENABLE_INTERRUPTS(t0) // enable interrupts
sw t2,0(a1) // set first PTE value
sw t3,4(a1) // set second PTE value
sw t4,0(a2) // set entry high register value
j ra // return
.end KiReadEntryTb
SBTTL("Flush Write Buffer")
//++
//
// VOID
// KeFlushWriteBuffer (
// VOID
// )
//
// Routine Description:
//
// This function flushes the write buffer on the current processor.
//
// Arguments:
//
// None.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KeFlushWriteBuffer)
j ra // return
.end KeFlushWritebuffer
//++
//
// BOOLEAN
// KiDisableInterrupts (
// VOID
// )
//
// Routine Description:
//
// This function disables interrupts and returns whether interrupts
// were previously enabled.
//
// Arguments:
//
// None.
//
// Return Value:
//
// A boolean value that determines whether interrupts were previously
// enabled (TRUE) or disabled(FALSE).
//
//--
LEAF_ENTRY(KiDisableInterrupts)
.set noreorder
.set noat
mfc0 t0,psr // get current processor status
li t1,~(1 << PSR_IE) // set interrupt enable mask
and t2,t1,t0 // clear interrupt enable
mtc0 t2,psr // disable interrupts
and v0,t0,1 << PSR_IE // iosolate current interrupt enable
srl v0,v0,PSR_IE //
.set at
.set reorder
j ra // return
.end KiDisableInterrupts
SBTTL("Restore Interrupts")
//++
//
// VOID
// KiRestoreInterrupts (
// IN BOOLEAN Enable
// )
//
// Routine Description:
//
// This function restores the interrupt enable that was returned by
// the disable interrupts function.
//
// Arguments:
//
// Enable (a0) - Supplies the interrupt enable value.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiRestoreInterrupts)
.set noreorder
.set noat
mfc0 t0,psr // get current processor status
sll t1,a0,PSR_IE // shift previous enable into position
or t1,t1,t0 // merge previous enable
mtc0 t1,psr // restore previous interrupt enable
nop //
.set at
.set reorder
j ra // return
.end KiRestoreInterrupts
SBTTL("Generate Trap Frame")
//++
//
// Routine Desription:
//
// This routine is called to save the volatile integer and floating
// registers in a trap frame.
//
// N.B. This routine uses a special argument passing mechanism and destroys
// no registers. It is assumed that integer register AT is saved by the
// caller.
//
// Arguments:
//
// s8 - Supplies a pointer to the base of an trap frame.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiGenerateTrapFrame)
sw v0,TrIntV0(s8) // save integer register v0
sw v1,TrIntV1(s8) // save integer register v1
mflo v1 // save lo integer register
sw v1,TrIntLo(s8) //
mfhi v1 // save hi integer register
sw v1,TrIntHi(s8) //
lw v1,TrIntV1(s8) // restore integer register v1
sw a0,TrIntA0(s8) // save integer registers a0 - a3
sw a1,TrIntA1(s8) //
sw a2,TrIntA2(s8) //
sw a3,TrIntA3(s8) //
sw t0,TrIntT0(s8) // save integer registers t0 - t9
sw t1,TrIntT1(s8) //
sw t2,TrIntT2(s8) //
sw t3,TrIntT3(s8) //
sw t4,TrIntT4(s8) //
sw t5,TrIntT5(s8) //
sw t6,TrIntT6(s8) //
sw t7,TrIntT7(s8) //
sw t8,TrIntT8(s8) //
sw t9,TrIntT9(s8) //
#if defined(R3000)
swc1 f0,TrFltF0(s8) // save floating register f0
#endif
#if defined(R4000)
sdc1 f0,TrFltF0(s8) // save floating register f0
#endif
b KiSaveVolatileFloatState // save remainder of state
.end KiGenerateTrapFrame
SBTTL("Restore Trap Frame")
//++
//
// Routine Description:
//
// This routine is called to restore the volatile integer and floating
// registers from a trap frame.
//
// N.B. This routine uses a special argument passing mechanism and destroys
// no registers. It is assumed that integer register AT is restored by
// the caller.
//
// Arguments:
//
// sp - Supplies a pointer to an exception frame.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiRestoreTrapFrame)
lw v0,TrIntV0(s8) // restore integer register v0
lw v1,TrIntV1(s8) // restore integer register v1
lw a0,TrIntA0(s8) // restore integer registers a0 - a3
lw a1,TrIntA1(s8) //
lw a2,TrIntA2(s8) //
lw a3,TrIntA3(s8) //
lw t0,TrIntLo(s8) // restore lo and hi integer registers
lw t1,TrIntHi(s8) //
mtlo t0 //
mthi t1 //
lw t0,TrIntT0(s8) // restore integer registers t0 - t9
lw t1,TrIntT1(s8) //
lw t2,TrIntT2(s8) //
lw t3,TrIntT3(s8) //
lw t4,TrIntT4(s8) //
lw t5,TrIntT5(s8) //
lw t6,TrIntT6(s8) //
lw t7,TrIntT7(s8) //
lw t8,TrIntT8(s8) //
lw t9,TrIntT9(s8) //
#if defined(R3000)
lwc1 f0,TrFltF0(s8) // restore floating register f0
#endif
#if defined(R4000)
ldc1 f0,TrFltF0(s8) // restore floating register f0
#endif
b KiRestoreVolatileFloatState // restore remainder of state
.end KiRestoreTrapFrame
SBTTL("Save Volatile Floating Registers")
//++
//
// Routine Desription:
//
// This routine is called to save the volatile floating registers.
//
// N.B. This routine uses a special argument passing mechanism and destroys
// no registers. It is assumed that floating register f0 is saved by the
// caller.
//
// Arguments:
//
// s8 - Supplies a pointer to a trap frame.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiSaveVolatileFloatState)
#if defined(R3000)
swc1 f1,TrFltF1(s8) // save floating register f1 - f19
swc1 f2,TrFltF2(s8) //
swc1 f3,TrFltF3(s8) //
swc1 f4,TrFltF4(s8) //
swc1 f5,TrFltF5(s8) //
swc1 f6,TrFltF6(s8) //
swc1 f7,TrFltF7(s8) //
swc1 f8,TrFltF8(s8) //
swc1 f9,TrFltF9(s8) //
swc1 f10,TrFltF10(s8) //
swc1 f11,TrFltF11(s8) //
swc1 f12,TrFltF12(s8) //
swc1 f13,TrFltF13(s8) //
swc1 f14,TrFltF14(s8) //
swc1 f15,TrFltF15(s8) //
swc1 f16,TrFltF16(s8) //
swc1 f17,TrFltF17(s8) //
swc1 f18,TrFltF18(s8) //
swc1 f19,TrFltF19(s8) //
#endif
#if defined(R4000)
sdc1 f2,TrFltF2(s8) // save floating register f2 - f19
sdc1 f4,TrFltF4(s8) //
sdc1 f6,TrFltF6(s8) //
sdc1 f8,TrFltF8(s8) //
sdc1 f10,TrFltF10(s8) //
sdc1 f12,TrFltF12(s8) //
sdc1 f14,TrFltF14(s8) //
sdc1 f16,TrFltF16(s8) //
sdc1 f18,TrFltF18(s8) //
#endif
j ra // return
.end KiSaveVolatileFloatState)
SBTTL("Restore Volatile Floating Registers")
//++
//
// Routine Desription:
//
// This routine is called to restore the volatile floating registers.
//
// N.B. This routine uses a special argument passing mechanism and destroys
// no registers. It is assumed that floating register f0 is restored by
// the caller.
//
// Arguments:
//
// s8 - Supplies a pointer to a trap frame.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiRestoreVolatileFloatState)
#if defined(R3000)
lwc1 f1,TrFltF1(s8) // restore floating registers f1 - f19
lwc1 f2,TrFltF2(s8) //
lwc1 f3,TrFltF3(s8) //
lwc1 f4,TrFltF4(s8) //
lwc1 f5,TrFltF5(s8) //
lwc1 f6,TrFltF6(s8) //
lwc1 f7,TrFltF7(s8) //
lwc1 f8,TrFltF8(s8) //
lwc1 f9,TrFltF9(s8) //
lwc1 f10,TrFltF10(s8) //
lwc1 f11,TrFltF11(s8) //
lwc1 f12,TrFltF12(s8) //
lwc1 f13,TrFltF13(s8) //
lwc1 f14,TrFltF14(s8) //
lwc1 f15,TrFltF15(s8) //
lwc1 f16,TrFltF16(s8) //
lwc1 f17,TrFltF17(s8) //
lwc1 f18,TrFltF18(s8) //
lwc1 f19,TrFltF19(s8) //
#endif
#if defined(R4000)
ldc1 f2,TrFltF2(s8) // restore floating registers f2 - f19
ldc1 f4,TrFltF4(s8) //
ldc1 f6,TrFltF6(s8) //
ldc1 f8,TrFltF8(s8) //
ldc1 f10,TrFltF10(s8) //
ldc1 f12,TrFltF12(s8) //
ldc1 f14,TrFltF14(s8) //
ldc1 f16,TrFltF16(s8) //
ldc1 f18,TrFltF18(s8) //
#endif
j ra // return
.end KiRestoreVolatileFloatState
#endif