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) 1996, 98, 99, 2000, 01 Ralf Baechle 7 * 8 * Multi-arch abstraction and asm macros for easier reading: 9 * Copyright (C) 1996 David S. Miller (davem@davemloft.net) 10 * 11 * Carsten Langgaard, carstenl@mips.com 12 * Copyright (C) 2000 MIPS Technologies, Inc. 13 * Copyright (C) 1999, 2001 Silicon Graphics, Inc. 14 */ 15#include <linux/export.h> 16#include <asm/asm.h> 17#include <asm/asmmacro.h> 18#include <asm/errno.h> 19#include <asm/fpregdef.h> 20#include <asm/mipsregs.h> 21#include <asm/asm-offsets.h> 22#include <asm/regdef.h> 23 24/* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */ 25#undef fp 26 27 .macro EX insn, reg, src 28 .set push 29 .set hardfloat 30 .set nomacro 31.ex\@: \insn \reg, \src 32 .set pop 33 .section __ex_table,"a" 34 PTR_WD .ex\@, fault 35 .previous 36 .endm 37 38/* 39 * Save a thread's fp context. 40 */ 41LEAF(_save_fp) 42EXPORT_SYMBOL(_save_fp) 43#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPSR2) || \ 44 defined(CONFIG_CPU_MIPSR5) || defined(CONFIG_CPU_MIPSR6) 45 mfc0 t0, CP0_STATUS 46#endif 47 fpu_save_double a0 t0 t1 # clobbers t1 48 jr ra 49 END(_save_fp) 50 51/* 52 * Restore a thread's fp context. 53 */ 54LEAF(_restore_fp) 55#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPSR2) || \ 56 defined(CONFIG_CPU_MIPSR5) || defined(CONFIG_CPU_MIPSR6) 57 mfc0 t0, CP0_STATUS 58#endif 59 fpu_restore_double a0 t0 t1 # clobbers t1 60 jr ra 61 END(_restore_fp) 62 63#ifdef CONFIG_CPU_HAS_MSA 64 65/* 66 * Save a thread's MSA vector context. 67 */ 68LEAF(_save_msa) 69EXPORT_SYMBOL(_save_msa) 70 msa_save_all a0 71 jr ra 72 END(_save_msa) 73 74/* 75 * Restore a thread's MSA vector context. 76 */ 77LEAF(_restore_msa) 78 msa_restore_all a0 79 jr ra 80 END(_restore_msa) 81 82LEAF(_init_msa_upper) 83 msa_init_all_upper 84 jr ra 85 END(_init_msa_upper) 86 87#endif 88 89 .set noreorder 90 91/** 92 * _save_fp_context() - save FP context from the FPU 93 * @a0 - pointer to fpregs field of sigcontext 94 * @a1 - pointer to fpc_csr field of sigcontext 95 * 96 * Save FP context, including the 32 FP data registers and the FP 97 * control & status register, from the FPU to signal context. 98 */ 99LEAF(_save_fp_context) 100 .set push 101 .set hardfloat 102 cfc1 t1, fcr31 103 .set pop 104 105#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPSR2) || \ 106 defined(CONFIG_CPU_MIPSR5) || defined(CONFIG_CPU_MIPSR6) 107 .set push 108 .set hardfloat 109#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5) 110 .set mips32r2 111 .set fp=64 112 mfc0 t0, CP0_STATUS 113 sll t0, t0, 5 114 bgez t0, 1f # skip storing odd if FR=0 115 nop 116#endif 117 /* Store the 16 odd double precision registers */ 118 EX sdc1 $f1, 8(a0) 119 EX sdc1 $f3, 24(a0) 120 EX sdc1 $f5, 40(a0) 121 EX sdc1 $f7, 56(a0) 122 EX sdc1 $f9, 72(a0) 123 EX sdc1 $f11, 88(a0) 124 EX sdc1 $f13, 104(a0) 125 EX sdc1 $f15, 120(a0) 126 EX sdc1 $f17, 136(a0) 127 EX sdc1 $f19, 152(a0) 128 EX sdc1 $f21, 168(a0) 129 EX sdc1 $f23, 184(a0) 130 EX sdc1 $f25, 200(a0) 131 EX sdc1 $f27, 216(a0) 132 EX sdc1 $f29, 232(a0) 133 EX sdc1 $f31, 248(a0) 1341: .set pop 135#endif 136 137 .set push 138 .set hardfloat 139 /* Store the 16 even double precision registers */ 140 EX sdc1 $f0, 0(a0) 141 EX sdc1 $f2, 16(a0) 142 EX sdc1 $f4, 32(a0) 143 EX sdc1 $f6, 48(a0) 144 EX sdc1 $f8, 64(a0) 145 EX sdc1 $f10, 80(a0) 146 EX sdc1 $f12, 96(a0) 147 EX sdc1 $f14, 112(a0) 148 EX sdc1 $f16, 128(a0) 149 EX sdc1 $f18, 144(a0) 150 EX sdc1 $f20, 160(a0) 151 EX sdc1 $f22, 176(a0) 152 EX sdc1 $f24, 192(a0) 153 EX sdc1 $f26, 208(a0) 154 EX sdc1 $f28, 224(a0) 155 EX sdc1 $f30, 240(a0) 156 EX sw t1, 0(a1) 157 jr ra 158 li v0, 0 # success 159 .set pop 160 END(_save_fp_context) 161 162/** 163 * _restore_fp_context() - restore FP context to the FPU 164 * @a0 - pointer to fpregs field of sigcontext 165 * @a1 - pointer to fpc_csr field of sigcontext 166 * 167 * Restore FP context, including the 32 FP data registers and the FP 168 * control & status register, from signal context to the FPU. 169 */ 170LEAF(_restore_fp_context) 171 EX lw t1, 0(a1) 172 173#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPSR2) || \ 174 defined(CONFIG_CPU_MIPSR5) || defined(CONFIG_CPU_MIPSR6) 175 .set push 176 .set hardfloat 177#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5) 178 .set mips32r2 179 .set fp=64 180 mfc0 t0, CP0_STATUS 181 sll t0, t0, 5 182 bgez t0, 1f # skip loading odd if FR=0 183 nop 184#endif 185 EX ldc1 $f1, 8(a0) 186 EX ldc1 $f3, 24(a0) 187 EX ldc1 $f5, 40(a0) 188 EX ldc1 $f7, 56(a0) 189 EX ldc1 $f9, 72(a0) 190 EX ldc1 $f11, 88(a0) 191 EX ldc1 $f13, 104(a0) 192 EX ldc1 $f15, 120(a0) 193 EX ldc1 $f17, 136(a0) 194 EX ldc1 $f19, 152(a0) 195 EX ldc1 $f21, 168(a0) 196 EX ldc1 $f23, 184(a0) 197 EX ldc1 $f25, 200(a0) 198 EX ldc1 $f27, 216(a0) 199 EX ldc1 $f29, 232(a0) 200 EX ldc1 $f31, 248(a0) 2011: .set pop 202#endif 203 .set push 204 .set hardfloat 205 EX ldc1 $f0, 0(a0) 206 EX ldc1 $f2, 16(a0) 207 EX ldc1 $f4, 32(a0) 208 EX ldc1 $f6, 48(a0) 209 EX ldc1 $f8, 64(a0) 210 EX ldc1 $f10, 80(a0) 211 EX ldc1 $f12, 96(a0) 212 EX ldc1 $f14, 112(a0) 213 EX ldc1 $f16, 128(a0) 214 EX ldc1 $f18, 144(a0) 215 EX ldc1 $f20, 160(a0) 216 EX ldc1 $f22, 176(a0) 217 EX ldc1 $f24, 192(a0) 218 EX ldc1 $f26, 208(a0) 219 EX ldc1 $f28, 224(a0) 220 EX ldc1 $f30, 240(a0) 221 ctc1 t1, fcr31 222 .set pop 223 jr ra 224 li v0, 0 # success 225 END(_restore_fp_context) 226 227#ifdef CONFIG_CPU_HAS_MSA 228 229 .macro op_one_wr op, idx, base 230 .align 4 231\idx: \op \idx, 0, \base 232 jr ra 233 nop 234 .endm 235 236 .macro op_msa_wr name, op 237LEAF(\name) 238 .set push 239 .set noreorder 240 sll t0, a0, 4 241 PTR_LA t1, 0f 242 PTR_ADDU t0, t0, t1 243 jr t0 244 nop 245 op_one_wr \op, 0, a1 246 op_one_wr \op, 1, a1 247 op_one_wr \op, 2, a1 248 op_one_wr \op, 3, a1 249 op_one_wr \op, 4, a1 250 op_one_wr \op, 5, a1 251 op_one_wr \op, 6, a1 252 op_one_wr \op, 7, a1 253 op_one_wr \op, 8, a1 254 op_one_wr \op, 9, a1 255 op_one_wr \op, 10, a1 256 op_one_wr \op, 11, a1 257 op_one_wr \op, 12, a1 258 op_one_wr \op, 13, a1 259 op_one_wr \op, 14, a1 260 op_one_wr \op, 15, a1 261 op_one_wr \op, 16, a1 262 op_one_wr \op, 17, a1 263 op_one_wr \op, 18, a1 264 op_one_wr \op, 19, a1 265 op_one_wr \op, 20, a1 266 op_one_wr \op, 21, a1 267 op_one_wr \op, 22, a1 268 op_one_wr \op, 23, a1 269 op_one_wr \op, 24, a1 270 op_one_wr \op, 25, a1 271 op_one_wr \op, 26, a1 272 op_one_wr \op, 27, a1 273 op_one_wr \op, 28, a1 274 op_one_wr \op, 29, a1 275 op_one_wr \op, 30, a1 276 op_one_wr \op, 31, a1 277 .set pop 278 END(\name) 279 .endm 280 281 op_msa_wr read_msa_wr_b, st_b 282 op_msa_wr read_msa_wr_h, st_h 283 op_msa_wr read_msa_wr_w, st_w 284 op_msa_wr read_msa_wr_d, st_d 285 286 op_msa_wr write_msa_wr_b, ld_b 287 op_msa_wr write_msa_wr_h, ld_h 288 op_msa_wr write_msa_wr_w, ld_w 289 op_msa_wr write_msa_wr_d, ld_d 290 291#endif /* CONFIG_CPU_HAS_MSA */ 292 293#ifdef CONFIG_CPU_HAS_MSA 294 295 .macro save_msa_upper wr, off, base 296 .set push 297 .set noat 298#ifdef CONFIG_64BIT 299 copy_s_d \wr, 1 300 EX sd $1, \off(\base) 301#elif defined(CONFIG_CPU_LITTLE_ENDIAN) 302 copy_s_w \wr, 2 303 EX sw $1, \off(\base) 304 copy_s_w \wr, 3 305 EX sw $1, (\off+4)(\base) 306#else /* CONFIG_CPU_BIG_ENDIAN */ 307 copy_s_w \wr, 2 308 EX sw $1, (\off+4)(\base) 309 copy_s_w \wr, 3 310 EX sw $1, \off(\base) 311#endif 312 .set pop 313 .endm 314 315LEAF(_save_msa_all_upper) 316 save_msa_upper 0, 0x00, a0 317 save_msa_upper 1, 0x08, a0 318 save_msa_upper 2, 0x10, a0 319 save_msa_upper 3, 0x18, a0 320 save_msa_upper 4, 0x20, a0 321 save_msa_upper 5, 0x28, a0 322 save_msa_upper 6, 0x30, a0 323 save_msa_upper 7, 0x38, a0 324 save_msa_upper 8, 0x40, a0 325 save_msa_upper 9, 0x48, a0 326 save_msa_upper 10, 0x50, a0 327 save_msa_upper 11, 0x58, a0 328 save_msa_upper 12, 0x60, a0 329 save_msa_upper 13, 0x68, a0 330 save_msa_upper 14, 0x70, a0 331 save_msa_upper 15, 0x78, a0 332 save_msa_upper 16, 0x80, a0 333 save_msa_upper 17, 0x88, a0 334 save_msa_upper 18, 0x90, a0 335 save_msa_upper 19, 0x98, a0 336 save_msa_upper 20, 0xa0, a0 337 save_msa_upper 21, 0xa8, a0 338 save_msa_upper 22, 0xb0, a0 339 save_msa_upper 23, 0xb8, a0 340 save_msa_upper 24, 0xc0, a0 341 save_msa_upper 25, 0xc8, a0 342 save_msa_upper 26, 0xd0, a0 343 save_msa_upper 27, 0xd8, a0 344 save_msa_upper 28, 0xe0, a0 345 save_msa_upper 29, 0xe8, a0 346 save_msa_upper 30, 0xf0, a0 347 save_msa_upper 31, 0xf8, a0 348 jr ra 349 li v0, 0 350 END(_save_msa_all_upper) 351 352 .macro restore_msa_upper wr, off, base 353 .set push 354 .set noat 355#ifdef CONFIG_64BIT 356 EX ld $1, \off(\base) 357 insert_d \wr, 1 358#elif defined(CONFIG_CPU_LITTLE_ENDIAN) 359 EX lw $1, \off(\base) 360 insert_w \wr, 2 361 EX lw $1, (\off+4)(\base) 362 insert_w \wr, 3 363#else /* CONFIG_CPU_BIG_ENDIAN */ 364 EX lw $1, (\off+4)(\base) 365 insert_w \wr, 2 366 EX lw $1, \off(\base) 367 insert_w \wr, 3 368#endif 369 .set pop 370 .endm 371 372LEAF(_restore_msa_all_upper) 373 restore_msa_upper 0, 0x00, a0 374 restore_msa_upper 1, 0x08, a0 375 restore_msa_upper 2, 0x10, a0 376 restore_msa_upper 3, 0x18, a0 377 restore_msa_upper 4, 0x20, a0 378 restore_msa_upper 5, 0x28, a0 379 restore_msa_upper 6, 0x30, a0 380 restore_msa_upper 7, 0x38, a0 381 restore_msa_upper 8, 0x40, a0 382 restore_msa_upper 9, 0x48, a0 383 restore_msa_upper 10, 0x50, a0 384 restore_msa_upper 11, 0x58, a0 385 restore_msa_upper 12, 0x60, a0 386 restore_msa_upper 13, 0x68, a0 387 restore_msa_upper 14, 0x70, a0 388 restore_msa_upper 15, 0x78, a0 389 restore_msa_upper 16, 0x80, a0 390 restore_msa_upper 17, 0x88, a0 391 restore_msa_upper 18, 0x90, a0 392 restore_msa_upper 19, 0x98, a0 393 restore_msa_upper 20, 0xa0, a0 394 restore_msa_upper 21, 0xa8, a0 395 restore_msa_upper 22, 0xb0, a0 396 restore_msa_upper 23, 0xb8, a0 397 restore_msa_upper 24, 0xc0, a0 398 restore_msa_upper 25, 0xc8, a0 399 restore_msa_upper 26, 0xd0, a0 400 restore_msa_upper 27, 0xd8, a0 401 restore_msa_upper 28, 0xe0, a0 402 restore_msa_upper 29, 0xe8, a0 403 restore_msa_upper 30, 0xf0, a0 404 restore_msa_upper 31, 0xf8, a0 405 jr ra 406 li v0, 0 407 END(_restore_msa_all_upper) 408 409#endif /* CONFIG_CPU_HAS_MSA */ 410 411 .set reorder 412 413 .type fault, @function 414 .ent fault 415fault: li v0, -EFAULT # failure 416 jr ra 417 .end fault 418