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 <asm/asm.h> 16#include <asm/asmmacro.h> 17#include <asm/errno.h> 18#include <asm/export.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 .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_MIPS32_R2) || \ 44 defined(CONFIG_CPU_MIPS32_R6) 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_MIPS32_R2) || \ 56 defined(CONFIG_CPU_MIPS32_R6) 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/* 90 * Load the FPU with signalling NANS. This bit pattern we're using has 91 * the property that no matter whether considered as single or as double 92 * precision represents signaling NANS. 93 * 94 * The value to initialize fcr31 to comes in $a0. 95 */ 96 97 .set push 98 SET_HARDFLOAT 99 100LEAF(_init_fpu) 101 mfc0 t0, CP0_STATUS 102 li t1, ST0_CU1 103 or t0, t1 104 mtc0 t0, CP0_STATUS 105 enable_fpu_hazard 106 107 ctc1 a0, fcr31 108 109 li t1, -1 # SNaN 110 111#ifdef CONFIG_64BIT 112 sll t0, t0, 5 113 bgez t0, 1f # 16 / 32 register mode? 114 115 dmtc1 t1, $f1 116 dmtc1 t1, $f3 117 dmtc1 t1, $f5 118 dmtc1 t1, $f7 119 dmtc1 t1, $f9 120 dmtc1 t1, $f11 121 dmtc1 t1, $f13 122 dmtc1 t1, $f15 123 dmtc1 t1, $f17 124 dmtc1 t1, $f19 125 dmtc1 t1, $f21 126 dmtc1 t1, $f23 127 dmtc1 t1, $f25 128 dmtc1 t1, $f27 129 dmtc1 t1, $f29 130 dmtc1 t1, $f31 1311: 132#endif 133 134#ifdef CONFIG_CPU_MIPS32 135 mtc1 t1, $f0 136 mtc1 t1, $f1 137 mtc1 t1, $f2 138 mtc1 t1, $f3 139 mtc1 t1, $f4 140 mtc1 t1, $f5 141 mtc1 t1, $f6 142 mtc1 t1, $f7 143 mtc1 t1, $f8 144 mtc1 t1, $f9 145 mtc1 t1, $f10 146 mtc1 t1, $f11 147 mtc1 t1, $f12 148 mtc1 t1, $f13 149 mtc1 t1, $f14 150 mtc1 t1, $f15 151 mtc1 t1, $f16 152 mtc1 t1, $f17 153 mtc1 t1, $f18 154 mtc1 t1, $f19 155 mtc1 t1, $f20 156 mtc1 t1, $f21 157 mtc1 t1, $f22 158 mtc1 t1, $f23 159 mtc1 t1, $f24 160 mtc1 t1, $f25 161 mtc1 t1, $f26 162 mtc1 t1, $f27 163 mtc1 t1, $f28 164 mtc1 t1, $f29 165 mtc1 t1, $f30 166 mtc1 t1, $f31 167 168#if defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS32_R6) 169 .set push 170 .set MIPS_ISA_LEVEL_RAW 171 .set fp=64 172 sll t0, t0, 5 # is Status.FR set? 173 bgez t0, 1f # no: skip setting upper 32b 174 175 mthc1 t1, $f0 176 mthc1 t1, $f1 177 mthc1 t1, $f2 178 mthc1 t1, $f3 179 mthc1 t1, $f4 180 mthc1 t1, $f5 181 mthc1 t1, $f6 182 mthc1 t1, $f7 183 mthc1 t1, $f8 184 mthc1 t1, $f9 185 mthc1 t1, $f10 186 mthc1 t1, $f11 187 mthc1 t1, $f12 188 mthc1 t1, $f13 189 mthc1 t1, $f14 190 mthc1 t1, $f15 191 mthc1 t1, $f16 192 mthc1 t1, $f17 193 mthc1 t1, $f18 194 mthc1 t1, $f19 195 mthc1 t1, $f20 196 mthc1 t1, $f21 197 mthc1 t1, $f22 198 mthc1 t1, $f23 199 mthc1 t1, $f24 200 mthc1 t1, $f25 201 mthc1 t1, $f26 202 mthc1 t1, $f27 203 mthc1 t1, $f28 204 mthc1 t1, $f29 205 mthc1 t1, $f30 206 mthc1 t1, $f31 2071: .set pop 208#endif /* CONFIG_CPU_MIPS32_R2 || CONFIG_CPU_MIPS32_R6 */ 209#else 210 .set MIPS_ISA_ARCH_LEVEL_RAW 211 dmtc1 t1, $f0 212 dmtc1 t1, $f2 213 dmtc1 t1, $f4 214 dmtc1 t1, $f6 215 dmtc1 t1, $f8 216 dmtc1 t1, $f10 217 dmtc1 t1, $f12 218 dmtc1 t1, $f14 219 dmtc1 t1, $f16 220 dmtc1 t1, $f18 221 dmtc1 t1, $f20 222 dmtc1 t1, $f22 223 dmtc1 t1, $f24 224 dmtc1 t1, $f26 225 dmtc1 t1, $f28 226 dmtc1 t1, $f30 227#endif 228 jr ra 229 END(_init_fpu) 230 231 .set pop /* SET_HARDFLOAT */ 232 233 .set noreorder 234 235/** 236 * _save_fp_context() - save FP context from the FPU 237 * @a0 - pointer to fpregs field of sigcontext 238 * @a1 - pointer to fpc_csr field of sigcontext 239 * 240 * Save FP context, including the 32 FP data registers and the FP 241 * control & status register, from the FPU to signal context. 242 */ 243LEAF(_save_fp_context) 244 .set push 245 SET_HARDFLOAT 246 cfc1 t1, fcr31 247 .set pop 248 249#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \ 250 defined(CONFIG_CPU_MIPS32_R6) 251 .set push 252 SET_HARDFLOAT 253#ifdef CONFIG_CPU_MIPS32_R2 254 .set mips32r2 255 .set fp=64 256 mfc0 t0, CP0_STATUS 257 sll t0, t0, 5 258 bgez t0, 1f # skip storing odd if FR=0 259 nop 260#endif 261 /* Store the 16 odd double precision registers */ 262 EX sdc1 $f1, 8(a0) 263 EX sdc1 $f3, 24(a0) 264 EX sdc1 $f5, 40(a0) 265 EX sdc1 $f7, 56(a0) 266 EX sdc1 $f9, 72(a0) 267 EX sdc1 $f11, 88(a0) 268 EX sdc1 $f13, 104(a0) 269 EX sdc1 $f15, 120(a0) 270 EX sdc1 $f17, 136(a0) 271 EX sdc1 $f19, 152(a0) 272 EX sdc1 $f21, 168(a0) 273 EX sdc1 $f23, 184(a0) 274 EX sdc1 $f25, 200(a0) 275 EX sdc1 $f27, 216(a0) 276 EX sdc1 $f29, 232(a0) 277 EX sdc1 $f31, 248(a0) 2781: .set pop 279#endif 280 281 .set push 282 SET_HARDFLOAT 283 /* Store the 16 even double precision registers */ 284 EX sdc1 $f0, 0(a0) 285 EX sdc1 $f2, 16(a0) 286 EX sdc1 $f4, 32(a0) 287 EX sdc1 $f6, 48(a0) 288 EX sdc1 $f8, 64(a0) 289 EX sdc1 $f10, 80(a0) 290 EX sdc1 $f12, 96(a0) 291 EX sdc1 $f14, 112(a0) 292 EX sdc1 $f16, 128(a0) 293 EX sdc1 $f18, 144(a0) 294 EX sdc1 $f20, 160(a0) 295 EX sdc1 $f22, 176(a0) 296 EX sdc1 $f24, 192(a0) 297 EX sdc1 $f26, 208(a0) 298 EX sdc1 $f28, 224(a0) 299 EX sdc1 $f30, 240(a0) 300 EX sw t1, 0(a1) 301 jr ra 302 li v0, 0 # success 303 .set pop 304 END(_save_fp_context) 305 306/** 307 * _restore_fp_context() - restore FP context to the FPU 308 * @a0 - pointer to fpregs field of sigcontext 309 * @a1 - pointer to fpc_csr field of sigcontext 310 * 311 * Restore FP context, including the 32 FP data registers and the FP 312 * control & status register, from signal context to the FPU. 313 */ 314LEAF(_restore_fp_context) 315 EX lw t1, 0(a1) 316 317#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \ 318 defined(CONFIG_CPU_MIPS32_R6) 319 .set push 320 SET_HARDFLOAT 321#ifdef CONFIG_CPU_MIPS32_R2 322 .set mips32r2 323 .set fp=64 324 mfc0 t0, CP0_STATUS 325 sll t0, t0, 5 326 bgez t0, 1f # skip loading odd if FR=0 327 nop 328#endif 329 EX ldc1 $f1, 8(a0) 330 EX ldc1 $f3, 24(a0) 331 EX ldc1 $f5, 40(a0) 332 EX ldc1 $f7, 56(a0) 333 EX ldc1 $f9, 72(a0) 334 EX ldc1 $f11, 88(a0) 335 EX ldc1 $f13, 104(a0) 336 EX ldc1 $f15, 120(a0) 337 EX ldc1 $f17, 136(a0) 338 EX ldc1 $f19, 152(a0) 339 EX ldc1 $f21, 168(a0) 340 EX ldc1 $f23, 184(a0) 341 EX ldc1 $f25, 200(a0) 342 EX ldc1 $f27, 216(a0) 343 EX ldc1 $f29, 232(a0) 344 EX ldc1 $f31, 248(a0) 3451: .set pop 346#endif 347 .set push 348 SET_HARDFLOAT 349 EX ldc1 $f0, 0(a0) 350 EX ldc1 $f2, 16(a0) 351 EX ldc1 $f4, 32(a0) 352 EX ldc1 $f6, 48(a0) 353 EX ldc1 $f8, 64(a0) 354 EX ldc1 $f10, 80(a0) 355 EX ldc1 $f12, 96(a0) 356 EX ldc1 $f14, 112(a0) 357 EX ldc1 $f16, 128(a0) 358 EX ldc1 $f18, 144(a0) 359 EX ldc1 $f20, 160(a0) 360 EX ldc1 $f22, 176(a0) 361 EX ldc1 $f24, 192(a0) 362 EX ldc1 $f26, 208(a0) 363 EX ldc1 $f28, 224(a0) 364 EX ldc1 $f30, 240(a0) 365 ctc1 t1, fcr31 366 .set pop 367 jr ra 368 li v0, 0 # success 369 END(_restore_fp_context) 370 371#ifdef CONFIG_CPU_HAS_MSA 372 373 .macro op_one_wr op, idx, base 374 .align 4 375\idx: \op \idx, 0, \base 376 jr ra 377 nop 378 .endm 379 380 .macro op_msa_wr name, op 381LEAF(\name) 382 .set push 383 .set noreorder 384 sll t0, a0, 4 385 PTR_LA t1, 0f 386 PTR_ADDU t0, t0, t1 387 jr t0 388 nop 389 op_one_wr \op, 0, a1 390 op_one_wr \op, 1, a1 391 op_one_wr \op, 2, a1 392 op_one_wr \op, 3, a1 393 op_one_wr \op, 4, a1 394 op_one_wr \op, 5, a1 395 op_one_wr \op, 6, a1 396 op_one_wr \op, 7, a1 397 op_one_wr \op, 8, a1 398 op_one_wr \op, 9, a1 399 op_one_wr \op, 10, a1 400 op_one_wr \op, 11, a1 401 op_one_wr \op, 12, a1 402 op_one_wr \op, 13, a1 403 op_one_wr \op, 14, a1 404 op_one_wr \op, 15, a1 405 op_one_wr \op, 16, a1 406 op_one_wr \op, 17, a1 407 op_one_wr \op, 18, a1 408 op_one_wr \op, 19, a1 409 op_one_wr \op, 20, a1 410 op_one_wr \op, 21, a1 411 op_one_wr \op, 22, a1 412 op_one_wr \op, 23, a1 413 op_one_wr \op, 24, a1 414 op_one_wr \op, 25, a1 415 op_one_wr \op, 26, a1 416 op_one_wr \op, 27, a1 417 op_one_wr \op, 28, a1 418 op_one_wr \op, 29, a1 419 op_one_wr \op, 30, a1 420 op_one_wr \op, 31, a1 421 .set pop 422 END(\name) 423 .endm 424 425 op_msa_wr read_msa_wr_b, st_b 426 op_msa_wr read_msa_wr_h, st_h 427 op_msa_wr read_msa_wr_w, st_w 428 op_msa_wr read_msa_wr_d, st_d 429 430 op_msa_wr write_msa_wr_b, ld_b 431 op_msa_wr write_msa_wr_h, ld_h 432 op_msa_wr write_msa_wr_w, ld_w 433 op_msa_wr write_msa_wr_d, ld_d 434 435#endif /* CONFIG_CPU_HAS_MSA */ 436 437#ifdef CONFIG_CPU_HAS_MSA 438 439 .macro save_msa_upper wr, off, base 440 .set push 441 .set noat 442#ifdef CONFIG_64BIT 443 copy_s_d \wr, 1 444 EX sd $1, \off(\base) 445#elif defined(CONFIG_CPU_LITTLE_ENDIAN) 446 copy_s_w \wr, 2 447 EX sw $1, \off(\base) 448 copy_s_w \wr, 3 449 EX sw $1, (\off+4)(\base) 450#else /* CONFIG_CPU_BIG_ENDIAN */ 451 copy_s_w \wr, 2 452 EX sw $1, (\off+4)(\base) 453 copy_s_w \wr, 3 454 EX sw $1, \off(\base) 455#endif 456 .set pop 457 .endm 458 459LEAF(_save_msa_all_upper) 460 save_msa_upper 0, 0x00, a0 461 save_msa_upper 1, 0x08, a0 462 save_msa_upper 2, 0x10, a0 463 save_msa_upper 3, 0x18, a0 464 save_msa_upper 4, 0x20, a0 465 save_msa_upper 5, 0x28, a0 466 save_msa_upper 6, 0x30, a0 467 save_msa_upper 7, 0x38, a0 468 save_msa_upper 8, 0x40, a0 469 save_msa_upper 9, 0x48, a0 470 save_msa_upper 10, 0x50, a0 471 save_msa_upper 11, 0x58, a0 472 save_msa_upper 12, 0x60, a0 473 save_msa_upper 13, 0x68, a0 474 save_msa_upper 14, 0x70, a0 475 save_msa_upper 15, 0x78, a0 476 save_msa_upper 16, 0x80, a0 477 save_msa_upper 17, 0x88, a0 478 save_msa_upper 18, 0x90, a0 479 save_msa_upper 19, 0x98, a0 480 save_msa_upper 20, 0xa0, a0 481 save_msa_upper 21, 0xa8, a0 482 save_msa_upper 22, 0xb0, a0 483 save_msa_upper 23, 0xb8, a0 484 save_msa_upper 24, 0xc0, a0 485 save_msa_upper 25, 0xc8, a0 486 save_msa_upper 26, 0xd0, a0 487 save_msa_upper 27, 0xd8, a0 488 save_msa_upper 28, 0xe0, a0 489 save_msa_upper 29, 0xe8, a0 490 save_msa_upper 30, 0xf0, a0 491 save_msa_upper 31, 0xf8, a0 492 jr ra 493 li v0, 0 494 END(_save_msa_all_upper) 495 496 .macro restore_msa_upper wr, off, base 497 .set push 498 .set noat 499#ifdef CONFIG_64BIT 500 EX ld $1, \off(\base) 501 insert_d \wr, 1 502#elif defined(CONFIG_CPU_LITTLE_ENDIAN) 503 EX lw $1, \off(\base) 504 insert_w \wr, 2 505 EX lw $1, (\off+4)(\base) 506 insert_w \wr, 3 507#else /* CONFIG_CPU_BIG_ENDIAN */ 508 EX lw $1, (\off+4)(\base) 509 insert_w \wr, 2 510 EX lw $1, \off(\base) 511 insert_w \wr, 3 512#endif 513 .set pop 514 .endm 515 516LEAF(_restore_msa_all_upper) 517 restore_msa_upper 0, 0x00, a0 518 restore_msa_upper 1, 0x08, a0 519 restore_msa_upper 2, 0x10, a0 520 restore_msa_upper 3, 0x18, a0 521 restore_msa_upper 4, 0x20, a0 522 restore_msa_upper 5, 0x28, a0 523 restore_msa_upper 6, 0x30, a0 524 restore_msa_upper 7, 0x38, a0 525 restore_msa_upper 8, 0x40, a0 526 restore_msa_upper 9, 0x48, a0 527 restore_msa_upper 10, 0x50, a0 528 restore_msa_upper 11, 0x58, a0 529 restore_msa_upper 12, 0x60, a0 530 restore_msa_upper 13, 0x68, a0 531 restore_msa_upper 14, 0x70, a0 532 restore_msa_upper 15, 0x78, a0 533 restore_msa_upper 16, 0x80, a0 534 restore_msa_upper 17, 0x88, a0 535 restore_msa_upper 18, 0x90, a0 536 restore_msa_upper 19, 0x98, a0 537 restore_msa_upper 20, 0xa0, a0 538 restore_msa_upper 21, 0xa8, a0 539 restore_msa_upper 22, 0xb0, a0 540 restore_msa_upper 23, 0xb8, a0 541 restore_msa_upper 24, 0xc0, a0 542 restore_msa_upper 25, 0xc8, a0 543 restore_msa_upper 26, 0xd0, a0 544 restore_msa_upper 27, 0xd8, a0 545 restore_msa_upper 28, 0xe0, a0 546 restore_msa_upper 29, 0xe8, a0 547 restore_msa_upper 30, 0xf0, a0 548 restore_msa_upper 31, 0xf8, a0 549 jr ra 550 li v0, 0 551 END(_restore_msa_all_upper) 552 553#endif /* CONFIG_CPU_HAS_MSA */ 554 555 .set reorder 556 557 .type fault, @function 558 .ent fault 559fault: li v0, -EFAULT # failure 560 jr ra 561 .end fault 562