Linux Audio

Check our new training course

In-person Linux kernel drivers training

Jun 16-20, 2025
Register
Loading...
  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	} else if (!delay_slot(regs)) {
 78		regs->cp0_epc += 4;
 79		return 0;
 80	}
 81
 82	return __compute_return_epc(regs);
 83}
 84
 85static inline int MIPS16e_compute_return_epc(struct pt_regs *regs,
 86					     union mips16e_instruction *inst)
 87{
 88	if (likely(!delay_slot(regs))) {
 89		if (inst->ri.opcode == MIPS16e_extend_op) {
 90			regs->cp0_epc += 4;
 91			return 0;
 92		}
 93		regs->cp0_epc += 2;
 94		return 0;
 95	}
 96
 97	return __MIPS16e_compute_return_epc(regs);
 98}
 99
100#endif /* _ASM_BRANCH_H */