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 <markos.chandras@imgtec.com>
This commit is contained in:
		
					parent
					
						
							
								a8ff66f52d
							
						
					
				
			
			
				commit
				
					
						f1b44067c1
					
				
			
		
					 2 changed files with 47 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -635,6 +635,28 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 | 
			
		|||
		if (NO_R6EMU)
 | 
			
		||||
			goto sigill_r6;
 | 
			
		||||
	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] = epc + 4;
 | 
			
		||||
			regs->cp0_epc += 8;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* rt field assumed to be zero */
 | 
			
		||||
		if ((long)regs->regs[insn.i_format.rs] > 0) {
 | 
			
		||||
			epc = epc + 4 + (insn.i_format.simmediate << 2);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 +
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue