Copro15ops 21.1 KB
Newer Older
1
; Copyright 2000 Pace Micro Technology plc
Neil Turton's avatar
Neil Turton committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
;
; 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.
;
; > Copro15ops

;macros for Coprocessor #15 operations (configuration), which run-time detect
;and cater for ARM 6,7,8,A (A=StrongARM).
;Routines detect which ARM directly by reading ARM ID register (avoids memory reads).

Kevin Bracey's avatar
Kevin Bracey committed
21 22
; 24-01-96 MJS Created
; 07-10-96 MJS Updated for proper ARM 810 support (not needed for RO 3.70)
23 24
; 10-03-97 MJS A few additions for chocolate flavour screen handling (possible
;              Domain and FSR register use) in Phoebe OS
25 26 27
; 05-02-09 JL  Disable ARM_flush_* when compiling OS for HAL. OS now supports
;              too many ARM versions for cache/TLB flushing to be implemented in
;              simple macros.
Neil Turton's avatar
Neil Turton committed
28

29 30
        GET     Hdr:CPU.Arch

Neil Turton's avatar
Neil Turton committed
31 32 33 34 35 36
ARM_config_cp        CP 15  ;coprocessor number for configuration control

ARM_ID_reg           CN  0  ;processor ID
ARM_control_reg      CN  1  ;control
ARM_tbase_reg        CN  2  ;translation base (MMU)
ARM_domain_reg       CN  3  ;domain access control (MMU)
37 38
ARM_FSR_reg          CN  5  ;Fault status reg (MMU, read only on ARM 6/7)
ARM_FAR_reg          CN  6  ;Fault address reg (MMU, read only on ARM 6/7)
Neil Turton's avatar
Neil Turton committed
39 40 41 42

ARM67_TLBflush_reg   CN  5  ;TLB flush, ARMs 6 or 7
ARM67_TLBpurge_reg   CN  6  ;TLB purge entry, ARMs 6 or 7
ARM67_cacheflush_reg CN  7  ;cache flush, ARMs 6 or 7
43 44 45
ARMv3_TLBflush_reg   CN  5  ;TLB flush, ARMs 6 or 7
ARMv3_TLBpurge_reg   CN  6  ;TLB purge entry, ARMs 6 or 7
ARMv3_cacheflush_reg CN  7  ;cache flush, ARMs 6 or 7
Neil Turton's avatar
Neil Turton committed
46 47 48

ARM8A_cache_reg      CN  7  ;cache operations, ARMs 8 or StrongARM
ARM8A_TLB_reg        CN  8  ;TLB operations, ARMs 8 or StrongARM
49 50
ARMv4_cache_reg      CN  7  ;cache operations, ARMs 8 or StrongARM
ARMv4_TLB_reg        CN  8  ;TLB operations, ARMs 8 or StrongARM
Neil Turton's avatar
Neil Turton committed
51 52 53 54

ARM8_cacheLD_reg     CN  9  ;cache lock-down, ARM 8
ARM8_TLBLD_reg       CN 10  ;TLB lock-down, ARM 8

Kevin Bracey's avatar
Kevin Bracey committed
55 56
ARM8_CTC_reg         CN 15  ;Clock and test configuration

Neil Turton's avatar
Neil Turton committed
57 58
ARMA_TCI_reg         CN 15  ;Test,Clock and Idle control

59
;so that bleedin' AASM will accept the general value for MCR CRm field
Neil Turton's avatar
Neil Turton committed
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
C0  CN  0
C1  CN  1
C2  CN  2
C3  CN  3
C4  CN  4
C5  CN  5
C6  CN  6
C7  CN  7
C8  CN  8
C9  CN  9
C10 CN 10
C11 CN 11
C12 CN 12
C13 CN 13
C14 CN 14
C15 CN 15


;
; ----------------- all ARMs ---------------------------------------------
;

;set MMU translation base
        MACRO
        ARM_MMU_transbase $reg,$cond
        MCR$cond ARM_config_cp,0,$reg,ARM_tbase_reg,C0,0
        MEND

;set MMU domain access register
        MACRO
        ARM_MMU_domain $reg,$cond
        MCR$cond ARM_config_cp,0,$reg,ARM_domain_reg,C0,0
        MEND

