aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorMarkos Chandras <markos.chandras@imgtec.com>2014-11-25 11:02:23 -0500
committerMarkos Chandras <markos.chandras@imgtec.com>2015-02-17 10:37:32 -0500
commit319824eabc3f1c1aab67f408d66f384fbb996ee2 (patch)
tree260bbaa71db86705f735b6c9e45bf32aad95c420 /arch/mips
parent5f9f41c474befb4ebbc40b27f65bb7d649241581 (diff)
MIPS: kernel: branch: Do not emulate the branch likelies on MIPS R6
MIPS R6 removed the BLTZL, BGEZL, BLTZAL, BGEZAL, BEQL, BNEL, BLEZL, BGTZL branch likely instructions so we must not try to emulate them on MIPS R6 if the R2-to-R6 emulator is not present. Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/kernel/branch.c70
-rw-r--r--arch/mips/math-emu/cp1emu.c32
2 files changed, 89 insertions, 13 deletions
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 5736949896d1..5121adaa34bd 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -431,8 +431,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
431 */ 431 */
432 case bcond_op: 432 case bcond_op:
433 switch (insn.i_format.rt) { 433 switch (insn.i_format.rt) {
434 case bltz_op:
435 case bltzl_op: 434 case bltzl_op:
435 if (NO_R6EMU)
436 goto sigill_r6;
437 case bltz_op:
436 if ((long)regs->regs[insn.i_format.rs] < 0) { 438 if ((long)regs->regs[insn.i_format.rs] < 0) {
437 epc = epc + 4 + (insn.i_format.simmediate << 2); 439 epc = epc + 4 + (insn.i_format.simmediate << 2);
438 if (insn.i_format.rt == bltzl_op) 440 if (insn.i_format.rt == bltzl_op)
@@ -442,8 +444,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
442 regs->cp0_epc = epc; 444 regs->cp0_epc = epc;
443 break; 445 break;
444 446
445 case bgez_op:
446 case bgezl_op: 447 case bgezl_op:
448 if (NO_R6EMU)
449 goto sigill_r6;
450 case bgez_op:
447 if ((long)regs->regs[insn.i_format.rs] >= 0) { 451 if ((long)regs->regs[insn.i_format.rs] >= 0) {
448 epc = epc + 4 + (insn.i_format.simmediate << 2); 452 epc = epc + 4 + (insn.i_format.simmediate << 2);
449 if (insn.i_format.rt == bgezl_op) 453 if (insn.i_format.rt == bgezl_op)
@@ -455,7 +459,29 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
455 459
456 case bltzal_op: 460 case bltzal_op:
457 case bltzall_op: 461 case bltzall_op:
462 if (NO_R6EMU && (insn.i_format.rs ||
463 insn.i_format.rt == bltzall_op)) {
464 ret = -SIGILL;
465 break;
466 }
458 regs->regs[31] = epc + 8; 467 regs->regs[31] = epc + 8;
468 /*
469 * OK we are here either because we hit a NAL
470 * instruction or because we are emulating an
471 * old bltzal{,l} one. Lets figure out what the
472 * case really is.
473 */
474 if (!insn.i_format.rs) {
475 /*
476 * NAL or BLTZAL with rs == 0
477 * Doesn't matter if we are R6 or not. The
478 * result is the same
479 */
480 regs->cp0_epc += 4 +
481 (insn.i_format.simmediate << 2);
482 break;
483 }
484 /* Now do the real thing for non-R6 BLTZAL{,L} */
459 if ((long)regs->regs[insn.i_format.rs] < 0) { 485 if ((long)regs->regs[insn.i_format.rs] < 0) {
460 epc = epc + 4 + (insn.i_format.simmediate << 2); 486 epc = epc + 4 + (insn.i_format.simmediate << 2);
461 if (insn.i_format.rt == bltzall_op) 487 if (insn.i_format.rt == bltzall_op)
@@ -467,7 +493,29 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
467 493
468 case bgezal_op: 494 case bgezal_op:
469 case bgezall_op: 495 case bgezall_op:
496 if (NO_R6EMU && (insn.i_format.rs ||
497 insn.i_format.rt == bgezall_op)) {
498 ret = -SIGILL;
499 break;
500 }
470 regs->regs[31] = epc + 8; 501 regs->regs[31] = epc + 8;
502 /*
503 * OK we are here either because we hit a BAL
504 * instruction or because we are emulating an
505 * old bgezal{,l} one. Lets figure out what the
506 * case really is.
507 */
508 if (!insn.i_format.rs) {
509 /*
510 * BAL or BGEZAL with rs == 0
511 * Doesn't matter if we are R6 or not. The
512 * result is the same
513 */
514 regs->cp0_epc += 4 +
515 (insn.i_format.simmediate << 2);
516 break;
517 }
518 /* Now do the real thing for non-R6 BGEZAL{,L} */
471 if ((long)regs->regs[insn.i_format.rs] >= 0) { 519 if ((long)regs->regs[insn.i_format.rs] >= 0) {
472 epc = epc + 4 + (insn.i_format.simmediate << 2); 520 epc = epc + 4 + (insn.i_format.simmediate << 2);
473 if (insn.i_format.rt == bgezall_op) 521 if (insn.i_format.rt == bgezall_op)
@@ -510,8 +558,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
510 /* 558 /*
511 * These are conditional and in i_format. 559 * These are conditional and in i_format.
512 */ 560 */
513 case beq_op:
514 case beql_op: 561 case beql_op:
562 if (NO_R6EMU)
563 goto sigill_r6;
564 case beq_op:
515 if (regs->regs[insn.i_format.rs] == 565 if (regs->regs[insn.i_format.rs] ==
516 regs->regs[insn.i_format.rt]) { 566 regs->regs[insn.i_format.rt]) {
517 epc = epc + 4 + (insn.i_format.simmediate << 2); 567 epc = epc + 4 + (insn.i_format.simmediate << 2);
@@ -522,8 +572,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
522 regs->cp0_epc = epc; 572 regs->cp0_epc = epc;
523 break; 573 break;
524 574
525 case bne_op:
526 case bnel_op: 575 case bnel_op:
576 if (NO_R6EMU)
577 goto sigill_r6;
578 case bne_op:
527 if (regs->regs[insn.i_format.rs] != 579 if (regs->regs[insn.i_format.rs] !=
528 regs->regs[insn.i_format.rt]) { 580 regs->regs[insn.i_format.rt]) {
529 epc = epc + 4 + (insn.i_format.simmediate << 2); 581 epc = epc + 4 + (insn.i_format.simmediate << 2);
@@ -534,8 +586,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
534 regs->cp0_epc = epc; 586 regs->cp0_epc = epc;
535 break; 587 break;
536 588
537 case blez_op: /* not really i_format */ 589 case blezl_op: /* not really i_format */
538 case blezl_op: 590 if (NO_R6EMU)
591 goto sigill_r6;
592 case blez_op:
539 /* rt field assumed to be zero */ 593 /* rt field assumed to be zero */
540 if ((long)regs->regs[insn.i_format.rs] <= 0) { 594 if ((long)regs->regs[insn.i_format.rs] <= 0) {
541 epc = epc + 4 + (insn.i_format.simmediate << 2); 595 epc = epc + 4 + (insn.i_format.simmediate << 2);
@@ -546,8 +600,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
546 regs->cp0_epc = epc; 600 regs->cp0_epc = epc;
547 break; 601 break;
548 602
549 case bgtz_op:
550 case bgtzl_op: 603 case bgtzl_op:
604 if (NO_R6EMU)
605 goto sigill_r6;
606 case bgtz_op:
551 /* rt field assumed to be zero */ 607 /* rt field assumed to be zero */
552 if ((long)regs->regs[insn.i_format.rs] > 0) { 608 if ((long)regs->regs[insn.i_format.rs] > 0) {
553 epc = epc + 4 + (insn.i_format.simmediate << 2); 609 epc = epc + 4 + (insn.i_format.simmediate << 2);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 9bf82117b4f2..7bbaefe0434d 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -459,12 +459,18 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
459 switch (insn.i_format.rt) { 459 switch (insn.i_format.rt) {
460 case bltzal_op: 460 case bltzal_op:
461 case bltzall_op: 461 case bltzall_op:
462 if (NO_R6EMU && (insn.i_format.rs ||
463 insn.i_format.rt == bltzall_op))
464 break;
465
462 regs->regs[31] = regs->cp0_epc + 466 regs->regs[31] = regs->cp0_epc +
463 dec_insn.pc_inc + 467 dec_insn.pc_inc +
464 dec_insn.next_pc_inc; 468 dec_insn.next_pc_inc;
465 /* Fall through */ 469 /* Fall through */
466 case bltz_op:
467 case bltzl_op: 470 case bltzl_op:
471 if (NO_R6EMU)
472 break;
473 case bltz_op:
468 if ((long)regs->regs[insn.i_format.rs] < 0) 474 if ((long)regs->regs[insn.i_format.rs] < 0)
469 *contpc = regs->cp0_epc + 475 *contpc = regs->cp0_epc +
470 dec_insn.pc_inc + 476 dec_insn.pc_inc +
@@ -476,12 +482,18 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
476 return 1; 482 return 1;
477 case bgezal_op: 483 case bgezal_op:
478 case bgezall_op: 484 case bgezall_op:
485 if (NO_R6EMU && (insn.i_format.rs ||
486 insn.i_format.rt == bgezall_op))
487 break;
488
479 regs->regs[31] = regs->cp0_epc + 489 regs->regs[31] = regs->cp0_epc +
480 dec_insn.pc_inc + 490 dec_insn.pc_inc +
481 dec_insn.next_pc_inc; 491 dec_insn.next_pc_inc;
482 /* Fall through */ 492 /* Fall through */
483 case bgez_op:
484 case bgezl_op: 493 case bgezl_op:
494 if (NO_R6EMU)
495 break;
496 case bgez_op:
485 if ((long)regs->regs[insn.i_format.rs] >= 0) 497 if ((long)regs->regs[insn.i_format.rs] >= 0)
486 *contpc = regs->cp0_epc + 498 *contpc = regs->cp0_epc +
487 dec_insn.pc_inc + 499 dec_insn.pc_inc +
@@ -508,8 +520,10 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
508 /* Set microMIPS mode bit: XOR for jalx. */ 520 /* Set microMIPS mode bit: XOR for jalx. */
509 *contpc ^= bit; 521 *contpc ^= bit;
510 return 1; 522 return 1;
511 case beq_op:
512 case beql_op: 523 case beql_op:
524 if (NO_R6EMU)
525 break;
526 case beq_op:
513 if (regs->regs[insn.i_format.rs] == 527 if (regs->regs[insn.i_format.rs] ==
514 regs->regs[insn.i_format.rt]) 528 regs->regs[insn.i_format.rt])
515 *contpc = regs->cp0_epc + 529 *contpc = regs->cp0_epc +
@@ -520,8 +534,10 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
520 dec_insn.pc_inc + 534 dec_insn.pc_inc +
521 dec_insn.next_pc_inc; 535 dec_insn.next_pc_inc;
522 return 1; 536 return 1;
523 case bne_op:
524 case bnel_op: 537 case bnel_op:
538 if (NO_R6EMU)
539 break;
540 case bne_op:
525 if (regs->regs[insn.i_format.rs] != 541 if (regs->regs[insn.i_format.rs] !=
526 regs->regs[insn.i_format.rt]) 542 regs->regs[insn.i_format.rt])
527 *contpc = regs->cp0_epc + 543 *contpc = regs->cp0_epc +
@@ -532,8 +548,10 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
532 dec_insn.pc_inc + 548 dec_insn.pc_inc +
533 dec_insn.next_pc_inc; 549 dec_insn.next_pc_inc;
534 return 1; 550 return 1;
535 case blez_op:
536 case blezl_op: 551 case blezl_op:
552 if (NO_R6EMU)
553 break;
554 case blez_op:
537 if ((long)regs->regs[insn.i_format.rs] <= 0) 555 if ((long)regs->regs[insn.i_format.rs] <= 0)
538 *contpc = regs->cp0_epc + 556 *contpc = regs->cp0_epc +
539 dec_insn.pc_inc + 557 dec_insn.pc_inc +
@@ -543,8 +561,10 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
543 dec_insn.pc_inc + 561 dec_insn.pc_inc +
544 dec_insn.next_pc_inc; 562 dec_insn.next_pc_inc;
545 return 1; 563 return 1;
546 case bgtz_op:
547 case bgtzl_op: 564 case bgtzl_op:
565 if (NO_R6EMU)
566 break;
567 case bgtz_op:
548 if ((long)regs->regs[insn.i_format.rs] > 0) 568 if ((long)regs->regs[insn.i_format.rs] > 0)
549 *contpc = regs->cp0_epc + 569 *contpc = regs->cp0_epc +
550 dec_insn.pc_inc + 570 dec_insn.pc_inc +