211 lines
6.2 KiB
ArmAsm
211 lines
6.2 KiB
ArmAsm
|
#if defined(R4000)
|
|||
|
|
|||
|
// TITLE("Interval and Profile Clock Interrupts")
|
|||
|
//++
|
|||
|
//
|
|||
|
// Copyright (c) 1991 Microsoft Corporation
|
|||
|
//
|
|||
|
// Module Name:
|
|||
|
//
|
|||
|
// x4clock.s
|
|||
|
//
|
|||
|
// Abstract:
|
|||
|
//
|
|||
|
// This module implements the code necessary to field and process the
|
|||
|
// interval and profile clock interrupts on a MIPS R4000 system.
|
|||
|
//
|
|||
|
// Author:
|
|||
|
//
|
|||
|
// David N. Cutler (davec) 26-Apr-1991
|
|||
|
//
|
|||
|
// Environment:
|
|||
|
//
|
|||
|
// Kernel mode only.
|
|||
|
//
|
|||
|
// Revision History:
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
#include "halmips.h"
|
|||
|
|
|||
|
SBTTL("System Clock Interrupt")
|
|||
|
//++
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This routine is entered as the result of an interrupt generated by
|
|||
|
// the interval timer. Its function is to acknowledge the interrupt and
|
|||
|
// transfer control to the standard system routine to update the system
|
|||
|
// time and the execution time of the current thread and process.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// s8 - Supplies a pointer to a trap frame.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
.struct 0
|
|||
|
CiArgs: .space 4 * 4 // saved arguments
|
|||
|
.space 3 * 4 // fill
|
|||
|
CiRa: .space 4 // saved return address
|
|||
|
CiFrameLength: //
|
|||
|
|
|||
|
NESTED_ENTRY(HalpClockInterrupt, CiFrameLength, zero)
|
|||
|
|
|||
|
subu sp,sp,CiFrameLength // allocate stack frame
|
|||
|
sw ra,CiRa(sp) // save return address
|
|||
|
|
|||
|
PROLOGUE_END
|
|||
|
|
|||
|
move a0,s8 // set address of trap frame
|
|||
|
lw a1,HalpCurrentTimeIncrement // Get current time increment
|
|||
|
jal KeUpdateSystemTime // update system time
|
|||
|
lw t0,HalpNextTimeIncrement // Get NextTimeIncrement
|
|||
|
sw t0,HalpCurrentTimeIncrement // Set CurrentTimeIncrement to NextTimeIncrement
|
|||
|
lw a0,HalpNextIntervalCount // Get Next Interval Count. If 0, then no change required
|
|||
|
beq zero,a0,5f // See if time increment is to be changed
|
|||
|
jal HalpProgramIntervalTimer // Program timer with new interval count value
|
|||
|
lw t0,HalpNewTimeIncrement // Get HalpNewTimeIncrement
|
|||
|
sw t0,HalpNextTimeIncrement // Set HalpNextTimeIncrement to HalpNewTimeIncrement
|
|||
|
sw zero,HalpNextIntervalCount // Set HalpNextIntervalCount to 0
|
|||
|
5:
|
|||
|
lw t0,KdDebuggerEnabled // check if debugger enabled
|
|||
|
lbu t0,0(t0) //
|
|||
|
beq zero,t0,10f // if eq, debugger not enabled
|
|||
|
jal KdPollBreakIn // check if breakin is requested
|
|||
|
beq zero,v0,10f // if eq, no breakin requested
|
|||
|
li a0,DBG_STATUS_CONTROL_C // break in and send
|
|||
|
jal DbgBreakPointWithStatus // status to debugger
|
|||
|
10: lw ra,CiRa(sp) // restore return address
|
|||
|
addu sp,sp,CiFrameLength // deallocate stack frame
|
|||
|
j ra // return
|
|||
|
|
|||
|
.end HalpClockInterrupt
|
|||
|
|
|||
|
SBTTL("Profile Clock Interrupt")
|
|||
|
//++
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This routine is entered as the result of an interrupt generated by the
|
|||
|
// profile clock. Its function is to acknowledge the profile interrupt,
|
|||
|
// compute the next compare value, update the performance counter, and
|
|||
|
// transfer control to the standard system routine to process any active
|
|||
|
// profiles.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// s8 - Supplies a pointer to a trap frame.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
LEAF_ENTRY(HalpProfileInterrupt)
|
|||
|
|
|||
|
.set noreorder
|
|||
|
.set noat
|
|||
|
mfc0 t1,count // get current count value
|
|||
|
mfc0 t0,compare // get current comparison value
|
|||
|
addu t1,t1,8 // factor in lost cycles
|
|||
|
subu t1,t1,t0 // compute initial count value
|
|||
|
mtc0 t0,compare // dismiss interrupt
|
|||
|
mtc0 t1,count // set new count register value
|
|||
|
.set at
|
|||
|
.set reorder
|
|||
|
|
|||
|
la t1,HalpPerformanceCounter // get performance counter address
|
|||
|
lw t2,LiLowPart(t1) // get low part of performance count
|
|||
|
lw t3,LiHighPart(t1) // get high part of performance count
|
|||
|
addu t2,t2,t0 // update low part of performance count
|
|||
|
sw t2,LiLowPart(t1) // store low part of performance count
|
|||
|
sltu t4,t2,t0 // generate carry into high part
|
|||
|
addu t3,t3,t4 // update high part of performance count
|
|||
|
sw t3,LiHighPart(t1) // store high part of performance count
|
|||
|
move a0,s8 // set address of trap frame
|
|||
|
j KeProfileInterrupt // process profile entries
|
|||
|
|
|||
|
.end HalpProfileInterrupt
|
|||
|
|
|||
|
SBTTL("Read Count Register")
|
|||
|
//++
|
|||
|
//
|
|||
|
// ULONG
|
|||
|
// HalpReadCountRegister (
|
|||
|
// VOID
|
|||
|
// );
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This routine reads the current value of the count register and
|
|||
|
// returns the value.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// Current value of the count register.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
LEAF_ENTRY(HalpReadCountRegister)
|
|||
|
|
|||
|
.set noreorder
|
|||
|
.set noat
|
|||
|
mfc0 v0,count // get count register value
|
|||
|
.set at
|
|||
|
.set reorder
|
|||
|
|
|||
|
j ra // return
|
|||
|
|
|||
|
.end HalpReadCountRegister
|
|||
|
|
|||
|
SBTTL("Write Compare Register And Clear")
|
|||
|
//++
|
|||
|
//
|
|||
|
// ULONG
|
|||
|
// HalpWriteCompareRegisterAndClear (
|
|||
|
// IN ULONG Value
|
|||
|
// );
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This routine reads the current value of the count register, writes
|
|||
|
// the value of the compare register, clears the count register, and
|
|||
|
// returns the previous value of the count register.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// Value - Supplies the value written to the compare register.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// Previous value of the count register.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
|
|||
|
|
|||
|
.set noreorder
|
|||
|
.set noat
|
|||
|
mfc0 v0,count // get count register value
|
|||
|
mtc0 a0,compare // set compare register value
|
|||
|
li t0,7 // set lost cycle count
|
|||
|
mtc0 t0,count // set count register to zero
|
|||
|
.set at
|
|||
|
.set reorder
|
|||
|
|
|||
|
j ra // return
|
|||
|
|
|||
|
.end HalpWriteCompareRegisterAndClear
|
|||
|
|
|||
|
#endif
|