aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/include/asm/branch.h18
-rw-r--r--arch/mips/kernel/branch.c196
-rw-r--r--arch/mips/math-emu/cp1emu.c201
3 files changed, 214 insertions, 201 deletions
diff --git a/arch/mips/include/asm/branch.h b/arch/mips/include/asm/branch.h
index d109e34130f5..de781cf54bc7 100644
--- a/arch/mips/include/asm/branch.h
+++ b/arch/mips/include/asm/branch.h
@@ -20,6 +20,24 @@ extern int __compute_return_epc_for_insn(struct pt_regs *regs,
20extern int __microMIPS_compute_return_epc(struct pt_regs *regs); 20extern int __microMIPS_compute_return_epc(struct pt_regs *regs);
21extern int __MIPS16e_compute_return_epc(struct pt_regs *regs); 21extern int __MIPS16e_compute_return_epc(struct pt_regs *regs);
22 22
23/*
24 * microMIPS bitfields
25 */
26#define MM_POOL32A_MINOR_MASK 0x3f
27#define MM_POOL32A_MINOR_SHIFT 0x6
28#define MM_MIPS32_COND_FC 0x30
29
30extern int __mm_isBranchInstr(struct pt_regs *regs,
31 struct mm_decoded_insn dec_insn, unsigned long *contpc);
32
33static inline int mm_isBranchInstr(struct pt_regs *regs,
34 struct mm_decoded_insn dec_insn, unsigned long *contpc)
35{
36 if (!cpu_has_mmips)
37 return 0;
38
39 return __mm_isBranchInstr(regs, dec_insn, contpc);
40}
23 41
24static inline int delay_slot(struct pt_regs *regs) 42static inline int delay_slot(struct pt_regs *regs)
25{ 43{
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 4d78bf445a9c..84888d9332b9 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -48,6 +48,202 @@ int __isa_exception_epc(struct pt_regs *regs)
48 return epc; 48 return epc;
49} 49}
50 50
51/* (microMIPS) Convert 16-bit register encoding to 32-bit register encoding. */
52static const unsigned int reg16to32map[8] = {16, 17, 2, 3, 4, 5, 6, 7};
53
54int __mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
55 unsigned long *contpc)
56{
57 union mips_instruction insn = (union mips_instruction)dec_insn.insn;
58 int bc_false = 0;
59 unsigned int fcr31;
60 unsigned int bit;
61
62 if (!cpu_has_mmips)
63 return 0;
64
65 switch (insn.mm_i_format.opcode) {
66 case mm_pool32a_op:
67 if ((insn.mm_i_format.simmediate & MM_POOL32A_MINOR_MASK) ==
68 mm_pool32axf_op) {
69 switch (insn.mm_i_format.simmediate >>
70 MM_POOL32A_MINOR_SHIFT) {
71 case mm_jalr_op:
72 case mm_jalrhb_op:
73 case mm_jalrs_op:
74 case mm_jalrshb_op:
75 if (insn.mm_i_format.rt != 0) /* Not mm_jr */
76 regs->regs[insn.mm_i_format.rt] =
77 regs->cp0_epc +
78 dec_insn.pc_inc +
79 dec_insn.next_pc_inc;
80 *contpc = regs->regs[insn.mm_i_format.rs];
81 return 1;
82 }
83 }
84 break;
85 case mm_pool32i_op:
86 switch (insn.mm_i_format.rt) {
87 case mm_bltzals_op:
88 case mm_bltzal_op:
89 regs->regs[31] = regs->cp0_epc +
90 dec_insn.pc_inc +
91 dec_insn.next_pc_inc;
92 /* Fall through */
93 case mm_bltz_op:
94 if ((long)regs->regs[insn.mm_i_format.rs] < 0)
95 *contpc = regs->cp0_epc +
96 dec_insn.pc_inc +
97 (insn.mm_i_format.simmediate << 1);
98 else
99 *contpc = regs->cp0_epc +
100 dec_insn.pc_inc +
101 dec_insn.next_pc_inc;
102 return 1;
103 case mm_bgezals_op:
104 case mm_bgezal_op:
105 regs->regs[31] = regs->cp0_epc +
106 dec_insn.pc_inc +
107 dec_insn.next_pc_inc;
108 /* Fall through */
109 case mm_bgez_op:
110 if ((long)regs->regs[insn.mm_i_format.rs] >= 0)
111 *contpc = regs->cp0_epc +
112 dec_insn.pc_inc +
113 (insn.mm_i_format.simmediate << 1);
114 else
115 *contpc = regs->cp0_epc +
116 dec_insn.pc_inc +
117 dec_insn.next_pc_inc;
118 return 1;
119 case mm_blez_op:
120 if ((long)regs->regs[insn.mm_i_format.rs] <= 0)
121 *contpc = regs->cp0_epc +
122 dec_insn.pc_inc +
123 (insn.mm_i_format.simmediate << 1);
124 else
125 *contpc = regs->cp0_epc +
126 dec_insn.pc_inc +
127 dec_insn.next_pc_inc;
128 return 1;
129 case mm_bgtz_op:
130 if ((long)regs->regs[insn.mm_i_format.rs] <= 0)
131 *contpc = regs->cp0_epc +
132 dec_insn.pc_inc +
133 (insn.mm_i_format.simmediate << 1);
134 else
135 *contpc = regs->cp0_epc +
136 dec_insn.pc_inc +
137 dec_insn.next_pc_inc;
138 return 1;
139 case mm_bc2f_op:
140 case mm_bc1f_op:
141 bc_false = 1;
142 /* Fall through */
143 case mm_bc2t_op:
144 case mm_bc1t_op:
145 preempt_disable();
146 if (is_fpu_owner())
147 asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
148 else
149 fcr31 = current->thread.fpu.fcr31;
150 preempt_enable();
151
152 if (bc_false)
153 fcr31 = ~fcr31;
154
155 bit = (insn.mm_i_format.rs >> 2);
156 bit += (bit != 0);
157 bit += 23;
158 if (fcr31 & (1 << bit))
159 *contpc = regs->cp0_epc +
160 dec_insn.pc_inc +
161 (insn.mm_i_format.simmediate << 1);
162 else
163 *contpc = regs->cp0_epc +
164 dec_insn.pc_inc + dec_insn.next_pc_inc;
165 return 1;
166 }
167 break;
168 case mm_pool16c_op:
169 switch (insn.mm_i_format.rt) {
170 case mm_jalr16_op:
171 case mm_jalrs16_op:
172 regs->regs[31] = regs->cp0_epc +
173 dec_insn.pc_inc + dec_insn.next_pc_inc;
174 /* Fall through */
175 case mm_jr16_op:
176 *contpc = regs->regs[insn.mm_i_format.rs];
177 return 1;
178 }
179 break;
180 case mm_beqz16_op:
181 if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] == 0)
182 *contpc = regs->cp0_epc +
183 dec_insn.pc_inc +
184 (insn.mm_b1_format.simmediate << 1);
185 else
186 *contpc = regs->cp0_epc +
187 dec_insn.pc_inc + dec_insn.next_pc_inc;
188 return 1;
189 case mm_bnez16_op:
190 if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] != 0)
191 *contpc = regs->cp0_epc +
192 dec_insn.pc_inc +
193 (insn.mm_b1_format.simmediate << 1);
194 else
195 *contpc = regs->cp0_epc +
196 dec_insn.pc_inc + dec_insn.next_pc_inc;
197 return 1;
198 case mm_b16_op:
199 *contpc = regs->cp0_epc + dec_insn.pc_inc +
200 (insn.mm_b0_format.simmediate << 1);
201 return 1;
202 case mm_beq32_op:
203 if (regs->regs[insn.mm_i_format.rs] ==
204 regs->regs[insn.mm_i_format.rt])
205 *contpc = regs->cp0_epc +
206 dec_insn.pc_inc +
207 (insn.mm_i_format.simmediate << 1);
208 else
209 *contpc = regs->cp0_epc +
210 dec_insn.pc_inc +
211 dec_insn.next_pc_inc;
212 return 1;
213 case mm_bne32_op:
214 if (regs->regs[insn.mm_i_format.rs] !=
215 regs->regs[insn.mm_i_format.rt])
216 *contpc = regs->cp0_epc +
217 dec_insn.pc_inc +
218 (insn.mm_i_format.simmediate << 1);
219 else
220 *contpc = regs->cp0_epc +
221 dec_insn.pc_inc + dec_insn.next_pc_inc;
222 return 1;
223 case mm_jalx32_op:
224 regs->regs[31] = regs->cp0_epc +
225 dec_insn.pc_inc + dec_insn.next_pc_inc;
226 *contpc = regs->cp0_epc + dec_insn.pc_inc;
227 *contpc >>= 28;
228 *contpc <<= 28;
229 *contpc |= (insn.j_format.target << 2);
230 return 1;
231 case mm_jals32_op:
232 case mm_jal32_op:
233 regs->regs[31] = regs->cp0_epc +
234 dec_insn.pc_inc + dec_insn.next_pc_inc;
235 /* Fall through */
236 case mm_j32_op:
237 *contpc = regs->cp0_epc + dec_insn.pc_inc;
238 *contpc >>= 27;
239 *contpc <<= 27;
240 *contpc |= (insn.j_format.target << 1);
241 set_isa16_mode(*contpc);
242 return 1;
243 }
244 return 0;
245}
246
51/* 247/*
52 * Compute return address and emulate branch in microMIPS mode after an 248 * Compute return address and emulate branch in microMIPS mode after an
53 * exception only. It does not handle compact branches/jumps and cannot 249 * exception only. It does not handle compact branches/jumps and cannot
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 6258291354eb..b31ce6cdb6b9 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -67,11 +67,6 @@ static int fpux_emu(struct pt_regs *,
67/* Determine rounding mode from the RM bits of the FCSR */ 67/* Determine rounding mode from the RM bits of the FCSR */
68#define modeindex(v) ((v) & FPU_CSR_RM) 68#define modeindex(v) ((v) & FPU_CSR_RM)
69 69
70/* microMIPS bitfields */
71#define MM_POOL32A_MINOR_MASK 0x3f
72#define MM_POOL32A_MINOR_SHIFT 0x6
73#define MM_MIPS32_COND_FC 0x30
74
75/* Convert MIPS rounding mode (0..3) to IEEE library modes. */ 70/* Convert MIPS rounding mode (0..3) to IEEE library modes. */
76static const unsigned char ieee_rm[4] = { 71static const unsigned char ieee_rm[4] = {
77 [FPU_CSR_RN] = IEEE754_RN, 72 [FPU_CSR_RN] = IEEE754_RN,
@@ -99,9 +94,6 @@ static const unsigned int fpucondbit[8] = {
99 FPU_CSR_COND7 94 FPU_CSR_COND7
100}; 95};
101 96
102/* (microMIPS) Convert 16-bit register encoding to 32-bit register encoding. */
103static const unsigned int reg16to32map[8] = {16, 17, 2, 3, 4, 5, 6, 7};
104
105/* (microMIPS) Convert certain microMIPS instructions to MIPS32 format. */ 97/* (microMIPS) Convert certain microMIPS instructions to MIPS32 format. */
106static const int sd_format[] = {16, 17, 0, 0, 0, 0, 0, 0}; 98static const int sd_format[] = {16, 17, 0, 0, 0, 0, 0, 0};
107static const int sdps_format[] = {16, 17, 22, 0, 0, 0, 0, 0}; 99static const int sdps_format[] = {16, 17, 22, 0, 0, 0, 0, 0};
@@ -449,199 +441,6 @@ static int microMIPS32_to_MIPS32(union mips_instruction *insn_ptr)
449 return 0; 441 return 0;
450} 442}
451 443
452int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
453 unsigned long *contpc)
454{
455 union mips_instruction insn = (union mips_instruction)dec_insn.insn;
456 int bc_false = 0;
457 unsigned int fcr31;
458 unsigned int bit;
459
460 if (!cpu_has_mmips)
461 return 0;
462
463 switch (insn.mm_i_format.opcode) {
464 case mm_pool32a_op:
465 if ((insn.mm_i_format.simmediate & MM_POOL32A_MINOR_MASK) ==
466 mm_pool32axf_op) {
467 switch (insn.mm_i_format.simmediate >>
468 MM_POOL32A_MINOR_SHIFT) {
469 case mm_jalr_op:
470 case mm_jalrhb_op:
471 case mm_jalrs_op:
472 case mm_jalrshb_op:
473 if (insn.mm_i_format.rt != 0) /* Not mm_jr */
474 regs->regs[insn.mm_i_format.rt] =
475 regs->cp0_epc +
476 dec_insn.pc_inc +
477 dec_insn.next_pc_inc;
478 *contpc = regs->regs[insn.mm_i_format.rs];
479 return 1;
480 }
481 }
482 break;
483 case mm_pool32i_op:
484 switch (insn.mm_i_format.rt) {
485 case mm_bltzals_op:
486 case mm_bltzal_op:
487 regs->regs[31] = regs->cp0_epc +
488 dec_insn.pc_inc +
489 dec_insn.next_pc_inc;
490 /* Fall through */
491 case mm_bltz_op:
492 if ((long)regs->regs[insn.mm_i_format.rs] < 0)
493 *contpc = regs->cp0_epc +
494 dec_insn.pc_inc +
495 (insn.mm_i_format.simmediate << 1);
496 else
497 *contpc = regs->cp0_epc +
498 dec_insn.pc_inc +
499 dec_insn.next_pc_inc;
500 return 1;
501 case mm_bgezals_op:
502 case mm_bgezal_op:
503 regs->regs[31] = regs->cp0_epc +
504 dec_insn.pc_inc +
505 dec_insn.next_pc_inc;
506 /* Fall through */
507 case mm_bgez_op:
508 if ((long)regs->regs[insn.mm_i_format.rs] >= 0)
509 *contpc = regs->cp0_epc +
510 dec_insn.pc_inc +
511 (insn.mm_i_format.simmediate << 1);
512 else
513 *contpc = regs->cp0_epc +
514 dec_insn.pc_inc +
515 dec_insn.next_pc_inc;
516 return 1;
517 case mm_blez_op:
518 if ((long)regs->regs[insn.mm_i_format.rs] <= 0)
519 *contpc = regs->cp0_epc +
520 dec_insn.pc_inc +
521 (insn.mm_i_format.simmediate << 1);
522 else
523 *contpc = regs->cp0_epc +
524 dec_insn.pc_inc +
525 dec_insn.next_pc_inc;
526 return 1;
527 case mm_bgtz_op:
528 if ((long)regs->regs[insn.mm_i_format.rs] <= 0)
529 *contpc = regs->cp0_epc +
530 dec_insn.pc_inc +
531 (insn.mm_i_format.simmediate << 1);
532 else
533 *contpc = regs->cp0_epc +
534 dec_insn.pc_inc +
535 dec_insn.next_pc_inc;
536 return 1;
537 case mm_bc2f_op:
538 case mm_bc1f_op:
539 bc_false = 1;
540 /* Fall through */
541 case mm_bc2t_op:
542 case mm_bc1t_op:
543 preempt_disable();
544 if (is_fpu_owner())
545 asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
546 else
547 fcr31 = current->thread.fpu.fcr31;
548 preempt_enable();
549
550 if (bc_false)
551 fcr31 = ~fcr31;
552
553 bit = (insn.mm_i_format.rs >> 2);
554 bit += (bit != 0);
555 bit += 23;
556 if (fcr31 & (1 << bit))
557 *contpc = regs->cp0_epc +
558 dec_insn.pc_inc +
559 (insn.mm_i_format.simmediate << 1);
560 else
561 *contpc = regs->cp0_epc +
562 dec_insn.pc_inc + dec_insn.next_pc_inc;
563 return 1;
564 }
565 break;
566 case mm_pool16c_op:
567 switch (insn.mm_i_format.rt) {
568 case mm_jalr16_op:
569 case mm_jalrs16_op:
570 regs->regs[31] = regs->cp0_epc +
571 dec_insn.pc_inc + dec_insn.next_pc_inc;
572 /* Fall through */
573 case mm_jr16_op:
574 *contpc = regs->regs[insn.mm_i_format.rs];
575 return 1;
576 }
577 break;
578 case mm_beqz16_op:
579 if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] == 0)
580 *contpc = regs->cp0_epc +
581 dec_insn.pc_inc +
582 (insn.mm_b1_format.simmediate << 1);
583 else
584 *contpc = regs->cp0_epc +
585 dec_insn.pc_inc + dec_insn.next_pc_inc;
586 return 1;
587 case mm_bnez16_op:
588 if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] != 0)
589 *contpc = regs->cp0_epc +
590 dec_insn.pc_inc +
591 (insn.mm_b1_format.simmediate << 1);
592 else
593 *contpc = regs->cp0_epc +
594 dec_insn.pc_inc + dec_insn.next_pc_inc;
595 return 1;
596 case mm_b16_op:
597 *contpc = regs->cp0_epc + dec_insn.pc_inc +
598 (insn.mm_b0_format.simmediate << 1);
599 return 1;
600 case mm_beq32_op:
601 if (regs->regs[insn.mm_i_format.rs] ==
602 regs->regs[insn.mm_i_format.rt])
603 *contpc = regs->cp0_epc +
604 dec_insn.pc_inc +
605 (insn.mm_i_format.simmediate << 1);
606 else
607 *contpc = regs->cp0_epc +
608 dec_insn.pc_inc +
609 dec_insn.next_pc_inc;
610 return 1;
611 case mm_bne32_op:
612 if (regs->regs[insn.mm_i_format.rs] !=
613 regs->regs[insn.mm_i_format.rt])
614 *contpc = regs->cp0_epc +
615 dec_insn.pc_inc +
616 (insn.mm_i_format.simmediate << 1);
617 else
618 *contpc = regs->cp0_epc +
619 dec_insn.pc_inc + dec_insn.next_pc_inc;
620 return 1;
621 case mm_jalx32_op:
622 regs->regs[31] = regs->cp0_epc +
623 dec_insn.pc_inc + dec_insn.next_pc_inc;
624 *contpc = regs->cp0_epc + dec_insn.pc_inc;
625 *contpc >>= 28;
626 *contpc <<= 28;
627 *contpc |= (insn.j_format.target << 2);
628 return 1;
629 case mm_jals32_op:
630 case mm_jal32_op:
631 regs->regs[31] = regs->cp0_epc +
632 dec_insn.pc_inc + dec_insn.next_pc_inc;
633 /* Fall through */
634 case mm_j32_op:
635 *contpc = regs->cp0_epc + dec_insn.pc_inc;
636 *contpc >>= 27;
637 *contpc <<= 27;
638 *contpc |= (insn.j_format.target << 1);
639 set_isa16_mode(*contpc);
640 return 1;
641 }
642 return 0;
643}
644
645/* 444/*
646 * Redundant with logic already in kernel/branch.c, 445 * Redundant with logic already in kernel/branch.c,
647 * embedded in compute_return_epc. At some point, 446 * embedded in compute_return_epc. At some point,