ARM: use a function table for determining instruction interpreter action
[firefly-linux-kernel-4.4.55.git] / arch / arm / kernel / kprobes-thumb.c
1 /*
2  * arch/arm/kernel/kprobes-thumb.c
3  *
4  * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
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
11 #include <linux/types.h>
12 #include <linux/kernel.h>
13 #include <linux/ptrace.h>
14 #include <linux/kprobes.h>
15
16 #include "kprobes.h"
17 #include "probes-thumb.h"
18
19 /* These emulation encodings are functionally equivalent... */
20 #define t32_emulate_rd8rn16rm0ra12_noflags \
21                 t32_emulate_rdlo12rdhi8rn16rm0_noflags
22
23 /*
24  * Return the PC value for a probe in thumb code.
25  * This is the address of the probed instruction plus 4.
26  * We subtract one because the address will have bit zero set to indicate
27  * a pointer to thumb code.
28  */
29 static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p)
30 {
31         return (unsigned long)p->addr - 1 + 4;
32 }
33
34 /* t32 thumb actions */
35
36 static void __kprobes
37 t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs)
38 {
39         kprobe_opcode_t insn = p->opcode;
40         unsigned long pc = thumb_probe_pc(p);
41         int rn = (insn >> 16) & 0xf;
42         int rm = insn & 0xf;
43
44         unsigned long rnv = (rn == 15) ? pc : regs->uregs[rn];
45         unsigned long rmv = regs->uregs[rm];
46         unsigned int halfwords;
47
48         if (insn & 0x10) /* TBH */
49                 halfwords = ((u16 *)rnv)[rmv];
50         else /* TBB */
51                 halfwords = ((u8 *)rnv)[rmv];
52
53         regs->ARM_pc = pc + 2 * halfwords;
54 }
55
56 static void __kprobes
57 t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs)
58 {
59         kprobe_opcode_t insn = p->opcode;
60         int rd = (insn >> 8) & 0xf;
61         unsigned long mask = 0xf8ff03df; /* Mask out execution state */
62         regs->uregs[rd] = regs->ARM_cpsr & mask;
63 }
64
65 static void __kprobes
66 t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
67 {
68         kprobe_opcode_t insn = p->opcode;
69         unsigned long pc = thumb_probe_pc(p);
70
71         long offset = insn & 0x7ff;             /* imm11 */
72         offset += (insn & 0x003f0000) >> 5;     /* imm6 */
73         offset += (insn & 0x00002000) << 4;     /* J1 */
74         offset += (insn & 0x00000800) << 7;     /* J2 */
75         offset -= (insn & 0x04000000) >> 7;     /* Apply sign bit */
76
77         regs->ARM_pc = pc + (offset * 2);
78 }
79
80 static enum kprobe_insn __kprobes
81 t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
82                 const struct decode_header *d)
83 {
84         int cc = (insn >> 22) & 0xf;
85         asi->insn_check_cc = kprobe_condition_checks[cc];
86         asi->insn_handler = t32_simulate_cond_branch;
87         return INSN_GOOD_NO_SLOT;
88 }
89
90 static void __kprobes
91 t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
92 {
93         kprobe_opcode_t insn = p->opcode;
94         unsigned long pc = thumb_probe_pc(p);
95
96         long offset = insn & 0x7ff;             /* imm11 */
97         offset += (insn & 0x03ff0000) >> 5;     /* imm10 */
98         offset += (insn & 0x00002000) << 9;     /* J1 */
99         offset += (insn & 0x00000800) << 10;    /* J2 */
100         if (insn & 0x04000000)
101                 offset -= 0x00800000; /* Apply sign bit */
102         else
103                 offset ^= 0x00600000; /* Invert J1 and J2 */
104
105         if (insn & (1 << 14)) {
106                 /* BL or BLX */
107                 regs->ARM_lr = (unsigned long)p->addr + 4;
108                 if (!(insn & (1 << 12))) {
109                         /* BLX so switch to ARM mode */
110                         regs->ARM_cpsr &= ~PSR_T_BIT;
111                         pc &= ~3;
112                 }
113         }
114
115         regs->ARM_pc = pc + (offset * 2);
116 }
117
118 static void __kprobes
119 t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
120 {
121         kprobe_opcode_t insn = p->opcode;
122         unsigned long addr = thumb_probe_pc(p) & ~3;
123         int rt = (insn >> 12) & 0xf;
124         unsigned long rtv;
125
126         long offset = insn & 0xfff;
127         if (insn & 0x00800000)
128                 addr += offset;
129         else
130                 addr -= offset;
131
132         if (insn & 0x00400000) {
133                 /* LDR */
134                 rtv = *(unsigned long *)addr;
135                 if (rt == 15) {
136                         bx_write_pc(rtv, regs);
137                         return;
138                 }
139         } else if (insn & 0x00200000) {
140                 /* LDRH */
141                 if (insn & 0x01000000)
142                         rtv = *(s16 *)addr;
143                 else
144                         rtv = *(u16 *)addr;
145         } else {
146                 /* LDRB */
147                 if (insn & 0x01000000)
148                         rtv = *(s8 *)addr;
149                 else
150                         rtv = *(u8 *)addr;
151         }
152
153         regs->uregs[rt] = rtv;
154 }
155
156 static enum kprobe_insn __kprobes
157 t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
158                 const struct decode_header *d)
159 {
160         enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi, d);
161
162         /* Fixup modified instruction to have halfwords in correct order...*/
163         insn = asi->insn[0];
164         ((u16 *)asi->insn)[0] = insn >> 16;
165         ((u16 *)asi->insn)[1] = insn & 0xffff;
166
167         return ret;
168 }
169
170 static void __kprobes
171 t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
172 {
173         kprobe_opcode_t insn = p->opcode;
174         unsigned long pc = thumb_probe_pc(p) & ~3;
175         int rt1 = (insn >> 12) & 0xf;
176         int rt2 = (insn >> 8) & 0xf;
177         int rn = (insn >> 16) & 0xf;
178
179         register unsigned long rt1v asm("r0") = regs->uregs[rt1];
180         register unsigned long rt2v asm("r1") = regs->uregs[rt2];
181         register unsigned long rnv asm("r2") = (rn == 15) ? pc
182                                                           : regs->uregs[rn];
183
184         __asm__ __volatile__ (
185                 "blx    %[fn]"
186                 : "=r" (rt1v), "=r" (rt2v), "=r" (rnv)
187                 : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (p->ainsn.insn_fn)
188                 : "lr", "memory", "cc"
189         );
190
191         if (rn != 15)
192                 regs->uregs[rn] = rnv; /* Writeback base register */
193         regs->uregs[rt1] = rt1v;
194         regs->uregs[rt2] = rt2v;
195 }
196
197 static void __kprobes
198 t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs)
199 {
200         kprobe_opcode_t insn = p->opcode;
201         int rt = (insn >> 12) & 0xf;
202         int rn = (insn >> 16) & 0xf;
203         int rm = insn & 0xf;
204
205         register unsigned long rtv asm("r0") = regs->uregs[rt];
206         register unsigned long rnv asm("r2") = regs->uregs[rn];
207         register unsigned long rmv asm("r3") = regs->uregs[rm];
208
209         __asm__ __volatile__ (
210                 "blx    %[fn]"
211                 : "=r" (rtv), "=r" (rnv)
212                 : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
213                 : "lr", "memory", "cc"
214         );
215
216         regs->uregs[rn] = rnv; /* Writeback base register */
217         if (rt == 15) /* Can't be true for a STR as they aren't allowed */
218                 bx_write_pc(rtv, regs);
219         else
220                 regs->uregs[rt] = rtv;
221 }
222
223 static void __kprobes
224 t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
225 {
226         kprobe_opcode_t insn = p->opcode;
227         int rd = (insn >> 8) & 0xf;
228         int rn = (insn >> 16) & 0xf;
229         int rm = insn & 0xf;
230
231         register unsigned long rdv asm("r1") = regs->uregs[rd];
232         register unsigned long rnv asm("r2") = regs->uregs[rn];
233         register unsigned long rmv asm("r3") = regs->uregs[rm];
234         unsigned long cpsr = regs->ARM_cpsr;
235
236         __asm__ __volatile__ (
237                 "msr    cpsr_fs, %[cpsr]        \n\t"
238                 "blx    %[fn]                   \n\t"
239                 "mrs    %[cpsr], cpsr           \n\t"
240                 : "=r" (rdv), [cpsr] "=r" (cpsr)
241                 : "0" (rdv), "r" (rnv), "r" (rmv),
242                   "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
243                 : "lr", "memory", "cc"
244         );
245
246         regs->uregs[rd] = rdv;
247         regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
248 }
249
250 static void __kprobes
251 t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs)
252 {
253         kprobe_opcode_t insn = p->opcode;
254         unsigned long pc = thumb_probe_pc(p);
255         int rd = (insn >> 8) & 0xf;
256
257         register unsigned long rdv asm("r1") = regs->uregs[rd];
258         register unsigned long rnv asm("r2") = pc & ~3;
259
260         __asm__ __volatile__ (
261                 "blx    %[fn]"
262                 : "=r" (rdv)
263                 : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn)
264                 : "lr", "memory", "cc"
265         );
266
267         regs->uregs[rd] = rdv;
268 }
269
270 static void __kprobes
271 t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs)
272 {
273         kprobe_opcode_t insn = p->opcode;
274         int rd = (insn >> 8) & 0xf;
275         int rn = (insn >> 16) & 0xf;
276
277         register unsigned long rdv asm("r1") = regs->uregs[rd];
278         register unsigned long rnv asm("r2") = regs->uregs[rn];
279
280         __asm__ __volatile__ (
281                 "blx    %[fn]"
282                 : "=r" (rdv)
283                 : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn)
284                 : "lr", "memory", "cc"
285         );
286
287         regs->uregs[rd] = rdv;
288 }
289
290 static void __kprobes
291 t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs)
292 {
293         kprobe_opcode_t insn = p->opcode;
294         int rdlo = (insn >> 12) & 0xf;
295         int rdhi = (insn >> 8) & 0xf;
296         int rn = (insn >> 16) & 0xf;
297         int rm = insn & 0xf;
298
299         register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
300         register unsigned long rdhiv asm("r1") = regs->uregs[rdhi];
301         register unsigned long rnv asm("r2") = regs->uregs[rn];
302         register unsigned long rmv asm("r3") = regs->uregs[rm];
303
304         __asm__ __volatile__ (
305                 "blx    %[fn]"
306                 : "=r" (rdlov), "=r" (rdhiv)
307                 : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
308                   [fn] "r" (p->ainsn.insn_fn)
309                 : "lr", "memory", "cc"
310         );
311
312         regs->uregs[rdlo] = rdlov;
313         regs->uregs[rdhi] = rdhiv;
314 }
315 /* t16 thumb actions */
316
317 static void __kprobes
318 t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs)
319 {
320         kprobe_opcode_t insn = p->opcode;
321         unsigned long pc = thumb_probe_pc(p);
322         int rm = (insn >> 3) & 0xf;
323         unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm];
324
325         if (insn & (1 << 7)) /* BLX ? */
326                 regs->ARM_lr = (unsigned long)p->addr + 2;
327
328         bx_write_pc(rmv, regs);
329 }
330
331 static void __kprobes
332 t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
333 {
334         kprobe_opcode_t insn = p->opcode;
335         unsigned long* base = (unsigned long *)(thumb_probe_pc(p) & ~3);
336         long index = insn & 0xff;
337         int rt = (insn >> 8) & 0x7;
338         regs->uregs[rt] = base[index];
339 }
340
341 static void __kprobes
342 t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs)
343 {
344         kprobe_opcode_t insn = p->opcode;
345         unsigned long* base = (unsigned long *)regs->ARM_sp;
346         long index = insn & 0xff;
347         int rt = (insn >> 8) & 0x7;
348         if (insn & 0x800) /* LDR */
349                 regs->uregs[rt] = base[index];
350         else /* STR */
351                 base[index] = regs->uregs[rt];
352 }
353
354 static void __kprobes
355 t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs)
356 {
357         kprobe_opcode_t insn = p->opcode;
358         unsigned long base = (insn & 0x800) ? regs->ARM_sp
359                                             : (thumb_probe_pc(p) & ~3);
360         long offset = insn & 0xff;
361         int rt = (insn >> 8) & 0x7;
362         regs->uregs[rt] = base + offset * 4;
363 }
364
365 static void __kprobes
366 t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs)
367 {
368         kprobe_opcode_t insn = p->opcode;
369         long imm = insn & 0x7f;
370         if (insn & 0x80) /* SUB */
371                 regs->ARM_sp -= imm * 4;
372         else /* ADD */
373                 regs->ARM_sp += imm * 4;
374 }
375
376 static void __kprobes
377 t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs)
378 {
379         kprobe_opcode_t insn = p->opcode;
380         int rn = insn & 0x7;
381         kprobe_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn;
382         if (nonzero & 0x800) {
383                 long i = insn & 0x200;
384                 long imm5 = insn & 0xf8;
385                 unsigned long pc = thumb_probe_pc(p);
386                 regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2);
387         }
388 }
389
390 static void __kprobes
391 t16_simulate_it(struct kprobe *p, struct pt_regs *regs)
392 {
393         /*
394          * The 8 IT state bits are split into two parts in CPSR:
395          *      ITSTATE<1:0> are in CPSR<26:25>
396          *      ITSTATE<7:2> are in CPSR<15:10>
397          * The new IT state is in the lower byte of insn.
398          */
399         kprobe_opcode_t insn = p->opcode;
400         unsigned long cpsr = regs->ARM_cpsr;
401         cpsr &= ~PSR_IT_MASK;
402         cpsr |= (insn & 0xfc) << 8;
403         cpsr |= (insn & 0x03) << 25;
404         regs->ARM_cpsr = cpsr;
405 }
406
407 static void __kprobes
408 t16_singlestep_it(struct kprobe *p, struct pt_regs *regs)
409 {
410         regs->ARM_pc += 2;
411         t16_simulate_it(p, regs);
412 }
413
414 static enum kprobe_insn __kprobes
415 t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi,
416                 const struct decode_header *d)
417 {
418         asi->insn_singlestep = t16_singlestep_it;
419         return INSN_GOOD_NO_SLOT;
420 }
421
422 static void __kprobes
423 t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
424 {
425         kprobe_opcode_t insn = p->opcode;
426         unsigned long pc = thumb_probe_pc(p);
427         long offset = insn & 0x7f;
428         offset -= insn & 0x80; /* Apply sign bit */
429         regs->ARM_pc = pc + (offset * 2);
430 }
431
432 static enum kprobe_insn __kprobes
433 t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
434                 const struct decode_header *d)
435 {
436         int cc = (insn >> 8) & 0xf;
437         asi->insn_check_cc = kprobe_condition_checks[cc];
438         asi->insn_handler = t16_simulate_cond_branch;
439         return INSN_GOOD_NO_SLOT;
440 }
441
442 static void __kprobes
443 t16_simulate_branch(struct kprobe *p, struct pt_regs *regs)
444 {
445         kprobe_opcode_t insn = p->opcode;
446         unsigned long pc = thumb_probe_pc(p);
447         long offset = insn & 0x3ff;
448         offset -= insn & 0x400; /* Apply sign bit */
449         regs->ARM_pc = pc + (offset * 2);
450 }
451
452 static unsigned long __kprobes
453 t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
454 {
455         unsigned long oldcpsr = regs->ARM_cpsr;
456         unsigned long newcpsr;
457
458         __asm__ __volatile__ (
459                 "msr    cpsr_fs, %[oldcpsr]     \n\t"
460                 "ldmia  %[regs], {r0-r7}        \n\t"
461                 "blx    %[fn]                   \n\t"
462                 "stmia  %[regs], {r0-r7}        \n\t"
463                 "mrs    %[newcpsr], cpsr        \n\t"
464                 : [newcpsr] "=r" (newcpsr)
465                 : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs),
466                   [fn] "r" (p->ainsn.insn_fn)
467                 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
468                   "lr", "memory", "cc"
469                 );
470
471         return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK);
472 }
473
474 static void __kprobes
475 t16_emulate_loregs_rwflags(struct kprobe *p, struct pt_regs *regs)
476 {
477         regs->ARM_cpsr = t16_emulate_loregs(p, regs);
478 }
479
480 static void __kprobes
481 t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs)
482 {
483         unsigned long cpsr = t16_emulate_loregs(p, regs);
484         if (!in_it_block(cpsr))
485                 regs->ARM_cpsr = cpsr;
486 }
487
488 static void __kprobes
489 t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs)
490 {
491         kprobe_opcode_t insn = p->opcode;
492         unsigned long pc = thumb_probe_pc(p);
493         int rdn = (insn & 0x7) | ((insn & 0x80) >> 4);
494         int rm = (insn >> 3) & 0xf;
495
496         register unsigned long rdnv asm("r1");
497         register unsigned long rmv asm("r0");
498         unsigned long cpsr = regs->ARM_cpsr;
499
500         rdnv = (rdn == 15) ? pc : regs->uregs[rdn];
501         rmv = (rm == 15) ? pc : regs->uregs[rm];
502
503         __asm__ __volatile__ (
504                 "msr    cpsr_fs, %[cpsr]        \n\t"
505                 "blx    %[fn]                   \n\t"
506                 "mrs    %[cpsr], cpsr           \n\t"
507                 : "=r" (rdnv), [cpsr] "=r" (cpsr)
508                 : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
509                 : "lr", "memory", "cc"
510         );
511
512         if (rdn == 15)
513                 rdnv &= ~1;
514
515         regs->uregs[rdn] = rdnv;
516         regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
517 }
518
519 static enum kprobe_insn __kprobes
520 t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi,
521                 const struct decode_header *d)
522 {
523         insn &= ~0x00ff;
524         insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */
525         ((u16 *)asi->insn)[0] = insn;
526         asi->insn_handler = t16_emulate_hiregs;
527         return INSN_GOOD;
528 }
529
530 static void __kprobes
531 t16_emulate_push(struct kprobe *p, struct pt_regs *regs)
532 {
533         __asm__ __volatile__ (
534                 "ldr    r9, [%[regs], #13*4]    \n\t"
535                 "ldr    r8, [%[regs], #14*4]    \n\t"
536                 "ldmia  %[regs], {r0-r7}        \n\t"
537                 "blx    %[fn]                   \n\t"
538                 "str    r9, [%[regs], #13*4]    \n\t"
539                 :
540                 : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
541                 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
542                   "lr", "memory", "cc"
543                 );
544 }
545
546 static enum kprobe_insn __kprobes
547 t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi,
548                 const struct decode_header *d)
549 {
550         /*
551          * To simulate a PUSH we use a Thumb-2 "STMDB R9!, {registers}"
552          * and call it with R9=SP and LR in the register list represented
553          * by R8.
554          */
555         ((u16 *)asi->insn)[0] = 0xe929;         /* 1st half STMDB R9!,{} */
556         ((u16 *)asi->insn)[1] = insn & 0x1ff;   /* 2nd half (register list) */
557         asi->insn_handler = t16_emulate_push;
558         return INSN_GOOD;
559 }
560
561 static void __kprobes
562 t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs)
563 {
564         __asm__ __volatile__ (
565                 "ldr    r9, [%[regs], #13*4]    \n\t"
566                 "ldmia  %[regs], {r0-r7}        \n\t"
567                 "blx    %[fn]                   \n\t"
568                 "stmia  %[regs], {r0-r7}        \n\t"
569                 "str    r9, [%[regs], #13*4]    \n\t"
570                 :
571                 : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
572                 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
573                   "lr", "memory", "cc"
574                 );
575 }
576
577 static void __kprobes
578 t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs)
579 {
580         register unsigned long pc asm("r8");
581
582         __asm__ __volatile__ (
583                 "ldr    r9, [%[regs], #13*4]    \n\t"
584                 "ldmia  %[regs], {r0-r7}        \n\t"
585                 "blx    %[fn]                   \n\t"
586                 "stmia  %[regs], {r0-r7}        \n\t"
587                 "str    r9, [%[regs], #13*4]    \n\t"
588                 : "=r" (pc)
589                 : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
590                 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
591                   "lr", "memory", "cc"
592                 );
593
594         bx_write_pc(pc, regs);
595 }
596
597 static enum kprobe_insn __kprobes
598 t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi,
599                 const struct decode_header *d)
600 {
601         /*
602          * To simulate a POP we use a Thumb-2 "LDMDB R9!, {registers}"
603          * and call it with R9=SP and PC in the register list represented
604          * by R8.
605          */
606         ((u16 *)asi->insn)[0] = 0xe8b9;         /* 1st half LDMIA R9!,{} */
607         ((u16 *)asi->insn)[1] = insn & 0x1ff;   /* 2nd half (register list) */
608         asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc
609                                          : t16_emulate_pop_nopc;
610         return INSN_GOOD;
611 }
612
613 const union decode_action kprobes_t16_actions[NUM_PROBES_T16_ACTIONS] = {
614         [PROBES_T16_ADD_SP] = {.handler = t16_simulate_add_sp_imm},
615         [PROBES_T16_CBZ] = {.handler = t16_simulate_cbz},
616         [PROBES_T16_SIGN_EXTEND] = {.handler = t16_emulate_loregs_rwflags},
617         [PROBES_T16_PUSH] = {.decoder = t16_decode_push},
618         [PROBES_T16_POP] = {.decoder = t16_decode_pop},
619         [PROBES_T16_SEV] = {.handler = kprobe_emulate_none},
620         [PROBES_T16_WFE] = {.handler = kprobe_simulate_nop},
621         [PROBES_T16_IT] = {.decoder = t16_decode_it},
622         [PROBES_T16_CMP] = {.handler = t16_emulate_loregs_rwflags},
623         [PROBES_T16_ADDSUB] = {.handler = t16_emulate_loregs_noitrwflags},
624         [PROBES_T16_LOGICAL] = {.handler = t16_emulate_loregs_noitrwflags},
625         [PROBES_T16_LDR_LIT] = {.handler = t16_simulate_ldr_literal},
626         [PROBES_T16_BLX] = {.handler = t16_simulate_bxblx},
627         [PROBES_T16_HIREGOPS] = {.decoder = t16_decode_hiregs},
628         [PROBES_T16_LDRHSTRH] = {.handler = t16_emulate_loregs_rwflags},
629         [PROBES_T16_LDRSTR] = {.handler = t16_simulate_ldrstr_sp_relative},
630         [PROBES_T16_ADR] = {.handler = t16_simulate_reladr},
631         [PROBES_T16_LDMSTM] = {.handler = t16_emulate_loregs_rwflags},
632         [PROBES_T16_BRANCH_COND] = {.decoder = t16_decode_cond_branch},
633         [PROBES_T16_BRANCH] = {.handler = t16_simulate_branch},
634 };
635
636 const union decode_action kprobes_t32_actions[NUM_PROBES_T32_ACTIONS] = {
637         [PROBES_T32_LDMSTM] = {.decoder = t32_decode_ldmstm},
638         [PROBES_T32_LDRDSTRD] = {.handler = t32_emulate_ldrdstrd},
639         [PROBES_T32_TABLE_BRANCH] = {.handler = t32_simulate_table_branch},
640         [PROBES_T32_TST] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
641         [PROBES_T32_MOV] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
642         [PROBES_T32_ADDSUB] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
643         [PROBES_T32_LOGICAL] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
644         [PROBES_T32_CMP] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
645         [PROBES_T32_ADDWSUBW_PC] = {.handler = t32_emulate_rd8pc16_noflags,},
646         [PROBES_T32_ADDWSUBW] = {.handler = t32_emulate_rd8rn16_noflags},
647         [PROBES_T32_MOVW] = {.handler = t32_emulate_rd8rn16_noflags},
648         [PROBES_T32_SAT] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
649         [PROBES_T32_BITFIELD] = {.handler = t32_emulate_rd8rn16_noflags},
650         [PROBES_T32_SEV] = {.handler = kprobe_emulate_none},
651         [PROBES_T32_WFE] = {.handler = kprobe_simulate_nop},
652         [PROBES_T32_MRS] = {.handler = t32_simulate_mrs},
653         [PROBES_T32_BRANCH_COND] = {.decoder = t32_decode_cond_branch},
654         [PROBES_T32_BRANCH] = {.handler = t32_simulate_branch},
655         [PROBES_T32_PLDI] = {.handler = kprobe_simulate_nop},
656         [PROBES_T32_LDR_LIT] = {.handler = t32_simulate_ldr_literal},
657         [PROBES_T32_LDRSTR] = {.handler = t32_emulate_ldrstr},
658         [PROBES_T32_SIGN_EXTEND] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
659         [PROBES_T32_MEDIA] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
660         [PROBES_T32_REVERSE] = {.handler = t32_emulate_rd8rn16_noflags},
661         [PROBES_T32_MUL_ADD] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
662         [PROBES_T32_MUL_ADD2] = {.handler = t32_emulate_rd8rn16rm0ra12_noflags},
663         [PROBES_T32_MUL_ADD_LONG] = {
664                 .handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags},
665 };