/* * Copyright 2010 Tilera Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, version 2. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or * NON INFRINGEMENT. See the GNU General Public License for * more details. * A routine for synchronizing the instruction and data caches. * Useful for self-modifying code. * * r0 holds the buffer address * r1 holds the size in bytes */ #include #include #if defined(__NEWLIB__) || defined(__BME__) #include #else #include #endif #ifdef __tilegx__ /* Share code among Tile family chips but adjust opcodes appropriately. */ #define slt cmpltu #define bbst blbst #define bnezt bnzt #endif #if defined(__tilegx__) && __SIZEOF_POINTER__ == 4 /* Force 32-bit ops so pointers wrap around appropriately. */ #define ADD_PTR addx #define ADDI_PTR addxi #else #define ADD_PTR add #define ADDI_PTR addi #endif .section .text.__invalidate_icache, "ax" .global __invalidate_icache .type __invalidate_icache,@function .hidden __invalidate_icache .align 8 __invalidate_icache: FEEDBACK_ENTER(__invalidate_icache) { ADD_PTR r1, r0, r1 /* end of buffer */ blez r1, .Lexit /* skip out if size <= 0 */ } { ADDI_PTR r1, r1, -1 /* point to last byte to flush */ andi r0, r0, -CHIP_L1I_LINE_SIZE() /* align to cache-line size */ } { andi r1, r1, -CHIP_L1I_LINE_SIZE() /* last cache line to flush */ mf } #if CHIP_L1I_CACHE_SIZE() > PAGE_SIZE { moveli r4, CHIP_L1I_CACHE_SIZE() / PAGE_SIZE /* loop counter */ move r2, r0 /* remember starting address */ } #endif drain { slt r3, r0, r1 /* set up loop invariant */ #if CHIP_L1I_CACHE_SIZE() > PAGE_SIZE moveli r6, PAGE_SIZE #endif } .Lentry: { icoh r0 ADDI_PTR r0, r0, CHIP_L1I_LINE_SIZE() /* advance buffer */ } { slt r3, r0, r1 /* check if buffer < buffer + size */ bbst r3, .Lentry /* loop if buffer < buffer + size */ } #if CHIP_L1I_CACHE_SIZE() > PAGE_SIZE { ADD_PTR r2, r2, r6 ADD_PTR r1, r1, r6 } { move r0, r2 addi r4, r4, -1 } { slt r3, r0, r1 /* set up loop invariant */ bnezt r4, .Lentry } #endif drain .Lexit: jrp lr .Lend___invalidate_icache: .size __invalidate_icache, \ .Lend___invalidate_icache - __invalidate_icache