Commit | Line | Data |
---|---|---|
35aa1df4 QB |
1 | /* |
2 | * arch/arm/kernel/kprobes-decode.c | |
3 | * | |
4 | * Copyright (C) 2006, 2007 Motorola Inc. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 as | |
8 | * published by the Free Software Foundation. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * General Public License for more details. | |
14 | */ | |
15 | ||
16 | /* | |
17 | * We do not have hardware single-stepping on ARM, This | |
18 | * effort is further complicated by the ARM not having a | |
19 | * "next PC" register. Instructions that change the PC | |
20 | * can't be safely single-stepped in a MP environment, so | |
21 | * we have a lot of work to do: | |
22 | * | |
23 | * In the prepare phase: | |
24 | * *) If it is an instruction that does anything | |
25 | * with the CPU mode, we reject it for a kprobe. | |
26 | * (This is out of laziness rather than need. The | |
27 | * instructions could be simulated.) | |
28 | * | |
29 | * *) Otherwise, decode the instruction rewriting its | |
30 | * registers to take fixed, ordered registers and | |
31 | * setting a handler for it to run the instruction. | |
32 | * | |
33 | * In the execution phase by an instruction's handler: | |
34 | * | |
35 | * *) If the PC is written to by the instruction, the | |
36 | * instruction must be fully simulated in software. | |
35aa1df4 QB |
37 | * |
38 | * *) Otherwise, a modified form of the instruction is | |
39 | * directly executed. Its handler calls the | |
40 | * instruction in insn[0]. In insn[1] is a | |
41 | * "mov pc, lr" to return. | |
42 | * | |
43 | * Before calling, load up the reordered registers | |
44 | * from the original instruction's registers. If one | |
45 | * of the original input registers is the PC, compute | |
46 | * and adjust the appropriate input register. | |
47 | * | |
48 | * After call completes, copy the output registers to | |
49 | * the original instruction's original registers. | |
50 | * | |
51 | * We don't use a real breakpoint instruction since that | |
52 | * would have us in the kernel go from SVC mode to SVC | |
53 | * mode losing the link register. Instead we use an | |
54 | * undefined instruction. To simplify processing, the | |
55 | * undefined instruction used for kprobes must be reserved | |
56 | * exclusively for kprobes use. | |
57 | * | |
58 | * TODO: ifdef out some instruction decoding based on architecture. | |
59 | */ | |
60 | ||
61 | #include <linux/kernel.h> | |
62 | #include <linux/kprobes.h> | |
2c89240b | 63 | #include <linux/module.h> |
35aa1df4 | 64 | |
221bf15f JM |
65 | #include "kprobes.h" |
66 | ||
35aa1df4 QB |
67 | #define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit))))) |
68 | ||
69 | #define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25) | |
70 | ||
7be7ee2d JM |
71 | #if __LINUX_ARM_ARCH__ >= 6 |
72 | #define BLX(reg) "blx "reg" \n\t" | |
73 | #else | |
74 | #define BLX(reg) "mov lr, pc \n\t" \ | |
75 | "mov pc, "reg" \n\t" | |
76 | #endif | |
77 | ||
35aa1df4 QB |
78 | /* |
79 | * To avoid the complications of mimicing single-stepping on a | |
80 | * processor without a Next-PC or a single-step mode, and to | |
81 | * avoid having to deal with the side-effects of boosting, we | |
82 | * simulate or emulate (almost) all ARM instructions. | |
83 | * | |
84 | * "Simulation" is where the instruction's behavior is duplicated in | |
85 | * C code. "Emulation" is where the original instruction is rewritten | |
86 | * and executed, often by altering its registers. | |
87 | * | |
88 | * By having all behavior of the kprobe'd instruction completed before | |
89 | * returning from the kprobe_handler(), all locks (scheduler and | |
90 | * interrupt) can safely be released. There is no need for secondary | |
91 | * breakpoints, no race with MP or preemptable kernels, nor having to | |
92 | * clean up resources counts at a later time impacting overall system | |
93 | * performance. By rewriting the instruction, only the minimum registers | |
94 | * need to be loaded and saved back optimizing performance. | |
95 | * | |
96 | * Calling the insnslot_*_rwflags version of a function doesn't hurt | |
97 | * anything even when the CPSR flags aren't updated by the | |
98 | * instruction. It's just a little slower in return for saving | |
99 | * a little space by not having a duplicate function that doesn't | |
100 | * update the flags. (The same optimization can be said for | |
101 | * instructions that do or don't perform register writeback) | |
102 | * Also, instructions can either read the flags, only write the | |
103 | * flags, or read and write the flags. To save combinations | |
104 | * rather than for sheer performance, flag functions just assume | |
105 | * read and write of flags. | |
106 | */ | |
107 | ||
108 | static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs) | |
109 | { | |
35aa1df4 QB |
110 | kprobe_opcode_t insn = p->opcode; |
111 | long iaddr = (long)p->addr; | |
112 | int disp = branch_displacement(insn); | |
113 | ||
35aa1df4 QB |
114 | if (insn & (1 << 24)) |
115 | regs->ARM_lr = iaddr + 4; | |
116 | ||
117 | regs->ARM_pc = iaddr + 8 + disp; | |
118 | } | |
119 | ||
120 | static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs) | |
121 | { | |
122 | kprobe_opcode_t insn = p->opcode; | |
123 | long iaddr = (long)p->addr; | |
124 | int disp = branch_displacement(insn); | |
125 | ||
126 | regs->ARM_lr = iaddr + 4; | |
127 | regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2); | |
128 | regs->ARM_cpsr |= PSR_T_BIT; | |
129 | } | |
130 | ||
131 | static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs) | |
132 | { | |
35aa1df4 QB |
133 | kprobe_opcode_t insn = p->opcode; |
134 | int rm = insn & 0xf; | |
135 | long rmv = regs->uregs[rm]; | |
136 | ||
35aa1df4 QB |
137 | if (insn & (1 << 5)) |
138 | regs->ARM_lr = (long)p->addr + 4; | |
139 | ||
140 | regs->ARM_pc = rmv & ~0x1; | |
141 | regs->ARM_cpsr &= ~PSR_T_BIT; | |
142 | if (rmv & 0x1) | |
143 | regs->ARM_cpsr |= PSR_T_BIT; | |
144 | } | |
145 | ||
c412aba2 JM |
146 | static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs) |
147 | { | |
148 | kprobe_opcode_t insn = p->opcode; | |
149 | int rd = (insn >> 12) & 0xf; | |
150 | unsigned long mask = 0xf8ff03df; /* Mask out execution state */ | |
151 | regs->uregs[rd] = regs->ARM_cpsr & mask; | |
152 | } | |
153 | ||
35aa1df4 QB |
154 | static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs) |
155 | { | |
156 | regs->uregs[12] = regs->uregs[13]; | |
157 | } | |
158 | ||
8723942f JM |
159 | static void __kprobes |
160 | emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | |
161 | { | |
162 | kprobe_opcode_t insn = p->opcode; | |
163 | unsigned long pc = (unsigned long)p->addr + 8; | |
164 | int rt = (insn >> 12) & 0xf; | |
165 | int rn = (insn >> 16) & 0xf; | |
166 | int rm = insn & 0xf; | |
167 | ||
168 | register unsigned long rtv asm("r0") = regs->uregs[rt]; | |
169 | register unsigned long rt2v asm("r1") = regs->uregs[rt+1]; | |
170 | register unsigned long rnv asm("r2") = (rn == 15) ? pc | |
171 | : regs->uregs[rn]; | |
172 | register unsigned long rmv asm("r3") = regs->uregs[rm]; | |
173 | ||
174 | __asm__ __volatile__ ( | |
175 | BLX("%[fn]") | |
176 | : "=r" (rtv), "=r" (rt2v), "=r" (rnv) | |
177 | : "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv), | |
178 | [fn] "r" (p->ainsn.insn_fn) | |
179 | : "lr", "memory", "cc" | |
180 | ); | |
181 | ||
182 | regs->uregs[rt] = rtv; | |
183 | regs->uregs[rt+1] = rt2v; | |
184 | if (is_writeback(insn)) | |
185 | regs->uregs[rn] = rnv; | |
186 | } | |
187 | ||
3c48fbb1 JM |
188 | static void __kprobes |
189 | emulate_ldr(struct kprobe *p, struct pt_regs *regs) | |
190 | { | |
191 | kprobe_opcode_t insn = p->opcode; | |
192 | unsigned long pc = (unsigned long)p->addr + 8; | |
193 | int rt = (insn >> 12) & 0xf; | |
194 | int rn = (insn >> 16) & 0xf; | |
195 | int rm = insn & 0xf; | |
196 | ||
197 | register unsigned long rtv asm("r0"); | |
198 | register unsigned long rnv asm("r2") = (rn == 15) ? pc | |
199 | : regs->uregs[rn]; | |
200 | register unsigned long rmv asm("r3") = regs->uregs[rm]; | |
201 | ||
202 | __asm__ __volatile__ ( | |
203 | BLX("%[fn]") | |
204 | : "=r" (rtv), "=r" (rnv) | |
205 | : "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) | |
206 | : "lr", "memory", "cc" | |
207 | ); | |
208 | ||
209 | if (rt == 15) | |
210 | load_write_pc(rtv, regs); | |
211 | else | |
212 | regs->uregs[rt] = rtv; | |
213 | ||
214 | if (is_writeback(insn)) | |
215 | regs->uregs[rn] = rnv; | |
216 | } | |
217 | ||
218 | static void __kprobes | |
219 | emulate_str(struct kprobe *p, struct pt_regs *regs) | |
220 | { | |
221 | kprobe_opcode_t insn = p->opcode; | |
222 | unsigned long rtpc = (unsigned long)p->addr + str_pc_offset; | |
223 | unsigned long rnpc = (unsigned long)p->addr + 8; | |
224 | int rt = (insn >> 12) & 0xf; | |
225 | int rn = (insn >> 16) & 0xf; | |
226 | int rm = insn & 0xf; | |
227 | ||
228 | register unsigned long rtv asm("r0") = (rt == 15) ? rtpc | |
229 | : regs->uregs[rt]; | |
230 | register unsigned long rnv asm("r2") = (rn == 15) ? rnpc | |
231 | : regs->uregs[rn]; | |
232 | register unsigned long rmv asm("r3") = regs->uregs[rm]; | |
233 | ||
234 | __asm__ __volatile__ ( | |
235 | BLX("%[fn]") | |
236 | : "=r" (rnv) | |
237 | : "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) | |
238 | : "lr", "memory", "cc" | |
239 | ); | |
240 | ||
241 | if (is_writeback(insn)) | |
242 | regs->uregs[rn] = rnv; | |
243 | } | |
244 | ||
9f596e51 JM |
245 | static void __kprobes |
246 | emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs) | |
247 | { | |
248 | kprobe_opcode_t insn = p->opcode; | |
249 | unsigned long pc = (unsigned long)p->addr + 8; | |
250 | int rd = (insn >> 12) & 0xf; | |
251 | int rn = (insn >> 16) & 0xf; | |
252 | int rm = insn & 0xf; | |
253 | int rs = (insn >> 8) & 0xf; | |
254 | ||
255 | register unsigned long rdv asm("r0") = regs->uregs[rd]; | |
256 | register unsigned long rnv asm("r2") = (rn == 15) ? pc | |
257 | : regs->uregs[rn]; | |
258 | register unsigned long rmv asm("r3") = (rm == 15) ? pc | |
259 | : regs->uregs[rm]; | |
260 | register unsigned long rsv asm("r1") = regs->uregs[rs]; | |
261 | unsigned long cpsr = regs->ARM_cpsr; | |
262 | ||
263 | __asm__ __volatile__ ( | |
264 | "msr cpsr_fs, %[cpsr] \n\t" | |
265 | BLX("%[fn]") | |
266 | "mrs %[cpsr], cpsr \n\t" | |
267 | : "=r" (rdv), [cpsr] "=r" (cpsr) | |
268 | : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), | |
269 | "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) | |
270 | : "lr", "memory", "cc" | |
271 | ); | |
272 | ||
273 | if (rd == 15) | |
274 | alu_write_pc(rdv, regs); | |
275 | else | |
276 | regs->uregs[rd] = rdv; | |
277 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); | |
278 | } | |
279 | ||
0e44e9a0 JM |
280 | static void __kprobes |
281 | emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |
282 | { | |
283 | kprobe_opcode_t insn = p->opcode; | |
284 | int rd = (insn >> 12) & 0xf; | |
285 | int rn = (insn >> 16) & 0xf; | |
286 | int rm = insn & 0xf; | |
287 | ||
288 | register unsigned long rdv asm("r0") = regs->uregs[rd]; | |
289 | register unsigned long rnv asm("r2") = regs->uregs[rn]; | |
290 | register unsigned long rmv asm("r3") = regs->uregs[rm]; | |
291 | unsigned long cpsr = regs->ARM_cpsr; | |
292 | ||
293 | __asm__ __volatile__ ( | |
294 | "msr cpsr_fs, %[cpsr] \n\t" | |
295 | BLX("%[fn]") | |
296 | "mrs %[cpsr], cpsr \n\t" | |
297 | : "=r" (rdv), [cpsr] "=r" (cpsr) | |
298 | : "0" (rdv), "r" (rnv), "r" (rmv), | |
299 | "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) | |
300 | : "lr", "memory", "cc" | |
301 | ); | |
302 | ||
303 | regs->uregs[rd] = rdv; | |
304 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); | |
305 | } | |
306 | ||
6091dfae JM |
307 | static void __kprobes |
308 | emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |
309 | { | |
310 | kprobe_opcode_t insn = p->opcode; | |
311 | int rd = (insn >> 16) & 0xf; | |
312 | int rn = (insn >> 12) & 0xf; | |
313 | int rm = insn & 0xf; | |
314 | int rs = (insn >> 8) & 0xf; | |
315 | ||
316 | register unsigned long rdv asm("r2") = regs->uregs[rd]; | |
317 | register unsigned long rnv asm("r0") = regs->uregs[rn]; | |
318 | register unsigned long rmv asm("r3") = regs->uregs[rm]; | |
319 | register unsigned long rsv asm("r1") = regs->uregs[rs]; | |
320 | unsigned long cpsr = regs->ARM_cpsr; | |
321 | ||
322 | __asm__ __volatile__ ( | |
323 | "msr cpsr_fs, %[cpsr] \n\t" | |
324 | BLX("%[fn]") | |
325 | "mrs %[cpsr], cpsr \n\t" | |
326 | : "=r" (rdv), [cpsr] "=r" (cpsr) | |
327 | : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), | |
328 | "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) | |
329 | : "lr", "memory", "cc" | |
330 | ); | |
331 | ||
332 | regs->uregs[rd] = rdv; | |
333 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); | |
334 | } | |
335 | ||
c82584eb JM |
336 | static void __kprobes |
337 | emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs) | |
338 | { | |
339 | kprobe_opcode_t insn = p->opcode; | |
340 | int rd = (insn >> 12) & 0xf; | |
341 | int rm = insn & 0xf; | |
342 | ||
343 | register unsigned long rdv asm("r0") = regs->uregs[rd]; | |
344 | register unsigned long rmv asm("r3") = regs->uregs[rm]; | |
345 | ||
346 | __asm__ __volatile__ ( | |
347 | BLX("%[fn]") | |
348 | : "=r" (rdv) | |
349 | : "0" (rdv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) | |
350 | : "lr", "memory", "cc" | |
351 | ); | |
352 | ||
353 | regs->uregs[rd] = rdv; | |
354 | } | |
355 | ||
12ce5d33 JM |
356 | static void __kprobes |
357 | emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |
358 | { | |
359 | kprobe_opcode_t insn = p->opcode; | |
360 | int rdlo = (insn >> 12) & 0xf; | |
361 | int rdhi = (insn >> 16) & 0xf; | |
362 | int rn = insn & 0xf; | |
363 | int rm = (insn >> 8) & 0xf; | |
364 | ||
365 | register unsigned long rdlov asm("r0") = regs->uregs[rdlo]; | |
366 | register unsigned long rdhiv asm("r2") = regs->uregs[rdhi]; | |
367 | register unsigned long rnv asm("r3") = regs->uregs[rn]; | |
368 | register unsigned long rmv asm("r1") = regs->uregs[rm]; | |
369 | unsigned long cpsr = regs->ARM_cpsr; | |
370 | ||
371 | __asm__ __volatile__ ( | |
372 | "msr cpsr_fs, %[cpsr] \n\t" | |
373 | BLX("%[fn]") | |
374 | "mrs %[cpsr], cpsr \n\t" | |
375 | : "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr) | |
376 | : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv), | |
377 | "2" (cpsr), [fn] "r" (p->ainsn.insn_fn) | |
378 | : "lr", "memory", "cc" | |
379 | ); | |
380 | ||
381 | regs->uregs[rdlo] = rdlov; | |
382 | regs->uregs[rdhi] = rdhiv; | |
383 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); | |
384 | } | |
385 | ||
35aa1df4 QB |
386 | /* |
387 | * For the instruction masking and comparisons in all the "space_*" | |
388 | * functions below, Do _not_ rearrange the order of tests unless | |
389 | * you're very, very sure of what you are doing. For the sake of | |
390 | * efficiency, the masks for some tests sometimes assume other test | |
391 | * have been done prior to them so the number of patterns to test | |
392 | * for an instruction set can be as broad as possible to reduce the | |
393 | * number of tests needed. | |
394 | */ | |
395 | ||
9a5c1284 JM |
396 | static const union decode_item arm_1111_table[] = { |
397 | /* Unconditional instructions */ | |
35aa1df4 | 398 | |
9a5c1284 JM |
399 | /* memory hint 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx */ |
400 | /* PLDI (immediate) 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx */ | |
401 | /* PLDW (immediate) 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx */ | |
402 | /* PLD (immediate) 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx */ | |
403 | DECODE_SIMULATE (0xfe300000, 0xf4100000, kprobe_simulate_nop), | |
35aa1df4 | 404 | |
0239269d JM |
405 | /* memory hint 1111 0110 x001 xxxx xxxx xxxx xxx0 xxxx */ |
406 | /* PLDI (register) 1111 0110 x101 xxxx xxxx xxxx xxx0 xxxx */ | |
407 | /* PLDW (register) 1111 0111 x001 xxxx xxxx xxxx xxx0 xxxx */ | |
408 | /* PLD (register) 1111 0111 x101 xxxx xxxx xxxx xxx0 xxxx */ | |
409 | DECODE_SIMULATE (0xfe300010, 0xf6100000, kprobe_simulate_nop), | |
410 | ||
9a5c1284 JM |
411 | /* BLX (immediate) 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx */ |
412 | DECODE_SIMULATE (0xfe000000, 0xfa000000, simulate_blx1), | |
72c2bab2 | 413 | |
9a5c1284 JM |
414 | /* CPS 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */ |
415 | /* SETEND 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */ | |
416 | /* SRS 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */ | |
417 | /* RFE 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */ | |
35aa1df4 | 418 | |
fa1a03b4 | 419 | /* Coprocessor instructions... */ |
9a5c1284 JM |
420 | /* MCRR2 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx */ |
421 | /* MRRC2 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx */ | |
422 | /* LDC2 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ | |
423 | /* STC2 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ | |
424 | /* CDP2 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ | |
425 | /* MCR2 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ | |
426 | /* MRC2 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ | |
427 | ||
428 | /* Other unallocated instructions... */ | |
429 | DECODE_END | |
430 | }; | |
35aa1df4 | 431 | |
75f115c0 JM |
432 | static const union decode_item arm_cccc_0001_0xx0____0xxx_table[] = { |
433 | /* Miscellaneous instructions */ | |
434 | ||
435 | /* MRS cpsr cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */ | |
436 | DECODE_SIMULATEX(0x0ff000f0, 0x01000000, simulate_mrs, | |
437 | REGS(0, NOPC, 0, 0, 0)), | |
438 | ||
439 | /* BX cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */ | |
440 | DECODE_SIMULATE (0x0ff000f0, 0x01200010, simulate_blx2bx), | |
441 | ||
442 | /* BLX (register) cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */ | |
443 | DECODE_SIMULATEX(0x0ff000f0, 0x01200030, simulate_blx2bx, | |
444 | REGS(0, 0, 0, 0, NOPC)), | |
445 | ||
446 | /* CLZ cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */ | |
c82584eb JM |
447 | DECODE_EMULATEX (0x0ff000f0, 0x01600010, emulate_rd12rm0_noflags_nopc, |
448 | REGS(0, NOPC, 0, 0, NOPC)), | |
75f115c0 JM |
449 | |
450 | /* QADD cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx */ | |
451 | /* QSUB cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx */ | |
452 | /* QDADD cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx */ | |
453 | /* QDSUB cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx */ | |
35fab774 JM |
454 | DECODE_EMULATEX (0x0f9000f0, 0x01000050, emulate_rd12rn16rm0_rwflags_nopc, |
455 | REGS(NOPC, NOPC, 0, 0, NOPC)), | |
75f115c0 JM |
456 | |
457 | /* BXJ cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */ | |
458 | /* MSR cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */ | |
459 | /* MRS spsr cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */ | |
460 | /* BKPT 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */ | |
461 | /* SMC cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */ | |
462 | /* And unallocated instructions... */ | |
463 | DECODE_END | |
464 | }; | |
465 | ||
466 | static const union decode_item arm_cccc_0001_0xx0____1xx0_table[] = { | |
467 | /* Halfword multiply and multiply-accumulate */ | |
468 | ||
469 | /* SMLALxy cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */ | |
12ce5d33 JM |
470 | DECODE_EMULATEX (0x0ff00090, 0x01400080, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, |
471 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | |
75f115c0 JM |
472 | |
473 | /* SMULWy cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */ | |
474 | DECODE_OR (0x0ff000b0, 0x012000a0), | |
475 | /* SMULxy cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */ | |
6091dfae JM |
476 | DECODE_EMULATEX (0x0ff00090, 0x01600080, emulate_rd16rn12rm0rs8_rwflags_nopc, |
477 | REGS(NOPC, 0, NOPC, 0, NOPC)), | |
75f115c0 JM |
478 | |
479 | /* SMLAxy cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx */ | |
480 | DECODE_OR (0x0ff00090, 0x01000080), | |
481 | /* SMLAWy cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx */ | |
6091dfae JM |
482 | DECODE_EMULATEX (0x0ff000b0, 0x01200080, emulate_rd16rn12rm0rs8_rwflags_nopc, |
483 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | |
75f115c0 JM |
484 | |
485 | DECODE_END | |
486 | }; | |
487 | ||
488 | static const union decode_item arm_cccc_0000_____1001_table[] = { | |
489 | /* Multiply and multiply-accumulate */ | |
490 | ||
491 | /* MUL cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx */ | |
492 | /* MULS cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx */ | |
6091dfae JM |
493 | DECODE_EMULATEX (0x0fe000f0, 0x00000090, emulate_rd16rn12rm0rs8_rwflags_nopc, |
494 | REGS(NOPC, 0, NOPC, 0, NOPC)), | |
75f115c0 JM |
495 | |
496 | /* MLA cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx */ | |
497 | /* MLAS cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx */ | |
498 | DECODE_OR (0x0fe000f0, 0x00200090), | |
499 | /* MLS cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx */ | |
6091dfae JM |
500 | DECODE_EMULATEX (0x0ff000f0, 0x00600090, emulate_rd16rn12rm0rs8_rwflags_nopc, |
501 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | |
75f115c0 JM |
502 | |
503 | /* UMAAL cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx */ | |
504 | DECODE_OR (0x0ff000f0, 0x00400090), | |
505 | /* UMULL cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx */ | |
506 | /* UMULLS cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx */ | |
507 | /* UMLAL cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx */ | |
508 | /* UMLALS cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx */ | |
509 | /* SMULL cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx */ | |
510 | /* SMULLS cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx */ | |
511 | /* SMLAL cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx */ | |
512 | /* SMLALS cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx */ | |
12ce5d33 JM |
513 | DECODE_EMULATEX (0x0f8000f0, 0x00800090, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, |
514 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | |
75f115c0 JM |
515 | |
516 | DECODE_END | |
517 | }; | |
518 | ||
519 | static const union decode_item arm_cccc_0001_____1001_table[] = { | |
520 | /* Synchronization primitives */ | |
521 | ||
b5bed7fe JMT |
522 | #if __LINUX_ARM_ARCH__ < 6 |
523 | /* Deprecated on ARMv6 and may be UNDEFINED on v7 */ | |
75f115c0 | 524 | /* SMP/SWPB cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */ |
35fab774 JM |
525 | DECODE_EMULATEX (0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc, |
526 | REGS(NOPC, NOPC, 0, 0, NOPC)), | |
b5bed7fe | 527 | #endif |
75f115c0 JM |
528 | /* LDREX/STREX{,D,B,H} cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */ |
529 | /* And unallocated instructions... */ | |
530 | DECODE_END | |
531 | }; | |
532 | ||
6c8a1929 | 533 | static const union decode_item arm_cccc_000x_____1xx1_table[] = { |
75f115c0 JM |
534 | /* Extra load/store instructions */ |
535 | ||
465f1ea5 JM |
536 | /* STRHT cccc 0000 xx10 xxxx xxxx xxxx 1011 xxxx */ |
537 | /* ??? cccc 0000 xx10 xxxx xxxx xxxx 11x1 xxxx */ | |
538 | /* LDRHT cccc 0000 xx11 xxxx xxxx xxxx 1011 xxxx */ | |
539 | /* LDRSBT cccc 0000 xx11 xxxx xxxx xxxx 1101 xxxx */ | |
540 | /* LDRSHT cccc 0000 xx11 xxxx xxxx xxxx 1111 xxxx */ | |
541 | DECODE_REJECT (0x0f200090, 0x00200090), | |
542 | ||
6c8a1929 JM |
543 | /* LDRD/STRD lr,pc,{... cccc 000x x0x0 xxxx 111x xxxx 1101 xxxx */ |
544 | DECODE_REJECT (0x0e10e0d0, 0x0000e0d0), | |
545 | ||
546 | /* LDRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1101 xxxx */ | |
547 | /* STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx */ | |
548 | DECODE_EMULATEX (0x0e5000d0, 0x000000d0, emulate_ldrdstrd, | |
549 | REGS(NOPCWB, NOPCX, 0, 0, NOPC)), | |
550 | ||
551 | /* LDRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1101 xxxx */ | |
552 | /* STRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1111 xxxx */ | |
553 | DECODE_EMULATEX (0x0e5000d0, 0x004000d0, emulate_ldrdstrd, | |
554 | REGS(NOPCWB, NOPCX, 0, 0, 0)), | |
555 | ||
75f115c0 | 556 | /* STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */ |
711bf106 JM |
557 | DECODE_EMULATEX (0x0e5000f0, 0x000000b0, emulate_str, |
558 | REGS(NOPCWB, NOPC, 0, 0, NOPC)), | |
559 | ||
75f115c0 JM |
560 | /* LDRH (register) cccc 000x x0x1 xxxx xxxx xxxx 1011 xxxx */ |
561 | /* LDRSB (register) cccc 000x x0x1 xxxx xxxx xxxx 1101 xxxx */ | |
562 | /* LDRSH (register) cccc 000x x0x1 xxxx xxxx xxxx 1111 xxxx */ | |
711bf106 JM |
563 | DECODE_EMULATEX (0x0e500090, 0x00100090, emulate_ldr, |
564 | REGS(NOPCWB, NOPC, 0, 0, NOPC)), | |
565 | ||
75f115c0 | 566 | /* STRH (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */ |
711bf106 JM |
567 | DECODE_EMULATEX (0x0e5000f0, 0x004000b0, emulate_str, |
568 | REGS(NOPCWB, NOPC, 0, 0, 0)), | |
569 | ||
75f115c0 JM |
570 | /* LDRH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1011 xxxx */ |
571 | /* LDRSB (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1101 xxxx */ | |
572 | /* LDRSH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1111 xxxx */ | |
711bf106 JM |
573 | DECODE_EMULATEX (0x0e500090, 0x00500090, emulate_ldr, |
574 | REGS(NOPCWB, NOPC, 0, 0, 0)), | |
75f115c0 | 575 | |
6c8a1929 JM |
576 | DECODE_END |
577 | }; | |
578 | ||
3535a89a JM |
579 | static const union decode_item arm_cccc_000x_table[] = { |
580 | /* Data-processing (register) */ | |
581 | ||
582 | /* <op>S PC, ... cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx */ | |
583 | DECODE_REJECT (0x0e10f000, 0x0010f000), | |
584 | ||
585 | /* MOV IP, SP 1110 0001 1010 0000 1100 0000 0000 1101 */ | |
586 | DECODE_SIMULATE (0xffffffff, 0xe1a0c00d, simulate_mov_ipsp), | |
587 | ||
588 | /* TST (register) cccc 0001 0001 xxxx xxxx xxxx xxx0 xxxx */ | |
589 | /* TEQ (register) cccc 0001 0011 xxxx xxxx xxxx xxx0 xxxx */ | |
590 | /* CMP (register) cccc 0001 0101 xxxx xxxx xxxx xxx0 xxxx */ | |
591 | /* CMN (register) cccc 0001 0111 xxxx xxxx xxxx xxx0 xxxx */ | |
592 | DECODE_EMULATEX (0x0f900010, 0x01100000, emulate_rd12rn16rm0rs8_rwflags, | |
593 | REGS(ANY, 0, 0, 0, ANY)), | |
594 | ||
595 | /* MOV (register) cccc 0001 101x xxxx xxxx xxxx xxx0 xxxx */ | |
596 | /* MVN (register) cccc 0001 111x xxxx xxxx xxxx xxx0 xxxx */ | |
597 | DECODE_EMULATEX (0x0fa00010, 0x01a00000, emulate_rd12rn16rm0rs8_rwflags, | |
598 | REGS(0, ANY, 0, 0, ANY)), | |
599 | ||
600 | /* AND (register) cccc 0000 000x xxxx xxxx xxxx xxx0 xxxx */ | |
601 | /* EOR (register) cccc 0000 001x xxxx xxxx xxxx xxx0 xxxx */ | |
602 | /* SUB (register) cccc 0000 010x xxxx xxxx xxxx xxx0 xxxx */ | |
603 | /* RSB (register) cccc 0000 011x xxxx xxxx xxxx xxx0 xxxx */ | |
604 | /* ADD (register) cccc 0000 100x xxxx xxxx xxxx xxx0 xxxx */ | |
605 | /* ADC (register) cccc 0000 101x xxxx xxxx xxxx xxx0 xxxx */ | |
606 | /* SBC (register) cccc 0000 110x xxxx xxxx xxxx xxx0 xxxx */ | |
607 | /* RSC (register) cccc 0000 111x xxxx xxxx xxxx xxx0 xxxx */ | |
608 | /* ORR (register) cccc 0001 100x xxxx xxxx xxxx xxx0 xxxx */ | |
609 | /* BIC (register) cccc 0001 110x xxxx xxxx xxxx xxx0 xxxx */ | |
610 | DECODE_EMULATEX (0x0e000010, 0x00000000, emulate_rd12rn16rm0rs8_rwflags, | |
611 | REGS(ANY, ANY, 0, 0, ANY)), | |
612 | ||
613 | /* TST (reg-shift reg) cccc 0001 0001 xxxx xxxx xxxx 0xx1 xxxx */ | |
614 | /* TEQ (reg-shift reg) cccc 0001 0011 xxxx xxxx xxxx 0xx1 xxxx */ | |
615 | /* CMP (reg-shift reg) cccc 0001 0101 xxxx xxxx xxxx 0xx1 xxxx */ | |
616 | /* CMN (reg-shift reg) cccc 0001 0111 xxxx xxxx xxxx 0xx1 xxxx */ | |
617 | DECODE_EMULATEX (0x0f900090, 0x01100010, emulate_rd12rn16rm0rs8_rwflags, | |
618 | REGS(ANY, 0, NOPC, 0, ANY)), | |
619 | ||
620 | /* MOV (reg-shift reg) cccc 0001 101x xxxx xxxx xxxx 0xx1 xxxx */ | |
621 | /* MVN (reg-shift reg) cccc 0001 111x xxxx xxxx xxxx 0xx1 xxxx */ | |
622 | DECODE_EMULATEX (0x0fa00090, 0x01a00010, emulate_rd12rn16rm0rs8_rwflags, | |
623 | REGS(0, ANY, NOPC, 0, ANY)), | |
624 | ||
625 | /* AND (reg-shift reg) cccc 0000 000x xxxx xxxx xxxx 0xx1 xxxx */ | |
626 | /* EOR (reg-shift reg) cccc 0000 001x xxxx xxxx xxxx 0xx1 xxxx */ | |
627 | /* SUB (reg-shift reg) cccc 0000 010x xxxx xxxx xxxx 0xx1 xxxx */ | |
628 | /* RSB (reg-shift reg) cccc 0000 011x xxxx xxxx xxxx 0xx1 xxxx */ | |
629 | /* ADD (reg-shift reg) cccc 0000 100x xxxx xxxx xxxx 0xx1 xxxx */ | |
630 | /* ADC (reg-shift reg) cccc 0000 101x xxxx xxxx xxxx 0xx1 xxxx */ | |
631 | /* SBC (reg-shift reg) cccc 0000 110x xxxx xxxx xxxx 0xx1 xxxx */ | |
632 | /* RSC (reg-shift reg) cccc 0000 111x xxxx xxxx xxxx 0xx1 xxxx */ | |
633 | /* ORR (reg-shift reg) cccc 0001 100x xxxx xxxx xxxx 0xx1 xxxx */ | |
634 | /* BIC (reg-shift reg) cccc 0001 110x xxxx xxxx xxxx 0xx1 xxxx */ | |
635 | DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags, | |
636 | REGS(ANY, ANY, NOPC, 0, ANY)), | |
637 | ||
638 | DECODE_END | |
639 | }; | |
640 | ||
c038f3af JM |
641 | static const union decode_item arm_cccc_001x_table[] = { |
642 | /* Data-processing (immediate) */ | |
643 | ||
644 | /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */ | |
645 | /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */ | |
c82584eb JM |
646 | DECODE_EMULATEX (0x0fb00000, 0x03000000, emulate_rd12rm0_noflags_nopc, |
647 | REGS(0, NOPC, 0, 0, 0)), | |
c038f3af JM |
648 | |
649 | /* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */ | |
650 | DECODE_OR (0x0fff00ff, 0x03200001), | |
651 | /* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */ | |
652 | DECODE_EMULATE (0x0fff00ff, 0x03200004, kprobe_emulate_none), | |
653 | /* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */ | |
654 | /* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */ | |
655 | /* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */ | |
656 | DECODE_SIMULATE (0x0fff00fc, 0x03200000, kprobe_simulate_nop), | |
657 | /* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */ | |
658 | /* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */ | |
659 | /* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */ | |
660 | DECODE_REJECT (0x0fb00000, 0x03200000), | |
661 | ||
662 | /* <op>S PC, ... cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx */ | |
663 | DECODE_REJECT (0x0e10f000, 0x0210f000), | |
664 | ||
665 | /* TST (immediate) cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx */ | |
666 | /* TEQ (immediate) cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx */ | |
667 | /* CMP (immediate) cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx */ | |
668 | /* CMN (immediate) cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx */ | |
669 | DECODE_EMULATEX (0x0f900000, 0x03100000, emulate_rd12rn16rm0rs8_rwflags, | |
670 | REGS(ANY, 0, 0, 0, 0)), | |
671 | ||
672 | /* MOV (immediate) cccc 0011 101x xxxx xxxx xxxx xxxx xxxx */ | |
673 | /* MVN (immediate) cccc 0011 111x xxxx xxxx xxxx xxxx xxxx */ | |
674 | DECODE_EMULATEX (0x0fa00000, 0x03a00000, emulate_rd12rn16rm0rs8_rwflags, | |
675 | REGS(0, ANY, 0, 0, 0)), | |
676 | ||
677 | /* AND (immediate) cccc 0010 000x xxxx xxxx xxxx xxxx xxxx */ | |
678 | /* EOR (immediate) cccc 0010 001x xxxx xxxx xxxx xxxx xxxx */ | |
679 | /* SUB (immediate) cccc 0010 010x xxxx xxxx xxxx xxxx xxxx */ | |
680 | /* RSB (immediate) cccc 0010 011x xxxx xxxx xxxx xxxx xxxx */ | |
681 | /* ADD (immediate) cccc 0010 100x xxxx xxxx xxxx xxxx xxxx */ | |
682 | /* ADC (immediate) cccc 0010 101x xxxx xxxx xxxx xxxx xxxx */ | |
683 | /* SBC (immediate) cccc 0010 110x xxxx xxxx xxxx xxxx xxxx */ | |
684 | /* RSC (immediate) cccc 0010 111x xxxx xxxx xxxx xxxx xxxx */ | |
685 | /* ORR (immediate) cccc 0011 100x xxxx xxxx xxxx xxxx xxxx */ | |
686 | /* BIC (immediate) cccc 0011 110x xxxx xxxx xxxx xxxx xxxx */ | |
687 | DECODE_EMULATEX (0x0e000000, 0x02000000, emulate_rd12rn16rm0rs8_rwflags, | |
688 | REGS(ANY, ANY, 0, 0, 0)), | |
94254930 | 689 | |
c038f3af JM |
690 | DECODE_END |
691 | }; | |
35aa1df4 | 692 | |
2ce5d033 JM |
693 | static const union decode_item arm_cccc_0110_____xxx1_table[] = { |
694 | /* Media instructions */ | |
695 | ||
696 | /* SEL cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx */ | |
697 | DECODE_EMULATEX (0x0ff000f0, 0x068000b0, emulate_rd12rn16rm0_rwflags_nopc, | |
698 | REGS(NOPC, NOPC, 0, 0, NOPC)), | |
699 | ||
700 | /* SSAT cccc 0110 101x xxxx xxxx xxxx xx01 xxxx */ | |
701 | /* USAT cccc 0110 111x xxxx xxxx xxxx xx01 xxxx */ | |
702 | DECODE_OR(0x0fa00030, 0x06a00010), | |
703 | /* SSAT16 cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx */ | |
704 | /* USAT16 cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx */ | |
705 | DECODE_EMULATEX (0x0fb000f0, 0x06a00030, emulate_rd12rn16rm0_rwflags_nopc, | |
706 | REGS(0, NOPC, 0, 0, NOPC)), | |
707 | ||
708 | /* REV cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */ | |
709 | /* REV16 cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */ | |
710 | /* RBIT cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */ | |
711 | /* REVSH cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */ | |
c82584eb JM |
712 | DECODE_EMULATEX (0x0fb00070, 0x06b00030, emulate_rd12rm0_noflags_nopc, |
713 | REGS(0, NOPC, 0, 0, NOPC)), | |
2ce5d033 JM |
714 | |
715 | /* ??? cccc 0110 0x00 xxxx xxxx xxxx xxx1 xxxx */ | |
716 | DECODE_REJECT (0x0fb00010, 0x06000010), | |
717 | /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1011 xxxx */ | |
718 | DECODE_REJECT (0x0f8000f0, 0x060000b0), | |
719 | /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1101 xxxx */ | |
720 | DECODE_REJECT (0x0f8000f0, 0x060000d0), | |
721 | /* SADD16 cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx */ | |
722 | /* SADDSUBX cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx */ | |
723 | /* SSUBADDX cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx */ | |
724 | /* SSUB16 cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx */ | |
725 | /* SADD8 cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx */ | |
726 | /* SSUB8 cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx */ | |
727 | /* QADD16 cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx */ | |
728 | /* QADDSUBX cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx */ | |
729 | /* QSUBADDX cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx */ | |
730 | /* QSUB16 cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx */ | |
731 | /* QADD8 cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx */ | |
732 | /* QSUB8 cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx */ | |
733 | /* SHADD16 cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx */ | |
734 | /* SHADDSUBX cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx */ | |
735 | /* SHSUBADDX cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx */ | |
736 | /* SHSUB16 cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx */ | |
737 | /* SHADD8 cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx */ | |
738 | /* SHSUB8 cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx */ | |
739 | /* UADD16 cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx */ | |
740 | /* UADDSUBX cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx */ | |
741 | /* USUBADDX cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx */ | |
742 | /* USUB16 cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx */ | |
743 | /* UADD8 cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx */ | |
744 | /* USUB8 cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx */ | |
745 | /* UQADD16 cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx */ | |
746 | /* UQADDSUBX cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx */ | |
747 | /* UQSUBADDX cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx */ | |
748 | /* UQSUB16 cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx */ | |
749 | /* UQADD8 cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx */ | |
750 | /* UQSUB8 cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx */ | |
751 | /* UHADD16 cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx */ | |
752 | /* UHADDSUBX cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx */ | |
753 | /* UHSUBADDX cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx */ | |
754 | /* UHSUB16 cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx */ | |
755 | /* UHADD8 cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx */ | |
756 | /* UHSUB8 cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx */ | |
35fab774 JM |
757 | DECODE_EMULATEX (0x0f800010, 0x06000010, emulate_rd12rn16rm0_rwflags_nopc, |
758 | REGS(NOPC, NOPC, 0, 0, NOPC)), | |
2ce5d033 JM |
759 | |
760 | /* PKHBT cccc 0110 1000 xxxx xxxx xxxx x001 xxxx */ | |
761 | /* PKHTB cccc 0110 1000 xxxx xxxx xxxx x101 xxxx */ | |
35fab774 JM |
762 | DECODE_EMULATEX (0x0ff00030, 0x06800010, emulate_rd12rn16rm0_rwflags_nopc, |
763 | REGS(NOPC, NOPC, 0, 0, NOPC)), | |
2ce5d033 JM |
764 | |
765 | /* ??? cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx */ | |
766 | /* ??? cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx */ | |
767 | DECODE_REJECT (0x0fb000f0, 0x06900070), | |
768 | ||
769 | /* SXTB16 cccc 0110 1000 1111 xxxx xxxx 0111 xxxx */ | |
770 | /* SXTB cccc 0110 1010 1111 xxxx xxxx 0111 xxxx */ | |
771 | /* SXTH cccc 0110 1011 1111 xxxx xxxx 0111 xxxx */ | |
772 | /* UXTB16 cccc 0110 1100 1111 xxxx xxxx 0111 xxxx */ | |
773 | /* UXTB cccc 0110 1110 1111 xxxx xxxx 0111 xxxx */ | |
774 | /* UXTH cccc 0110 1111 1111 xxxx xxxx 0111 xxxx */ | |
c82584eb JM |
775 | DECODE_EMULATEX (0x0f8f00f0, 0x068f0070, emulate_rd12rm0_noflags_nopc, |
776 | REGS(0, NOPC, 0, 0, NOPC)), | |
2ce5d033 JM |
777 | |
778 | /* SXTAB16 cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx */ | |
779 | /* SXTAB cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx */ | |
780 | /* SXTAH cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx */ | |
781 | /* UXTAB16 cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx */ | |
782 | /* UXTAB cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx */ | |
783 | /* UXTAH cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx */ | |
35fab774 JM |
784 | DECODE_EMULATEX (0x0f8000f0, 0x06800070, emulate_rd12rn16rm0_rwflags_nopc, |
785 | REGS(NOPCX, NOPC, 0, 0, NOPC)), | |
780b5c11 | 786 | |
2ce5d033 JM |
787 | DECODE_END |
788 | }; | |
35aa1df4 | 789 | |
ad2e81a7 JM |
790 | static const union decode_item arm_cccc_0111_____xxx1_table[] = { |
791 | /* Media instructions */ | |
35aa1df4 | 792 | |
ad2e81a7 JM |
793 | /* UNDEFINED cccc 0111 1111 xxxx xxxx xxxx 1111 xxxx */ |
794 | DECODE_REJECT (0x0ff000f0, 0x07f000f0), | |
038c3839 | 795 | |
ad2e81a7 JM |
796 | /* SMLALD cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */ |
797 | /* SMLSLD cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */ | |
12ce5d33 JM |
798 | DECODE_EMULATEX (0x0ff00090, 0x07400010, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, |
799 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | |
35aa1df4 | 800 | |
ad2e81a7 JM |
801 | /* SMUAD cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx */ |
802 | /* SMUSD cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx */ | |
803 | DECODE_OR (0x0ff0f090, 0x0700f010), | |
804 | /* SMMUL cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx */ | |
805 | DECODE_OR (0x0ff0f0d0, 0x0750f010), | |
806 | /* USAD8 cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */ | |
6091dfae JM |
807 | DECODE_EMULATEX (0x0ff0f0f0, 0x0780f010, emulate_rd16rn12rm0rs8_rwflags_nopc, |
808 | REGS(NOPC, 0, NOPC, 0, NOPC)), | |
20e8155e | 809 | |
ad2e81a7 JM |
810 | /* SMLAD cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx */ |
811 | /* SMLSD cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx */ | |
812 | DECODE_OR (0x0ff00090, 0x07000010), | |
813 | /* SMMLA cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx */ | |
814 | DECODE_OR (0x0ff000d0, 0x07500010), | |
815 | /* USADA8 cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */ | |
6091dfae JM |
816 | DECODE_EMULATEX (0x0ff000f0, 0x07800010, emulate_rd16rn12rm0rs8_rwflags_nopc, |
817 | REGS(NOPC, NOPCX, NOPC, 0, NOPC)), | |
20e8155e | 818 | |
ad2e81a7 | 819 | /* SMMLS cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx */ |
6091dfae JM |
820 | DECODE_EMULATEX (0x0ff000d0, 0x075000d0, emulate_rd16rn12rm0rs8_rwflags_nopc, |
821 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | |
20e8155e | 822 | |
ad2e81a7 JM |
823 | /* SBFX cccc 0111 101x xxxx xxxx xxxx x101 xxxx */ |
824 | /* UBFX cccc 0111 111x xxxx xxxx xxxx x101 xxxx */ | |
c82584eb JM |
825 | DECODE_EMULATEX (0x0fa00070, 0x07a00050, emulate_rd12rm0_noflags_nopc, |
826 | REGS(0, NOPC, 0, 0, NOPC)), | |
ad2e81a7 JM |
827 | |
828 | /* BFC cccc 0111 110x xxxx xxxx xxxx x001 1111 */ | |
c82584eb JM |
829 | DECODE_EMULATEX (0x0fe0007f, 0x07c0001f, emulate_rd12rm0_noflags_nopc, |
830 | REGS(0, NOPC, 0, 0, 0)), | |
ad2e81a7 JM |
831 | |
832 | /* BFI cccc 0111 110x xxxx xxxx xxxx x001 xxxx */ | |
c82584eb JM |
833 | DECODE_EMULATEX (0x0fe00070, 0x07c00010, emulate_rd12rm0_noflags_nopc, |
834 | REGS(0, NOPC, 0, 0, NOPCX)), | |
ad2e81a7 JM |
835 | |
836 | DECODE_END | |
837 | }; | |
35aa1df4 | 838 | |
56d8fbdd JM |
839 | static const union decode_item arm_cccc_01xx_table[] = { |
840 | /* Load/store word and unsigned byte */ | |
841 | ||
842 | /* LDRB/STRB pc,[...] cccc 01xx x0xx xxxx xxxx xxxx xxxx xxxx */ | |
843 | DECODE_REJECT (0x0c40f000, 0x0440f000), | |
844 | ||
465f1ea5 JM |
845 | /* STRT cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */ |
846 | /* LDRT cccc 01x0 x011 xxxx xxxx xxxx xxxx xxxx */ | |
847 | /* STRBT cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */ | |
848 | /* LDRBT cccc 01x0 x111 xxxx xxxx xxxx xxxx xxxx */ | |
849 | DECODE_REJECT (0x0d200000, 0x04200000), | |
850 | ||
711bf106 JM |
851 | /* STR (immediate) cccc 010x x0x0 xxxx xxxx xxxx xxxx xxxx */ |
852 | /* STRB (immediate) cccc 010x x1x0 xxxx xxxx xxxx xxxx xxxx */ | |
853 | DECODE_EMULATEX (0x0e100000, 0x04000000, emulate_str, | |
854 | REGS(NOPCWB, ANY, 0, 0, 0)), | |
855 | ||
856 | /* LDR (immediate) cccc 010x x0x1 xxxx xxxx xxxx xxxx xxxx */ | |
857 | /* LDRB (immediate) cccc 010x x1x1 xxxx xxxx xxxx xxxx xxxx */ | |
858 | DECODE_EMULATEX (0x0e100000, 0x04100000, emulate_ldr, | |
859 | REGS(NOPCWB, ANY, 0, 0, 0)), | |
860 | ||
861 | /* STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx */ | |
862 | /* STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx */ | |
863 | DECODE_EMULATEX (0x0e100000, 0x06000000, emulate_str, | |
864 | REGS(NOPCWB, ANY, 0, 0, NOPC)), | |
865 | ||
866 | /* LDR (register) cccc 011x x0x1 xxxx xxxx xxxx xxxx xxxx */ | |
867 | /* LDRB (register) cccc 011x x1x1 xxxx xxxx xxxx xxxx xxxx */ | |
868 | DECODE_EMULATEX (0x0e100000, 0x06100000, emulate_ldr, | |
869 | REGS(NOPCWB, ANY, 0, 0, NOPC)), | |
56d8fbdd JM |
870 | |
871 | DECODE_END | |
872 | }; | |
35aa1df4 | 873 | |
0d32e7d1 JM |
874 | static const union decode_item arm_cccc_100x_table[] = { |
875 | /* Block data transfer instructions */ | |
876 | ||
877 | /* LDM cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */ | |
878 | /* STM cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */ | |
879 | DECODE_CUSTOM (0x0e400000, 0x08000000, kprobe_decode_ldmstm), | |
880 | ||
881 | /* STM (user registers) cccc 100x x1x0 xxxx xxxx xxxx xxxx xxxx */ | |
882 | /* LDM (user registers) cccc 100x x1x1 xxxx 0xxx xxxx xxxx xxxx */ | |
883 | /* LDM (exception ret) cccc 100x x1x1 xxxx 1xxx xxxx xxxx xxxx */ | |
884 | DECODE_END | |
885 | }; | |
35aa1df4 | 886 | |
e9a92859 JM |
887 | const union decode_item kprobe_decode_arm_table[] = { |
888 | /* | |
889 | * Unconditional instructions | |
890 | * 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx | |
891 | */ | |
892 | DECODE_TABLE (0xf0000000, 0xf0000000, arm_1111_table), | |
893 | ||
894 | /* | |
895 | * Miscellaneous instructions | |
896 | * cccc 0001 0xx0 xxxx xxxx xxxx 0xxx xxxx | |
897 | */ | |
898 | DECODE_TABLE (0x0f900080, 0x01000000, arm_cccc_0001_0xx0____0xxx_table), | |
899 | ||
900 | /* | |
901 | * Halfword multiply and multiply-accumulate | |
902 | * cccc 0001 0xx0 xxxx xxxx xxxx 1xx0 xxxx | |
903 | */ | |
904 | DECODE_TABLE (0x0f900090, 0x01000080, arm_cccc_0001_0xx0____1xx0_table), | |
905 | ||
906 | /* | |
907 | * Multiply and multiply-accumulate | |
908 | * cccc 0000 xxxx xxxx xxxx xxxx 1001 xxxx | |
909 | */ | |
910 | DECODE_TABLE (0x0f0000f0, 0x00000090, arm_cccc_0000_____1001_table), | |
911 | ||
912 | /* | |
913 | * Synchronization primitives | |
914 | * cccc 0001 xxxx xxxx xxxx xxxx 1001 xxxx | |
915 | */ | |
916 | DECODE_TABLE (0x0f0000f0, 0x01000090, arm_cccc_0001_____1001_table), | |
917 | ||
918 | /* | |
919 | * Extra load/store instructions | |
920 | * cccc 000x xxxx xxxx xxxx xxxx 1xx1 xxxx | |
921 | */ | |
922 | DECODE_TABLE (0x0e000090, 0x00000090, arm_cccc_000x_____1xx1_table), | |
923 | ||
924 | /* | |
925 | * Data-processing (register) | |
926 | * cccc 000x xxxx xxxx xxxx xxxx xxx0 xxxx | |
927 | * Data-processing (register-shifted register) | |
928 | * cccc 000x xxxx xxxx xxxx xxxx 0xx1 xxxx | |
929 | */ | |
930 | DECODE_TABLE (0x0e000000, 0x00000000, arm_cccc_000x_table), | |
931 | ||
932 | /* | |
933 | * Data-processing (immediate) | |
934 | * cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx | |
935 | */ | |
936 | DECODE_TABLE (0x0e000000, 0x02000000, arm_cccc_001x_table), | |
937 | ||
938 | /* | |
939 | * Media instructions | |
940 | * cccc 011x xxxx xxxx xxxx xxxx xxx1 xxxx | |
941 | */ | |
942 | DECODE_TABLE (0x0f000010, 0x06000010, arm_cccc_0110_____xxx1_table), | |
943 | DECODE_TABLE (0x0f000010, 0x07000010, arm_cccc_0111_____xxx1_table), | |
944 | ||
945 | /* | |
946 | * Load/store word and unsigned byte | |
947 | * cccc 01xx xxxx xxxx xxxx xxxx xxxx xxxx | |
948 | */ | |
949 | DECODE_TABLE (0x0c000000, 0x04000000, arm_cccc_01xx_table), | |
950 | ||
951 | /* | |
952 | * Block data transfer instructions | |
953 | * cccc 100x xxxx xxxx xxxx xxxx xxxx xxxx | |
954 | */ | |
955 | DECODE_TABLE (0x0e000000, 0x08000000, arm_cccc_100x_table), | |
956 | ||
957 | /* B cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */ | |
958 | /* BL cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */ | |
959 | DECODE_SIMULATE (0x0e000000, 0x0a000000, simulate_bbl), | |
960 | ||
961 | /* | |
962 | * Supervisor Call, and coprocessor instructions | |
963 | */ | |
964 | ||
965 | /* MCRR cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx */ | |
966 | /* MRRC cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx */ | |
967 | /* LDC cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ | |
968 | /* STC cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ | |
969 | /* CDP cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ | |
970 | /* MCR cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ | |
971 | /* MRC cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ | |
972 | /* SVC cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */ | |
973 | DECODE_REJECT (0x0c000000, 0x0c000000), | |
35aa1df4 | 974 | |
e9a92859 JM |
975 | DECODE_END |
976 | }; | |
2c89240b JM |
977 | #ifdef CONFIG_ARM_KPROBES_TEST_MODULE |
978 | EXPORT_SYMBOL_GPL(kprobe_decode_arm_table); | |
979 | #endif | |
35aa1df4 | 980 | |
c6a7d97d JM |
981 | static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs) |
982 | { | |
983 | regs->ARM_pc += 4; | |
984 | p->ainsn.insn_handler(p, regs); | |
985 | } | |
986 | ||
35aa1df4 QB |
987 | /* Return: |
988 | * INSN_REJECTED If instruction is one not allowed to kprobe, | |
989 | * INSN_GOOD If instruction is supported and uses instruction slot, | |
990 | * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot. | |
991 | * | |
992 | * For instructions we don't want to kprobe (INSN_REJECTED return result): | |
993 | * These are generally ones that modify the processor state making | |
994 | * them "hard" to simulate such as switches processor modes or | |
995 | * make accesses in alternate modes. Any of these could be simulated | |
996 | * if the work was put into it, but low return considering they | |
997 | * should also be very rare. | |
998 | */ | |
999 | enum kprobe_insn __kprobes | |
1000 | arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |
1001 | { | |
c6a7d97d | 1002 | asi->insn_singlestep = arm_singlestep; |
0ab4c02d | 1003 | asi->insn_check_cc = kprobe_condition_checks[insn>>28]; |
e9a92859 | 1004 | return kprobe_decode_insn(insn, asi, kprobe_decode_arm_table, false); |
35aa1df4 | 1005 | } |