;read control register
        MACRO
        ARM_read_control $reg,$cond
        MRC$cond ARM_config_cp,0,$reg,ARM_control_reg,C0,0
        MEND

;set control register
        MACRO
        ARM_write_control $reg,$cond
        MCR$cond ARM_config_cp,0,$reg,ARM_control_reg,C0,0
        MEND

106
;read MMU/external fault status
107 108 109 110 111
        MACRO
        ARM_read_FSR $reg,$cond
        MRC$cond ARM_config_cp,0,$reg,ARM_FSR_reg,C0,0
        MEND

112 113 114 115 116 117 118
;set MMU/external fault status
        MACRO
        ARM_write_FSR $reg,$cond
        MCR$cond ARM_config_cp,0,$reg,ARM_FSR_reg,C0,0
        MEND

;read MMU/external fault address
119 120 121 122 123
        MACRO
        ARM_read_FAR $reg,$cond
        MRC$cond ARM_config_cp,0,$reg,ARM_FAR_reg,C0,0
        MEND

124 125 126 127 128 129
; set MMU/external fault address
        MACRO
        ARM_write_FAR $reg,$cond
        MCR$cond ARM_config_cp,0,$reg,ARM_FAR_reg,C0,0
        MEND

Neil Turton's avatar
Neil Turton committed
130 131 132 133 134 135 136
;read ID register to register $id
;bits 15:12 of returned ID will be 0,7,8,10 for ARM 6,7,8,A
        MACRO
        ARM_read_ID $id,$cond
        MRC$cond ARM_config_cp,0,$id,ARM_ID_reg,C0,0
        MEND

137 138 139 140 141 142
;read cache type register to register $type
        MACRO
        ARM_read_cachetype $type,$cond
        MRC$cond ARM_config_cp,0,$type,ARM_ID_reg,C0,1
        MEND

Neil Turton's avatar
Neil Turton committed
143 144 145 146 147 148 149 150 151
;read ARM 'number' (6,7,8,&A currently) into $num
        MACRO
        ARM_number $num
        ARM_read_ID $num
        ANDS     $num,$num,#&F000
        MOVEQ    $num,#&6000       ;catch and correct daft ARM 6 ID layout
        MOV      $num,$num,LSR #12
        MEND

152 153 154 155 156 157 158
; check if we're on an ARM 6 - EQ if so
        MACRO
        ARM_6       $tmp, $cond
        ARM_read_ID $tmp, $cond
        TST$cond    $tmp, #&F000
        MEND

159 160 161 162 163
;check whether running on emulator - this is subject to change. ARMs before
;ARM 920 ignore op2, and will definitely return something other than "1".
;ARM 920 onwards use op2 0 and 1 - behaviour with other op2 values is as yet
;unknown...
        MACRO
Kevin Bracey's avatar
Kevin Bracey committed
164 165 166
        ARM_on_emulator $tmp,$cond
        MRC$cond ARM_config_cp,0,$tmp,ARM_ID_reg,C0,7
        TEQ$cond $tmp,#1
167 168
        MEND

169
 [ :LNOT: HAL
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 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
;flush whole TLB (both data and instruction for StrongARM)
;trashes $temp
        MACRO
        ARM_flush_TLB $temp
        ARM_read_ID $temp
        AND      $temp,$temp,#&F000
        CMP      $temp,#&8000   ;ARM 8?
        CMPNE    $temp,#&A000   ;or StrongARM?
        MCRNE    ARM_config_cp,0,R0,ARM67_TLBflush_reg,C0,0
        MCREQ    ARM_config_cp,0,R0,ARM8A_TLB_reg,C7,0
        MEND

;flush whole cache (both data and instruction for StrongARM),
;without worrying about any cache cleaning
;trashes $temp
        MACRO
        ARM_flush_cache $temp
        ARM_read_ID $temp
        AND      $temp,$temp,#&F000
        CMP      $temp,#&8000   ;ARM 8?
        CMPNE    $temp,#&A000   ;or StrongARM?
        MCRNE    ARM_config_cp,0,R0,ARM67_cacheflush_reg,C0,0
        MCREQ    ARM_config_cp,0,R0,ARM8A_cache_reg,C7,0
        MEND

;flush whole TLB and cache (both data and instruction for StrongARM),
;without worrying about any cache cleaning
;trashes $temp
        MACRO
        ARM_flush_cacheandTLB $temp
        ARM_read_ID $temp
        AND      $temp,$temp,#&F000
        CMP      $temp,#&8000   ;ARM 8?
        CMPNE    $temp,#&A000   ;or StrongARM?
        MCRNE    ARM_config_cp,0,R0,ARM67_cacheflush_reg,C0,0
        MCRNE    ARM_config_cp,0,R0,ARM67_TLBflush_reg,C0,0
        MCREQ    ARM_config_cp,0,R0,ARM8A_cache_reg,C7,0
        MCREQ    ARM_config_cp,0,R0,ARM8A_TLB_reg,C7,0
        MEND
209
 ]
Neil Turton's avatar
Neil Turton committed
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233

;
; -------------- ARM 6,7 only --------------------------------------------
;

;flush cache
        MACRO
        ARM67_flush_cache $cond
        MCR$cond ARM_config_cp,0,R0,ARM67_cacheflush_reg,C0,0
        MEND

;flush TLB
        MACRO
        ARM67_flush_TLB $cond
        MCR$cond ARM_config_cp,0,R0,ARM67_TLBflush_reg,C0,0
        MEND

;flush TLB entry, virtual address in $reg
        MACRO
        ARM67_flush_TLBentry $reg,$cond
        MCR$cond ARM_config_cp,0,$reg,ARM67_TLBpurge_reg,C0,0
        MEND

;
Kevin Bracey's avatar
Kevin Bracey committed
234 235 236
; -------------- ARM 810 only ----------------------------------------------
;

237
 [ {FALSE}
Kevin Bracey's avatar
Kevin Bracey committed
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313

;turn off branch prediction
; - the forced mispredicted branch ensures that the predictor is trapped in
;   this code segment when turned off
; - corrupts $temp and status flags
;
        MACRO
        ARM8_branchpredict_off $temp
01
        ARM_read_control $temp
        BIC $temp,$temp,#&800        ;z bit (branch prediction)
        ARM_write_control $temp
        SEC                          ;set carry flag
        BCC %BT01
        MEND

;turn on branch prediction
        MACRO
        ARM8_branchpredict_on $temp
        ARM_read_control $temp
        ORR $temp,$temp,#&800        ;z bit (branch prediction)
        ARM_write_control $temp
        MEND

;flush branch prediction, which is sufficient for an IMB (instruction memory
;barrier) on ARM 810, BUT...
; - intended for in line use only, where efficiency matters, or SWI call is
;   awkward
; - general code should use SWI OS_SynchroniseCodeAreas to implement
;   an IMB (instruction memory barrier) in future proof, ARM independent way
; - kernel code may use this without regard to which ARM running - ie. assumed
;   harmless on other ARMs
;
        MACRO
        ARM8_branchpredict_flush
        SUB PC,PC,#4        ;flush, because PC is written by data op
        MEND

;clean cache entry
; - segment,index spec in $reg
; - bits 4..6   = segment (0..7)
; - bits 26..31 = index   (0..63)
; - all other bits zero
        MACRO
        ARM8_clean_IDCentry $reg,$cond
        MCR$cond ARM_config_cp,0,$reg,ARM8A_cache_reg,C11,1
        MEND

;flush cache entry -  segment,index spec in $reg, as for ARM8_clean_IDCentry
        MACRO
        ARM8_flush_IDCentry $reg,$cond
        MCR$cond ARM_config_cp,0,$reg,ARM8A_cache_reg,C7,1
        MEND

;clean and flush cache entry -  segment,index spec in $reg, as for ARM8_clean_IDCentry
;
;if ARM810cleanflushbroken is TRUE, interrupts *must* be currently diabled (see below)
;
        MACRO
        ARM8_cleanflush_IDCentry $reg,$cond
  [ ARM810cleanflushbroken
        ARM8_clean_IDCentry $reg,$cond
        ARM8_flush_IDCentry $reg,$cond
  |
        MCR$cond ARM_config_cp,0,$reg,ARM8A_cache_reg,C15,1
  ]
        MEND

;fully clean and flush cache (assumes no locked-down entries to preserve)
;
;if ARM810cleanflushbroken is TRUE, then we have to make sure interrupts are disabled during
;the sequence of 2 MCRs that make up ARM8_cleanflush_IDCentry, to avoid an interrupt hole.
;The hole occurs if an interrupt fills and dirties the particular cache entry after the clean
;but before the flush. We don't have this problem with StrongARM, because the entry is
;specified by virtual address, and RISC OS only cleans/flushes address space not currently
;involved in interrupts.
Neil Turton's avatar
Neil Turton committed
314
;
Kevin Bracey's avatar
Kevin Bracey committed
315 316 317 318
  [ ARM810cleanflushbroken

        MACRO
        ARM8_cleanflush_IDC $temp,$temp2
Kevin Bracey's avatar
Kevin Bracey committed
319 320 321 322
        ;for simplicity, disable interrupts during entire operation
        mrs ,$temp2,CPSR
        ORR  $temp,$temp2,#I32_bit
        msr ,CPSR_c,$temp                        ;disable I
Kevin Bracey's avatar
Kevin Bracey committed
323 324 325 326 327 328 329 330 331
        MOV  $temp,#0                            ;initial segment and index
01
        ARM8_cleanflush_IDCentry $temp
        ADD $temp,$temp,#1 :SHL: 26              ;next index
        CMP $temp,#1 :SHL: 26                    ;last index done if index field wrapped to 0
        BHS %BT01
        ADD $temp,$temp,#1 :SHL: 4               ;next segment
        CMP $temp,#8 :SHL: 4                     ;8 segments done?
        BLO %BT01
Kevin Bracey's avatar
Kevin Bracey committed
332
        msr ,CPSR_c,$temp2                       ;restore I
Kevin Bracey's avatar
Kevin Bracey committed
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398
        MEND

  |

        MACRO
        ARM8_cleanflush_IDC $temp
        MOV $temp,#0                             ;initial segment and index
01
        ARM8_cleanflush_IDCentry $temp
        ADD $temp,$temp,#1 :SHL: 26              ;next index
        CMP $temp,#1 :SHL: 26                    ;last index done if index field wrapped to 0
        BHS %BT01
        ADD $temp,$temp,#1 :SHL: 4               ;next segment
        CMP $temp,#8 :SHL: 4                     ;8 segments done?
        BLO %BT01
        MEND

  ]

;flush whole TLB (actually, same as ARMA_flush_TLBs)
        MACRO
        ARM8_flush_TLB $cond
        MCR$cond ARM_config_cp,0,R0,ARM8A_TLB_reg,C7,0
        MEND

;flush TLB entry, virtual address in $reg
        MACRO
        ARM8_flush_TLBentry $reg,$cond
        MCR$cond ARM_config_cp,0,$reg,ARM8A_TLB_reg,C7,1
        MEND

;select external Refclk pin as fast clock (dynamic switching, asynchronous)
        MACRO
        ARM8_refclk_fclk $temp
        MRC ARM_config_cp,0,$temp,ARM8_CTC_reg,C0,0
        BIC $temp, $temp,#&1                        ;turn off dynamic bus switching (bit0)
        MCR ARM_config_cp,0,$temp,ARM8_CTC_reg,C0,0
        BIC $temp,$temp,#&2                         ;select asynchronous mode (default) (bit1)
        ORR $temp,$temp,#&4                         ;select REFCLK as the FCLK source (bits3:2)
        BIC $temp,$temp,#&10                        ;ensure L=0 when writing (PLL locked) (bit4)
        MCR ARM_config_cp,0,$temp,ARM8_CTC_reg,C0,0
        NOP
        NOP
        NOP
        NOP
        ORR $temp,$temp,#&1                         ;select dynamic clock switching (bit0)
        MCR ARM_config_cp,0,$temp,ARM8_CTC_reg,C0,0
        MEND

;select PLL output as fast clock (dynamic switching, asynchronous)
        MACRO
        ARM8_pll_fclk $temp
        MRC ARM_config_cp,0,$temp,ARM8_CTC_reg,C0,0
        BIC $temp,$temp,#&1                         ;turn off dynamic bus switching (bit0)
        MCR ARM_config_cp,0,$temp,ARM8_CTC_reg,C0,0
        BIC $temp,$temp,#&2                         ;select asynchronous mode (default) (bit1)
        ORR $temp,$temp,#&C                         ;select PLLClkOut as the FCLK source (bits3:2)
        BIC $temp,$temp,#&10                        ;ensure L=0 when writing (PLL locked) (bit4)
        MCR ARM_config_cp,0,$temp,ARM8_CTC_reg,C0,0
        NOP
        NOP
        NOP
        NOP
        ORR $temp,$temp,#&1                         ;select dynamic clock switching (bit0)
        MCR ARM_config_cp,0,$temp,ARM8_CTC_reg,C0,0
        MEND
Neil Turton's avatar
Neil Turton committed
399

Kevin Bracey's avatar
Kevin Bracey committed
400
 ] ;ARM810support
