NT4/private/ntos/nthals/halsni4x/mips/x4clock.s
2020-09-30 17:12:29 +02:00

326 lines
11 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.

//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/x4clock.s,v 1.4 1995/02/13 12:54:07 flo Exp $")
// 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.
//
// Environment:
//
// Kernel mode only.
//
//
//--
#include "halmips.h"
#include "SNIdef.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
lw t0,__imp_KeUpdateSystemTime // update system time
jal t0 //
#if DBG
#else
//
// we use this only when we have the machine up and running ...
// LED's can show us something, what we do not see in the debugger
//
la t0,HalpLedRegister // get current Value of LED Register
lw a0,0(t0)
addu a0,a0,1 // increment
sw a0,0(t0) // store and
la t0, HalpLedAddress // get address of the variable
lw t0,0(t0) // get value
sb a0,0(t0) // display LSByte (set the LED)
#endif
//
// At each clock interrupt the next time increment is moved to the current
// time increment to "pipeline" the update of the current increment at the
// correct time. If the new time increment is nonzero, then the new time
// increment is moved to the next time increment and the timer is reprogramed
//
lw t0,KdDebuggerEnabled // get address of debugger enable
lw t1,HalpNewTimeIncrement // get new time increment
lw t2,HalpNextTimeIncrement // get the next increment value
lbu t0,0(t0) // get debugger enable flag
lw ra,CiRa(sp) // restore return address
or t4,t1,t0 // new interval count or debugger?
sw t2,HalpCurrentTimeIncrement // pipeline current increment value
bne zero,t4,10f // if ne, interval change or debugger
addu sp,sp,CiFrameLength // deallocate stack frame
j ra // return
//
// The interval count must be changed or the debugger is enabled.
//
10: sw zero,HalpNewTimeIncrement // clear new time increment
beq zero,t1,15f // if eq, not interval count change
sw t1,HalpNextTimeIncrement // set next time increment value
move a0,t1 // prepare to call HalpProgramIntervalTimer
jal HalpProgramIntervalTimer // program timer chip ...
15: beq zero,t0,40f // if eq, debugger not enabled
//15: beq zero,t0,20f // if eq, debugger not enabled
jal KdPollBreakIn // check if breakin is requested
beq zero,v0,40f // if eq, no breakin requested
// beq zero,v0,20f // if eq, no breakin requested
li a0,DBG_STATUS_CONTROL_C // break in and send
jal DbgBreakPointWithStatus // status to debugger
//
// Check if profiling is active and the profile interval has expired.
//
//
//20: la t0,HalpCountCompareInterrupt // profiling via CountCompare ?
// lb t1,0(t0)
// bne zero,t1,40f // if set, profiling is done via CountCompare Interrupt
// lw t0,KiPcr + PcProfileCount(zero) // get remaining profile count
// li t1,TIME_INCREMENT // get time increment value
// beq zero,t0,40f // if eq, profiling not enabled
// subu t0,t0,t1 // subtract time increment from count
// bgtz t0,30f // if gtz, not end of profile interval
// move a0,s8 // set address of trap frame
// jal KeProfileInterrupt // process profile entries
// lw t0,KiPcr + PcProfileInterval(zero) // get profile interval value
//30: sw t0,KiPcr + PcProfileCount(zero) // set remaining profile count
40: lw ra,CiRa(sp) // restore return address
addu sp,sp,CiFrameLength // deallocate stack frame
j ra // return
.end HalpClockInterrupt
SBTTL("System Clock Interrupt - Processor N")
//++
//
// Routine Description:
//
// This routine is entered as the result of an interrupt generated by
// the extra interval timer in the slave processors. Its function is
// to transfer control to the standard system routine to update the
// execution time of the current thread and process.
//
// Note: We plan to use the extra timer for our MultiProcessor (SNI)Machine
// MAYBE, if we have arbitrated interrupts, we have to acknowledge
// this interrupt here and send an message to the other processors
// (Quadro machine)
//
// Arguments:
//
// s8 - Supplies a pointer to a trap frame.
//
// Return Value:
//
// None.
//
//--
NESTED_ENTRY(HalpClockInterrupt1, CiFrameLength, zero)
subu sp,sp,CiFrameLength // allocate stack frame
sw ra,CiRa(sp) // save return address
PROLOGUE_END
li t0, RM400_TIMER0_ACK_ADDR // get address of acknowledge register
sb zero,0(t0) // acknowledge timer interrupt
jal HalpCheckSpuriousInt
move a0,s8 // set address of trap frame
lw t1,__imp_KeUpdateRunTime // update system runtime
lw ra,CiRa(sp) // restore return address
addu sp,sp,CiFrameLength // deallocate stack frame
j t1 //
.end HalpClockInterrupt1
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.
//
//--
NESTED_ENTRY(HalpProfileInterrupt, CiFrameLength, zero)
subu sp,sp,CiFrameLength // allocate stack frame
sw ra,CiRa(sp) // save return address
PROLOGUE_END
.set noreorder
.set noat
jal HalpCheckSpuriousInt
nop
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
//
// we prefer the MultiPro version, which also works on UniPro machines
//
lw t1,KiPcr + PcPrcb(zero) // get current processor block address
la t2,HalpPerformanceCounter // get performance counter address
lbu t1,PbNumber(t1) // get processor number
sll t1,t1,3 // compute address of performance count
addu t1,t1,t2 //
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
lw t4,__imp_KeProfileInterrupt // process profile interrupt
lw ra,CiRa(sp) // restore return address
addu sp,sp,CiFrameLength // deallocate stack frame
j t4 //
.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