1/* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Copyright (C) 2003, 2004 Ralf Baechle <ralf@linux-mips.org> 7 * Copyright (C) MIPS Technologies, Inc. 8 * written by Ralf Baechle <ralf@linux-mips.org> 9 */ 10#ifndef _ASM_HAZARDS_H 11#define _ASM_HAZARDS_H 12 13 14#ifdef __ASSEMBLY__ 15#define ASMMACRO(name, code...) .macro name; code; .endm 16#else 17 18#define ASMMACRO(name, code...) \ 19__asm__(".macro " #name "; " #code "; .endm"); \ 20 \ 21static inline void name(void) \ 22{ \ 23 __asm__ __volatile__ (#name); \ 24} 25 26#endif 27 28ASMMACRO(_ssnop, 29 sll $0, $0, 1 30 ) 31 32ASMMACRO(_ehb, 33 sll $0, $0, 3 34 ) 35 36/* 37 * TLB hazards 38 */ 39#if defined(CONFIG_CPU_MIPSR2) 40 41/* 42 * MIPSR2 defines ehb for hazard avoidance 43 */ 44 45ASMMACRO(mtc0_tlbw_hazard, 46 _ehb 47 ) 48ASMMACRO(tlbw_use_hazard, 49 _ehb 50 ) 51ASMMACRO(tlb_probe_hazard, 52 _ehb 53 ) 54ASMMACRO(irq_enable_hazard, 55 _ehb 56 ) 57ASMMACRO(irq_disable_hazard, 58 _ehb 59 ) 60ASMMACRO(back_to_back_c0_hazard, 61 _ehb 62 ) 63/* 64 * gcc has a tradition of misscompiling the previous construct using the 65 * address of a label as argument to inline assembler. Gas otoh has the 66 * annoying difference between la and dla which are only usable for 32-bit 67 * rsp. 64-bit code, so can't be used without conditional compilation. 68 * The alterantive is switching the assembler to 64-bit code which happens 69 * to work right even for 32-bit code ... 70 */ 71#define instruction_hazard() \ 72do { \ 73 unsigned long tmp; \ 74 \ 75 __asm__ __volatile__( \ 76 " .set mips64r2 \n" \ 77 " dla %0, 1f \n" \ 78 " jr.hb %0 \n" \ 79 " .set mips0 \n" \ 80 "1: \n" \ 81 : "=r" (tmp)); \ 82} while (0) 83 84#elif defined(CONFIG_CPU_R10000) 85 86/* 87 * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer. 88 */ 89 90ASMMACRO(mtc0_tlbw_hazard, 91 ) 92ASMMACRO(tlbw_use_hazard, 93 ) 94ASMMACRO(tlb_probe_hazard, 95 ) 96ASMMACRO(irq_enable_hazard, 97 ) 98ASMMACRO(irq_disable_hazard, 99 ) 100ASMMACRO(back_to_back_c0_hazard, 101 ) 102#define instruction_hazard() do { } while (0) 103 104#elif defined(CONFIG_CPU_RM9000) 105 106/* 107 * RM9000 hazards. When the JTLB is updated by tlbwi or tlbwr, a subsequent 108 * use of the JTLB for instructions should not occur for 4 cpu cycles and use 109 * for data translations should not occur for 3 cpu cycles. 110 */ 111 112ASMMACRO(mtc0_tlbw_hazard, 113 _ssnop; _ssnop; _ssnop; _ssnop 114 ) 115ASMMACRO(tlbw_use_hazard, 116 _ssnop; _ssnop; _ssnop; _ssnop 117 ) 118ASMMACRO(tlb_probe_hazard, 119 _ssnop; _ssnop; _ssnop; _ssnop 120 ) 121ASMMACRO(irq_enable_hazard, 122 ) 123ASMMACRO(irq_disable_hazard, 124 ) 125ASMMACRO(back_to_back_c0_hazard, 126 ) 127#define instruction_hazard() do { } while (0) 128 129#elif defined(CONFIG_CPU_SB1) 130 131/* 132 * Mostly like R4000 for historic reasons 133 */ 134ASMMACRO(mtc0_tlbw_hazard, 135 ) 136ASMMACRO(tlbw_use_hazard, 137 ) 138ASMMACRO(tlb_probe_hazard, 139 ) 140ASMMACRO(irq_enable_hazard, 141 ) 142ASMMACRO(irq_disable_hazard, 143 _ssnop; _ssnop; _ssnop 144 ) 145ASMMACRO(back_to_back_c0_hazard, 146 ) 147#define instruction_hazard() do { } while (0) 148 149#else 150 151/* 152 * Finally the catchall case for all other processors including R4000, R4400, 153 * R4600, R4700, R5000, RM7000, NEC VR41xx etc. 154 * 155 * The taken branch will result in a two cycle penalty for the two killed 156 * instructions on R4000 / R4400. Other processors only have a single cycle 157 * hazard so this is nice trick to have an optimal code for a range of 158 * processors. 159 * Make it compatible with Mips32r2 processors 160 */ 161ASMMACRO(mtc0_tlbw_hazard, 162 nop; nop; _ehb 163 ) 164ASMMACRO(tlbw_use_hazard, 165 nop; nop; nop; _ehb 166 ) 167ASMMACRO(tlb_probe_hazard, 168 nop; nop; nop; _ehb 169 ) 170ASMMACRO(irq_enable_hazard, 171 _ehb 172 ) 173ASMMACRO(irq_disable_hazard, 174 nop; nop; nop; _ehb 175 ) 176ASMMACRO(back_to_back_c0_hazard, 177 _ssnop; _ssnop; _ssnop; _ehb 178 ) 179#define instruction_hazard() do { } while (0) 180 181#endif 182 183 184/* FPU hazards */ 185 186#if defined(CONFIG_CPU_SB1) 187ASMMACRO(enable_fpu_hazard, 188 .set push; 189 .set mips64; 190 .set noreorder; 191 _ssnop; 192 bnezl $0,.+4; 193 _ssnop; 194 .set pop 195) 196ASMMACRO(disable_fpu_hazard, 197) 198 199#elif defined(CONFIG_CPU_MIPSR2) 200ASMMACRO(enable_fpu_hazard, 201 _ehb 202) 203ASMMACRO(disable_fpu_hazard, 204 _ehb 205) 206#else 207ASMMACRO(enable_fpu_hazard, 208 nop; nop; nop; nop; _ehb 209) 210ASMMACRO(disable_fpu_hazard, 211 _ehb 212) 213#endif 214 215#endif /* _ASM_HAZARDS_H */ 216