diff options
-rw-r--r-- | arch/mips/include/asm/mipsregs.h | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 7a59ad6e7f7d..ac70613fd3b8 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h | |||
@@ -1181,6 +1181,89 @@ static inline int mm_insn_16bit(u16 insn) | |||
1181 | #endif | 1181 | #endif |
1182 | 1182 | ||
1183 | /* | 1183 | /* |
1184 | * parse_r var, r - Helper assembler macro for parsing register names. | ||
1185 | * | ||
1186 | * This converts the register name in $n form provided in \r to the | ||
1187 | * corresponding register number, which is assigned to the variable \var. It is | ||
1188 | * needed to allow explicit encoding of instructions in inline assembly where | ||
1189 | * registers are chosen by the compiler in $n form, allowing us to avoid using | ||
1190 | * fixed register numbers. | ||
1191 | * | ||
1192 | * It also allows newer instructions (not implemented by the assembler) to be | ||
1193 | * transparently implemented using assembler macros, instead of needing separate | ||
1194 | * cases depending on toolchain support. | ||
1195 | * | ||
1196 | * Simple usage example: | ||
1197 | * __asm__ __volatile__("parse_r __rt, %0\n\t" | ||
1198 | * ".insn\n\t" | ||
1199 | * "# di %0\n\t" | ||
1200 | * ".word (0x41606000 | (__rt << 16))" | ||
1201 | * : "=r" (status); | ||
1202 | */ | ||
1203 | |||
1204 | /* Match an individual register number and assign to \var */ | ||
1205 | #define _IFC_REG(n) \ | ||
1206 | ".ifc \\r, $" #n "\n\t" \ | ||
1207 | "\\var = " #n "\n\t" \ | ||
1208 | ".endif\n\t" | ||
1209 | |||
1210 | __asm__(".macro parse_r var r\n\t" | ||
1211 | "\\var = -1\n\t" | ||
1212 | _IFC_REG(0) _IFC_REG(1) _IFC_REG(2) _IFC_REG(3) | ||
1213 | _IFC_REG(4) _IFC_REG(5) _IFC_REG(6) _IFC_REG(7) | ||
1214 | _IFC_REG(8) _IFC_REG(9) _IFC_REG(10) _IFC_REG(11) | ||
1215 | _IFC_REG(12) _IFC_REG(13) _IFC_REG(14) _IFC_REG(15) | ||
1216 | _IFC_REG(16) _IFC_REG(17) _IFC_REG(18) _IFC_REG(19) | ||
1217 | _IFC_REG(20) _IFC_REG(21) _IFC_REG(22) _IFC_REG(23) | ||
1218 | _IFC_REG(24) _IFC_REG(25) _IFC_REG(26) _IFC_REG(27) | ||
1219 | _IFC_REG(28) _IFC_REG(29) _IFC_REG(30) _IFC_REG(31) | ||
1220 | ".iflt \\var\n\t" | ||
1221 | ".error \"Unable to parse register name \\r\"\n\t" | ||
1222 | ".endif\n\t" | ||
1223 | ".endm"); | ||
1224 | |||
1225 | #undef _IFC_REG | ||
1226 | |||
1227 | /* | ||
1228 | * C macros for generating assembler macros for common instruction formats. | ||
1229 | * | ||
1230 | * The names of the operands can be chosen by the caller, and the encoding of | ||
1231 | * register operand \<Rn> is assigned to __<Rn> where it can be accessed from | ||
1232 | * the ENC encodings. | ||
1233 | */ | ||
1234 | |||
1235 | /* Instructions with no operands */ | ||
1236 | #define _ASM_MACRO_0(OP, ENC) \ | ||
1237 | __asm__(".macro " #OP "\n\t" \ | ||
1238 | ENC \ | ||
1239 | ".endm") | ||
1240 | |||
1241 | /* Instructions with 2 register operands */ | ||
1242 | #define _ASM_MACRO_2R(OP, R1, R2, ENC) \ | ||
1243 | __asm__(".macro " #OP " " #R1 ", " #R2 "\n\t" \ | ||
1244 | "parse_r __" #R1 ", \\" #R1 "\n\t" \ | ||
1245 | "parse_r __" #R2 ", \\" #R2 "\n\t" \ | ||
1246 | ENC \ | ||
1247 | ".endm") | ||
1248 | |||
1249 | /* Instructions with 3 register operands */ | ||
1250 | #define _ASM_MACRO_3R(OP, R1, R2, R3, ENC) \ | ||
1251 | __asm__(".macro " #OP " " #R1 ", " #R2 ", " #R3 "\n\t" \ | ||
1252 | "parse_r __" #R1 ", \\" #R1 "\n\t" \ | ||
1253 | "parse_r __" #R2 ", \\" #R2 "\n\t" \ | ||
1254 | "parse_r __" #R3 ", \\" #R3 "\n\t" \ | ||
1255 | ENC \ | ||
1256 | ".endm") | ||
1257 | |||
1258 | /* Instructions with 2 register operands and 1 optional select operand */ | ||
1259 | #define _ASM_MACRO_2R_1S(OP, R1, R2, SEL3, ENC) \ | ||
1260 | __asm__(".macro " #OP " " #R1 ", " #R2 ", " #SEL3 " = 0\n\t" \ | ||
1261 | "parse_r __" #R1 ", \\" #R1 "\n\t" \ | ||
1262 | "parse_r __" #R2 ", \\" #R2 "\n\t" \ | ||
1263 | ENC \ | ||
1264 | ".endm") | ||
1265 | |||
1266 | /* | ||
1184 | * TLB Invalidate Flush | 1267 | * TLB Invalidate Flush |
1185 | */ | 1268 | */ |
1186 | static inline void tlbinvf(void) | 1269 | static inline void tlbinvf(void) |