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
|