Neil Turton's avatar
Neil Turton committed
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478

;
; -------------- StrongARM only ------------------------------------------
;

;clean whole data cache, using 16k private cleaner area at address in
;$cleanaddr
;trashes $cleanaddr,$temp1,$temp2
;
;method:
;clean whole (16k) data cache by reading 16k private cleaner area in 8-word
;(one cache line) steps
;
;note: this routine should NOT be used as is without care - remember
;      1) interrupts should be off (to guarantee this clean is effective)
;      2) DC should be flushed afterwards (to guarantee next clean using
;         private area is effective, ie. all private area flushed out now)
;      see ARMA_fullycleanflush_DC for 'packaged routine'
;
        MACRO
        ARMA_clean_DC $cleanaddr,$temp1,$temp2
        ADD     $temp1,$cleanaddr,#16*1024
10
        LDR     $temp2,[$cleanaddr],#32
        TEQ     $temp1,$cleanaddr
        BNE     %BT10
        MEND

;flush whole data cache
        MACRO
        ARMA_flush_DC $cond
        MCR$cond ARM_config_cp,0,R0,ARM8A_cache_reg,C6,0
        MEND

;clean data cache entry, virtual addr in $reg
        MACRO
        ARMA_clean_DCentry $reg,$cond
        MCR$cond ARM_config_cp,0,$reg,ARM8A_cache_reg,C10,1
        MEND

