Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: Fix little endian microMIPS MSA encodings

When the toolchain doesn't support MSA we encode MSA instructions
explicitly in assembly. Unfortunately we use .word for both MIPS and
microMIPS encodings which is wrong, since 32-bit microMIPS instructions
are made up from a pair of halfwords.

- The most significant halfword always comes first, so for little endian
builds the halves will be emitted in the wrong order.

- 32-bit alignment isn't guaranteed, so the assembler may insert a
16-bit nop instruction to pad the instruction stream to a 32-bit
boundary.

Use the new instruction encoding macros to encode microMIPS MSA
instructions correctly.

Fixes: d96cc3d1ec5d ("MIPS: Add microMIPS MSA support.")
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paul Burton <Paul.Burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/13312/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

James Hogan and committed by
Ralf Baechle
6e1b29c3 1c48a177

+58 -62
+50 -49
arch/mips/include/asm/asmmacro.h
··· 19 19 #include <asm/asmmacro-64.h> 20 20 #endif 21 21 22 + /* 23 + * Helper macros for generating raw instruction encodings. 24 + */ 25 + #ifdef CONFIG_CPU_MICROMIPS 26 + .macro insn32_if_mm enc 27 + .insn 28 + .hword ((\enc) >> 16) 29 + .hword ((\enc) & 0xffff) 30 + .endm 31 + 32 + .macro insn_if_mips enc 33 + .endm 34 + #else 35 + .macro insn32_if_mm enc 36 + .endm 37 + 38 + .macro insn_if_mips enc 39 + .insn 40 + .word (\enc) 41 + .endm 42 + #endif 43 + 22 44 #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) 23 45 .macro local_irq_enable reg=t0 24 46 ei ··· 363 341 .endm 364 342 #else 365 343 366 - #ifdef CONFIG_CPU_MICROMIPS 367 - #define CFC_MSA_INSN 0x587e0056 368 - #define CTC_MSA_INSN 0x583e0816 369 - #define LDB_MSA_INSN 0x58000807 370 - #define LDH_MSA_INSN 0x58000817 371 - #define LDW_MSA_INSN 0x58000827 372 - #define LDD_MSA_INSN 0x58000837 373 - #define STB_MSA_INSN 0x5800080f 374 - #define STH_MSA_INSN 0x5800081f 375 - #define STW_MSA_INSN 0x5800082f 376 - #define STD_MSA_INSN 0x5800083f 377 - #define COPY_SW_MSA_INSN 0x58b00056 378 - #define COPY_SD_MSA_INSN 0x58b80056 379 - #define INSERT_W_MSA_INSN 0x59300816 380 - #define INSERT_D_MSA_INSN 0x59380816 381 - #else 382 - #define CFC_MSA_INSN 0x787e0059 383 - #define CTC_MSA_INSN 0x783e0819 384 - #define LDB_MSA_INSN 0x78000820 385 - #define LDH_MSA_INSN 0x78000821 386 - #define LDW_MSA_INSN 0x78000822 387 - #define LDD_MSA_INSN 0x78000823 388 - #define STB_MSA_INSN 0x78000824 389 - #define STH_MSA_INSN 0x78000825 390 - #define STW_MSA_INSN 0x78000826 391 - #define STD_MSA_INSN 0x78000827 392 - #define COPY_SW_MSA_INSN 0x78b00059 393 - #define COPY_SD_MSA_INSN 0x78b80059 394 - #define INSERT_W_MSA_INSN 0x79300819 395 - #define INSERT_D_MSA_INSN 0x79380819 396 - #endif 397 - 398 344 /* 399 345 * Temporary until all toolchains in use include MSA support. 400 346 */ ··· 370 380 .set push 371 381 .set noat 372 382 SET_HARDFLOAT 373 - .insn 374 - .word CFC_MSA_INSN | (\cs << 11) 383 + insn_if_mips 0x787e0059 | (\cs << 11) 384 + insn32_if_mm 0x587e0056 | (\cs << 11) 375 385 move \rd, $1 376 386 .set pop 377 387 .endm ··· 381 391 .set noat 382 392 SET_HARDFLOAT 383 393 move $1, \rs 384 - .word CTC_MSA_INSN | (\cd << 6) 394 + insn_if_mips 0x783e0819 | (\cd << 6) 395 + insn32_if_mm 0x583e0816 | (\cd << 6) 385 396 .set pop 386 397 .endm 387 398 ··· 391 400 .set noat 392 401 SET_HARDFLOAT 393 402 PTR_ADDU $1, \base, \off 394 - .word LDB_MSA_INSN | (\wd << 6) 403 + insn_if_mips 0x78000820 | (\wd << 6) 404 + insn32_if_mm 0x58000807 | (\wd << 6) 395 405 .set pop 396 406 .endm 397 407 ··· 401 409 .set noat 402 410 SET_HARDFLOAT 403 411 PTR_ADDU $1, \base, \off 404 - .word LDH_MSA_INSN | (\wd << 6) 412 + insn_if_mips 0x78000821 | (\wd << 6) 413 + insn32_if_mm 0x58000817 | (\wd << 6) 405 414 .set pop 406 415 .endm 407 416 ··· 411 418 .set noat 412 419 SET_HARDFLOAT 413 420 PTR_ADDU $1, \base, \off 414 - .word LDW_MSA_INSN | (\wd << 6) 421 + insn_if_mips 0x78000822 | (\wd << 6) 422 + insn32_if_mm 0x58000827 | (\wd << 6) 415 423 .set pop 416 424 .endm 417 425 ··· 421 427 .set noat 422 428 SET_HARDFLOAT 423 429 PTR_ADDU $1, \base, \off 424 - .word LDD_MSA_INSN | (\wd << 6) 430 + insn_if_mips 0x78000823 | (\wd << 6) 431 + insn32_if_mm 0x58000837 | (\wd << 6) 425 432 .set pop 426 433 .endm 427 434 ··· 431 436 .set noat 432 437 SET_HARDFLOAT 433 438 PTR_ADDU $1, \base, \off 434 - .word STB_MSA_INSN | (\wd << 6) 439 + insn_if_mips 0x78000824 | (\wd << 6) 440 + insn32_if_mm 0x5800080f | (\wd << 6) 435 441 .set pop 436 442 .endm 437 443 ··· 441 445 .set noat 442 446 SET_HARDFLOAT 443 447 PTR_ADDU $1, \base, \off 444 - .word STH_MSA_INSN | (\wd << 6) 448 + insn_if_mips 0x78000825 | (\wd << 6) 449 + insn32_if_mm 0x5800081f | (\wd << 6) 445 450 .set pop 446 451 .endm 447 452 ··· 451 454 .set noat 452 455 SET_HARDFLOAT 453 456 PTR_ADDU $1, \base, \off 454 - .word STW_MSA_INSN | (\wd << 6) 457 + insn_if_mips 0x78000826 | (\wd << 6) 458 + insn32_if_mm 0x5800082f | (\wd << 6) 455 459 .set pop 456 460 .endm 457 461 ··· 461 463 .set noat 462 464 SET_HARDFLOAT 463 465 PTR_ADDU $1, \base, \off 464 - .word STD_MSA_INSN | (\wd << 6) 466 + insn_if_mips 0x78000827 | (\wd << 6) 467 + insn32_if_mm 0x5800083f | (\wd << 6) 465 468 .set pop 466 469 .endm 467 470 ··· 470 471 .set push 471 472 .set noat 472 473 SET_HARDFLOAT 473 - .insn 474 - .word COPY_SW_MSA_INSN | (\n << 16) | (\ws << 11) 474 + insn_if_mips 0x78b00059 | (\n << 16) | (\ws << 11) 475 + insn32_if_mm 0x58b00056 | (\n << 16) | (\ws << 11) 475 476 .set pop 476 477 .endm 477 478 ··· 479 480 .set push 480 481 .set noat 481 482 SET_HARDFLOAT 482 - .insn 483 - .word COPY_SD_MSA_INSN | (\n << 16) | (\ws << 11) 483 + insn_if_mips 0x78b80059 | (\n << 16) | (\ws << 11) 484 + insn32_if_mm 0x58b80056 | (\n << 16) | (\ws << 11) 484 485 .set pop 485 486 .endm 486 487 ··· 488 489 .set push 489 490 .set noat 490 491 SET_HARDFLOAT 491 - .word INSERT_W_MSA_INSN | (\n << 16) | (\wd << 6) 492 + insn_if_mips 0x79300819 | (\n << 16) | (\wd << 6) 493 + insn32_if_mm 0x59300816 | (\n << 16) | (\wd << 6) 492 494 .set pop 493 495 .endm 494 496 ··· 497 497 .set push 498 498 .set noat 499 499 SET_HARDFLOAT 500 - .word INSERT_D_MSA_INSN | (\n << 16) | (\wd << 6) 500 + insn_if_mips 0x79380819 | (\n << 16) | (\wd << 6) 501 + insn32_if_mm 0x59380816 | (\n << 16) | (\wd << 6) 501 502 .set pop 502 503 .endm 503 504 #endif
+8 -13
arch/mips/include/asm/msa.h
··· 192 192 * allow compilation with toolchains that do not support MSA. Once all 193 193 * toolchains in use support MSA these can be removed. 194 194 */ 195 - #ifdef CONFIG_CPU_MICROMIPS 196 - #define CFC_MSA_INSN 0x587e0056 197 - #define CTC_MSA_INSN 0x583e0816 198 - #else 199 - #define CFC_MSA_INSN 0x787e0059 200 - #define CTC_MSA_INSN 0x783e0819 201 - #endif 202 195 203 196 #define __BUILD_MSA_CTL_REG(name, cs) \ 204 197 static inline unsigned int read_msa_##name(void) \ ··· 200 207 __asm__ __volatile__( \ 201 208 " .set push\n" \ 202 209 " .set noat\n" \ 203 - " .insn\n" \ 204 - " .word %1 | (" #cs " << 11)\n" \ 210 + " # cfcmsa $1, $%1\n" \ 211 + _ASM_INSN_IF_MIPS(0x787e0059 | %1 << 11) \ 212 + _ASM_INSN32_IF_MM(0x587e0056 | %1 << 11) \ 205 213 " move %0, $1\n" \ 206 214 " .set pop\n" \ 207 - : "=r"(reg) : "i"(CFC_MSA_INSN)); \ 215 + : "=r"(reg) : "i"(cs)); \ 208 216 return reg; \ 209 217 } \ 210 218 \ ··· 215 221 " .set push\n" \ 216 222 " .set noat\n" \ 217 223 " move $1, %0\n" \ 218 - " .insn\n" \ 219 - " .word %1 | (" #cs " << 6)\n" \ 224 + " # ctcmsa $%1, $1\n" \ 225 + _ASM_INSN_IF_MIPS(0x783e0819 | %1 << 6) \ 226 + _ASM_INSN32_IF_MM(0x583e0816 | %1 << 6) \ 220 227 " .set pop\n" \ 221 - : : "r"(val), "i"(CTC_MSA_INSN)); \ 228 + : : "r"(val), "i"(cs)); \ 222 229 } 223 230 224 231 #endif /* !TOOLCHAIN_SUPPORTS_MSA */