kprobes-thumb.c revision b48354d3584e93284fba2ee99f6f9f44d18e4f83
12437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst/*
22437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * arch/arm/kernel/kprobes-thumb.c
32437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst *
42437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
52437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst *
62437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * This program is free software; you can redistribute it and/or modify
72437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * it under the terms of the GNU General Public License version 2 as
82437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * published by the Free Software Foundation.
92437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst */
102437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst
112437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst#include <linux/kernel.h>
122437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst#include <linux/kprobes.h>
132437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst
142437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst#include "kprobes.h"
152437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst
16eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst
17eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst/*
18eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst * True if current instruction is in an IT block.
19eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst */
20eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst#define in_it_block(cpsr)	((cpsr & 0x06000c00) != 0x00000000)
21eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst
22eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst/*
23eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst * Return the condition code to check for the currently executing instruction.
24eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst * This is in ITSTATE<7:4> which is in CPSR<15:12> but is only valid if
25eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst * in_it_block returns true.
26eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst */
27eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst#define current_cond(cpsr)	((cpsr >> 12) & 0xf)
28eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst
29a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst/*
30a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst * Return the PC value for a probe in thumb code.
31a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst * This is the address of the probed instruction plus 4.
32a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst * We subtract one because the address will have bit zero set to indicate
33a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst * a pointer to thumb code.
34a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst */
35a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurststatic inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p)
36a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst{
37a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst	return (unsigned long)p->addr - 1 + 4;
38a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst}
39a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst
40eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurststatic enum kprobe_insn __kprobes
41eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurstt32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
42eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst{
43eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi);
44eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst
45eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	/* Fixup modified instruction to have halfwords in correct order...*/
46eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	insn = asi->insn[0];
47eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	((u16 *)asi->insn)[0] = insn >> 16;
48eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	((u16 *)asi->insn)[1] = insn & 0xffff;
49eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst
50eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	return ret;
51eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst}
52eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst
53b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurststatic void __kprobes
54b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurstt32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
55b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst{
56b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	kprobe_opcode_t insn = p->opcode;
57b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	unsigned long pc = thumb_probe_pc(p) & ~3;
58b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	int rt1 = (insn >> 12) & 0xf;
59b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	int rt2 = (insn >> 8) & 0xf;
60b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	int rn = (insn >> 16) & 0xf;
61b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst
62b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	register unsigned long rt1v asm("r0") = regs->uregs[rt1];
63b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	register unsigned long rt2v asm("r1") = regs->uregs[rt2];
64b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	register unsigned long rnv asm("r2") = (rn == 15) ? pc
65b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst							  : regs->uregs[rn];
66b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst
67b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	__asm__ __volatile__ (
68b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst		"blx    %[fn]"
69b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst		: "=r" (rt1v), "=r" (rt2v), "=r" (rnv)
70b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst		: "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (p->ainsn.insn_fn)
71b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst		: "lr", "memory", "cc"
72b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	);
73b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst
74b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	if (rn != 15)
75b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst		regs->uregs[rn] = rnv; /* Writeback base register */
76b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	regs->uregs[rt1] = rt1v;
77b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	regs->uregs[rt2] = rt2v;
78b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst}
79b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst
80eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurststatic const union decode_item t32_table_1110_100x_x0xx[] = {
81eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	/* Load/store multiple instructions */
82eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst
83eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	/* Rn is PC		1110 100x x0xx 1111 xxxx xxxx xxxx xxxx */
84eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	DECODE_REJECT	(0xfe4f0000, 0xe80f0000),
85eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst
86eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	/* SRS			1110 1000 00x0 xxxx xxxx xxxx xxxx xxxx */
87eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	/* RFE			1110 1000 00x1 xxxx xxxx xxxx xxxx xxxx */
88eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	DECODE_REJECT	(0xffc00000, 0xe8000000),
89eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	/* SRS			1110 1001 10x0 xxxx xxxx xxxx xxxx xxxx */
90eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	/* RFE			1110 1001 10x1 xxxx xxxx xxxx xxxx xxxx */
91eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	DECODE_REJECT	(0xffc00000, 0xe9800000),
92eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst
93eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	/* STM Rn, {...pc}	1110 100x x0x0 xxxx 1xxx xxxx xxxx xxxx */
94eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	DECODE_REJECT	(0xfe508000, 0xe8008000),
95eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	/* LDM Rn, {...lr,pc}	1110 100x x0x1 xxxx 11xx xxxx xxxx xxxx */
96eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	DECODE_REJECT	(0xfe50c000, 0xe810c000),
97eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	/* LDM/STM Rn, {...sp}	1110 100x x0xx xxxx xx1x xxxx xxxx xxxx */
98eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	DECODE_REJECT	(0xfe402000, 0xe8002000),
99eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst
100eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	/* STMIA		1110 1000 10x0 xxxx xxxx xxxx xxxx xxxx */
101eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	/* LDMIA		1110 1000 10x1 xxxx xxxx xxxx xxxx xxxx */
102eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	/* STMDB		1110 1001 00x0 xxxx xxxx xxxx xxxx xxxx */
103eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	/* LDMDB		1110 1001 00x1 xxxx xxxx xxxx xxxx xxxx */
104eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	DECODE_CUSTOM	(0xfe400000, 0xe8000000, t32_decode_ldmstm),
105eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst
106eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	DECODE_END
107eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst};
108eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst
109b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurststatic const union decode_item t32_table_1110_100x_x1xx[] = {
110b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	/* Load/store dual, load/store exclusive, table branch */
111b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst
112b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	/* STRD (immediate)	1110 1000 x110 xxxx xxxx xxxx xxxx xxxx */
113b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	/* LDRD (immediate)	1110 1000 x111 xxxx xxxx xxxx xxxx xxxx */
114b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	DECODE_OR	(0xff600000, 0xe8600000),
115b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	/* STRD (immediate)	1110 1001 x1x0 xxxx xxxx xxxx xxxx xxxx */
116b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	/* LDRD (immediate)	1110 1001 x1x1 xxxx xxxx xxxx xxxx xxxx */
117b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	DECODE_EMULATEX	(0xff400000, 0xe9400000, t32_emulate_ldrdstrd,
118b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst						 REGS(NOPCWB, NOSPPC, NOSPPC, 0, 0)),
119b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst
120b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	/* STREX		1110 1000 0100 xxxx xxxx xxxx xxxx xxxx */
121b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	/* LDREX		1110 1000 0101 xxxx xxxx xxxx xxxx xxxx */
122b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	/* STREXB		1110 1000 1100 xxxx xxxx xxxx 0100 xxxx */
123b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	/* STREXH		1110 1000 1100 xxxx xxxx xxxx 0101 xxxx */
124b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	/* STREXD		1110 1000 1100 xxxx xxxx xxxx 0111 xxxx */
125b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	/* LDREXB		1110 1000 1101 xxxx xxxx xxxx 0100 xxxx */
126b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	/* LDREXH		1110 1000 1101 xxxx xxxx xxxx 0101 xxxx */
127b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	/* LDREXD		1110 1000 1101 xxxx xxxx xxxx 0111 xxxx */
128b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	/* And unallocated instructions...				*/
129b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	DECODE_END
130b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst};
131b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst
132f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurststatic const union decode_item t32_table_1111_0xxx___1[] = {
133f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst	/* Branches and miscellaneous control				*/
134f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst
135f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst	/* YIELD		1111 0011 1010 xxxx 10x0 x000 0000 0001 */
136f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst	DECODE_OR	(0xfff0d7ff, 0xf3a08001),
137f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst	/* SEV			1111 0011 1010 xxxx 10x0 x000 0000 0100 */
138f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst	DECODE_EMULATE	(0xfff0d7ff, 0xf3a08004, kprobe_emulate_none),
139f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst	/* NOP			1111 0011 1010 xxxx 10x0 x000 0000 0000 */
140f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst	/* WFE			1111 0011 1010 xxxx 10x0 x000 0000 0010 */
141f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst	/* WFI			1111 0011 1010 xxxx 10x0 x000 0000 0011 */
142f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst	DECODE_SIMULATE	(0xfff0d7fc, 0xf3a08000, kprobe_simulate_nop),
143f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst
144f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst	DECODE_END
145f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst};
146f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst
147f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurstconst union decode_item kprobe_decode_thumb32_table[] = {
148f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst
149f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst	/*
150eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	 * Load/store multiple instructions
151eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	 *			1110 100x x0xx xxxx xxxx xxxx xxxx xxxx
152eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	 */
153eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	DECODE_TABLE	(0xfe400000, 0xe8000000, t32_table_1110_100x_x0xx),
154eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst
155eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst	/*
156b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	 * Load/store dual, load/store exclusive, table branch
157b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	 *			1110 100x x1xx xxxx xxxx xxxx xxxx xxxx
158b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	 */
159b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	DECODE_TABLE	(0xfe400000, 0xe8400000, t32_table_1110_100x_x1xx),
160b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst
161b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst	/*
162f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst	 * Branches and miscellaneous control
163f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst	 *			1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx
164f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst	 */
165f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst	DECODE_TABLE	(0xf8008000, 0xf0008000, t32_table_1111_0xxx___1),
166f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst
167f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst	DECODE_END
168f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst};
169f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst
170a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurststatic void __kprobes
171a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurstt16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs)
172a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst{
173a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst	kprobe_opcode_t insn = p->opcode;
174a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst	unsigned long pc = thumb_probe_pc(p);
175a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst	int rm = (insn >> 3) & 0xf;
176a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst	unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm];
177a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst
178a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst	if (insn & (1 << 7)) /* BLX ? */
179a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst		regs->ARM_lr = (unsigned long)p->addr + 2;
180a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst
181a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst	bx_write_pc(rmv, regs);
182a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst}
183a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst
184f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurststatic void __kprobes
185f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurstt16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
186f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst{
187f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	kprobe_opcode_t insn = p->opcode;
188f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	unsigned long* base = (unsigned long *)(thumb_probe_pc(p) & ~3);
189f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	long index = insn & 0xff;
190f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	int rt = (insn >> 8) & 0x7;
191f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	regs->uregs[rt] = base[index];
192f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst}
193f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst
194f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurststatic void __kprobes
195f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurstt16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs)
196f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst{
197f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	kprobe_opcode_t insn = p->opcode;
198f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	unsigned long* base = (unsigned long *)regs->ARM_sp;
199f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	long index = insn & 0xff;
200f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	int rt = (insn >> 8) & 0x7;
201f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	if (insn & 0x800) /* LDR */
202f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst		regs->uregs[rt] = base[index];
203f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	else /* STR */
204f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst		base[index] = regs->uregs[rt];
205f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst}
206f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst
2072f335829040cb16d0640e87121bef208894d4934Jon Medhurststatic void __kprobes
2082f335829040cb16d0640e87121bef208894d4934Jon Medhurstt16_simulate_reladr(struct kprobe *p, struct pt_regs *regs)
2092f335829040cb16d0640e87121bef208894d4934Jon Medhurst{
2102f335829040cb16d0640e87121bef208894d4934Jon Medhurst	kprobe_opcode_t insn = p->opcode;
2112f335829040cb16d0640e87121bef208894d4934Jon Medhurst	unsigned long base = (insn & 0x800) ? regs->ARM_sp
2122f335829040cb16d0640e87121bef208894d4934Jon Medhurst					    : (thumb_probe_pc(p) & ~3);
2132f335829040cb16d0640e87121bef208894d4934Jon Medhurst	long offset = insn & 0xff;
2142f335829040cb16d0640e87121bef208894d4934Jon Medhurst	int rt = (insn >> 8) & 0x7;
2152f335829040cb16d0640e87121bef208894d4934Jon Medhurst	regs->uregs[rt] = base + offset * 4;
2162f335829040cb16d0640e87121bef208894d4934Jon Medhurst}
2172f335829040cb16d0640e87121bef208894d4934Jon Medhurst
2182f335829040cb16d0640e87121bef208894d4934Jon Medhurststatic void __kprobes
2192f335829040cb16d0640e87121bef208894d4934Jon Medhurstt16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs)
2202f335829040cb16d0640e87121bef208894d4934Jon Medhurst{
2212f335829040cb16d0640e87121bef208894d4934Jon Medhurst	kprobe_opcode_t insn = p->opcode;
2222f335829040cb16d0640e87121bef208894d4934Jon Medhurst	long imm = insn & 0x7f;
2232f335829040cb16d0640e87121bef208894d4934Jon Medhurst	if (insn & 0x80) /* SUB */
2242f335829040cb16d0640e87121bef208894d4934Jon Medhurst		regs->ARM_sp -= imm * 4;
2252f335829040cb16d0640e87121bef208894d4934Jon Medhurst	else /* ADD */
2262f335829040cb16d0640e87121bef208894d4934Jon Medhurst		regs->ARM_sp += imm * 4;
2272f335829040cb16d0640e87121bef208894d4934Jon Medhurst}
2282f335829040cb16d0640e87121bef208894d4934Jon Medhurst
22932818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurststatic void __kprobes
23032818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurstt16_simulate_cbz(struct kprobe *p, struct pt_regs *regs)
23132818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst{
23232818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	kprobe_opcode_t insn = p->opcode;
23332818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	int rn = insn & 0x7;
23432818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	kprobe_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn;
23532818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	if (nonzero & 0x800) {
23632818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst		long i = insn & 0x200;
23732818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst		long imm5 = insn & 0xf8;
23832818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst		unsigned long pc = thumb_probe_pc(p);
23932818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst		regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2);
24032818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	}
24132818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst}
24232818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst
2435b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurststatic void __kprobes
2445b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurstt16_simulate_it(struct kprobe *p, struct pt_regs *regs)
2455b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst{
2465b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	/*
2475b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	 * The 8 IT state bits are split into two parts in CPSR:
2485b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	 *	ITSTATE<1:0> are in CPSR<26:25>
2495b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	 *	ITSTATE<7:2> are in CPSR<15:10>
2505b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	 * The new IT state is in the lower byte of insn.
2515b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	 */
2525b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	kprobe_opcode_t insn = p->opcode;
2535b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	unsigned long cpsr = regs->ARM_cpsr;
2545b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	cpsr &= ~PSR_IT_MASK;
2555b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	cpsr |= (insn & 0xfc) << 8;
2565b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	cpsr |= (insn & 0x03) << 25;
2575b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	regs->ARM_cpsr = cpsr;
2585b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst}
2595b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst
2605b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurststatic void __kprobes
2615b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurstt16_singlestep_it(struct kprobe *p, struct pt_regs *regs)
2625b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst{
2635b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	regs->ARM_pc += 2;
2645b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	t16_simulate_it(p, regs);
2655b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst}
2665b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst
2675b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurststatic enum kprobe_insn __kprobes
2685b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurstt16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi)
2695b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst{
2705b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	asi->insn_singlestep = t16_singlestep_it;
2715b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	return INSN_GOOD_NO_SLOT;
2725b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst}
2735b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst
274396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurststatic void __kprobes
275396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurstt16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
276396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst{
277396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	kprobe_opcode_t insn = p->opcode;
278396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	unsigned long pc = thumb_probe_pc(p);
279396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	long offset = insn & 0x7f;
280396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	offset -= insn & 0x80; /* Apply sign bit */
281396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	regs->ARM_pc = pc + (offset * 2);
282396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst}
283396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst
284396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurststatic enum kprobe_insn __kprobes
285396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurstt16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi)
286396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst{
287396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	int cc = (insn >> 8) & 0xf;
288396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	asi->insn_check_cc = kprobe_condition_checks[cc];
289396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	asi->insn_handler = t16_simulate_cond_branch;
290396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	return INSN_GOOD_NO_SLOT;
291396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst}
292396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst
293396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurststatic void __kprobes
294396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurstt16_simulate_branch(struct kprobe *p, struct pt_regs *regs)
295396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst{
296396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	kprobe_opcode_t insn = p->opcode;
297396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	unsigned long pc = thumb_probe_pc(p);
298396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	long offset = insn & 0x3ff;
299396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	offset -= insn & 0x400; /* Apply sign bit */
300396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	regs->ARM_pc = pc + (offset * 2);
301396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst}
302396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst
30302d194f64772aee91e7319ca033905b0bafee04cJon Medhurststatic unsigned long __kprobes
30402d194f64772aee91e7319ca033905b0bafee04cJon Medhurstt16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
30502d194f64772aee91e7319ca033905b0bafee04cJon Medhurst{
30602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	unsigned long oldcpsr = regs->ARM_cpsr;
30702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	unsigned long newcpsr;
30802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst
30902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	__asm__ __volatile__ (
31002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst		"msr	cpsr_fs, %[oldcpsr]	\n\t"
31102d194f64772aee91e7319ca033905b0bafee04cJon Medhurst		"ldmia	%[regs], {r0-r7}	\n\t"
31202d194f64772aee91e7319ca033905b0bafee04cJon Medhurst		"blx	%[fn]			\n\t"
31302d194f64772aee91e7319ca033905b0bafee04cJon Medhurst		"stmia	%[regs], {r0-r7}	\n\t"
31402d194f64772aee91e7319ca033905b0bafee04cJon Medhurst		"mrs	%[newcpsr], cpsr	\n\t"
31502d194f64772aee91e7319ca033905b0bafee04cJon Medhurst		: [newcpsr] "=r" (newcpsr)
31602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst		: [oldcpsr] "r" (oldcpsr), [regs] "r" (regs),
31702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst		  [fn] "r" (p->ainsn.insn_fn)
31802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst		: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
31902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst		  "lr", "memory", "cc"
32002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst		);
32102d194f64772aee91e7319ca033905b0bafee04cJon Medhurst
32202d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK);
32302d194f64772aee91e7319ca033905b0bafee04cJon Medhurst}
32402d194f64772aee91e7319ca033905b0bafee04cJon Medhurst
32502d194f64772aee91e7319ca033905b0bafee04cJon Medhurststatic void __kprobes
32602d194f64772aee91e7319ca033905b0bafee04cJon Medhurstt16_emulate_loregs_rwflags(struct kprobe *p, struct pt_regs *regs)
32702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst{
32802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	regs->ARM_cpsr = t16_emulate_loregs(p, regs);
32902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst}
33002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst
33102d194f64772aee91e7319ca033905b0bafee04cJon Medhurststatic void __kprobes
33202d194f64772aee91e7319ca033905b0bafee04cJon Medhurstt16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs)
33302d194f64772aee91e7319ca033905b0bafee04cJon Medhurst{
33402d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	unsigned long cpsr = t16_emulate_loregs(p, regs);
33502d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	if (!in_it_block(cpsr))
33602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst		regs->ARM_cpsr = cpsr;
33702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst}
33802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst
3393b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurststatic void __kprobes
3403b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurstt16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs)
3413b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst{
3423b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	kprobe_opcode_t insn = p->opcode;
3433b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	unsigned long pc = thumb_probe_pc(p);
3443b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	int rdn = (insn & 0x7) | ((insn & 0x80) >> 4);
3453b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	int rm = (insn >> 3) & 0xf;
3463b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst
3473b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	register unsigned long rdnv asm("r1");
3483b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	register unsigned long rmv asm("r0");
3493b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	unsigned long cpsr = regs->ARM_cpsr;
3503b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst
3513b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	rdnv = (rdn == 15) ? pc : regs->uregs[rdn];
3523b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	rmv = (rm == 15) ? pc : regs->uregs[rm];
3533b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst
3543b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	__asm__ __volatile__ (
3553b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst		"msr	cpsr_fs, %[cpsr]	\n\t"
3563b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst		"blx    %[fn]			\n\t"
3573b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst		"mrs	%[cpsr], cpsr		\n\t"
3583b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst		: "=r" (rdnv), [cpsr] "=r" (cpsr)
3593b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst		: "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
3603b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst		: "lr", "memory", "cc"
3613b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	);
3623b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst
3633b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	if (rdn == 15)
3643b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst		rdnv &= ~1;
3653b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst
3663b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	regs->uregs[rdn] = rdnv;
3673b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
3683b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst}
3693b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst
3703b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurststatic enum kprobe_insn __kprobes
3713b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurstt16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi)
3723b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst{
3733b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	insn &= ~0x00ff;
3743b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */
3753b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	((u16 *)asi->insn)[0] = insn;
3763b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	asi->insn_handler = t16_emulate_hiregs;
3773b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	return INSN_GOOD;
3783b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst}
3793b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst
380fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurststatic void __kprobes
381fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurstt16_emulate_push(struct kprobe *p, struct pt_regs *regs)
382fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst{
383fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	__asm__ __volatile__ (
384fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		"ldr	r9, [%[regs], #13*4]	\n\t"
385fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		"ldr	r8, [%[regs], #14*4]	\n\t"
386fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		"ldmia	%[regs], {r0-r7}	\n\t"
387fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		"blx	%[fn]			\n\t"
388fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		"str	r9, [%[regs], #13*4]	\n\t"
389fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		:
390fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		: [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
391fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
392fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		  "lr", "memory", "cc"
393fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		);
394fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst}
395fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst
396fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurststatic enum kprobe_insn __kprobes
397fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurstt16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi)
398fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst{
399fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	/*
400fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	 * To simulate a PUSH we use a Thumb-2 "STMDB R9!, {registers}"
401fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	 * and call it with R9=SP and LR in the register list represented
402fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	 * by R8.
403fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	 */
404fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	((u16 *)asi->insn)[0] = 0xe929;		/* 1st half STMDB R9!,{} */
405fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	((u16 *)asi->insn)[1] = insn & 0x1ff;	/* 2nd half (register list) */
406fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	asi->insn_handler = t16_emulate_push;
407fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	return INSN_GOOD;
408fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst}
409fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst
410fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurststatic void __kprobes
411fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurstt16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs)
412fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst{
413fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	__asm__ __volatile__ (
414fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		"ldr	r9, [%[regs], #13*4]	\n\t"
415fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		"ldmia	%[regs], {r0-r7}	\n\t"
416fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		"blx	%[fn]			\n\t"
417fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		"stmia	%[regs], {r0-r7}	\n\t"
418fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		"str	r9, [%[regs], #13*4]	\n\t"
419fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		:
420fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		: [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
421fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
422fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		  "lr", "memory", "cc"
423fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		);
424fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst}
425fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst
426fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurststatic void __kprobes
427fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurstt16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs)
428fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst{
429fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	register unsigned long pc asm("r8");
430fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst
431fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	__asm__ __volatile__ (
432fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		"ldr	r9, [%[regs], #13*4]	\n\t"
433fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		"ldmia	%[regs], {r0-r7}	\n\t"
434fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		"blx	%[fn]			\n\t"
435fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		"stmia	%[regs], {r0-r7}	\n\t"
436fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		"str	r9, [%[regs], #13*4]	\n\t"
437fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		: "=r" (pc)
438fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		: [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
439fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
440fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		  "lr", "memory", "cc"
441fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst		);
442fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst
443fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	bx_write_pc(pc, regs);
444fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst}
445fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst
446fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurststatic enum kprobe_insn __kprobes
447fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurstt16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi)
448fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst{
449fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	/*
450fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	 * To simulate a POP we use a Thumb-2 "LDMDB R9!, {registers}"
451fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	 * and call it with R9=SP and PC in the register list represented
452fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	 * by R8.
453fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	 */
454fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	((u16 *)asi->insn)[0] = 0xe8b9;		/* 1st half LDMIA R9!,{} */
455fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	((u16 *)asi->insn)[1] = insn & 0x1ff;	/* 2nd half (register list) */
456fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc
457fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst					 : t16_emulate_pop_nopc;
458fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	return INSN_GOOD;
459fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst}
460fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst
4613f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurststatic const union decode_item t16_table_1011[] = {
4623f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	/* Miscellaneous 16-bit instructions		    */
4633f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst
4642f335829040cb16d0640e87121bef208894d4934Jon Medhurst	/* ADD (SP plus immediate)	1011 0000 0xxx xxxx */
4652f335829040cb16d0640e87121bef208894d4934Jon Medhurst	/* SUB (SP minus immediate)	1011 0000 1xxx xxxx */
4662f335829040cb16d0640e87121bef208894d4934Jon Medhurst	DECODE_SIMULATE	(0xff00, 0xb000, t16_simulate_add_sp_imm),
4672f335829040cb16d0640e87121bef208894d4934Jon Medhurst
46832818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	/* CBZ				1011 00x1 xxxx xxxx */
46932818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	/* CBNZ				1011 10x1 xxxx xxxx */
47032818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	DECODE_SIMULATE	(0xf500, 0xb100, t16_simulate_cbz),
47132818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst
47232818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	/* SXTH				1011 0010 00xx xxxx */
47332818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	/* SXTB				1011 0010 01xx xxxx */
47432818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	/* UXTH				1011 0010 10xx xxxx */
47532818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	/* UXTB				1011 0010 11xx xxxx */
47632818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	/* REV				1011 1010 00xx xxxx */
47732818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	/* REV16			1011 1010 01xx xxxx */
47832818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	/* ???				1011 1010 10xx xxxx */
47932818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	/* REVSH			1011 1010 11xx xxxx */
48032818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	DECODE_REJECT	(0xffc0, 0xba80),
48132818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst	DECODE_EMULATE	(0xf500, 0xb000, t16_emulate_loregs_rwflags),
48232818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst
483fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	/* PUSH				1011 010x xxxx xxxx */
484fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	DECODE_CUSTOM	(0xfe00, 0xb400, t16_decode_push),
485fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	/* POP				1011 110x xxxx xxxx */
486fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst	DECODE_CUSTOM	(0xfe00, 0xbc00, t16_decode_pop),
487fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst
4883f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	/*
4893f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	 * If-Then, and hints
4903f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	 *				1011 1111 xxxx xxxx
4913f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	 */
4923f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst
4933f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	/* YIELD			1011 1111 0001 0000 */
4943f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	DECODE_OR	(0xffff, 0xbf10),
4953f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	/* SEV				1011 1111 0100 0000 */
4963f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	DECODE_EMULATE	(0xffff, 0xbf40, kprobe_emulate_none),
4973f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	/* NOP				1011 1111 0000 0000 */
4983f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	/* WFE				1011 1111 0010 0000 */
4993f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	/* WFI				1011 1111 0011 0000 */
5003f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	DECODE_SIMULATE	(0xffcf, 0xbf00, kprobe_simulate_nop),
5013f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	/* Unassigned hints		1011 1111 xxxx 0000 */
5023f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	DECODE_REJECT	(0xff0f, 0xbf00),
5035b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	/* IT				1011 1111 xxxx xxxx */
5045b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst	DECODE_CUSTOM	(0xff00, 0xbf00, t16_decode_it),
5053f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst
5060a188ccb5eceb58101fcc11b3ec2d860ccbf92a3Jon Medhurst	/* SETEND			1011 0110 010x xxxx */
5070a188ccb5eceb58101fcc11b3ec2d860ccbf92a3Jon Medhurst	/* CPS				1011 0110 011x xxxx */
5080a188ccb5eceb58101fcc11b3ec2d860ccbf92a3Jon Medhurst	/* BKPT				1011 1110 xxxx xxxx */
5090a188ccb5eceb58101fcc11b3ec2d860ccbf92a3Jon Medhurst	/* And unallocated instructions...		    */
5103f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	DECODE_END
5113f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst};
5123f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst
5133f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurstconst union decode_item kprobe_decode_thumb16_table[] = {
5143f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst
5153f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	/*
51602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	 * Shift (immediate), add, subtract, move, and compare
51702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	 *				00xx xxxx xxxx xxxx
51802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	 */
51902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst
52002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* CMP (immediate)		0010 1xxx xxxx xxxx */
52102d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	DECODE_EMULATE	(0xf800, 0x2800, t16_emulate_loregs_rwflags),
52202d194f64772aee91e7319ca033905b0bafee04cJon Medhurst
52302d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* ADD (register)		0001 100x xxxx xxxx */
52402d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* SUB (register)		0001 101x xxxx xxxx */
52502d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* LSL (immediate)		0000 0xxx xxxx xxxx */
52602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* LSR (immediate)		0000 1xxx xxxx xxxx */
52702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* ASR (immediate)		0001 0xxx xxxx xxxx */
52802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* ADD (immediate, Thumb)	0001 110x xxxx xxxx */
52902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* SUB (immediate, Thumb)	0001 111x xxxx xxxx */
53002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* MOV (immediate)		0010 0xxx xxxx xxxx */
53102d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* ADD (immediate, Thumb)	0011 0xxx xxxx xxxx */
53202d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* SUB (immediate, Thumb)	0011 1xxx xxxx xxxx */
53302d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	DECODE_EMULATE	(0xc000, 0x0000, t16_emulate_loregs_noitrwflags),
53402d194f64772aee91e7319ca033905b0bafee04cJon Medhurst
53502d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/*
53602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	 * 16-bit Thumb data-processing instructions
53702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	 *				0100 00xx xxxx xxxx
53802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	 */
53902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst
54002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* TST (register)		0100 0010 00xx xxxx */
54102d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	DECODE_EMULATE	(0xffc0, 0x4200, t16_emulate_loregs_rwflags),
54202d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* CMP (register)		0100 0010 10xx xxxx */
54302d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* CMN (register)		0100 0010 11xx xxxx */
54402d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	DECODE_EMULATE	(0xff80, 0x4280, t16_emulate_loregs_rwflags),
54502d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* AND (register)		0100 0000 00xx xxxx */
54602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* EOR (register)		0100 0000 01xx xxxx */
54702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* LSL (register)		0100 0000 10xx xxxx */
54802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* LSR (register)		0100 0000 11xx xxxx */
54902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* ASR (register)		0100 0001 00xx xxxx */
55002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* ADC (register)		0100 0001 01xx xxxx */
55102d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* SBC (register)		0100 0001 10xx xxxx */
55202d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* ROR (register)		0100 0001 11xx xxxx */
55302d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* RSB (immediate)		0100 0010 01xx xxxx */
55402d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* ORR (register)		0100 0011 00xx xxxx */
55502d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* MUL				0100 0011 00xx xxxx */
55602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* BIC (register)		0100 0011 10xx xxxx */
55702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/* MVN (register)		0100 0011 10xx xxxx */
55802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	DECODE_EMULATE	(0xfc00, 0x4000, t16_emulate_loregs_noitrwflags),
55902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst
56002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst	/*
561a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst	 * Special data instructions and branch and exchange
562a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst	 *				0100 01xx xxxx xxxx
563a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst	 */
564a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst
565a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst	/* BLX pc			0100 0111 1111 1xxx */
566a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst	DECODE_REJECT	(0xfff8, 0x47f8),
567a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst
568a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst	/* BX (register)		0100 0111 0xxx xxxx */
569a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst	/* BLX (register)		0100 0111 1xxx xxxx */
570a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst	DECODE_SIMULATE (0xff00, 0x4700, t16_simulate_bxblx),
571a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst
5723b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	/* ADD pc, pc			0100 0100 1111 1111 */
5733b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	DECODE_REJECT	(0xffff, 0x44ff),
5743b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst
5753b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	/* ADD (register)		0100 0100 xxxx xxxx */
5763b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	/* CMP (register)		0100 0101 xxxx xxxx */
5773b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	/* MOV (register)		0100 0110 xxxx xxxx */
5783b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst	DECODE_CUSTOM	(0xfc00, 0x4400, t16_decode_hiregs),
5793b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst
580a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst	/*
581f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	 * Load from Literal Pool
582f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	 * LDR (literal)		0100 1xxx xxxx xxxx
583f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	 */
584f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	DECODE_SIMULATE	(0xf800, 0x4800, t16_simulate_ldr_literal),
585f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst
586f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/*
587f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	 * 16-bit Thumb Load/store instructions
588f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	 *				0101 xxxx xxxx xxxx
589f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	 *				011x xxxx xxxx xxxx
590f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	 *				100x xxxx xxxx xxxx
591f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	 */
592f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst
593f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* STR (register)		0101 000x xxxx xxxx */
594f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* STRH (register)		0101 001x xxxx xxxx */
595f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* STRB (register)		0101 010x xxxx xxxx */
596f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* LDRSB (register)		0101 011x xxxx xxxx */
597f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* LDR (register)		0101 100x xxxx xxxx */
598f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* LDRH (register)		0101 101x xxxx xxxx */
599f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* LDRB (register)		0101 110x xxxx xxxx */
600f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* LDRSH (register)		0101 111x xxxx xxxx */
601f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* STR (immediate, Thumb)	0110 0xxx xxxx xxxx */
602f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* LDR (immediate, Thumb)	0110 1xxx xxxx xxxx */
603f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* STRB (immediate, Thumb)	0111 0xxx xxxx xxxx */
604f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* LDRB (immediate, Thumb)	0111 1xxx xxxx xxxx */
605f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	DECODE_EMULATE	(0xc000, 0x4000, t16_emulate_loregs_rwflags),
606f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* STRH (immediate, Thumb)	1000 0xxx xxxx xxxx */
607f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* LDRH (immediate, Thumb)	1000 1xxx xxxx xxxx */
608f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	DECODE_EMULATE	(0xf000, 0x8000, t16_emulate_loregs_rwflags),
609f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* STR (immediate, Thumb)	1001 0xxx xxxx xxxx */
610f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* LDR (immediate, Thumb)	1001 1xxx xxxx xxxx */
611f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	DECODE_SIMULATE	(0xf000, 0x9000, t16_simulate_ldrstr_sp_relative),
612f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst
613f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/*
6142f335829040cb16d0640e87121bef208894d4934Jon Medhurst	 * Generate PC-/SP-relative address
6152f335829040cb16d0640e87121bef208894d4934Jon Medhurst	 * ADR (literal)		1010 0xxx xxxx xxxx
6162f335829040cb16d0640e87121bef208894d4934Jon Medhurst	 * ADD (SP plus immediate)	1010 1xxx xxxx xxxx
6172f335829040cb16d0640e87121bef208894d4934Jon Medhurst	 */
6182f335829040cb16d0640e87121bef208894d4934Jon Medhurst	DECODE_SIMULATE	(0xf000, 0xa000, t16_simulate_reladr),
6192f335829040cb16d0640e87121bef208894d4934Jon Medhurst
6202f335829040cb16d0640e87121bef208894d4934Jon Medhurst	/*
6213f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	 * Miscellaneous 16-bit instructions
6223f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	 *				1011 xxxx xxxx xxxx
6233f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	 */
6243f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	DECODE_TABLE	(0xf000, 0xb000, t16_table_1011),
6253f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst
626f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* STM				1100 0xxx xxxx xxxx */
627f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	/* LDM				1100 1xxx xxxx xxxx */
628f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst	DECODE_EMULATE	(0xf000, 0xc000, t16_emulate_loregs_rwflags),
629f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst
630444956677eccfcdfe05de761e1286f62c423ce88Jon Medhurst	/*
631444956677eccfcdfe05de761e1286f62c423ce88Jon Medhurst	 * Conditional branch, and Supervisor Call
632444956677eccfcdfe05de761e1286f62c423ce88Jon Medhurst	 */
633444956677eccfcdfe05de761e1286f62c423ce88Jon Medhurst
634444956677eccfcdfe05de761e1286f62c423ce88Jon Medhurst	/* Permanently UNDEFINED	1101 1110 xxxx xxxx */
635444956677eccfcdfe05de761e1286f62c423ce88Jon Medhurst	/* SVC				1101 1111 xxxx xxxx */
636444956677eccfcdfe05de761e1286f62c423ce88Jon Medhurst	DECODE_REJECT	(0xfe00, 0xde00),
637444956677eccfcdfe05de761e1286f62c423ce88Jon Medhurst
638396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	/* Conditional branch		1101 xxxx xxxx xxxx */
639396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	DECODE_CUSTOM	(0xf000, 0xd000, t16_decode_cond_branch),
640396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst
641396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	/*
642396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	 * Unconditional branch
643396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	 * B				1110 0xxx xxxx xxxx
644396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	 */
645396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst	DECODE_SIMULATE	(0xf800, 0xe000, t16_simulate_branch),
646396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst
6473f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	DECODE_END
6483f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst};
6493f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst
650eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurststatic unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
651eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst{
652eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst	if (unlikely(in_it_block(cpsr)))
653eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst		return kprobe_condition_checks[current_cond(cpsr)](cpsr);
654eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst	return true;
655eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst}
656eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst
657c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurststatic void __kprobes thumb16_singlestep(struct kprobe *p, struct pt_regs *regs)
658c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst{
659c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst	regs->ARM_pc += 2;
660c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst	p->ainsn.insn_handler(p, regs);
661c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst	regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
662c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst}
663c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst
664c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurststatic void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs)
665c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst{
666c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst	regs->ARM_pc += 4;
667c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst	p->ainsn.insn_handler(p, regs);
668c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst	regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
669c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst}
670c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst
6712437170710c4a3dee137a65623960aa7ac82a32eJon Medhurstenum kprobe_insn __kprobes
6722437170710c4a3dee137a65623960aa7ac82a32eJon Medhurstthumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
6732437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst{
674c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst	asi->insn_singlestep = thumb16_singlestep;
675eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst	asi->insn_check_cc = thumb_check_cc;
6763f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst	return kprobe_decode_insn(insn, asi, kprobe_decode_thumb16_table, true);
6772437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst}
6782437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst
6792437170710c4a3dee137a65623960aa7ac82a32eJon Medhurstenum kprobe_insn __kprobes
6802437170710c4a3dee137a65623960aa7ac82a32eJon Medhurstthumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
6812437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst{
682c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst	asi->insn_singlestep = thumb32_singlestep;
683eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst	asi->insn_check_cc = thumb_check_cc;
684f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst	return kprobe_decode_insn(insn, asi, kprobe_decode_thumb32_table, true);
6852437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst}
686