133e53ae1SGuo Ren // SPDX-License-Identifier: GPL-2.0+
233e53ae1SGuo Ren 
333e53ae1SGuo Ren #include <linux/bitops.h>
433e53ae1SGuo Ren #include <linux/kernel.h>
533e53ae1SGuo Ren #include <linux/kprobes.h>
633e53ae1SGuo Ren 
733e53ae1SGuo Ren #include "decode-insn.h"
833e53ae1SGuo Ren #include "simulate-insn.h"
933e53ae1SGuo Ren 
csky_insn_reg_get_val(struct pt_regs * regs,unsigned long index,unsigned long * ptr)1033e53ae1SGuo Ren static inline bool csky_insn_reg_get_val(struct pt_regs *regs,
1133e53ae1SGuo Ren 					 unsigned long index,
1233e53ae1SGuo Ren 					 unsigned long *ptr)
1333e53ae1SGuo Ren {
1433e53ae1SGuo Ren 	if (index < 14)
1533e53ae1SGuo Ren 		*ptr = *(&regs->a0 + index);
1633e53ae1SGuo Ren 
1733e53ae1SGuo Ren 	if (index > 15 && index < 31)
1833e53ae1SGuo Ren 		*ptr = *(&regs->exregs[0] + index - 16);
1933e53ae1SGuo Ren 
2033e53ae1SGuo Ren 	switch (index) {
2133e53ae1SGuo Ren 	case 14:
2233e53ae1SGuo Ren 		*ptr = regs->usp;
2333e53ae1SGuo Ren 		break;
2433e53ae1SGuo Ren 	case 15:
2533e53ae1SGuo Ren 		*ptr = regs->lr;
2633e53ae1SGuo Ren 		break;
2733e53ae1SGuo Ren 	case 31:
2833e53ae1SGuo Ren 		*ptr = regs->tls;
2933e53ae1SGuo Ren 		break;
3033e53ae1SGuo Ren 	default:
3133e53ae1SGuo Ren 		goto fail;
3233e53ae1SGuo Ren 	}
3333e53ae1SGuo Ren 
3433e53ae1SGuo Ren 	return true;
3533e53ae1SGuo Ren fail:
3633e53ae1SGuo Ren 	return false;
3733e53ae1SGuo Ren }
3833e53ae1SGuo Ren 
csky_insn_reg_set_val(struct pt_regs * regs,unsigned long index,unsigned long val)3933e53ae1SGuo Ren static inline bool csky_insn_reg_set_val(struct pt_regs *regs,
4033e53ae1SGuo Ren 					 unsigned long index,
4133e53ae1SGuo Ren 					 unsigned long val)
4233e53ae1SGuo Ren {
4333e53ae1SGuo Ren 	if (index < 14)
4433e53ae1SGuo Ren 		*(&regs->a0 + index) = val;
4533e53ae1SGuo Ren 
4633e53ae1SGuo Ren 	if (index > 15 && index < 31)
4733e53ae1SGuo Ren 		*(&regs->exregs[0] + index - 16) = val;
4833e53ae1SGuo Ren 
4933e53ae1SGuo Ren 	switch (index) {
5033e53ae1SGuo Ren 	case 14:
5133e53ae1SGuo Ren 		regs->usp = val;
5233e53ae1SGuo Ren 		break;
5333e53ae1SGuo Ren 	case 15:
5433e53ae1SGuo Ren 		regs->lr = val;
5533e53ae1SGuo Ren 		break;
5633e53ae1SGuo Ren 	case 31:
5733e53ae1SGuo Ren 		regs->tls = val;
5833e53ae1SGuo Ren 		break;
5933e53ae1SGuo Ren 	default:
6033e53ae1SGuo Ren 		goto fail;
6133e53ae1SGuo Ren 	}
6233e53ae1SGuo Ren 
6333e53ae1SGuo Ren 	return true;
6433e53ae1SGuo Ren fail:
6533e53ae1SGuo Ren 	return false;
6633e53ae1SGuo Ren }
6733e53ae1SGuo Ren 
6833e53ae1SGuo Ren void __kprobes
simulate_br16(u32 opcode,long addr,struct pt_regs * regs)6933e53ae1SGuo Ren simulate_br16(u32 opcode, long addr, struct pt_regs *regs)
7033e53ae1SGuo Ren {
7133e53ae1SGuo Ren 	instruction_pointer_set(regs,
7233e53ae1SGuo Ren 		addr + sign_extend32((opcode & 0x3ff) << 1, 9));
7333e53ae1SGuo Ren }
7433e53ae1SGuo Ren 
7533e53ae1SGuo Ren void __kprobes
simulate_br32(u32 opcode,long addr,struct pt_regs * regs)7633e53ae1SGuo Ren simulate_br32(u32 opcode, long addr, struct pt_regs *regs)
7733e53ae1SGuo Ren {
7833e53ae1SGuo Ren 	instruction_pointer_set(regs,
7933e53ae1SGuo Ren 		addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
8033e53ae1SGuo Ren }
8133e53ae1SGuo Ren 
8233e53ae1SGuo Ren void __kprobes
simulate_bt16(u32 opcode,long addr,struct pt_regs * regs)8333e53ae1SGuo Ren simulate_bt16(u32 opcode, long addr, struct pt_regs *regs)
8433e53ae1SGuo Ren {
8533e53ae1SGuo Ren 	if (regs->sr & 1)
8633e53ae1SGuo Ren 		instruction_pointer_set(regs,
8733e53ae1SGuo Ren 			addr + sign_extend32((opcode & 0x3ff) << 1, 9));
8833e53ae1SGuo Ren 	else
8933e53ae1SGuo Ren 		instruction_pointer_set(regs, addr + 2);
9033e53ae1SGuo Ren }
9133e53ae1SGuo Ren 
9233e53ae1SGuo Ren void __kprobes
simulate_bt32(u32 opcode,long addr,struct pt_regs * regs)9333e53ae1SGuo Ren simulate_bt32(u32 opcode, long addr, struct pt_regs *regs)
9433e53ae1SGuo Ren {
9533e53ae1SGuo Ren 	if (regs->sr & 1)
9633e53ae1SGuo Ren 		instruction_pointer_set(regs,
9733e53ae1SGuo Ren 			addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
9833e53ae1SGuo Ren 	else
9933e53ae1SGuo Ren 		instruction_pointer_set(regs, addr + 4);
10033e53ae1SGuo Ren }
10133e53ae1SGuo Ren 
10233e53ae1SGuo Ren void __kprobes
simulate_bf16(u32 opcode,long addr,struct pt_regs * regs)10333e53ae1SGuo Ren simulate_bf16(u32 opcode, long addr, struct pt_regs *regs)
10433e53ae1SGuo Ren {
10533e53ae1SGuo Ren 	if (!(regs->sr & 1))
10633e53ae1SGuo Ren 		instruction_pointer_set(regs,
10733e53ae1SGuo Ren 			addr + sign_extend32((opcode & 0x3ff) << 1, 9));
10833e53ae1SGuo Ren 	else
10933e53ae1SGuo Ren 		instruction_pointer_set(regs, addr + 2);
11033e53ae1SGuo Ren }
11133e53ae1SGuo Ren 
11233e53ae1SGuo Ren void __kprobes
simulate_bf32(u32 opcode,long addr,struct pt_regs * regs)11333e53ae1SGuo Ren simulate_bf32(u32 opcode, long addr, struct pt_regs *regs)
11433e53ae1SGuo Ren {
11533e53ae1SGuo Ren 	if (!(regs->sr & 1))
11633e53ae1SGuo Ren 		instruction_pointer_set(regs,
11733e53ae1SGuo Ren 			addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
11833e53ae1SGuo Ren 	else
11933e53ae1SGuo Ren 		instruction_pointer_set(regs, addr + 4);
12033e53ae1SGuo Ren }
12133e53ae1SGuo Ren 
12233e53ae1SGuo Ren void __kprobes
simulate_jmp16(u32 opcode,long addr,struct pt_regs * regs)12333e53ae1SGuo Ren simulate_jmp16(u32 opcode, long addr, struct pt_regs *regs)
12433e53ae1SGuo Ren {
12533e53ae1SGuo Ren 	unsigned long tmp = (opcode >> 2) & 0xf;
12633e53ae1SGuo Ren 
12733e53ae1SGuo Ren 	csky_insn_reg_get_val(regs, tmp, &tmp);
12833e53ae1SGuo Ren 
12933e53ae1SGuo Ren 	instruction_pointer_set(regs, tmp & 0xfffffffe);
13033e53ae1SGuo Ren }
13133e53ae1SGuo Ren 
13233e53ae1SGuo Ren void __kprobes
simulate_jmp32(u32 opcode,long addr,struct pt_regs * regs)13333e53ae1SGuo Ren simulate_jmp32(u32 opcode, long addr, struct pt_regs *regs)
13433e53ae1SGuo Ren {
13533e53ae1SGuo Ren 	unsigned long tmp = opcode & 0x1f;
13633e53ae1SGuo Ren 
13733e53ae1SGuo Ren 	csky_insn_reg_get_val(regs, tmp, &tmp);
13833e53ae1SGuo Ren 
13933e53ae1SGuo Ren 	instruction_pointer_set(regs, tmp & 0xfffffffe);
14033e53ae1SGuo Ren }
14133e53ae1SGuo Ren 
14233e53ae1SGuo Ren void __kprobes
simulate_jsr16(u32 opcode,long addr,struct pt_regs * regs)14333e53ae1SGuo Ren simulate_jsr16(u32 opcode, long addr, struct pt_regs *regs)
14433e53ae1SGuo Ren {
14533e53ae1SGuo Ren 	unsigned long tmp = (opcode >> 2) & 0xf;
14633e53ae1SGuo Ren 
14733e53ae1SGuo Ren 	csky_insn_reg_get_val(regs, tmp, &tmp);
14833e53ae1SGuo Ren 
14933e53ae1SGuo Ren 	regs->lr = addr + 2;
15033e53ae1SGuo Ren 
15133e53ae1SGuo Ren 	instruction_pointer_set(regs, tmp & 0xfffffffe);
15233e53ae1SGuo Ren }
15333e53ae1SGuo Ren 
15433e53ae1SGuo Ren void __kprobes
simulate_jsr32(u32 opcode,long addr,struct pt_regs * regs)15533e53ae1SGuo Ren simulate_jsr32(u32 opcode, long addr, struct pt_regs *regs)
15633e53ae1SGuo Ren {
15733e53ae1SGuo Ren 	unsigned long tmp = opcode & 0x1f;
15833e53ae1SGuo Ren 
15933e53ae1SGuo Ren 	csky_insn_reg_get_val(regs, tmp, &tmp);
16033e53ae1SGuo Ren 
16133e53ae1SGuo Ren 	regs->lr = addr + 4;
16233e53ae1SGuo Ren 
16333e53ae1SGuo Ren 	instruction_pointer_set(regs, tmp & 0xfffffffe);
16433e53ae1SGuo Ren }
16533e53ae1SGuo Ren 
16633e53ae1SGuo Ren void __kprobes
simulate_lrw16(u32 opcode,long addr,struct pt_regs * regs)16733e53ae1SGuo Ren simulate_lrw16(u32 opcode, long addr, struct pt_regs *regs)
16833e53ae1SGuo Ren {
16933e53ae1SGuo Ren 	unsigned long val;
17033e53ae1SGuo Ren 	unsigned long tmp = (opcode & 0x300) >> 3;
17133e53ae1SGuo Ren 	unsigned long offset = ((opcode & 0x1f) | tmp) << 2;
17233e53ae1SGuo Ren 
17333e53ae1SGuo Ren 	tmp = (opcode & 0xe0) >> 5;
17433e53ae1SGuo Ren 
17533e53ae1SGuo Ren 	val = *(unsigned int *)(instruction_pointer(regs) + offset);
17633e53ae1SGuo Ren 
17733e53ae1SGuo Ren 	csky_insn_reg_set_val(regs, tmp, val);
17833e53ae1SGuo Ren }
17933e53ae1SGuo Ren 
18033e53ae1SGuo Ren void __kprobes
simulate_lrw32(u32 opcode,long addr,struct pt_regs * regs)18133e53ae1SGuo Ren simulate_lrw32(u32 opcode, long addr, struct pt_regs *regs)
18233e53ae1SGuo Ren {
18333e53ae1SGuo Ren 	unsigned long val;
18433e53ae1SGuo Ren 	unsigned long offset = (opcode & 0xffff0000) >> 14;
18533e53ae1SGuo Ren 	unsigned long tmp = opcode & 0x0000001f;
18633e53ae1SGuo Ren 
18733e53ae1SGuo Ren 	val = *(unsigned int *)
18833e53ae1SGuo Ren 		((instruction_pointer(regs) + offset) & 0xfffffffc);
18933e53ae1SGuo Ren 
19033e53ae1SGuo Ren 	csky_insn_reg_set_val(regs, tmp, val);
19133e53ae1SGuo Ren }
19233e53ae1SGuo Ren 
19333e53ae1SGuo Ren void __kprobes
simulate_pop16(u32 opcode,long addr,struct pt_regs * regs)19433e53ae1SGuo Ren simulate_pop16(u32 opcode, long addr, struct pt_regs *regs)
19533e53ae1SGuo Ren {
19633e53ae1SGuo Ren 	unsigned long *tmp = (unsigned long *)regs->usp;
19733e53ae1SGuo Ren 	int i;
19833e53ae1SGuo Ren 
19933e53ae1SGuo Ren 	for (i = 0; i < (opcode & 0xf); i++) {
20033e53ae1SGuo Ren 		csky_insn_reg_set_val(regs, i + 4, *tmp);
20133e53ae1SGuo Ren 		tmp += 1;
20233e53ae1SGuo Ren 	}
20333e53ae1SGuo Ren 
20433e53ae1SGuo Ren 	if (opcode & 0x10) {
20533e53ae1SGuo Ren 		csky_insn_reg_set_val(regs, 15, *tmp);
20633e53ae1SGuo Ren 		tmp += 1;
20733e53ae1SGuo Ren 	}
20833e53ae1SGuo Ren 
20933e53ae1SGuo Ren 	regs->usp = (unsigned long)tmp;
21033e53ae1SGuo Ren 
21133e53ae1SGuo Ren 	instruction_pointer_set(regs, regs->lr);
21233e53ae1SGuo Ren }
21333e53ae1SGuo Ren 
21433e53ae1SGuo Ren void __kprobes
simulate_pop32(u32 opcode,long addr,struct pt_regs * regs)21533e53ae1SGuo Ren simulate_pop32(u32 opcode, long addr, struct pt_regs *regs)
21633e53ae1SGuo Ren {
21733e53ae1SGuo Ren 	unsigned long *tmp = (unsigned long *)regs->usp;
21833e53ae1SGuo Ren 	int i;
21933e53ae1SGuo Ren 
22033e53ae1SGuo Ren 	for (i = 0; i < ((opcode & 0xf0000) >> 16); i++) {
22133e53ae1SGuo Ren 		csky_insn_reg_set_val(regs, i + 4, *tmp);
22233e53ae1SGuo Ren 		tmp += 1;
22333e53ae1SGuo Ren 	}
22433e53ae1SGuo Ren 
22533e53ae1SGuo Ren 	if (opcode & 0x100000) {
22633e53ae1SGuo Ren 		csky_insn_reg_set_val(regs, 15, *tmp);
22733e53ae1SGuo Ren 		tmp += 1;
22833e53ae1SGuo Ren 	}
22933e53ae1SGuo Ren 
23033e53ae1SGuo Ren 	for (i = 0; i < ((opcode & 0xe00000) >> 21); i++) {
23133e53ae1SGuo Ren 		csky_insn_reg_set_val(regs, i + 16, *tmp);
23233e53ae1SGuo Ren 		tmp += 1;
23333e53ae1SGuo Ren 	}
23433e53ae1SGuo Ren 
23533e53ae1SGuo Ren 	if (opcode & 0x1000000) {
23633e53ae1SGuo Ren 		csky_insn_reg_set_val(regs, 29, *tmp);
23733e53ae1SGuo Ren 		tmp += 1;
23833e53ae1SGuo Ren 	}
23933e53ae1SGuo Ren 
24033e53ae1SGuo Ren 	regs->usp = (unsigned long)tmp;
24133e53ae1SGuo Ren 
24233e53ae1SGuo Ren 	instruction_pointer_set(regs, regs->lr);
24333e53ae1SGuo Ren }
24433e53ae1SGuo Ren 
24533e53ae1SGuo Ren void __kprobes
simulate_bez32(u32 opcode,long addr,struct pt_regs * regs)24633e53ae1SGuo Ren simulate_bez32(u32 opcode, long addr, struct pt_regs *regs)
24733e53ae1SGuo Ren {
24833e53ae1SGuo Ren 	unsigned long tmp = opcode & 0x1f;
24933e53ae1SGuo Ren 
25033e53ae1SGuo Ren 	csky_insn_reg_get_val(regs, tmp, &tmp);
25133e53ae1SGuo Ren 
25233e53ae1SGuo Ren 	if (tmp == 0) {
25333e53ae1SGuo Ren 		instruction_pointer_set(regs,
25433e53ae1SGuo Ren 			addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
25533e53ae1SGuo Ren 	} else
25633e53ae1SGuo Ren 		instruction_pointer_set(regs, addr + 4);
25733e53ae1SGuo Ren }
25833e53ae1SGuo Ren 
25933e53ae1SGuo Ren void __kprobes
simulate_bnez32(u32 opcode,long addr,struct pt_regs * regs)26033e53ae1SGuo Ren simulate_bnez32(u32 opcode, long addr, struct pt_regs *regs)
26133e53ae1SGuo Ren {
26233e53ae1SGuo Ren 	unsigned long tmp = opcode & 0x1f;
26333e53ae1SGuo Ren 
26433e53ae1SGuo Ren 	csky_insn_reg_get_val(regs, tmp, &tmp);
26533e53ae1SGuo Ren 
26633e53ae1SGuo Ren 	if (tmp != 0) {
26733e53ae1SGuo Ren 		instruction_pointer_set(regs,
26833e53ae1SGuo Ren 			addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
26933e53ae1SGuo Ren 	} else
27033e53ae1SGuo Ren 		instruction_pointer_set(regs, addr + 4);
27133e53ae1SGuo Ren }
27233e53ae1SGuo Ren 
27333e53ae1SGuo Ren void __kprobes
simulate_bnezad32(u32 opcode,long addr,struct pt_regs * regs)27433e53ae1SGuo Ren simulate_bnezad32(u32 opcode, long addr, struct pt_regs *regs)
27533e53ae1SGuo Ren {
27633e53ae1SGuo Ren 	unsigned long tmp = opcode & 0x1f;
277*8dcbc611SGuo Ren 	long val;
27833e53ae1SGuo Ren 
279*8dcbc611SGuo Ren 	csky_insn_reg_get_val(regs, tmp, (unsigned long *)&val);
28033e53ae1SGuo Ren 
28133e53ae1SGuo Ren 	val -= 1;
28233e53ae1SGuo Ren 
28333e53ae1SGuo Ren 	if (val > 0) {
28433e53ae1SGuo Ren 		instruction_pointer_set(regs,
28533e53ae1SGuo Ren 			addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
28633e53ae1SGuo Ren 	} else
28733e53ae1SGuo Ren 		instruction_pointer_set(regs, addr + 4);
28833e53ae1SGuo Ren 
289*8dcbc611SGuo Ren 	csky_insn_reg_set_val(regs, tmp, (unsigned long)val);
29033e53ae1SGuo Ren }
29133e53ae1SGuo Ren 
29233e53ae1SGuo Ren void __kprobes
simulate_bhsz32(u32 opcode,long addr,struct pt_regs * regs)29333e53ae1SGuo Ren simulate_bhsz32(u32 opcode, long addr, struct pt_regs *regs)
29433e53ae1SGuo Ren {
29533e53ae1SGuo Ren 	unsigned long tmp = opcode & 0x1f;
29633e53ae1SGuo Ren 	unsigned long val;
29733e53ae1SGuo Ren 
29833e53ae1SGuo Ren 	csky_insn_reg_get_val(regs, tmp, &val);
29933e53ae1SGuo Ren 
300*8dcbc611SGuo Ren 	if ((long) val >= 0) {
30133e53ae1SGuo Ren 		instruction_pointer_set(regs,
30233e53ae1SGuo Ren 			addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
30333e53ae1SGuo Ren 	} else
30433e53ae1SGuo Ren 		instruction_pointer_set(regs, addr + 4);
30533e53ae1SGuo Ren }
30633e53ae1SGuo Ren 
30733e53ae1SGuo Ren void __kprobes
simulate_bhz32(u32 opcode,long addr,struct pt_regs * regs)30833e53ae1SGuo Ren simulate_bhz32(u32 opcode, long addr, struct pt_regs *regs)
30933e53ae1SGuo Ren {
31033e53ae1SGuo Ren 	unsigned long tmp = opcode & 0x1f;
31133e53ae1SGuo Ren 	unsigned long val;
31233e53ae1SGuo Ren 
31333e53ae1SGuo Ren 	csky_insn_reg_get_val(regs, tmp, &val);
31433e53ae1SGuo Ren 
315*8dcbc611SGuo Ren 	if ((long) val > 0) {
31633e53ae1SGuo Ren 		instruction_pointer_set(regs,
31733e53ae1SGuo Ren 			addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
31833e53ae1SGuo Ren 	} else
31933e53ae1SGuo Ren 		instruction_pointer_set(regs, addr + 4);
32033e53ae1SGuo Ren }
32133e53ae1SGuo Ren 
32233e53ae1SGuo Ren void __kprobes
simulate_blsz32(u32 opcode,long addr,struct pt_regs * regs)32333e53ae1SGuo Ren simulate_blsz32(u32 opcode, long addr, struct pt_regs *regs)
32433e53ae1SGuo Ren {
32533e53ae1SGuo Ren 	unsigned long tmp = opcode & 0x1f;
32633e53ae1SGuo Ren 	unsigned long val;
32733e53ae1SGuo Ren 
32833e53ae1SGuo Ren 	csky_insn_reg_get_val(regs, tmp, &val);
32933e53ae1SGuo Ren 
330*8dcbc611SGuo Ren 	if ((long) val <= 0) {
33133e53ae1SGuo Ren 		instruction_pointer_set(regs,
33233e53ae1SGuo Ren 			addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
33333e53ae1SGuo Ren 	} else
33433e53ae1SGuo Ren 		instruction_pointer_set(regs, addr + 4);
33533e53ae1SGuo Ren }
33633e53ae1SGuo Ren 
33733e53ae1SGuo Ren void __kprobes
simulate_blz32(u32 opcode,long addr,struct pt_regs * regs)33833e53ae1SGuo Ren simulate_blz32(u32 opcode, long addr, struct pt_regs *regs)
33933e53ae1SGuo Ren {
34033e53ae1SGuo Ren 	unsigned long tmp = opcode & 0x1f;
34133e53ae1SGuo Ren 	unsigned long val;
34233e53ae1SGuo Ren 
34333e53ae1SGuo Ren 	csky_insn_reg_get_val(regs, tmp, &val);
34433e53ae1SGuo Ren 
345*8dcbc611SGuo Ren 	if ((long) val < 0) {
34633e53ae1SGuo Ren 		instruction_pointer_set(regs,
34733e53ae1SGuo Ren 			addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
34833e53ae1SGuo Ren 	} else
34933e53ae1SGuo Ren 		instruction_pointer_set(regs, addr + 4);
35033e53ae1SGuo Ren }
35133e53ae1SGuo Ren 
35233e53ae1SGuo Ren void __kprobes
simulate_bsr32(u32 opcode,long addr,struct pt_regs * regs)35333e53ae1SGuo Ren simulate_bsr32(u32 opcode, long addr, struct pt_regs *regs)
35433e53ae1SGuo Ren {
35533e53ae1SGuo Ren 	unsigned long tmp;
35633e53ae1SGuo Ren 
35733e53ae1SGuo Ren 	tmp = (opcode & 0xffff) << 16;
35833e53ae1SGuo Ren 	tmp |= (opcode & 0xffff0000) >> 16;
35933e53ae1SGuo Ren 
36033e53ae1SGuo Ren 	instruction_pointer_set(regs,
36133e53ae1SGuo Ren 		addr + sign_extend32((tmp & 0x3ffffff) << 1, 15));
36233e53ae1SGuo Ren 
36333e53ae1SGuo Ren 	regs->lr = addr + 4;
36433e53ae1SGuo Ren }
36533e53ae1SGuo Ren 
36633e53ae1SGuo Ren void __kprobes
simulate_jmpi32(u32 opcode,long addr,struct pt_regs * regs)36733e53ae1SGuo Ren simulate_jmpi32(u32 opcode, long addr, struct pt_regs *regs)
36833e53ae1SGuo Ren {
36933e53ae1SGuo Ren 	unsigned long val;
37033e53ae1SGuo Ren 	unsigned long offset = ((opcode & 0xffff0000) >> 14);
37133e53ae1SGuo Ren 
37233e53ae1SGuo Ren 	val = *(unsigned int *)
37333e53ae1SGuo Ren 		((instruction_pointer(regs) + offset) & 0xfffffffc);
37433e53ae1SGuo Ren 
37533e53ae1SGuo Ren 	instruction_pointer_set(regs, val);
37633e53ae1SGuo Ren }
37733e53ae1SGuo Ren 
37833e53ae1SGuo Ren void __kprobes
simulate_jsri32(u32 opcode,long addr,struct pt_regs * regs)37933e53ae1SGuo Ren simulate_jsri32(u32 opcode, long addr, struct pt_regs *regs)
38033e53ae1SGuo Ren {
38133e53ae1SGuo Ren 	unsigned long val;
38233e53ae1SGuo Ren 	unsigned long offset = ((opcode & 0xffff0000) >> 14);
38333e53ae1SGuo Ren 
38433e53ae1SGuo Ren 	val = *(unsigned int *)
38533e53ae1SGuo Ren 		((instruction_pointer(regs) + offset) & 0xfffffffc);
38633e53ae1SGuo Ren 
38733e53ae1SGuo Ren 	regs->lr = addr + 4;
38833e53ae1SGuo Ren 
38933e53ae1SGuo Ren 	instruction_pointer_set(regs, val);
39033e53ae1SGuo Ren }
391