Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 1996, 1997, 1998, 2001 by Ralf Baechle
0007  */
0008 #ifndef _ASM_BRANCH_H
0009 #define _ASM_BRANCH_H
0010 
0011 #include <asm/cpu-features.h>
0012 #include <asm/mipsregs.h>
0013 #include <asm/ptrace.h>
0014 #include <asm/inst.h>
0015 
0016 extern int __isa_exception_epc(struct pt_regs *regs);
0017 extern int __compute_return_epc(struct pt_regs *regs);
0018 extern int __compute_return_epc_for_insn(struct pt_regs *regs,
0019                      union mips_instruction insn);
0020 extern int __microMIPS_compute_return_epc(struct pt_regs *regs);
0021 extern int __MIPS16e_compute_return_epc(struct pt_regs *regs);
0022 
0023 /*
0024  * microMIPS bitfields
0025  */
0026 #define MM_POOL32A_MINOR_MASK   0x3f
0027 #define MM_POOL32A_MINOR_SHIFT  0x6
0028 #define MM_MIPS32_COND_FC   0x30
0029 
0030 int isBranchInstr(struct pt_regs *regs,
0031     struct mm_decoded_insn dec_insn, unsigned long *contpc);
0032 
0033 extern int __mm_isBranchInstr(struct pt_regs *regs,
0034     struct mm_decoded_insn dec_insn, unsigned long *contpc);
0035 
0036 static inline int mm_isBranchInstr(struct pt_regs *regs,
0037     struct mm_decoded_insn dec_insn, unsigned long *contpc)
0038 {
0039     if (!cpu_has_mmips)
0040         return 0;
0041 
0042     return __mm_isBranchInstr(regs, dec_insn, contpc);
0043 }
0044 
0045 static inline int delay_slot(struct pt_regs *regs)
0046 {
0047     return regs->cp0_cause & CAUSEF_BD;
0048 }
0049 
0050 static inline void clear_delay_slot(struct pt_regs *regs)
0051 {
0052     regs->cp0_cause &= ~CAUSEF_BD;
0053 }
0054 
0055 static inline void set_delay_slot(struct pt_regs *regs)
0056 {
0057     regs->cp0_cause |= CAUSEF_BD;
0058 }
0059 
0060 static inline unsigned long exception_epc(struct pt_regs *regs)
0061 {
0062     if (likely(!delay_slot(regs)))
0063         return regs->cp0_epc;
0064 
0065     if (get_isa16_mode(regs->cp0_epc))
0066         return __isa_exception_epc(regs);
0067 
0068     return regs->cp0_epc + 4;
0069 }
0070 
0071 #define BRANCH_LIKELY_TAKEN 0x0001
0072 
0073 static inline int compute_return_epc(struct pt_regs *regs)
0074 {
0075     if (get_isa16_mode(regs->cp0_epc)) {
0076         if (cpu_has_mmips)
0077             return __microMIPS_compute_return_epc(regs);
0078         if (cpu_has_mips16)
0079             return __MIPS16e_compute_return_epc(regs);
0080     } else if (!delay_slot(regs)) {
0081         regs->cp0_epc += 4;
0082         return 0;
0083     }
0084 
0085     return __compute_return_epc(regs);
0086 }
0087 
0088 static inline int MIPS16e_compute_return_epc(struct pt_regs *regs,
0089                          union mips16e_instruction *inst)
0090 {
0091     if (likely(!delay_slot(regs))) {
0092         if (inst->ri.opcode == MIPS16e_extend_op) {
0093             regs->cp0_epc += 4;
0094             return 0;
0095         }
0096         regs->cp0_epc += 2;
0097         return 0;
0098     }
0099 
0100     return __MIPS16e_compute_return_epc(regs);
0101 }
0102 
0103 #endif /* _ASM_BRANCH_H */