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
  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}
  41
  42static inline int delay_slot(struct pt_regs *regs)
  43{
  44        return regs->cp0_cause & CAUSEF_BD;
  45}
  46
  47static inline void clear_delay_slot(struct pt_regs *regs)
  48{
  49        regs->cp0_cause &= ~CAUSEF_BD;
  50}
  51
  52static inline void set_delay_slot(struct pt_regs *regs)
  53{
  54        regs->cp0_cause |= CAUSEF_BD;
  55}
  56
  57static inline unsigned long exception_epc(struct pt_regs *regs)
  58{
  59        if (likely(!delay_slot(regs)))
  60                return regs->cp0_epc;
  61
  62        if (get_isa16_mode(regs->cp0_epc))
  63                return __isa_exception_epc(regs);
  64
  65        return regs->cp0_epc + 4;
  66}
  67
  68#define BRANCH_LIKELY_TAKEN 0x0001
  69
  70static inline int compute_return_epc(struct pt_regs *regs)
  71{
  72        if (get_isa16_mode(regs->cp0_epc)) {
  73                if (cpu_has_mmips)
  74                        return __microMIPS_compute_return_epc(regs);
  75                if (cpu_has_mips16)
  76                        return __MIPS16e_compute_return_epc(regs);
  77                return regs->cp0_epc;
  78        }
  79
  80        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