branch.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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, 97, 2000, 2001 by Ralf Baechle
  7. * Copyright (C) 2001 MIPS Technologies, Inc.
  8. */
  9. #include <linux/kernel.h>
  10. #include <linux/sched.h>
  11. #include <linux/signal.h>
  12. #include <asm/branch.h>
  13. #include <asm/cpu.h>
  14. #include <asm/cpu-features.h>
  15. #include <asm/inst.h>
  16. #include <asm/ptrace.h>
  17. #include <asm/uaccess.h>
  18. /*
  19. * Compute the return address and do emulate branch simulation, if required.
  20. */
  21. int __compute_return_epc(struct pt_regs *regs)
  22. {
  23. unsigned int *addr, bit, fcr31;
  24. long epc;
  25. union mips_instruction insn;
  26. epc = regs->cp0_epc;
  27. if (epc & 3)
  28. goto unaligned;
  29. /*
  30. * Read the instruction
  31. */
  32. addr = (unsigned int *) epc;
  33. if (__get_user(insn.word, addr)) {
  34. force_sig(SIGSEGV, current);
  35. return -EFAULT;
  36. }
  37. regs->regs[0] = 0;
  38. switch (insn.i_format.opcode) {
  39. /*
  40. * jr and jalr are in r_format format.
  41. */
  42. case spec_op:
  43. switch (insn.r_format.func) {
  44. case jalr_op:
  45. regs->regs[insn.r_format.rd] = epc + 8;
  46. /* Fall through */
  47. case jr_op:
  48. regs->cp0_epc = regs->regs[insn.r_format.rs];
  49. break;
  50. }
  51. break;
  52. /*
  53. * This group contains:
  54. * bltz_op, bgez_op, bltzl_op, bgezl_op,
  55. * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
  56. */
  57. case bcond_op:
  58. switch (insn.i_format.rt) {
  59. case bltz_op:
  60. case bltzl_op:
  61. if ((long)regs->regs[insn.i_format.rs] < 0)
  62. epc = epc + 4 + (insn.i_format.simmediate << 2);
  63. else
  64. epc += 8;
  65. regs->cp0_epc = epc;
  66. break;
  67. case bgez_op:
  68. case bgezl_op:
  69. if ((long)regs->regs[insn.i_format.rs] >= 0)
  70. epc = epc + 4 + (insn.i_format.simmediate << 2);
  71. else
  72. epc += 8;
  73. regs->cp0_epc = epc;
  74. break;
  75. case bltzal_op:
  76. case bltzall_op:
  77. regs->regs[31] = epc + 8;
  78. if ((long)regs->regs[insn.i_format.rs] < 0)
  79. epc = epc + 4 + (insn.i_format.simmediate << 2);
  80. else
  81. epc += 8;
  82. regs->cp0_epc = epc;
  83. break;
  84. case bgezal_op:
  85. case bgezall_op:
  86. regs->regs[31] = epc + 8;
  87. if ((long)regs->regs[insn.i_format.rs] >= 0)
  88. epc = epc + 4 + (insn.i_format.simmediate << 2);
  89. else
  90. epc += 8;
  91. regs->cp0_epc = epc;
  92. break;
  93. }
  94. break;
  95. /*
  96. * These are unconditional and in j_format.
  97. */
  98. case jal_op:
  99. regs->regs[31] = regs->cp0_epc + 8;
  100. case j_op:
  101. epc += 4;
  102. epc >>= 28;
  103. epc <<= 28;
  104. epc |= (insn.j_format.target << 2);
  105. regs->cp0_epc = epc;
  106. break;
  107. /*
  108. * These are conditional and in i_format.
  109. */
  110. case beq_op:
  111. case beql_op:
  112. if (regs->regs[insn.i_format.rs] ==
  113. regs->regs[insn.i_format.rt])
  114. epc = epc + 4 + (insn.i_format.simmediate << 2);
  115. else
  116. epc += 8;
  117. regs->cp0_epc = epc;
  118. break;
  119. case bne_op:
  120. case bnel_op:
  121. if (regs->regs[insn.i_format.rs] !=
  122. regs->regs[insn.i_format.rt])
  123. epc = epc + 4 + (insn.i_format.simmediate << 2);
  124. else
  125. epc += 8;
  126. regs->cp0_epc = epc;
  127. break;
  128. case blez_op: /* not really i_format */
  129. case blezl_op:
  130. /* rt field assumed to be zero */
  131. if ((long)regs->regs[insn.i_format.rs] <= 0)
  132. epc = epc + 4 + (insn.i_format.simmediate << 2);
  133. else
  134. epc += 8;
  135. regs->cp0_epc = epc;
  136. break;
  137. case bgtz_op:
  138. case bgtzl_op:
  139. /* rt field assumed to be zero */
  140. if ((long)regs->regs[insn.i_format.rs] > 0)
  141. epc = epc + 4 + (insn.i_format.simmediate << 2);
  142. else
  143. epc += 8;
  144. regs->cp0_epc = epc;
  145. break;
  146. /*
  147. * And now the FPA/cp1 branch instructions.
  148. */
  149. case cop1_op:
  150. if (!cpu_has_fpu)
  151. fcr31 = current->thread.fpu.soft.fcr31;
  152. else
  153. asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
  154. bit = (insn.i_format.rt >> 2);
  155. bit += (bit != 0);
  156. bit += 23;
  157. switch (insn.i_format.rt) {
  158. case 0: /* bc1f */
  159. case 2: /* bc1fl */
  160. if (~fcr31 & (1 << bit))
  161. epc = epc + 4 + (insn.i_format.simmediate << 2);
  162. else
  163. epc += 8;
  164. regs->cp0_epc = epc;
  165. break;
  166. case 1: /* bc1t */
  167. case 3: /* bc1tl */
  168. if (fcr31 & (1 << bit))
  169. epc = epc + 4 + (insn.i_format.simmediate << 2);
  170. else
  171. epc += 8;
  172. regs->cp0_epc = epc;
  173. break;
  174. }
  175. break;
  176. }
  177. return 0;
  178. unaligned:
  179. printk("%s: unaligned epc - sending SIGBUS.\n", current->comm);
  180. force_sig(SIGBUS, current);
  181. return -EFAULT;
  182. }