linux/arch/mips/include/asm/branch.h
<<
>>
Prefs
   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, 1997, 1998, 2001 by Ralf Baechle
   7 */
   8#ifndef _ASM_BRANCH_H
   9#define _ASM_BRANCH_H
  10
  11#include <asm/cpu-features.h>
  12#include <asm/mipsregs.h>
  13#include <asm/ptrace.h>
  14#include <asm/inst.h>
  15
  16extern int __isa_exception_epc(struct pt_regs *regs);
  17extern int __compute_return_epc(struct pt_regs *regs);
  18extern int __compute_return_epc_for_insn(struct pt_regs *regs,
  19                                         union mips_instruction insn);
  20extern int __microMIPS_compute_return_epc(struct pt_regs *regs);
  21extern int __MIPS16e_compute_return_epc(struct pt_regs *regs);
  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
  30int isBranchInstr(struct pt_regs *regs,
  31        struct mm_decoded_insn dec_insn, unsigned long *contpc);
  32
  33extern int __mm_isBranchInstr(struct pt_regs *regs,
  34        struct mm_decoded_insn dec_insn, unsigned long *contpc);
  35
  36static inline int mm_isBranchInstr(struct pt_regs *regs,
  37        struct mm_decoded_insn dec_insn, unsigned long *contpc)
  38{
  39        if (!cpu_has_mmips)
  40                return 0;
  41
  42        return __mm_isBranchInstr(regs, dec_insn, contpc);
  43}
  44
  45static inline int delay_slot(struct pt_regs *regs)
  46{
  47        return regs->cp0_cause & CAUSEF_BD;
  48}
  49
  50static inline void clear_delay_slot(struct pt_regs *regs)
  51{
  52        regs->cp0_cause &= ~CAUSEF_BD;
  53}
  54
  55static inline void set_delay_slot(struct pt_regs *regs)
  56{
  57        regs->cp0_cause |= CAUSEF_BD;
  58}
  59
  60static inline unsigned long exception_epc(struct pt_regs *regs)
  61{
  62        if (likely(!delay_slot(regs)))
  63                return regs->cp0_epc;
  64
  65        if (get_isa16_mode(regs->cp0_epc))
  66                return __isa_exception_epc(regs);
  67
  68        return regs->cp0_epc + 4;
  69}
  70
  71#define BRANCH_LIKELY_TAKEN 0x0001
  72
  73static inline int compute_return_epc(struct pt_regs *regs)
  74{
  75        if (get_isa16_mode(regs->cp0_epc)) {
  76                if (cpu_has_mmips)
  77                        return __microMIPS_compute_return_epc(regs);
  78                if (cpu_has_mips16)
  79                        return __MIPS16e_compute_return_epc(regs);
  80        } else if (!delay_slot(regs)) {
  81                regs->cp0_epc += 4;
  82                return 0;
  83        }
  84
  85        return __compute_return_epc(regs);
  86}
  87
  88static inline int MIPS16e_compute_return_epc(struct pt_regs *regs,
  89                                             union mips16e_instruction *inst)
  90{
  91        if (likely(!delay_slot(regs))) {
  92                if (inst->ri.opcode == MIPS16e_extend_op) {
  93                        regs->cp0_epc += 4;
  94                        return 0;
  95                }
  96                regs->cp0_epc += 2;
  97                return 0;
  98        }
  99
 100        return __MIPS16e_compute_return_epc(regs);
 101}
 102
 103#endif /* _ASM_BRANCH_H */
 104