1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * arch/arm/probes/decode-arm.c
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Some code moved here from arch/arm/kernel/kprobes-arm.c
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Copyright (C) 2006, 2007 Motorola Inc.
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <linux/stddef.h>
14*4882a593Smuzhiyun #include <linux/ptrace.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include "decode.h"
17*4882a593Smuzhiyun #include "decode-arm.h"
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun /*
24*4882a593Smuzhiyun * To avoid the complications of mimicing single-stepping on a
25*4882a593Smuzhiyun * processor without a Next-PC or a single-step mode, and to
26*4882a593Smuzhiyun * avoid having to deal with the side-effects of boosting, we
27*4882a593Smuzhiyun * simulate or emulate (almost) all ARM instructions.
28*4882a593Smuzhiyun *
29*4882a593Smuzhiyun * "Simulation" is where the instruction's behavior is duplicated in
30*4882a593Smuzhiyun * C code. "Emulation" is where the original instruction is rewritten
31*4882a593Smuzhiyun * and executed, often by altering its registers.
32*4882a593Smuzhiyun *
33*4882a593Smuzhiyun * By having all behavior of the kprobe'd instruction completed before
34*4882a593Smuzhiyun * returning from the kprobe_handler(), all locks (scheduler and
35*4882a593Smuzhiyun * interrupt) can safely be released. There is no need for secondary
36*4882a593Smuzhiyun * breakpoints, no race with MP or preemptable kernels, nor having to
37*4882a593Smuzhiyun * clean up resources counts at a later time impacting overall system
38*4882a593Smuzhiyun * performance. By rewriting the instruction, only the minimum registers
39*4882a593Smuzhiyun * need to be loaded and saved back optimizing performance.
40*4882a593Smuzhiyun *
41*4882a593Smuzhiyun * Calling the insnslot_*_rwflags version of a function doesn't hurt
42*4882a593Smuzhiyun * anything even when the CPSR flags aren't updated by the
43*4882a593Smuzhiyun * instruction. It's just a little slower in return for saving
44*4882a593Smuzhiyun * a little space by not having a duplicate function that doesn't
45*4882a593Smuzhiyun * update the flags. (The same optimization can be said for
46*4882a593Smuzhiyun * instructions that do or don't perform register writeback)
47*4882a593Smuzhiyun * Also, instructions can either read the flags, only write the
48*4882a593Smuzhiyun * flags, or read and write the flags. To save combinations
49*4882a593Smuzhiyun * rather than for sheer performance, flag functions just assume
50*4882a593Smuzhiyun * read and write of flags.
51*4882a593Smuzhiyun */
52*4882a593Smuzhiyun
simulate_bbl(probes_opcode_t insn,struct arch_probes_insn * asi,struct pt_regs * regs)53*4882a593Smuzhiyun void __kprobes simulate_bbl(probes_opcode_t insn,
54*4882a593Smuzhiyun struct arch_probes_insn *asi, struct pt_regs *regs)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun long iaddr = (long) regs->ARM_pc - 4;
57*4882a593Smuzhiyun int disp = branch_displacement(insn);
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun if (insn & (1 << 24))
60*4882a593Smuzhiyun regs->ARM_lr = iaddr + 4;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun regs->ARM_pc = iaddr + 8 + disp;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
simulate_blx1(probes_opcode_t insn,struct arch_probes_insn * asi,struct pt_regs * regs)65*4882a593Smuzhiyun void __kprobes simulate_blx1(probes_opcode_t insn,
66*4882a593Smuzhiyun struct arch_probes_insn *asi, struct pt_regs *regs)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun long iaddr = (long) regs->ARM_pc - 4;
69*4882a593Smuzhiyun int disp = branch_displacement(insn);
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun regs->ARM_lr = iaddr + 4;
72*4882a593Smuzhiyun regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2);
73*4882a593Smuzhiyun regs->ARM_cpsr |= PSR_T_BIT;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
simulate_blx2bx(probes_opcode_t insn,struct arch_probes_insn * asi,struct pt_regs * regs)76*4882a593Smuzhiyun void __kprobes simulate_blx2bx(probes_opcode_t insn,
77*4882a593Smuzhiyun struct arch_probes_insn *asi, struct pt_regs *regs)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun int rm = insn & 0xf;
80*4882a593Smuzhiyun long rmv = regs->uregs[rm];
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun if (insn & (1 << 5))
83*4882a593Smuzhiyun regs->ARM_lr = (long) regs->ARM_pc;
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun regs->ARM_pc = rmv & ~0x1;
86*4882a593Smuzhiyun regs->ARM_cpsr &= ~PSR_T_BIT;
87*4882a593Smuzhiyun if (rmv & 0x1)
88*4882a593Smuzhiyun regs->ARM_cpsr |= PSR_T_BIT;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
simulate_mrs(probes_opcode_t insn,struct arch_probes_insn * asi,struct pt_regs * regs)91*4882a593Smuzhiyun void __kprobes simulate_mrs(probes_opcode_t insn,
92*4882a593Smuzhiyun struct arch_probes_insn *asi, struct pt_regs *regs)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun int rd = (insn >> 12) & 0xf;
95*4882a593Smuzhiyun unsigned long mask = 0xf8ff03df; /* Mask out execution state */
96*4882a593Smuzhiyun regs->uregs[rd] = regs->ARM_cpsr & mask;
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
simulate_mov_ipsp(probes_opcode_t insn,struct arch_probes_insn * asi,struct pt_regs * regs)99*4882a593Smuzhiyun void __kprobes simulate_mov_ipsp(probes_opcode_t insn,
100*4882a593Smuzhiyun struct arch_probes_insn *asi, struct pt_regs *regs)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun regs->uregs[12] = regs->uregs[13];
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun /*
106*4882a593Smuzhiyun * For the instruction masking and comparisons in all the "space_*"
107*4882a593Smuzhiyun * functions below, Do _not_ rearrange the order of tests unless
108*4882a593Smuzhiyun * you're very, very sure of what you are doing. For the sake of
109*4882a593Smuzhiyun * efficiency, the masks for some tests sometimes assume other test
110*4882a593Smuzhiyun * have been done prior to them so the number of patterns to test
111*4882a593Smuzhiyun * for an instruction set can be as broad as possible to reduce the
112*4882a593Smuzhiyun * number of tests needed.
113*4882a593Smuzhiyun */
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun static const union decode_item arm_1111_table[] = {
116*4882a593Smuzhiyun /* Unconditional instructions */
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /* memory hint 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx */
119*4882a593Smuzhiyun /* PLDI (immediate) 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx */
120*4882a593Smuzhiyun /* PLDW (immediate) 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx */
121*4882a593Smuzhiyun /* PLD (immediate) 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx */
122*4882a593Smuzhiyun DECODE_SIMULATE (0xfe300000, 0xf4100000, PROBES_PRELOAD_IMM),
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun /* memory hint 1111 0110 x001 xxxx xxxx xxxx xxx0 xxxx */
125*4882a593Smuzhiyun /* PLDI (register) 1111 0110 x101 xxxx xxxx xxxx xxx0 xxxx */
126*4882a593Smuzhiyun /* PLDW (register) 1111 0111 x001 xxxx xxxx xxxx xxx0 xxxx */
127*4882a593Smuzhiyun /* PLD (register) 1111 0111 x101 xxxx xxxx xxxx xxx0 xxxx */
128*4882a593Smuzhiyun DECODE_SIMULATE (0xfe300010, 0xf6100000, PROBES_PRELOAD_REG),
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun /* BLX (immediate) 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx */
131*4882a593Smuzhiyun DECODE_SIMULATE (0xfe000000, 0xfa000000, PROBES_BRANCH_IMM),
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun /* CPS 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */
134*4882a593Smuzhiyun /* SETEND 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
135*4882a593Smuzhiyun /* SRS 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
136*4882a593Smuzhiyun /* RFE 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun /* Coprocessor instructions... */
139*4882a593Smuzhiyun /* MCRR2 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx */
140*4882a593Smuzhiyun /* MRRC2 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx */
141*4882a593Smuzhiyun /* LDC2 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
142*4882a593Smuzhiyun /* STC2 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
143*4882a593Smuzhiyun /* CDP2 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
144*4882a593Smuzhiyun /* MCR2 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
145*4882a593Smuzhiyun /* MRC2 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun /* Other unallocated instructions... */
148*4882a593Smuzhiyun DECODE_END
149*4882a593Smuzhiyun };
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun static const union decode_item arm_cccc_0001_0xx0____0xxx_table[] = {
152*4882a593Smuzhiyun /* Miscellaneous instructions */
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun /* MRS cpsr cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
155*4882a593Smuzhiyun DECODE_SIMULATEX(0x0ff000f0, 0x01000000, PROBES_MRS,
156*4882a593Smuzhiyun REGS(0, NOPC, 0, 0, 0)),
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun /* BX cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
159*4882a593Smuzhiyun DECODE_SIMULATE (0x0ff000f0, 0x01200010, PROBES_BRANCH_REG),
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun /* BLX (register) cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
162*4882a593Smuzhiyun DECODE_SIMULATEX(0x0ff000f0, 0x01200030, PROBES_BRANCH_REG,
163*4882a593Smuzhiyun REGS(0, 0, 0, 0, NOPC)),
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun /* CLZ cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
166*4882a593Smuzhiyun DECODE_EMULATEX (0x0ff000f0, 0x01600010, PROBES_CLZ,
167*4882a593Smuzhiyun REGS(0, NOPC, 0, 0, NOPC)),
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun /* QADD cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx */
170*4882a593Smuzhiyun /* QSUB cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx */
171*4882a593Smuzhiyun /* QDADD cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx */
172*4882a593Smuzhiyun /* QDSUB cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx */
173*4882a593Smuzhiyun DECODE_EMULATEX (0x0f9000f0, 0x01000050, PROBES_SATURATING_ARITHMETIC,
174*4882a593Smuzhiyun REGS(NOPC, NOPC, 0, 0, NOPC)),
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /* BXJ cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
177*4882a593Smuzhiyun /* MSR cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
178*4882a593Smuzhiyun /* MRS spsr cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */
179*4882a593Smuzhiyun /* BKPT 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
180*4882a593Smuzhiyun /* SMC cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */
181*4882a593Smuzhiyun /* And unallocated instructions... */
182*4882a593Smuzhiyun DECODE_END
183*4882a593Smuzhiyun };
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun static const union decode_item arm_cccc_0001_0xx0____1xx0_table[] = {
186*4882a593Smuzhiyun /* Halfword multiply and multiply-accumulate */
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun /* SMLALxy cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
189*4882a593Smuzhiyun DECODE_EMULATEX (0x0ff00090, 0x01400080, PROBES_MUL1,
190*4882a593Smuzhiyun REGS(NOPC, NOPC, NOPC, 0, NOPC)),
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun /* SMULWy cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
193*4882a593Smuzhiyun DECODE_OR (0x0ff000b0, 0x012000a0),
194*4882a593Smuzhiyun /* SMULxy cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
195*4882a593Smuzhiyun DECODE_EMULATEX (0x0ff00090, 0x01600080, PROBES_MUL2,
196*4882a593Smuzhiyun REGS(NOPC, 0, NOPC, 0, NOPC)),
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun /* SMLAxy cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx */
199*4882a593Smuzhiyun DECODE_OR (0x0ff00090, 0x01000080),
200*4882a593Smuzhiyun /* SMLAWy cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx */
201*4882a593Smuzhiyun DECODE_EMULATEX (0x0ff000b0, 0x01200080, PROBES_MUL2,
202*4882a593Smuzhiyun REGS(NOPC, NOPC, NOPC, 0, NOPC)),
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun DECODE_END
205*4882a593Smuzhiyun };
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun static const union decode_item arm_cccc_0000_____1001_table[] = {
208*4882a593Smuzhiyun /* Multiply and multiply-accumulate */
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun /* MUL cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx */
211*4882a593Smuzhiyun /* MULS cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx */
212*4882a593Smuzhiyun DECODE_EMULATEX (0x0fe000f0, 0x00000090, PROBES_MUL2,
213*4882a593Smuzhiyun REGS(NOPC, 0, NOPC, 0, NOPC)),
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun /* MLA cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx */
216*4882a593Smuzhiyun /* MLAS cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx */
217*4882a593Smuzhiyun DECODE_OR (0x0fe000f0, 0x00200090),
218*4882a593Smuzhiyun /* MLS cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx */
219*4882a593Smuzhiyun DECODE_EMULATEX (0x0ff000f0, 0x00600090, PROBES_MUL2,
220*4882a593Smuzhiyun REGS(NOPC, NOPC, NOPC, 0, NOPC)),
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun /* UMAAL cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx */
223*4882a593Smuzhiyun DECODE_OR (0x0ff000f0, 0x00400090),
224*4882a593Smuzhiyun /* UMULL cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx */
225*4882a593Smuzhiyun /* UMULLS cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx */
226*4882a593Smuzhiyun /* UMLAL cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx */
227*4882a593Smuzhiyun /* UMLALS cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx */
228*4882a593Smuzhiyun /* SMULL cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx */
229*4882a593Smuzhiyun /* SMULLS cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx */
230*4882a593Smuzhiyun /* SMLAL cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx */
231*4882a593Smuzhiyun /* SMLALS cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx */
232*4882a593Smuzhiyun DECODE_EMULATEX (0x0f8000f0, 0x00800090, PROBES_MUL1,
233*4882a593Smuzhiyun REGS(NOPC, NOPC, NOPC, 0, NOPC)),
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun DECODE_END
236*4882a593Smuzhiyun };
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun static const union decode_item arm_cccc_0001_____1001_table[] = {
239*4882a593Smuzhiyun /* Synchronization primitives */
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun #if __LINUX_ARM_ARCH__ < 6
242*4882a593Smuzhiyun /* Deprecated on ARMv6 and may be UNDEFINED on v7 */
243*4882a593Smuzhiyun /* SMP/SWPB cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */
244*4882a593Smuzhiyun DECODE_EMULATEX (0x0fb000f0, 0x01000090, PROBES_SWP,
245*4882a593Smuzhiyun REGS(NOPC, NOPC, 0, 0, NOPC)),
246*4882a593Smuzhiyun #endif
247*4882a593Smuzhiyun /* LDREX/STREX{,D,B,H} cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */
248*4882a593Smuzhiyun /* And unallocated instructions... */
249*4882a593Smuzhiyun DECODE_END
250*4882a593Smuzhiyun };
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun static const union decode_item arm_cccc_000x_____1xx1_table[] = {
253*4882a593Smuzhiyun /* Extra load/store instructions */
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun /* STRHT cccc 0000 xx10 xxxx xxxx xxxx 1011 xxxx */
256*4882a593Smuzhiyun /* ??? cccc 0000 xx10 xxxx xxxx xxxx 11x1 xxxx */
257*4882a593Smuzhiyun /* LDRHT cccc 0000 xx11 xxxx xxxx xxxx 1011 xxxx */
258*4882a593Smuzhiyun /* LDRSBT cccc 0000 xx11 xxxx xxxx xxxx 1101 xxxx */
259*4882a593Smuzhiyun /* LDRSHT cccc 0000 xx11 xxxx xxxx xxxx 1111 xxxx */
260*4882a593Smuzhiyun DECODE_REJECT (0x0f200090, 0x00200090),
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun /* LDRD/STRD lr,pc,{... cccc 000x x0x0 xxxx 111x xxxx 1101 xxxx */
263*4882a593Smuzhiyun DECODE_REJECT (0x0e10e0d0, 0x0000e0d0),
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun /* LDRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1101 xxxx */
266*4882a593Smuzhiyun /* STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx */
267*4882a593Smuzhiyun DECODE_EMULATEX (0x0e5000d0, 0x000000d0, PROBES_LDRSTRD,
268*4882a593Smuzhiyun REGS(NOPCWB, NOPCX, 0, 0, NOPC)),
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun /* LDRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1101 xxxx */
271*4882a593Smuzhiyun /* STRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1111 xxxx */
272*4882a593Smuzhiyun DECODE_EMULATEX (0x0e5000d0, 0x004000d0, PROBES_LDRSTRD,
273*4882a593Smuzhiyun REGS(NOPCWB, NOPCX, 0, 0, 0)),
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun /* STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */
276*4882a593Smuzhiyun DECODE_EMULATEX (0x0e5000f0, 0x000000b0, PROBES_STORE_EXTRA,
277*4882a593Smuzhiyun REGS(NOPCWB, NOPC, 0, 0, NOPC)),
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun /* LDRH (register) cccc 000x x0x1 xxxx xxxx xxxx 1011 xxxx */
280*4882a593Smuzhiyun /* LDRSB (register) cccc 000x x0x1 xxxx xxxx xxxx 1101 xxxx */
281*4882a593Smuzhiyun /* LDRSH (register) cccc 000x x0x1 xxxx xxxx xxxx 1111 xxxx */
282*4882a593Smuzhiyun DECODE_EMULATEX (0x0e500090, 0x00100090, PROBES_LOAD_EXTRA,
283*4882a593Smuzhiyun REGS(NOPCWB, NOPC, 0, 0, NOPC)),
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun /* STRH (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */
286*4882a593Smuzhiyun DECODE_EMULATEX (0x0e5000f0, 0x004000b0, PROBES_STORE_EXTRA,
287*4882a593Smuzhiyun REGS(NOPCWB, NOPC, 0, 0, 0)),
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun /* LDRH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1011 xxxx */
290*4882a593Smuzhiyun /* LDRSB (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1101 xxxx */
291*4882a593Smuzhiyun /* LDRSH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1111 xxxx */
292*4882a593Smuzhiyun DECODE_EMULATEX (0x0e500090, 0x00500090, PROBES_LOAD_EXTRA,
293*4882a593Smuzhiyun REGS(NOPCWB, NOPC, 0, 0, 0)),
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun DECODE_END
296*4882a593Smuzhiyun };
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun static const union decode_item arm_cccc_000x_table[] = {
299*4882a593Smuzhiyun /* Data-processing (register) */
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun /* <op>S PC, ... cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx */
302*4882a593Smuzhiyun DECODE_REJECT (0x0e10f000, 0x0010f000),
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun /* MOV IP, SP 1110 0001 1010 0000 1100 0000 0000 1101 */
305*4882a593Smuzhiyun DECODE_SIMULATE (0xffffffff, 0xe1a0c00d, PROBES_MOV_IP_SP),
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun /* TST (register) cccc 0001 0001 xxxx xxxx xxxx xxx0 xxxx */
308*4882a593Smuzhiyun /* TEQ (register) cccc 0001 0011 xxxx xxxx xxxx xxx0 xxxx */
309*4882a593Smuzhiyun /* CMP (register) cccc 0001 0101 xxxx xxxx xxxx xxx0 xxxx */
310*4882a593Smuzhiyun /* CMN (register) cccc 0001 0111 xxxx xxxx xxxx xxx0 xxxx */
311*4882a593Smuzhiyun DECODE_EMULATEX (0x0f900010, 0x01100000, PROBES_DATA_PROCESSING_REG,
312*4882a593Smuzhiyun REGS(ANY, 0, 0, 0, ANY)),
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun /* MOV (register) cccc 0001 101x xxxx xxxx xxxx xxx0 xxxx */
315*4882a593Smuzhiyun /* MVN (register) cccc 0001 111x xxxx xxxx xxxx xxx0 xxxx */
316*4882a593Smuzhiyun DECODE_EMULATEX (0x0fa00010, 0x01a00000, PROBES_DATA_PROCESSING_REG,
317*4882a593Smuzhiyun REGS(0, ANY, 0, 0, ANY)),
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun /* AND (register) cccc 0000 000x xxxx xxxx xxxx xxx0 xxxx */
320*4882a593Smuzhiyun /* EOR (register) cccc 0000 001x xxxx xxxx xxxx xxx0 xxxx */
321*4882a593Smuzhiyun /* SUB (register) cccc 0000 010x xxxx xxxx xxxx xxx0 xxxx */
322*4882a593Smuzhiyun /* RSB (register) cccc 0000 011x xxxx xxxx xxxx xxx0 xxxx */
323*4882a593Smuzhiyun /* ADD (register) cccc 0000 100x xxxx xxxx xxxx xxx0 xxxx */
324*4882a593Smuzhiyun /* ADC (register) cccc 0000 101x xxxx xxxx xxxx xxx0 xxxx */
325*4882a593Smuzhiyun /* SBC (register) cccc 0000 110x xxxx xxxx xxxx xxx0 xxxx */
326*4882a593Smuzhiyun /* RSC (register) cccc 0000 111x xxxx xxxx xxxx xxx0 xxxx */
327*4882a593Smuzhiyun /* ORR (register) cccc 0001 100x xxxx xxxx xxxx xxx0 xxxx */
328*4882a593Smuzhiyun /* BIC (register) cccc 0001 110x xxxx xxxx xxxx xxx0 xxxx */
329*4882a593Smuzhiyun DECODE_EMULATEX (0x0e000010, 0x00000000, PROBES_DATA_PROCESSING_REG,
330*4882a593Smuzhiyun REGS(ANY, ANY, 0, 0, ANY)),
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun /* TST (reg-shift reg) cccc 0001 0001 xxxx xxxx xxxx 0xx1 xxxx */
333*4882a593Smuzhiyun /* TEQ (reg-shift reg) cccc 0001 0011 xxxx xxxx xxxx 0xx1 xxxx */
334*4882a593Smuzhiyun /* CMP (reg-shift reg) cccc 0001 0101 xxxx xxxx xxxx 0xx1 xxxx */
335*4882a593Smuzhiyun /* CMN (reg-shift reg) cccc 0001 0111 xxxx xxxx xxxx 0xx1 xxxx */
336*4882a593Smuzhiyun DECODE_EMULATEX (0x0f900090, 0x01100010, PROBES_DATA_PROCESSING_REG,
337*4882a593Smuzhiyun REGS(NOPC, 0, NOPC, 0, NOPC)),
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun /* MOV (reg-shift reg) cccc 0001 101x xxxx xxxx xxxx 0xx1 xxxx */
340*4882a593Smuzhiyun /* MVN (reg-shift reg) cccc 0001 111x xxxx xxxx xxxx 0xx1 xxxx */
341*4882a593Smuzhiyun DECODE_EMULATEX (0x0fa00090, 0x01a00010, PROBES_DATA_PROCESSING_REG,
342*4882a593Smuzhiyun REGS(0, NOPC, NOPC, 0, NOPC)),
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun /* AND (reg-shift reg) cccc 0000 000x xxxx xxxx xxxx 0xx1 xxxx */
345*4882a593Smuzhiyun /* EOR (reg-shift reg) cccc 0000 001x xxxx xxxx xxxx 0xx1 xxxx */
346*4882a593Smuzhiyun /* SUB (reg-shift reg) cccc 0000 010x xxxx xxxx xxxx 0xx1 xxxx */
347*4882a593Smuzhiyun /* RSB (reg-shift reg) cccc 0000 011x xxxx xxxx xxxx 0xx1 xxxx */
348*4882a593Smuzhiyun /* ADD (reg-shift reg) cccc 0000 100x xxxx xxxx xxxx 0xx1 xxxx */
349*4882a593Smuzhiyun /* ADC (reg-shift reg) cccc 0000 101x xxxx xxxx xxxx 0xx1 xxxx */
350*4882a593Smuzhiyun /* SBC (reg-shift reg) cccc 0000 110x xxxx xxxx xxxx 0xx1 xxxx */
351*4882a593Smuzhiyun /* RSC (reg-shift reg) cccc 0000 111x xxxx xxxx xxxx 0xx1 xxxx */
352*4882a593Smuzhiyun /* ORR (reg-shift reg) cccc 0001 100x xxxx xxxx xxxx 0xx1 xxxx */
353*4882a593Smuzhiyun /* BIC (reg-shift reg) cccc 0001 110x xxxx xxxx xxxx 0xx1 xxxx */
354*4882a593Smuzhiyun DECODE_EMULATEX (0x0e000090, 0x00000010, PROBES_DATA_PROCESSING_REG,
355*4882a593Smuzhiyun REGS(NOPC, NOPC, NOPC, 0, NOPC)),
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun DECODE_END
358*4882a593Smuzhiyun };
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun static const union decode_item arm_cccc_001x_table[] = {
361*4882a593Smuzhiyun /* Data-processing (immediate) */
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */
364*4882a593Smuzhiyun /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */
365*4882a593Smuzhiyun DECODE_EMULATEX (0x0fb00000, 0x03000000, PROBES_MOV_HALFWORD,
366*4882a593Smuzhiyun REGS(0, NOPC, 0, 0, 0)),
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun /* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */
369*4882a593Smuzhiyun DECODE_OR (0x0fff00ff, 0x03200001),
370*4882a593Smuzhiyun /* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */
371*4882a593Smuzhiyun DECODE_EMULATE (0x0fff00ff, 0x03200004, PROBES_SEV),
372*4882a593Smuzhiyun /* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */
373*4882a593Smuzhiyun /* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */
374*4882a593Smuzhiyun /* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */
375*4882a593Smuzhiyun DECODE_SIMULATE (0x0fff00fc, 0x03200000, PROBES_WFE),
376*4882a593Smuzhiyun /* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */
377*4882a593Smuzhiyun /* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */
378*4882a593Smuzhiyun /* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */
379*4882a593Smuzhiyun DECODE_REJECT (0x0fb00000, 0x03200000),
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun /* <op>S PC, ... cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx */
382*4882a593Smuzhiyun DECODE_REJECT (0x0e10f000, 0x0210f000),
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun /* TST (immediate) cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx */
385*4882a593Smuzhiyun /* TEQ (immediate) cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx */
386*4882a593Smuzhiyun /* CMP (immediate) cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx */
387*4882a593Smuzhiyun /* CMN (immediate) cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx */
388*4882a593Smuzhiyun DECODE_EMULATEX (0x0f900000, 0x03100000, PROBES_DATA_PROCESSING_IMM,
389*4882a593Smuzhiyun REGS(ANY, 0, 0, 0, 0)),
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun /* MOV (immediate) cccc 0011 101x xxxx xxxx xxxx xxxx xxxx */
392*4882a593Smuzhiyun /* MVN (immediate) cccc 0011 111x xxxx xxxx xxxx xxxx xxxx */
393*4882a593Smuzhiyun DECODE_EMULATEX (0x0fa00000, 0x03a00000, PROBES_DATA_PROCESSING_IMM,
394*4882a593Smuzhiyun REGS(0, ANY, 0, 0, 0)),
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun /* AND (immediate) cccc 0010 000x xxxx xxxx xxxx xxxx xxxx */
397*4882a593Smuzhiyun /* EOR (immediate) cccc 0010 001x xxxx xxxx xxxx xxxx xxxx */
398*4882a593Smuzhiyun /* SUB (immediate) cccc 0010 010x xxxx xxxx xxxx xxxx xxxx */
399*4882a593Smuzhiyun /* RSB (immediate) cccc 0010 011x xxxx xxxx xxxx xxxx xxxx */
400*4882a593Smuzhiyun /* ADD (immediate) cccc 0010 100x xxxx xxxx xxxx xxxx xxxx */
401*4882a593Smuzhiyun /* ADC (immediate) cccc 0010 101x xxxx xxxx xxxx xxxx xxxx */
402*4882a593Smuzhiyun /* SBC (immediate) cccc 0010 110x xxxx xxxx xxxx xxxx xxxx */
403*4882a593Smuzhiyun /* RSC (immediate) cccc 0010 111x xxxx xxxx xxxx xxxx xxxx */
404*4882a593Smuzhiyun /* ORR (immediate) cccc 0011 100x xxxx xxxx xxxx xxxx xxxx */
405*4882a593Smuzhiyun /* BIC (immediate) cccc 0011 110x xxxx xxxx xxxx xxxx xxxx */
406*4882a593Smuzhiyun DECODE_EMULATEX (0x0e000000, 0x02000000, PROBES_DATA_PROCESSING_IMM,
407*4882a593Smuzhiyun REGS(ANY, ANY, 0, 0, 0)),
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun DECODE_END
410*4882a593Smuzhiyun };
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun static const union decode_item arm_cccc_0110_____xxx1_table[] = {
413*4882a593Smuzhiyun /* Media instructions */
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun /* SEL cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx */
416*4882a593Smuzhiyun DECODE_EMULATEX (0x0ff000f0, 0x068000b0, PROBES_SATURATE,
417*4882a593Smuzhiyun REGS(NOPC, NOPC, 0, 0, NOPC)),
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun /* SSAT cccc 0110 101x xxxx xxxx xxxx xx01 xxxx */
420*4882a593Smuzhiyun /* USAT cccc 0110 111x xxxx xxxx xxxx xx01 xxxx */
421*4882a593Smuzhiyun DECODE_OR(0x0fa00030, 0x06a00010),
422*4882a593Smuzhiyun /* SSAT16 cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx */
423*4882a593Smuzhiyun /* USAT16 cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx */
424*4882a593Smuzhiyun DECODE_EMULATEX (0x0fb000f0, 0x06a00030, PROBES_SATURATE,
425*4882a593Smuzhiyun REGS(0, NOPC, 0, 0, NOPC)),
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun /* REV cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */
428*4882a593Smuzhiyun /* REV16 cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */
429*4882a593Smuzhiyun /* RBIT cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */
430*4882a593Smuzhiyun /* REVSH cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */
431*4882a593Smuzhiyun DECODE_EMULATEX (0x0fb00070, 0x06b00030, PROBES_REV,
432*4882a593Smuzhiyun REGS(0, NOPC, 0, 0, NOPC)),
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun /* ??? cccc 0110 0x00 xxxx xxxx xxxx xxx1 xxxx */
435*4882a593Smuzhiyun DECODE_REJECT (0x0fb00010, 0x06000010),
436*4882a593Smuzhiyun /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1011 xxxx */
437*4882a593Smuzhiyun DECODE_REJECT (0x0f8000f0, 0x060000b0),
438*4882a593Smuzhiyun /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1101 xxxx */
439*4882a593Smuzhiyun DECODE_REJECT (0x0f8000f0, 0x060000d0),
440*4882a593Smuzhiyun /* SADD16 cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx */
441*4882a593Smuzhiyun /* SADDSUBX cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx */
442*4882a593Smuzhiyun /* SSUBADDX cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx */
443*4882a593Smuzhiyun /* SSUB16 cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx */
444*4882a593Smuzhiyun /* SADD8 cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx */
445*4882a593Smuzhiyun /* SSUB8 cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx */
446*4882a593Smuzhiyun /* QADD16 cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx */
447*4882a593Smuzhiyun /* QADDSUBX cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx */
448*4882a593Smuzhiyun /* QSUBADDX cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx */
449*4882a593Smuzhiyun /* QSUB16 cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx */
450*4882a593Smuzhiyun /* QADD8 cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx */
451*4882a593Smuzhiyun /* QSUB8 cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx */
452*4882a593Smuzhiyun /* SHADD16 cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx */
453*4882a593Smuzhiyun /* SHADDSUBX cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx */
454*4882a593Smuzhiyun /* SHSUBADDX cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx */
455*4882a593Smuzhiyun /* SHSUB16 cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx */
456*4882a593Smuzhiyun /* SHADD8 cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx */
457*4882a593Smuzhiyun /* SHSUB8 cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx */
458*4882a593Smuzhiyun /* UADD16 cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx */
459*4882a593Smuzhiyun /* UADDSUBX cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx */
460*4882a593Smuzhiyun /* USUBADDX cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx */
461*4882a593Smuzhiyun /* USUB16 cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx */
462*4882a593Smuzhiyun /* UADD8 cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx */
463*4882a593Smuzhiyun /* USUB8 cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx */
464*4882a593Smuzhiyun /* UQADD16 cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx */
465*4882a593Smuzhiyun /* UQADDSUBX cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx */
466*4882a593Smuzhiyun /* UQSUBADDX cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx */
467*4882a593Smuzhiyun /* UQSUB16 cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx */
468*4882a593Smuzhiyun /* UQADD8 cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx */
469*4882a593Smuzhiyun /* UQSUB8 cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx */
470*4882a593Smuzhiyun /* UHADD16 cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx */
471*4882a593Smuzhiyun /* UHADDSUBX cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx */
472*4882a593Smuzhiyun /* UHSUBADDX cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx */
473*4882a593Smuzhiyun /* UHSUB16 cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx */
474*4882a593Smuzhiyun /* UHADD8 cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx */
475*4882a593Smuzhiyun /* UHSUB8 cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx */
476*4882a593Smuzhiyun DECODE_EMULATEX (0x0f800010, 0x06000010, PROBES_MMI,
477*4882a593Smuzhiyun REGS(NOPC, NOPC, 0, 0, NOPC)),
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun /* PKHBT cccc 0110 1000 xxxx xxxx xxxx x001 xxxx */
480*4882a593Smuzhiyun /* PKHTB cccc 0110 1000 xxxx xxxx xxxx x101 xxxx */
481*4882a593Smuzhiyun DECODE_EMULATEX (0x0ff00030, 0x06800010, PROBES_PACK,
482*4882a593Smuzhiyun REGS(NOPC, NOPC, 0, 0, NOPC)),
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun /* ??? cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx */
485*4882a593Smuzhiyun /* ??? cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx */
486*4882a593Smuzhiyun DECODE_REJECT (0x0fb000f0, 0x06900070),
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun /* SXTB16 cccc 0110 1000 1111 xxxx xxxx 0111 xxxx */
489*4882a593Smuzhiyun /* SXTB cccc 0110 1010 1111 xxxx xxxx 0111 xxxx */
490*4882a593Smuzhiyun /* SXTH cccc 0110 1011 1111 xxxx xxxx 0111 xxxx */
491*4882a593Smuzhiyun /* UXTB16 cccc 0110 1100 1111 xxxx xxxx 0111 xxxx */
492*4882a593Smuzhiyun /* UXTB cccc 0110 1110 1111 xxxx xxxx 0111 xxxx */
493*4882a593Smuzhiyun /* UXTH cccc 0110 1111 1111 xxxx xxxx 0111 xxxx */
494*4882a593Smuzhiyun DECODE_EMULATEX (0x0f8f00f0, 0x068f0070, PROBES_EXTEND,
495*4882a593Smuzhiyun REGS(0, NOPC, 0, 0, NOPC)),
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun /* SXTAB16 cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx */
498*4882a593Smuzhiyun /* SXTAB cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx */
499*4882a593Smuzhiyun /* SXTAH cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx */
500*4882a593Smuzhiyun /* UXTAB16 cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx */
501*4882a593Smuzhiyun /* UXTAB cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx */
502*4882a593Smuzhiyun /* UXTAH cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx */
503*4882a593Smuzhiyun DECODE_EMULATEX (0x0f8000f0, 0x06800070, PROBES_EXTEND_ADD,
504*4882a593Smuzhiyun REGS(NOPCX, NOPC, 0, 0, NOPC)),
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun DECODE_END
507*4882a593Smuzhiyun };
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun static const union decode_item arm_cccc_0111_____xxx1_table[] = {
510*4882a593Smuzhiyun /* Media instructions */
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun /* UNDEFINED cccc 0111 1111 xxxx xxxx xxxx 1111 xxxx */
513*4882a593Smuzhiyun DECODE_REJECT (0x0ff000f0, 0x07f000f0),
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun /* SMLALD cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */
516*4882a593Smuzhiyun /* SMLSLD cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */
517*4882a593Smuzhiyun DECODE_EMULATEX (0x0ff00090, 0x07400010, PROBES_MUL_ADD_LONG,
518*4882a593Smuzhiyun REGS(NOPC, NOPC, NOPC, 0, NOPC)),
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun /* SMUAD cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx */
521*4882a593Smuzhiyun /* SMUSD cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx */
522*4882a593Smuzhiyun DECODE_OR (0x0ff0f090, 0x0700f010),
523*4882a593Smuzhiyun /* SMMUL cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx */
524*4882a593Smuzhiyun DECODE_OR (0x0ff0f0d0, 0x0750f010),
525*4882a593Smuzhiyun /* USAD8 cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */
526*4882a593Smuzhiyun DECODE_EMULATEX (0x0ff0f0f0, 0x0780f010, PROBES_MUL_ADD,
527*4882a593Smuzhiyun REGS(NOPC, 0, NOPC, 0, NOPC)),
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun /* SMLAD cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx */
530*4882a593Smuzhiyun /* SMLSD cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx */
531*4882a593Smuzhiyun DECODE_OR (0x0ff00090, 0x07000010),
532*4882a593Smuzhiyun /* SMMLA cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx */
533*4882a593Smuzhiyun DECODE_OR (0x0ff000d0, 0x07500010),
534*4882a593Smuzhiyun /* USADA8 cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */
535*4882a593Smuzhiyun DECODE_EMULATEX (0x0ff000f0, 0x07800010, PROBES_MUL_ADD,
536*4882a593Smuzhiyun REGS(NOPC, NOPCX, NOPC, 0, NOPC)),
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun /* SMMLS cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx */
539*4882a593Smuzhiyun DECODE_EMULATEX (0x0ff000d0, 0x075000d0, PROBES_MUL_ADD,
540*4882a593Smuzhiyun REGS(NOPC, NOPC, NOPC, 0, NOPC)),
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun /* SBFX cccc 0111 101x xxxx xxxx xxxx x101 xxxx */
543*4882a593Smuzhiyun /* UBFX cccc 0111 111x xxxx xxxx xxxx x101 xxxx */
544*4882a593Smuzhiyun DECODE_EMULATEX (0x0fa00070, 0x07a00050, PROBES_BITFIELD,
545*4882a593Smuzhiyun REGS(0, NOPC, 0, 0, NOPC)),
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun /* BFC cccc 0111 110x xxxx xxxx xxxx x001 1111 */
548*4882a593Smuzhiyun DECODE_EMULATEX (0x0fe0007f, 0x07c0001f, PROBES_BITFIELD,
549*4882a593Smuzhiyun REGS(0, NOPC, 0, 0, 0)),
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun /* BFI cccc 0111 110x xxxx xxxx xxxx x001 xxxx */
552*4882a593Smuzhiyun DECODE_EMULATEX (0x0fe00070, 0x07c00010, PROBES_BITFIELD,
553*4882a593Smuzhiyun REGS(0, NOPC, 0, 0, NOPCX)),
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun DECODE_END
556*4882a593Smuzhiyun };
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun static const union decode_item arm_cccc_01xx_table[] = {
559*4882a593Smuzhiyun /* Load/store word and unsigned byte */
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun /* LDRB/STRB pc,[...] cccc 01xx x0xx xxxx xxxx xxxx xxxx xxxx */
562*4882a593Smuzhiyun DECODE_REJECT (0x0c40f000, 0x0440f000),
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun /* STRT cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */
565*4882a593Smuzhiyun /* LDRT cccc 01x0 x011 xxxx xxxx xxxx xxxx xxxx */
566*4882a593Smuzhiyun /* STRBT cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */
567*4882a593Smuzhiyun /* LDRBT cccc 01x0 x111 xxxx xxxx xxxx xxxx xxxx */
568*4882a593Smuzhiyun DECODE_REJECT (0x0d200000, 0x04200000),
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun /* STR (immediate) cccc 010x x0x0 xxxx xxxx xxxx xxxx xxxx */
571*4882a593Smuzhiyun /* STRB (immediate) cccc 010x x1x0 xxxx xxxx xxxx xxxx xxxx */
572*4882a593Smuzhiyun DECODE_EMULATEX (0x0e100000, 0x04000000, PROBES_STORE,
573*4882a593Smuzhiyun REGS(NOPCWB, ANY, 0, 0, 0)),
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun /* LDR (immediate) cccc 010x x0x1 xxxx xxxx xxxx xxxx xxxx */
576*4882a593Smuzhiyun /* LDRB (immediate) cccc 010x x1x1 xxxx xxxx xxxx xxxx xxxx */
577*4882a593Smuzhiyun DECODE_EMULATEX (0x0e100000, 0x04100000, PROBES_LOAD,
578*4882a593Smuzhiyun REGS(NOPCWB, ANY, 0, 0, 0)),
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun /* STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx */
581*4882a593Smuzhiyun /* STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx */
582*4882a593Smuzhiyun DECODE_EMULATEX (0x0e100000, 0x06000000, PROBES_STORE,
583*4882a593Smuzhiyun REGS(NOPCWB, ANY, 0, 0, NOPC)),
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun /* LDR (register) cccc 011x x0x1 xxxx xxxx xxxx xxxx xxxx */
586*4882a593Smuzhiyun /* LDRB (register) cccc 011x x1x1 xxxx xxxx xxxx xxxx xxxx */
587*4882a593Smuzhiyun DECODE_EMULATEX (0x0e100000, 0x06100000, PROBES_LOAD,
588*4882a593Smuzhiyun REGS(NOPCWB, ANY, 0, 0, NOPC)),
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun DECODE_END
591*4882a593Smuzhiyun };
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun static const union decode_item arm_cccc_100x_table[] = {
594*4882a593Smuzhiyun /* Block data transfer instructions */
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun /* LDM cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
597*4882a593Smuzhiyun /* STM cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
598*4882a593Smuzhiyun DECODE_CUSTOM (0x0e400000, 0x08000000, PROBES_LDMSTM),
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun /* STM (user registers) cccc 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
601*4882a593Smuzhiyun /* LDM (user registers) cccc 100x x1x1 xxxx 0xxx xxxx xxxx xxxx */
602*4882a593Smuzhiyun /* LDM (exception ret) cccc 100x x1x1 xxxx 1xxx xxxx xxxx xxxx */
603*4882a593Smuzhiyun DECODE_END
604*4882a593Smuzhiyun };
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun const union decode_item probes_decode_arm_table[] = {
607*4882a593Smuzhiyun /*
608*4882a593Smuzhiyun * Unconditional instructions
609*4882a593Smuzhiyun * 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx
610*4882a593Smuzhiyun */
611*4882a593Smuzhiyun DECODE_TABLE (0xf0000000, 0xf0000000, arm_1111_table),
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun /*
614*4882a593Smuzhiyun * Miscellaneous instructions
615*4882a593Smuzhiyun * cccc 0001 0xx0 xxxx xxxx xxxx 0xxx xxxx
616*4882a593Smuzhiyun */
617*4882a593Smuzhiyun DECODE_TABLE (0x0f900080, 0x01000000, arm_cccc_0001_0xx0____0xxx_table),
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun /*
620*4882a593Smuzhiyun * Halfword multiply and multiply-accumulate
621*4882a593Smuzhiyun * cccc 0001 0xx0 xxxx xxxx xxxx 1xx0 xxxx
622*4882a593Smuzhiyun */
623*4882a593Smuzhiyun DECODE_TABLE (0x0f900090, 0x01000080, arm_cccc_0001_0xx0____1xx0_table),
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun /*
626*4882a593Smuzhiyun * Multiply and multiply-accumulate
627*4882a593Smuzhiyun * cccc 0000 xxxx xxxx xxxx xxxx 1001 xxxx
628*4882a593Smuzhiyun */
629*4882a593Smuzhiyun DECODE_TABLE (0x0f0000f0, 0x00000090, arm_cccc_0000_____1001_table),
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun /*
632*4882a593Smuzhiyun * Synchronization primitives
633*4882a593Smuzhiyun * cccc 0001 xxxx xxxx xxxx xxxx 1001 xxxx
634*4882a593Smuzhiyun */
635*4882a593Smuzhiyun DECODE_TABLE (0x0f0000f0, 0x01000090, arm_cccc_0001_____1001_table),
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun /*
638*4882a593Smuzhiyun * Extra load/store instructions
639*4882a593Smuzhiyun * cccc 000x xxxx xxxx xxxx xxxx 1xx1 xxxx
640*4882a593Smuzhiyun */
641*4882a593Smuzhiyun DECODE_TABLE (0x0e000090, 0x00000090, arm_cccc_000x_____1xx1_table),
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun /*
644*4882a593Smuzhiyun * Data-processing (register)
645*4882a593Smuzhiyun * cccc 000x xxxx xxxx xxxx xxxx xxx0 xxxx
646*4882a593Smuzhiyun * Data-processing (register-shifted register)
647*4882a593Smuzhiyun * cccc 000x xxxx xxxx xxxx xxxx 0xx1 xxxx
648*4882a593Smuzhiyun */
649*4882a593Smuzhiyun DECODE_TABLE (0x0e000000, 0x00000000, arm_cccc_000x_table),
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun /*
652*4882a593Smuzhiyun * Data-processing (immediate)
653*4882a593Smuzhiyun * cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx
654*4882a593Smuzhiyun */
655*4882a593Smuzhiyun DECODE_TABLE (0x0e000000, 0x02000000, arm_cccc_001x_table),
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun /*
658*4882a593Smuzhiyun * Media instructions
659*4882a593Smuzhiyun * cccc 011x xxxx xxxx xxxx xxxx xxx1 xxxx
660*4882a593Smuzhiyun */
661*4882a593Smuzhiyun DECODE_TABLE (0x0f000010, 0x06000010, arm_cccc_0110_____xxx1_table),
662*4882a593Smuzhiyun DECODE_TABLE (0x0f000010, 0x07000010, arm_cccc_0111_____xxx1_table),
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun /*
665*4882a593Smuzhiyun * Load/store word and unsigned byte
666*4882a593Smuzhiyun * cccc 01xx xxxx xxxx xxxx xxxx xxxx xxxx
667*4882a593Smuzhiyun */
668*4882a593Smuzhiyun DECODE_TABLE (0x0c000000, 0x04000000, arm_cccc_01xx_table),
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun /*
671*4882a593Smuzhiyun * Block data transfer instructions
672*4882a593Smuzhiyun * cccc 100x xxxx xxxx xxxx xxxx xxxx xxxx
673*4882a593Smuzhiyun */
674*4882a593Smuzhiyun DECODE_TABLE (0x0e000000, 0x08000000, arm_cccc_100x_table),
675*4882a593Smuzhiyun
676*4882a593Smuzhiyun /* B cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */
677*4882a593Smuzhiyun /* BL cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */
678*4882a593Smuzhiyun DECODE_SIMULATE (0x0e000000, 0x0a000000, PROBES_BRANCH),
679*4882a593Smuzhiyun
680*4882a593Smuzhiyun /*
681*4882a593Smuzhiyun * Supervisor Call, and coprocessor instructions
682*4882a593Smuzhiyun */
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun /* MCRR cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx */
685*4882a593Smuzhiyun /* MRRC cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx */
686*4882a593Smuzhiyun /* LDC cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
687*4882a593Smuzhiyun /* STC cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
688*4882a593Smuzhiyun /* CDP cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
689*4882a593Smuzhiyun /* MCR cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
690*4882a593Smuzhiyun /* MRC cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
691*4882a593Smuzhiyun /* SVC cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
692*4882a593Smuzhiyun DECODE_REJECT (0x0c000000, 0x0c000000),
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun DECODE_END
695*4882a593Smuzhiyun };
696*4882a593Smuzhiyun #ifdef CONFIG_ARM_KPROBES_TEST_MODULE
697*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(probes_decode_arm_table);
698*4882a593Smuzhiyun #endif
699*4882a593Smuzhiyun
arm_singlestep(probes_opcode_t insn,struct arch_probes_insn * asi,struct pt_regs * regs)700*4882a593Smuzhiyun static void __kprobes arm_singlestep(probes_opcode_t insn,
701*4882a593Smuzhiyun struct arch_probes_insn *asi, struct pt_regs *regs)
702*4882a593Smuzhiyun {
703*4882a593Smuzhiyun regs->ARM_pc += 4;
704*4882a593Smuzhiyun asi->insn_handler(insn, asi, regs);
705*4882a593Smuzhiyun }
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun /* Return:
708*4882a593Smuzhiyun * INSN_REJECTED If instruction is one not allowed to kprobe,
709*4882a593Smuzhiyun * INSN_GOOD If instruction is supported and uses instruction slot,
710*4882a593Smuzhiyun * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot.
711*4882a593Smuzhiyun *
712*4882a593Smuzhiyun * For instructions we don't want to kprobe (INSN_REJECTED return result):
713*4882a593Smuzhiyun * These are generally ones that modify the processor state making
714*4882a593Smuzhiyun * them "hard" to simulate such as switches processor modes or
715*4882a593Smuzhiyun * make accesses in alternate modes. Any of these could be simulated
716*4882a593Smuzhiyun * if the work was put into it, but low return considering they
717*4882a593Smuzhiyun * should also be very rare.
718*4882a593Smuzhiyun */
719*4882a593Smuzhiyun enum probes_insn __kprobes
arm_probes_decode_insn(probes_opcode_t insn,struct arch_probes_insn * asi,bool emulate,const union decode_action * actions,const struct decode_checker * checkers[])720*4882a593Smuzhiyun arm_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
721*4882a593Smuzhiyun bool emulate, const union decode_action *actions,
722*4882a593Smuzhiyun const struct decode_checker *checkers[])
723*4882a593Smuzhiyun {
724*4882a593Smuzhiyun asi->insn_singlestep = arm_singlestep;
725*4882a593Smuzhiyun asi->insn_check_cc = probes_condition_checks[insn>>28];
726*4882a593Smuzhiyun return probes_decode_insn(insn, asi, probes_decode_arm_table, false,
727*4882a593Smuzhiyun emulate, actions, checkers);
728*4882a593Smuzhiyun }
729