ZealOS/src/Kernel/KExcept.ZC

161 lines
3.8 KiB
HolyC
Executable file

asm {
#assert !((REGG_LOCAL_NON_PTR_VARS | REGG_LOCAL_VARS) & ~0xFCC0)
_TEST_EXCEPT::
XOR RAX, RAX
MOV RAX, FS:U64 CTask.last_except[RAX]
MOV RBP, U64 CExcept.rbp[RAX]
MOV RSI, U64 CExcept.rsi[RAX]
MOV RDI, U64 CExcept.rdi[RAX]
MOV R10, U64 CExcept.r10[RAX]
MOV R11, U64 CExcept.r11[RAX]
MOV R12, U64 CExcept.r12[RAX]
MOV R13, U64 CExcept.r13[RAX]
MOV R14, U64 CExcept.r14[RAX]
MOV R15, U64 CExcept.r15[RAX]
PUSH U64 CExcept.rflags[RAX]
POPFD
JMP U64 CExcept.handler_catch[RAX]
_TAKE_EXCEPT::
XOR RAX, RAX
MOV RAX, FS:U64 CTask.last_except[RAX]
MOV RSP, U64 CExcept.rsp[RAX]
JMP U64 CExcept.handler_untry[RAX]
_SAVE_EXCEPT_REGS::
PUSH RBP
MOV RBP,RSP
MOV RAX,U64 SF_ARG1[RBP]
MOV U64 CExcept.rsi[RAX], RSI
MOV U64 CExcept.rdi[RAX], RDI
MOV U64 CExcept.r10[RAX], R10
MOV U64 CExcept.r11[RAX], R11
MOV U64 CExcept.r12[RAX], R12
MOV U64 CExcept.r13[RAX], R13
MOV U64 CExcept.r14[RAX], R14
MOV U64 CExcept.r15[RAX], R15
POP RBP
RET1 8
}
_extern _TEST_EXCEPT U0 TestExcept();
_extern _TAKE_EXCEPT U0 TakeExcept();
_extern _SAVE_EXCEPT_REGS U0 SaveExceptRegs(CExcept *t);
U0 PutExcept(Bool catch_it=TRUE)
{//Print exception message and catch exception.
"Except © %c © ", Fs->except_ch;
"%P © %P © %P © %P © %P © %P\n", Fs->except_callers[0], Fs->except_callers[1], Fs->except_callers[2], Fs->except_callers[3],
Fs->except_callers[4], Fs->except_callers[5], Fs->except_callers[6], Fs->except_callers[7];
Fs->catch_except = catch_it;
}
#exe {Option(OPTf_NO_REG_VAR, ON);};
class CTryStack
{
I64 rbp;
I64 ret_rip;
I64 arg1;
I64 arg2;
};
U0 SysTry(U8 *catch_start, U8 *untry_start)
{
I64 *rbp = RBPGet;
CExcept *tmpt = MAlloc(sizeof(CExcept));
tmpt->handler_catch = catch_start;
tmpt->handler_untry = untry_start;
tmpt->rsp = rbp(U8 *) + sizeof(CTryStack);
tmpt->rbp = *rbp;
tmpt->rflags = RFlagsGet;
SaveExceptRegs(tmpt);
QueueInsert(tmpt, Fs->last_except);
}
U0 SysUntry()
{
CExcept *tmpt = Fs->last_except;
QueueRemove(tmpt);
Free(tmpt);
}
U0 throw(I64 ch=0, Bool no_log=FALSE)
{//ch can be up to 8 chars like $LK,"PutChars",A="MN:PutChars"$().
//In the catcher, fetch ch from Fs->except_ch.
CExcept *tmpt = Fs->last_except;
Bool was_raw;
I64 i;
Fs->except_ch = ch;
for (i = 0; i < TASK_EXCEPT_CALLERS; i++)
Fs->except_callers[i] = Caller(i + 1);
Fs->except_rbp = RBPGet;
Fs->catch_except = FALSE;
if (!no_log)
SysLog("Except © %c © %p © %p © %p © %p © %p © %p\n", ch,
Fs->except_callers[0], Fs->except_callers[1], Fs->except_callers[2], Fs->except_callers[3],
Fs->except_callers[4], Fs->except_callers[5], Fs->except_callers[6], Fs->except_callers[7]);
while (Fs->next_except != &Fs->next_except)
{
TestExcept;
if (Fs->catch_except)
TakeExcept;
RBPSet(Fs->except_rbp);
tmpt = Fs->last_except;
QueueRemove(tmpt);
Free(tmpt);
}
was_raw = Raw(ON);
PutExcept(FALSE);
Panic("Unhandled Exception");
Raw(was_raw);
}
#exe {Option(OPTf_NO_REG_VAR, OFF);};
U0 Break()
{//Send <CTRL-ALT-c>.
if (Bt(&Fs->task_flags, TASKf_BREAK_TO_SHIFT_ESC))
Message(MESSAGE_KEY_DOWN, CH_SHIFT_ESC, 0x20100000201);
else
{
Fs->wake_jiffy = 0;
TaskResetAwaitingMessage;
DrivesRelease();
BlkDevsRelease();
FlushMessages;
throw('Break');
}
}
Bool BreakLock(CTask *task=NULL)
{//Disables <CTRL-ALT-c>.
if (!task)
task = Fs;
return !LBts(&task->task_flags, TASKf_BREAK_LOCKED);
}
Bool BreakUnlock(CTask *task=NULL)
{//Reenables <CTRL-ALT-c> and issues any pending breaks.
Bool res;
if (!task)
task = Fs;
res = LBtr(&task->task_flags, TASKf_BREAK_LOCKED);
if (LBtr(&task->task_flags, TASKf_PENDING_BREAK))
{
if (task == Fs)
Break;
else
task->rip = &Break;
}
return res;
}