From 5f9f41c474befb4ebbc40b27f65bb7d649241581 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 25 Nov 2014 15:54:14 +0000 Subject: MIPS: kernel: Prepare the JR instruction for emulation on MIPS R6 The MIPS R6 JR instruction is an alias to the JALR one, so it may need emulation for non-R6 userlands. Signed-off-by: Markos Chandras --- arch/mips/math-emu/cp1emu.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/mips/math-emu/cp1emu.c') diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 9dfcd7fc1bc3..9bf82117b4f2 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -448,6 +448,9 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.next_pc_inc; /* Fall through */ case jr_op: + /* For R6, JR already emulated in jalr_op */ + if (NO_R6EMU && insn.r_format.opcode == jr_op) + break; *contpc = regs->regs[insn.r_format.rs]; return 1; } -- cgit v1.2.3 From 319824eabc3f1c1aab67f408d66f384fbb996ee2 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 25 Nov 2014 16:02:23 +0000 Subject: 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 --- arch/mips/math-emu/cp1emu.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'arch/mips/math-emu/cp1emu.c') 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, switch (insn.i_format.rt) { case bltzal_op: case bltzall_op: + if (NO_R6EMU && (insn.i_format.rs || + insn.i_format.rt == bltzall_op)) + break; + regs->regs[31] = regs->cp0_epc + dec_insn.pc_inc + dec_insn.next_pc_inc; /* Fall through */ - case bltz_op: case bltzl_op: + if (NO_R6EMU) + break; + case bltz_op: if ((long)regs->regs[insn.i_format.rs] < 0) *contpc = regs->cp0_epc + dec_insn.pc_inc + @@ -476,12 +482,18 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, return 1; case bgezal_op: case bgezall_op: + if (NO_R6EMU && (insn.i_format.rs || + insn.i_format.rt == bgezall_op)) + break; + regs->regs[31] = regs->cp0_epc + dec_insn.pc_inc + dec_insn.next_pc_inc; /* Fall through */ - case bgez_op: case bgezl_op: + if (NO_R6EMU) + break; + case bgez_op: if ((long)regs->regs[insn.i_format.rs] >= 0) *contpc = regs->cp0_epc + dec_insn.pc_inc + @@ -508,8 +520,10 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, /* Set microMIPS mode bit: XOR for jalx. */ *contpc ^= bit; return 1; - case beq_op: case beql_op: + if (NO_R6EMU) + break; + case beq_op: if (regs->regs[insn.i_format.rs] == regs->regs[insn.i_format.rt]) *contpc = regs->cp0_epc + @@ -520,8 +534,10 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - case bne_op: case bnel_op: + if (NO_R6EMU) + break; + case bne_op: if (regs->regs[insn.i_format.rs] != regs->regs[insn.i_format.rt]) *contpc = regs->cp0_epc + @@ -532,8 +548,10 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - case blez_op: case blezl_op: + if (NO_R6EMU) + break; + case blez_op: if ((long)regs->regs[insn.i_format.rs] <= 0) *contpc = regs->cp0_epc + dec_insn.pc_inc + @@ -543,8 +561,10 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - case bgtz_op: case bgtzl_op: + if (NO_R6EMU) + break; + case bgtz_op: if ((long)regs->regs[insn.i_format.rs] > 0) *contpc = regs->cp0_epc + dec_insn.pc_inc + -- cgit v1.2.3 From c8a34581ec09a5ee11dd833d6c5cf41fdbef706f Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Wed, 26 Nov 2014 10:10:18 +0000 Subject: MIPS: Emulate the BC1{EQ,NE}Z FPU instructions MIPS R6 introduced the following two branch instructions for COP1: BC1EQZ: Branch if Cop1 (FPR) Register Bit 0 is Equal to Zero BC1NEZ: Branch if Cop1 (FPR) Register Bit 0 is Not Equal to Zero Signed-off-by: Markos Chandras --- arch/mips/math-emu/cp1emu.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'arch/mips/math-emu/cp1emu.c') diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 7bbaefe0434d..798204e492fc 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -602,6 +602,33 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, #endif case cop0_op: case cop1_op: + /* Need to check for R6 bc1nez and bc1eqz branches */ + if (cpu_has_mips_r6 && + ((insn.i_format.rs == bc1eqz_op) || + (insn.i_format.rs == bc1nez_op))) { + bit = 0; + switch (insn.i_format.rs) { + case bc1eqz_op: + if (get_fpr32(¤t->thread.fpu.fpr[insn.i_format.rt], 0) & 0x1) + bit = 1; + break; + case bc1nez_op: + if (!(get_fpr32(¤t->thread.fpu.fpr[insn.i_format.rt], 0) & 0x1)) + bit = 1; + break; + } + if (bit) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.i_format.simmediate << 2); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + + return 1; + } + /* R2/R6 compatible cop1 instruction. Fall through */ case cop2_op: case cop1x_op: if (insn.i_format.rs == bc_op) { -- cgit v1.2.3 From a8ff66f52d3f17b5ae793955270675c197f73d6c Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Wed, 26 Nov 2014 12:57:54 +0000 Subject: =?UTF-8?q?MIPS:=20Emulate=20the=20new=20MIPS=20R6=20B{L,G}=CE=95{?= =?UTF-8?q?Z,}{AL,}C=20instructions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MIPS R6 added the following four instructions which share the BLEZ and BLEZL opcodes: BLEZALC: Compact branch-and-link if GPR rt is <= to zero BGEZALC: Compact branch-and-link if GPR rt is >= to zero BLEZC : Compact branch if GPR rt is <= to zero BGEZC : Compact branch if GPR rt is >= to zero BGEC : Compact branch if GPR rs is less than or equal to GPR rt BGEUC : Similar to BGEC but unsigned. Signed-off-by: Markos Chandras --- arch/mips/math-emu/cp1emu.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'arch/mips/math-emu/cp1emu.c') diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 798204e492fc..c770617dc340 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -552,6 +552,30 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, if (NO_R6EMU) break; case blez_op: + + /* + * Compact branches for R6 for the + * blez and blezl opcodes. + * BLEZ | rs = 0 | rt != 0 == BLEZALC + * BLEZ | rs = rt != 0 == BGEZALC + * BLEZ | rs != 0 | rt != 0 == BGEUC + * BLEZL | rs = 0 | rt != 0 == BLEZC + * BLEZL | rs = rt != 0 == BGEZC + * BLEZL | rs != 0 | rt != 0 == BGEC + * + * For real BLEZ{,L}, rt is always 0. + */ + if (cpu_has_mips_r6 && insn.i_format.rt) { + if ((insn.i_format.opcode == blez_op) && + ((!insn.i_format.rs && insn.i_format.rt) || + (insn.i_format.rs == insn.i_format.rt))) + regs->regs[31] = regs->cp0_epc + + dec_insn.pc_inc; + *contpc = regs->cp0_epc + dec_insn.pc_inc + + dec_insn.next_pc_inc; + + return 1; + } if ((long)regs->regs[insn.i_format.rs] <= 0) *contpc = regs->cp0_epc + dec_insn.pc_inc + -- cgit v1.2.3 From f1b44067c19258b7614e3cd09dfe8d8e12ff5895 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Wed, 26 Nov 2014 13:05:09 +0000 Subject: MIPS: Emulate the new MIPS R6 B{L,G}T{Z,}{AL,}C instructions MIPS R6 added the following four instructions which share the BGTZ and BGTZL opcode: BLTZALC: Compact branch-and-link if GPR rt is < to zero BGTZALC: Compact branch-and-link if GPR rt is > to zero BLTZL : Compact branch if GPR rt is < to zero BGTZL : Compact branch if GPR rt is > to zero BLTC : Compact branch if GPR rs is less than GPR rt BLTUC : Similar to BLTC but unsigned Signed-off-by: Markos Chandras --- arch/mips/math-emu/cp1emu.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'arch/mips/math-emu/cp1emu.c') diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index c770617dc340..d6d67e2a0434 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -589,6 +589,31 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, if (NO_R6EMU) break; case bgtz_op: + /* + * Compact branches for R6 for the + * bgtz and bgtzl opcodes. + * BGTZ | rs = 0 | rt != 0 == BGTZALC + * BGTZ | rs = rt != 0 == BLTZALC + * BGTZ | rs != 0 | rt != 0 == BLTUC + * BGTZL | rs = 0 | rt != 0 == BGTZC + * BGTZL | rs = rt != 0 == BLTZC + * BGTZL | rs != 0 | rt != 0 == BLTC + * + * *ZALC varint for BGTZ &&& rt != 0 + * For real GTZ{,L}, rt is always 0. + */ + if (cpu_has_mips_r6 && insn.i_format.rt) { + if ((insn.i_format.opcode == blez_op) && + ((!insn.i_format.rs && insn.i_format.rt) || + (insn.i_format.rs == insn.i_format.rt))) + regs->regs[31] = regs->cp0_epc + + dec_insn.pc_inc; + *contpc = regs->cp0_epc + dec_insn.pc_inc + + dec_insn.next_pc_inc; + + return 1; + } + if ((long)regs->regs[insn.i_format.rs] > 0) *contpc = regs->cp0_epc + dec_insn.pc_inc + -- cgit v1.2.3 From 8467ca0122e20f3f8e73d34907b8b30461af5d4e Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Wed, 26 Nov 2014 13:56:51 +0000 Subject: MIPS: Emulate the new MIPS R6 branch compact (BC) instruction MIPS R6 uses the --- arch/mips/math-emu/cp1emu.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'arch/mips/math-emu/cp1emu.c') diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index d6d67e2a0434..7f373a2858b5 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -648,6 +648,19 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, else *contpc = regs->cp0_epc + 8; return 1; +#else + case bc6_op: + /* + * Only valid for MIPS R6 but we can still end up + * here from a broken userland so just tell emulator + * this is not a branch and let it break later on. + */ + if (!cpu_has_mips_r6) + break; + *contpc = regs->cp0_epc + dec_insn.pc_inc + + dec_insn.next_pc_inc; + + return 1; #endif case cop0_op: case cop1_op: -- cgit v1.2.3 From c893ce38b265d5787d03850b36221f595b224538 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Wed, 26 Nov 2014 14:08:52 +0000 Subject: MIPS: Emulate the new MIPS R6 BOVC, BEQC and BEQZALC instructions MIPS R6 uses the --- arch/mips/math-emu/cp1emu.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch/mips/math-emu/cp1emu.c') diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 7f373a2858b5..c115d969664b 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -623,6 +623,15 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; + case cbcond0_op: + if (!cpu_has_mips_r6) + break; + if (insn.i_format.rt && !insn.i_format.rs) + regs->regs[31] = regs->cp0_epc + 4; + *contpc = regs->cp0_epc + dec_insn.pc_inc + + dec_insn.next_pc_inc; + + return 1; #ifdef CONFIG_CPU_CAVIUM_OCTEON case lwc2_op: /* This is bbit0 on Octeon */ if ((regs->regs[insn.i_format.rs] & (1ull< Date: Wed, 26 Nov 2014 15:03:54 +0000 Subject: MIPS: Emulate the new MIPS R6 BNVC, BNEC and BNEZLAC instructions MIPS R6 uses the --- arch/mips/math-emu/cp1emu.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/mips/math-emu/cp1emu.c') diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index c115d969664b..0d8407b51470 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -624,6 +624,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.next_pc_inc; return 1; case cbcond0_op: + case cbcond1_op: if (!cpu_has_mips_r6) break; if (insn.i_format.rt && !insn.i_format.rs) -- cgit v1.2.3 From 84fef630127aa90ef547ddd018d3dc47b1e79a1e Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Wed, 26 Nov 2014 15:43:11 +0000 Subject: MIPS: Emulate the new MIPS R6 BALC instruction MIPS R6 uses the --- arch/mips/math-emu/cp1emu.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch/mips/math-emu/cp1emu.c') diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 0d8407b51470..d732100c99f0 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -670,6 +670,14 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, *contpc = regs->cp0_epc + dec_insn.pc_inc + dec_insn.next_pc_inc; + return 1; + case balc6_op: + if (!cpu_has_mips_r6) + break; + regs->regs[31] = regs->cp0_epc + 4; + *contpc = regs->cp0_epc + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; #endif case cop0_op: -- cgit v1.2.3 From 69b9a2fd05a308b9b1e1f282f3b772491603c582 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Thu, 27 Nov 2014 09:32:25 +0000 Subject: MIPS: Emulate the new MIPS R6 BEQZC and JIC instructions MIPS R6 uses the --- arch/mips/math-emu/cp1emu.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch/mips/math-emu/cp1emu.c') diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index d732100c99f0..f00af84f017d 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -678,6 +678,13 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, *contpc = regs->cp0_epc + dec_insn.pc_inc + dec_insn.next_pc_inc; + return 1; + case beqzcjic_op: + if (!cpu_has_mips_r6) + break; + *contpc = regs->cp0_epc + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; #endif case cop0_op: -- cgit v1.2.3 From 28d6f93d201d20ce47a9e8414655569a78f0353c Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Thu, 8 Jan 2015 11:55:20 +0000 Subject: MIPS: Emulate the new MIPS R6 BNEZC and JIALC instructions MIPS R6 uses the --- arch/mips/math-emu/cp1emu.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch/mips/math-emu/cp1emu.c') diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index f00af84f017d..6e7920b20822 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -685,6 +685,15 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, *contpc = regs->cp0_epc + dec_insn.pc_inc + dec_insn.next_pc_inc; + return 1; + case bnezcjialc_op: + if (!cpu_has_mips_r6) + break; + if (!insn.i_format.rs) + regs->regs[31] = regs->cp0_epc + 4; + *contpc = regs->cp0_epc + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; #endif case cop0_op: -- cgit v1.2.3 From b0a668fb2038d846a466c7a16a358d874002b697 Mon Sep 17 00:00:00 2001 From: Leonid Yegoshin Date: Wed, 3 Dec 2014 15:47:03 +0000 Subject: MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6 MIPS R6 removed quite a few R2 instructions. However, there is plenty of Signed-off-by: Markos Chandras --- arch/mips/math-emu/cp1emu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/mips/math-emu/cp1emu.c') diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 6e7920b20822..3c341b08d120 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -48,6 +48,7 @@ #include #include #include +#include #include "ieee754.h" @@ -68,7 +69,7 @@ static int fpux_emu(struct pt_regs *, #define modeindex(v) ((v) & FPU_CSR_RM) /* convert condition code register number to csr bit */ -static const unsigned int fpucondbit[8] = { +const unsigned int fpucondbit[8] = { FPU_CSR_COND0, FPU_CSR_COND1, FPU_CSR_COND2, -- cgit v1.2.3 From e0d32f33e651a393a23826c06a9301917372f3e2 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Thu, 15 Jan 2015 10:11:17 +0000 Subject: MIPS: Handle MIPS IV, V and R2 FPU instructions on MIPS R6 as well MIPS R2 FPU instructions are also present in MIPS R6 so amend the preprocessor definitions to take MIPS R6 into consideration. Signed-off-by: Markos Chandras --- arch/mips/math-emu/cp1emu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/mips/math-emu/cp1emu.c') diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 3c341b08d120..b30bf65c7d7d 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -1561,14 +1561,14 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, * achieve full IEEE-754 accuracy - however this emulator does. */ case frsqrt_op: - if (!cpu_has_mips_4_5_r2) + if (!cpu_has_mips_4_5_r2_r6) return SIGILL; handler.u = fpemu_sp_rsqrt; goto scopuop; case frecip_op: - if (!cpu_has_mips_4_5_r2) + if (!cpu_has_mips_4_5_r2_r6) return SIGILL; handler.u = fpemu_sp_recip; @@ -1763,13 +1763,13 @@ copcsr: * achieve full IEEE-754 accuracy - however this emulator does. */ case frsqrt_op: - if (!cpu_has_mips_4_5_r2) + if (!cpu_has_mips_4_5_r2_r6) return SIGILL; handler.u = fpemu_dp_rsqrt; goto dcopuop; case frecip_op: - if (!cpu_has_mips_4_5_r2) + if (!cpu_has_mips_4_5_r2_r6) return SIGILL; handler.u = fpemu_dp_recip; -- cgit v1.2.3