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