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