;
; Copyright (c) Microsoft Corporation.  All rights reserved.
;
;
; Use of this source code is subject to the terms of the Microsoft end-user
; license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
; If you did not accept the terms of the EULA, you are not authorized to use
; this source code. For a copy of the EULA, please see the LICENSE.RTF on your
; install media.
;
;
;------------------------------------------------------------------------------
;
;   File:  DCache.s
;
;   To invalidate Data Cache Lines
;
;------------------------------------------------------------------------------

        INCLUDE kxarm.h

        TEXTAREA

;-------------------------------------------------------------------------------------
; void InvalidateDCacheForG2D(VOID *pAddress, DWORD width, DWORD height, DWORD stride)
;-------------------------------------------------------------------------------------
    LEAF_ENTRY InvalidateDCacheForG2D

        stmfd   sp!, {r4-r8}                    ; store off registers to stack

        mov     r4, #64
        mvn     r6, #63

Inv_Loop_Height
        mov     r5, r1
        
        mov     r7, r0               
        and     r7, r7, r6
        sub     r8, r0, r7
        add     r5, r5, r8
                     
Inv_Loop_Width
        mcr     p15, 0, r7, c7, c6, 1           ; invalidate entry
        add     r7, r7, r4                      ; move to next
        subs    r5, r5, r4
        bgt     Inv_Loop_Width                  ; loop while > 0 bytes left

        add     r0, r0, r3
        subs    r2, r2, #1
        bgt     Inv_Loop_Height

        mov     r0, #0
        DCD     0xf57ff04f                      ; DSB (Data Synchronization Barrier)
        mcr     p15, 0, r0, c7, c5, 6           ; flush the BTAC (Entire Branch Preditor array)
        
        DCD     0xf57ff04f                      ; DSB (Data Synchronization Barrier)
        DCD     0xf57ff06f                      ; ISB (Instruction Synchronization Barrier)

        ldmfd   sp!, {r4-r8}                    ; restore registers
        mov	    pc, lr


;--------------------------------------------------------------------------------
; void CleanDCacheForG2D(VOID *pAddress, DWORD width, DWORD height, DWORD stride)
;--------------------------------------------------------------------------------
        LEAF_ENTRY CleanDCacheForG2D
        
        stmfd   sp!, {r4-r8}                    ; store off registers to stack

        mov     r4, #64
        mvn     r6, #63

Clean_Loop_Height
        mov     r5, r1
        
        mov     r7, r0               
        and     r7, r7, r6
        sub     r8, r0, r7
        add     r5, r5, r8

Clean_Loop_Width                     
        mcr     p15, 0, r7, c7, c10, 1          ; clean and invalidate entry
        add     r7, r7, r4                      ; move to next
        subs    r5, r5, r4
        bgt     Clean_Loop_Width                ; loop while > 0 bytes left

        add     r0, r0, r3
        subs    r2, r2, #1
        bgt     Clean_Loop_Height

        mov     r2, #0
        ;mcr     p15, 0, r2, c7, c10, 4         ; data sync barrier operation
        DCD     0xf57ff04f                      ; DSB (Data Synchronization Barrier)
        mcr     p15, 0, r2, c7, c5, 6           ; flush the BTAC (Entire Branch Preditor array)

        DCD     0xf57ff04f                      ; DSB (Data Synchronization Barrier)
        DCD     0xf57ff06f                      ; ISB (Instruction Synchronization Barrier)

        ldmfd   sp!, {r4-r8}                    ; restore registers
        mov	    pc, lr


;---------------------------------------------------------------------------------------------
; void CleanAndInvalidateDCacheForG2D(VOID *pAddress, DWORD width, DWORD height, DWORD stride)
;---------------------------------------------------------------------------------------------
  LEAF_ENTRY CleanAndInvalidateDCacheForG2D

        stmfd   sp!, {r4-r8}                    ; store off registers to stack

        mov     r4, #64
        mvn     r6, #63

CleanAndInv_Loop_Height
        mov     r5, r1
        
        mov     r7, r0               
        and     r7, r7, r6
        sub     r8, r0, r7
        add     r5, r5, r8
                     
CleanAndInv_Loop_Width
        mcr     p15, 0, r7, c7, c14, 1          ; clean and invalidate entry
        add     r7, r7, r4                      ; move to next
        subs    r5, r5, r4
        bgt     CleanAndInv_Loop_Width          ; loop while > 0 bytes left

        add     r0, r0, r3
        subs    r2, r2, #1
        bgt     CleanAndInv_Loop_Height

        mov     r0, #0
        DCD     0xf57ff04f                      ; DSB (Data Synchronization Barrier)
        mcr     p15, 0, r0, c7, c5, 6           ; flush the BTAC (Entire Branch Preditor array)
        
        DCD     0xf57ff04f                      ; DSB (Data Synchronization Barrier)
        DCD     0xf57ff06f                      ; ISB (Instruction Synchronization Barrier)

        ldmfd   sp!, {r4-r8}                    ; restore registers
        mov	    pc, lr


    end
