aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/branch.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/branch.c')
-rw-r--r--arch/mips/kernel/branch.c70
1 files changed, 63 insertions, 7 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);