;flush data cache entry, virtual addr in $reg
        MACRO
        ARMA_flush_DCentry $reg,$cond
        MCR$cond ARM_config_cp,0,$reg,ARM8A_cache_reg,C6,1
        MEND

;clean and flush data cache entry, virtual addr in $reg
        MACRO
        ARMA_cleanflush_DCentry $reg,$cond
        MCR$cond ARM_config_cp,0,$reg,ARM8A_cache_reg,C14,1
        MEND

;clean data cache for virtual address range from $lo (inclusive) to $hi (exclusive)
;corrupts $lo,$hi
        MACRO
        ARMA_clean_DCrange $lo,$hi
        BIC     $lo,$lo,#31    ;align down to 8-word (1 cache line) boundary
        ADD     $hi,$hi,#31
        BIC     $hi,$hi,#31    ;align up to 8-word boundary
01
        ARMA_clean_DCentry $lo ;clean entry for virtual address $lo
        ADD     $lo,$lo,#32    ;next line
        ARMA_clean_DCentry $lo
        ADD     $lo,$lo,#32
        ARMA_clean_DCentry $lo
        ADD     $lo,$lo,#32
        ARMA_clean_DCentry $lo
        ADD     $lo,$lo,#32
        CMP     $lo,$hi
        BLO     %BT01
        MEND

;drain write buffer
        MACRO
        ARMA_drain_WB $cond
        MCR$cond ARM_config_cp,0,R0,ARM8A_cache_reg,C10,4
        MEND

479 480 481 482 483
        MACRO
        ARM_drain_WB $cond
        MCR$cond ARM_config_cp,0,R0,ARM8A_cache_reg,C10,4
        MEND

