289 lines
5.8 KiB
ArmAsm
289 lines
5.8 KiB
ArmAsm
|
#if defined(JAZZ) && defined(R3000)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1990 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
j3trap.s
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module will handle exceptions
|
|||
|
It will save the state of the processor, check jump table
|
|||
|
to see if it should dispatch somewhere, and then return to
|
|||
|
monitor.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
John Cooper (johncoop) 4-Oct-90
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
//
|
|||
|
// include header file
|
|||
|
//
|
|||
|
|
|||
|
#include "ksmips.h"
|
|||
|
#include "selfmap.h"
|
|||
|
#include "led.h"
|
|||
|
#define PROM_BASE (KSEG1_BASE | 0x1fc00000)
|
|||
|
#define PROM_ENTRY(x) (PROM_BASE + ((x) * 8))
|
|||
|
|
|||
|
.set noat
|
|||
|
.set noreorder
|
|||
|
.text
|
|||
|
|
|||
|
|
|||
|
|
|||
|
.globl ExceptionDispatch
|
|||
|
ExceptionDispatch:
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will use a lookup table based on the exception
|
|||
|
cause, to call an exception handler. If the value in
|
|||
|
lookup table is zero, the state of the machine is saved,
|
|||
|
and control is passed to monitor.
|
|||
|
The return value of the exception handler indicates where
|
|||
|
control should go when the exception condition is cleared.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
K1 - Contains the cause register.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
//
|
|||
|
// Need to save return address before calling an exec. handler.
|
|||
|
//
|
|||
|
|
|||
|
li k0,GLOBAL_DATA_BASE // base of saved state
|
|||
|
sw ra, 0x7C(k0) // save ra
|
|||
|
|
|||
|
//
|
|||
|
// Get jump vector from lookup table based on cause.
|
|||
|
// Call handler if value is non-zero
|
|||
|
//
|
|||
|
li k0,EXCEPTION_JUMP_TABLE // base of jump table
|
|||
|
addu k0,k0,k1 // add offset to base
|
|||
|
lw k1,0(k0) // get jump vector from tbl
|
|||
|
li k0,GOTO_MONITOR // go back to monitor by default
|
|||
|
beq k1,zero,ExceptionReturn // go save state and call mon.
|
|||
|
li ra,COMMONEXCEPTION // load this value into ra.
|
|||
|
// this will get passed as
|
|||
|
// argument to MonitorInit()
|
|||
|
// which will then print a message
|
|||
|
// saying a COMMONEXCEPTION occured.
|
|||
|
// COMMON EXCEPTION is an unaligned #.
|
|||
|
// if k1 != zero the jal reloads ra
|
|||
|
jal k1 // with the right value.
|
|||
|
nop // control will pass to the
|
|||
|
// Exception Return routine next.
|
|||
|
// return value from handler
|
|||
|
// should be returned in k0.
|
|||
|
// this is passed as argument
|
|||
|
// to ExceptionReturn.
|
|||
|
|
|||
|
.globl ExceptionReturn
|
|||
|
ExceptionReturn:
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will restore any registers that have been modified
|
|||
|
by the trap handler. Control is then passed back to one
|
|||
|
of three places. Either the monitor, the location stored in the
|
|||
|
EPC, or the value supplied in the argumnet k0.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
k0 - supplies indication of where to go after clearing exception.
|
|||
|
if bits [1:0] are 00B then go to location indicated
|
|||
|
in k0. if bits [1:0] are GOTO_MONITOR, then control
|
|||
|
is passed to MonitorReInit(). if bits are GOTO_EPC then
|
|||
|
control is returned to location where exception occured.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Return value from exec. handler is in k0.
|
|||
|
// if low bits are 00, then return to value in k0
|
|||
|
// if low bits are 01, then return to Err PC
|
|||
|
// if low bits are 10, then return to monitor
|
|||
|
//
|
|||
|
andi k1,k0,3 // k1 = k0 & 3
|
|||
|
beq k1,zero,returntok0 // go if return code is 0
|
|||
|
andi k1,k0,GOTO_EPC // k1 = k0 & 1
|
|||
|
bne k1,zero,returntoEPC // if bit1=1 then GOTO_EPC
|
|||
|
andi k1,k0,GOTO_MONITOR // k1 = k0 & 2
|
|||
|
bne k1,zero,returntomonitor // if bit2=1 then GOTO_MONITOR
|
|||
|
nop
|
|||
|
b returntomonitor // default return action
|
|||
|
nop
|
|||
|
returntok0:
|
|||
|
|
|||
|
//
|
|||
|
// restore value to ra
|
|||
|
//
|
|||
|
|
|||
|
li k1,GLOBAL_DATA_BASE // base of saved state
|
|||
|
lw ra, 0x7C(k1) // restore ra
|
|||
|
|
|||
|
//
|
|||
|
// return to value in k0 when clearing exception condition
|
|||
|
// do this by putting k0 in EPC
|
|||
|
//
|
|||
|
j k0 // return to k0
|
|||
|
rfe // restore pre-exc state
|
|||
|
returntoEPC:
|
|||
|
|
|||
|
//
|
|||
|
// restore value to ra
|
|||
|
//
|
|||
|
|
|||
|
li k1,GLOBAL_DATA_BASE // base of saved state
|
|||
|
|
|||
|
//
|
|||
|
// return to location where exeception was caused
|
|||
|
//
|
|||
|
mfc0 k0,epc // get return PC from cop0
|
|||
|
lw ra, 0x7C(k1) // restore ra
|
|||
|
j k0 // jump to (EPC)
|
|||
|
rfe // clear exception condition
|
|||
|
|
|||
|
returntomonitor:
|
|||
|
|
|||
|
//
|
|||
|
// return to monitor by calling MonitorReInit()
|
|||
|
//
|
|||
|
//li k0,MONITOR_LINK_ADDRESS
|
|||
|
//j k0
|
|||
|
//rfe // restore pre-exc state
|
|||
|
li k0,PROM_ENTRY(14)
|
|||
|
lui a0,LED_BLINK
|
|||
|
jal k0
|
|||
|
ori a0,a0,0xFC
|
|||
|
|
|||
|
.globl TLBMiss
|
|||
|
TLBMiss:
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will modifiy the TLB when a miss occurs.
|
|||
|
It will take the failed virtual address and place it
|
|||
|
in the TLB as a physical address. This will make
|
|||
|
a one to one mapping between virtual and physical.
|
|||
|
If the address is E2000000 - E3FFFFFF, then routine
|
|||
|
will subtract off 52000000 for eisa spaces.
|
|||
|
This routine is only expected to be used for the R3000
|
|||
|
|
|||
|
Note that the control from the exception vector is passed
|
|||
|
to the dispatch routine. The dispatch routine calls this
|
|||
|
routine - control is passed back to the dispatch routine.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
//
|
|||
|
// load bad virtual address - the address that missed in TLB
|
|||
|
//
|
|||
|
|
|||
|
mfc0 k0,badvaddr
|
|||
|
|
|||
|
//
|
|||
|
// mask out page offset to get virtual page number.
|
|||
|
// offset differs in size between R4000 and R3000
|
|||
|
//
|
|||
|
|
|||
|
li k1,0xFFFFF000
|
|||
|
|
|||
|
and k0,k0,k1
|
|||
|
|
|||
|
//
|
|||
|
// store bad virtual address in the EntryHi register to
|
|||
|
//
|
|||
|
|
|||
|
mtc0 k0,entryhi
|
|||
|
|
|||
|
//
|
|||
|
// check if value is between E2000000 - E3FFFFFF
|
|||
|
// set bits in range (01FFFFFF) and compare to E3FFFFFF
|
|||
|
//
|
|||
|
|
|||
|
li k1,0x01FFFFFF
|
|||
|
or k0,k0,k1
|
|||
|
li k1,0xE3FFFFFF
|
|||
|
|
|||
|
bne k1,k0,noteisa
|
|||
|
|
|||
|
//
|
|||
|
// subtract off 52000000
|
|||
|
//
|
|||
|
|
|||
|
mfc0 k0,entryhi
|
|||
|
li k1,0x52000000
|
|||
|
sub k0,k0,k1
|
|||
|
nop
|
|||
|
|
|||
|
noteisa:
|
|||
|
//
|
|||
|
// set non-cached, dirty, valid, and global bits
|
|||
|
//
|
|||
|
//
|
|||
|
|
|||
|
li k1,(1<<ENTRYLO_D) + (1<<ENTRYLO_V) + (1<<ENTRYLO_G) + (1<<ENTRYLO_N)
|
|||
|
or k0,k0,k1
|
|||
|
mtc0 k0,entrylo
|
|||
|
|
|||
|
//
|
|||
|
// set index to 63 to write the 63 entry. always replace this
|
|||
|
// entry to preserve all the other entries.
|
|||
|
//
|
|||
|
|
|||
|
li k0,(63<<INDEX_INDEX)
|
|||
|
mtc0 k0,index
|
|||
|
nop
|
|||
|
|
|||
|
//
|
|||
|
// write the tlb entry.
|
|||
|
//
|
|||
|
|
|||
|
tlbwi
|
|||
|
nop
|
|||
|
|
|||
|
//
|
|||
|
// return from exception - tell dispatch to go to EPC
|
|||
|
//
|
|||
|
|
|||
|
j ra
|
|||
|
li k0,GOTO_EPC
|
|||
|
|
|||
|
#endif // R3000 && JAZZ
|