diff --git a/Doc/AbortNotes b/Doc/AbortNotes new file mode 100644 index 0000000000000000000000000000000000000000..8981a6d4fb09c5df134abb07dc84770184c2ab57 --- /dev/null +++ b/Doc/AbortNotes @@ -0,0 +1,40 @@ +R0 -> error, R1-R9 as returned from SWI, R10-R12, SWI addr on stack, R14=SPSR + +On entry to error handler, for SWI errors: + +User mode - IRQs on + +R0 -> error handler's buffer (containing PC error occured at (address of instr after SWI), + and a copy of the error) +R1-R9 as returned from the SWI +R10-R12 recovered from stack (may be wrong if SWI wasn't top level - bad person) +User R13,R14 as it was when SWI called + + +Default abort handler: +Register block filled in with registers for current mode at time of abort. +Stacks flattened +R10-R12, PC from dump placed in SVC stack +OS_Generate error called. +End result: R0-> error + R1-R9 corrupt + R10-R12 = registers at instant of abort (from mode in which abort happened) + R13,R14 = USR registers at instant of abort + Register block contains registers for current mode at time of abort. + + +C abort handler should note USR mode registers (only) then pass it on. +C error handler should note that it is an abort, and not touch the register dump. + +Error numbers: +&800000XX - machine exceptions: 00=Undef, 01=PAbort, 02=DAbort, 03=AddrEx, 04=Unknown IRQ? + 05=BThru0 +&800002XX - FP exceptions: 00=IVO, 01=OFL, 02=DVZ, 03=UFL, 04=INX, 05=Faulty + + +FP exceptions: + +User mode registers go into integer register dump. +FP registers go into FP register dump +OS_GenerateError from inside FPEm - error handler called with all except R1 intact. + diff --git a/VersionASM b/VersionASM index 91da5046c8c8c2a007085d9219caf034c2aa03f6..c28713d3d5ba926c6c80a3783dd02bc5c5afdb2c 100644 --- a/VersionASM +++ b/VersionASM @@ -1,5 +1,6 @@ ; ; This file is automatically maintained by srccommit, do not edit manually. +; Last processed by srccommit version: 1.62. ; GBLS Module_MajorVersion GBLA Module_Version @@ -11,14 +12,14 @@ GBLS Module_HelpVersion GBLS Module_ComponentName GBLS Module_ComponentPath -Module_MajorVersion SETS "5.34" -Module_Version SETA 534 +Module_MajorVersion SETS "5.35" +Module_Version SETA 535 Module_MinorVersion SETS "" -Module_Date SETS "23 Aug 2001" -Module_ApplicationDate2 SETS "23-Aug-01" -Module_ApplicationDate4 SETS "23-Aug-2001" +Module_Date SETS "29 Jan 2002" +Module_ApplicationDate2 SETS "29-Jan-02" +Module_ApplicationDate4 SETS "29-Jan-2002" Module_ComponentName SETS "RISC_OSLib" Module_ComponentPath SETS "RiscOS/Sources/Lib/RISC_OSLib" -Module_FullVersion SETS "5.34" -Module_HelpVersion SETS "5.34 (23 Aug 2001)" +Module_FullVersion SETS "5.35" +Module_HelpVersion SETS "5.35 (29 Jan 2002)" END diff --git a/VersionNum b/VersionNum index 4894d1e8cb9a9ef65c26a0b50ed11a7784f714dd..6989597e6eab04c87437a5439a6e2b062e02d1d3 100644 --- a/VersionNum +++ b/VersionNum @@ -1,22 +1,24 @@ -/* (5.34) +/* (5.35) * * This file is automatically maintained by srccommit, do not edit manually. + * Last processed by srccommit version: 1.62. * */ -#define Module_MajorVersion_CMHG 5.34 +#define Module_MajorVersion_CMHG 5.35 #define Module_MinorVersion_CMHG -#define Module_Date_CMHG 23 Aug 2001 +#define Module_Date_CMHG 29 Jan 2002 -#define Module_MajorVersion "5.34" -#define Module_Version 534 +#define Module_MajorVersion "5.35" +#define Module_Version 535 #define Module_MinorVersion "" -#define Module_Date "23 Aug 2001" +#define Module_Date "29 Jan 2002" -#define Module_ApplicationDate2 "23-Aug-01" -#define Module_ApplicationDate4 "23-Aug-2001" +#define Module_ApplicationDate2 "29-Jan-02" +#define Module_ApplicationDate4 "29-Jan-2002" #define Module_ComponentName "RISC_OSLib" #define Module_ComponentPath "RiscOS/Sources/Lib/RISC_OSLib" -#define Module_FullVersion "5.34" -#define Module_HelpVersion "5.34 (23 Aug 2001)" +#define Module_FullVersion "5.35" +#define Module_HelpVersion "5.35 (29 Jan 2002)" +#define Module_LibraryVersionInfo "5:35" diff --git a/c/armsys b/c/armsys index 4b270b6f6cf9526dc95323aba5e419ef00cd2e61..21723b28c08170aa5ad6ed216eb16d7af9d2d900 100644 --- a/c/armsys +++ b/c/armsys @@ -33,6 +33,7 @@ #include <string.h> /* for strlen() */ #include <time.h> /* for clock */ #include <errno.h> +#include <stdbool.h> /* IMPORTS */ extern int main(int argc, char **argv); /* the point of it all */ @@ -40,11 +41,14 @@ extern FILEHANDLE __dup(int new, int old); extern void _ctype_init(void); extern int _fprintf_lf(FILE *fp, const char *fmt, ...); extern int _sprintf_lf(char *buff, const char *fmt, ...); +extern _kernel_oserror *_kernel_peek_last_oserror(void); /* HIDDEN EXPORTS */ void _main(char *s, int (*main)(int, char **)); void _backtrace(int why, int *address, _kernel_unwindblock *uwb); const char *_clib_version(void); +int _sys_msg_1(const char *s, const char *but); +int _desktop_task(void); #define str(x) #x #define xstr(x) str(x) @@ -149,9 +153,118 @@ time_t time(time_t *timer) #define istty(fh) ((fh) == TTYHANDLE) +/* + * We're a desktop task if we're in user mode, TaskWindow_TaskInfo 0 returns 0 (or an error), + * and Wimp_ReadSysInfo 3 says we're in the desktop, and Wimp_ReadSysInfo 5 gives us a + * task handle. + */ +int _desktop_task() +{ + int h = 0; + if (_kernel_processor_mode() & 0xF) return 0; + _swix(TaskWindow_TaskInfo, _IN(0)|_OUT(0), 0, &h); + if (h) return 0; + _swix(Wimp_ReadSysInfo, _IN(0)|_OUT(0), 3, &h); + if (h == 0) return 0; + _swix(Wimp_ReadSysInfo, _IN(0)|_OUT(0), 5, &h); + return h; +} + +static int _desktop_report(const char *s, const char *but) +{ + _kernel_oserror err, *e; + const char *n = NULL; + char *p, *end; + int flags, r, h = _desktop_task(); + if (h == 0) return 0; + + flags = 0x102; /* New error, cancel button */ + + if ((e = _kernel_last_oserror()) != NULL && s == e->errmess) + { + flags |= 2 << 9; + } + else + { + while (*s == ' ') + s++; + + if (s[0] == '*') /* If leading '*'s then make it a serious one */ + { + while (*s == '*' || *s == ' ') /* Strip off the '*'s */ + s++; + flags |= 3 << 9; + err.errnum = 0x1B << 24; + } + else + { + flags |= 2 << 9; + err.errnum = 0; + } + + for (p = err.errmess, end = err.errmess + sizeof err.errmess - 1; p < end && *s >= ' '; ) + *p++ = *s++; + + *p = '\0'; + err.errmess[0] = toupper(err.errmess[0]); + + e = &err; + } + _swix(TaskManager_TaskNameFromHandle, _IN(0)|_OUT(0), h, &n); + + r = 0; + _swix(Wimp_ReportError, _INR(0,5)|_OUT(1), e, flags, n, NULL, 1, but, &r); + return r; +} + +bool _sys__assert(const char *s, const char *expr, const char *file, int line) +{ + char buffer[252]; + int len, exprlen, filelen; + + if (!istty(stderr->__file)) return false; + + if (!_desktop_task()) return false; + + if (strlen(s) > 200) return false; /* Be safe */ + + len = sprintf(buffer, s, "", "", line); + exprlen = strlen(expr); + filelen = strlen(file); + if (len + exprlen + filelen < 251) + { + sprintf(buffer, s, expr, file, line); + } + else + { + char expr2[200]; + char file2[100]; + + #define min(a,b) a<b?a:b + exprlen = min(exprlen, 199); + filelen = min(filelen, 99); + filelen = min(filelen, 251-len-exprlen); + if (filelen < 0) filelen = 0; + exprlen = min(exprlen, 251-len-filelen); + memcpy(expr2, expr, exprlen); + memcpy(file2, file, filelen); + expr2[exprlen]='\0'; + file2[filelen]='\0'; + sprintf(buffer, s, expr2, file2, line); + } + return _desktop_report(buffer, NULL); +} + static int _error_recursion; -void _sys_msg(const char *s) -{ /* write out s carefully for intimate system use. */ +int _sys_msg_1(const char *s, const char *but) +{ + if (istty(stderr->__file)) + { + int r = _desktop_report(s, but); + if (r) return r; + } + + /* write out s carefully for intimate system use. */ if ((stderr->__flag & _IOWRITE) && !_error_recursion) { _error_recursion = 1; @@ -166,6 +279,13 @@ void _sys_msg(const char *s) _ttywrite((unsigned char *)s, strlen(s), 0); _ttywrite((unsigned char *)"\n", 1, 0); } + + return 0; +} + +void _sys_msg(const char *s) +{ + _sys_msg_1(s, NULL); } #define LF '\n' @@ -195,9 +315,8 @@ FILEHANDLE _sys_open(const char *filename, int openmode) (openmode & OPEN_W) || (openmode & ~OPEN_B) == OPEN_A) /* or mode = w, w+, or a */ { if (_kernel_osfile(9, name, &fb) == _kernel_ERROR) - { if (_kernel_last_oserror()->errnum == 0x108c9) - { (void)_kernel_osfile(9, name, &fb); /* to restore the error */ - errno = -1; + { if (_kernel_peek_last_oserror()->errnum == 0x108c9) + { errno = -1; return NONHANDLE; /* (Protected disc) */ } } diff --git a/c/error b/c/error index d6fdcfc43fc562fc54f9c418be923d0639ab4964..00c3eac4c08d0325410e65205a4bcb1f8d1249e7 100644 --- a/c/error +++ b/c/error @@ -49,9 +49,11 @@ void _sysdie(const char *s) /* from <assert.h> */ void __assert(char *expr, char *file, int line) { - _fprintf_lf(stderr, - _kernel_getmessage("*** assertion failed: %s, file %s, line %d", "C34"), - expr, file, line); + const char *s; + s = _kernel_getmessage("*** assertion failed: %s, file %s, line %d", "C34"); + + if (!_sys__assert(s, expr, file, line)) + _fprintf_lf(stderr, s, expr, file, line); fputc('\n', stderr); abort(); } diff --git a/c/signal b/c/signal index 1186109b5d12466656c1a4a4e0520285babbd274..fb4417ed05168cc694b797daf2f43c1010fbf803 100644 --- a/c/signal +++ b/c/signal @@ -29,6 +29,9 @@ extern int _fprintf_lf(FILE *fp, const char *fmt, ...); extern int _sprintf_lf(char *buff, const char *fmt, ...); +extern int _SignalNumber(int errnum); +extern _kernel_oserror *_kernel_peek_last_oserror(void); + #define SIGLAST 11 /* one after highest signal number (see <signal.h>) */ static void (*_signalvector[SIGLAST+1])(int); @@ -47,6 +50,14 @@ extern void __ignore_signal_handler(int sig) static void _real_default_signal_handler(int sig) { char *s, v[128]; + _kernel_oserror *e = _kernel_peek_last_oserror(); + + if (((sig == SIGSEGV || sig == SIGILL) && _SignalNumber(e->errnum) == sig) || + sig == SIGFPE || sig == SIGOSERROR) + { + _postmortem(e->errmess, *((int *)"mesg")); + return; + } switch (sig) { @@ -56,10 +67,6 @@ case SIGABRT: #endif s = _kernel_getmessage(s, "C39"); break; -case SIGFPE: -case SIGOSERROR: - s = &(_kernel_last_oserror()->errmess[0]); - break; case SIGILL: #ifdef DEFAULT_TEXT #ifdef __arm diff --git a/clib/s/cl_body b/clib/s/cl_body index 5a0f957b9703b01060847d4a9547f0924498fae7..e4272d61f1b3b41727e8e1ce8ba4eb61024a0552 100644 --- a/clib/s/cl_body +++ b/clib/s/cl_body @@ -68,6 +68,7 @@ $Label RFS r1 IMPORT |_signal_real_handler| IMPORT |_armsys_lib_init| IMPORT |_sys_msg| + IMPORT |_sys_msg_1| IMPORT |_kernel_fpavailable| IMPORT |_kernel_exittraphandler| @@ -103,11 +104,7 @@ $Label RFS r1 EXPORT |x$stack_overflow| EXPORT |x$stack_overflow_1| EXPORT |_raise_stacked_interrupts| - EXPORT |x$udivide| - EXPORT |x$uremainder| - EXPORT |x$divide| EXPORT |x$divtest| - EXPORT |x$remainder| EXPORT |x$multiply| EXPORT |_rd1chk| EXPORT |_rd2chk| @@ -137,14 +134,13 @@ $Label RFS r1 EXPORT |_count| EXPORT |_count1| EXPORT |_default_sigstak_handler| + EXPORT |_SignalNumber| EXPORT |_ldfp| EXPORT |_stfp| EXPORT |__rt_stkovf_split_small| EXPORT |__rt_stkovf_split_big| - EXPORT |__rt_udiv| - EXPORT |__rt_sdiv| EXPORT |__rt_divtest| EXPORT |__rt_rd1chk| EXPORT |__rt_rd2chk| @@ -242,6 +238,7 @@ UnhandledEventHandler Keep 02 MOV a1, #1 ; we wish to handle it, but not just yet Return ,LinkNotStacked +|_SignalNumber| SignalNumber Keep ; nb required not to disturb a4 MOV a2, #SIGOSERROR @@ -316,39 +313,21 @@ Raised |x$multiply| ; a1 := a2 * a1. -; sets a2 to 0 and a3 to a copy of the product. - MOV a3, #0 -m0loop MOVS a2, a2, LSR #1 - ADDCS a3, a3, a1 - ADD a1, a1, a1 - BNE m0loop - MOV a1, a3 +; a2, a3 can be scrambled. + MUL a1, a2, a1 Return ,LinkNotStacked -|x$remainder| - B |_kernel_srem| - IMPORT |_kernel_copyerror| IMPORT |_kernel_fault| |__rt_divtest| |x$divtest| ; test for division by zero (used when division is voided) - CMPS a1, #0 + TEQS a1, #0 Return ,LinkNotStacked, NE STMFD sp!, {r0} ADR r0, E_DivideByZero B |_kernel_fault| -|__rt_sdiv| -|x$divide| - B |_kernel_sdiv| - -|__rt_udiv| -|x$udivide| - B |_kernel_udiv| - -|x$uremainder| - B |_kernel_urem| |__rt_rd1chk| |_rd1chk| @@ -492,10 +471,6 @@ readfail Return mesg DCB "mesg" -wimp_title - DCB "WindowManager", 0 -utility_title - DCB "UtilityModule", 0 [ :DEF:DEFAULT_TEXT postmortem_title DCB "Postmortem", 0 @@ -504,70 +479,13 @@ postmortem_tag DCB "C65", 0 ALIGN -n_module_lookup EQU 18 -wimp_preinitflag EQU &80000000 -zp_wimpdomain EQU &ff8 - + IMPORT |_desktop_task| IMPORT |_kernel_unwind| + IMPORT exit |_postmortem| ; Prepare window manager for output ; First check this is a wimp task STMFD sp!, {r0-r5, r14} - MOV r0, #n_module_lookup - ADR r1, utility_title - SWI XOS_Module - BVS postmortem2 - LDR r0, [r3, #5 * 4] - MOV r1, #0 - ADD r0, r0, r3 -postmortem3 - LDRB r2, [r0], #1 - CMP r2, #9 - ORREQ r1, r1, #7 - ADD r1, r1, #1 - CMP r1, #16 - BCC postmortem3 - LDRB r1, [r0] - SUB r1, r1, #'0' - LDRB r2, [r0, #2] - SUB r2, r2, #'0' - ADD r1, r1, r1, LSL #2 - ADD r1, r2, r1, LSL #1 - LDRB r2, [r0, #3] - SUB r2, r2, #'0' - ADD r1, r1, r1, LSL #2 - ADD r1, r2, r1, LSL #1 - CMP r1, #202 - BCC postmortem2 - MOV r0, #0 - SWI XTaskWindow_TaskInfo - MOVVS r0, #0 - CMP r0, #0 - BNE postmortem0 - MOV r0, #3 - SWI XWimp_ReadSysInfo - BVS postmortem0 - CMP r0, #0 - BEQ postmortem0 - B postmortem4 -postmortem2 - MOV r0, #0 - SWI XWimp_ReadSysInfo - BVS postmortem0 - CMP r0, #0 - BEQ postmortem0 - ; In desktop, now check Wimp_Initialise has been called - MOV r0, #n_module_lookup - ADR r1, wimp_title - SWI XOS_Module - BVS postmortem0 - MOV r0, #0 - LDR r0, [r0, #zp_wimpdomain] - LDR r0, [r4, r0] - TST r0, #wimp_preinitflag - BNE postmortem0 - ; If so reopen command window -postmortem4 [ :DEF:DEFAULT_TEXT ADR r0, postmortem_title ADR r1, postmortem_tag @@ -575,13 +493,32 @@ postmortem4 ADR r0, postmortem_tag ] BL |_kernel_getmessage| - SWI XWimp_CommandWindow + MOV r5, r0 postmortem0 - LDMFD sp!, {r0-r5} - LDR a3, mesg - CMP a2, a3 - BLEQ |_sys_msg| ; BL<cond> 32-bit OK + LDMFD sp, {a1-a2} + LDR a3, mesg ; if magic arg2 != "mesg" + CMP a2, a3 ; then go straight onto postmortem + BNE postmortem1 + MOV a2, r5 ; if so, offer postmortem + BL |_sys_msg_1| + TEQ r4, #1 + TEQ a1, #0 ; if didn't display the button + TEQNE a1, #3 ; or if he selected it, then carry on with postmortem + MOVNE a1, #1 ; otherwise exit(EXIT_FAILURE) + BNE exit postmortem1 + BL _desktop_task + TEQ a1, #0 + BEQ postmortem2 + LoadStaticAddress __iob + 2 * 40, a2, a3 ; a2 -> stderr + LDR r4, [a2, #20] ; a2 = stderr->__file + TEQ r4, #0 ; istty(stderr->__file)? + BNE postmortem2 + MOV r0, r5 ; if desktop, and stderr = tty + SWI XWimp_CommandWindow ; then open command window, + SWI XOS_WriteI + 14 ; page mode on +postmortem2 + LDMFD sp!, {r0-r5} BL |_kernel_fpavailable| LDMFD sp!, {r14} CMP a1, #0 @@ -645,6 +582,28 @@ postmortem_nofp ADD sp, sp, #22*4 MOV a3, sp B |_backtrace| + ;MOV a1, #&4000 + ;MOV a2, #&4000 + ;MOV a3, #&20 + ;MOV a4, #&FF + ;SWI XOS_ReadLine + ;MOVCS a1, #124 + ;SWICS XOS_Byte + ;SWI XWimp_CloseDown + ;ADR a1, debug_cmd + ;SWI XOS_CLI + ;MOVVC a1, #0 + ;LDRVS a1, [a1] + ;TEQ a1, #0 + ;TEQNE a1, #&11 + ;MOVEQ a1, #-1 + ;SWIEQ XWimp_CommandWindow + ;MOV a1, #1 + ;B exit + +debug_cmd + DCB "Debug", 0 + ALIGN |__rt_stkovf_split_small| |x$stack_overflow| diff --git a/h/hostsys b/h/hostsys index a51bf5bb62effc1fc6c00f61704bee28528758e5..d0cf53706810d0f15de28c6aaf5851be469ae6ab 100644 --- a/h/hostsys +++ b/h/hostsys @@ -23,6 +23,7 @@ #define __hostsys_h #include <stdio.h> +#include <stdbool.h> #undef MACHINE #ifdef __arm @@ -99,6 +100,8 @@ extern void *_sys_alloc(size_t n); extern void _init_user_alloc(void); extern void _terminate_user_alloc(void); extern void _sys_msg(const char *); +extern bool _sys__assert(const char *fmt, + const char *expr, const char *file, int line); extern void _exit(int n); extern void _terminate_getenv(void); diff --git a/kernel/s/k_body b/kernel/s/k_body index 8e2f5c1fdec50b6c2c80b00f8b6cee0c946c346e..87badcdcd229ef495523e657aee18b25123d6005 100644 --- a/kernel/s/k_body +++ b/kernel/s/k_body @@ -47,6 +47,7 @@ EXPORT |_kernel_osargs| EXPORT |_kernel_oscli| EXPORT |_kernel_last_oserror| + EXPORT |_kernel_peek_last_oserror| EXPORT |_kernel_system| EXPORT |_kernel_getenv| EXPORT |_kernel_setenv| @@ -88,9 +89,16 @@ EXPORT |_kernel_call_client| EXPORT |_kernel_raise_error| + EXPORT |__rt_sdiv| + EXPORT |__rt_udiv| EXPORT |__rt_udiv10| EXPORT |__rt_sdiv10| + EXPORT |x$divide| + EXPORT |x$udivide| + EXPORT |x$remainder| + EXPORT |x$uremainder| + EXPORT |__counter| PSRBits * &FC000003 @@ -719,7 +727,7 @@ ABEXString ; tacked on the end. IIHandlerInDataInitValue - STMFD r13!, {r0, r12} + STMFD r13!, {r0-r4, r12, r14, pc} SUB r12, pc, #O_IIHandlerInData+12 ; Now the bits of the abort handlers which get executed from the code. @@ -728,81 +736,88 @@ IIHandlerInDataInitValue IIHandler Keep SUB r14, r14, #4 - ADR r0, E_IllegalInstruction + STR r14, [r12, #O_registerDump + 15 * 4] + + LDR r14, [r12, #O_oldAbortHandlers + 0] + STR r14, [r13, #28] B Aborted + PAHandlerInDataInitValue - STMFD r13!, {r0, r12} + STMFD r13!, {r0-r4, r12, r14, pc} SUB r12, pc, #O_PAHandlerInData+12 PAHandler Keep SUB r14, r14, #4 - ADR r0, E_PrefetchAbort + STR r14, [r12, #O_registerDump + 15 * 4] + + LDR r14, [r12, #O_oldAbortHandlers + 4] + STR r14, [r13, #28] B Aborted DAHandlerInDataInitValue - STMFD r13!, {r0, r12} + STMFD r13!, {r0-r4, r12, r14, pc} SUB r12, pc, #O_DAHandlerInData+12 DAHandler Keep SUB r14, r14, #8 - ADR r0, E_DataAbort + STR r14, [r12, #O_registerDump + 15 * 4] + + LDR r14, [r12, #O_oldAbortHandlers + 8] + STR r14, [r13, #28] B Aborted2 AEHandlerInDataInitValue - STMFD r13!, {r0, r12} + STMFD r13!, {r0-r4, r12, r14, pc} SUB r12, pc, #O_AEHandlerInData+12 AEHandler Keep SUB r14, r14, #8 - ADR r0, E_AddressException + STR r14, [r12, #O_registerDump + 15 * 4] + + LDR r14, [r12, #O_oldAbortHandlers + 12] + STR r14, [r13, #28] ; B Aborted2 Aborted2 Keep ; Abort which may be in the FP emulator, and if so should be reported ; as occurring at the instruction being emulated. ; Try the FPEmulator_Abort SWI - STMFD sp!, {r0-r2, r14} + + LDR r2, [sp, #24] [ {CONFIG}=26 - BIC r14, r14, #PSRBits + BIC r2, r2, #PSRBits | - MOV r0, #0 - MRS r0, CPSR - TST r0, #2_11100 - BICEQ r14, r14, #PSRBits + TEQ pc, pc + BICNE r2, r2, #PSRBits ] MOV r0, #-2 ; current context LDR r1, [sp, #20] ; original r12 - ADD r2, r14, #8 ; original r14 + ADD r2, r2, #8 ; original r14 SWI XFPEmulator_Abort BVS NoFPEAbortSWI TEQ r0, #0 - LDMEQFD sp!, {r0-r2, r14} + LDMEQFD sp, {r0-r2} BEQ Aborted ; not in FPEmulator - STR r0, [sp, #20] ; update r12 in stack - LDMFD sp!, {r0-r2, r14} B FPEFault NoFPEAbortSWI ; If in user mode, can't be in FPE [ {CONFIG}=26 - LDR r1, [sp, #12] + LDR r1, [sp, #24] TST r1, #PSRPrivileged | - MOV r2, #0 - MRS r2, CPSR - TST r2, #2_11100 - LDREQ r1, [sp, #12] - ANDEQ r1, r1, #3 ; obtain aborter's mode from R14 - MRSNE r1, SPSR ; obtain aborter's mode from SPSR + TEQ pc, pc + LDRNE r1, [sp, #24] + ANDNE r1, r1, #PSRMode ; obtain aborter's mode from R14 + MRSEQ r1, SPSR ; obtain aborter's mode from SPSR TST r1, #PSR32Privileged ] - LDMEQFD sp!, {r0-r2, r14} + LDMEQFD sp, {r0-r4} BEQ Aborted ; Otherwise, find out where the FPE module is [ {CONFIG} <> 26 TST r2, #2_11100 ] - LDMFD sp!, {r0-r2, r14} - STMFD sp!, {r0 - r6, r14} + STMFD sp!, {r0 - r6} [ {CONFIG} = 26 BIC r6, r14, #PSRBits | @@ -812,65 +827,60 @@ NoFPEAbortSWI MOV r0, #18 ADR r1, FPEName SWI Module - LDMVSFD sp!, {r0 - r6, r14} + LDMVSFD sp!, {r0 - r6} BVS Aborted ; (r3 = code base of FPE; word before is length of FPE code) CMP r6, r3 LDRGE r4, [r3, #-4] ADDGE r3, r3, r4 CMPGE r3, r6 - LDMFD sp!, {r0 - r6, r14} + LDMFD sp!, {r0 - r6} BLT Aborted ; It was a storage fault in the FP emulator. -; We assume FPEmulator 4.00 or later - r12 in the register dump +; We assume FPEmulator 4.00 or later - r0 ; will point to a full register save. The format differs slightly ; depending on whether the FPEmulator is 32-bit or not. If we're ; in a 32-bit mode, we know the FPEmulator will be. If not, check ; to see if the saved r12 is in the UND stack. FPEFault - LDR r1, [r13, #4] ; r1 -> FPE stack frame - ADD r13, r13, #8 ; pop the saved values of r0 and r12 ADD r14, r12, #O_registerDump - LDMIA r1!, {r2-r9} ; copy R0-R15 - STMIA r14!, {r2-r9} - LDMIA r1!, {r2-r9} - SUB r9, r9, #4 - STMIA r14!, {r2-r9} + LDMIA r0!, {r1-r4} ; copy R0-R15 + STMIA r14!, {r1-r4} + LDMIA r0!, {r1-r4} + STMIA r14!, {r1-r4} + LDMIA r0!, {r1-r4} + STMIA r14!, {r1-r4} + LDMIA r0!, {r1-r4} + SUB r4, r4, #4 ; adjust PC back 4 + STMIA r14!, {r1-r4} [ {CONFIG}<>26 - MOV r2, #0 - MRS r2, CPSR - TST r2, #2_11100 - BNE FPEFault_32on32 + TEQ pc, pc + BEQ FPEFault_32on32 ] LDR r3, [r12, #O_undStack] MOV r2, r1, LSR #20 ; we're on a 26-bit system TEQ r2, r3, LSR #20 ; is the stack frame in the UND stack? BEQ FPEFault_32on26 FPEFault_26on26 - MOV sp, r1 ; pull the SVC stack up - B AbortFindHandler + B FPEFault_Continue FPEFault_32on26 - LDR r2, [r1, #-72] ; get the SPSR + LDR r2, [r0, #-72] ; get the SPSR AND r2, r2, #PSRBits - BIC r9, r9, #PSRBits - ORR r9, r9, r2 - STR r9, [r14, #-4] ; merge it with pc in register dump - B FPEFault_32 + BIC r4, r4, #PSRBits + ORR r4, r4, r2 + STR r4, [r14, #-4] ; merge it with pc in register dump + [ {CONFIG}<>26 + B FPEFault_Continue FPEFault_32on32 LDR r2, [r1, #-72] ; get the SPSR STR r2, [r14] ; store it in the register dump + ] -FPEFault_32 - MRS r2, CPSR - BIC r3, r2, #PSR32Mode - ORR r3, r3, #PSR32IBit + PSR32UNDMode - MSR CPSR_c, r3 - MOV sp, r1 ; pull the UND stack up - MSR CPSR_c, r2 - B AbortFindHandler +FPEFault_Continue + LDMFD r13!, {r0-r4, r12, r14, pc} ErrorBlock PrefetchAbort, "Prefetch Abort", C60 ErrorBlock DataAbort, "Data Abort", C61 @@ -880,59 +890,49 @@ FPEName = "FPEmulator",0 ALIGN Aborted Keep -; entry here in SVC26, SVC32, ABT32 or UND32 mode -; r0 a pointer to an error block describing the abort. -; all user registers except r0, r12 are as at the time of the abort. -; r0 & r12 are on the stack. -; First, save all user registers in registerDump. - STMFD r13!, {r14} ; remember the abort pc - BL |_kernel_copyerror| ADD r14, r12, #O_registerDump - [ SASTMhatbroken - STMIB r14!, {r1-r12} - STMIB r14, {r13,r14}^ - NOP - SUB r14, r14, #12*4 + STMIA r14!, {r0-r12} + STMIA r14, {r13,r14}^ + NOP + SUB r14, r14, #13*4 | - STMIB r14, {r1-r14}^ + STMIA r14, {r0-r14}^ + NOP ] - LDMFD r13!, {r1, r2, r3} ; abort PC, R0, R12 - - MOV r6, r14 ; switch it to a non-banked register - MOV r4, #0 - MRS r4, CPSR - TST r4, #2_11100 - ANDEQ r5, r1, #3 ; obtain aborter's mode from R14 - MRSNE r5, SPSR ; obtain aborter's mode from SPSR - STRNE r5, [r14, #16*4] ; store aborter's SPSR if in 32-bit mode - BICNE r4, r4, #PSR32Mode - ORRNE r4, r4, #PSR32SVCMode - MSRNE CPSR_c, r4 ; switch to SVC32 (already in SVC26 if 26bit) - TST r5, #PSR32Privileged - LDRNE r1, [r6, #lr*4] ; if aborted in a privileged mode, save - STR r1, [r6, #pc*4] ; PC as user R14 - STR r2, [r6, #r0*4] - STREQ r3, [r6, #r12*4] - BEQ AbortFlattenStacks - LDR r4, [r12, #O_svcStack] - SUB r1, r4, sp - CMP r1, #3 * 4 - BCC AbortFlattenStacks - LDMEA r4, {r1, r2, r3} - ADD r4, r6, #10 * 4 - STMIA r4, {r1, r2, r3} - -; should really fall through to error handler and let the OS clean up, -; but this is a lot better than it was! -AbortFlattenStacks - MRS r4, CPSR ; MRS and MSR here will be NOPs on - ORR r1, r4, #PSR32UNDMode ; ARM2/3, so we'll end up setting - MSR CPSR_c, r1 ; R13_svc twice; just make sure - LDR sp, [r12, #O_undStack] ; we set the real value last. - MSR CPSR_c, r4 - LDR sp, [r12, #O_svcStack] + LDR r0, [r13, #20] + STR r0, [r14, #r12*4] + + MOV r3, pc + AND r3, r3, #PSRBits + MRS r3, CPSR + TST r3, #2_11100 + LDREQ r0, [sp, #24] + ANDEQ r0, r0, #PSRMode ; obtain aborter's mode from R14 + MRSNE r0, SPSR ; obtain aborter's mode from SPSR + STRNE r0, [r14, #16*4] ; store aborter's SPSR if in 32-bit mode + TST r0, #PSR32Privileged + BEQ NotPrivileged + LDR r0, [r14, #r14*4] ; if abort in a privileged mode, save + STR r0, [r14, #pc*4] ; PC as user R14 + LDR r0, [r12, #O_svcStack] ; switch to SVC mode and look at R13_svc + TEQ pc, pc + MSREQ CPSR_c, #PSR32SVCMode + TEQNEP pc, #PSRSVCMode + NOP + SUB r12, r0, sp + CMP r12, #3 * 4 + BLT NotPrivileged + LDMDB r0, {r0-r2} ; Pull R10-R12 off of top of SVC stack + ADD r4, r14, #10 * 4 ; if there were at least 3 words on it + STMIA r4, {r0-r2} + TEQ pc, pc + MSREQ CPSR_cxs, r3 + TEQNEP pc, r3 + NOP +NotPrivileged + LDMFD r13!, {r0-r4, r12, r14, pc} AbortFindHandler Keep ; We can only call an abort handler if we had a stack at the @@ -1493,19 +1493,26 @@ ErrorHandler Keep ; Since it would be nice to preserve as much as possible for the FP fault case ; we switch back to SWI mode to save the registers. SWI EnterSVC - ADD r14, r0, #O_registerDump + LDR r14, [r0, #O_errorNumber] + TEQ r14, #Error_IllegalInstruction + TEQNE r14, #Error_PrefetchAbort + TEQNE r14, #Error_DataAbort + TEQNE r14, #Error_AddressException [ SASTMhatbroken - STMIA r14!, {r0-r12} - STMIA r14, {r13,r14}^ - NOP - SUB r14, r14, #13*4 + ADDNE r14, r0, #O_registerDump + STMNEIA r14!, {r0-r12} + STMNEIA r14, {r13,r14}^ + NOP + SUBNE r14, r14, #13*4 | - STMIA r14, {r0-r14}^ + STMNEIA r14, {r0-r14}^ ] MOV r12, r0 ADD r0, r0, #O_errorNumber + BEQ AbortFindHandler + LDMDA r0, {r1, r2} ; r1 is error pc, r2 error number MOV r14, #0 STR r14, [r12, #O_registerDump+16*4] ; zero PSR @@ -1582,13 +1589,20 @@ EndFastEventHandlers EscapeHandler Keep TSTS r11, #&40 - MOVEQ pc, r14 ; ignore flag going away + BNE haveEscape + STMFD r13!, {r0} + MOV r0, #0 + STRB r0, [r12, #O_hadEscape] + LDMFD r13!, {r0} + MOV pc, r14 ; ignore flag going away +haveEscape ; In Arthur, it is NEVER safe to call a handler now: we always have to ; wait for CallBack. STMFD r13!, {r0} MOV r0, #-1 STRB r0, [r12, #O_hadEscape] + LDRB r0, [r12, #O_eventCode] STRB r0, [r12, #O_escapeSeen] STR r0, [r12, #O_eventCode] LDRB r11, [r12, #O_callbackInactive] @@ -1652,9 +1666,12 @@ Event_NoStackForHandler MOV r1, #0 STRB r1, [v6, #O_hadEscape] LDR v1, [v6, #O_eventCode] + TEQ r0, #0 ; if hadEscape = 0 + CMPEQ v1, #-1 ; and it's an escape event + BEQ %FT02 ; then the escape's gone. CMP r0, #0 BEQ %FT01 - MOV r0, #&7e + MOV r0, #126 ; acknowledge escape SWI Byte MOV v1, #-1 ; escape overrides everything else 01 @@ -1667,7 +1684,7 @@ Event_NoStackForHandler CMP r12, #0 BGE CallEventHandlers - +02 ADD r0, v6, #O_registerDump B ReloadUserState @@ -2116,6 +2133,13 @@ ErrorExitV6Stacked STRNE a2, [ip, #O_errorBuffer] Return ,LinkNotStacked +|_kernel_peek_last_oserror| + LoadStaticBase ip, a1 + LDR a1, [ip, #O_errorBuffer] + TEQ a1, #0 + ADDNE a1, ip, #O_errorNumber + Return ,LinkNotStacked + |_kernel_system| ; Execute the string a1 as a command; if a2 is zero, as a subprogram, ; otherwise a replacement. @@ -2853,7 +2877,9 @@ StackOverflowFault Keep ;* Arithmetic * ;*-------------------------------------------------------------------* +|__rt_udiv| |_kernel_udiv| +|x$udivide| ; Unsigned divide of a2 by a1: returns quotient in a1, remainder in a2 ; Destroys a3 and ip @@ -2913,6 +2939,7 @@ u_sh0 RSBS ip, a1, a2 ; codegenerator will call udiv directly and use the result in a2 |_kernel_urem| +|x$uremainder| FunctionEntry BL |_kernel_udiv| MOV a1, a2 @@ -2936,7 +2963,9 @@ u_sh0 RSBS ip, a1, a2 Return ,LinkNotStacked +|__rt_sdiv| |_kernel_sdiv| +|x$divide| ; Signed divide of a2 by a1: returns quotient in a1, remainder in a2 ; Quotient is truncated (rounded towards zero). ; Sign of remainder = sign of dividend. @@ -3001,6 +3030,7 @@ s_sh0 RSBS ip, a1, a2 ; Signed remainder of a2 by a1: returns remainder in a1 |_kernel_srem| +|x$remainder| FunctionEntry BL |_kernel_sdiv| MOV a1, a2