Neil Turton's avatar
Neil Turton committed
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
;flush whole instruction cache
        MACRO
        ARMA_flush_IC $WithoutNOPs,$cond
        MCR$cond ARM_config_cp,0,R0,ARM8A_cache_reg,C5,0
      [ "$WithoutNOPs" = ""
        MOV     R0,R0 ; 4 NOPS - up to 4 further instructions may come from IC before flush
        MOV     R0,R0
        MOV     R0,R0
        MOV     R0,R0
      ]
        MEND

;flush whole instruction cache and whole data cache
        MACRO
        ARMA_flush_ICandDC $WithoutNOPs,$cond
        MCR$cond ARM_config_cp,0,R0,ARM8A_cache_reg,C7,0
      [ "$WithoutNOPs" = ""
        MOV     R0,R0 ; 4 NOPS - up to 4 further instructions may come from IC before flush
        MOV     R0,R0
        MOV     R0,R0
        MOV     R0,R0
      ]
        MEND

;flush whole instruction TLB
        MACRO
        ARMA_flush_ITLB $cond
        MCR$cond ARM_config_cp,0,R0,ARM8A_TLB_reg,C5,0
        MEND

;flush whole data TLB
        MACRO
        ARMA_flush_DTLB $cond
        MCR$cond ARM_config_cp,0,R0,ARM8A_TLB_reg,C6,0
        MEND

;flush whole instruction and data TLBs
        MACRO
        ARMA_flush_TLBs $cond
        MCR$cond ARM_config_cp,0,R0,ARM8A_TLB_reg,C7,0
        MEND

;flush data TLB entry, virtual address in $reg
        MACRO
        ARMA_flush_DTLBentry $reg,$cond
        MCR$cond ARM_config_cp,0,$reg,ARM8A_TLB_reg,C6,1
        MEND

;fully clean and flush DC - see ARMA_clean_DC for more info
        MACRO
        ARMA_fullycleanflush_DC $cleanaddr,$temp1,$temp2,$temp3
Kevin Bracey's avatar
Kevin Bracey committed
535 536 537
        mrs    ,$temp3,CPSR
        ORR     $temp1,$temp3,#I32_bit
        msr    ,CPSR_c,$temp1         ;disable IRQs
Neil Turton's avatar
Neil Turton committed
538 539
        ARMA_clean_DC $cleanaddr,$temp1,$temp2
        ARMA_flush_DC
Kevin Bracey's avatar
Kevin Bracey committed
540
        msr    ,CPSR_c,$temp3         ;restore IRQ state
Neil Turton's avatar
Neil Turton committed
541 542 543 544 545 546 547 548 549 550 551 552 553 554
        MEND

;enable core clock switching (fast core clock allowed)
        MACRO
        ARMA_fastcoreclock $cond
        MCR$cond ARM_config_cp,0,R0,ARMA_TCI_reg,C1,2
        MEND

;disable core clock switching (core clock is memory clock)
        MACRO
        ARMA_slowcoreclock $cond
        MCR$cond ARM_config_cp,0,R0,ARMA_TCI_reg,C2,2
        MEND

555 556 557 558 559 560 561
;
; -------------- Additional ARMv7 stuff -----------------------------------
;

; Provided here are ISB, DSB and DMB macros suitable for ARMv6+
; Although ARMv4 & v5 do provide CP15 ops that are compatible with the ARMv6 ops, it's implementation defined whether each processor implements the ops or not (and the ops are unpredictable if unimplemented)
; So to play it safe these macros will complain if used on pre-ARMv6
562 563
; For all the macros, set the $quick to something if the value of $temp is
; already zero (this will cut out a pointless MOV)
564 565 566 567 568

; Instruction Synchronisation Barrier - required on ARMv6+ to ensure the effects of the following are visible to following instructions:
; * Completed cache, TLB & branch predictor maintenance operations
; * CP14/CP15 writes
        MACRO
