ARM600 73.6 KB
Newer Older
Neil Turton's avatar
Neil Turton committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
; Copyright 1996 Acorn Computers Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; > ARM600

        GBLL    DebugAborts
DebugAborts SETL {FALSE}

20 21 22 23 24 25
; Disable ProcessTransfer code pending execution.
; If we want to reuse the code at some point in the future, be aware that it
; needs the following work performing:
; * Updating to cope with HiProcVecs (or special zero page handling removed)
; * (preferablly) add support for all the 'new' load/store instructions.
;   LDRH/STRH, LDRD/STRD, coprocessor transfers, etc.
Jeffrey Lee's avatar
Jeffrey Lee committed
26
        GBLL    UseProcessTransfer
27
UseProcessTransfer SETL {FALSE}
Jeffrey Lee's avatar
Jeffrey Lee committed
28

Neil Turton's avatar
Neil Turton committed
29 30 31 32 33 34

; MMU interface file - ARM600 version

; Created by TMD 15-Jul-92
; Comments updated by TMD 04-Aug-93

35 36 37
;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
Neil Turton's avatar
Neil Turton committed
38 39


Neil Turton's avatar
Neil Turton committed
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
; Workspace needed for ARM600 work is as follows:
;
; * Level 2 page tables for a contiguous logical area starting at zero
;     This consists of:
;       a) a fixed size bit covering 0 to 192M (currently)
;       b) a variable size bit covering the free pool - 192M to 192M + (memsize rounded up to 4M)
;     Note that the 192M value is sufficient to cover all the fixed size areas at present.
;     As more areas switch to new world, this limit will come down and down, but free pool must always
;      start at the end of the fixed areas.
;     (Level 2 for areas outside this region are allocated dynamically afterwards)
;
; * Level 1 page table (16K, stored in the middle of L2PT, where the I/O + ROM would be if it wasn't section mapped)
;
; * Undefined32 mode stack (8K)
;
Kevin Bracey's avatar
Kevin Bracey committed
55 56
; * Abort32 mode stack (8K)
;
Neil Turton's avatar
Neil Turton committed
57 58 59 60 61 62 63 64 65 66 67 68 69
; * Soft CAM map (variable size = memsize/4K*8, rounded up to 4K)
;
; In order to make the memory models for MEMC1 and IOMD harmonious, the MEMC1 system is considered as a section of
; video RAM starting at &02000000 size 480K, and an area of "non-video RAM" starting at &02078000, size (totalRAM-480K)
; IOMD has 1 area of video RAM and up to 4 areas of non-video RAM.
;
; (Note: when OS is soft-loaded, a 2 Mbyte chunk of DRAM is removed from the RAM map, therefore the model allows for
;  1 area of video RAM and up to 5 areas of non-video RAM)
;
; The fixed system pages (which include those described above) start at the base of the first bank of non-video RAM
; (on IOMD we allow this to be in any of the 4 RAM sites, ie you don't have to have RAM in any particular SIMM site)
; Consequently the base of the fixed system pages is not known at assembly time, so has to be passed in a register
; to the generic code.
Neil Turton's avatar
Neil Turton committed
70 71 72 73
;
; amg 7/12/96 Renaissance, import changes below from Spinner tree, but this is fundamentally the
; 3.70 file.

74
; 17-Jun-96     BAR     Change speed settings for the second bank of ROM space.
Neil Turton's avatar
Neil Turton committed
75 76
; 09-Jul-96     BAR     Improve IOMD ID vsn code - two places.
;                       Change ROM Speed settings for 7500FE and non-7500FE parts.
77 78 79 80 81 82 83
; 25-Jul-96     BAR     Correct bug in video bandwidth code, wrong label used.
; 16-Aug-96     JRH     Programming of 2nd ROM bank (IOMD ROMCR1 register):
;                               reinstated ExtROMSupport code, added CanLiveOnROMCard code
;                       MemInitTable:
;                               If ExtROMSupport: added assertion that ImageSize <= 4096
;                               and maps 4MB of each ROM bank.
;                               Otherwise: always maps 8MB of ROM space independant of ImageSize
Neil Turton's avatar
Neil Turton committed
84 85


86
 [ :LNOT: HAL
Neil Turton's avatar
Neil Turton committed
87 88 89 90 91 92
; Fixed page allocation is as follows

        ^       0
DRAMOffset_CursorChunk  #       32*1024         ; ie on MEMC1 this is the last 32K of DAG-addressable memory
DRAMOffset_PageZero     #       32*1024         ; 32K at location zero
DRAMOffset_SystemHeap   #       32*1024         ; system heap/svc stack
Kevin Bracey's avatar
Kevin Bracey committed
93 94 95 96
 [ No26bitCode
DRAMOffset_AbortStack   #        8*1024
 ]
        AlignSpace      16*1024                 ; L1PT (and hence L2PT) must be 16K-aligned
Neil Turton's avatar
Neil Turton committed
97 98 99 100 101 102 103 104 105 106 107
DRAMOffset_L2PT         #       0               ; static L2PT (variable size, with embedded L1PT)
DRAMOffset_L1PT         *       DRAMOffset_L2PT + 48*1024

; Undefined stack memory (size 8K) starts immediately after end of L2PT (which is variable size)
; Soft CAM map (variable size) starts immediately after end of UndStack

StaticPagesSize         *       @

; Logical addresses are as follows


Neil Turton's avatar
Neil Turton committed
108
FixedAreasL2Size        *       96*1024        ; amount of L2 to cover fixed areas, excluding free pool
Neil Turton's avatar
Neil Turton committed
109 110 111

UndStackSoftCamChunk    *       &01E00000
UndStackSize            *       8*1024
Kevin Bracey's avatar
Kevin Bracey committed
112
CamEntriesForVicky      *       UndStackSoftCamChunk + UndStackSize
Neil Turton's avatar
Neil Turton committed
113

Neil Turton's avatar
Neil Turton committed
114 115 116 117 118

; - address for virtual area for StrongARM data cache cleaning (32k, for two 16k areas)
; - the two areas are used in strict rotation for each full clean, so that we can do a full
;   clean (and not flush) with interrupts on
; - the address must be aligned such that EOR with 16*1024 flipflops between the two addresses
Kevin Bracey's avatar
Kevin Bracey committed
119
ARMA_Cleaners_address  * &01F10000
120
 ] ; :LNOT: HAL
Neil Turton's avatar
Neil Turton committed
121 122


123 124
        KEEP

Neil Turton's avatar
Neil Turton committed
125 126 127 128
; **************** CAM manipulation utility routines ***********************************

; **************************************************************************************
;
129
;       BangCamUpdate - Update CAM, MMU for page move, coping with page currently mapped in
Neil Turton's avatar
Neil Turton committed
130
;
131 132
; mjs Oct 2000
; reworked to use generic ARM ops (vectored to appropriate routines during boot)
Neil Turton's avatar
Neil Turton committed
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
;
; First look in the CamEntries table to find the logical address L this physical page is
; currently allocated to. Then check in the Level 2 page tables to see if page L is currently
; at page R2. If it is, then map page L to be inaccessible, otherwise leave page L alone.
; Then map logical page R3 to physical page R2.
;
; in:   r2 = physical page number
;       r3 = logical address (2nd copy if doubly mapped area)
;       r9 = offset from 1st to 2nd copy of doubly mapped area (either source or dest, but not both)
;       r11 = PPL + CB bits
;
; out:  r0, r1, r4, r6 corrupted
;       r2, r3, r5, r7-r12 preserved
;
; NB Use of stack is allowed in this routine

BangCamUpdate ROUT
        TST     r11, #DynAreaFlags_DoublyMapped ; if moving page to doubly mapped area
        SUBNE   r3, r3, r9                      ; then CAM soft copy holds ptr to 1st copy

Jeffrey Lee's avatar
Jeffrey Lee committed
153
        LDR     r1, =ZeroPage
Neil Turton's avatar
Neil Turton committed
154 155 156
        LDR     r1, [r1, #CamEntriesPointer]
        ADD     r1, r1, r2, LSL #3              ; point at cam entry (logaddr, PPL)
        LDMIA   r1, {r0, r6}                    ; r0 = current logaddress, r6 = current PPL
157 158
        BIC     r4, r11, #PageFlags_Unsafe
        STMIA   r1, {r3, r4}                    ; store new address, PPL
Neil Turton's avatar
Neil Turton committed
159
        Push    "r0, r6"                        ; save old logical address, PPL
Jeffrey Lee's avatar
Jeffrey Lee committed
160
        LDR     r1, =ZeroPage+PhysRamTable      ; go through phys RAM table
Neil Turton's avatar
Neil Turton committed
161 162 163 164 165 166 167 168
        MOV     r6, r2                          ; make copy of r2 (since that must be preserved)
10
        LDMIA   r1!, {r0, r4}                   ; load next address, size
        SUBS    r6, r6, r4, LSR #12             ; subtract off that many pages
        BCS     %BT10                           ; if more than that, go onto next bank

        ADD     r6, r6, r4, LSR #12             ; put back the ones which were too many
        ADD     r0, r0, r6, LSL #12             ; move on address by the number of pages left
Robert Sprowson's avatar
Robert Sprowson committed
169
        LDR     r6, [sp]                        ; reload old logical address
Neil Turton's avatar
Neil Turton committed
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187

; now we have r6 = old logical address, r2 = physical page number, r0 = physical address

        TEQ     r6, r3                          ; TMD 19-Jan-94: if old logaddr = new logaddr, then
        BEQ     %FT20                           ; don't remove page from where it is, to avoid window
                                                ; where page is nowhere.
        LDR     r1, =L2PT
        ADD     r6, r1, r6, LSR #10             ; r6 -> L2PT entry for old log.addr
        MOV     r4, r6, LSR #12                 ; r4 = word offset into L2 for address r6
        LDR     r4, [r1, r4, LSL #2]            ; r4 = L2PT entry for L2PT entry for old log.addr
        TST     r4, #3                          ; if page not there
        BEQ     %FT20                           ; then no point in trying to remove it

        LDR     r4, [r6]                        ; r4 = L2PT entry for old log.addr
        MOV     r4, r4, LSR #12                 ; r4 = physical address for old log.addr
        TEQ     r4, r0, LSR #12                 ; if equal to physical address of page being moved
        BNE     %FT20                           ; if not there, then just put in new page

188
        AND     r4, r11, #PageFlags_Unsafe
Neil Turton's avatar
Neil Turton committed
189 190 191
        Push    "r0, r3, r11, r14"              ; save phys.addr, new log.addr, new PPL, lr
        ADD     r3, sp, #4*4
        LDMIA   r3, {r3, r11}                   ; reload old logical address, old PPL
192 193 194
        LDR     r0, =DuffEntry                  ; Nothing to do if wasn't mapped in
        ORR     r11, r11, r4
        TEQ     r3, r0
Neil Turton's avatar
Neil Turton committed
195
        MOV     r0, #0                          ; cause translation fault
196
        BLNE    BangL2PT                        ; map page out
Neil Turton's avatar
Neil Turton committed
197 198 199 200 201 202 203
        Pull    "r0, r3, r11, r14"
20
        ADD     sp, sp, #8                      ; junk old logical address, PPL
        B       BangCamAltEntry                 ; and branch into BangCam code

; **************************************************************************************
;
204
;       BangCam - Update CAM, MMU for page move, assuming page currently mapped out
Neil Turton's avatar
Neil Turton committed
205 206
;
; This routine maps a physical page to a given logical address
207
; It is assumed that the physical page is currently not mapped anywhere else
Neil Turton's avatar
Neil Turton committed
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
;
; in:   r2 = physical page number
;       r3 = logical address (2nd copy if doubly mapped)
;       r9 = offset from 1st to 2nd copy of doubly mapped area (either source or dest, but not both)
;       r11 = PPL
;
; out:  r0, r1, r4, r6 corrupted
;       r2, r3, r5, r7-r12 preserved
;
; NB Can't use stack - there might not be one!
;
; NB Also - the physical page number MUST be in range.

; This routine must work in 32-bit mode

BangCam ROUT
        TST     r11, #DynAreaFlags_DoublyMapped ; if area doubly mapped
        SUBNE   r3, r3, r9              ; then move ptr to 1st copy

Jeffrey Lee's avatar
Jeffrey Lee committed
227
        LDR     r1, =ZeroPage+PhysRamTable ; go through phys RAM table
Neil Turton's avatar
Neil Turton committed
228 229 230 231 232 233 234 235 236
        MOV     r6, r2                  ; make copy of r2 (since that must be preserved)
10
        LDMIA   r1!, {r0, r4}           ; load next address, size
        SUBS    r6, r6, r4, LSR #12     ; subtract off that many pages
        BCS     %BT10                   ; if more than that, go onto next bank

        ADD     r6, r6, r4, LSR #12     ; put back the ones which were too many
        ADD     r0, r0, r6, LSL #12     ; move on address by the number of pages left
BangCamAltEntry
237
        LDR     r4, =DuffEntry          ; check for requests to map a page to nowhere
238
        LDR     r6, =ZeroPage
239
        TEQ     r4, r3                  ; don't actually map anything to nowhere
240
        LDR     r1, [r6, #ProcessorFlags]
241
        MOVEQ   pc, lr
242
        TST     r1, #CPUFlag_ExtendedPages
Neil Turton's avatar
Neil Turton committed
243
        AND     r4, r11, #3             ; first use PPL bits
244 245
        ADREQ   r1, PPLTrans
        ADRNE   r1, PPLTransX           ; always use extended pages if supported
Neil Turton's avatar
Neil Turton committed
246
        LDR     r1, [r1, r4, LSL #2]    ; get PPL bits and SmallPage indicator
247

248 249 250
        ASSERT  DynAreaFlags_CPBits = 7*XCB_P :SHL: 10
        ASSERT  DynAreaFlags_NotCacheable = XCB_NC :SHL: 4
        ASSERT  DynAreaFlags_NotBufferable = XCB_NB :SHL: 4
Kevin Bracey's avatar
Kevin Bracey committed
251 252 253 254 255 256 257 258

        ORR     r0, r0, r1

        LDR     r6, [r6, #MMU_PCBTrans]
        AND     r4, r11, #DynAreaFlags_CPBits
        AND     r1, r11, #DynAreaFlags_NotCacheable + DynAreaFlags_NotBufferable
        TST     r11, #PageFlags_TempUncacheableBits
        ORRNE   r1, r1, #DynAreaFlags_NotCacheable      ; if temp uncache, set NC bit, ignore P
259
        ORREQ   r1, r1, r4, LSR #10-4                   ; else use NC, NB and P bits
Kevin Bracey's avatar
Kevin Bracey committed
260 261
        LDRB    r1, [r6, r1, LSR #4]                    ; convert to X, C and B bits for this CPU
        ORR     r0, r0, r1
Neil Turton's avatar
Neil Turton committed
262 263 264

        LDR     r1, =L2PT               ; point to level 2 page tables

265 266
        ;fall through to BangL2PT

Neil Turton's avatar
Neil Turton committed
267 268 269 270 271 272 273
;internal entry point for updating L2PT entry
;
; entry: r0 = new L2PT value, r1 -> L2PT, r3 = logical address (4k aligned), r11 = PPL
;
; exit: r0,r1,r4,r6 corrupted
;
BangL2PT                                        ; internal entry point used only by BangCamUpdate
274 275 276
        Push    "lr"
        MOV     r6, r0

277 278 279
        TST     r11, #PageFlags_Unsafe
        BNE     %FT30

Neil Turton's avatar
Neil Turton committed
280 281 282
        TST     r11, #DynAreaFlags_DoublyMapped
        BNE     BangL2PT_sledgehammer           ;if doubly mapped, don't try to be clever

283 284 285 286 287
        ;we sort out cache coherency _before_ remapping, because some ARMs might insist on
        ;that order (write back cache doing write backs to logical addresses)
        ;we need to worry about cache only if mapping out a cacheable page
        ;
        TEQ     r6, #0                          ;EQ if mapping out
Kevin Bracey's avatar
Kevin Bracey committed
288
        TSTEQ   r11, #DynAreaFlags_NotCacheable ;EQ if also cacheable (overcautious for temp uncache+illegal PCB combos)
289 290
        MOV     r0, r3                          ;MMU page entry address
        ADR     lr, %FT20
Jeffrey Lee's avatar
Jeffrey Lee committed
291
        LDR     r4, =ZeroPage
292 293
        ARMop   MMU_ChangingEntry, EQ, tailcall, r4
        ARMop   MMU_ChangingUncachedEntry, NE, tailcall, r4
Neil Turton's avatar
Neil Turton committed
294

295 296 297
20      STR     r6, [r1, r3, LSR #10]           ;update L2PT entry

        Pull    "pc"
Neil Turton's avatar
Neil Turton committed
298 299

BangL2PT_sledgehammer
300 301 302 303 304

        ;sledgehammer is super cautious and does cache/TLB coherency on a global basis
        ;should only be used for awkward cases
        ;
        TEQ     r6, #0                          ;EQ if mapping out
Kevin Bracey's avatar
Kevin Bracey committed
305
        TSTEQ   r11, #DynAreaFlags_NotCacheable ;EQ if also cacheable (overcautious for temp uncache+illegal PCB combos)
306
        ADR     lr, %FT30
Jeffrey Lee's avatar
Jeffrey Lee committed
307
        LDR     r4, =ZeroPage
308 309 310 311
        ARMop   MMU_Changing, EQ, tailcall, r4
        ARMop   MMU_ChangingUncached, NE, tailcall, r4

30      STR     r6, [r1, r3, LSR #10]!          ; update level 2 page table (and update pointer so we can use bank-to-bank offset
Neil Turton's avatar
Neil Turton committed
312
        TST     r11, #DynAreaFlags_DoublyMapped ; if area doubly mapped
313 314
        STRNE   r6, [r1, r9, LSR #10]           ; then store entry for 2nd copy as well
        ADDNE   r3, r3, r9                      ; and point logical address back at 2nd copy
Neil Turton's avatar
Neil Turton committed
315

316
        Pull    "pc"
Neil Turton's avatar
Neil Turton committed
317

Neil Turton's avatar
Neil Turton committed
318

319 320 321 322 323 324
PPLTransL1
        &       (AP_Full * L1_APMult) + L1_Section        ; R any W any
        &       (AP_Read * L1_APMult) + L1_Section        ; R any W sup
        &       (AP_None * L1_APMult) + L1_Section        ; R sup W sup
        &       (AP_ROM  * L1_APMult) + L1_Section        ; R any W none

Neil Turton's avatar
Neil Turton committed
325 326 327 328
PPLTrans
        &       (AP_Full * L2_APMult) + L2_SmallPage      ; R any W any
        &       (AP_Read * L2_APMult) + L2_SmallPage      ; R any W sup
        &       (AP_None * L2_APMult) + L2_SmallPage      ; R sup W sup
329
        &       (AP_ROM  * L2_APMult) + L2_SmallPage      ; R any W none
Neil Turton's avatar
Neil Turton committed
330

Kevin Bracey's avatar
Kevin Bracey committed
331 332 333 334 335 336
PPLTransX
        &       (AP_Full * L2X_APMult) + L2_ExtPage       ; R any W any
        &       (AP_Read * L2X_APMult) + L2_ExtPage       ; R any W sup
        &       (AP_None * L2X_APMult) + L2_ExtPage       ; R sup W sup
        &       (AP_ROM  * L2X_APMult) + L2_ExtPage       ; R any W none

Neil Turton's avatar
Neil Turton committed
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
PageSizes
        &       4*1024                  ; 0 is 4K
        &       8*1024                  ; 4 is 8K
        &       16*1024                 ; 8 is 16
        &       32*1024                 ; C is 32

PageShifts
        =       12, 13, 0, 14           ; 1 2 3 4
        =       0,  0,  0, 15           ; 5 6 7 8

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; SWI OS_UpdateMEMC: Read/write MEMC1 control register

SSETMEMC ROUT

        AND     r10, r0, r1
Jeffrey Lee's avatar
Jeffrey Lee committed
353
        LDR     r12, =ZeroPage
Kevin Bracey's avatar
Kevin Bracey committed
354
        WritePSRc SVC_mode+I_bit+F_bit, r0
Neil Turton's avatar
Neil Turton committed
355 356 357 358 359 360 361 362
        LDR     r0, [r12, #MEMC_CR_SoftCopy] ; return old value
        BIC     r11, r0, r1
        ORR     r11, r11, R10
        BIC     r11, r11, #&FF000000
        BIC     r11, r11, #&00F00000
        ORR     r11, r11, #MEMCADR
        STR     r11, [r12, #MEMC_CR_SoftCopy]

363 364 365 366 367 368 369 370 371 372
; mjs Oct 2000 kernel/HAL split
;
; The kernel itself should now never call this SWI, but grudgingly has
; to maintain at least bit 10 of soft copy
;
; Here, we only mimic action of bit 10 to control video/cursor DMA (eg. for ADFS)
; The whole OS_UpdateMEMC thing would ideally be withdrawn as archaic, but
; unfortunately has not even been deprecated up to now

; for reference, the bits of the MEMC1 control register are:
Neil Turton's avatar
Neil Turton committed
373 374 375 376 377 378 379 380 381 382
;
; bits 0,1 => unused
; bits 2,3 => page size, irrelevant since always 4K
; bits 4,5 => low ROM access time (mostly irrelevant but set it up anyway)
; bits 6,7 => hi  ROM access time (definitely irrelevant but set it up anyway)
; bits 8,9 => DRAM refresh control
; bit 10   => Video/cursor DMA enable
; bit 11   => Sound DMA enable
; bit 12   => OS mode

Kevin Bracey's avatar
Kevin Bracey committed
383 384 385 386 387
        Push  "r0,r1,r4, r14"
        TST   r11, #(1 :SHL: 10)
        MOVEQ r0, #1             ; blank (video DMA disable)
        MOVNE r0, #0             ; unblank (video DMA enable)
        MOV   r1, #0             ; no funny business with DPMS
Jeffrey Lee's avatar
Jeffrey Lee committed
388 389 390 391
        ADD   r4, r12, #VduDriverWorkSpace
        LDR   r4, [r4, #CurrentGraphicsVDriver]
        MOV   r4, r4, LSL #24
        ORR   r4, r4, #GraphicsV_SetBlank
Kevin Bracey's avatar
Kevin Bracey committed
392 393
        BL    CallGraphicsV
        Pull  "r0,r1,r4, r14"
Neil Turton's avatar
Neil Turton committed
394

Kevin Bracey's avatar
Kevin Bracey committed
395
        WritePSRc SVC_mode+I_bit, r11
Neil Turton's avatar
Neil Turton committed
396 397 398 399 400 401
        ExitSWIHandler

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;       SWI OS_MMUControl
;
Neil Turton's avatar
Neil Turton committed
402
; in:   r0 = 0 (reason code 0, for modify control register)
Neil Turton's avatar
Neil Turton committed
403 404 405 406 407 408 409
;       r1 = EOR mask
;       r2 = AND mask
;
;       new control = ((old control AND r2) EOR r1)
;
; out:  r1 = old value
;       r2 = new value
Neil Turton's avatar
Neil Turton committed
410 411 412 413 414
;
; in:   r0 bits 1 to 28 = 0, bit 0 = 1  (reason code 1, for flush request)
;          r0 bit 31 set if cache(s) to be flushed
;          r0 bit 30 set if TLB(s) to be flushed
;          r0 bit 29 set if flush of entry only (else whole flush)
Kevin Bracey's avatar
Kevin Bracey committed
415
;          r0 bit 28 set if write buffer to be flushed (implied by bit 31)
Neil Turton's avatar
Neil Turton committed
416 417
;       r1 = entry specifier, if r0 bit 29 set
;       (currently, flushing by entry is ignored, and just does full flush)
418 419 420 421 422
;
; in:   r0 bits 0-7 = 2: reason code 2, read ARMop
;          r0 bits 15-8 = ARMop index
;
; out:  r0 = ARMop function ptr
Neil Turton's avatar
Neil Turton committed
423
;
Neil Turton's avatar
Neil Turton committed
424

425
MMUControlSWI   Entry
Neil Turton's avatar
Neil Turton committed
426 427 428 429 430 431
        BL      MMUControlSub
        PullEnv
        ORRVS   lr, lr, #V_bit
        ExitSWIHandler

MMUControlSub
Neil Turton's avatar
Neil Turton committed
432 433 434 435
        Push    lr
        AND     lr,r0,#&FF
        CMP     lr, #MMUCReason_Unknown
        ADDCC   pc, pc, lr, LSL #2
Neil Turton's avatar
Neil Turton committed
436 437
        B       MMUControl_Unknown
        B       MMUControl_ModifyControl
Neil Turton's avatar
Neil Turton committed
438
        B       MMUControl_Flush
439
        B       MMUControl_GetARMop
Neil Turton's avatar
Neil Turton committed
440 441 442 443 444

MMUControl_Unknown
        ADRL    r0, ErrorBlock_HeapBadReason
 [ International
        BL      TranslateError
Robert Sprowson's avatar
Robert Sprowson committed
445
 |
Neil Turton's avatar
Neil Turton committed
446
        SETV
Robert Sprowson's avatar
Robert Sprowson committed
447 448
 ]
        Pull    "pc"
Neil Turton's avatar
Neil Turton committed
449

450

Neil Turton's avatar
Neil Turton committed
451 452 453 454 455
MMUControl_ModifyControl ROUT
        Push    "r3,r4,r5"
        CMP     r1,#0
        CMPEQ   r2,#&FFFFFFFF
        BEQ     MMUC_modcon_readonly
Jeffrey Lee's avatar
Jeffrey Lee committed
456
        LDR     r3,=ZeroPage
457 458 459 460
        LDRB    r5,[r3, #ProcessorArch]
        PHPSEI  r4                      ; disable IRQs while we modify soft copy (and possibly switch caches off/on)

        CMP     r5,#ARMv4
461
        LDRLO   lr, [r3, #MMUControlSoftCopy]
462
        ARM_read_control lr,HS
463 464
;        MOVHS   lr,lr,LSL #19
;        MOVHS   lr,lr,LSR #19           ; if ARMv4 or later, we can read control reg. - trust this more than soft copy
Neil Turton's avatar
Neil Turton committed
465 466 467
        AND     r2, r2, lr
        EOR     r2, r2, r1
        MOV     r1, lr
468 469 470
        LDR     r5, [r3, #ProcessorFlags]
        TST     r5, #CPUFlag_SplitCache
        BEQ     %FT05
471 472 473 474 475
 [ {FALSE}
        TST     r2,#MMUC_C              ; if split caches, then I bit mirrors C bit
        ORRNE   r2,r2,#MMUC_I
        BICEQ   r2,r2,#MMUC_I
 ]
Neil Turton's avatar
Neil Turton committed
476
05
Neil Turton's avatar
Neil Turton committed
477 478
        STR     r2, [r3, #MMUControlSoftCopy]
        BIC     lr, r2, r1              ; lr = bits going from 0->1
Neil Turton's avatar
Neil Turton committed
479
        TST     lr, #MMUC_C             ; if cache turning on then flush cache before we do it
480
        TSTEQ   lr, #MMUC_I
Neil Turton's avatar
Neil Turton committed
481
        BEQ     %FT10
482

483
        Push    "r0"
Jeffrey Lee's avatar
Jeffrey Lee committed
484
        ARMop   Cache_InvalidateAll,,,r3
485
        Pull    "r0"
Neil Turton's avatar
Neil Turton committed
486
10
487
        BIC     lr, r1, r2              ; lr = bits going from 1->0
488 489
        TST     lr, #MMUC_C             ; if cache turning off then clean data cache first
        BEQ     %FT15
490
        Push    "r0"
Jeffrey Lee's avatar
Jeffrey Lee committed
491
        ARMop   Cache_CleanAll,,,r3
492
        Pull    "r0"
Neil Turton's avatar
Neil Turton committed
493 494 495 496
15
        ARM_write_control r2
        BIC     lr, r1, r2              ; lr = bits going from 1->0
        TST     lr, #MMUC_C             ; if cache turning off then flush cache afterwards
497
        TSTNE   lr, #MMUC_I
Neil Turton's avatar
Neil Turton committed
498
        BEQ     %FT20
499
        Push    "r0"
Jeffrey Lee's avatar
Jeffrey Lee committed
500
        ARMop   Cache_InvalidateAll,,,r3
501
        Pull    "r0"
Neil Turton's avatar
Neil Turton committed
502
20
Kevin Bracey's avatar
Kevin Bracey committed
503
        PLP     r4                      ; restore IRQ state
Neil Turton's avatar
Neil Turton committed
504 505 506
        Pull    "r3,r4,r5,pc"

MMUC_modcon_readonly
Jeffrey Lee's avatar
Jeffrey Lee committed
507
        LDR     r3, =ZeroPage
508 509
        LDRB    r5, [r3, #ProcessorArch]
        CMP     r5, #ARMv4
510
        LDRLO   lr, [r3, #MMUControlSoftCopy]
511
        ARM_read_control lr,HS
512 513
;        MOVHS   lr,lr,LSL #19
;        MOVHS   lr,lr,LSR #19           ; if ARMv4 or later, we can read control reg. - trust this more than soft copy
514
        STRHS   lr, [r3, #MMUControlSoftCopy]
Neil Turton's avatar
Neil Turton committed
515 516 517 518 519
        MOV     r1, lr
        MOV     r2, lr
        Pull    "r3,r4,r5,pc"

MMUControl_Flush
Kevin Bracey's avatar
Kevin Bracey committed
520
       MOVS     r10, r0
Jeffrey Lee's avatar
Jeffrey Lee committed
521
       LDR      r12, =ZeroPage
Kevin Bracey's avatar
Kevin Bracey committed
522 523 524 525
       ARMop    Cache_CleanInvalidateAll,MI,,r12
       TST      r10,#&40000000
       ARMop    TLB_InvalidateAll,NE,,r12
       TST      r10,#&10000000
526
       ARMop    DSB_ReadWrite,NE,,r12
Kevin Bracey's avatar
Kevin Bracey committed
527 528
       ADDS     r0,r10,#0
       Pull     "pc"
Neil Turton's avatar
Neil Turton committed
529

530 531 532 533 534 535 536 537 538
MMUControl_GetARMop
       AND      r0, r0, #&FF00
       CMP      r0, #(ARMopPtrTable_End-ARMopPtrTable):SHL:6
       BHS      MMUControl_Unknown
       ADRL     lr, ARMopPtrTable
       LDR      r0, [lr, r0, LSR #6]
       LDR      r0, [r0]
       Pull     "pc"

Neil Turton's avatar
Neil Turton committed
539 540 541 542
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;       Exception veneers

Kevin Bracey's avatar
Kevin Bracey committed
543
 [ :LNOT:No26bitCode
Neil Turton's avatar
Neil Turton committed
544 545 546 547 548 549 550 551 552 553 554 555
; Undefined instruction trap pre-veneer
; in:   r13_undef -> a FD stack
;       r14_undef -> undefined instruction +4
;       psr_undef = PSR at time of undef'd instruction

UndPreVeneer    ROUT

        Push    "r0-r7,r14"             ; push r0-r7 on undef stack, and make room for return address
        MOV     r0, r13_undef

; for the time being just merge lr and psr

556
        MRS     r1, SPSR                                ; r1 = saved PSR
Neil Turton's avatar
Neil Turton committed
557 558 559 560 561
        AND     r2, r1, #&F0000003                      ; get saved NZCV and 26 bit modes
        ORR     lr_undef, lr_undef, r2
        AND     r2, r1, #I32_bit + F32_bit              ; extract I and F from new place
        ORR     r1, lr_undef, r2, LSL #IF32_26Shift     ; r1 = combined lr and psr

562
        MRS     r2, CPSR                ; now switch into SVC26
Neil Turton's avatar
Neil Turton committed
563 564
        BIC     r3, r2, #&1F
        ORR     r3, r3, #SVC26_mode
565 566
        MSR     SPSR_cxsf, r3           ; set SPSR_undef to be CPSR but with SVC26
        MSR     CPSR_c, r3              ; and select this mode now
Neil Turton's avatar
Neil Turton committed
567 568 569

        MOV     lr_svc, r1              ; lr_svc = PC + PSR from exception

570
        MSR     CPSR_c, r2              ; go back into undef mode
Neil Turton's avatar
Neil Turton committed
571 572 573 574 575

        LDR     r1, =UndHan             ; work out address of undefined instruction handler
        LDR     r1, [r1]
        STR     r1, [r0, #8*4]          ; and store it as return address
        Pull    "r0-r7, pc",,^          ; exit to handler, restoring sp_undef and entering SVC26 mode
Kevin Bracey's avatar
Kevin Bracey committed
576
 ]
Neil Turton's avatar
Neil Turton committed
577

578 579 580 581 582 583
 [ No26bitCode :LAND: ChocolateAMB
;  Instruction fetch abort pre-veneer, just to field possible lazy AMB aborts
;
PAbPreVeneer    ROUT
        Push    "r0-r7, lr"               ; wahey, we have an abort stack
        SUB     r0, lr_abort, #4          ; aborting address
584
        MOV     r2, #1
585 586 587 588
        BL      AMB_LazyFixUp             ; can trash r0-r7, returns NE status if claimed and fixed up
        Pull    "r0-r7, lr", NE           ; restore regs and
        SUBNES  pc, lr_abort, #4          ; restart aborting instruction if fixed up
        LDR     lr, [sp, #8*4]            ; (not a lazy abort) restore lr
Jeffrey Lee's avatar
Jeffrey Lee committed
589
        LDR     r0, =ZeroPage+PAbHan      ; we want to jump to PAb handler, in abort mode
590 591 592 593 594
        LDR     r0, [r0]
        STR     r0, [sp, #8*4]
        Pull    "r0-r7, pc"
 ]

Kevin Bracey's avatar
Kevin Bracey committed
595
 [ :LNOT:No26bitCode
Neil Turton's avatar
Neil Turton committed
596 597 598 599 600 601 602 603 604 605
; Instruction fetch abort pre-veneer

PAbPreVeneer    ROUT

        LDR     r13_abort, =PreVeneerRegDump
        STMIA   r13_abort, {r0-r7}
        MOV     r0, r13_abort

; for the time being just merge lr and psr

606
        MRS     r1, SPSR                                ; r1 = saved PSR
607 608 609 610 611

        LDR     r2, =Abort32_dumparea
        STMIA   r2, {r1,lr_abort}                       ;dump 32-bit PSR, fault address (PC)
        STR     lr_abort,[r2,#2*4]                      ;dump 32-bit PC

Neil Turton's avatar
Neil Turton committed
612 613 614 615 616
        AND     r2, r1, #&F0000003                      ; get saved NZCV and 26 bit modes
        ORR     lr_abort, lr_abort, r2
        AND     r2, r1, #I32_bit + F32_bit              ; extract I and F from new place
        ORR     r1, lr_abort, r2, LSL #IF32_26Shift     ; r1 = combined lr and psr

617
        MRS     r2, CPSR                ; now switch into SVC26
Neil Turton's avatar
Neil Turton committed
618 619
        BIC     r2, r2, #&1F
        ORR     r2, r2, #SVC26_mode
620
        MSR     CPSR_c, r2
Neil Turton's avatar
Neil Turton committed
621 622 623 624 625 626

        MOV     lr_svc, r1              ; lr_svc = PC + PSR from exception
        LDR     r1, =PAbHan
        LDR     r1, [r1]
        STR     r1, [r0, #8*4]
        LDMIA   r0, {r0-r7, pc}         ; jump to prefetch abort handler
Kevin Bracey's avatar
Kevin Bracey committed
627
 ]
Neil Turton's avatar
Neil Turton committed
628 629 630 631 632 633 634 635 636 637

; Preliminary layout of abort indirection nodes

        ^       0
AI_Link #       4
AI_Low  #       4
AI_High #       4
AI_WS   #       4
AI_Addr #       4

638 639
        EXPORT DAbPreVeneer

Neil Turton's avatar
Neil Turton committed
640 641
DAbPreVeneer    ROUT

Kevin Bracey's avatar
Kevin Bracey committed
642 643 644
 [ No26bitCode
        SUB     r13_abort, r13_abort, #17*4     ; we use stacks, dontcherknow
 |
Neil Turton's avatar
Neil Turton committed
645
        LDR     r13_abort, =PreVeneerRegDump
Kevin Bracey's avatar
Kevin Bracey committed
646
 ]
Neil Turton's avatar
Neil Turton committed
647 648 649
        STMIA   r13_abort, {r0-r7}              ; save unbanked registers anyway
        STR     lr_abort, [r13_abort, #15*4]    ; save old PC, ie instruction address

650 651
  [ ChocolateAMB
        ARM_read_FAR r0                         ; aborting address
652
        MOV     r2, #0
653 654 655 656 657 658 659
        BL      AMB_LazyFixUp                   ; can trash r0-r7, returns NE status if claimed and fixed up
        LDR     lr_abort, [r13_abort, #15*4]    ; restore lr_abort
        LDMIA   r13_abort, {r0-r7}              ; restore regs
        ADDNE   r13_abort, r13_abort, #17*4     ; if fixed up, restore r13_abort
        SUBNES  pc, lr_abort, #8                ; and restart aborting instruction
  ]

660 661
        MRS     r0, SPSR                        ; r0 = PSR when we aborted
        MRS     r1, CPSR                        ; r1 = CPSR
Neil Turton's avatar
Neil Turton committed
662 663
        ADD     r2, r13_abort, #8*4             ; r2 -> saved register bank for r8 onwards

Jeffrey Lee's avatar
Jeffrey Lee committed
664
        LDR     r4, =ZeroPage+Abort32_dumparea+3*4 ;use temp area (avoid overwriting main area for expected aborts)
665 666 667
        ARM_read_FAR r3
        STMIA   r4, {r0,r3,lr_abort}            ; dump 32-bit PSR, fault address, 32-bit PC

Neil Turton's avatar
Neil Turton committed
668 669 670 671
        MOV     r4, lr_abort                    ; move address of aborting instruction into an unbanked register
        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
672 673 674 675 676
  [ SASTMhatbroken
        STMEQIA r2!,{r8-r12}
        STMEQIA r2 ,{r13,r14}^
        SUBEQ   r2, r2, #5*4
  |
Neil Turton's avatar
Neil Turton committed
677
        STMEQIA r2, {r8-r14}^
678
  ]
Neil Turton's avatar
Neil Turton committed
679 680 681
        BEQ     %FT05

        ORR     r3, r3, r1                      ; and put in user's
682
        MSR     CPSR_c, r3                      ; switch to user's mode
Neil Turton's avatar
Neil Turton committed
683 684 685

        STMIA   r2, {r8-r14}                    ; save the banked registers

686
        MRS     r5, SPSR                        ; get the SPSR for the aborter's mode
Neil Turton's avatar
Neil Turton committed
687 688
        STR     r5, [r2, #8*4]                  ; and store away in the spare slot on the end
                                                ; (this is needed for LDM with PC and ^)
Kevin Bracey's avatar
Kevin Bracey committed
689 690
  [ No26bitCode
        ORR     r1, r1, #ABT32_mode
691
        MSR     CPSR_c, r1                      ; back to abort mode for the rest of this
Neil Turton's avatar
Neil Turton committed
692
05
Kevin Bracey's avatar
Kevin Bracey committed
693 694 695 696
        Push    "r0"                            ; save SPSR_abort
  |
05
        ORR     r1, r1, #SVC26_mode             ; then switch to SVC for the rest of this
697
        MSR     CPSR_c, r1
Neil Turton's avatar
Neil Turton committed
698
        Push    "r0, lr_svc"                    ; save SPSR_abort and lr_svc
Kevin Bracey's avatar
Kevin Bracey committed
699 700
  ]

701
  [ SASTMhatbroken
Kevin Bracey's avatar
Kevin Bracey committed
702 703
        SUB     sp, sp, #3*4
        STMIA   sp, {r13,r14}^                  ; save USR bank in case STM ^, and also so we can corrupt them
704
        NOP
Kevin Bracey's avatar
Kevin Bracey committed
705
        STMDB   sp!, {r8-r12}
706
  |
Kevin Bracey's avatar
Kevin Bracey committed
707 708
        SUB     sp, sp, #8*4                    ; make room for r8_usr to r14_usr and PC
        STMIA   sp, {r8-r15}^                   ; save USR bank in case STM ^, and also so we can corrupt them
709
  ]
Neil Turton's avatar
Neil Turton committed
710 711

        SUB     r11, r2, #8*4                   ; r11 -> register bank
Kevin Bracey's avatar
Kevin Bracey committed
712
        STR     r4, [sp, #7*4]                  ; store aborter's PC in user register bank
Neil Turton's avatar
Neil Turton committed
713

Jeffrey Lee's avatar
Jeffrey Lee committed
714
 [ UseProcessTransfer
Kevin Bracey's avatar
Kevin Bracey committed
715 716 717
        TST     r0, #T32_bit                    ; were they in Thumb mode? if so, give up now
        BNE     %FT90

718 719 720
;ARMv4+ allow half-word load/stores - not supported at present
;ARMv5TE+ allow double-word load/stores - not supported at present
;ARMv6 allow load/store exclusive - not supported at present
Neil Turton's avatar
Neil Turton committed
721
        LDR     r10, [r4, #-8]!                 ; r10 = actual instruction that aborted, and r4 points to it
722 723
        AND     r9, r10, #2_1110 :SHL: 24
        TEQ     r9, #2_1000 :SHL: 24            ; test for LDM/STM
Neil Turton's avatar
Neil Turton committed
724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
        BNE     %FT50                           ; if not LDM/STM, then it's an "easy" LDR/STR

 [ DebugAborts
        DLINE   "It's an LDM/STM"
 ]

; First count the number of transferred registers, and undo any writeback

        MOV     r9, #0                          ; r9 = no. of registers in list
        MOVS    r8, r10, LSL #16
        BEQ     %FT20
10
        MOVS    r8, r8, LSL #1
        ADDCS   r9, r9, #1
        BNE     %BT10
20
        MOV     r8, r10, LSR #16
        AND     r8, r8, #&0F                    ; base register number
        LDR     r7, [r11, r8, LSL #2]           ; ------""----- value

        TST     r10, #1 :SHL: 23                ; test up/down
Neil Turton's avatar
Neil Turton committed
745 746 747 748 749
        MOVNE   r1, r9                          ; if up, r1 = +ve no. of regs
        RSBEQ   r1, r9, #0                      ; if down, r1 = -ve no. of regs

;initially assume writeback
;we want r6 = base reg value before assumed writeback (r7 is base reg value after abort)
750 751
;writeback will have been performed for ARMs with CPUFlag_BaseRestored clear
;
Jeffrey Lee's avatar
Jeffrey Lee committed
752
        LDR     r6, =ZeroPage
753 754 755 756
        LDR     r6, [r6, #ProcessorFlags]
        TST     r6, #CPUFlag_BaseRestored
        MOVNE   r6, r7
        SUBEQ   r6, r7, r1, ASL #2
Neil Turton's avatar
Neil Turton committed
757 758 759

;now we want r6 to be the base register value before the abort, so we will discard
;our adjusted value and take r7, if the instruction in fact had no writeback
760
;
Neil Turton's avatar
Neil Turton committed
761 762
        TST     r10, #1 :SHL: 21                ; test if write-back bit set
        TEQNE   r8, #15                         ; (if base is PC then write-back not allowed)
Neil Turton's avatar
Neil Turton committed
763
        MOVEQ   r6, r7                          ; if not wb, reg after abort is correct
Neil Turton's avatar
Neil Turton committed
764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812

        MOV     r1, sp                          ; r1 -> end of stack frame, and start of user-mode register bank
        SUB     sp, sp, r9, LSL #2              ; make stack frame for registers
        TST     r10, #1 :SHL: 20                ; if its an STM, we have to load up the stack frame
        BNE     %FT30                           ; but if it's an LDM, we call trap routine first

        STR     r6, [r11, r8, LSL #2]           ; store original base in register list, to be overwritten after 1st transfer

; now go through registers, storing them into frame

        MOV     r5, sp                          ; pointer to position in stack frame
        MOV     lr, r10, LSL #16                ; extract bottom 16 bits
        MOVS    lr, lr, LSR #16                 ; ie bitmask of which registers r0-r15 stored
        BEQ     %FT30                           ; this shouldn't happen (it's illegal)

        MOV     r3, r11                         ; current pointer into register bank
21
        TST     r10, #1 :SHL: 22                ; is it STM with ^
        ANDNE   lr, lr, #&FF                    ; if so then extract bottom 8 bits (r0-r7 on 1st pass, r8-r15 on 2nd)
22
        MOVS    lr, lr, LSR #1                  ; shift bit into carry
        LDRCS   r2, [r3], #4                    ; if set bit then transfer word from register bank
        STRCS   r2, [r5], #4                    ; into stack frame
        STRCS   r7, [r11, r8, LSL #2]           ; and after 1st transfer, store updated base into register bank
        ADDCC   r3, r3, #4                      ; else just increment register bank pointer
        BNE     %BT22                           ; if more bits to do, then loop

        TEQ     r5, r1                          ; have we done all registers?
        MOVNE   lr, r10, LSR #8                 ; no, then must have been doing STM with ^, and have some user-bank regs to store
        MOVNE   r3, r1                          ; so point r3 at user-mode register bank
        BNE     %BT21                           ; and go back into loop

30

; now work out address of 1st transfer

        ANDS    r5, r10, #(3 :SHL: 23)          ; bit 24 set => pre, bit 23 set => inc
        SUBEQ   r2, r6, r9, LSL #2              ; if post-dec, then 1st address = initial-nregs*4+4
        ADDEQ   r2, r2, #4
        BEQ     %FT32

        CMP     r5, #2 :SHL: 23
        MOVCC   r2, r6                          ; CC => post-inc, so 1st address = initial
        SUBEQ   r2, r6, r9, LSL #2              ; EQ => pre-dec,  so 1st address = initial-nregs*4
        ADDHI   r2, r6, #4                      ; HI => pre-inc,  so 1st address = initial+4
32
        ANDS    r0, r10, #1 :SHL: 20            ; r0 = 0 => STM
        MOVNE   r0, #1                          ;    = 1 => LDM
        LDR     r1, [r1, #8*4]                  ; get SPSR_abort
813
        TST     r1, #&F                         ; test if transfer took place in USR mode
Neil Turton's avatar
Neil Turton committed
814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842
        ORRNE   r0, r0, #2                      ; if not then set bit 1 of flags word in r0
        MOV     r1, sp                          ; block to transfer from/into
        BIC     r2, r2, #3                      ; LDM/STM always present word-aligned address
        MOV     r3, r9, LSL #2                  ; length of transfer in bytes, and r4 still points to aborting instruction
        BL      ProcessTransfer
        ADDVS   sp, sp, r9, LSL #2              ; if invalid transfer then junk stack frame
        BVS     %FT90                           ; and generate an exception

; we transferred successfully, so now check if LDM and load up register bank from block

        TST     r10, #1 :SHL: 20
        ADDEQ   sp, sp, r9, LSL #2              ; it's an STM, so junk stack frame and tidy up
        BEQ     %FT70

; now go through registers, loading them from frame

        ADD     r1, sp, r9, LSL #2              ; r1 -> end of stack frame, and start of user-mode bank registers
        MOV     r5, sp                          ; pointer to position in stack frame
        MOV     r4, r10, LSL #16                ; extract bottom 16 bits
        MOVS    r4, r4, LSR #16                 ; ie bitmask of which registers r0-r15 stored
        BEQ     %FT40                           ; this shouldn't happen (it's illegal)

        SUB     r3, r1, #8*4                    ; r3 -> notional start of user bank, if it began at r0 (it actually starts at r8)
        MOV     r0, #0                          ; assume no user registers by default
        TST     r10, #1 :SHL: 15                ; is PC in list
        BNE     %FT34                           ; then can't be LDM of user bank
        TST     r10, #1 :SHL: 22                ; is it LDM with ^
        BEQ     %FT34                           ; no, then use main bank for all registers
        LDR     r2, [r1, #8*4]                  ; get SPSR
Kevin Bracey's avatar
Kevin Bracey committed
843
        ANDS    r2, r2, #15                     ; get bottom 4 bits of mode (EQ => USR26 or USR32)
Neil Turton's avatar
Neil Turton committed
844 845 846 847 848 849 850
        BEQ     %FT34                           ; if USR mode then use main bank for all
        TEQ     r2, #FIQ26_mode                 ; if FIQ mode then put r8-r14 in user bank
        LDREQ   lr, =&7F00                      ; then put r8-r14 in user bank
        LDRNE   lr, =&6000                      ; else put r13,r14 in user bank
        AND     r0, r4, lr                      ; r0 = mask of registers to put into user bank
        BIC     r4, r4, lr                      ; r4 = mask of registers to put into main bank
34
Jeffrey Lee's avatar
Jeffrey Lee committed
851 852
        MOV     lr, #0
35
Neil Turton's avatar
Neil Turton committed
853 854 855 856 857 858 859 860
        MOVS    r4, r4, LSR #1                  ; shift bit into carry
        LDRCS   r2, [r5], #4                    ; if set bit then transfer word from stack frame
        STRCS   r2, [r11, lr, LSL #2]           ; into main register bank
        MOVS    r0, r0, LSR #1                  ; shift bit into carry
        LDRCS   r2, [r5], #4                    ; if set bit then transfer word from stack frame
        STRCS   r2, [r3, lr, LSL #2]            ; into user register bank
        ADD     lr, lr, #1
        ORRS    r6, r0, r4                      ; have we finished both banks?
Jeffrey Lee's avatar
Jeffrey Lee committed
861
        BNE     %BT35                           ; no, then loop
Neil Turton's avatar
Neil Turton committed
862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878

; If LDM with PC in list, then add 4 to it, so the exit procedure is the same as if PC not loaded
; Also, if it was an LDM with PC and ^, then we have to update the stacked SPSR

40
        MOV     sp, r1                          ; junk frame

        TST     r10, #1 :SHL: 15                ; check PC in list
        ADDNE   r2, r2, #4                      ; since PC is last, r2 will still hold the value loaded
        STRNE   r2, [r11, #15*4]                ; store back into main register bank
        TSTNE   r10, #1 :SHL: 22                ; now check LDM ^
        BEQ     %FT70                           ; [not LDM with PC in list]

        LDR     r9, [sp, #8*4]                  ; get SPSR_abort
        AND     r8, r9, #&1F                    ; r8 = aborter's mode
        TEQ     r8, #USR32_mode                 ; if in USR32
        BEQ     %FT70                           ; then the ^ has no effect (actually uses CPSR)
Kevin Bracey's avatar
Kevin Bracey committed
879
        TST     r8, #&1C                        ; if 32-bit mode
Neil Turton's avatar
Neil Turton committed
880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897
        LDRNE   r7, [r11, #16*4]                ; then use SPSR for the aborter's mode else use updated r15 in r2 (26-bit format)
        ANDEQ   r7, r2, #&F0000003              ; flag and mode bits in same place
        ANDEQ   r2, r2, #&0C000000              ; but I and F have to move to bits 7 and 6
        ORREQ   r7, r7, r2, LSR #(26-6)

; r7 is now desired PSR (in 32-bit format) to update to
; now check which bits can actually be updated

        TEQ     r8, #USR26_mode
        BICEQ   r9, r9, #&F0000000              ; if USR26 then we can only update NZCV
        ANDEQ   r7, r7, #&F0000000
        ORREQ   r9, r9, r7
        MOVNE   r9, r7                          ; else can update all bits
        STR     r9, [sp, #8*4]                  ; store back updated SPSR_abort (to become CPSR)
        B       %FT70                           ; now tidy up

50

898
; it's an LDR/STR
Neil Turton's avatar
Neil Turton committed
899

900 901
        TEQ     r9, #2_0000 :SHL: 24            ; is it the extra load/store family?
        BNE     %FT55                           ; no, plain LDR[B]
Neil Turton's avatar
Neil Turton committed
902
 [ DebugAborts
903 904 905 906 907 908 909 910 911
        DLINE   "It's LDR[EX|SB|H|SH|D]/STR[EX|H|D]"
 ]
        AND     r9, r10, #2_1111 :SHL: 4
        TEQ     r9, #2_1101 :SHL: 4
        BNE     %FT90                           ; Abort if LDR[EX|H|SH]/STR[EX|H|D]
        TST     r10, #1 :SHL: 20
        BEQ     %FT90                           ; Abort if LDRD (encoded where STRSB would be)

        TST     r10, #1 :SHL: 22                ; if immediate
Robert Sprowson's avatar
Robert Sprowson committed
912
        BICNE   r9, r10, #2_1111 :SHL: 4
913 914 915 916 917 918 919 920 921 922 923 924 925 926
        ORRNE   r9, r9, r9, LSR #4
        ANDNE   r9, r9, #&FF                    ; then extract imm8 bits
        ANDEQ   r8, r10, #&0F                   ; register offset
        LDREQ   r9, [r11, r8, LSL #2]           ; get actual value of register
        ORR     r10, r10, #1 :SHL: 22           ; ensure it looks like a byte access
        B       %FT60
        ; We've effectively reencoded the weird load/stores to look like
        ; cccc 0zxp ubwl nnnn tttt xxxx xxxx xxxx
        ; z = zero/sign extend     b = byte/word
        ; p = pre/post             l = load/store
        ; u = up/down              x = don't care from here on
55
 [ DebugAborts
        DLINE   "It's an LDR[B]/STR[B]"
Neil Turton's avatar
Neil Turton committed
927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958
 ]
        TST     r10, #1 :SHL: 25                ; if immediate
        MOVEQ   r9, r10, LSL #(31-11)           ; then extract bottom 12 bits
        MOVEQ   r9, r9, LSR #(31-11)
        BEQ     %FT60

        AND     r8, r10, #&0F                   ; register to shift
        LDR     r9, [r11, r8, LSL #2]           ; get actual value of register

        MOV     r8, r10, LSR #7                 ; extract shift amount
        ANDS    r8, r8, #&1F                    ; (bits 7..11)
        MOVEQ   r8, #32                         ; if zero then make 32

        ANDS    r7, r10, #&60
        ANDEQ   r8, r8, #&1F                    ; LSL 0 is really zero
        MOVEQ   r9, r9, LSL r8
        TEQ     r7, #&20
        MOVEQ   r9, r9, LSR r8
        TEQ     r7, #&40
        MOVEQ   r9, r9, ASR r8
        TEQ     r7, #&60
        MOVEQ   r9, r9, ROR r8                  ; if 32 then we haven't spoilt it!
        TEQEQ   r8, #32                         ; if ROR #32 then really RRX
        BNE     %FT60
        LDR     r7, [sp, #8*4]                  ; get SPSR
        AND     r7, r7, #C_bit
        CMP     r7, #1                          ; set carry from original user
        MOV     r9, r9, RRX
60
        TST     r10, #1 :SHL: 23                ; test for up/down
        RSBEQ   r9, r9, #0                      ; if down then negate

Jeffrey Lee's avatar
Jeffrey Lee committed
959
        LDR     r8, =ZeroPage
960 961 962 963
        LDR     r8, [r8, #ProcessorFlags]
        TST     r8, #CPUFlag_BaseRestored
        BNE     %FT62
;not base restored
Neil Turton's avatar
Neil Turton committed
964 965 966 967 968 969 970 971 972
        TST     r10, #1 :SHL: 21                ; if write-back
        MOVNE   r8, #0                          ; then no post-inc
        RSBEQ   r8, r9, #0                      ; else post-inc = - pre-inc
        ADD     r0, r8, r9                      ; amount to subtract off base register for correction

        TST     r10, #1 :SHL: 24                ; however, if we're doing post-increment
        MOVEQ   r8, r9                          ; then post-inc = what was pre-inc
        MOVEQ   r0, r9                          ; and adjustment is what was added on
        RSB     r9, r8, #0                      ; and pre-inc = -post-inc
Neil Turton's avatar
Neil Turton committed
973 974
        B       %FT63
62
975
;base restored
Neil Turton's avatar
Neil Turton committed
976 977 978 979 980 981 982 983
        TST     r10, #1 :SHL: 21                ; if write-back
        MOVNE   r8, #0                          ; then no post-inc
        RSBEQ   r8, r9, #0                      ; else post-inc = - pre-inc

        TST     r10, #1 :SHL: 24                ; however, if we're doing post-increment
        MOVEQ   r8, r9                          ; then post-inc = what was pre-inc
        MOVEQ   r9, #0                          ; and pre-inc = 0

Neil Turton's avatar
Neil Turton committed
984
63
Neil Turton's avatar
Neil Turton committed
985 986 987 988
        MOV     r7, r10, LSL #31-19
        MOV     r7, r7, LSR #28                 ; r7 = base register number
        LDR     r6, [r11, r7, LSL #2]           ; r6 = base register value

Jeffrey Lee's avatar
Jeffrey Lee committed
989
        LDR     r1, =ZeroPage
990 991 992 993
        LDR     r1, [r1, #ProcessorFlags]
        TST     r1, #CPUFlag_BaseRestored
        SUBEQ   r0, r6, r0                      ; compute adjusted base register (if not base restored)
        STREQ   r0, [r11, r7, LSL #2]           ; and store back in case we decide to abort after all
Neil Turton's avatar
Neil Turton committed
994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018

; no need to clear PSR bits out of R15, because PSR is separate

        ADD     r9, r9, r6                      ; r2 = offset+base = illegal address

 [ DebugAborts
        DREG    r9, "Aborting address = "
        DREG    r8, "Post-increment = "
        DREG    r4, "Instruction where abort happened = "
 ]

        ANDS    r0, r10, #1 :SHL: 20            ; if an LDR then bit 20 set
        MOVNE   r0, #1                          ; so make 1
        SUBNE   sp, sp, #4                      ; then just create 1 word stack frame
        BNE     %FT65

        MOV     r5, r10, LSR #12                ; else it's an STR (r0 = 0)
        AND     r5, r5, #&0F                    ; r5 = source register number
        LDR     r5, [r11, r5, LSL #2]           ; r5 = value of source register
 [ DebugAborts
        DREG    r5, "Data value to store = "
 ]
        Push    "r5"                            ; create stack frame with this value in it
65
        LDR     r1, [sp, #(1+8)*4]              ; get SPSR_abort
1019
        TST     r1, #&F                         ; test if transfer took place in USR mode
Neil Turton's avatar
Neil Turton committed
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
        ORRNE   r0, r0, #2                      ; if not then set bit 1 of flags word in r0

        MOV     r1, sp                          ; r1 -> data block
        TST     r10, #1 :SHL: 22                ; if byte transfer
        MOVNE   r3, #1                          ; then length of transfer = 1
        MOVNE   r2, r9                          ; and use unmolested address
        MOVEQ   r3, #4                          ; else length = 4
        BICEQ   r2, r9, #3                      ; and mask out bottom 2 bits of address

        BL      ProcessTransfer
        ADDVS   sp, sp, #4                      ; if illegal transfer, junk stack frame
        BVS     %FT90                           ; and cause exception

        ADD     r6, r9, r8                      ; update base register with offset
        STR     r6, [r11, r7, LSL #2]           ; and store back (NB if LDR and dest=base, the load overwrites the updated base)

        TST     r10, #1 :SHL: 20                ; if it's STR (not LDR)
        ADDEQ   sp, sp, #4                      ; then junk stack frame
        BEQ     %FT70                           ; and tidy up

1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
        Pull    "r6"                            ; LDR/LDRB/LDRSB: get value to load into register
        TST     r10, #1 :SHL: 22
        BEQ     %FT67
        TST     r10, #1 :SHL: 26                ; LDRB: see if zero fill or sign extend is needed
        MOVEQ   r6, r6, LSL #24
        MOVEQ   r6, r6, ASR #24                 ; fill with b7
        ANDNE   r6, r6, #&FF                    ; fill with zero
        B       %FT69
67
        AND     r9, r9, #3                      ; LDR: rotate word to correct position - r9 = bottom 2 bits of address
        MOV     r9, r9, LSL #3                  ; multiply by 8 to get rotation factor
        MOV     r6, r6, ROR r9                  ; rotate to correct position in register
69
Neil Turton's avatar
Neil Turton committed
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067
        MOV     r5, r10, LSR #12                ; test for LDR PC
        AND     r5, r5, #&0F                    ; r5 = dest register number
        TEQ     r5, #15                         ; if PC
        ADDEQ   r6, r6, #4                      ; then adjust for abort exit
        STR     r6, [r11, r5, LSL #2]           ; store into register bank

70

; Tidy up routine, common to LDR/STR and LDM/STM

        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^
        ADD     sp, sp, #8*4                    ; junk user bank stack frame

Kevin Bracey's avatar
Kevin Bracey committed
1068 1069
 [ No26bitCode
        Pull    "r0"                            ; r0 = (possibly updated) SPSR_abort
1070
        MRS     r1, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
1071
 |
Neil Turton's avatar
Neil Turton committed
1072 1073 1074
        Pull    "r0, lr"                        ; r0 = (possibly updated) SPSR_abort, restore lr_svc

        SetMode ABT32_mode, r1                  ; leaves r1 = current PSR
Kevin Bracey's avatar
Kevin Bracey committed
1075
 ]
Neil Turton's avatar
Neil Turton committed
1076

1077
        MRS     r6, SPSR                        ; get original SPSR, with aborter's original mode
Kevin Bracey's avatar
Kevin Bracey committed
1078 1079
        AND     r7, r6, #&0F
        TEQ     r7, #USR26_mode                 ; also matches USR32
Neil Turton's avatar
Neil Turton committed
1080 1081 1082 1083 1084
        LDMEQIA r2, {r8-r14}^                   ; if user mode then just use ^ to reload registers
        NOP
        BEQ     %FT80

        ORR     r6, r6, #I32_bit                ; use aborter's flags and mode but set I
Kevin Bracey's avatar
Kevin Bracey committed
1085
        BIC     r6, r6, #T32_bit                ; and don't set Thumb bit
1086
        MSR     CPSR_c, r6                      ; switch to aborter's mode
Neil Turton's avatar
Neil Turton committed
1087
        LDMIA   r2, {r8-r14}                    ; reload banked registers
1088
        MSR     CPSR_c, r1                      ; switch back to ABT32
Neil Turton's avatar
Neil Turton committed
1089 1090 1091

80
        LDR     lr_abort, [r13_abort, #15*4]    ; get PC to return to
1092
        MSR     SPSR_cxsf, r0                   ; set up new SPSR (may have changed for LDM {PC}^)
Neil Turton's avatar
Neil Turton committed
1093 1094

        LDMIA   r13_abort, {r0-r7}              ; reload r0-r7
Kevin Bracey's avatar
Kevin Bracey committed
1095 1096 1097
 [ No26bitCode
        ADD     r13_abort, r13_abort, #17*4     ; we use stacks, dontcherknow
 ]
Neil Turton's avatar
Neil Turton committed
1098 1099 1100
        SUBS    pc, lr_abort, #4                ; go back 8 to adjust for PC being 2 words out,
                                                ; then forward 4 to skip instruction we've just executed

Jeffrey Lee's avatar
Jeffrey Lee committed
1101 1102
 ] ; UseProcessTransfer

Neil Turton's avatar
Neil Turton committed
1103 1104 1105 1106
; Call normal exception handler

90

1107 1108
; copy temp area to real area (we believe this is an unexpected data abort now)

Jeffrey Lee's avatar
Jeffrey Lee committed
1109
        LDR     r0, =ZeroPage+Abort32_dumparea
1110 1111 1112 1113 1114 1115 1116
        LDR     r1, [r0,#3*4]
        STR     r1, [r0]
        LDR     r1, [r0,#4*4]
        STR     r1, [r0,#4]
        LDR     r1, [r0,#5*4]
        STR     r1, [r0,#2*4]

Kevin Bracey's avatar
Kevin Bracey committed
1117
 [ No26bitCode
Jeffrey Lee's avatar
Jeffrey Lee committed
1118 1119
        LDR     r0, =ZeroPage                           ; we're going to call abort handler
      [ ZeroPage = 0
Kevin Bracey's avatar
Kevin Bracey committed
1120
        STR     r0, [r0, #CDASemaphore]                 ; so allow recovery if we were in CDA
Jeffrey Lee's avatar
Jeffrey Lee committed
1121 1122 1123 1124
      |
        MOV     r2, #0
        STR     r2, [r0, #CDASemaphore]                 ; so allow recovery if we were in CDA
      ]
Kevin Bracey's avatar
Kevin Bracey committed
1125

Jeffrey Lee's avatar
Jeffrey Lee committed
1126
        LDR     r0, [r0, #DAbHan]                       ; get address of data abort handler
Kevin Bracey's avatar
Kevin Bracey committed
1127 1128 1129 1130 1131 1132 1133 1134 1135
 [ DebugAborts
        DREG    r0, "Handler address = "
 ]

        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^
        ADD     sp, sp, #9*4                    ; junk user bank stack frame + saved SPSR

1136
        MRS     r1, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
1137

1138
        MRS     r6, SPSR                        ; get original SPSR, with aborter's original mode
Kevin Bracey's avatar
Kevin Bracey committed
1139 1140 1141 1142 1143 1144 1145 1146
        AND     r7, r6, #&0F
        TEQ     r7, #USR26_mode                 ; also matches USR32
        LDMEQIA r2, {r8-r14}^                   ; if user mode then just use ^ to reload registers
        NOP
        BEQ     %FT80

        ORR     r6, r6, #I32_bit                ; use aborter's flags and mode but set I
        BIC     r6, r6, #T32_bit                ; and don't set Thumb
1147
        MSR     CPSR_c, r6                      ; switch to aborter's mode
Kevin Bracey's avatar
Kevin Bracey committed
1148
        LDMIA   r2, {r8-r14}                    ; reload banked registers
1149
        MSR     CPSR_c, r1                      ; switch back to ABT32
Kevin Bracey's avatar
Kevin Bracey committed
1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160

80
        STR     r0, [r13_abort, #16*4]          ; save handler address at top of stack
        LDR     lr_abort, [r13_abort, #15*4]    ; get abort address back in R14

        LDMIA   r13_abort, {r0-r7}              ; reload r0-r7
        ADD     r13_abort, r13_abort, #16*4     ; we use stacks, dontcherknow

        Pull    pc

 |
Neil Turton's avatar
Neil Turton committed
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184
; for the time being just merge lr and psr

        LDR     r0, [sp, #8*4]                          ; r0 = original SPSR (can't have been modified)

        LDR     lr, [r11, #15*4]                        ; get PC of aborter
        AND     r1, r0, #&F0000000                      ; get saved NZCV
        ORR     lr, lr, r1
        AND     r1, r0, #I32_bit + F32_bit              ; extract I and F from new place
        ORR     lr, lr, r1, LSL #IF32_26Shift           ; and merge
        AND     r1, r0, #3                              ; get old mode bits (have to assume a 26-bit mode!)
        ORR     lr, lr, r1                              ; lr = combined lr and psr
        STR     lr, [sp, #9*4]                          ; overwrite stacked lr_svc
        TEQ     r1, #SVC26_mode                         ; if aborter was in SVC mode
        STREQ   lr, [r11, #14*4]                        ; then also overwrite r14 in aborter's register bank

        BIC     r0, r0, #&1F                            ; clear mode bits in SPSR
        ORR     r0, r0, #SVC26_mode :OR: I32_bit        ; and force SVC26 with I set
 [ DebugAborts
        DLINE   "Going to call data abort handler"
        DREG    lr, "lr_svc will be "
        DREG    r0, "PSR going to exit with = "
 ]
        STR     r0, [sp, #8*4]                          ; overwrite stacked SPSR

Jeffrey Lee's avatar
Jeffrey Lee committed
1185 1186
        LDR     r0, =ZeroPage                           ; we're going to call abort handler
      [ ZeroPage = 0
Neil Turton's avatar
Neil Turton committed
1187
        STR     r0, [r0, #CDASemaphore]                 ; so allow recovery if we were in CDA
Jeffrey Lee's avatar
Jeffrey Lee committed
1188 1189 1190 1191
      |
        MOV     r2, #0
        STR     r2, [r0, #CDASemaphore]                 ; so allow recovery if we were in CDA
      ]
Neil Turton's avatar
Neil Turton committed
1192

Jeffrey Lee's avatar
Jeffrey Lee committed
1193 1194
        LDR     r0, =ZeroPage+DAbHan
        LDR     r0, [r0, #DAbHan]                       ; get address of data abort handler
Neil Turton's avatar
Neil Turton committed
1195 1196 1197 1198 1199 1200
 [ DebugAborts
        DREG    r0, "Handler address = "
 ]
        ADD     r0, r0, #4                              ; add on 4 to adjust for abort exit
        STR     r0, [r11, #15*4]                        ; and store in pc in register bank
        B       %BT70                                   ; then junk to normal tidy-up routine
Jeffrey Lee's avatar
Jeffrey Lee committed
1201 1202 1203
 ]

 [ UseProcessTransfer
Neil Turton's avatar
Neil Turton committed
1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;       ProcessTransfer - Process an abort transfer
;
; in:   r0 = flags
;               bit 0 = 0 => Store to memory
;                       1 => Load from memory
;               bit 1 = 0 => Transfer executed in user mode
;                       1 => Transfer executed in non-user mode
;       r1 = block of data to transfer from/into
;       r2 = illegal address
;       r3 = length of transfer in bytes
;       r4 -> instruction which aborted
Kevin Bracey's avatar
Kevin Bracey committed
1218
;       SVC26/32 mode
Neil Turton's avatar
Neil Turton committed
1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233
;
; out:  V=0 => transfer accomplished
;       V=1 => transfer not accomplished
;       All registers preserved
;

SectionSizeShift *      20
SectionSize     *       1 :SHL: SectionSizeShift

LargePageSizeShift *    16
LargePageSize   *       1 :SHL: LargePageSizeShift

SmallPageSizeShift *    12
SmallPageSize   *       1 :SHL: SmallPageSizeShift

1234
ProcessTransfer Entry "r1-r7,r12"
Neil Turton's avatar
Neil Turton committed
1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286

 [ DebugAborts
        DLINE   "ProcessTransfer entered"
        DREG    r2, "Illegal address = "
        DREG    r3, "Length of transfer = "
        DREG    r4, "Abort happened at address "
        DREG    r0, "Flags = "
        DLINE   "Data = ",cc

        MOV     r5, r3
        MOV     r6, r1
01
        LDR     r7, [r6], #4
        DREG    r7," ",cc
        SUBS    r5, r5, #4
        BHI     %BT01
        DLINE   ""
 ]


; First identify if start address should have aborted

10
        LDR     r7, =L1PT
        MOV     lr, r2, LSR #SectionSizeShift           ; r2 as a multiple of 1Mb
        EOR     r5, r2, lr, LSL #SectionSizeShift       ; r5 = offset within section
        SUB     r5, r2, r5                              ; r5 -> start of section containing r2
        ADD     r5, r5, #SectionSize                    ; r5 -> start of section after r2

        LDR     lr, [r7, lr, LSL #2]                    ; get L1PT entry
        ANDS    r7, lr, #3                              ; 00 => trans.fault, 01 => page, 10 => section, 11 => reserved (fault)
        TEQNE   r7, #3
        BEQ     Fault
        TEQ     r7, #1
        BEQ     CheckPage

; it's section mapped - check section access privileges

15
        ANDS    r7, lr, #3 :SHL: 10                     ; extract ap
        BEQ     Fault                                   ; 00 => no access for anyone (at the moment)
        TST     r0, #2                                  ; test for non-usr access
        BNE     %FT20                                   ; if non-usr then OK to access here
        CMP     r7, #2 :SHL: 10
        BCC     Fault                                   ; 01 => no usr access
        BHI     %FT20                                   ; 11 => full user access, so OK
        TST     r0, #1
        BEQ     Fault                                   ; 10 => usr read-only, so stores not allowed

; access OK, so copy up to end of section/sub-page

20
Neil Turton's avatar
Neil Turton committed
1287 1288
;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
1289
;In fact, StrongARM does not abort (optional in architecture 4), but ARM 8 does - MJS 08-10-96
Neil Turton's avatar
Neil Turton committed
1290
  [ {FALSE}
Neil Turton's avatar
Neil Turton committed
1291 1292
        TST     r0, #1                                  ; if load from memory
        BNE     %FT60                                   ; then skip
Neil Turton's avatar
Neil Turton committed
1293
  ]
Neil Turton's avatar
Neil Turton committed
1294

Neil Turton's avatar
Neil Turton committed
1295
; it's a store to memory (may be a vector write), or a read from memory (may be a vector read)
Neil Turton's avatar
Neil Turton committed
1296 1297 1298
; do it in words if >= 4 bytes, so word writes to VIDC work for example

25
Jeffrey Lee's avatar
Jeffrey Lee committed
1299
        ASSERT  (:LNOT: HiProcVecs) ; Needs updating for high vectors!
Neil Turton's avatar
Neil Turton committed
1300
        CMP     r2, #&1C                                ; if in abort area (but allow any access to &1C)
1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312
  [ OnlyKernelCanAccessHardwareVectors
        BHS     %FT22
        CMP     r4, #ROM                                ; and executing outside the kernel
        BLO     %FT23
        ADRL    lr, EndOfKernel
        CMP     r4, lr
        BLO     %FT22
23
        MOV     r5, #&20                                ; then set end-of-section = 32
        B       Fault                                   ; and check user list
22
  |
Neil Turton's avatar
Neil Turton committed
1313 1314 1315
        CMPCC   r4, #ROM                                ; and executing out of RAM
        MOVCC   r5, #&20                                ; then set end-of-section = 32
        BCC     Fault                                   ; and check user list
1316
  ]
Neil Turton's avatar
Neil Turton committed
1317

Kevin Bracey's avatar
Kevin Bracey committed
1318
  [ :LNOT:No26bitCode
Neil Turton's avatar
Neil Turton committed
1319
        SetMode SVC32_mode, lr                          ; go into SVC32 so we can poke or peek vector area
Kevin Bracey's avatar
Kevin Bracey committed
1320
  ]
Neil Turton's avatar
Neil Turton committed
1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343

        TST     r0, #1                                  ; test for peek/poke
        BEQ     %FT30
26
;peeking
        TEQ     r2, r5                                  ; have we gone onto a new block?
        BEQ     %FT50                                   ; if so then exit if finished else go back to outer loop
        SUBS    r3, r3, #4                              ; have we got at least a word to do?
        LDRCS   lr, [r2], #4                            ; if so then copy word
        STRCS   lr, [r1], #4
        BHI     %BT26                                   ; and if not all done then loop
        BEQ     %FT50                                   ; if all done then switch back to SVC26 and exit

        ADDS    r3, r3, #4
27
        LDRB    lr, [r2], #1                            ; read byte from register bank
        STRB    lr, [r1], #1                            ; and store to memory
        SUBS    r3, r3, #1                              ; decrement byte count
        BEQ     %FT50                                   ; if finished then switch back to SVC26 and exit
        TEQ     r2, r5                                  ; have we gone onto a new block?
        BNE     %BT27                                   ; no, then loop
        B       %FT50

Neil Turton's avatar
Neil Turton committed
1344
30
Neil Turton's avatar
Neil Turton committed
1345
;poking
Neil Turton's avatar
Neil Turton committed
1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363
        TEQ     r2, r5                                  ; have we gone onto a new block?
        BEQ     %FT50                                   ; if so then exit if finished else go back to outer loop
        SUBS    r3, r3, #4                              ; have we got at least a word to do?
        LDRCS   lr, [r1], #4                            ; if so then copy word
        STRCS   lr, [r2], #4
        BHI     %BT30                                   ; and if not all done then loop
        BEQ     %FT50                                   ; if all done then switch back to SVC26 and exit

        ADDS    r3, r3, #4
40
        LDRB    lr, [r1], #1                            ; read byte from register bank
        STRB    lr, [r2], #1                            ; and store to memory
        SUBS    r3, r3, #1                              ; decrement byte count
        BEQ     %FT50                                   ; if finished then switch back to SVC26 and exit
        TEQ     r2, r5                                  ; have we gone onto a new block?
        BNE     %BT40                                   ; no, then loop

50
Kevin Bracey's avatar
Kevin Bracey committed
1364
  [ :LNOT:No26bitCode
Neil Turton's avatar
Neil Turton committed
1365
        SetMode SVC26_mode, lr
Kevin Bracey's avatar
Kevin Bracey committed
1366
  ]
Neil Turton's avatar
Neil Turton committed
1367 1368 1369 1370
        CMP     r3, #0
        BNE     %BT10
        EXIT                                            ; exit (VC from CMP)

Neil Turton's avatar
Neil Turton committed
1371
  [ {FALSE}
Neil Turton's avatar
Neil Turton committed
1372 1373 1374 1375 1376 1377 1378 1379 1380
; it's a load from memory
60
        LDRB    lr, [r2], #1                            ; read byte from memory
        STRB    lr, [r1], #1                            ; and store to memory bank
        SUBS    r3, r3, #1                              ; decrement byte count
        EXIT    EQ                                      ; if finished then exit (VC from SUBS)
        TEQ     r2, r5                                  ; have we gone onto a new block?
        BNE     %BT60                                   ; no, then loop
        B       %BT10                                   ; yes, then go back to start
Neil Turton's avatar
Neil Turton committed
1381
  ]
Neil Turton's avatar
Neil Turton committed
1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393

; it's page mapped, so check L2PT
; lr = L1 table entry
; We use the logical copy of physical space here, in order to access the entry pointed to by the L1 entry

CheckPage
        MOV     r5, r2, LSR #SmallPageSizeShift         ; r2 as a multiple of 4K
        MOV     r5, r5, LSL #SmallPageSizeShift
        ADD     r5, r5, #SmallPageSize                  ; if translation fault, then it applies to small page

        MOV     lr, lr, LSR #10                         ; remove domain and U bits
        MOV     lr, lr, LSL #10
1394 1395 1396 1397 1398 1399 1400 1401 1402 1403
 [ HAL
        SUB     sp, sp, #4
        Push    "r0-r3,r12"
        MOV     r0, #0
        MOV     r1, lr
        ADD     r2, sp, #5*4
        BL      RISCOS_AccessPhysicalAddress
        MOV     lr, r0
        Pull    "r0-r3,r12"
 |
Neil Turton's avatar
Neil Turton committed
1404
        ORR     lr, lr, #PhysSpace                      ; now physical address is converted to a logical one (in physspace)
1405
 ]
Neil Turton's avatar
Neil Turton committed
1406 1407 1408
        AND     r7, r2, #&000FF000                      ; extract bits which are to form L2 offset

        LDR     lr, [lr, r7, LSR #10]                   ; lr = L2PT entry
1409 1410 1411 1412 1413 1414 1415
 [ HAL
        Push    "r0-r3,r12,lr"
        LDR     r0, [sp, #6*4]
        BL      RISCOS_ReleasePhysicalAddress
        Pull    "r0-r3,r12,lr"
        ADD     sp, sp, #4
 ]
1416 1417
        ANDS    r7, lr, #3                              ; 00 => trans.fault, 01 => large page
                                                        ; 10 => small page, 11 => reserved (fault)
Neil Turton's avatar
Neil Turton committed
1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443
        TEQNE   r7, #3
        BEQ     Fault
        TEQ     r7, #2                          ; if small page
        MOVEQ   r7, #SmallPageSizeShift-2       ; then sub-page size = 1<<10
        MOVNE   r7, #LargePageSizeShift-2       ; else sub-page size = 1<<14

        MOV     r5, r2, LSR r7                  ; round down to start of sub-page
        MOV     r5, r5, LSL r7
        MOV     r6, #1
        ADD     r5, r5, r6, LSL r7              ; then move on to start of next sub-page

        MOV     r7, r2, LSR r7                  ; put sub-page number in bits 1,2
        AND     r7, r7, #3                      ; and junk other bits
        RSB     r7, r7, #3                      ; invert sub-page ordering
        MOV     r7, r7, LSL #1                  ; and double it
        MOV     lr, lr, LSL r7                  ; then shift up access privileges so that correct ones appear in bits 10,11
        B       %BT15                           ; re-use code to check access privileges

Fault
        SUB     r5, r5, r2                      ; r5 = number of bytes we can do in this section/page/sub-page
        Push    "r3"                            ; save number of bytes to do
        CMP     r3, r5                          ; if more bytes than there are in this block
        MOVHI   r3, r5

; Now scan list of user abort addresses

Jeffrey Lee's avatar
Jeffrey Lee committed
1444
        LDR     r6, =ZeroPage
Neil Turton's avatar
Neil Turton committed
1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494
        LDR     r6, [r6, #AbortIndirection]
        TEQ     r6, #0
        BEQ     %FT85                           ; address not in any abort node
75
        LDR     r5, [r6, #AI_Low]
        CMP     r2, r5
        BCC     %FT80
        LDR     r5, [r6, #AI_High]
        CMP     r2, r5
        BCS     %FT80

        Push    "r3"                            ; save number of bytes we can do in this section/page/sub-page
        SUB     r5, r5, r2                      ; number of bytes we can do for this node
        CMP     r3, r5                          ; if bigger than the size of this node
        MOVHI   r3, r5                          ; then restrict number of bytes

        ADD     r5, r6, #AI_WS
        MOV     lr, pc
        LDMIA   r5, {r12, pc}

; returns to here

        ADDVS   sp, sp, #8                      ; if user abort failed, then junk both pushed r3's
        EXIT    VS                              ; and exit

        ADD     r1, r1, r3                      ; advance register block
        ADD     r2, r2, r3                      ; and illegal address pointer

        LDR     r5, [sp, #4]                    ; subtract amount done from stacked total amount to do
        SUBS    r5, r5, r3
        STR     r5, [sp, #4]                    ; and store back

        Pull    "r5"
        SUBS    r3, r5, r3                      ; is there more to do in this section/page/sub-page?
        BEQ     %FT90                           ; no then skip
80
        LDR     r6, [r6, #AI_Link]              ; else try next node
        TEQ     r6, #0
        BNE     %BT75
85
        ADD     sp, sp, #4                      ; junk pushed r3
        SETV                                    ; indicate access invalid
        EXIT                                    ; and exit

90
        Pull    "r3"                            ; restore total amount left to do
        TEQ     r3, #0
        BNE     %BT10                           ; yes, then loop
        EXIT                                    ; no, then exit (V=0 from SUBS)

Neil Turton's avatar
Neil Turton committed
1495

1496 1497 1498
; L1L2PTenhancements not currently used for HAL, but let's keep it as reference in case we want to implement it later
 [ :LNOT: HAL

Neil Turton's avatar
Neil Turton committed
1499 1500 1501 1502
;some tricks to improve performance, looking at MMU level 1 and level 2 page tables
L1L2PTenhancements ROUT
        Push    "r0-r5,lr"

Kevin Bracey's avatar
Kevin Bracey committed
1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520
        ;mjs change for Ursula:
        ;improved kernel workspace protection
        ; - user access to bottom 3k restricted to read only (things like Clib tmpnam counter prevent
        ;   going further)
        ; - Java VM will probably require bottom 1k restricted to no user access (so that VM can avoid
        ;   all run-time checks for null pointers), but this currently makes various things like ShareFS
        ;   go pop-bang, so not done yet (see TRUE/FALSE choice below)
        ;
        MOV     r0,#L2PT                ;L2PT address for page at 0
        LDR     r1,[r0]
        BIC     r1,r1,#&FF0             ;clear current AP bits for all four 1k sub-pages (S0 to S3)
     [ {FALSE}                          ;this would be good for Java VM:
        ORR     r1,r1,#&E90             ;S0=user none, S1=user read, S2=user read, S3=user read/write
     |                                  ;this makes less current things go pop-bang:
        ORR     r1,r1,#&EA0             ;S0=user read, S1=user read, S2=user read, S3=user read/write
     ]
        STR     r1,[r0]

Neil Turton's avatar
Neil Turton committed
1521 1522
;if the MMU control reg (soft copy) has R bit set (bit 9), then adjust the L1 entries for ROM
;space to give full write protection (user and supervisor)
Jeffrey Lee's avatar
Jeffrey Lee committed
1523
        LDR     r0,=ZeroPage
Neil Turton's avatar
Neil Turton committed
1524
        LDR     r1,[r0,#MMUControlSoftCopy]
Jeffrey Lee's avatar
Jeffrey Lee committed
1525
        TST     r1,#MMUC_R
Neil Turton's avatar
Neil Turton committed
1526 1527 1528
        BEQ     L1L2PTe_WPROMdone              ;ARM 610 has no R bit, for example
        LDR     r0,=L1PT
        ADD     r0,r0,#ROM :SHR: (20-2)        ;address of first L1PT entry for ROM space
1529 1530 1531
  [ OSROM_ImageSize > 8192
        MOV     r1,#OSROM_ImageSize / 1024
  |
Neil Turton's avatar
Neil Turton committed
1532
        MOV     r1,#8                          ;8 entries (8 Mbytes)
1533
  ]
Neil Turton's avatar
Neil Turton committed
1534 1535 1536 1537 1538 1539 1540 1541
L1L2PTe_WPROMloop
        LDR     r2,[r0]
        BIC     r2,r2,#&C00                    ;set AP (access permission) bits to 00
        STR     r2,[r0],#4
        SUBS    r1,r1,#1
        BNE     L1L2PTe_WPROMloop
L1L2PTe_WPROMdone

Kevin Bracey's avatar
Kevin Bracey committed
1542 1543
   [ :LNOT: (CanLiveOnROMCard :LOR: ROMCardSupport :LOR: ExtROMSupport)

Neil Turton's avatar
Neil Turton committed
1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557
;go for best available memory speed for data cache cleaner area (StrongARM)
        LDR     r0,=L2PT :OR: (ARMA_Cleaners_address :SHR: 10)  ;address of 1st L2PT word for cleaner area
        LDR     r1,[r0]
        MOV     r1,r1,LSL #20
        MOV     r1,r1,LSR #20                   ;zap physical address field
        ORR     r1,r1,#&01000000                ; = physical address of start of ROM bank 1
        MOV     r2,#8                           ;8 L2PT entries to fiddle
00
        STR     r1,[r0],#4
        SUBS    r2,r2,#1
        BNE     %BT00
        MOV     r0,#IOC
        MOV     r1,#5
        STRB    r1,[r0, #IOMD_ROMCR1]           ;ROM bank 1 speed = fastest (62.5 ns)
Kevin Bracey's avatar
Kevin Bracey committed
1558
    ]
Neil Turton's avatar
Neil Turton committed
1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584

;make first 5 pages of cursor chunk cacheable and bufferable - this is rather handy, 'coz things
;like the SWI dispatcher, IRQ dispatcher are here. May be a slight worry over cursor data
;being write-back cached (StrongARM) - should strictly clean,drain write buffer or whatever for shape change.
        LDR     r0,=L2PT :OR: (CursorChunkAddress :SHR: 10)  ;address of 1st L2PT word for CursorChunk
        MOV     R2,#5                           ;5 entries to adjust
01
        LDR     r1,[r0]
        ORR     r1,r1,#&C                       ;make page cacheable and bufferable
        STR     r1,[r0],#4
        SUBS    r2,r2,#1
        BNE     %BT01

;make other 3 pages of chunk bufferable
        MOV     R2,#3
02
        LDR     r1,[r0]
        ORR     r1,r1,#&4                       ;make page bufferable
        STR     r1,[r0],#4
        SUBS    r2,r2,#1
        BNE     %BT02

;try to rescue some pages from the L2PT itself, in the AppSpace region - ie. AppSpace max size can really
;be total RAM size, if that is less than 28 Mb, and for every 4Mb less that is we can rescue a 4k page
;and return it to the free pool - handy on a 2Mb Kryten for instance!

Jeffrey Lee's avatar
Jeffrey Lee committed
1585
        LDR     r0,=ZeroPage+MaxCamEntry
Neil Turton's avatar
Neil Turton committed
1586
        LDR     r0,[r0]
1587 1588 1589 1590
        ADD     r0,r0,#1+255+768                ; = no. of 4k RAM pages in machine + 255 + 3*256
        MOV     r0,r0,LSR #8                    ; = no. of Mbytes in machine rounded up + 3
        BIC     r0,r0,#3                        ; round up to next 4 Mb
        CMP     r0,#28                          ; if 28Mb or more, no pages to be rescued from L2PT AppSpace
Neil Turton's avatar
Neil Turton committed
1591
        BHS     %FT09
Jeffrey Lee's avatar
Jeffrey Lee committed
1592
        LDR     r1,=ZeroPage+AppSpaceDANode
Neil Turton's avatar
Neil Turton committed
1593
        MOV     r2,r0,LSL #20
1594 1595
        STR     r2,[r1,#DANode_MaxSize]         ; update AppSpace max size
        MOV     r0,r0,LSR #2                    ; no. of L2PT AppSpace pages which cannot be rescued
Neil Turton's avatar
Neil Turton committed
1596
        MOV     r1,#L2PT
1597 1598 1599 1600
        ADD     r4, r1, #L1PT-L2PT
        ADD     r4, r4, r0, LSL #4              ;the L1PT entry to blank out (4 L1 entries per L2 entry)
        ADD     r1,r1,#(L2PT :SHR: (12-2))      ;the L2PT of the L2PT (and first 7 entries are for App Space)
        ADD     r1,r1,r0,LSL #2                 ;first entry for rescue
Jeffrey Lee's avatar
Jeffrey Lee committed
1601
        LDR     r3,=ZeroPage+FreePoolDANode
Neil Turton's avatar
Neil Turton committed
1602
        LDR     r2,[r3,#DANode_Base]
1603 1604
        LDR     r5,[r3,#DANode_Size]            ; FreePool size so far
        ADD     r2,r2,r5                        ; r2 -> next logical address for a rescued page
Neil Turton's avatar
Neil Turton committed
1605

1606
        SUB     sp,sp,#16                       ; room for 1 page block entry + terminator
Neil Turton's avatar
Neil Turton committed
1607 1608
        MOV     r3,sp
05
1609
        Push    "r0"
1610
        LDR     r0,[r1],#4                      ; pick up the L2PT entry
1611
        BIC     r0,r0,#&0FF
1612 1613
        BIC     r0,r0,#&F00                     ; mask to leave physical address only
        STR     r0,[r3,#8]                      ; store physical address in word 2 of page block entry
1614 1615

        Push    "r1-r2"
Neil Turton's avatar
Neil Turton committed
1616 1617 1618
        MOV     r0,#&0C00
        MOV     r1,r3
        MOV     r2,#1
1619
        SWI     XOS_Memory                      ; fill in page number, given physical address
1620

1621
        MOV     r0,#2                           ; means inaccessible in user mode (destined for FreePool)
1622 1623
        STR     r0,[r3,#8]
        MOV     r0,#-1
1624
        STR     r0,[r3,#12]                     ; terminator
1625 1626
        Pull    "r1-r2"

1627
        STR     r2,[r3,#4]                      ; new logical address for page
Neil Turton's avatar
Neil Turton committed
1628 1629
        MOV     r0,r3
        SWI     XOS_SetMemMapEntries
1630

1631 1632 1633 1634 1635
        MOV     r0, #0                          ; Blank out the L1PT entries for the page table we just removed
        STR     r0, [r4], #4
        STR     r0, [r4], #4
        STR     r0, [r4], #4
        STR     r0, [r4], #4
1636

Neil Turton's avatar
Neil Turton committed
1637 1638
        Pull    "r0"
        ADD     r2,r2,#4096
1639
        ADD     r5,r5,#4096                     ; next page
Neil Turton's avatar
Neil Turton committed
1640
        ADD     r0,r0,#1
1641
        CMP     r0,#7                           ;7 entries in total for full 28Mb AppSpace
Neil Turton's avatar
Neil Turton committed
1642
        BNE     %BT05
1643
        ADD     sp,sp,#16                       ;drop the workspace
Neil Turton's avatar
Neil Turton committed
1644

Jeffrey Lee's avatar
Jeffrey Lee committed
1645
        LDR     r0,=ZeroPage+FreePoolDANode
1646
        STR     r5,[r0,#DANode_Size]            ;update FreePoolSize
Neil Turton's avatar
Neil Turton committed
1647 1648 1649

09
        Pull    "r0-r5,pc"
1650

1651 1652
 ] ; :LNOT: HAL

Jeffrey Lee's avatar
Jeffrey Lee committed
1653
 ] ; UseProcessTransfer
1654

Neil Turton's avatar
Neil Turton committed
1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673
;
; ---------------- XOS_SynchroniseCodeAreas implementation ---------------
;

;this SWI effectively implements IMB and IMBrange (Instruction Memory Barrier)
;for newer ARMs

;entry:
;   R0 = flags
;        bit 0 set ->  R1,R2 specify virtual address range to synchronise
;                      R1 = start address (word aligned, inclusive)
;                      R2 = end address (word aligned, inclusive)
;        bit 0 clear   synchronise entire virtual space
;        bits 1..31    reserved
;
;exit:
;   R0-R2 preserved
;
SyncCodeAreasSWI ROUT
1674 1675 1676 1677 1678 1679 1680 1681 1682 1683
        Push    "lr"
        BL      SyncCodeAreas
        Pull    "lr"                    ; no error return possible
        B       SLVK

SyncCodeAreas
        TST     R0,#1                   ; range variant of SWI?
        BEQ     SyncCodeAreasFull

SyncCodeAreasRange
1684 1685 1686
        Push    "r0-r2, lr"
        MOV     r0, r1
        ADD     r1, r2, #4                 ;exclusive end address
Jeffrey Lee's avatar
Jeffrey Lee committed
1687
        LDR     r2, =ZeroPage
1688 1689 1690 1691 1692
        LDRB    lr, [r2, #Cache_Type]
        CMP     lr, #CT_ctype_WB_CR7_Lx ; DCache_LineLen lin or log?
        LDRB    lr, [r2, #DCache_LineLen]
        MOVEQ   r2, #4
        MOVEQ   lr, r2, LSL lr
Jeffrey Lee's avatar
Jeffrey Lee committed
1693
        LDREQ   r2, =ZeroPage
1694 1695 1696 1697 1698 1699 1700
        SUB     lr, lr, #1
        ADD     r1, r1, lr                 ;rounding up end address
        MVN     lr, lr
        AND     r0, r0, lr                 ;cache line aligned
        AND     r1, r1, lr                 ;cache line aligned
        ARMop   IMB_Range,,,r2
        Pull    "r0-r2, pc"
1701 1702

SyncCodeAreasFull
1703
        Push    "r0, lr"
Jeffrey Lee's avatar
Jeffrey Lee committed
1704
        LDR     r0, =ZeroPage
1705 1706
        ARMop   IMB_Full,,,r0
        Pull    "r0, pc"
Neil Turton's avatar
Neil Turton committed
1707 1708 1709

        LTORG

Neil Turton's avatar
Neil Turton committed
1710 1711 1712 1713
 [ DebugAborts
        InsertDebugRoutines
 ]
        END