ARM600 26.3 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}

Jeffrey Lee's avatar
Jeffrey Lee committed
20 21 22 23 24 25 26 27 28 29 30 31 32
        ; Convert given page flags to the equivalent temp uncacheable L2PT flags
        ; n.b. temp not used here but included for VMSAv6 compatibility
        MACRO
        GetTempUncache $out, $pageflags, $pcbtrans, $temp
        ASSERT  DynAreaFlags_CPBits = 7*XCB_P :SHL: 10
        ASSERT  DynAreaFlags_NotCacheable = XCB_NC :SHL: 4
        ASSERT  DynAreaFlags_NotBufferable = XCB_NB :SHL: 4
        AND     $out, $pageflags, #DynAreaFlags_NotCacheable + DynAreaFlags_NotBufferable
        ORR     $out, $out, #DynAreaFlags_NotCacheable      ; treat as temp uncache
        LDRB    $out, [$pcbtrans, $out, LSR #4]             ; convert to X, C and B bits for this CPU
        MEND

TempUncache_L2PTMask * L2_X+L2_C+L2_B
Neil Turton's avatar
Neil Turton committed
33 34 35

; MMU interface file - ARM600 version

36 37
        KEEP

Neil Turton's avatar
Neil Turton committed
38 39 40 41
; **************** CAM manipulation utility routines ***********************************

; **************************************************************************************
;
42
;       BangCamUpdate - Update CAM, MMU for page move, coping with page currently mapped in
Neil Turton's avatar
Neil Turton committed
43
;
44 45
; mjs Oct 2000
; reworked to use generic ARM ops (vectored to appropriate routines during boot)
Neil Turton's avatar
Neil Turton committed
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
;
; 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
66
        LDR     r1, =ZeroPage
Neil Turton's avatar
Neil Turton committed
67
        LDR     r1, [r1, #CamEntriesPointer]
68 69 70
        ADD     r1, r1, r2, LSL #CAM_EntrySizeLog2 ; point at cam entry (logaddr, PPL)
        ASSERT  CAM_LogAddr=0
        ASSERT  CAM_PageFlags=4
Neil Turton's avatar
Neil Turton committed
71
        LDMIA   r1, {r0, r6}                    ; r0 = current logaddress, r6 = current PPL
72 73
        BIC     r4, r11, #PageFlags_Unsafe
        STMIA   r1, {r3, r4}                    ; store new address, PPL
Neil Turton's avatar
Neil Turton committed
74
        Push    "r0, r6"                        ; save old logical address, PPL
Jeffrey Lee's avatar
Jeffrey Lee committed
75
        LDR     r1, =ZeroPage+PhysRamTable      ; go through phys RAM table
Neil Turton's avatar
Neil Turton committed
76 77 78 79 80 81 82 83
        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
84
        LDR     r6, [sp]                        ; reload old logical address
Neil Turton's avatar
Neil Turton committed
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

; 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

103
        AND     r4, r11, #PageFlags_Unsafe
Neil Turton's avatar
Neil Turton committed
104 105 106
        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
107 108 109
        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
110
        MOV     r0, #0                          ; cause translation fault
111
        BLNE    BangL2PT                        ; map page out
Neil Turton's avatar
Neil Turton committed
112 113 114 115 116 117 118
        Pull    "r0, r3, r11, r14"
20
        ADD     sp, sp, #8                      ; junk old logical address, PPL
        B       BangCamAltEntry                 ; and branch into BangCam code

; **************************************************************************************
;
119
;       BangCam - Update CAM, MMU for page move, assuming page currently mapped out
Neil Turton's avatar
Neil Turton committed
120 121
;
; This routine maps a physical page to a given logical address
122
; It is assumed that the physical page is currently not mapped anywhere else
Neil Turton's avatar
Neil Turton committed
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
;
; 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
142
        LDR     r1, =ZeroPage+PhysRamTable ; go through phys RAM table
Neil Turton's avatar
Neil Turton committed
143 144 145 146 147 148 149 150 151
        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
152
        LDR     r4, =DuffEntry          ; check for requests to map a page to nowhere
153
        LDR     r6, =ZeroPage
154
        TEQ     r4, r3                  ; don't actually map anything to nowhere
155
        LDR     r1, [r6, #ProcessorFlags]
156
        MOVEQ   pc, lr
157
        TST     r1, #CPUFlag_ExtendedPages
Neil Turton's avatar
Neil Turton committed
158
        AND     r4, r11, #3             ; first use PPL bits
159 160
        ADREQ   r1, PPLTrans
        ADRNE   r1, PPLTransX           ; always use extended pages if supported
Neil Turton's avatar
Neil Turton committed
161
        LDR     r1, [r1, r4, LSL #2]    ; get PPL bits and SmallPage indicator
162

163 164 165
        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
166 167 168 169 170 171 172 173

        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
174
        ORREQ   r1, r1, r4, LSR #10-4                   ; else use NC, NB and P bits
Kevin Bracey's avatar
Kevin Bracey committed
175 176
        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
177 178 179

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

180 181
        ;fall through to BangL2PT

Neil Turton's avatar
Neil Turton committed
182 183 184 185 186 187 188
;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
189 190 191
        Push    "lr"
        MOV     r6, r0

192 193 194
        TST     r11, #PageFlags_Unsafe
        BNE     %FT30

Neil Turton's avatar
Neil Turton committed
195 196 197
        TST     r11, #DynAreaFlags_DoublyMapped
        BNE     BangL2PT_sledgehammer           ;if doubly mapped, don't try to be clever

Jeffrey Lee's avatar
Jeffrey Lee committed
198 199 200 201 202 203 204 205
        ;In order to safely map out a cacheable page and remove it from the
        ;cache, we need to perform the following process:
        ;* Make the page uncacheable
        ;* Flush TLB
        ;* Clean+invalidate cache
        ;* Write new mapping (r6)
        ;* Flush TLB
        ;For uncacheable pages we can just do the last two steps
206 207
        ;
        TEQ     r6, #0                          ;EQ if mapping out
Kevin Bracey's avatar
Kevin Bracey committed
208
        TSTEQ   r11, #DynAreaFlags_NotCacheable ;EQ if also cacheable (overcautious for temp uncache+illegal PCB combos)
Jeffrey Lee's avatar
Jeffrey Lee committed
209
        LDR     r4, =ZeroPage
Jeffrey Lee's avatar
Jeffrey Lee committed
210 211 212 213 214 215 216 217 218 219 220 221 222
        BNE     %FT20
        LDR     lr, [r4, #MMU_PCBTrans]
        GetTempUncache r0, r11, lr
        LDR     lr, [r1, r3, LSR #10]           ;get current L2PT entry
        BIC     lr, lr, #TempUncache_L2PTMask   ;remove current attributes
        ORR     lr, lr, r0
        STR     lr, [r1, r3, LSR #10]           ;Make uncacheable
        MOV     r0, r3
        ARMop   MMU_ChangingUncachedEntry,,, r4 ; TLB flush
        MOV     r0, r3
        ADD     r1, r3, #4096
        ARMop   Cache_CleanInvalidateRange,,, r4 ; Cache flush
        LDR     r1, =L2PT
Neil Turton's avatar
Neil Turton committed
223

224
20      STR     r6, [r1, r3, LSR #10]           ;update L2PT entry
Jeffrey Lee's avatar
Jeffrey Lee committed
225 226 227
        Pull    "lr"
        MOV     r0, r3
        ARMop   MMU_ChangingUncachedEntry,,tailcall,r4
Neil Turton's avatar
Neil Turton committed
228 229

BangL2PT_sledgehammer
230 231 232 233 234

        ;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
235
        TSTEQ   r11, #DynAreaFlags_NotCacheable ;EQ if also cacheable (overcautious for temp uncache+illegal PCB combos)
236
        ADR     lr, %FT30
Jeffrey Lee's avatar
Jeffrey Lee committed
237
        LDR     r4, =ZeroPage
238 239 240 241
        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
242
        TST     r11, #DynAreaFlags_DoublyMapped ; if area doubly mapped
243 244
        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
245

246
        Pull    "pc"
Neil Turton's avatar
Neil Turton committed
247

Neil Turton's avatar
Neil Turton committed
248

249 250 251 252 253 254
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
255 256 257 258
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
259
        &       (AP_ROM  * L2_APMult) + L2_SmallPage      ; R any W none
Neil Turton's avatar
Neil Turton committed
260

Kevin Bracey's avatar
Kevin Bracey committed
261 262 263 264 265 266
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
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
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
283
        LDR     r12, =ZeroPage
Kevin Bracey's avatar
Kevin Bracey committed
284
        WritePSRc SVC_mode+I_bit+F_bit, r0
Neil Turton's avatar
Neil Turton committed
285 286 287 288 289 290 291 292
        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]

293 294 295 296 297 298 299 300 301 302
; 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
303 304 305 306 307 308 309 310 311 312
;
; 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
313 314 315 316 317
        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
318 319 320 321
        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
322 323
        BL    CallGraphicsV
        Pull  "r0,r1,r4, r14"
Neil Turton's avatar
Neil Turton committed
324

Kevin Bracey's avatar
Kevin Bracey committed
325
        WritePSRc SVC_mode+I_bit, r11
Neil Turton's avatar
Neil Turton committed
326 327 328 329 330 331
        ExitSWIHandler

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;       SWI OS_MMUControl
;
Neil Turton's avatar
Neil Turton committed
332
; in:   r0 = 0 (reason code 0, for modify control register)
Neil Turton's avatar
Neil Turton committed
333 334 335 336 337 338 339
;       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
340 341 342 343 344
;
; 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
345
;          r0 bit 28 set if write buffer to be flushed (implied by bit 31)
Neil Turton's avatar
Neil Turton committed
346 347
;       r1 = entry specifier, if r0 bit 29 set
;       (currently, flushing by entry is ignored, and just does full flush)
348 349 350 351 352
;
; 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
353
;
Neil Turton's avatar
Neil Turton committed
354

355
MMUControlSWI   Entry
Neil Turton's avatar
Neil Turton committed
356 357 358 359 360 361
        BL      MMUControlSub
        PullEnv
        ORRVS   lr, lr, #V_bit
        ExitSWIHandler

MMUControlSub
Neil Turton's avatar
Neil Turton committed
362 363 364 365
        Push    lr
        AND     lr,r0,#&FF
        CMP     lr, #MMUCReason_Unknown
        ADDCC   pc, pc, lr, LSL #2
Neil Turton's avatar
Neil Turton committed
366 367
        B       MMUControl_Unknown
        B       MMUControl_ModifyControl
Neil Turton's avatar
Neil Turton committed
368
        B       MMUControl_Flush
369
        B       MMUControl_GetARMop
Neil Turton's avatar
Neil Turton committed
370 371 372 373 374

MMUControl_Unknown
        ADRL    r0, ErrorBlock_HeapBadReason
 [ International
        BL      TranslateError
Robert Sprowson's avatar
Robert Sprowson committed
375
 |
Neil Turton's avatar
Neil Turton committed
376
        SETV
Robert Sprowson's avatar
Robert Sprowson committed
377 378
 ]
        Pull    "pc"
Neil Turton's avatar
Neil Turton committed
379

380

Neil Turton's avatar
Neil Turton committed
381 382 383 384 385
MMUControl_ModifyControl ROUT
        Push    "r3,r4,r5"
        CMP     r1,#0
        CMPEQ   r2,#&FFFFFFFF
        BEQ     MMUC_modcon_readonly
Jeffrey Lee's avatar
Jeffrey Lee committed
386
        LDR     r3,=ZeroPage
387 388 389 390
        LDRB    r5,[r3, #ProcessorArch]
        PHPSEI  r4                      ; disable IRQs while we modify soft copy (and possibly switch caches off/on)

        CMP     r5,#ARMv4
391
        LDRLO   lr, [r3, #MMUControlSoftCopy]
392
        ARM_read_control lr,HS
393 394
;        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
395 396 397
        AND     r2, r2, lr
        EOR     r2, r2, r1
        MOV     r1, lr
398 399 400
        LDR     r5, [r3, #ProcessorFlags]
        TST     r5, #CPUFlag_SplitCache
        BEQ     %FT05
401 402 403 404 405
 [ {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
406
05
Neil Turton's avatar
Neil Turton committed
407 408
        STR     r2, [r3, #MMUControlSoftCopy]
        BIC     lr, r2, r1              ; lr = bits going from 0->1
Neil Turton's avatar
Neil Turton committed
409
        TST     lr, #MMUC_C             ; if cache turning on then flush cache before we do it
410
        TSTEQ   lr, #MMUC_I
Neil Turton's avatar
Neil Turton committed
411
        BEQ     %FT10
412

413
        Push    "r0"
Jeffrey Lee's avatar
Jeffrey Lee committed
414
        ARMop   Cache_InvalidateAll,,,r3
415
        Pull    "r0"
Neil Turton's avatar
Neil Turton committed
416
10
417
        BIC     lr, r1, r2              ; lr = bits going from 1->0
418 419
        TST     lr, #MMUC_C             ; if cache turning off then clean data cache first
        BEQ     %FT15
420
        Push    "r0"
Jeffrey Lee's avatar
Jeffrey Lee committed
421
        ARMop   Cache_CleanAll,,,r3
422
        Pull    "r0"
Neil Turton's avatar
Neil Turton committed
423 424 425 426
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
427
        TSTNE   lr, #MMUC_I
Neil Turton's avatar
Neil Turton committed
428
        BEQ     %FT20
429
        Push    "r0"
Jeffrey Lee's avatar
Jeffrey Lee committed
430
        ARMop   Cache_InvalidateAll,,,r3
431
        Pull    "r0"
Neil Turton's avatar
Neil Turton committed
432
20
Kevin Bracey's avatar
Kevin Bracey committed
433
        PLP     r4                      ; restore IRQ state
Neil Turton's avatar
Neil Turton committed
434 435 436
        Pull    "r3,r4,r5,pc"

MMUC_modcon_readonly
Jeffrey Lee's avatar
Jeffrey Lee committed
437
        LDR     r3, =ZeroPage
438 439
        LDRB    r5, [r3, #ProcessorArch]
        CMP     r5, #ARMv4
440
        LDRLO   lr, [r3, #MMUControlSoftCopy]
441
        ARM_read_control lr,HS
442 443
;        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
444
        STRHS   lr, [r3, #MMUControlSoftCopy]
Neil Turton's avatar
Neil Turton committed
445 446 447 448 449
        MOV     r1, lr
        MOV     r2, lr
        Pull    "r3,r4,r5,pc"

MMUControl_Flush
Kevin Bracey's avatar
Kevin Bracey committed
450
       MOVS     r10, r0
Jeffrey Lee's avatar
Jeffrey Lee committed
451
       LDR      r12, =ZeroPage
Kevin Bracey's avatar
Kevin Bracey committed
452 453 454 455
       ARMop    Cache_CleanInvalidateAll,MI,,r12
       TST      r10,#&40000000
       ARMop    TLB_InvalidateAll,NE,,r12
       TST      r10,#&10000000
456
       ARMop    DSB_ReadWrite,NE,,r12
Kevin Bracey's avatar
Kevin Bracey committed
457 458
       ADDS     r0,r10,#0
       Pull     "pc"
Neil Turton's avatar
Neil Turton committed
459

460 461 462 463 464 465 466 467 468
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
469 470 471 472
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;       Exception veneers

Jeffrey Lee's avatar
Jeffrey Lee committed
473
 [ ChocolateAMB
474 475 476 477 478
;  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
479
        MOV     r2, #1
480 481 482 483
        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
484
        LDR     r0, =ZeroPage+PAbHan      ; we want to jump to PAb handler, in abort mode
485 486 487 488 489
        LDR     r0, [r0]
        STR     r0, [sp, #8*4]
        Pull    "r0-r7, pc"
 ]

Neil Turton's avatar
Neil Turton committed
490 491 492 493 494 495 496 497 498
; Preliminary layout of abort indirection nodes

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

499 500
        EXPORT DAbPreVeneer

Neil Turton's avatar
Neil Turton committed
501 502
DAbPreVeneer    ROUT

Kevin Bracey's avatar
Kevin Bracey committed
503
        SUB     r13_abort, r13_abort, #17*4     ; we use stacks, dontcherknow
Neil Turton's avatar
Neil Turton committed
504 505 506
        STMIA   r13_abort, {r0-r7}              ; save unbanked registers anyway
        STR     lr_abort, [r13_abort, #15*4]    ; save old PC, ie instruction address

507 508
  [ ChocolateAMB
        ARM_read_FAR r0                         ; aborting address
509
        MOV     r2, #0
510 511 512 513 514 515 516
        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
  ]

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

Jeffrey Lee's avatar
Jeffrey Lee committed
521
        LDR     r4, =ZeroPage+Abort32_dumparea+3*4 ;use temp area (avoid overwriting main area for expected aborts)
522 523 524
        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
525 526 527 528
        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
529 530 531 532 533
  [ SASTMhatbroken
        STMEQIA r2!,{r8-r12}
        STMEQIA r2 ,{r13,r14}^
        SUBEQ   r2, r2, #5*4
  |
Neil Turton's avatar
Neil Turton committed
534
        STMEQIA r2, {r8-r14}^
535
  ]
Neil Turton's avatar
Neil Turton committed
536 537 538
        BEQ     %FT05

        ORR     r3, r3, r1                      ; and put in user's
539
        MSR     CPSR_c, r3                      ; switch to user's mode
Neil Turton's avatar
Neil Turton committed
540 541 542

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

543
        MRS     r5, SPSR                        ; get the SPSR for the aborter's mode
Neil Turton's avatar
Neil Turton committed
544 545
        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
546
        ORR     r1, r1, #ABT32_mode
547
        MSR     CPSR_c, r1                      ; back to abort mode for the rest of this
Neil Turton's avatar
Neil Turton committed
548
05
Kevin Bracey's avatar
Kevin Bracey committed
549 550
        Push    "r0"                            ; save SPSR_abort

551
  [ SASTMhatbroken
Kevin Bracey's avatar
Kevin Bracey committed
552 553
        SUB     sp, sp, #3*4
        STMIA   sp, {r13,r14}^                  ; save USR bank in case STM ^, and also so we can corrupt them
554
        NOP
Kevin Bracey's avatar
Kevin Bracey committed
555
        STMDB   sp!, {r8-r12}
556
  |
Kevin Bracey's avatar
Kevin Bracey committed
557 558
        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
559
  ]
Neil Turton's avatar
Neil Turton committed
560 561

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

; Call normal exception handler

90

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

Jeffrey Lee's avatar
Jeffrey Lee committed
570
        LDR     r0, =ZeroPage+Abort32_dumparea
571 572 573 574 575 576 577
        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]

Jeffrey Lee's avatar
Jeffrey Lee committed
578 579
        LDR     r0, =ZeroPage                           ; we're going to call abort handler
      [ ZeroPage = 0
Kevin Bracey's avatar
Kevin Bracey committed
580
        STR     r0, [r0, #CDASemaphore]                 ; so allow recovery if we were in CDA
Jeffrey Lee's avatar
Jeffrey Lee committed
581 582 583 584
      |
        MOV     r2, #0
        STR     r2, [r0, #CDASemaphore]                 ; so allow recovery if we were in CDA
      ]
Kevin Bracey's avatar
Kevin Bracey committed
585

Jeffrey Lee's avatar
Jeffrey Lee committed
586
        LDR     r0, [r0, #DAbHan]                       ; get address of data abort handler
Kevin Bracey's avatar
Kevin Bracey committed
587 588 589 590 591 592 593 594 595
 [ 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

596
        MRS     r1, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
597

598
        MRS     r6, SPSR                        ; get original SPSR, with aborter's original mode
Kevin Bracey's avatar
Kevin Bracey committed
599 600 601 602 603 604 605 606
        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
607
        MSR     CPSR_c, r6                      ; switch to aborter's mode
Kevin Bracey's avatar
Kevin Bracey committed
608
        LDMIA   r2, {r8-r14}                    ; reload banked registers
609
        MSR     CPSR_c, r1                      ; switch back to ABT32
Kevin Bracey's avatar
Kevin Bracey committed
610 611 612 613 614 615 616 617 618 619

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

Jeffrey Lee's avatar
Jeffrey Lee committed
620

Neil Turton's avatar
Neil Turton committed
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
;
; ---------------- 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
640 641 642 643 644 645 646 647 648 649
        Push    "lr"
        BL      SyncCodeAreas
        Pull    "lr"                    ; no error return possible
        B       SLVK

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

SyncCodeAreasRange
650 651 652
        Push    "r0-r2, lr"
        MOV     r0, r1
        ADD     r1, r2, #4                 ;exclusive end address
Jeffrey Lee's avatar
Jeffrey Lee committed
653
        LDR     r2, =ZeroPage
654 655 656 657 658
        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
659
        LDREQ   r2, =ZeroPage
660 661 662 663 664 665 666
        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"
667 668

SyncCodeAreasFull
669
        Push    "r0, lr"
Jeffrey Lee's avatar
Jeffrey Lee committed
670
        LDR     r0, =ZeroPage
671 672
        ARMop   IMB_Full,,,r0
        Pull    "r0, pc"
Neil Turton's avatar
Neil Turton committed
673 674 675

        LTORG

Neil Turton's avatar
Neil Turton committed
676 677 678 679
 [ DebugAborts
        InsertDebugRoutines
 ]
        END