622 lines
15 KiB
ArmAsm
622 lines
15 KiB
ArmAsm
|
/* #pragma comment(exestr, "@(#) NEC(MIPS) r94anmi.s 1.2 95/10/17 01:19:11" ) */
|
|||
|
//
|
|||
|
// TITLE("R94A NMI routine")
|
|||
|
//++
|
|||
|
//
|
|||
|
// Copyright (c) 1995 NEC Corporation
|
|||
|
//
|
|||
|
// Module Name:
|
|||
|
//
|
|||
|
// r94anmi.s
|
|||
|
//
|
|||
|
// Abstract:
|
|||
|
//
|
|||
|
// This routine support for dump switch.
|
|||
|
//
|
|||
|
// Author:
|
|||
|
//
|
|||
|
// Akitoshi Kuriyama (NEC Software Kobe,Inc)
|
|||
|
//
|
|||
|
// Environment:
|
|||
|
//
|
|||
|
// Kernel mode only.
|
|||
|
//
|
|||
|
// R4400 based only.
|
|||
|
//
|
|||
|
// Revision History:
|
|||
|
//
|
|||
|
// kuriyama@oa2.kbnes.nec.co.jp Sun Oct 15 20:11:38 JST 1995
|
|||
|
// - new code for J94D (!_MRCDUMP_ _MRCPOWER_ compile option need)
|
|||
|
//
|
|||
|
//--
|
|||
|
#include "halmips.h"
|
|||
|
|
|||
|
SBTTL("NMI dispatch routine")
|
|||
|
//++
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// HalpNMIDispatch (
|
|||
|
// VOID
|
|||
|
// )
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This function was called by firmware when NMI occuerd.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// none.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// none.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
LEAF_ENTRY(HalpNMIDispatch)
|
|||
|
|
|||
|
.set noreorder
|
|||
|
.set noat
|
|||
|
|
|||
|
//
|
|||
|
// Save temporary Registers for use.
|
|||
|
// save area shoud have for every processros.
|
|||
|
//
|
|||
|
|
|||
|
li k0,0xffffc070 // get processor number.
|
|||
|
lw k0,(k0) //
|
|||
|
bne k0,zero,10f //
|
|||
|
nop // fill
|
|||
|
|
|||
|
la k1,HalpNMISave0 // set save address.
|
|||
|
j 20f //
|
|||
|
nop // fill
|
|||
|
|
|||
|
10:
|
|||
|
la k1,HalpNMISave1 // set save address.
|
|||
|
nop // 1 cycle hazzerd
|
|||
|
|
|||
|
20:
|
|||
|
sw AT,0x0(k1) // register save.
|
|||
|
sw v0,0x4(k1) //
|
|||
|
sw v1,0x8(k1) //
|
|||
|
sw a0,0xc(k1) //
|
|||
|
sw a1,0x10(k1) //
|
|||
|
sw a2,0x14(k1) //
|
|||
|
sw a3,0x18(k1) //
|
|||
|
sw t0,0x1c(k1) //
|
|||
|
sw t1,0x20(k1) //
|
|||
|
sw t2,0x24(k1) //
|
|||
|
sw t3,0x28(k1) //
|
|||
|
sw t4,0x2c(k1) //
|
|||
|
sw t5,0x30(k1) //
|
|||
|
sw t6,0x34(k1) //
|
|||
|
sw t7,0x38(k1) //
|
|||
|
sw t8,0x3c(k1) //
|
|||
|
sw t9,0x40(k1) //
|
|||
|
sw gp,0x44(k1) //
|
|||
|
sw sp,0x48(k1) //
|
|||
|
sw s8,0x4c(k1) //
|
|||
|
sw ra,0x50(k1) //
|
|||
|
mfc0 k0,psr //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
sw k0,0x54(k1) //
|
|||
|
nop //
|
|||
|
mfc0 k0,cause //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
sw k0,0x58(k1) //
|
|||
|
nop //
|
|||
|
mfc0 k0,epc //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
sw k0,0x5c(k1) //
|
|||
|
nop //
|
|||
|
mfc0 k0,errorepc //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
sw k0,0x60(k1) //
|
|||
|
nop //
|
|||
|
mfc0 k0,cacheerr //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
sw k0,0x64(k1) //
|
|||
|
|
|||
|
sdc1 f0,0x68(k1) //
|
|||
|
|
|||
|
//
|
|||
|
// Set Dump Switch Status register to tlb fixed entry
|
|||
|
//
|
|||
|
|
|||
|
li t0,4 // set index 4(hurricane register)
|
|||
|
li t1,0x80012 << 6 // set MRC register
|
|||
|
li t2,0x8000e << 6 // set Self-Test address
|
|||
|
|
|||
|
mfc0 t3,index // save tlb registers
|
|||
|
mfc0 t4,entryhi //
|
|||
|
mfc0 t5,entrylo0 //
|
|||
|
mfc0 t6,entrylo1 //
|
|||
|
mfc0 t7,pagemask //
|
|||
|
mtc0 t0,index //
|
|||
|
nop
|
|||
|
nop
|
|||
|
nop
|
|||
|
|
|||
|
tlbr // read index 4 tlb
|
|||
|
nop
|
|||
|
nop
|
|||
|
nop
|
|||
|
nop
|
|||
|
|
|||
|
mfc0 t8,entrylo0 // Get entrylo0
|
|||
|
mfc0 t9,entrylo1 // Get entrylo1
|
|||
|
nop
|
|||
|
nop
|
|||
|
nop
|
|||
|
or t1,t8,t1 // set MRC address
|
|||
|
or t2,t8,t2 // set Self-test address
|
|||
|
nop
|
|||
|
|
|||
|
mtc0 t1,entrylo0 // set MRC to tlb 4 0
|
|||
|
mtc0 t2,entrylo1 // set Self-test to tlb 4 1
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
|
|||
|
tlbwi // write to tlb entry
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
|
|||
|
//
|
|||
|
// read dump status
|
|||
|
//
|
|||
|
|
|||
|
#if defined(_MRCDUMP_)
|
|||
|
|
|||
|
li t1,0xffffc108 // load MRC Mode value
|
|||
|
|
|||
|
#else // SELFTEST DUMP
|
|||
|
|
|||
|
li t1,0xffffd000 // load Self-Test value
|
|||
|
|
|||
|
li k0,0x1b // set dash
|
|||
|
sb k0,(t1) // display led
|
|||
|
sync
|
|||
|
|
|||
|
#endif // _MRCDUMP_
|
|||
|
|
|||
|
lb k0,(t1) // load Dump switch status.
|
|||
|
nop //
|
|||
|
lb k0,(t1) // wait
|
|||
|
nop //
|
|||
|
|
|||
|
//
|
|||
|
// Check dump status
|
|||
|
//
|
|||
|
|
|||
|
li t1,2 // check for dump switch
|
|||
|
and k0,k0,t1 //
|
|||
|
|
|||
|
#if defined(_MRCDUMP_)
|
|||
|
beq k0,zero,30f // if 0 dump swith was not pressed
|
|||
|
#else // _MRCDUMP_
|
|||
|
bne k0,zero,30f // if 0 dump swith was pressed
|
|||
|
#endif // _MRCDUMP_
|
|||
|
nop //
|
|||
|
|
|||
|
#if !defined(_MRCDUMP_)
|
|||
|
li t1,0xffffd000 // set dump switch status address
|
|||
|
li t2,0x1b // display LED dash
|
|||
|
sb t2,(t1) //
|
|||
|
sync //
|
|||
|
#endif // not _MRCDUMP_
|
|||
|
|
|||
|
//
|
|||
|
// enable powoff NMI
|
|||
|
//
|
|||
|
|
|||
|
#if defined(_MRCPOWER_)
|
|||
|
li t1,0xffffc108 //
|
|||
|
li t0,0x82 //
|
|||
|
nop //
|
|||
|
sb t0,(t1) //
|
|||
|
nop //
|
|||
|
li t0,0x80 //
|
|||
|
nop //
|
|||
|
sb t0,(t1) //
|
|||
|
nop //
|
|||
|
li t0,0x02 //
|
|||
|
nop //
|
|||
|
sb t0,(t1) //
|
|||
|
nop //
|
|||
|
#endif // _MRCPOWER_
|
|||
|
|
|||
|
//
|
|||
|
// restore tlb 4 entry
|
|||
|
//
|
|||
|
|
|||
|
mtc0 t8,entrylo0 // restore tlb 4 0
|
|||
|
mtc0 t9,entrylo1 // restore tlb 4 1
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
|
|||
|
tlbwi // write to tlb entry
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
|
|||
|
//
|
|||
|
// restore tlb registers
|
|||
|
//
|
|||
|
mtc0 t3,index //
|
|||
|
mtc0 t4,entryhi //
|
|||
|
mtc0 t5,entrylo0 //
|
|||
|
mtc0 t6,entrylo1 //
|
|||
|
mtc0 t7,pagemask //
|
|||
|
|
|||
|
#if !defined(_MRCDUMP_)
|
|||
|
la k0,0xffffc5b8 // get NEC I/O port value
|
|||
|
lb t0,(k0) //
|
|||
|
nop // 1 cycle hazzerd
|
|||
|
li t1,0xfd // clear dump enable bit
|
|||
|
and t0,t0,t1
|
|||
|
sb t0,(k0) // set NEC I/O port value
|
|||
|
#endif // not _MRCDUMP_
|
|||
|
|
|||
|
//
|
|||
|
// set NMI flag 1
|
|||
|
//
|
|||
|
|
|||
|
la t2,HalpNMIFlag // set NMI flag address
|
|||
|
li t3,0xa0000000 // set KSEG1_BASE
|
|||
|
or t2,t2,t3 //
|
|||
|
li t3,1 //
|
|||
|
sw t3,(t2) // set NMI flag 1
|
|||
|
|
|||
|
//
|
|||
|
// set dump flag 1
|
|||
|
//
|
|||
|
|
|||
|
la t2,HalpDumpNMIFlag // set Dump NMI flag address
|
|||
|
li t3,0xa0000000 // set KSEG1_BASE
|
|||
|
or t2,t2,t3 //
|
|||
|
li t3,1 //
|
|||
|
sw t3,(t2) // set NMI flag 1
|
|||
|
|
|||
|
//
|
|||
|
// clear psr BEV bit
|
|||
|
//
|
|||
|
|
|||
|
mfc0 t0,psr // get psr
|
|||
|
li t2,0xffbfffff // clear BEV bit
|
|||
|
nop // fill
|
|||
|
nop // fill
|
|||
|
and t0,t0,t2 //
|
|||
|
nop //
|
|||
|
mtc0 t0,psr // set psr
|
|||
|
|
|||
|
lw t0,0x1c(k1) // restore temporary registers
|
|||
|
lw t1,0x20(k1) //
|
|||
|
lw t2,0x24(k1) //
|
|||
|
lw t3,0x28(k1) //
|
|||
|
lw t4,0x2c(k1) //
|
|||
|
lw t5,0x30(k1) //
|
|||
|
lw t6,0x34(k1) //
|
|||
|
lw t7,0x38(k1) //
|
|||
|
lw t8,0x3c(k1) //
|
|||
|
lw t9,0x40(k1) //
|
|||
|
lw AT,0x0(k1) //
|
|||
|
|
|||
|
eret // return to error epc
|
|||
|
nop // errata
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
eret //
|
|||
|
nop //
|
|||
|
|
|||
|
30:
|
|||
|
|
|||
|
//
|
|||
|
// No Dump Switch.
|
|||
|
//
|
|||
|
// Check Power Switch
|
|||
|
|
|||
|
#if defined(_MRCPOWER_)
|
|||
|
li t1,0xffffc108
|
|||
|
nop
|
|||
|
li t0,0x02
|
|||
|
nop
|
|||
|
sb t0,(t1)
|
|||
|
nop
|
|||
|
|
|||
|
#endif // _MRCPOWER_
|
|||
|
|
|||
|
mtc0 t8,entrylo0 // restore tlb 4
|
|||
|
mtc0 t9,entrylo1 // restore tlb 4
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
|
|||
|
tlbwi // write to tlb entry
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
|
|||
|
mtc0 t3,index // restore tlb registers
|
|||
|
mtc0 t4,entryhi //
|
|||
|
mtc0 t5,entrylo0 //
|
|||
|
mtc0 t6,entrylo1 //
|
|||
|
mtc0 t7,pagemask //
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// set NMI flag 1
|
|||
|
//
|
|||
|
la t2,HalpNMIFlag // set NMI flag address
|
|||
|
li t3,0xa0000000 // set KSEG1_BASE
|
|||
|
or t2,t2,t3 //
|
|||
|
li t3,1 //
|
|||
|
sw t3,(t2) // set NMI flag 1
|
|||
|
|
|||
|
// S003 +++
|
|||
|
li t1,0xffffc078 // check NMI source
|
|||
|
lw t0,(t1) // check NMI source
|
|||
|
nop //
|
|||
|
beq t0,zero,40f //
|
|||
|
nop //
|
|||
|
li t1,0xffffc020
|
|||
|
nop
|
|||
|
ldc1 f0,(t1) // clear processor invalid
|
|||
|
nop
|
|||
|
sdc1 f0,0x70(k1) // save processor invalid
|
|||
|
40:
|
|||
|
// S003 ---
|
|||
|
|
|||
|
mfc0 t0,psr // get psr
|
|||
|
li t2,0xffbfffff // clear BEV bit
|
|||
|
nop // fill
|
|||
|
nop // fill
|
|||
|
and t0,t0,t2 //
|
|||
|
nop //
|
|||
|
mtc0 t0,psr // set psr
|
|||
|
|
|||
|
lw t0,0x1c(k1) // restore temporary registers
|
|||
|
lw t1,0x20(k1) //
|
|||
|
lw t2,0x24(k1) //
|
|||
|
lw t3,0x28(k1) //
|
|||
|
lw t4,0x2c(k1) //
|
|||
|
lw t5,0x30(k1) //
|
|||
|
lw t6,0x34(k1) //
|
|||
|
lw t7,0x38(k1) //
|
|||
|
lw t8,0x3c(k1) //
|
|||
|
lw t9,0x40(k1) //
|
|||
|
lw AT,0x0(k1) //
|
|||
|
ldc1 f0,0x68(k1) //
|
|||
|
nop
|
|||
|
|
|||
|
eret // return to errorepc
|
|||
|
nop // errata
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
eret //
|
|||
|
nop //
|
|||
|
|
|||
|
// L001 ---
|
|||
|
|
|||
|
.set at
|
|||
|
.set reorder
|
|||
|
|
|||
|
.end HalpNMIDispatch
|
|||
|
|
|||
|
// Start M008
|
|||
|
SBTTL("Software Power Off")
|
|||
|
//++
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// HalpPowOffNMIDispatch (
|
|||
|
// VOID
|
|||
|
// )
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This function was called by firmware when NMI occuerd.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// none.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// none.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
LEAF_ENTRY(HalpPowOffNMIDispatch)
|
|||
|
|
|||
|
.set noat
|
|||
|
.set noreorder
|
|||
|
|
|||
|
//
|
|||
|
// Save temporary Registers for use.
|
|||
|
// save area shoud have for every processros.
|
|||
|
//
|
|||
|
|
|||
|
li k0,0xffffc070 // get processor number.
|
|||
|
lw k0,(k0) //
|
|||
|
bne k0,zero,60f //
|
|||
|
nop // fill
|
|||
|
|
|||
|
la k1,HalpNMISave0 // set save address.
|
|||
|
j 70f //
|
|||
|
nop // fill
|
|||
|
|
|||
|
60:
|
|||
|
la k1,HalpNMISave1 // set save address.
|
|||
|
nop // 1 cycle hazzerd
|
|||
|
|
|||
|
70:
|
|||
|
sw t0,0(k1) // save temporary registers
|
|||
|
sw t1,4(k1) //
|
|||
|
sw t2,8(k1) //
|
|||
|
sw t3,12(k1) //
|
|||
|
sw t4,16(k1) //
|
|||
|
sw t5,20(k1) //
|
|||
|
sw t6,24(k1) //
|
|||
|
sw t7,28(k1) //
|
|||
|
sw AT,32(k1) //
|
|||
|
|
|||
|
//
|
|||
|
// Set Power Switch Status register to tlb fixed entry
|
|||
|
//
|
|||
|
li t0,4 // set index 4(hurricane register)
|
|||
|
|
|||
|
li t1,0x80012 << 6 // set MRC register
|
|||
|
|
|||
|
mfc0 t3,index // save tlb registers
|
|||
|
mfc0 t4,entryhi //
|
|||
|
mfc0 t5,entrylo0 //
|
|||
|
mfc0 t6,entrylo1 //
|
|||
|
mfc0 t7,pagemask //
|
|||
|
mtc0 t0,index //
|
|||
|
nop
|
|||
|
nop
|
|||
|
nop
|
|||
|
|
|||
|
tlbr // read index 4 tlb
|
|||
|
nop
|
|||
|
nop
|
|||
|
nop
|
|||
|
nop
|
|||
|
|
|||
|
mfc0 t2,entrylo0 // set Self-test address to tlb
|
|||
|
nop
|
|||
|
nop
|
|||
|
nop
|
|||
|
or t1,t2,t1
|
|||
|
nop
|
|||
|
|
|||
|
mtc0 t1,entrylo0 // set Self-Test to tlb 4
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
|
|||
|
tlbwi // write to tlb entry
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
|
|||
|
li t1,0xffffc100 // load MRC Int value
|
|||
|
|
|||
|
nop
|
|||
|
lb k0,(t1) // load Interrupt status.
|
|||
|
nop
|
|||
|
lb k0,(t1) // wait
|
|||
|
nop
|
|||
|
|
|||
|
li t0,0x01 // set clear value
|
|||
|
sb t0,(t1) // clear OffSw bit
|
|||
|
|
|||
|
li t1,0x4 // check for OffSw switch
|
|||
|
nop //
|
|||
|
and k0,k0,t1 //
|
|||
|
|
|||
|
beq k0,zero,80f // 0 means Power switch was not pressed
|
|||
|
nop //
|
|||
|
|
|||
|
li t1,0xffffc130 // load MRC Software PowerOff Register
|
|||
|
|
|||
|
nop
|
|||
|
|
|||
|
lb t0,0x1 // set PowerOff Value
|
|||
|
|
|||
|
90:
|
|||
|
sb t0,(t1) // write PowerOff bit
|
|||
|
beq zero,zero,90b
|
|||
|
nop
|
|||
|
|
|||
|
eret
|
|||
|
nop
|
|||
|
nop
|
|||
|
nop
|
|||
|
eret
|
|||
|
nop
|
|||
|
80:
|
|||
|
|
|||
|
//
|
|||
|
// No Power Switch.
|
|||
|
//
|
|||
|
|
|||
|
mtc0 t2,entrylo0 // restore tlb 4
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
|
|||
|
tlbwi // write to tlb entry
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
|
|||
|
mtc0 t3,index // restore tlb registers
|
|||
|
mtc0 t4,entryhi //
|
|||
|
mtc0 t5,entrylo0 //
|
|||
|
mtc0 t6,entrylo1 //
|
|||
|
mtc0 t7,pagemask //
|
|||
|
|
|||
|
|
|||
|
la t2,HalpNMIFlag // set NMI flag address
|
|||
|
li t3,0xa0000000 // set KSEG1_BASE
|
|||
|
or t2,t2,t3 //
|
|||
|
li t3,1 //
|
|||
|
sw t3,(t2) // set NMI flag 1
|
|||
|
|
|||
|
lw t0,0xffffc078 // check NMI source
|
|||
|
nop //
|
|||
|
beq t0,zero,45f //
|
|||
|
nop //
|
|||
|
lw t0,0xffffc020 // clear processor invalid
|
|||
|
45:
|
|||
|
|
|||
|
mfc0 t0,psr // get psr
|
|||
|
li t2,0xffbfffff // clear BEV bit
|
|||
|
nop // fill
|
|||
|
nop // fill
|
|||
|
and t0,t0,t2 //
|
|||
|
nop //
|
|||
|
mtc0 t0,psr // set psr
|
|||
|
|
|||
|
lw t0,0(k1) // restore temporary registers
|
|||
|
lw t1,4(k1) //
|
|||
|
lw t2,8(k1) //
|
|||
|
lw t3,12(k1) //
|
|||
|
lw t4,16(k1) //
|
|||
|
lw t5,20(k1) //
|
|||
|
lw t6,24(k1) //
|
|||
|
lw t7,28(k1) //
|
|||
|
lw AT,32(k1) //
|
|||
|
|
|||
|
eret // return to errorepc
|
|||
|
nop // errata
|
|||
|
nop //
|
|||
|
nop //
|
|||
|
eret //
|
|||
|
nop //
|
|||
|
|
|||
|
.set reorder
|
|||
|
.set at
|
|||
|
|
|||
|
.end HalpPowOffNMIDispatch
|
|||
|
// End M008
|