-
-
Notifications
You must be signed in to change notification settings - Fork 10
/
exception.c
63 lines (59 loc) · 1.96 KB
/
exception.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include "exception.h"
#include "csr.h"
#include "serial.h"
#include "assert.h"
//-----------------------------------------------------------------
// Locals
//-----------------------------------------------------------------
#define CAUSE_MAX_EXC (CAUSE_PAGE_FAULT_STORE + 1)
static fp_exception _exception_table[CAUSE_MAX_EXC];
static fp_irq _irq_handler = 0;
void exception_set_irq_handler(fp_irq handler) { _irq_handler = handler; }
void exception_set_syscall_handler(fp_syscall handler)
{
_exception_table[CAUSE_ECALL_U] = handler;
_exception_table[CAUSE_ECALL_S] = handler;
_exception_table[CAUSE_ECALL_M] = handler;
}
//-----------------------------------------------------------------
// exception_set_handler: Register exception handler
//-----------------------------------------------------------------
void exception_set_handler(int cause, fp_exception handler)
{
_exception_table[cause] = handler;
}
//-----------------------------------------------------------------
// exception_handler:
//-----------------------------------------------------------------
struct irq_context * exception_handler(struct irq_context *ctx)
{
// External interrupt
if (ctx->cause & CAUSE_INTERRUPT)
{
if (_irq_handler)
ctx = _irq_handler(ctx);
else
serial_putstr_hex("ERROR: Unhandled IRQ: ", ctx->cause);
}
// Exception
else
{
switch (ctx->cause)
{
case CAUSE_ECALL_U:
case CAUSE_ECALL_S:
case CAUSE_ECALL_M:
ctx->pc += 4;
break;
}
if (ctx->cause < CAUSE_MAX_EXC && _exception_table[ctx->cause])
ctx = _exception_table[ctx->cause](ctx);
else
{
serial_putstr_hex("ERROR: Unhandled exception: ", ctx->cause);
serial_putstr_hex(" at PC: ", ctx->pc);
assert(!"Unhandled exception");
}
}
return ctx;
}