Extended unaligned load support to work from DoubleExceptionVector

Allows handling bad loads that occur inside level 1 exception handlers.
This commit is contained in:
Angus Gratton 2015-09-10 15:02:47 +10:00
parent 1aaef737df
commit a5a179beef

View file

@ -15,6 +15,12 @@
Additions Copyright (C) Superhouse Automation Pty Ltd
BSD Licensed as described in the file LICENSE
*/
/* Some UserException causes, see table Table 464 in ISA reference */
#define CAUSE_SYSCALL 1
#define CAUSE_LOADSTORE 3
#define CAUSE_LVL1INT 4
.text
.section .vecbase.text, "x"
.align 256
@ -48,15 +54,15 @@ KernelExceptionVector:
.align 16
UserExceptionVector:
wsr.excsave1 a0
call0 CallUserExceptionHandler
rfe /* CallUserExceptionHandler should call rfe itself */
.align 16
.L_EmptyVectorEntry2:
nop
rsr.exccause a0
beqi a0, CAUSE_SYSCALL, UserSyscallHandler
beqi a0, CAUSE_LOADSTORE, UserExceptionLoadStoreHandler
j UserExceptionHandler
/* Empty exception slot goes here, but previous slot is large enough we can skip it */
.align 16
DoubleExceptionVector:
break 1, 4
call0 sdk_user_fatal_exception_handler
j DoubleExceptionHandler
.align 16
.L_UnusedResetVector:
/* reset vector slot doesn't get used, as vecbase goes back to mask ROM on reset */
@ -171,24 +177,16 @@ CallNMIExceptionHandler:
LOAD_REG a1, 1
rfi 0x3
/* Some UserException causes, see table Table 464 in ISA reference */
#define CAUSE_SYSCALL 1
#define CAUSE_LOADSTORE 3
#define CAUSE_LVL1INT 4
.type CallUserExceptionHandler, @function
CallUserExceptionHandler:
rsr.exccause a0
beqi a0, CAUSE_SYSCALL, UserSyscallHandler
beqi a0, CAUSE_LOADSTORE, UserLoadStoreExceptionHandler
mov a0, sp
.type UserExceptionHandler, @function
UserExceptionHandler:
mov a0, sp /* a0 was saved in UserExceptionVector */
addi sp, sp, -0x50
s32i a0, sp, 0x10
rsr.ps a0
s32i a0, sp, 0x08
rsr.epc1 a0
s32i a0, sp, 0x04
rsr.excsave1 a0 /* a0 was saved in UserExceptionVector */
rsr.excsave1 a0
s32i a0, sp, 0x0c
movi a0, _xt_user_exit
s32i a0, sp, 0x0
@ -244,24 +242,51 @@ UserSyscallHandler:
rsr.excsave1 a0
rfe
.text
.section .vecbase.text
.literal_position
.align 4
DoubleExceptionHandler:
rsr.exccause a0
beqi a0, CAUSE_LOADSTORE, DoubleExceptionLoadStoreHandler
call0 sdk_user_fatal_exception_handler
.text
.section .vecbase.text
.literal_position
.align 4
.global UserLoadStoreExceptionHandler
/* "Fix" LoadStoreException exceptions thatare l8/l16 from an Instruction region */
UserLoadStoreExceptionHandler:
/* "Fix" LoadStoreException exceptions that are l8/l16 from an Instruction region,
DoubleException exception variant (ie load happened in a level1 exception handler). */
DoubleExceptionLoadStoreHandler:
addi sp, sp, -0x18
s32i a2, sp, 0x08
rsr.epc2 a2
j InnerLoadStoreExceptionHandler
.text
.section .vecbase.text
.literal_position
.align 4
/* "Fix" LoadStoreException exceptions that are l8/l16 from an Instruction region,
normal exception variant. */
UserExceptionLoadStoreHandler:
addi sp, sp, -0x18
s32i a2, sp, 0x08
rsr.epc1 a2
/* Inner UserLoadStoreExceptionHandler handlers. Works for both level1 & level 2 interrupt level.
*
* Called from level-specific handler above which sets up stack and loads epcX into a2.
*/
InnerLoadStoreExceptionHandler:
s32i a3, sp, 0x0c
s32i a4, sp, 0x10
s32i a5, sp, 0x14
rsr.sar a0 // save sar in a0
/* Load the instruction we failed to execute */
rsr.epc1 a2
ssa8l a2 // sar is now correct shift to read a3
/* Examine the instruction we failed to execute (in a2) */
ssa8l a2 // sar is now correct shift for aligned read
movi a3, ~3
and a2, a2, a3 // a2 now 4-byte aligned address of instruction
l32i a3, a2, 0
@ -324,16 +349,18 @@ UserLoadStoreExceptionHandler:
s32i a4, a5, 0
.Lafter_write_value:
/* Footer*/
//Increment PC
/* test PS.INTLEVEL (1=User, 2=Double) to see which interrupt level we restore from
*/
rsr.ps a2
bbsi a2, 1, .Lincrement_PC_intlevel2
.Lincrement_PC_intlevel1:
rsr.epc1 a2
addi a3, a2, 0x3
wsr.epc1 a3
.Lexit:
wsr.sar a0 // restore saved sar
// Restore registers
rsr.excsave1 a0 // restore a0 saved in exception vector
.Lafter_increment_PC:
// Restore registers
l32i a2, sp, 0x08
l32i a3, sp, 0x0c
l32i a4, sp, 0x10
@ -341,6 +368,14 @@ UserLoadStoreExceptionHandler:
addi sp, sp, 0x18
rfe
.Lincrement_PC_intlevel2:
rsr.epc2 a2
addi a3, a2, 0x3
wsr.epc2 a3
wsr.sar a0 // restore saved sar
rsr.excsave2 a0 // restore a0 saved in exception vector
j .Lafter_increment_PC
.Lextend_sign: /* apply 16-bit sign extension if necessary
a3 holds raw value, a4 holds masked */
bbci a3, 15, .Lafter_extend_sign /* sign bit not set, do nothing */
@ -388,10 +423,14 @@ UserLoadStoreExceptionHandler:
j .Lafter_write_value
.Lwrite_value_a0_reg:
/* a0 is saved in excsave1,so just update this with value */
/* a0 is saved in excsave1,so just update this with value
TODO: This won't work with interrupt level 2
*/
wsr.excsave1 a4
j .Lafter_write_value
/* End of InnerUserLoadStoreExceptionHandler */
.global _xt_user_exit
.type _xt_user_exit, @function
_xt_user_exit: