From 5b02a99eb465467fd09705b00466698009bb547f Mon Sep 17 00:00:00 2001
From: Kevin Bracey <kbracey@gitlab.riscosopen.org>
Date: Thu, 1 May 1997 08:09:35 +0000
Subject: [PATCH] RISC OS 3.71 version taken

---
 TestSrc/Begin       | 124 ++++++++++++++--
 TestSrc/Ioc         |  11 +-
 TestSrc/Mem1IOMD    |  20 ++-
 TestSrc/Mem2        |  62 ++++++--
 TestSrc/Mem3        |   4 +
 Version             |   6 +-
 s/AMBControl/memmap |  48 +++++-
 s/ARM600            | 352 +++++++++++++++++++++++++++++++++++++++-----
 s/ChangeDyn         |   9 ++
 s/Copro15ops        | 172 +++++++++++++++++++++-
 s/GetAll            |  40 ++++-
 s/KbdResPC          |  14 +-
 s/Kernel            |   7 +
 s/Middle            |  27 ++--
 s/NewReset          |  93 +++++++++++-
 s/PMF/osinit        |  14 +-
 s/vdu/vdudriver     |  23 ++-
 17 files changed, 894 insertions(+), 132 deletions(-)

diff --git a/TestSrc/Begin b/TestSrc/Begin
index 7c1dd7b6..1cc7ca4c 100644
--- a/TestSrc/Begin
+++ b/TestSrc/Begin
@@ -284,6 +284,20 @@ ts_ROM_bvectors
         SetMode SVC32_mode,$tmp
         MEND
 
+ [ StrongARM_POST
+;  ensure 26-bit mode for StrongARM or ARM 8 (since there is no 26 bit configuration)
+        MACRO
+        Ensure26bit_ARM8A $tmp
+        ARM_read_ID $tmp
+        AND     $tmp, $tmp, #&F000
+        CMP     $tmp, #&A000
+        CMPNE   $tmp, #&8000
+        mrs     EQ, $tmp, CPSR_all
+        BICEQ   $tmp, $tmp, #&10
+        msr     EQ, CPSR_all, $tmp
+        MEND
+  ]
+
 ;
 ; Define an area of storage with the required set of data bus patterns
 ; These are used both for testing the complete width of the data bus
@@ -481,8 +495,13 @@ ts_User_startup    ROUT
         ADDS    r1,r1,r1                ; then shift it into carry
         BCC     ts_Self_test_end        ; POR bit clear - do soft reset.
 
-; it's a power-on reset, so assume we can't be in 32-bit mode
+; it's a power-on reset, so assume we can't be in 32-bit mode for ARM 6/7
 
+  [ StrongARM_POST
+    ; make sure we are in 26-bit mode (ARM 6/7 reset in 26-bit config)
+    ; note that MOV_fiq macro assumes 26-bit, so must sort this now
+    Ensure26bit_ARM8A r0
+  ]
         MOV_fiq r12_fiq, #R_HARD
         B       ts_Self_test_startup
         |
@@ -501,6 +520,11 @@ ts_User_startup    ROUT
 
 ts_Forced_startup  ROUT
 
+  [ StrongARM_POST
+    ; make sure we are in 26-bit mode (ARM 6/7 reset in 26-bit config)
+    ; note that MOV_fiq macro assumes 26-bit, so must sort this now
+    Ensure26bit_ARM8A r0
+  ]
         MOV_fiq r12_fiq, #R_TESTED
         B       ts_Self_test_startup
 
@@ -508,6 +532,11 @@ ts_Forced_startup  ROUT
 
 ts_Dealer_startup  ROUT
 
+  [ StrongARM_POST
+    ; make sure we are in 26-bit mode (ARM 6/7 reset in 26-bit config)
+    ; note that MOV_fiq macro assumes 26-bit, so must sort this now
+    Ensure26bit_ARM8A r4
+  ]
         MOV_fiq r12_fiq, #R_EXTERN
 
         LDR     r4,%FT02                ; make a pointer to signon string
@@ -538,10 +567,17 @@ ts_Self_test_startup ROUT
         MOV     r2, #IOMD_Base
 
         LDRB    r0, [r2, #IOMD_ID0]
-        CMP     r0, #&98
+        CMP     r0, #&E7
         LDRB    r0, [r2, #IOMD_ID1]
-        CMPEQ   r0, #&5B
-        BNE     %FT10
+        CMPEQ   r0, #&D4
+        BEQ     %FT10
+
+ [ RO371Timings
+
+        MOV     r0, #0                  ;Calling from POST
+        BL      TimeCPU                 ;just sets things according to assumed bus speeds for each IOMD id, in this case
+
+ | ; else if not RO371Timings
 
 ;
 ; PSwindell wants all prescalers set to divide by 1
@@ -557,6 +593,7 @@ ts_Self_test_startup ROUT
 ;
         LDRB    r1, [r2, #IOMD_ROMCR0]
         AND     r1, r1, #&40            ; clear all but 16-bit mode bit
+
  [ :LNOT: AutoSpeedROMS
   [ NormalSpeedROMS
    ;Normal code
@@ -570,12 +607,16 @@ ts_Self_test_startup ROUT
 
         ! 0, "*** WARNING *** Slow ROM version ment for PSwindell"
   ]
+
         STRB    r1, [r2, #IOMD_ROMCR0]
         STRB    r1, [r2, #IOMD_ROMCR1]         ; and do the same for extension ROMs (just in case)
  |
         MOV     r0, #0                  ;Don't muck with the CPU coprocessor regs
         BL      TimeCPU                 ;This times the memory bus & sets the ROM speed accordingly
  ]
+
+ ] ;RO371Timings conditional
+
 ;
 10
  ]
@@ -609,15 +650,27 @@ ts_InitVIDC
         STRNE   r0, [r1]
         BNE     %BT10
 
- [ StrongARM
-   ;just too horrible to fix POST for StrongARM (Architecture 4) at the moment
-   ARM_read_ID r0
-   AND     r0,r0,#&F000
-   CMP     r0,#&A000              ;if we are a StrongARM...
-   LDREQ   r0,=C_WARMSTART        ;the colour that indicates no POST performed
-   STREQ   r0,[r1]
-   BEQ     ts_Hardstart           ;RISC OS - right now!
+ [ :LNOT: StrongARM_POST
+   ;skip POST for StrongARM or ARM8
+        ARM_read_ID r0
+        AND     r0,r0,#&F000
+        CMP     r0,#&A000              ;if we are a StrongARM...
+        CMPNE   r0,#&8000              ;or an ARM8...
+        LDREQ   r0,=C_WARMSTART        ;the colour that indicates no POST performed
+        STREQ   r0,[r1]
+        BEQ     ts_Hardstart           ;RISC OS - right now!
+ ]
+
+ [ ARM810support :LAND: (:LNOT: ARM810_POST)
+   ;just too horrible to fix POST for ARM 8 at the moment
+        ARM_read_ID r0
+        AND     r0,r0,#&F000
+        CMP     r0,#&8000              ;if we are an ARM 8
+        LDREQ   r0,=C_WARMSTART        ;the colour that indicates no POST performed
+        STREQ   r0,[r1]
+        BEQ     ts_Hardstart           ;RISC OS - right now!
  ]
+
         LDR     r0,=C_ARMOK     ; set initial screen colour
         STR     r0, [r1]
 
@@ -1162,6 +1215,27 @@ ts_CAMtest
 ;
 
 ts_restore_physical
+
+  [ StrongARM_POST
+    ;make sure ARM810 cache or StrongARM data cache is cleaned/flushed, because we are going to remap
+        ARM_read_ID r5
+        AND     r5,r5,#&F000
+        CMP     r5,#&8000
+        BNE     %FT22
+;ARM810
+;;;        ARM8_cleanflush_IDC r5  ;not implemented yet
+        B       %FT24
+22
+        CMP     r5,#&A000
+        BNE     %FT24
+;StrongARM
+;tricky...we'll read 16k of data in current ROM space, to act as clean and flush of current data
+        MOV     r3,pc
+        BIC     r3,r3,#31      ;32 byte aligned
+        ARMA_clean_DC r3,r5,r7
+24
+  ] ;StrongARM_POST
+
         MOV     r5, pc                          ; obtain current address
         SUB     r5, r5,#PhysSpace               ; adjust to point to unmapped version
         MOV     r5, r5, LSR #20                 ; divide by 1MB
@@ -1174,8 +1248,20 @@ ts_restore_physical
         ADD     r3, r3, #DRAMOffset_L1PT
         STR     r7, [r3, r5, LSL #2]            ; store replacement entry in L1 (not U,C or B)
 
+  [ StrongARM_POST
+    ;flush cache if ARM 6/7 (ARM 8,StrongARM already sorted, above)
+    ;flush TLB(s)
+        ARM_read_ID r4
+        AND      r4,r4,#&F000
+        CMP      r4,#&8000   ;ARM 8?
+        CMPNE    r4,#&A000   ;or StrongARM?
+        MCRNE    ARM_config_cp,0,R0,ARM67_cacheflush_reg,C0,0   ;flush 6/7 cache
+        MCRNE    ARM_config_cp,0,R0,ARM67_TLBflush_reg,C0,0     ;flush 6/7 TLB
+        MCREQ    ARM_config_cp,0,R0,ARM8A_TLB_reg,C7,0          ;flush 8/StrongARM TLB(s)
+  |
         SetCop  r7, CR_IDCFlush                 ; flush cache + TLB just in case
         SetCop  r7, CR_TLBFlush                 ; (data written is irrelevant)
+  ]
 
 ; The ROM should now be mapped at the present address less PhysSpace, which is where it
 ; would be if the MMU were turned off.
@@ -1184,9 +1270,15 @@ ts_restore_physical
         SUB     pc,pc,r4
         NOP                             ; this instruction is skipped
 
-        MOV     r7, #MMUC_D             ; Now turn the MMU off
+; now turn the MMU off, also ensures 26 bit mode, if ARM 6/7 (since P bit zero)
+        MOV     r7, #MMUC_D
         SetCop  r7, CR_Control
 
+  [ StrongARM_POST
+        Ensure26bit_ARM8A r7
+        MOV     r7, #MMUC_D    ;avoid corrupting r7, just in case
+  ]
+
         B       ts_VIDCtest
 
 ;
@@ -1223,10 +1315,10 @@ ts_VIDCtest
         MOV     r3, #IOMD_Base
 
         LDRB    r0, [r3, #IOMD_ID0]
-        CMP     r0, #&98
+        CMP     r0, #&E7
         LDRB    r0, [r3, #IOMD_ID1]
-        CMPEQ   r0, #&5B                ; skip Virq test on Morris
-        BEQ     %FT10
+        CMPEQ   r0, #&D4                ; skip Virq test on Morris
+        BNE     %FT10
  ]
 
         BL      ts_VIDC_period
diff --git a/TestSrc/Ioc b/TestSrc/Ioc
index 1c37914c..e5a9ac07 100644
--- a/TestSrc/Ioc
+++ b/TestSrc/Ioc
@@ -3,7 +3,7 @@
         TTL RISC OS 2+ POST IO controller
 ;
 ; This initial IOC test simply reports the content of the IRQ and FIRQ
-; registers, to show any unexpected pending IRQs. 
+; registers, to show any unexpected pending IRQs.
 ; Certain of these should really be cleared, and the effect of an
 ; interrupt tested.
 ;
@@ -77,8 +77,9 @@ ts_IOCstat
         LDR     r1,=ts_IOMD_ID
         CMPS    r0,r1                   ; check IOMD identity
  [ MorrisSupport
-        LDRNE   r1,=ts_IOMD_IDmorris    ; allow for Morris variant
-        CMPNES  r0,r1
+;;        LDRNE   r1,=ts_IOMD_IDmorris    ; allow for Morris variant
+;;        CMPNES  r0,r1
+        CMPNE r0,r0    ;insist on not failing (allow 7500,7500FE...)
  ]
         MOV     r0,r0,LSL #16
         LDRB    r1,[r3,#IOMD_VERSION]
@@ -98,5 +99,5 @@ ts_IOCstat
         MOV     pc,r14
         ]
 
-        END 
- 
+        END
+
diff --git a/TestSrc/Mem1IOMD b/TestSrc/Mem1IOMD
index d44b2a96..10230ab0 100644
--- a/TestSrc/Mem1IOMD
+++ b/TestSrc/Mem1IOMD
@@ -42,10 +42,10 @@ ts_LineTest
         MOV     r12, #IOMD_Base
 
         LDRB    r0, [r12, #IOMD_ID0]
-        CMP     r0, #&98
+        CMP     r0, #&E7
         LDRB    r0, [r12, #IOMD_ID1]
-        CMPEQ   r0, #&5B
-        BNE     ts_LineTestIOMD                         ; NOT MORRIS assume Medusa hardware
+        CMPEQ   r0, #&D4
+        BEQ     ts_LineTestIOMD                         ; Medusa hardware, else assume Morris
 
 ;
 ; ts_LineTest for Morris
@@ -54,9 +54,14 @@ ts_LineTest
         MOV     r14, #IOMD_Base
         STRB    r11, [r14, #IOMD_DRAMWID]
 
-        MOV     r0,#MMUC_D                              ; enable 32-bit addressing of data
+; enable 32-bit addressing of data, also forces 26 bit mode, if ARM 6/7 (since P bit zero)
+        MOV     r0,#MMUC_D
         SetCop  r0,CR_Control
 
+  [ StrongARM_POST
+        Ensure26bit_ARM8A r0
+  ]
+
         MOV     r0,#0
         MOV_fiq r9,r0                                   ; r9-fiq records low DRAM address for use elsewhere
 
@@ -344,9 +349,14 @@ ts_LineTestIOMD
         MOV     r14, #IOMD_Base
         STRB    r11, [r14, #IOMD_DRAMCR]
 
-        MOV     r0,#MMUC_D                              ; enable 32-bit addressing of data
+; enable 32-bit addressing of data, also forces 26 bit mode, if ARM 6/7 (since P bit zero)
+        MOV     r0,#MMUC_D
         SetCop  r0,CR_Control
 
+  [ StrongARM_POST
+        Ensure26bit_ARM8A r10
+  ]
+
         MOV     r10, #0                                 ; indicate no RAM found yet
         MOV     r9, #IOMD_DRAMCR_DRAM_Small             ; bit to OR into DRAMCR
         MOV     r12, #DRAM0PhysRam
diff --git a/TestSrc/Mem2 b/TestSrc/Mem2
index 89f5bc2d..09e9b97a 100644
--- a/TestSrc/Mem2
+++ b/TestSrc/Mem2
@@ -1,13 +1,13 @@
 ;> MEM2C
-; 
+;
 ; RISC OS 2+ BOOT TEST SOFTWARE
 ; MEMORY TEST 2 VERSION A.
 ; BRIAN RICE 30-10-89
 ; 06-Apr-90     ArtG    0.1     Test variable memory size
 ;
 ; This file will perform a simple test on all DRAM.
-; The test code for this test was taken from thhe A680 Quick memory 
-; test software. The software was copied straight but the number of times 
+; The test code for this test was taken from thhe A680 Quick memory
+; test software. The software was copied straight but the number of times
 ; the test looped arround was cut down to two loops, because of time
 ; constraints when testing the memory.
 
@@ -50,8 +50,8 @@ test_mem_quit
 	ANDS    r2,r2,#1	        ; calculate expected data
 	ADREQ   r12,%20	        	; and load suitable message
 	ADRNE   r12,%21
-	MOVS    r0,r0			; with zero flag set for PASS. 
-10	
+	MOVS    r0,r0			; with zero flag set for PASS.
+10
 	LDR	pc,[r13,#Test_wks_return1]
 
 ; Fail messages indicate incorrect data read after WRote 0 or Wrote 1
@@ -84,7 +84,7 @@ test_mem_code
 	STR	r14, [r13, #Test_wks_return2]
 ;
 ; Copy the ram test code into low ram, modifying MOV instructions
-; to MVN in accordance with the test pattern. 
+; to MVN in accordance with the test pattern.
 ;
 	ADR    r1, test_mem_template
 	ADD    r2, r13,        #Test_code_off
@@ -149,7 +149,7 @@ test_mem_code
 ; The following code is copied  (and modified) into RAM for execution
 ;
 
-test_mem_template 
+test_mem_template
 	ROUT
 	STR     r0, test_mem_stadd      ; save initial RAM address
 	STR	r13, test_mem_base	; save test area base address
@@ -188,7 +188,7 @@ test_mem_template
 	CMPEQ   r11, #0	        ; Converted to cmneq if bit = 1
 	CMPEQ   r12, #0	        ; Converted to cmneq if bit = 1
 	CMPEQ   r13, #0	        ; Converted to cmneq if bit = 1
-test_mem_chk 
+test_mem_chk
 	BNE     %F5		; go report fault data
 	CMP     r0, r14
 	BLO     %B1		; else loop for next batch
@@ -201,7 +201,7 @@ test_mem_chk
 ; the first failing address and data.
 ; Note that the test instructions are copied to %8 to permit individual
 ; execution, and %7 is overwritten with an instruction used to copy
-; the failing data into r1. Change this code very carefully ! 
+; the failing data into r1. Change this code very carefully !
 
 5
 	LDR     r14,%2			; Obtain first test in the set
@@ -218,8 +218,8 @@ test_mem_chk
 				    	; r14 => failing instruction
 
 	LDR     r1,[r14,#4]!	    	;fetch next instruction
-	AND     r1,r1,#&f0000		;make an instruction 
-	MOV     r1,r1,LSR #16		;to copy the next register 
+	AND     r1,r1,#&f0000		;make an instruction
+	MOV     r1,r1,LSR #16		;to copy the next register
 	ORR     r1,r1,#&E1000000	;down to r1
 	ORR     r1,r1,#&00A00000	;e.g. CMPEQ r10,#0
 	ORR     r1,r1,#&00001000
@@ -243,6 +243,27 @@ test_mem_template_end
 	ROUT
 
 ts_remap_ttab
+
+   [ StrongARM_POST
+    ;make sure ARM810 cache or StrongARM data cache is cleaned/flushed, because we are going to remap
+        ARM_read_ID r3
+        AND     r3,r3,#&F000
+        CMP     r3,#&8000
+        BNE     %FT22
+;ARM810
+;;;        ARM8_cleanflush_IDC r3 ;not implemented yet
+        B       %FT24
+22
+        CMP     r3,#&A000
+        BNE     %FT24
+;StrongARM
+;tricky...we'll read 16k of data in current ROM space, to act as clean and flush of current data
+        MOV     r3,pc
+        BIC     r3,r3,#31      ;32 byte aligned
+        ARMA_clean_DC r3,r4,r5
+24
+  ] ;StrongARM_POST
+
 	MOV	r2,#FixedAreasL2Size
 	ADD	r0,r0,r2		; point to locations in PhysSpace
 	ADD	r0,r0,#PhysSpace
@@ -255,7 +276,7 @@ ts_remap_ttab
 	SUBS	r2,r2,#(8*4)
 	BNE	%BT10
 
-	SUB	r9,r1,r0		; r9 = offset from original to copy 
+	SUB	r9,r1,r0		; r9 = offset from original to copy
         ADD     r0, r0, #DRAMOffset_L1PT-DRAMOffset_L2PT	; r0 -> copy of L1Phys
 	SUB	r10, r0, #PhysSpace	; keep real address of L1PT for MMU
 	ADD	r2,r0,#((1 :SHL: (32-20))*4)	; size of L1PT - 1 word per meg of memory
@@ -265,14 +286,27 @@ ts_remap_ttab
 	SUBEQ	r3,r3,r9		; adjust the page table base address
 	STREQ	r3,[r0,#-4]
 	CMPS	r0,r2			; repeat for all the level 1 table
-	BNE	%BT11	
+	BNE	%BT11
 
         SetCop  r10, CR_TTabBase	; set up MMU pointer to L1
+
+  [ StrongARM_POST
+    ;flush cache if ARM 6/7 (ARM 8,StrongARM already sorted, above)
+    ;flush TLB(s)
+        ARM_read_ID r4
+        AND      r4,r4,#&F000
+        CMP      r4,#&8000   ;ARM 8?
+        CMPNE    r4,#&A000   ;or StrongARM?
+        MCRNE    ARM_config_cp,0,R0,ARM67_cacheflush_reg,C0,0   ;flush 6/7 cache
+        MCRNE    ARM_config_cp,0,R0,ARM67_TLBflush_reg,C0,0     ;flush 6/7 TLB
+        MCREQ    ARM_config_cp,0,R0,ARM8A_TLB_reg,C7,0          ;flush 8/StrongARM TLB(s)
+  |
         SetCop  r0, CR_IDCFlush		; flush cache + TLB just in case
         SetCop  r0, CR_TLBFlush		; (data written is irrelevant)
+  ]
 
 	MOV	pc,r14
 
 
  END
-  
+
diff --git a/TestSrc/Mem3 b/TestSrc/Mem3
index 1313275f..482c5fad 100644
--- a/TestSrc/Mem3
+++ b/TestSrc/Mem3
@@ -36,6 +36,10 @@ ts_CRCsize      *       (2 * 4)
 
 ts_ROM_checksum
 
+;StrongARM_POST issue:
+;ARM810 - this will probably go bang! because ARM810 aborts if the processor
+;         vectors (00 - 1C) are read in 26-bit mode
+
          MOV    r1, #&00                    ; initialise accumulator    
          LDR    r0, =PhysROM                ; initialise pointer
          LDR    r2, [r0, #ts_ROMSIZE]       ; initialise endstop
diff --git a/Version b/Version
index 13586c92..fc4ea6b7 100644
--- a/Version
+++ b/Version
@@ -4,8 +4,8 @@
         GBLS    VString
         GBLS    Date
 
-Version SETA    370
-VString SETS    "3.70"
-Date    SETS    "30 Jul 1996"
+Version SETA    371
+VString SETS    "3.71"
+Date    SETS    "19 Feb 1997"
 
         END
diff --git a/s/AMBControl/memmap b/s/AMBControl/memmap
index 7a4067de..95c5ae3d 100644
--- a/s/AMBControl/memmap
+++ b/s/AMBControl/memmap
@@ -235,6 +235,33 @@ AMB_movepagesout_L2PT ROUT
         ARMA_drain_WB EQ         ;because L2PT area for AppSpace will be bufferable
         Pull    "r0-r8,pc"
 
+  [ ARM810support
+    ;Previously supported ARMs all tolerate cache (clean and) flush _after_
+    ;remapping - ARMs 6,7 because there is no clean, StrongARM because the cache
+    ;writebacks use physical address.
+    ;ARM810 does not support clean of writeback cache after remapping, since
+    ;writebacks use virtual address. Rather than completely restructure code,
+    ;this routine is called before remapping where necessary, and cleans/flushes
+    ;if it finds we are running on ARM 810.
+    ;
+    ;corrupts r3
+    ;
+AMB_cachecleanflush_ifARM810
+        ARM_read_ID r3
+        AND     r3,r3,#&F000
+        CMP     r3,#&8000
+        MOVNE   pc,lr           ;not ARM8
+    [ ARM810cleanflushbroken
+        Push    "lr"
+        ARM8_cleanflush_IDC r3,lr
+        Pull    "pc"
+    |
+        ARM8_cleanflush_IDC r3
+        MOV     pc,lr
+    ]
+
+  ] ;ARM810support
+
 ;**************************************************************************
 ; AMB_SetMemMapEntries:
 ;
@@ -285,6 +312,9 @@ AMB_SetMemMapEntries ROUT
 ;could be an optimise here if source is FreePool and we know that FreePool
 ;has not been used - ie. no need to clean/flush cache(s) - not done yet (requires
 ;sorting of Wimp_ClaimFreeMemory)
+  [ ARM810support
+        BL      AMB_cachecleanflush_ifARM810
+  ]
         MOV     r3,r5
         BL      AMB_movepagesout_L2PT
         BL      AMB_movepagesin_L2PT
@@ -293,6 +323,9 @@ AMB_SetMemMapEntries ROUT
 
 ;all pages sourced from same old logical page 'nowhere'
 AMB_smme_mapin
+  [ ARM810support
+        BL      AMB_cachecleanflush_ifARM810
+  ]
         MOV     r3,r5
         BL      AMB_movepagesin_L2PT
         BL      AMB_movepagesin_CAM
@@ -303,14 +336,22 @@ AMB_smme_mapin
 
 ;all pages destined for same new logical page 'nowhere'
 AMB_smme_mapout
+  [ ARM810support
+        BL      AMB_cachecleanflush_ifARM810
+  ]
         LDR     r3,=DuffEntry
         BL      AMB_movepagesout_L2PT
         BL      AMB_movepagesout_CAM
 
-;(clean and) flush cache(s) appropriately
+;(clean and) flush cache(s) appropriately, then flush TLB(s)
 AMB_smme_cachecleanflush
         ARM_read_ID r0
         AND     r0,r0,#&F000
+  [ ARM810support
+        CMP     r0,#&8000      ;cache clean/flush done before remapping if ARM810
+        ARM8_flush_TLB EQ
+        Pull    "r0-r4,r7-r11, pc",EQ
+  ]
         CMP     r0,#&A000
         ARM67_flush_cache NE
         ARM67_flush_TLB NE
@@ -389,11 +430,16 @@ AMB_smme_StrongARM_flushrange
         Pull    "r0-r4,r7-r11, pc"
 
 AMB_smme_TLBflush
+  [ ARM810support
+    ;there is a general macro, should have used this before anyway
+        ARM_flush_TLB r0
+  |
         ARM_read_ID r0
         AND     r0,r0,#&F000
         CMP     r0,#&A000
         ARM67_flush_TLB NE
         ARMA_flush_TLBs EQ
+  ]
 AMB_smme_exit
         Pull    "r0-r4,r7-r11, pc"
 
diff --git a/s/ARM600 b/s/ARM600
index a09307f0..8639cb3c 100644
--- a/s/ARM600
+++ b/s/ARM600
@@ -27,9 +27,9 @@ DebugAborts SETL {FALSE}
 ; Created by TMD 15-Jul-92
 ; Comments updated by TMD 04-Aug-93
 
-;now effectively codes for ARM 6 onwards (6,7,8,A, where A = StrongARM) - MJS, 24-01-96
-
-;but ARM8 not done yet! (29-01-96)
+;24-01-96 MJS  now effectively codes for ARM 6 onwards (6,7,8,A, where A = StrongARM)
+;              but ARM8 not properly supported (not needed for RO 3.70)
+;07-10-96 MJS  proper support for ARM810 added
 
 
 ; Workspace needed for ARM600 work is as follows:
@@ -113,8 +113,13 @@ ARM_default_MMU_CR_table
 ;ARM 7            FRSB1DPWCAM
          DCD  2_0011001111101
 ;
+  [ ARM810bpbroken  ;branch prediction broken!
+;ARM 8           Z0RSB111WCAM
+         DCD  2_0001001111101
+  |
 ;ARM 8           Z0RSB111WCAM
          DCD  2_0101001111101
+  ]
 ;
 ;ARM 9 ??
          DCD  0
@@ -434,18 +439,44 @@ BangL2PT                                        ; internal entry point used only
   |
         TST     r11, #DynAreaFlags_DoublyMapped
         BNE     BangL2PT_sledgehammer           ;if doubly mapped, don't try to be clever
+  ]
+  [ ARM810support
+    ;if we are mapping out a cacheable page on an ARM810, must clean+flush cache _before_
+    ;remapping, since ARM810 relies on virtual addresses for writebacks
+        ARM_read_ID r4
+        AND     r4,r4,#&F000                    ;ARM ID nibble now in r4
+        CMP     r0,#0                           ;EQ if map out
+        TSTEQ   r11,#DynAreaFlags_NotCacheable  ;EQ if also cacheable
+        CMPEQ   r4,#&8000                       ;EQ if also ARM 8
+        BNE     BangL2PT_noARM810flush
+    [ ARM810cleanflushbroken
+        ARM8_cleanflush_IDC r6,r4
+        MOV     r4,#&8000
+    |
+        ARM8_cleanflush_IDC r6
+    ]
+BangL2PT_noARM810flush
   ]
         STR     r0, [r1, r3, LSR #10]           ;update L2PT
+  [ :LNOT: ARM810support
         ARM_read_ID r4
         AND     r4,r4,#&F000                    ;ARM ID nibble in r4
+  ]
         CMP     r0,#0
         BEQ     BangL2PT_mapout                 ;the update is a map out => cache(s) may need clean/flush
 ;else update is a map in (and nothing should be there at the moment) => no cache worries
         CMP     r4,#&A000
         BEQ     BangL2PT_mapin_StrongARM
+  [ ARM810support
+        CMP     r4,#&8000
+        ARM8_flush_TLBentry r3,EQ               ;flush TLB entry for this page, ARM 8
+        ARM67_flush_TLBentry r3,NE              ;flush TLB entry for this page, ARM 6,7
+        MOV     pc,lr
+  |
 ;else assume ARM 6,7
         ARM67_flush_TLBentry r3                 ;flush TLB entry for this page
         MOV     pc,lr
+  ]
 
 BangL2PT_mapin_StrongARM
         ARMA_drain_WB                           ;in case L2PT entry itself is in a bufferable area
@@ -460,6 +491,11 @@ BangL2PT_mapin_StrongARM
 BangL2PT_mapout
         CMP     r4,#&A000
         BEQ     BangL2PT_mapout_StrongARM
+  [ ARM810support
+        CMP     r4,#&8000
+        ARM8_flush_TLBentry r3,EQ                 ;flush TLB entry for this page, ARM 8
+        MOVEQ   pc,lr                             ;ARM8 cache already flushed, if necessary
+  ]
 ;else assume ARM 6,7
         TST     r11,#DynAreaFlags_NotCacheable
         ARM67_flush_cache EQ                    ;flush instruction/data cache if necessary
@@ -516,6 +552,20 @@ BangL2PT_mapout_StrongARM
         MOV     pc,lr
 
 BangL2PT_sledgehammer
+  [ ARM810support
+        ;if necessary, clean+flush _before_ reamapping, since ARM810 writebacks use virtual addresses
+        ARM_read_ID r4
+        AND     r4,r4,#&F000
+        CMP     r4,#&8000
+        TSTEQ   r11,#DynAreaFlags_NotCacheable
+        BNE     BangL2PT_sledge_noARM810flush
+    [ ARM810cleanflushbroken
+        ARM8_cleanflush_IDC r4,r6
+    |
+        ARM8_cleanflush_IDC r4
+    ]
+BangL2PT_sledge_noARM810flush
+  ]
         BICS    r4, r3, #(3 :SHL: 10)   ; ensure going to be on word boundary
  [ {FALSE}      ; this breaks too many things at the moment
         BICEQ   r0, r0, #&30            ; if logical page zero, then make 1st 1K no user access
@@ -535,6 +585,11 @@ BangL2PT_sledgehammer
         AND     r4,r4,#&F000
         CMP     r4,#&A000
         BEQ     BangL2PT_sledgehammer_StrongARM
+  [ ARM810support
+        CMP     r4,#&8000
+        ARM8_flush_TLB EQ
+        MOVEQ   pc, lr      ;ARM8 cache already flushed if necessary
+  ]
 ;else assume ARM 6,7
         TST     r11,#DynAreaFlags_NotCacheable
         ARM67_flush_cache EQ
@@ -664,7 +719,7 @@ ClearPhysRAM ROUT
     [ :LNOT: RunningOnEmul
 
 ;StrongARM - We will make the logical representation of physical space for RAM temporarily bufferable
-;            (on any ARM). This is harmless for ARM 6,7 but a big speed benefit for StrongARM (which
+;            (on any ARM). This is small boost for ARM 6,7,8 but a big speed benefit for StrongARM (which
 ;            won't burst write in non bufferable areas).
 
         LDR     r0,  =L1PT
@@ -675,6 +730,9 @@ ClearPhysRAM ROUT
         SUB     r11,r11,#&100000                        ; 1 Mb will be done on first L1PT update
         ORR     r10, r10, #PhysSpace                    ; point to logical representation of physical space
         ADD     r1,r0,r10,LSR #(20-2)                   ; L1PT address for same
+;MJS bug fix (since 3.70) for memory fragments not necessarily 1Mb aligned (eg 2 Mb Kryten)
+        BIC     r1,r1,#3
+;
 04
         LDR     r2,[r1]
         ORR     r2,r2,#4                                ; bufferable bit
@@ -750,6 +808,9 @@ ClearPhysRAM ROUT
         SUB     r11,r11,#&100000                        ; 1 Mb will be done on first L1PT update
         ORR     r10, r10, #PhysSpace                    ; point to logical representation of physical space
         ADD     r1,r0,r10,LSR #(20-2)                   ; L1PT address for same
+;MJS bug fix (since 3.70) for memory fragments not necessarily 1Mb aligned (eg 2 Mb Kryten)
+        BIC     r1,r1,#3
+;
 34
         LDR     r2,[r1]
         BIC     r2,r2,#4                                ; bufferable bit
@@ -853,16 +914,37 @@ InitMEMC ROUT
         STRB    r12, [r12, #IOMD_DMAREQ]              ; writes to DMAREQ are ignored
 
         LDRB    r0, [r12, #IOMD_ID0]
-        CMP     r0, #&98
+        CMP     r0, #&E7
         LDRB    r0, [r12, #IOMD_ID1]
-        CMPEQ   r0, #&5B
+        CMPEQ   r0, #&D4
        ;MOVEQ   r3, #xxxx
-        BNE     MedusaInit                            ; NOT MORRIS assume Medusa hardware
+        BEQ     MedusaInit                            ; Medusa, else assume Morris
 ;
 ; MORRIS contains IOMD equivalant circuitry. Due to lack of VRAM, presence of 16/32 bit support
 ; and a different ROM speed register, we program it slightly differently.
 ;
 
+  [ RO371Timings
+        ;IOMD_ID1 still in r0 - check for 7500FE
+        CMP     r0, #&aa         ; EQ if 7500FE   => assume 64 MHz bus, EDO RAM
+                                 ; NE assume 7500 => assume 32 MHz bus
+;7500FE
+;set memory to 32MHz for early boot (avoid probs with POST and with power-on key detection)
+        MOVEQ   r0, #&12                 ; 5-3 cycle ROM access, Half speed (ie. 10-6)
+        STREQB  r0, [r12, #IOMD_ROMCR0]
+        STREQB  r0, [r12, #IOMD_ROMCR1]
+        MOVEQ   r0, #&70                 ; EDO RAM selected, 32 bit wide, conservative RAS,CAS timing
+        STREQB  r0, [r12, #IOMD_DRAMWID] ; DRAM control reg. (more than just width on FE)
+        MOVEQ   r0, #&04                 ; clock dividers: /1 for CPU, /2 for memory, /2 for I/O
+        STREQB  r0, [r12, #IOMD_CLKCTL]
+;7500
+        MOVNE   r0, #&32                 ; 5-3 cycle ROM access
+        STRNEB  r0, [r12, #IOMD_ROMCR0]
+        STRNEB  r0, [r12, #IOMD_ROMCR1]
+        MOVNE   r0, #&07                 ; clock dividers: /1 for I/O, /1 for CPU, /1 for memory
+        STRNEB  r0, [r12, #IOMD_CLKCTL]
+
+  | ;else if not RO371Timings
 ;
 ; PSwindell wants all prescalers set to divide by 1
 ;
@@ -892,8 +974,12 @@ InitMEMC ROUT
         ! 0, "*** WARNING *** Slow ROM version ment for PSwindell"
   ]
  ]
+
         STRB    r0, [r12, #IOMD_ROMCR0]
         STRB    r0, [r12, #IOMD_ROMCR1]         ; and do the same for extension ROMs (just in case)
+
+  ] ;RO371Timings conditional
+
 ;
 ; MORRIS doesn't support VRAM. Kryten has same DRAM speed as Medusa
 ;
@@ -916,6 +1002,11 @@ InitMEMC ROUT
 MedusaInit
  ]
 
+
+  [ RO371Timings
+        MOV     r0, #&12    ; 5-3 cycle ROM access
+  |
+
  [ Simulator
         MOV     r0, #IOMD_ROMCR_62 + IOMD_ROMCR_BurstOff        ; make faster for simulation (no point in burst mode, it's
                                                                 ; no faster than the fastest initial speed)
@@ -937,6 +1028,9 @@ MedusaInit
         MOV     r0, #IOMD_ROMCR_156 + IOMD_ROMCR_BurstOff       ; initialise ROM speed to 156.25ns (changed from 187ns 21-Jan-94)
   ]
  ]
+
+  ] ;RO371Timings conditional
+
         STRB    r0, [r12, #IOMD_ROMCR0]
         STRB    r0, [r12, #IOMD_ROMCR1]         ; and do the same for extension ROMs (just in case)
 
@@ -1122,15 +1216,19 @@ MemSize ROUT
  [ MorrisSupport
 ;
         LDRB    r0, [r12, #IOMD_ID0]
-        CMP     r0, #&98
+        CMP     r0, #&E7
         LDRB    r0, [r12, #IOMD_ID1]
-        CMPEQ   r0, #&5B
+        CMPEQ   r0, #&D4
        ;MOVEQ   r3, #xxxx
-        BNE     MemSizeIOMD                             ; NOT MORRIS assume Medusa hardware
+        BEQ     MemSizeIOMD                             ; IOMD (Medusa), else assume Morris
 ;
 ; MemSize for Morris
 ;
+  [ RO371Timings
+        MOV     r11, #&70     ;all 4 banks assumed 32 bit - EDO and timing bits set in case 7500FE (don't care bits otherwise)
+  |
         MOV     r11, #IOMD_DRAMWID_DRAM_32bit * &0F     ;set all 4 banks to be 32bit initially
+  ]
         MOV     r14, #IOMD_Base
         STRB    r11, [r14, #IOMD_DRAMWID]
  [ 1 = 0
@@ -1414,8 +1512,23 @@ MemSizeIOMD
         ORR     r2,r2,#&1000     ;I cache bit is bit 12
         ARM_write_control r2
         ARMA_fastcoreclock
-
+  [ ARM810fastclock
+        B       MemSizeIOMD_not810
+  ]
 MemSizeIOMD_notSA
+  [ ARM810fastclock
+    ;fast clock for ARM 810 now
+        ARM_read_ID r2
+        AND     r2,r2,#&F000
+        CMP     r2,#&8000
+        BNE     MemSizeIOMD_not810
+    [ ARM810usePLL
+        ARM8_pll_fclk r2
+    |
+        ARM8_refclk_fclk r2
+    ]
+MemSizeIOMD_not810
+  ]
         MOV     r2, #IOMD_VREFCR_VRAM_256Kx64 :OR: IOMD_VREFCR_REF_16 ; assume 2 banks of VRAM by default
         STRB    r2, [r12, #IOMD_VREFCR]
 
@@ -1862,8 +1975,12 @@ MemSizeDone
         ARM_flush_cacheandTLB r7                ; flush cache + TLB just in case
 
         ARM_number r2                           ;should be 6,7,8 or &A
+ [ ARM810support
+   ;ARM810 has already had fast clock selected (MemSizeIOMD) - so has StrongARM, therefore code below removed
+ |
         CMP     r2,#&A
         ARMA_fastcoreclock EQ                   ;otherwise StrongARM is going to have a limp wrist
+ ]
         SUB     r2,r2,#6                        ; r2 := 0..4 for ARM 6,7,8,(9),&A
         ADRL    r7,ARM_default_MMU_CR_table
         LDR     r7,[r7,r2,LSL #2]               ;get appropriate default value for MMU control reg
@@ -2100,15 +2217,78 @@ Page8K  * &4
 Page4K  * &0
 
 ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-; In    r0=0 -> Coming from the Test routine, just go back!
+; In    r0=0 -> Coming from the Test routine - no fancy business!
 ;       r1-r6 trashable
-;       r9 = Current MEMC CR (true MEMC value, not fudged to look like 4K page size)
+;       [[[ r9 = Current MEMC CR (true MEMC value, not fudged to look like 4K page size) ]]]
 
-; Out   r9 MEMC value with slowest ROM speed, correct pagesize
+; Out   [[[ r9 MEMC value with slowest ROM speed, correct pagesize ]]]
 ;       r7 processor speed in kHz, bit 16 => can do STM to I/O (ie MEMC1a, MEMC2), bit 17 => MEMC2
 
 ; This routine must work in 32-bit mode, and should not use any memory!!!!
 
+  [ RO371Timings
+
+TimeCPU ROUT         ;does not actually measure anything - assumes timings (and EDO for 7500FE) according to IOMD id
+
+        MOV     r2, #IOC                ; Address of the IO controller  (IOMD)
+
+        LDRB    r7, [r2, #IOMD_ID0]     ; Is
+        CMP     r7, #&E7                ; It
+        LDRB    r7, [r2, #IOMD_ID1]     ; A
+        CMPEQ   r7, #&D4                ; Risc PC ?
+        BEQ     timecpuriscpc
+        CMP     r7, #&AA                ; assume 7500 or 7500FE
+        BEQ     timecpu7500FE
+;7500 then
+        MOV     r7, #&32                      ; 5-3 cycle ROM access
+        STRB    r7, [r2, #IOMD_ROMCR0]
+        STRB    r7, [r2, #IOMD_ROMCR1]
+        MOV     r7, #&07                      ; clock dividers: /1 for I/O, /1 for CPU, /1 for memory
+        STRB    r7, [r2, #IOMD_CLKCTL]
+        LDR     r7, =(1 :SHL: 16) :OR: 16000  ; assumed 16MHz RAM (32 MHz bus)
+        MOV     pc, lr
+
+timecpu7500FE
+;set memory to 32MHz for early boot (avoid probs with POST and with power-on key detection)
+        MOV     r7, #&12                      ; 5-3 cycle ROM access, half speed (ie. 10-6)
+        STRB    r7, [r2, #IOMD_ROMCR0]
+        STRB    r7, [r2, #IOMD_ROMCR1]
+        MOV     r7, #&70                      ; EDO RAM, 32 bit wide, conservative RAS and CAS timing
+        STRB    r7, [r2, #IOMD_DRAMWID]       ; DRAM control reg. (more than just width on FE)
+        MOV     r7, #&04                      ; clock dividers: /1 for CPU, /2 for memory, /2 for I/O
+        STRB    r7, [r2, #IOMD_CLKCTL]
+        LDR     r7, =(1 :SHL: 16) :OR: 32000  ; assumed 32MHz RAM (64 MHz bus), even though /2 at the moment
+        MOV     pc, lr
+
+timecpuriscpc
+        MOV     r7, #&12                      ; 5-3 cycle ROM access
+        STR     r7, [r2, #IOMD_ROMCR0]
+        STR     r7, [r2, #IOMD_ROMCR1]
+        LDR     r7, =(1 :SHL: 16) :OR: 16000  ; assumed 16MHz RAM (32 MHz bus)
+        MOV     pc, lr
+
+;used by NewReset, after main kernel boot
+;sets full 64MHz memory if on 7500FE
+;preserves registers _and_ flags
+;
+finalmemoryspeed ROUT
+        Push    "r0,lr"
+        MOV     lr, #IOC
+        LDRB    r0, [lr, #IOMD_ID0]     ; Is
+        CMP     r0, #&E7                ; It
+        LDRB    r0, [lr, #IOMD_ID1]     ; A
+        CMPEQ   r0, #&D4                ; Risc PC ?
+        BEQ     fmspeed_done
+        CMP     r0, #&AA                ; EQ if 7500FE
+        MOVEQ   r0, #&80
+        STREQB  r0, [lr, #&CC]          ; ASTCR register: set i/o asynchronous timing for fast memory clock
+        MOVEQ   r0, #&06                ; clock dividers: /1 for CPU, /1 for memory, /2 for I/O
+        STREQB  r0, [lr, #IOMD_CLKCTL]
+fmspeed_done
+        Pull    "r0,pc",,^
+
+  | ; else if not RO371Timings
+
 ncpuloops * 1024 ; don't go longer than 4ms without refresh !
 nmulloops * 128
 
@@ -2119,14 +2299,18 @@ TimeCPU ROUT            ;ONLY WORKS FOR IOMD(L) machines - this shouldn't be a p
 
    [ {TRUE}
 ;don't do timing for Risc PC
-        LDRB    r0, [r3, #IOMD_ID0]     ; Is
-        CMP     r0, #&98                ; It
-        LDRB    r0, [r3, #IOMD_ID1]     ; A
-        CMPEQ   r0, #&5B                ; Morris?
-        MOVNE   r7,#&3e00               ;for non-Morris force 16MHz timing, assumed Risc PC
-        ORRNE   r7,r7,#&80
-        ORRNE   r7,r7,#&10000           ;and note we're on IOMD
-        MOVNE   pc,lr
+;
+;MJS bug fix (since 3.70) - setup r3 properly, and don't corrupt r0 you fool
+;
+        MOV     r3, #IOC                ; Address of the IO controller
+        LDRB    r7, [r3, #IOMD_ID0]     ; Is
+        CMP     r7, #&E7                ; It
+        LDRB    r7, [r3, #IOMD_ID1]     ; A
+        CMPEQ   r7, #&D4                ; Medusa?
+        MOVEQ   r7,#&3e00               ;for non-Morris force 16MHz timing, assumed Risc PC
+        ORREQ   r7,r7,#&80
+        ORREQ   r7,r7,#&10000           ;and note we're on IOMD
+        MOVEQ   pc,lr
   ]
 
 ; Time CPU/Memory speed
@@ -2197,12 +2381,12 @@ TimeCPU ROUT            ;ONLY WORKS FOR IOMD(L) machines - this shouldn't be a p
 
  [ MorrisSupport
         LDRB    r0, [r3, #IOMD_ID0]     ; Is
-        CMP     r0, #&98                ; It
+        CMP     r0, #&E7                ; It
         LDRB    r0, [r3, #IOMD_ID1]     ; A
-        CMPEQ   r0, #&5B                ; Morris?
-        LDREQ   r0, =(4*15*500*ncpuloops)               ;Morris timing values [reordered to prevent miscalculation
+        CMPEQ   r0, #&D4                ; Medusa?
+        LDRNE   r0, =(4*15*500*ncpuloops)               ;Morris timing values [reordered to prevent miscalculation
                                                         ;due to Aasm integering mid-calculation] (30720000)
-        LDRNE   r0, =(4*(8*500/1000)*ncpuloops*1000)    ;RiscPC/IOMD timing values      (16384000)
+        LDREQ   r0, =(4*(8*500/1000)*ncpuloops*1000)    ;RiscPC/IOMD timing values      (16384000)
         DivRem  r7, r0, r2, r1          ; r2 preserved,   R7=memory speed in kHz (MEMCLK/2)
  |
         LDR     r0, =(4*(8*500/1000)*ncpuloops*1000)    ;RiscPC/IOMD timing values      (16384000)
@@ -2257,6 +2441,8 @@ TimeCPU ROUT            ;ONLY WORKS FOR IOMD(L) machines - this shouldn't be a p
 timecpu_sodthefancytimingstuff
         MOV     pc, lr
 
+  ] ;RO371Timings conditional
+
 MemClkTable
         DCB     2_100101                ; 0 cycles (set to min which is 2)
         DCB     2_100101                ; 1 cycle (set to min. which is 2)
@@ -2346,22 +2532,39 @@ MMUControl_ModifyControl ROUT
         MOV     r3, #0
         LDR     lr, [r3, #MMUControlSoftCopy]
         CMP     r5,#&A
+  [ ARM810support
+        CMPNE   r5,#8                   ; can read control reg on ARM 810 too
+  ]
         ARM_read_control lr,EQ
         MOVEQ   lr,lr,LSL #19
         MOVEQ   lr,lr,LSR #19           ; if StrongARM then we can read control reg. - trust this more than soft copy
         AND     r2, r2, lr
         EOR     r2, r2, r1
         MOV     r1, lr
+  [ ARM810support
+        CMP     r5,#8
+        BNE     %FT03
+        TST     r2,#4
+        ORRNE   r2,r2,#&800            ; if ARM810 then Z bit (branch prediction) mirrors C bit
+        BICEQ   r2,r2,#&800
+03
+  ]
         CMP     r5,#&A
         BNE     %FT05
         TST     r2,#&4                  ; if StrongARM, then I bit mirrors C bit
         ORRNE   r2,r2,#&1000
         BICEQ   r2,r2,#&1000
 05
+   [ SAWBbroken :LOR: ARM810bpbroken
+        MOV     lr,r2
    [ SAWBbroken
         CMP     r5,#&A
-        BICEQ   lr,r2,#&0008                   ;sorry guys, we can't use write buffer (safe-ish - safer would zap data cache bit as well)
-        MOVNE   lr,r2
+        BICEQ   lr,lr,#&0008                   ;sorry guys, we can't use write buffer (safe-ish - safer would zap data cache bit as well)
+     ]
+     [ ARM810bpbroken
+        CMP     r5, #8
+        BICEQ   lr,lr,#&0800                   ;sorry guys (or sorry Guy!), we can't use branch predictor
+     ]
         STR     lr, [r3, #MMUControlSoftCopy]
    |
         STR     r2, [r3, #MMUControlSoftCopy]
@@ -2371,6 +2574,25 @@ MMUControl_ModifyControl ROUT
         BEQ     %FT10
         ARM_flush_cache r3
 10
+  [ ARM810support
+        CMP     r5,#8
+        BNE     %FT12
+        BIC     lr, r1, r2              ; lr = bits going from 1->0
+        TST     lr, #MMUC_C             ; if cache turning off then clean/flush cache first
+        BEQ     %FT12
+    [ ARM810cleanflushbroken
+        Push    "r0,r1"
+        ARM8_cleanflush_IDC r0,r1
+        ARM8_branchpredict_off r0       ; and turn off branch predict cleanly (must go off with cache)
+        Pull    "r0,r1"
+    |
+        Push    "r0"
+        ARM8_cleanflush_IDC r0
+        ARM8_branchpredict_off r0       ; and turn off branch predict cleanly (must go off with cache)
+        Pull    "r0"
+    ]
+12
+  ]
         CMP     r5,#&A
         BNE     %FT15
         BIC     lr, r1, r2              ; lr = bits going from 1->0
@@ -2384,10 +2606,16 @@ MMUControl_ModifyControl ROUT
         ARMA_clean_DC r0,r1,r2
         Pull    "r0-r2"
 15
+   [ SAWBbroken :LOR: ARM810bpbroken
+        MOV     lr,r2
    [ SAWBbroken
         CMP     r5,#&A
-        BICEQ   lr,r2,#&0008            ;sorry guys, we can't use write buffer
-        MOVNE   lr,r2
+        BICEQ   lr,lr,#&0008            ;sorry guys, we can't use write buffer
+     ]
+     [ ARM810bpbroken
+        CMP     r5,#8
+        BICEQ   lr,lr,#&0800            ;sorry guys, we can't use branch predictor
+     ]
         ARM_write_control lr
    |
         ARM_write_control r2
@@ -2405,6 +2633,9 @@ MMUC_modcon_readonly
         MOV     r3, #0
         LDR     lr, [r3, #MMUControlSoftCopy]
         CMP     r5,#&A
+  [ ARM810support
+        CMPNE   r5,#8                   ; can read control reg on ARM 810 too
+  ]
         ARM_read_control lr,EQ
         MOVEQ   lr,lr,LSL #19
         MOVEQ   lr,lr,LSR #19           ; if StrongARM then we can read control reg. - trust this more than soft copy
@@ -2421,8 +2652,24 @@ MMUControl_Flush
        BEQ      MMUC_flush_flushT
 ;flush cache
        CMP      r4,#&A000
-       ARM67_flush_cache NE       ;if not StrongARM, assume 6,7
+  [ ARM810support
+       CMPNE    r4,#&8000
+  ]
+       ARM67_flush_cache NE       ;if not StrongARM or ARM810, assume 6,7
        BNE      MMUC_flush_flushT
+  [ ARM810support
+       CMP      r4,#&A000
+       BEQ      MMUC_flush_SA
+;ARM810 then
+    [ ARM810cleanflushbroken
+       ARM8_cleanflush_IDC r1,r4
+       MOV      r4,#&8000
+    |
+       ARM8_cleanflush_IDC r1
+    ]
+       B        MMUC_flush_flushT
+MMUC_flush_SA
+  ]
 ;StrongARM then
        MOV     r2,#ARMA_Cleaner_flipflop
        LDR     r1,[r2]
@@ -2434,9 +2681,14 @@ MMUControl_Flush
 MMUC_flush_flushT
        TST     r0,#&40000000
        BEQ     MMUC_flush_done
+  [ ARM810support
+    ;there is a general macro, should have used this before anyway
+       ARM_flush_TLB r1
+  |
        CMP     r4,#&A000
        ARMA_flush_TLBs EQ
        ARM67_flush_TLB NE         ;if not StrongARM, assume 6,7
+  ]
 MMUC_flush_done
        Pull     "r0-r4,pc"
 
@@ -2544,7 +2796,13 @@ DAbPreVeneer    ROUT
         BIC     r1, r1, #&1F                    ; knock out current mode bits
         ANDS    r3, r0, #&1F                    ; extract old mode bits (and test for USR26_mode (=0))
         TEQNE   r3, #USR32_mode                 ; if usr26 or usr32 then use ^ to store registers
+  [ SASTMhatbroken
+        STMEQIA r2!,{r8-r12}
+        STMEQIA r2 ,{r13,r14}^
+        SUBEQ   r2, r2, #5*4
+  |
         STMEQIA r2, {r8-r14}^
+  ]
         BEQ     %FT05
 
         ORR     r3, r3, r1                      ; and put in user's
@@ -2561,7 +2819,15 @@ DAbPreVeneer    ROUT
 
         Push    "r0, lr_svc"                    ; save SPSR_abort and lr_svc
         SUB     sp_svc, sp_svc, #8*4            ; make room for r8_usr to r14_usr and PC
+  [ SASTMhatbroken
+        STMIA   sp_svc!,{r8-r12}
+        STMIA   sp_svc, {r13,r14}^
+        NOP
+        STR     pc, [sp_svc,#2*4]
+        SUB     sp_svc, sp_svc, #5*4            ; save USR bank in case STM ^, and also so we can corrupt them
+  |
         STMIA   sp_svc, {r8-r15}^               ; save USR bank in case STM ^, and also so we can corrupt them
+  ]
 
         SUB     r11, r2, #8*4                   ; r11 -> register bank
         STR     r4, [sp_svc, #7*4]              ; store aborter's PC in user register bank
@@ -2914,9 +3180,6 @@ DAbPreVeneer    ROUT
         ADD     r2, r11, #8*4                   ; point r2 at 2nd half of main register bank
         LDMIA   sp, {r8-r14}^                   ; reload user bank registers
         NOP                                     ; don't access banked registers after LDM^
-   [ SAUBxferbroken
-        NOP                                     ; 'fraid so
-   ]
         ADD     sp, sp, #8*4                    ; junk user bank stack frame
 
         Pull    "r0, lr"                        ; r0 = (possibly updated) SPSR_abort, restore lr_svc
@@ -2929,9 +3192,6 @@ DAbPreVeneer    ROUT
         TEQNE   r7, #USR32_mode                 ; test also for USR32
         LDMEQIA r2, {r8-r14}^                   ; if user mode then just use ^ to reload registers
         NOP
-   [ SAUBxferbroken
-        NOP                                     ; 'fraid so
-   ]
         BEQ     %FT80
 
         ORR     r6, r6, #I32_bit                ; use aborter's flags and mode but set I
@@ -3075,6 +3335,7 @@ ProcessTransfer ENTRY "r1-r7,r12"
 20
 ;ARM 8 and StrongARM will abort for vector reads (as well as writes) in 26bit mode, so we must
 ;handle vector reads properly as well now
+;In fact, StrongARM does not abort (optional in architecture 4), but ARM 8 does - MJS 08-10-96
   [ {FALSE}
         TST     r0, #1                                  ; if load from memory
         BNE     %FT60                                   ; then skip
@@ -3502,12 +3763,18 @@ dtgps_SAloop1
     ARMA_drain_WB           ; squeeze out those last drops
     MOV     pc,lr
 
+;ARM810 equiv of dtgps_SAcleanflush must clean/flush whole cache (cannot clean/flush by virtual address)
+;and is shared with code in meminfo_flushplease, below
 
 meminfo_flushplease         ; used by MemInfo
         ARM_read_ID r0
         AND     r0,r0,#&F000
         CMP     r0,#&A000
         BEQ     mifp_SA
+  [ ARM810support
+        CMP     r0,#&8000
+        BEQ     mifp_810
+  ]
 ;assume ARM 6 or 7 - simple!
         ARM67_flush_cache
         MOV     pc,lr
@@ -3520,7 +3787,16 @@ mifp_SA
         ARMA_clean_DC r0,r1,r2          ;clean/flush data cache wrt non-interrupt stuff (trashes r0,r1,r2)
         ARMA_flush_IC                   ;do *not* flush DC - may be interrupt stuff
         MOV     pc,lr
-
+  [ ARM810support
+mifp_810
+dtgps_810cleanflush                     ;entry point also used during pages_unsafe/safe in ChangeDyn
+    [ ARM810cleanflushbroken
+        ARM8_cleanflush_IDC r0,r1
+    |
+        ARM8_cleanflush_IDC r0
+    ]
+        MOV     pc,lr
+  ]
 ;
 
         DCB     "GROT"                  ;spare words marker
diff --git a/s/ChangeDyn b/s/ChangeDyn
index 12c7e22d..9efb8fa3 100644
--- a/s/ChangeDyn
+++ b/s/ChangeDyn
@@ -3283,6 +3283,15 @@ DoTheGrowPagesSpecified
     BLEQ    dtgps_SAcleanflush
   ]
 
+  [ ARM810support
+    ;
+    ; ARM810 has writeback cache too
+    ;
+    ARM_number r0
+    CMP     r0,#8
+    BLEQ    dtgps_810cleanflush
+  ]
+
 ; now move the pages
 
         LDR     r2, TotalAmount                 ; amount moving
diff --git a/s/Copro15ops b/s/Copro15ops
index 3a3428dc..e76fce00 100644
--- a/s/Copro15ops
+++ b/s/Copro15ops
@@ -18,7 +18,8 @@
 ;and cater for ARM 6,7,8,A (A=StrongARM).
 ;Routines detect which ARM directly by reading ARM ID register (avoids memory reads).
 
-; Created by MJS, 24-01-96
+; 24-01-96 MJS Created
+; 07-10-96 MJS Updated for proper ARM 810 support (not needed for RO 3.70)
 
 ARM_config_cp        CP 15  ;coprocessor number for configuration control
 
@@ -37,6 +38,8 @@ ARM8A_TLB_reg        CN  8  ;TLB operations, ARMs 8 or StrongARM
 ARM8_cacheLD_reg     CN  9  ;cache lock-down, ARM 8
 ARM8_TLBLD_reg       CN 10  ;TLB lock-down, ARM 8
 
+ARM8_CTC_reg         CN 15  ;Clock and test configuration
+
 ARMA_TCI_reg         CN 15  ;Test,Clock and Idle control
 
 ;so that AASM will accept the general value for MCR CRm field
@@ -165,9 +168,174 @@ C15 CN 15
         MEND
 
 ;
-; -------------- ARM 8 only ----------------------------------------------
+; -------------- ARM 810 only ----------------------------------------------
+;
+
+ [ ARM810support
+
+;turn off branch prediction
+; - the forced mispredicted branch ensures that the predictor is trapped in
+;   this code segment when turned off
+; - corrupts $temp and status flags
+;
+        MACRO
+        ARM8_branchpredict_off $temp
+01
+        ARM_read_control $temp
+        BIC $temp,$temp,#&800        ;z bit (branch prediction)
+        ARM_write_control $temp
+        SEC                          ;set carry flag
+        BCC %BT01
+        MEND
+
+;turn on branch prediction
+        MACRO
+        ARM8_branchpredict_on $temp
+        ARM_read_control $temp
+        ORR $temp,$temp,#&800        ;z bit (branch prediction)
+        ARM_write_control $temp
+        MEND
+
+;flush branch prediction, which is sufficient for an IMB (instruction memory
+;barrier) on ARM 810, BUT...
+; - intended for in line use only, where efficiency matters, or SWI call is
+;   awkward
+; - general code should use SWI OS_SynchroniseCodeAreas to implement
+;   an IMB (instruction memory barrier) in future proof, ARM independent way
+; - kernel code may use this without regard to which ARM running - ie. assumed
+;   harmless on other ARMs
+;
+        MACRO
+        ARM8_branchpredict_flush
+        SUB PC,PC,#4        ;flush, because PC is written by data op
+        MEND
+
+;clean cache entry
+; - segment,index spec in $reg
+; - bits 4..6   = segment (0..7)
+; - bits 26..31 = index   (0..63)
+; - all other bits zero
+        MACRO
+        ARM8_clean_IDCentry $reg,$cond
+        MCR$cond ARM_config_cp,0,$reg,ARM8A_cache_reg,C11,1
+        MEND
+
+;flush cache entry -  segment,index spec in $reg, as for ARM8_clean_IDCentry
+        MACRO
+        ARM8_flush_IDCentry $reg,$cond
+        MCR$cond ARM_config_cp,0,$reg,ARM8A_cache_reg,C7,1
+        MEND
+
+;clean and flush cache entry -  segment,index spec in $reg, as for ARM8_clean_IDCentry
+;
+;if ARM810cleanflushbroken is TRUE, interrupts *must* be currently diabled (see below)
+;
+        MACRO
+        ARM8_cleanflush_IDCentry $reg,$cond
+  [ ARM810cleanflushbroken
+        ARM8_clean_IDCentry $reg,$cond
+        ARM8_flush_IDCentry $reg,$cond
+  |
+        MCR$cond ARM_config_cp,0,$reg,ARM8A_cache_reg,C15,1
+  ]
+        MEND
+
+;fully clean and flush cache (assumes no locked-down entries to preserve)
+;
+;if ARM810cleanflushbroken is TRUE, then we have to make sure interrupts are disabled during
+;the sequence of 2 MCRs that make up ARM8_cleanflush_IDCentry, to avoid an interrupt hole.
+;The hole occurs if an interrupt fills and dirties the particular cache entry after the clean
+;but before the flush. We don't have this problem with StrongARM, because the entry is
+;specified by virtual address, and RISC OS only cleans/flushes address space not currently
+;involved in interrupts.
 ;
+  [ ARM810cleanflushbroken
+
+        MACRO
+        ARM8_cleanflush_IDC $temp,$temp2
+        ;for simplicity, disable interrupts during entire operation - 26-bit assumed
+        MOV  $temp2,pc
+        AND  $temp2,$temp2,#I_bit
+        EOR  $temp2,$temp2,#I_bit                ;temp := <current I> EOR <I set>
+        TEQP $temp2,pc                           ;disable I
+        MOV  $temp,#0                            ;initial segment and index
+01
+        ARM8_cleanflush_IDCentry $temp
+        ADD $temp,$temp,#1 :SHL: 26              ;next index
+        CMP $temp,#1 :SHL: 26                    ;last index done if index field wrapped to 0
+        BHS %BT01
+        ADD $temp,$temp,#1 :SHL: 4               ;next segment
+        CMP $temp,#8 :SHL: 4                     ;8 segments done?
+        BLO %BT01
+        TEQP $temp2,pc                           ;restore I
+        MEND
+
+  |
+
+        MACRO
+        ARM8_cleanflush_IDC $temp
+        MOV $temp,#0                             ;initial segment and index
+01
+        ARM8_cleanflush_IDCentry $temp
+        ADD $temp,$temp,#1 :SHL: 26              ;next index
+        CMP $temp,#1 :SHL: 26                    ;last index done if index field wrapped to 0
+        BHS %BT01
+        ADD $temp,$temp,#1 :SHL: 4               ;next segment
+        CMP $temp,#8 :SHL: 4                     ;8 segments done?
+        BLO %BT01
+        MEND
+
+  ]
+
+;flush whole TLB (actually, same as ARMA_flush_TLBs)
+        MACRO
+        ARM8_flush_TLB $cond
+        MCR$cond ARM_config_cp,0,R0,ARM8A_TLB_reg,C7,0
+        MEND
+
+;flush TLB entry, virtual address in $reg
+        MACRO
+        ARM8_flush_TLBentry $reg,$cond
+        MCR$cond ARM_config_cp,0,$reg,ARM8A_TLB_reg,C7,1
+        MEND
+
+;select external Refclk pin as fast clock (dynamic switching, asynchronous)
+        MACRO
+        ARM8_refclk_fclk $temp
+        MRC ARM_config_cp,0,$temp,ARM8_CTC_reg,C0,0
+        BIC $temp, $temp,#&1                        ;turn off dynamic bus switching (bit0)
+        MCR ARM_config_cp,0,$temp,ARM8_CTC_reg,C0,0
+        BIC $temp,$temp,#&2                         ;select asynchronous mode (default) (bit1)
+        ORR $temp,$temp,#&4                         ;select REFCLK as the FCLK source (bits3:2)
+        BIC $temp,$temp,#&10                        ;ensure L=0 when writing (PLL locked) (bit4)
+        MCR ARM_config_cp,0,$temp,ARM8_CTC_reg,C0,0
+        NOP
+        NOP
+        NOP
+        NOP
+        ORR $temp,$temp,#&1                         ;select dynamic clock switching (bit0)
+        MCR ARM_config_cp,0,$temp,ARM8_CTC_reg,C0,0
+        MEND
+
+;select PLL output as fast clock (dynamic switching, asynchronous)
+        MACRO
+        ARM8_pll_fclk $temp
+        MRC ARM_config_cp,0,$temp,ARM8_CTC_reg,C0,0
+        BIC $temp,$temp,#&1                         ;turn off dynamic bus switching (bit0)
+        MCR ARM_config_cp,0,$temp,ARM8_CTC_reg,C0,0
+        BIC $temp,$temp,#&2                         ;select asynchronous mode (default) (bit1)
+        ORR $temp,$temp,#&C                         ;select PLLClkOut as the FCLK source (bits3:2)
+        BIC $temp,$temp,#&10                        ;ensure L=0 when writing (PLL locked) (bit4)
+        MCR ARM_config_cp,0,$temp,ARM8_CTC_reg,C0,0
+        NOP
+        NOP
+        NOP
+        NOP
+        ORR $temp,$temp,#&1                         ;select dynamic clock switching (bit0)
+        MCR ARM_config_cp,0,$temp,ARM8_CTC_reg,C0,0
+        MEND
 
+ ] ;ARM810support
 
 ;
 ; -------------- StrongARM only ------------------------------------------
diff --git a/s/GetAll b/s/GetAll
index 2c8e73ba..cdd7464e 100644
--- a/s/GetAll
+++ b/s/GetAll
@@ -190,12 +190,22 @@ IncludeTestSrc  SETL    :LNOT: (MEMM_Type = "MEMC2") ; not on internal test vers
 IncludeTestSrc  SETL    {FALSE}
  ]
 
+;RISC OS 3.71 onwards assumed bus timings - if true, then ROM speeds atc are assumed according to IOMD ID regs. as follows:
+;     if IOMD (Risc PC)     ROM ticks 5-3 (assumed bus 32 MHz)
+;     if 7500 (A7000)       ROM ticks 5-3 (assumed bus 32 MHz), all clocks divide-by-1
+;     if 7500FE (A7000+)    ROM ticks 5-3,half speed (asssumed bus 64 MHz), EDO memory, divide-by-2 I/O, divide-by-1 CPU and memory
+;
+                GBLL    RO371Timings
+RO371Timings    SETL    {TRUE}
+
+
+  [ :LNOT: RO371Timings
 
                 GBLL    NormalSpeedROMS
 NormalSpeedROMS SETL    {FALSE}          ;use FALSE for slow EPROMS
 
                 GBLL    AutoSpeedROMS
-AutoSpeedROMS   SETL    {TRUE}
+AutoSpeedROMS   SETL    {TRUE}           ;WARNING: may not be reliable if true
 
                 GBLL    RISCPCBurstMode
 RISCPCBurstMode SETL    {FALSE}
@@ -203,6 +213,8 @@ RISCPCBurstMode SETL    {FALSE}
 ;>>>RISC PC (no reason why it shouldn't) all references to RISCPCBurstMode
 ;>>>could be replaced by NormalSpeedROMS
 
+  ]
+
                 GBLL    Select16BitSound
 Select16BitSound SETL   {TRUE}
 
@@ -276,18 +288,38 @@ IgnoreVRAM      SETL    {FALSE}
 LateAborts      SETL    MEMM_Type = "ARM600" :LAND: {TRUE}
 
 
-
                 GBLL    StrongARM
                 GBLL    SAWBbroken              ;whether StrongARM Write Buffer is broken (pass 1 silicon only)
                 GBLL    SAcleanflushbroken      ;whether StrongARM single MCR for DC clean+flush broken (is always for SA110)
-                GBLL    SAUBxferbroken          ;whether extra NOPs required for user bank STM/LDM (is so far)
+                GBLL    SASTMhatbroken          ;whether ROM must support SA110's with broken STM^ (revision 3 should fix this)
+                GBLL    StrongARM_POST          ;whether to run POST for StrongARM (and possibly ARM8)
+
+                GBLL    ARM810support           ;StrongARM must also be true for this to be useful
+                GBLL    ARM810bpbroken          ;whether branch predict is broken
+                GBLL    ARM810cleanflushbroken  ;whether single MCR for IDC clean+flush broken (a la StrongARM!)
+                GBLL    ARM810fastclock         ;whether to attempt to use fast clock (false means bus clock)
+                GBLL    ARM810usePLL            ;whether to use PLL for fast clock (else RefClk pin)
+                GBLL    ARM810_POST             ;whether to run POST for ARM810 (StrongARM_POST must also be true)
 
 StrongARM          SETL {TRUE}
 SAWBbroken         SETL {FALSE} :LAND: StrongARM
 SAcleanflushbroken SETL {TRUE}  :LAND: StrongARM
-SAUBxferbroken     SETL {TRUE}  :LAND: StrongARM
+SASTMhatbroken         SETL {TRUE}  :LAND: StrongARM
+StrongARM_POST         SETL {TRUE}  :LAND: StrongARM
+
+ARM810support          SETL {FALSE} :LAND: StrongARM
+ARM810bpbroken         SETL {TRUE}  :LAND: ARM810support
+ARM810cleanflushbroken SETL {TRUE}  :LAND: ARM810support
+ARM810fastclock        SETL {FALSE} :LAND: ARM810support
+ARM810usePLL           SETL {TRUE}  :LAND: ARM810fastclock
+ARM810_POST            SETL {FALSE} :LAND: ARM810support
+
+                GBLL    VCOstartfix              ;code in early kernel to fix VCO start problem on A7000 (esp. 7500FE)
+VCOstartfix     SETL    {TRUE}
 
 
+                GBLL    MorrisIDString           ;whether printed CPU string includes 7500/7500FE recognition
+MorrisIDString  SETL    {TRUE} :LAND: StrongARM  ;printed CPU type only implemented if StrongARM true
 
                 GBLL    CheckProtectionLink     ; if true, disallow CMOS RAM changes if link in protected position
 CheckProtectionLink SETL (IO_Type = "IOMD") :LAND: {TRUE}       ; NB affects Delete/Copy/R/T and 0-9/.
diff --git a/s/KbdResPC b/s/KbdResPC
index e3e56852..8bfc394c 100644
--- a/s/KbdResPC
+++ b/s/KbdResPC
@@ -74,11 +74,11 @@ SetUpKbd
         MOV     r0, #IOBase
 
  [ MorrisSupport
-        LDRB    R1, [R0, #IOMD_ID0]             ;Are we running on Morris
-        CMP     R1, #&98
+        LDRB    R1, [R0, #IOMD_ID0]             ;Are we running on Medusa
+        CMP     R1, #&E7
         LDRB    R1, [R0, #IOMD_ID1]
-        CMPEQ   R1, #&5B
-        BNE     %FT30                           ;NE: no, assume IOMD, so only one PS2 port
+        CMPEQ   R1, #&D4
+        BEQ     %FT30                           ;EQ: yes, it is IOMD, so only one PS2 port
 
   [ 1 = 1
 ;
@@ -178,10 +178,10 @@ SetUpKbd
 
  [ MorrisSupport
         LDRB    R1, [R0, #IOMD_ID0]             ;Are we running on Morris
-        CMP     R1, #&98
+        CMP     R1, #&E7
         LDRB    R1, [R0, #IOMD_ID1]
-        CMPEQ   R1, #&5B
-        BNE     %FT30                           ;NE: no, assume IOMD, so only one PS2 port
+        CMPEQ   R1, #&D4
+        BEQ     %FT30                           ;EQ: yes, it is IOMD, so only one PS2 port
 
         MOV     R1, #IOMD_MSECR_Enable          ;yes, so initialise 2nd PS2 (mouse) port cos
         STRB    R1, [R0, #IOMD_MSECR]           ;keyboard may be connected there instead
diff --git a/s/Kernel b/s/Kernel
index 473515ff..153b7b65 100644
--- a/s/Kernel
+++ b/s/Kernel
@@ -812,7 +812,14 @@ Do_CallBack                                    ; CallBack allowed:
         STR     r14, [r12, #4*15]             ; user PC
         MOV     r14, r12
         Pull   "r10-r12"
+  [ SASTMhatbroken
+        STMIA   r14!,{r0-r12}
+        STMIA   r14,{r13,r14}^                ; user registers
+        NOP
+        SUB     r14,r14,#13*4
+  |
         STMIA   r14, {r0-r14}^                ; user registers
+  ]
 
         MOV     R12, #CallAd_ws
         LDMIA   R12, {R12, PC}                ; jump to CallBackHandler
diff --git a/s/Middle b/s/Middle
index 1a043b56..708489e8 100644
--- a/s/Middle
+++ b/s/Middle
@@ -247,15 +247,14 @@ SBRKPT ROUT
         MOV     r0, r12
         LDMFD   sp, {r10-r12}
 
-    [ SAUBxferbroken
-        NOP
-        NOP
-    ]
+  [ SASTMhatbroken
+        STMIA   r0!,{r1-r12}
+        STMIA   r0, {r13_usr,r14_usr}^ ; user mode case done.
+        SUB     r0, r0, #12*4
+  |
         STMIA   r0, {r1-r12, r13_usr, r14_usr}^ ; user mode case done.
         NOP
-    [ SAUBxferbroken
-        NOP
-    ]
+  ]
 
 10      LDR     stack, =SVCSTK
         MOV     r12, #BrkAd_ws
@@ -390,15 +389,8 @@ EVENTH  MOV     pc, lr
 
 NOCALL  MOV     r0, #0                  ; default callback routine
         LDR     r14, [r0, #CallBf]
-  [ SAUBxferbroken
-        NOP
-        NOP
-  ]
         LDMIA   r14, {r0-r12, r13_usr, r14_usr}^ ; load user's regs
         NOP
-  [ SAUBxferbroken
-        NOP
-  ]
         LDR     r14, [r14, #4*15]
         MOVS    pc, r14
 
@@ -597,9 +589,12 @@ DumpyTheRegisters  ROUT
         LDR     R1, [R0, -R0]         ; PC when exception happened
         STR     R1, [R0, #(15-8)*4]   ; In the right slot now ...
         TST     R1, #SVC_mode
+  [ SASTMhatbroken
+        STMEQIA R0!,{R8-R12}
+        STMEQIA R0, {R13,R14}^        ; user mode case done.
+        SUBEQ   R0, R0, #5*4
+  |
         STMEQIA R0, {R8-R14}^         ; user mode case done.
-  [ SAUBxferbroken
-        NOP
   ]
         BEQ     UNDEF1
 
diff --git a/s/NewReset b/s/NewReset
index a70c9a03..d06f4042 100644
--- a/s/NewReset
+++ b/s/NewReset
@@ -290,7 +290,11 @@ VIDCTAB
 
 ; Program Control Register first, to clear power-down bit
 
+   [ VCOstartfix
+        & &E0000404     ; CR: FIFO load 16 words, 1 bpp, ck/2, vclk (allow for doubled VCO freq)
+   |
         & &E0000400     ; CR: FIFO load 16 words, 1 bpp, ck/1, vclk
+   ]
 
 ; Don't bother programming all 256 palette entries, we'll be here all night
 ; Since we're setting up a 1 bit-per-pixel mode, just do colours 0 and 1
@@ -333,7 +337,11 @@ VIDCTAB
         & &B1000001     ; SCR: sound disabled (+use 24MHz clock)
 
         & &C00F1003     ; EREG = comp sync, DACs on, ereg output ext lut
+   [ VCOstartfix
+        & &D0000302     ; FSYNREG, clk = (3+1)/(2+1) * 24MHz = 32MHz  (higher frequency as part of fix)
+   |
         & &D0000305     ; FSYNREG, clk = (3+1)/(5+1) * 24MHz = 16MHz
+   ]
         & &F0013000     ; DCR: bus D[31:0], Hdisc       ;RCM 29/9/94: changed from &F0012000 at PSwindells request
         & &FFFFFFFF     ; That's the lot
  |
@@ -496,6 +504,33 @@ Continue
         MOV     R0, #timer0_bit
         STRB    R0, [R1, #IOCIRQCLRA]   ; Clear pending t0 interrupt j.i.c.
 
+  [ VCOstartfix
+        ;2nd part of fix for VCO failing to start on A7000 (esp. 7500FE) - forcing PCOMP high for about 3 ms
+        LDRB    R0, [R1,#IOMD_ID0]
+        CMP     R0, #&E7
+        LDREQB  R0, [R1,#IOMD_ID1]
+        CMPEQ   R0, #&D4
+        BEQ     vcofix_notMorris      ; risky to force PCOMP on Risc PC
+        MOV     R0, #VIDCPhys
+        LDR     R2, =&D0000342        ; VIDC20 FSYNREG, as in VIDCTAB but with force PCOMP high
+        STR     R2, [R0]
+        MOV     R0, #3072*2           ; time delay of about 3 ms (0.5 us units)
+        STRB    R0, [R1, #Timer0LR]   ; copy counter into output latch
+        LDRB    R2, [R1, #Timer0CL]   ; R2 := low output latch
+vcofix_waitloop
+        STRB    R0, [R1, #Timer0LR]   ; copy counter into output latch
+        LDRB    R3, [R1, #Timer0CL]   ; R3 := low output latch
+        TEQ     R3, R2                ; unchanged ?
+        BEQ     vcofix_waitloop       ; then loop
+        MOV     R2, R3                ; copy anyway
+        SUBS    R0, R0, #1            ; decrement count
+        BNE     vcofix_waitloop       ; loop if not finished
+        MOV     R0, #VIDCPhys
+        LDR     R2, =&D0000302        ; VIDC20 FSYNREG, as in VIDCTAB (PCOMP low again)
+        STR     R2, [R0]
+vcofix_notMorris
+  ]
+
 ; now size memory
 
         BL      MemSize                 ; out: r0 = page size, r1 = memory size, r2 = MEMC CR value, r3-r14 corrupt
@@ -650,6 +685,9 @@ SetUpKbdReturn
         ARMA_drain_WB
         ARMA_flush_IC
 vectorpoke_notSA_1
+    [ ARM810support
+        ARM8_branchpredict_flush  ;IMB on ARM810, and harmless on other ARMs
+    ]
  ]
 
         BIC     r0, r0, #I32_bit        ; and enable IRQs
@@ -844,6 +882,9 @@ conversionSWIfill
         ARMA_drain_WB
         ARMA_flush_IC
 afterpokingaround_notSA
+    [ ARM810support
+        ARM8_branchpredict_flush  ;IMB on ARM810, and harmless on other ARMs
+    ]
   ]
 
 ; Initialise CAO ptr to none.
@@ -874,7 +915,6 @@ kbdwait
 kbdthere
     ]
 
-
 ; IF power-on bit set in IOC AND R/T/Del/Copy pressed THEN reset CMOS RAM
 ; note that memory cleared if POR, so key info has had plenty of time!
         MOV     R0, #IOC
@@ -970,10 +1010,10 @@ not_full_reset
  [ MorrisSupport
         MOV     R8, #IOMD_Base
         LDRB    R0, [R8, #IOMD_ID0]
-        CMP     R0, #&98
+        CMP     R0, #&E7
         LDRB    R0, [R8, #IOMD_ID1]
-        CMPEQ   r0, #&5B
-        BNE     dont_program_mousetype
+        CMPEQ   r0, #&D4
+        BEQ     dont_program_mousetype  ; IOMD (not Morris)
 ;
 ; Morris based machines use PS2 mice/tracker balls
 ;
@@ -1062,7 +1102,7 @@ DefaultCMOSTable ; list of non-zero options wanted :
         =       SoundCMOS,      &F0     ; speaker on, volume 7, channel 1
 
         =       LanguageCMOS,   ConfiguredLang
-        =       YearCMOS,       95      ; changed from 93 to 95 on 12-Jan-95 to fix MED-04318
+        =       YearCMOS,       97      ; changed from 95 to 97 on 02-Jan-97
         =       YearCMOS+1,     19
  [ :LNOT: Select16BitSound
         =       TutuCMOS,       2_0100  ; tbs chars valid, ctrlchars '|x'
@@ -1865,6 +1905,9 @@ CopyDefaultIRQ1V
         ARMA_flush_IC
         MOV     r0,#0    ;restore r0 as zero base
 furtherpoke_notSA
+    [ ARM810support
+        ARM8_branchpredict_flush  ;IMB on ARM810, and harmless on other ARMs
+    ]
  ]
 
  [ CPU_Type = "ARM600"
@@ -1959,7 +2002,9 @@ furtherpoke_notSA
         SWI     XOS_NewLine
   ]
         SWI     XOS_EnterOS             ; switch back to SVC mode (IRQs, FIQs enabled)
-
+  [ RO371Timings
+        BL      finalmemoryspeed
+  ]
 ; end of added code
 
       [ International                   ; Open the kernel messages file.
@@ -2155,7 +2200,12 @@ processor_names
         ALIGN 32
         DCB     "StrongARM Processor",10,13,10,0
         ALIGN 32
-
+ [ MorrisIDString
+        DCB     "ARM 7500 Processor",10,13,10,0
+        ALIGN 32
+        DCB     "ARM 7500FE Processor",10,13,10,0
+        ALIGN 32
+ ]
         ; type, internal type, features
 cputable
         DCD &6000,0,0
@@ -2163,7 +2213,17 @@ cputable
         DCD &7000,2,0
         DCD &7100,3,0
         DCD &8100,4,2_11101
+ [ {TRUE}
+   ;corrected for 3.71 (SA does not abort for vector reads in 26-bit mode)
+        DCD &a100,5,2_11011
+ |
+   ;value for 3.70
         DCD &a100,5,2_11111
+ ]
+ [ MorrisIDString
+        DCD &7500,6,0
+        DCD &7501,7,0
+ ]
         DCD -1
  ]
 
@@ -2174,11 +2234,30 @@ MessageFileName DCB     "Resources:$.Resources.Kernel.Messages",0
 
  [ StrongARM
 Processor_Type
+   [ MorrisIDString
+        MOV     r0,#IOMD_Base
+        LDRB    r1,[r0,#IOMD_ID0]
+        CMP     r1,#&E7
+        LDRB    r1,[r0,#IOMD_ID1]
+        CMPEQ   r1,#&D4
+        BEQ     PT_RiscPC               ; E7,D4 means Risc PC
+        CMP     r1,#&5B
+        MOVEQ   r0,#&7500               ; 5B means 7500
+        BEQ     PT_lookup
+        CMP     r1,#&AA
+        MOVEQ   r0,#&7500
+        ORREQ   r0,r0,#&0001            ; AA means 7500FE - mark as 7501
+        BEQ     PT_lookup
+PT_RiscPC
+   ]
         ReadCop  R0,CR_ID               ; see data sheets for values
         ; ARM 600 funny
         TST     R0,#&f000
         MOVEQ   R0,R0, LSL #4
         AND     R0,R0,#&ff00
+   [ MorrisIDString
+PT_lookup
+   ]
         ADR     R1,cputable
 66
         LDR     R2,[R1],#4
diff --git a/s/PMF/osinit b/s/PMF/osinit
index 2b5c93b7..f546ed48 100644
--- a/s/PMF/osinit
+++ b/s/PMF/osinit
@@ -562,19 +562,21 @@ ReadMachineType ENTRY "r0-r12"
   [ MorrisSupport
         MOV     r12, #IOMD_Base
         LDRB    r0, [r12, #IOMD_ID0]
-        CMP     r0, #&98
+        CMP     r0, #&E7
         LDRB    r0, [r12, #IOMD_ID1]
-        CMPEQ   r0, #&5B
-        MOVEQ   r11, #IOST_7500                         ;EQ, Morris
-        MOVNE   r11, #0                                 ;NE, assume Medusa
+        CMPEQ   r0, #&D4
+        MOVEQ   r11, #0                         ;EQ, Medusa
+	BEQ	rmtype_nomorris
+        MOV     r11, #IOST_7500                 ;NE, assume Morris
 ;
 ; On Kryten, Morris pin Event2 is tied low so bit Nevent2 is a ONE
 ; On Stork, Morris pin Event2 is tied high so bit Nevent2 is a ZERO
 ;
-        LDREQB  r0, [r12, #IOMD_IRQSTD]                 ;EQ, Morris
-        TSTEQ   r0, #IOMD_Nevent2_bit
+        LDRB    r0, [r12, #IOMD_IRQSTD]                 ;Morris
+        TST     r0, #IOMD_Nevent2_bit
         ORREQ   r11, r11, #IOST_BATMAN                  ;EQ, Stork ie Morris & BATMAN
 
+rmtype_nomorris
         ORR     r0, r11, #IOST_IOEB                     ; pretend we've got IOEB
 ;
 ; r11 holds  0                        for  IOMD   (Risc PC)
diff --git a/s/vdu/vdudriver b/s/vdu/vdudriver
index 89eee2b4..475a5c5d 100644
--- a/s/vdu/vdudriver
+++ b/s/vdu/vdudriver
@@ -1015,11 +1015,11 @@ DbgFilename
   [ MorrisSupport
     ;    MOV     R10, #IOMD_Base
     ;    LDRB    R9, [R10, #IOMD_ID0]
-    ;    CMP     R9, #&98
+    ;    CMP     R9, #&E7
     ;    LDRB    R9, [R10, #IOMD_ID1]
-    ;    CMPEQ   R9, #&5B
-    ;    MOVEQ   R9, #32000              ;Morris clocks VIDC20L at 32Mhz
-    ;    LDRNE   R9, =24000              ;RISC PC clocks VIDC20 at 24MHz
+    ;    CMPEQ   R9, #&D4
+    ;    MOVNE   R9, #32000              ;Morris clocks VIDC20L at 32Mhz
+    ;    LDREQ   R9, =24000              ;RISC PC clocks VIDC20 at 24MHz
         MOV     R9, #0
         LDRB    R9, [R9, #IOSystemType]
         TST     R9, #IOST_7500
@@ -1933,11 +1933,11 @@ ProcessVIDCListType3 ROUT
  [ MorrisSupport
    ;     MOV     R14, #IOMD_Base
    ;     LDRB    R1, [R14, #IOMD_ID0]
-   ;     CMP     R1, #&98
+   ;     CMP     R1, #&E7
    ;     LDRB    R1, [R14, #IOMD_ID1]
-   ;     CMPEQ   R1, #&5B
-   ;     MOVEQ   R1, #32000              ;Morris clocks VIDC20L at 32Mhz
-   ;     LDRNE   R1, =24000              ;RISC PC clocks VIDC20 at 24MHz
+   ;     CMPEQ   R1, #&D4
+   ;     MOVNE   R1, #32000              ;Morris clocks VIDC20L at 32Mhz
+   ;     LDREQ   R1, =24000              ;RISC PC clocks VIDC20 at 24MHz
         MOV     R1, #0
         LDRB    R1, [R1, #IOSystemType]
         TST     R1, #IOST_7500
@@ -2323,8 +2323,15 @@ ComputeModuli ENTRY "r2-r12", ComputeModuliStack
         LDR     r5, [r2, #BestVInRange - BestDInRange]  ; r5 = Best V
 
         SUBS    r4, r4, #1              ; values in FSyn are n-1
+  [ VCOstartfix
+        ;do *not* do the very slow trick - this will stall the VCO and it may not restart
+        ;properly later (we don't give a fig for power consumption)
+        MOVEQ   r4, #3
+        MOVEQ   r5, #8                  ; after sub below, (7+1)/(3+1) so VCO runs at twice ref clock
+  |
         MOVEQ   r4, #63                 ; if R=V=1 then use max R
         MOVEQ   r5, #2                  ; and min V to make VCO go really slow
+  ]
 
         SUB     r5, r5, #1              ; for both v and r
         ASSERT  FSyn_RShift = 0
-- 
GitLab