569 570
        myISB $cond,$temp,$option,$quick
     [ NoARMv6
571
        ! 1, "Don't know what to do on pre-ARMv6!"
572 573
     |
      [ NoARMv7
574
        ; ARMv6, use legacy MCR op
Jeffrey Lee's avatar
Jeffrey Lee committed
575
       [ "$quick"=""
576
        MOV$cond $temp,#0
577
       ]
578
        MCR$cond p15,0,$temp,c7,c5,4
579
      |
580 581 582 583
        ; ARMv7+, use ISB instruction (saves on temp register, but instruction is unconditional)
        ; Shouldn't hurt too much if we just ignore the condition code
        DCI &F57FF06F ; ISB SY
      ]
584
     ]
585 586 587 588
        MEND

; Data Synchronisation Barrier - aka drain write buffer/data write barrier. Stalls pipeline until all preceeding memory accesses (including cache/TLB/BTC ops complete.
        MACRO
589
        myDSB $cond,$temp,$option,$quick
590 591 592 593 594
     [ NoARMv6
        ! 1, "Don't know what to do on pre-ARMv6!"
     |
      [ NoARMv7
        ; pre-ARMv7, use legacy MCR op
595
       [ "$quick"=""
596
        MOV$cond $temp,#0
597
       ]
598 599 600 601 602 603 604 605 606 607
        MCR$cond p15,0,$temp,c7,c10,4
      |
        ; ARMv7+, use DSB instruction
       [ "$option"="SY" :LOR: "$option"=""
        DCI &F57FF04F ; DSB SY
       |
       [ "$option"="ST" :LOR: "$option"="SYST"
        DCI &F57FF04E ; DSB ST
       |
       [ "$option"="ISH"
Jeffrey Lee's avatar
Jeffrey Lee committed
608
        DCI &F57FF04B ; DSB ISH
609 610
       |
       [ "$option"="ISHST"
Jeffrey Lee's avatar
Jeffrey Lee committed
611
        DCI &F57FF04A ; DSB ISHST
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
       |
       [ "$option"="NSH"
        DCI &F57FF047 ; DSB NSH
       |
       [ "$option"="NSHST"
        DCI &F57FF046 ; DSB NSHST
       |
       [ "$option"="OSH"
        DCI &F57FF043 ; DSB OSH
       |
       [ "$option"="OSHST"
        DCI &F57FF042 ; DSB OSHST
       |
        ! 1, "Unrecognised DSB option"
       ]
       ]
       ]
       ]
       ]
       ]
       ]
       ]
      ]
     ]
        MEND

; Data Memory Barrier - More lightweight DSB, ensures memory accesses behave correctly without stalling the pipeline to wait for preceeding accesses to complete. I.e. it's only good for synchronising load/store instructions.
        MACRO
640
        myDMB $cond,$temp,$option,$quick
641 642 643 644 645
     [ NoARMv6
        ! 1, "Don't know what to do on pre-ARMv6!"
     |
      [ NoARMv7
        ; ARMv6, use legacy MCR op
646
       [ "$quick"=""
647
        MOV$cond $temp,#0
648
       ]
649 650 651 652 653 654 655 656 657 658
        MCR$cond p15,0,$temp,c7,c10,5
      |
        ; ARMv7+, use DMB instruction
       [ "$option"="SY" :LOR: "$option"=""
        DCI &F57FF05F ; DMB SY
       |
       [ "$option"="ST" :LOR: "$option"="SYST"
        DCI &F57FF05E ; DMB ST
       |
       [ "$option"="ISH"
Jeffrey Lee's avatar
Jeffrey Lee committed
659
        DCI &F57FF05B ; DMB ISH
660 661
       |
       [ "$option"="ISHST"
Jeffrey Lee's avatar
Jeffrey Lee committed
662
        DCI &F57FF05A ; DMB ISHST
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
       |
       [ "$option"="NSH"
        DCI &F57FF057 ; DMB NSH
       |
       [ "$option"="NSHST"
        DCI &F57FF056 ; DMB NSHST
       |
       [ "$option"="OSH"
        DCI &F57FF053 ; DMB OSH
       |
       [ "$option"="OSHST"
        DCI &F57FF052 ; DMB OSHST
       |
        ! 1, "Unrecognised DMB option"
       ]
       ]
       ]
       ]
       ]
       ]
       ]
       ]
      ]
     ]
        MEND

Neil Turton's avatar
Neil Turton committed
689 690

    END