aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/Makefile16
-rw-r--r--arch/arm/kernel/entry-armv.S3
-rw-r--r--arch/arm/kernel/ftrace.c3
-rw-r--r--arch/arm/kernel/head.S9
-rw-r--r--arch/arm/kernel/insn.h29
-rw-r--r--arch/arm/kernel/irq.c3
-rw-r--r--arch/arm/kernel/jump_label.c5
-rw-r--r--arch/arm/kernel/kgdb.c3
-rw-r--r--arch/arm/kernel/kprobes-arm.c343
-rw-r--r--arch/arm/kernel/kprobes-common.c171
-rw-r--r--arch/arm/kernel/kprobes-test-arm.c1346
-rw-r--r--arch/arm/kernel/kprobes-test-thumb.c1188
-rw-r--r--arch/arm/kernel/kprobes-test.c1713
-rw-r--r--arch/arm/kernel/kprobes-test.h435
-rw-r--r--arch/arm/kernel/kprobes-thumb.c666
-rw-r--r--arch/arm/kernel/kprobes.c628
-rw-r--r--arch/arm/kernel/kprobes.h52
-rw-r--r--arch/arm/kernel/patch.c3
-rw-r--r--arch/arm/kernel/patch.h17
-rw-r--r--arch/arm/kernel/probes-arm.c734
-rw-r--r--arch/arm/kernel/probes-arm.h73
-rw-r--r--arch/arm/kernel/probes-thumb.c882
-rw-r--r--arch/arm/kernel/probes-thumb.h97
-rw-r--r--arch/arm/kernel/probes.c456
-rw-r--r--arch/arm/kernel/probes.h407
-rw-r--r--arch/arm/kernel/suspend.c4
-rw-r--r--arch/arm/kernel/uprobes-arm.c234
-rw-r--r--arch/arm/kernel/uprobes.c230
-rw-r--r--arch/arm/kernel/uprobes.h35
29 files changed, 19 insertions, 9766 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index fb2b71ebe3f2..902397dd1000 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -51,20 +51,8 @@ obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o
51obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o 51obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o
52obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o 52obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o
53obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o 53obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
54obj-$(CONFIG_UPROBES) += probes.o probes-arm.o uprobes.o uprobes-arm.o 54# Main staffs in KPROBES are in arch/arm/probes/ .
55obj-$(CONFIG_KPROBES) += probes.o kprobes.o kprobes-common.o patch.o 55obj-$(CONFIG_KPROBES) += patch.o insn.o
56ifdef CONFIG_THUMB2_KERNEL
57obj-$(CONFIG_KPROBES) += kprobes-thumb.o probes-thumb.o
58else
59obj-$(CONFIG_KPROBES) += kprobes-arm.o probes-arm.o
60endif
61obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o
62test-kprobes-objs := kprobes-test.o
63ifdef CONFIG_THUMB2_KERNEL
64test-kprobes-objs += kprobes-test-thumb.o
65else
66test-kprobes-objs += kprobes-test-arm.o
67endif
68obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o 56obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
69obj-$(CONFIG_ARM_THUMBEE) += thumbee.o 57obj-$(CONFIG_ARM_THUMBEE) += thumbee.o
70obj-$(CONFIG_KGDB) += kgdb.o patch.o 58obj-$(CONFIG_KGDB) += kgdb.o patch.o
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 2f5555d307b3..672b21942fff 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -31,6 +31,7 @@
31 31
32#include "entry-header.S" 32#include "entry-header.S"
33#include <asm/entry-macro-multi.S> 33#include <asm/entry-macro-multi.S>
34#include <asm/probes.h>
34 35
35/* 36/*
36 * Interrupt handling. 37 * Interrupt handling.
@@ -249,7 +250,7 @@ __und_svc:
249 @ If a kprobe is about to simulate a "stmdb sp..." instruction, 250 @ If a kprobe is about to simulate a "stmdb sp..." instruction,
250 @ it obviously needs free stack space which then will belong to 251 @ it obviously needs free stack space which then will belong to
251 @ the saved context. 252 @ the saved context.
252 svc_entry 64 253 svc_entry MAX_STACK_SIZE
253#else 254#else
254 svc_entry 255 svc_entry
255#endif 256#endif
diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c
index b8c75e45a950..709ee1d6d4df 100644
--- a/arch/arm/kernel/ftrace.c
+++ b/arch/arm/kernel/ftrace.c
@@ -20,8 +20,7 @@
20#include <asm/cacheflush.h> 20#include <asm/cacheflush.h>
21#include <asm/opcodes.h> 21#include <asm/opcodes.h>
22#include <asm/ftrace.h> 22#include <asm/ftrace.h>
23 23#include <asm/insn.h>
24#include "insn.h"
25 24
26#ifdef CONFIG_THUMB2_KERNEL 25#ifdef CONFIG_THUMB2_KERNEL
27#define NOP 0xf85deb04 /* pop.w {lr} */ 26#define NOP 0xf85deb04 /* pop.w {lr} */
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 664eee8c4a26..01963273c07a 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -346,6 +346,12 @@ __turn_mmu_on_loc:
346 346
347#if defined(CONFIG_SMP) 347#if defined(CONFIG_SMP)
348 .text 348 .text
349ENTRY(secondary_startup_arm)
350 .arm
351 THUMB( adr r9, BSYM(1f) ) @ Kernel is entered in ARM.
352 THUMB( bx r9 ) @ If this is a Thumb-2 kernel,
353 THUMB( .thumb ) @ switch to Thumb now.
354 THUMB(1: )
349ENTRY(secondary_startup) 355ENTRY(secondary_startup)
350 /* 356 /*
351 * Common entry point for secondary CPUs. 357 * Common entry point for secondary CPUs.
@@ -385,6 +391,7 @@ ENTRY(secondary_startup)
385 THUMB( add r12, r10, #PROCINFO_INITFUNC ) 391 THUMB( add r12, r10, #PROCINFO_INITFUNC )
386 THUMB( ret r12 ) 392 THUMB( ret r12 )
387ENDPROC(secondary_startup) 393ENDPROC(secondary_startup)
394ENDPROC(secondary_startup_arm)
388 395
389 /* 396 /*
390 * r6 = &secondary_data 397 * r6 = &secondary_data
@@ -586,7 +593,7 @@ __fixup_pv_table:
586 add r5, r5, r3 @ adjust table end address 593 add r5, r5, r3 @ adjust table end address
587 add r6, r6, r3 @ adjust __pv_phys_pfn_offset address 594 add r6, r6, r3 @ adjust __pv_phys_pfn_offset address
588 add r7, r7, r3 @ adjust __pv_offset address 595 add r7, r7, r3 @ adjust __pv_offset address
589 mov r0, r8, lsr #12 @ convert to PFN 596 mov r0, r8, lsr #PAGE_SHIFT @ convert to PFN
590 str r0, [r6] @ save computed PHYS_OFFSET to __pv_phys_pfn_offset 597 str r0, [r6] @ save computed PHYS_OFFSET to __pv_phys_pfn_offset
591 strcc ip, [r7, #HIGH_OFFSET] @ save to __pv_offset high bits 598 strcc ip, [r7, #HIGH_OFFSET] @ save to __pv_offset high bits
592 mov r6, r3, lsr #24 @ constant for add/sub instructions 599 mov r6, r3, lsr #24 @ constant for add/sub instructions
diff --git a/arch/arm/kernel/insn.h b/arch/arm/kernel/insn.h
deleted file mode 100644
index e96065da4dae..000000000000
--- a/arch/arm/kernel/insn.h
+++ /dev/null
@@ -1,29 +0,0 @@
1#ifndef __ASM_ARM_INSN_H
2#define __ASM_ARM_INSN_H
3
4static inline unsigned long
5arm_gen_nop(void)
6{
7#ifdef CONFIG_THUMB2_KERNEL
8 return 0xf3af8000; /* nop.w */
9#else
10 return 0xe1a00000; /* mov r0, r0 */
11#endif
12}
13
14unsigned long
15__arm_gen_branch(unsigned long pc, unsigned long addr, bool link);
16
17static inline unsigned long
18arm_gen_branch(unsigned long pc, unsigned long addr)
19{
20 return __arm_gen_branch(pc, addr, false);
21}
22
23static inline unsigned long
24arm_gen_branch_link(unsigned long pc, unsigned long addr)
25{
26 return __arm_gen_branch(pc, addr, true);
27}
28
29#endif
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index ad857bada96c..350f188c92d2 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -109,7 +109,8 @@ void __init init_IRQ(void)
109 109
110 if (IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_CACHE_L2X0) && 110 if (IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_CACHE_L2X0) &&
111 (machine_desc->l2c_aux_mask || machine_desc->l2c_aux_val)) { 111 (machine_desc->l2c_aux_mask || machine_desc->l2c_aux_val)) {
112 outer_cache.write_sec = machine_desc->l2c_write_sec; 112 if (!outer_cache.write_sec)
113 outer_cache.write_sec = machine_desc->l2c_write_sec;
113 ret = l2x0_of_init(machine_desc->l2c_aux_val, 114 ret = l2x0_of_init(machine_desc->l2c_aux_val,
114 machine_desc->l2c_aux_mask); 115 machine_desc->l2c_aux_mask);
115 if (ret) 116 if (ret)
diff --git a/arch/arm/kernel/jump_label.c b/arch/arm/kernel/jump_label.c
index afeeb9ea6f43..e39cbf488cfe 100644
--- a/arch/arm/kernel/jump_label.c
+++ b/arch/arm/kernel/jump_label.c
@@ -1,8 +1,7 @@
1#include <linux/kernel.h> 1#include <linux/kernel.h>
2#include <linux/jump_label.h> 2#include <linux/jump_label.h>
3 3#include <asm/patch.h>
4#include "insn.h" 4#include <asm/insn.h>
5#include "patch.h"
6 5
7#ifdef HAVE_JUMP_LABEL 6#ifdef HAVE_JUMP_LABEL
8 7
diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c
index 07db2f8a1b45..a6ad93c9bce3 100644
--- a/arch/arm/kernel/kgdb.c
+++ b/arch/arm/kernel/kgdb.c
@@ -14,10 +14,9 @@
14#include <linux/kgdb.h> 14#include <linux/kgdb.h>
15#include <linux/uaccess.h> 15#include <linux/uaccess.h>
16 16
17#include <asm/patch.h>
17#include <asm/traps.h> 18#include <asm/traps.h>
18 19
19#include "patch.h"
20
21struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = 20struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] =
22{ 21{
23 { "r0", 4, offsetof(struct pt_regs, ARM_r0)}, 22 { "r0", 4, offsetof(struct pt_regs, ARM_r0)},
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
deleted file mode 100644
index ac300c60d656..000000000000
--- a/arch/arm/kernel/kprobes-arm.c
+++ /dev/null
@@ -1,343 +0,0 @@
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.
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>
63#include <linux/ptrace.h>
64
65#include "kprobes.h"
66#include "probes-arm.h"
67
68#if __LINUX_ARM_ARCH__ >= 6
69#define BLX(reg) "blx "reg" \n\t"
70#else
71#define BLX(reg) "mov lr, pc \n\t" \
72 "mov pc, "reg" \n\t"
73#endif
74
75static void __kprobes
76emulate_ldrdstrd(probes_opcode_t insn,
77 struct arch_probes_insn *asi, struct pt_regs *regs)
78{
79 unsigned long pc = regs->ARM_pc + 4;
80 int rt = (insn >> 12) & 0xf;
81 int rn = (insn >> 16) & 0xf;
82 int rm = insn & 0xf;
83
84 register unsigned long rtv asm("r0") = regs->uregs[rt];
85 register unsigned long rt2v asm("r1") = regs->uregs[rt+1];
86 register unsigned long rnv asm("r2") = (rn == 15) ? pc
87 : regs->uregs[rn];
88 register unsigned long rmv asm("r3") = regs->uregs[rm];
89
90 __asm__ __volatile__ (
91 BLX("%[fn]")
92 : "=r" (rtv), "=r" (rt2v), "=r" (rnv)
93 : "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv),
94 [fn] "r" (asi->insn_fn)
95 : "lr", "memory", "cc"
96 );
97
98 regs->uregs[rt] = rtv;
99 regs->uregs[rt+1] = rt2v;
100 if (is_writeback(insn))
101 regs->uregs[rn] = rnv;
102}
103
104static void __kprobes
105emulate_ldr(probes_opcode_t insn,
106 struct arch_probes_insn *asi, struct pt_regs *regs)
107{
108 unsigned long pc = regs->ARM_pc + 4;
109 int rt = (insn >> 12) & 0xf;
110 int rn = (insn >> 16) & 0xf;
111 int rm = insn & 0xf;
112
113 register unsigned long rtv asm("r0");
114 register unsigned long rnv asm("r2") = (rn == 15) ? pc
115 : regs->uregs[rn];
116 register unsigned long rmv asm("r3") = regs->uregs[rm];
117
118 __asm__ __volatile__ (
119 BLX("%[fn]")
120 : "=r" (rtv), "=r" (rnv)
121 : "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
122 : "lr", "memory", "cc"
123 );
124
125 if (rt == 15)
126 load_write_pc(rtv, regs);
127 else
128 regs->uregs[rt] = rtv;
129
130 if (is_writeback(insn))
131 regs->uregs[rn] = rnv;
132}
133
134static void __kprobes
135emulate_str(probes_opcode_t insn,
136 struct arch_probes_insn *asi, struct pt_regs *regs)
137{
138 unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset;
139 unsigned long rnpc = regs->ARM_pc + 4;
140 int rt = (insn >> 12) & 0xf;
141 int rn = (insn >> 16) & 0xf;
142 int rm = insn & 0xf;
143
144 register unsigned long rtv asm("r0") = (rt == 15) ? rtpc
145 : regs->uregs[rt];
146 register unsigned long rnv asm("r2") = (rn == 15) ? rnpc
147 : regs->uregs[rn];
148 register unsigned long rmv asm("r3") = regs->uregs[rm];
149
150 __asm__ __volatile__ (
151 BLX("%[fn]")
152 : "=r" (rnv)
153 : "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
154 : "lr", "memory", "cc"
155 );
156
157 if (is_writeback(insn))
158 regs->uregs[rn] = rnv;
159}
160
161static void __kprobes
162emulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,
163 struct arch_probes_insn *asi, struct pt_regs *regs)
164{
165 unsigned long pc = regs->ARM_pc + 4;
166 int rd = (insn >> 12) & 0xf;
167 int rn = (insn >> 16) & 0xf;
168 int rm = insn & 0xf;
169 int rs = (insn >> 8) & 0xf;
170
171 register unsigned long rdv asm("r0") = regs->uregs[rd];
172 register unsigned long rnv asm("r2") = (rn == 15) ? pc
173 : regs->uregs[rn];
174 register unsigned long rmv asm("r3") = (rm == 15) ? pc
175 : regs->uregs[rm];
176 register unsigned long rsv asm("r1") = regs->uregs[rs];
177 unsigned long cpsr = regs->ARM_cpsr;
178
179 __asm__ __volatile__ (
180 "msr cpsr_fs, %[cpsr] \n\t"
181 BLX("%[fn]")
182 "mrs %[cpsr], cpsr \n\t"
183 : "=r" (rdv), [cpsr] "=r" (cpsr)
184 : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
185 "1" (cpsr), [fn] "r" (asi->insn_fn)
186 : "lr", "memory", "cc"
187 );
188
189 if (rd == 15)
190 alu_write_pc(rdv, regs);
191 else
192 regs->uregs[rd] = rdv;
193 regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
194}
195
196static void __kprobes
197emulate_rd12rn16rm0_rwflags_nopc(probes_opcode_t insn,
198 struct arch_probes_insn *asi, struct pt_regs *regs)
199{
200 int rd = (insn >> 12) & 0xf;
201 int rn = (insn >> 16) & 0xf;
202 int rm = insn & 0xf;
203
204 register unsigned long rdv asm("r0") = regs->uregs[rd];
205 register unsigned long rnv asm("r2") = regs->uregs[rn];
206 register unsigned long rmv asm("r3") = regs->uregs[rm];
207 unsigned long cpsr = regs->ARM_cpsr;
208
209 __asm__ __volatile__ (
210 "msr cpsr_fs, %[cpsr] \n\t"
211 BLX("%[fn]")
212 "mrs %[cpsr], cpsr \n\t"
213 : "=r" (rdv), [cpsr] "=r" (cpsr)
214 : "0" (rdv), "r" (rnv), "r" (rmv),
215 "1" (cpsr), [fn] "r" (asi->insn_fn)
216 : "lr", "memory", "cc"
217 );
218
219 regs->uregs[rd] = rdv;
220 regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
221}
222
223static void __kprobes
224emulate_rd16rn12rm0rs8_rwflags_nopc(probes_opcode_t insn,
225 struct arch_probes_insn *asi,
226 struct pt_regs *regs)
227{
228 int rd = (insn >> 16) & 0xf;
229 int rn = (insn >> 12) & 0xf;
230 int rm = insn & 0xf;
231 int rs = (insn >> 8) & 0xf;
232
233 register unsigned long rdv asm("r2") = regs->uregs[rd];
234 register unsigned long rnv asm("r0") = regs->uregs[rn];
235 register unsigned long rmv asm("r3") = regs->uregs[rm];
236 register unsigned long rsv asm("r1") = regs->uregs[rs];
237 unsigned long cpsr = regs->ARM_cpsr;
238
239 __asm__ __volatile__ (
240 "msr cpsr_fs, %[cpsr] \n\t"
241 BLX("%[fn]")
242 "mrs %[cpsr], cpsr \n\t"
243 : "=r" (rdv), [cpsr] "=r" (cpsr)
244 : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
245 "1" (cpsr), [fn] "r" (asi->insn_fn)
246 : "lr", "memory", "cc"
247 );
248
249 regs->uregs[rd] = rdv;
250 regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
251}
252
253static void __kprobes
254emulate_rd12rm0_noflags_nopc(probes_opcode_t insn,
255 struct arch_probes_insn *asi, struct pt_regs *regs)
256{
257 int rd = (insn >> 12) & 0xf;
258 int rm = insn & 0xf;
259
260 register unsigned long rdv asm("r0") = regs->uregs[rd];
261 register unsigned long rmv asm("r3") = regs->uregs[rm];
262
263 __asm__ __volatile__ (
264 BLX("%[fn]")
265 : "=r" (rdv)
266 : "0" (rdv), "r" (rmv), [fn] "r" (asi->insn_fn)
267 : "lr", "memory", "cc"
268 );
269
270 regs->uregs[rd] = rdv;
271}
272
273static void __kprobes
274emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn,
275 struct arch_probes_insn *asi,
276 struct pt_regs *regs)
277{
278 int rdlo = (insn >> 12) & 0xf;
279 int rdhi = (insn >> 16) & 0xf;
280 int rn = insn & 0xf;
281 int rm = (insn >> 8) & 0xf;
282
283 register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
284 register unsigned long rdhiv asm("r2") = regs->uregs[rdhi];
285 register unsigned long rnv asm("r3") = regs->uregs[rn];
286 register unsigned long rmv asm("r1") = regs->uregs[rm];
287 unsigned long cpsr = regs->ARM_cpsr;
288
289 __asm__ __volatile__ (
290 "msr cpsr_fs, %[cpsr] \n\t"
291 BLX("%[fn]")
292 "mrs %[cpsr], cpsr \n\t"
293 : "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr)
294 : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
295 "2" (cpsr), [fn] "r" (asi->insn_fn)
296 : "lr", "memory", "cc"
297 );
298
299 regs->uregs[rdlo] = rdlov;
300 regs->uregs[rdhi] = rdhiv;
301 regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
302}
303
304const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = {
305 [PROBES_EMULATE_NONE] = {.handler = probes_emulate_none},
306 [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop},
307 [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop},
308 [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop},
309 [PROBES_BRANCH_IMM] = {.handler = simulate_blx1},
310 [PROBES_MRS] = {.handler = simulate_mrs},
311 [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx},
312 [PROBES_CLZ] = {.handler = emulate_rd12rm0_noflags_nopc},
313 [PROBES_SATURATING_ARITHMETIC] = {
314 .handler = emulate_rd12rn16rm0_rwflags_nopc},
315 [PROBES_MUL1] = {.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc},
316 [PROBES_MUL2] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc},
317 [PROBES_SWP] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
318 [PROBES_LDRSTRD] = {.handler = emulate_ldrdstrd},
319 [PROBES_LOAD_EXTRA] = {.handler = emulate_ldr},
320 [PROBES_LOAD] = {.handler = emulate_ldr},
321 [PROBES_STORE_EXTRA] = {.handler = emulate_str},
322 [PROBES_STORE] = {.handler = emulate_str},
323 [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp},
324 [PROBES_DATA_PROCESSING_REG] = {
325 .handler = emulate_rd12rn16rm0rs8_rwflags},
326 [PROBES_DATA_PROCESSING_IMM] = {
327 .handler = emulate_rd12rn16rm0rs8_rwflags},
328 [PROBES_MOV_HALFWORD] = {.handler = emulate_rd12rm0_noflags_nopc},
329 [PROBES_SEV] = {.handler = probes_emulate_none},
330 [PROBES_WFE] = {.handler = probes_simulate_nop},
331 [PROBES_SATURATE] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
332 [PROBES_REV] = {.handler = emulate_rd12rm0_noflags_nopc},
333 [PROBES_MMI] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
334 [PROBES_PACK] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
335 [PROBES_EXTEND] = {.handler = emulate_rd12rm0_noflags_nopc},
336 [PROBES_EXTEND_ADD] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
337 [PROBES_MUL_ADD_LONG] = {
338 .handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc},
339 [PROBES_MUL_ADD] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc},
340 [PROBES_BITFIELD] = {.handler = emulate_rd12rm0_noflags_nopc},
341 [PROBES_BRANCH] = {.handler = simulate_bbl},
342 [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm}
343};
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
deleted file mode 100644
index 0bf5d64eba1d..000000000000
--- a/arch/arm/kernel/kprobes-common.c
+++ /dev/null
@@ -1,171 +0,0 @@
1/*
2 * arch/arm/kernel/kprobes-common.c
3 *
4 * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
5 *
6 * Some contents moved here from arch/arm/include/asm/kprobes-arm.c which is
7 * Copyright (C) 2006, 2007 Motorola Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/kernel.h>
15#include <linux/kprobes.h>
16#include <asm/opcodes.h>
17
18#include "kprobes.h"
19
20
21static void __kprobes simulate_ldm1stm1(probes_opcode_t insn,
22 struct arch_probes_insn *asi,
23 struct pt_regs *regs)
24{
25 int rn = (insn >> 16) & 0xf;
26 int lbit = insn & (1 << 20);
27 int wbit = insn & (1 << 21);
28 int ubit = insn & (1 << 23);
29 int pbit = insn & (1 << 24);
30 long *addr = (long *)regs->uregs[rn];
31 int reg_bit_vector;
32 int reg_count;
33
34 reg_count = 0;
35 reg_bit_vector = insn & 0xffff;
36 while (reg_bit_vector) {
37 reg_bit_vector &= (reg_bit_vector - 1);
38 ++reg_count;
39 }
40
41 if (!ubit)
42 addr -= reg_count;
43 addr += (!pbit == !ubit);
44
45 reg_bit_vector = insn & 0xffff;
46 while (reg_bit_vector) {
47 int reg = __ffs(reg_bit_vector);
48 reg_bit_vector &= (reg_bit_vector - 1);
49 if (lbit)
50 regs->uregs[reg] = *addr++;
51 else
52 *addr++ = regs->uregs[reg];
53 }
54
55 if (wbit) {
56 if (!ubit)
57 addr -= reg_count;
58 addr -= (!pbit == !ubit);
59 regs->uregs[rn] = (long)addr;
60 }
61}
62
63static void __kprobes simulate_stm1_pc(probes_opcode_t insn,
64 struct arch_probes_insn *asi,
65 struct pt_regs *regs)
66{
67 unsigned long addr = regs->ARM_pc - 4;
68
69 regs->ARM_pc = (long)addr + str_pc_offset;
70 simulate_ldm1stm1(insn, asi, regs);
71 regs->ARM_pc = (long)addr + 4;
72}
73
74static void __kprobes simulate_ldm1_pc(probes_opcode_t insn,
75 struct arch_probes_insn *asi,
76 struct pt_regs *regs)
77{
78 simulate_ldm1stm1(insn, asi, regs);
79 load_write_pc(regs->ARM_pc, regs);
80}
81
82static void __kprobes
83emulate_generic_r0_12_noflags(probes_opcode_t insn,
84 struct arch_probes_insn *asi, struct pt_regs *regs)
85{
86 register void *rregs asm("r1") = regs;
87 register void *rfn asm("lr") = asi->insn_fn;
88
89 __asm__ __volatile__ (
90 "stmdb sp!, {%[regs], r11} \n\t"
91 "ldmia %[regs], {r0-r12} \n\t"
92#if __LINUX_ARM_ARCH__ >= 6
93 "blx %[fn] \n\t"
94#else
95 "str %[fn], [sp, #-4]! \n\t"
96 "adr lr, 1f \n\t"
97 "ldr pc, [sp], #4 \n\t"
98 "1: \n\t"
99#endif
100 "ldr lr, [sp], #4 \n\t" /* lr = regs */
101 "stmia lr, {r0-r12} \n\t"
102 "ldr r11, [sp], #4 \n\t"
103 : [regs] "=r" (rregs), [fn] "=r" (rfn)
104 : "0" (rregs), "1" (rfn)
105 : "r0", "r2", "r3", "r4", "r5", "r6", "r7",
106 "r8", "r9", "r10", "r12", "memory", "cc"
107 );
108}
109
110static void __kprobes
111emulate_generic_r2_14_noflags(probes_opcode_t insn,
112 struct arch_probes_insn *asi, struct pt_regs *regs)
113{
114 emulate_generic_r0_12_noflags(insn, asi,
115 (struct pt_regs *)(regs->uregs+2));
116}
117
118static void __kprobes
119emulate_ldm_r3_15(probes_opcode_t insn,
120 struct arch_probes_insn *asi, struct pt_regs *regs)
121{
122 emulate_generic_r0_12_noflags(insn, asi,
123 (struct pt_regs *)(regs->uregs+3));
124 load_write_pc(regs->ARM_pc, regs);
125}
126
127enum probes_insn __kprobes
128kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi,
129 const struct decode_header *h)
130{
131 probes_insn_handler_t *handler = 0;
132 unsigned reglist = insn & 0xffff;
133 int is_ldm = insn & 0x100000;
134 int rn = (insn >> 16) & 0xf;
135
136 if (rn <= 12 && (reglist & 0xe000) == 0) {
137 /* Instruction only uses registers in the range R0..R12 */
138 handler = emulate_generic_r0_12_noflags;
139
140 } else if (rn >= 2 && (reglist & 0x8003) == 0) {
141 /* Instruction only uses registers in the range R2..R14 */
142 rn -= 2;
143 reglist >>= 2;
144 handler = emulate_generic_r2_14_noflags;
145
146 } else if (rn >= 3 && (reglist & 0x0007) == 0) {
147 /* Instruction only uses registers in the range R3..R15 */
148 if (is_ldm && (reglist & 0x8000)) {
149 rn -= 3;
150 reglist >>= 3;
151 handler = emulate_ldm_r3_15;
152 }
153 }
154
155 if (handler) {
156 /* We can emulate the instruction in (possibly) modified form */
157 asi->insn[0] = __opcode_to_mem_arm((insn & 0xfff00000) |
158 (rn << 16) | reglist);
159 asi->insn_handler = handler;
160 return INSN_GOOD;
161 }
162
163 /* Fallback to slower simulation... */
164 if (reglist & 0x8000)
165 handler = is_ldm ? simulate_ldm1_pc : simulate_stm1_pc;
166 else
167 handler = simulate_ldm1stm1;
168 asi->insn_handler = handler;
169 return INSN_GOOD_NO_SLOT;
170}
171
diff --git a/arch/arm/kernel/kprobes-test-arm.c b/arch/arm/kernel/kprobes-test-arm.c
deleted file mode 100644
index cb1424240ff6..000000000000
--- a/arch/arm/kernel/kprobes-test-arm.c
+++ /dev/null
@@ -1,1346 +0,0 @@
1/*
2 * arch/arm/kernel/kprobes-test-arm.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/kernel.h>
12#include <linux/module.h>
13#include <asm/system_info.h>
14#include <asm/opcodes.h>
15
16#include "kprobes-test.h"
17
18
19#define TEST_ISA "32"
20
21#define TEST_ARM_TO_THUMB_INTERWORK_R(code1, reg, val, code2) \
22 TESTCASE_START(code1 #reg code2) \
23 TEST_ARG_REG(reg, val) \
24 TEST_ARG_REG(14, 99f) \
25 TEST_ARG_END("") \
26 "50: nop \n\t" \
27 "1: "code1 #reg code2" \n\t" \
28 " bx lr \n\t" \
29 ".thumb \n\t" \
30 "3: adr lr, 2f \n\t" \
31 " bx lr \n\t" \
32 ".arm \n\t" \
33 "2: nop \n\t" \
34 TESTCASE_END
35
36#define TEST_ARM_TO_THUMB_INTERWORK_P(code1, reg, val, code2) \
37 TESTCASE_START(code1 #reg code2) \
38 TEST_ARG_PTR(reg, val) \
39 TEST_ARG_REG(14, 99f) \
40 TEST_ARG_MEM(15, 3f+1) \
41 TEST_ARG_END("") \
42 "50: nop \n\t" \
43 "1: "code1 #reg code2" \n\t" \
44 " bx lr \n\t" \
45 ".thumb \n\t" \
46 "3: adr lr, 2f \n\t" \
47 " bx lr \n\t" \
48 ".arm \n\t" \
49 "2: nop \n\t" \
50 TESTCASE_END
51
52
53void kprobe_arm_test_cases(void)
54{
55 kprobe_test_flags = 0;
56
57 TEST_GROUP("Data-processing (register), (register-shifted register), (immediate)")
58
59#define _DATA_PROCESSING_DNM(op,s,val) \
60 TEST_RR( op "eq" s " r0, r",1, VAL1,", r",2, val, "") \
61 TEST_RR( op "ne" s " r1, r",1, VAL1,", r",2, val, ", lsl #3") \
62 TEST_RR( op "cs" s " r2, r",3, VAL1,", r",2, val, ", lsr #4") \
63 TEST_RR( op "cc" s " r3, r",3, VAL1,", r",2, val, ", asr #5") \
64 TEST_RR( op "mi" s " r4, r",5, VAL1,", r",2, N(val),", asr #6") \
65 TEST_RR( op "pl" s " r5, r",5, VAL1,", r",2, val, ", ror #7") \
66 TEST_RR( op "vs" s " r6, r",7, VAL1,", r",2, val, ", rrx") \
67 TEST_R( op "vc" s " r6, r",7, VAL1,", pc, lsl #3") \
68 TEST_R( op "vc" s " r6, r",7, VAL1,", sp, lsr #4") \
69 TEST_R( op "vc" s " r6, pc, r",7, VAL1,", asr #5") \
70 TEST_R( op "vc" s " r6, sp, r",7, VAL1,", ror #6") \
71 TEST_RRR( op "hi" s " r8, r",9, VAL1,", r",14,val, ", lsl r",0, 3,"")\
72 TEST_RRR( op "ls" s " r9, r",9, VAL1,", r",14,val, ", lsr r",7, 4,"")\
73 TEST_RRR( op "ge" s " r10, r",11,VAL1,", r",14,val, ", asr r",7, 5,"")\
74 TEST_RRR( op "lt" s " r11, r",11,VAL1,", r",14,N(val),", asr r",7, 6,"")\
75 TEST_RR( op "gt" s " r12, r13" ", r",14,val, ", ror r",14,7,"")\
76 TEST_RR( op "le" s " r14, r",0, val, ", r13" ", lsl r",14,8,"")\
77 TEST_R( op "eq" s " r0, r",11,VAL1,", #0xf5") \
78 TEST_R( op "ne" s " r11, r",0, VAL1,", #0xf5000000") \
79 TEST_R( op s " r7, r",8, VAL2,", #0x000af000") \
80 TEST( op s " r4, pc" ", #0x00005a00")
81
82#define DATA_PROCESSING_DNM(op,val) \
83 _DATA_PROCESSING_DNM(op,"",val) \
84 _DATA_PROCESSING_DNM(op,"s",val)
85
86#define DATA_PROCESSING_NM(op,val) \
87 TEST_RR( op "ne r",1, VAL1,", r",2, val, "") \
88 TEST_RR( op "eq r",1, VAL1,", r",2, val, ", lsl #3") \
89 TEST_RR( op "cc r",3, VAL1,", r",2, val, ", lsr #4") \
90 TEST_RR( op "cs r",3, VAL1,", r",2, val, ", asr #5") \
91 TEST_RR( op "pl r",5, VAL1,", r",2, N(val),", asr #6") \
92 TEST_RR( op "mi r",5, VAL1,", r",2, val, ", ror #7") \
93 TEST_RR( op "vc r",7, VAL1,", r",2, val, ", rrx") \
94 TEST_R ( op "vs r",7, VAL1,", pc, lsl #3") \
95 TEST_R ( op "vs r",7, VAL1,", sp, lsr #4") \
96 TEST_R( op "vs pc, r",7, VAL1,", asr #5") \
97 TEST_R( op "vs sp, r",7, VAL1,", ror #6") \
98 TEST_RRR( op "ls r",9, VAL1,", r",14,val, ", lsl r",0, 3,"") \
99 TEST_RRR( op "hi r",9, VAL1,", r",14,val, ", lsr r",7, 4,"") \
100 TEST_RRR( op "lt r",11,VAL1,", r",14,val, ", asr r",7, 5,"") \
101 TEST_RRR( op "ge r",11,VAL1,", r",14,N(val),", asr r",7, 6,"") \
102 TEST_RR( op "le r13" ", r",14,val, ", ror r",14,7,"") \
103 TEST_RR( op "gt r",0, val, ", r13" ", lsl r",14,8,"") \
104 TEST_R( op "eq r",11,VAL1,", #0xf5") \
105 TEST_R( op "ne r",0, VAL1,", #0xf5000000") \
106 TEST_R( op " r",8, VAL2,", #0x000af000")
107
108#define _DATA_PROCESSING_DM(op,s,val) \
109 TEST_R( op "eq" s " r0, r",1, val, "") \
110 TEST_R( op "ne" s " r1, r",1, val, ", lsl #3") \
111 TEST_R( op "cs" s " r2, r",3, val, ", lsr #4") \
112 TEST_R( op "cc" s " r3, r",3, val, ", asr #5") \
113 TEST_R( op "mi" s " r4, r",5, N(val),", asr #6") \
114 TEST_R( op "pl" s " r5, r",5, val, ", ror #7") \
115 TEST_R( op "vs" s " r6, r",10,val, ", rrx") \
116 TEST( op "vs" s " r7, pc, lsl #3") \
117 TEST( op "vs" s " r7, sp, lsr #4") \
118 TEST_RR( op "vc" s " r8, r",7, val, ", lsl r",0, 3,"") \
119 TEST_RR( op "hi" s " r9, r",9, val, ", lsr r",7, 4,"") \
120 TEST_RR( op "ls" s " r10, r",9, val, ", asr r",7, 5,"") \
121 TEST_RR( op "ge" s " r11, r",11,N(val),", asr r",7, 6,"") \
122 TEST_RR( op "lt" s " r12, r",11,val, ", ror r",14,7,"") \
123 TEST_R( op "gt" s " r14, r13" ", lsl r",14,8,"") \
124 TEST( op "eq" s " r0, #0xf5") \
125 TEST( op "ne" s " r11, #0xf5000000") \
126 TEST( op s " r7, #0x000af000") \
127 TEST( op s " r4, #0x00005a00")
128
129#define DATA_PROCESSING_DM(op,val) \
130 _DATA_PROCESSING_DM(op,"",val) \
131 _DATA_PROCESSING_DM(op,"s",val)
132
133 DATA_PROCESSING_DNM("and",0xf00f00ff)
134 DATA_PROCESSING_DNM("eor",0xf00f00ff)
135 DATA_PROCESSING_DNM("sub",VAL2)
136 DATA_PROCESSING_DNM("rsb",VAL2)
137 DATA_PROCESSING_DNM("add",VAL2)
138 DATA_PROCESSING_DNM("adc",VAL2)
139 DATA_PROCESSING_DNM("sbc",VAL2)
140 DATA_PROCESSING_DNM("rsc",VAL2)
141 DATA_PROCESSING_NM("tst",0xf00f00ff)
142 DATA_PROCESSING_NM("teq",0xf00f00ff)
143 DATA_PROCESSING_NM("cmp",VAL2)
144 DATA_PROCESSING_NM("cmn",VAL2)
145 DATA_PROCESSING_DNM("orr",0xf00f00ff)
146 DATA_PROCESSING_DM("mov",VAL2)
147 DATA_PROCESSING_DNM("bic",0xf00f00ff)
148 DATA_PROCESSING_DM("mvn",VAL2)
149
150 TEST("mov ip, sp") /* This has special case emulation code */
151
152 TEST_SUPPORTED("mov pc, #0x1000");
153 TEST_SUPPORTED("mov sp, #0x1000");
154 TEST_SUPPORTED("cmp pc, #0x1000");
155 TEST_SUPPORTED("cmp sp, #0x1000");
156
157 /* Data-processing with PC and a shift count in a register */
158 TEST_UNSUPPORTED(__inst_arm(0xe15c0f1e) " @ cmp r12, r14, asl pc")
159 TEST_UNSUPPORTED(__inst_arm(0xe1a0cf1e) " @ mov r12, r14, asl pc")
160 TEST_UNSUPPORTED(__inst_arm(0xe08caf1e) " @ add r10, r12, r14, asl pc")
161 TEST_UNSUPPORTED(__inst_arm(0xe151021f) " @ cmp r1, pc, lsl r2")
162 TEST_UNSUPPORTED(__inst_arm(0xe17f0211) " @ cmn pc, r1, lsl r2")
163 TEST_UNSUPPORTED(__inst_arm(0xe1a0121f) " @ mov r1, pc, lsl r2")
164 TEST_UNSUPPORTED(__inst_arm(0xe1a0f211) " @ mov pc, r1, lsl r2")
165 TEST_UNSUPPORTED(__inst_arm(0xe042131f) " @ sub r1, r2, pc, lsl r3")
166 TEST_UNSUPPORTED(__inst_arm(0xe1cf1312) " @ bic r1, pc, r2, lsl r3")
167 TEST_UNSUPPORTED(__inst_arm(0xe081f312) " @ add pc, r1, r2, lsl r3")
168
169 /* Data-processing with PC as a target and status registers updated */
170 TEST_UNSUPPORTED("movs pc, r1")
171 TEST_UNSUPPORTED("movs pc, r1, lsl r2")
172 TEST_UNSUPPORTED("movs pc, #0x10000")
173 TEST_UNSUPPORTED("adds pc, lr, r1")
174 TEST_UNSUPPORTED("adds pc, lr, r1, lsl r2")
175 TEST_UNSUPPORTED("adds pc, lr, #4")
176
177 /* Data-processing with SP as target */
178 TEST("add sp, sp, #16")
179 TEST("sub sp, sp, #8")
180 TEST("bic sp, sp, #0x20")
181 TEST("orr sp, sp, #0x20")
182 TEST_PR( "add sp, r",10,0,", r",11,4,"")
183 TEST_PRR("add sp, r",10,0,", r",11,4,", asl r",12,1,"")
184 TEST_P( "mov sp, r",10,0,"")
185 TEST_PR( "mov sp, r",10,0,", asl r",12,0,"")
186
187 /* Data-processing with PC as target */
188 TEST_BF( "add pc, pc, #2f-1b-8")
189 TEST_BF_R ("add pc, pc, r",14,2f-1f-8,"")
190 TEST_BF_R ("add pc, r",14,2f-1f-8,", pc")
191 TEST_BF_R ("mov pc, r",0,2f,"")
192 TEST_BF_R ("add pc, pc, r",14,(2f-1f-8)*2,", asr #1")
193 TEST_BB( "sub pc, pc, #1b-2b+8")
194#if __LINUX_ARM_ARCH__ == 6 && !defined(CONFIG_CPU_V7)
195 TEST_BB( "sub pc, pc, #1b-2b+8-2") /* UNPREDICTABLE before and after ARMv6 */
196#endif
197 TEST_BB_R( "sub pc, pc, r",14, 1f-2f+8,"")
198 TEST_BB_R( "rsb pc, r",14,1f-2f+8,", pc")
199 TEST_R( "add pc, pc, r",10,-2,", asl #1")
200#ifdef CONFIG_THUMB2_KERNEL
201 TEST_ARM_TO_THUMB_INTERWORK_R("add pc, pc, r",0,3f-1f-8+1,"")
202 TEST_ARM_TO_THUMB_INTERWORK_R("sub pc, r",0,3f+8+1,", #8")
203#endif
204 TEST_GROUP("Miscellaneous instructions")
205
206 TEST("mrs r0, cpsr")
207 TEST("mrspl r7, cpsr")
208 TEST("mrs r14, cpsr")
209 TEST_UNSUPPORTED(__inst_arm(0xe10ff000) " @ mrs r15, cpsr")
210 TEST_UNSUPPORTED("mrs r0, spsr")
211 TEST_UNSUPPORTED("mrs lr, spsr")
212
213 TEST_UNSUPPORTED("msr cpsr, r0")
214 TEST_UNSUPPORTED("msr cpsr_f, lr")
215 TEST_UNSUPPORTED("msr spsr, r0")
216
217 TEST_BF_R("bx r",0,2f,"")
218 TEST_BB_R("bx r",7,2f,"")
219 TEST_BF_R("bxeq r",14,2f,"")
220
221#if __LINUX_ARM_ARCH__ >= 5
222 TEST_R("clz r0, r",0, 0x0,"")
223 TEST_R("clzeq r7, r",14,0x1,"")
224 TEST_R("clz lr, r",7, 0xffffffff,"")
225 TEST( "clz r4, sp")
226 TEST_UNSUPPORTED(__inst_arm(0x016fff10) " @ clz pc, r0")
227 TEST_UNSUPPORTED(__inst_arm(0x016f0f1f) " @ clz r0, pc")
228
229#if __LINUX_ARM_ARCH__ >= 6
230 TEST_UNSUPPORTED("bxj r0")
231#endif
232
233 TEST_BF_R("blx r",0,2f,"")
234 TEST_BB_R("blx r",7,2f,"")
235 TEST_BF_R("blxeq r",14,2f,"")
236 TEST_UNSUPPORTED(__inst_arm(0x0120003f) " @ blx pc")
237
238 TEST_RR( "qadd r0, r",1, VAL1,", r",2, VAL2,"")
239 TEST_RR( "qaddvs lr, r",9, VAL2,", r",8, VAL1,"")
240 TEST_R( "qadd lr, r",9, VAL2,", r13")
241 TEST_RR( "qsub r0, r",1, VAL1,", r",2, VAL2,"")
242 TEST_RR( "qsubvs lr, r",9, VAL2,", r",8, VAL1,"")
243 TEST_R( "qsub lr, r",9, VAL2,", r13")
244 TEST_RR( "qdadd r0, r",1, VAL1,", r",2, VAL2,"")
245 TEST_RR( "qdaddvs lr, r",9, VAL2,", r",8, VAL1,"")
246 TEST_R( "qdadd lr, r",9, VAL2,", r13")
247 TEST_RR( "qdsub r0, r",1, VAL1,", r",2, VAL2,"")
248 TEST_RR( "qdsubvs lr, r",9, VAL2,", r",8, VAL1,"")
249 TEST_R( "qdsub lr, r",9, VAL2,", r13")
250 TEST_UNSUPPORTED(__inst_arm(0xe101f050) " @ qadd pc, r0, r1")
251 TEST_UNSUPPORTED(__inst_arm(0xe121f050) " @ qsub pc, r0, r1")
252 TEST_UNSUPPORTED(__inst_arm(0xe141f050) " @ qdadd pc, r0, r1")
253 TEST_UNSUPPORTED(__inst_arm(0xe161f050) " @ qdsub pc, r0, r1")
254 TEST_UNSUPPORTED(__inst_arm(0xe16f2050) " @ qdsub r2, r0, pc")
255 TEST_UNSUPPORTED(__inst_arm(0xe161205f) " @ qdsub r2, pc, r1")
256
257 TEST_UNSUPPORTED("bkpt 0xffff")
258 TEST_UNSUPPORTED("bkpt 0x0000")
259
260 TEST_UNSUPPORTED(__inst_arm(0xe1600070) " @ smc #0")
261
262 TEST_GROUP("Halfword multiply and multiply-accumulate")
263
264 TEST_RRR( "smlabb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
265 TEST_RRR( "smlabbge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
266 TEST_RR( "smlabb lr, r",1, VAL2,", r",2, VAL3,", r13")
267 TEST_UNSUPPORTED(__inst_arm(0xe10f3281) " @ smlabb pc, r1, r2, r3")
268 TEST_RRR( "smlatb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
269 TEST_RRR( "smlatbge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
270 TEST_RR( "smlatb lr, r",1, VAL2,", r",2, VAL3,", r13")
271 TEST_UNSUPPORTED(__inst_arm(0xe10f32a1) " @ smlatb pc, r1, r2, r3")
272 TEST_RRR( "smlabt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
273 TEST_RRR( "smlabtge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
274 TEST_RR( "smlabt lr, r",1, VAL2,", r",2, VAL3,", r13")
275 TEST_UNSUPPORTED(__inst_arm(0xe10f32c1) " @ smlabt pc, r1, r2, r3")
276 TEST_RRR( "smlatt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
277 TEST_RRR( "smlattge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
278 TEST_RR( "smlatt lr, r",1, VAL2,", r",2, VAL3,", r13")
279 TEST_UNSUPPORTED(__inst_arm(0xe10f32e1) " @ smlatt pc, r1, r2, r3")
280
281 TEST_RRR( "smlawb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
282 TEST_RRR( "smlawbge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
283 TEST_RR( "smlawb lr, r",1, VAL2,", r",2, VAL3,", r13")
284 TEST_UNSUPPORTED(__inst_arm(0xe12f3281) " @ smlawb pc, r1, r2, r3")
285 TEST_RRR( "smlawt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
286 TEST_RRR( "smlawtge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
287 TEST_RR( "smlawt lr, r",1, VAL2,", r",2, VAL3,", r13")
288 TEST_UNSUPPORTED(__inst_arm(0xe12f32c1) " @ smlawt pc, r1, r2, r3")
289 TEST_UNSUPPORTED(__inst_arm(0xe12032cf) " @ smlawt r0, pc, r2, r3")
290 TEST_UNSUPPORTED(__inst_arm(0xe1203fc1) " @ smlawt r0, r1, pc, r3")
291 TEST_UNSUPPORTED(__inst_arm(0xe120f2c1) " @ smlawt r0, r1, r2, pc")
292
293 TEST_RR( "smulwb r0, r",1, VAL1,", r",2, VAL2,"")
294 TEST_RR( "smulwbge r7, r",8, VAL3,", r",9, VAL1,"")
295 TEST_R( "smulwb lr, r",1, VAL2,", r13")
296 TEST_UNSUPPORTED(__inst_arm(0xe12f02a1) " @ smulwb pc, r1, r2")
297 TEST_RR( "smulwt r0, r",1, VAL1,", r",2, VAL2,"")
298 TEST_RR( "smulwtge r7, r",8, VAL3,", r",9, VAL1,"")
299 TEST_R( "smulwt lr, r",1, VAL2,", r13")
300 TEST_UNSUPPORTED(__inst_arm(0xe12f02e1) " @ smulwt pc, r1, r2")
301
302 TEST_RRRR( "smlalbb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
303 TEST_RRRR( "smlalbble r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
304 TEST_RRR( "smlalbb r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
305 TEST_UNSUPPORTED(__inst_arm(0xe14f1382) " @ smlalbb pc, r1, r2, r3")
306 TEST_UNSUPPORTED(__inst_arm(0xe141f382) " @ smlalbb r1, pc, r2, r3")
307 TEST_RRRR( "smlaltb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
308 TEST_RRRR( "smlaltble r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
309 TEST_RRR( "smlaltb r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
310 TEST_UNSUPPORTED(__inst_arm(0xe14f13a2) " @ smlaltb pc, r1, r2, r3")
311 TEST_UNSUPPORTED(__inst_arm(0xe141f3a2) " @ smlaltb r1, pc, r2, r3")
312 TEST_RRRR( "smlalbt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
313 TEST_RRRR( "smlalbtle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
314 TEST_RRR( "smlalbt r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
315 TEST_UNSUPPORTED(__inst_arm(0xe14f13c2) " @ smlalbt pc, r1, r2, r3")
316 TEST_UNSUPPORTED(__inst_arm(0xe141f3c2) " @ smlalbt r1, pc, r2, r3")
317 TEST_RRRR( "smlaltt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
318 TEST_RRRR( "smlalttle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
319 TEST_RRR( "smlaltt r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
320 TEST_UNSUPPORTED(__inst_arm(0xe14f13e2) " @ smlalbb pc, r1, r2, r3")
321 TEST_UNSUPPORTED(__inst_arm(0xe140f3e2) " @ smlalbb r0, pc, r2, r3")
322 TEST_UNSUPPORTED(__inst_arm(0xe14013ef) " @ smlalbb r0, r1, pc, r3")
323 TEST_UNSUPPORTED(__inst_arm(0xe1401fe2) " @ smlalbb r0, r1, r2, pc")
324
325 TEST_RR( "smulbb r0, r",1, VAL1,", r",2, VAL2,"")
326 TEST_RR( "smulbbge r7, r",8, VAL3,", r",9, VAL1,"")
327 TEST_R( "smulbb lr, r",1, VAL2,", r13")
328 TEST_UNSUPPORTED(__inst_arm(0xe16f0281) " @ smulbb pc, r1, r2")
329 TEST_RR( "smultb r0, r",1, VAL1,", r",2, VAL2,"")
330 TEST_RR( "smultbge r7, r",8, VAL3,", r",9, VAL1,"")
331 TEST_R( "smultb lr, r",1, VAL2,", r13")
332 TEST_UNSUPPORTED(__inst_arm(0xe16f02a1) " @ smultb pc, r1, r2")
333 TEST_RR( "smulbt r0, r",1, VAL1,", r",2, VAL2,"")
334 TEST_RR( "smulbtge r7, r",8, VAL3,", r",9, VAL1,"")
335 TEST_R( "smulbt lr, r",1, VAL2,", r13")
336 TEST_UNSUPPORTED(__inst_arm(0xe16f02c1) " @ smultb pc, r1, r2")
337 TEST_RR( "smultt r0, r",1, VAL1,", r",2, VAL2,"")
338 TEST_RR( "smulttge r7, r",8, VAL3,", r",9, VAL1,"")
339 TEST_R( "smultt lr, r",1, VAL2,", r13")
340 TEST_UNSUPPORTED(__inst_arm(0xe16f02e1) " @ smultt pc, r1, r2")
341 TEST_UNSUPPORTED(__inst_arm(0xe16002ef) " @ smultt r0, pc, r2")
342 TEST_UNSUPPORTED(__inst_arm(0xe1600fe1) " @ smultt r0, r1, pc")
343#endif
344
345 TEST_GROUP("Multiply and multiply-accumulate")
346
347 TEST_RR( "mul r0, r",1, VAL1,", r",2, VAL2,"")
348 TEST_RR( "mulls r7, r",8, VAL2,", r",9, VAL2,"")
349 TEST_R( "mul lr, r",4, VAL3,", r13")
350 TEST_UNSUPPORTED(__inst_arm(0xe00f0291) " @ mul pc, r1, r2")
351 TEST_UNSUPPORTED(__inst_arm(0xe000029f) " @ mul r0, pc, r2")
352 TEST_UNSUPPORTED(__inst_arm(0xe0000f91) " @ mul r0, r1, pc")
353 TEST_RR( "muls r0, r",1, VAL1,", r",2, VAL2,"")
354 TEST_RR( "mullss r7, r",8, VAL2,", r",9, VAL2,"")
355 TEST_R( "muls lr, r",4, VAL3,", r13")
356 TEST_UNSUPPORTED(__inst_arm(0xe01f0291) " @ muls pc, r1, r2")
357
358 TEST_RRR( "mla r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
359 TEST_RRR( "mlahi r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
360 TEST_RR( "mla lr, r",1, VAL2,", r",2, VAL3,", r13")
361 TEST_UNSUPPORTED(__inst_arm(0xe02f3291) " @ mla pc, r1, r2, r3")
362 TEST_RRR( "mlas r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
363 TEST_RRR( "mlahis r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
364 TEST_RR( "mlas lr, r",1, VAL2,", r",2, VAL3,", r13")
365 TEST_UNSUPPORTED(__inst_arm(0xe03f3291) " @ mlas pc, r1, r2, r3")
366
367#if __LINUX_ARM_ARCH__ >= 6
368 TEST_RR( "umaal r0, r1, r",2, VAL1,", r",3, VAL2,"")
369 TEST_RR( "umaalls r7, r8, r",9, VAL2,", r",10, VAL1,"")
370 TEST_R( "umaal lr, r12, r",11,VAL3,", r13")
371 TEST_UNSUPPORTED(__inst_arm(0xe041f392) " @ umaal pc, r1, r2, r3")
372 TEST_UNSUPPORTED(__inst_arm(0xe04f0392) " @ umaal r0, pc, r2, r3")
373 TEST_UNSUPPORTED(__inst_arm(0xe0500090) " @ undef")
374 TEST_UNSUPPORTED(__inst_arm(0xe05fff9f) " @ undef")
375#endif
376
377#if __LINUX_ARM_ARCH__ >= 7
378 TEST_RRR( "mls r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
379 TEST_RRR( "mlshi r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
380 TEST_RR( "mls lr, r",1, VAL2,", r",2, VAL3,", r13")
381 TEST_UNSUPPORTED(__inst_arm(0xe06f3291) " @ mls pc, r1, r2, r3")
382 TEST_UNSUPPORTED(__inst_arm(0xe060329f) " @ mls r0, pc, r2, r3")
383 TEST_UNSUPPORTED(__inst_arm(0xe0603f91) " @ mls r0, r1, pc, r3")
384 TEST_UNSUPPORTED(__inst_arm(0xe060f291) " @ mls r0, r1, r2, pc")
385#endif
386
387 TEST_UNSUPPORTED(__inst_arm(0xe0700090) " @ undef")
388 TEST_UNSUPPORTED(__inst_arm(0xe07fff9f) " @ undef")
389
390 TEST_RR( "umull r0, r1, r",2, VAL1,", r",3, VAL2,"")
391 TEST_RR( "umullls r7, r8, r",9, VAL2,", r",10, VAL1,"")
392 TEST_R( "umull lr, r12, r",11,VAL3,", r13")
393 TEST_UNSUPPORTED(__inst_arm(0xe081f392) " @ umull pc, r1, r2, r3")
394 TEST_UNSUPPORTED(__inst_arm(0xe08f1392) " @ umull r1, pc, r2, r3")
395 TEST_RR( "umulls r0, r1, r",2, VAL1,", r",3, VAL2,"")
396 TEST_RR( "umulllss r7, r8, r",9, VAL2,", r",10, VAL1,"")
397 TEST_R( "umulls lr, r12, r",11,VAL3,", r13")
398 TEST_UNSUPPORTED(__inst_arm(0xe091f392) " @ umulls pc, r1, r2, r3")
399 TEST_UNSUPPORTED(__inst_arm(0xe09f1392) " @ umulls r1, pc, r2, r3")
400
401 TEST_RRRR( "umlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
402 TEST_RRRR( "umlalle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
403 TEST_RRR( "umlal r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
404 TEST_UNSUPPORTED(__inst_arm(0xe0af1392) " @ umlal pc, r1, r2, r3")
405 TEST_UNSUPPORTED(__inst_arm(0xe0a1f392) " @ umlal r1, pc, r2, r3")
406 TEST_RRRR( "umlals r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
407 TEST_RRRR( "umlalles r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
408 TEST_RRR( "umlals r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
409 TEST_UNSUPPORTED(__inst_arm(0xe0bf1392) " @ umlals pc, r1, r2, r3")
410 TEST_UNSUPPORTED(__inst_arm(0xe0b1f392) " @ umlals r1, pc, r2, r3")
411
412 TEST_RR( "smull r0, r1, r",2, VAL1,", r",3, VAL2,"")
413 TEST_RR( "smullls r7, r8, r",9, VAL2,", r",10, VAL1,"")
414 TEST_R( "smull lr, r12, r",11,VAL3,", r13")
415 TEST_UNSUPPORTED(__inst_arm(0xe0c1f392) " @ smull pc, r1, r2, r3")
416 TEST_UNSUPPORTED(__inst_arm(0xe0cf1392) " @ smull r1, pc, r2, r3")
417 TEST_RR( "smulls r0, r1, r",2, VAL1,", r",3, VAL2,"")
418 TEST_RR( "smulllss r7, r8, r",9, VAL2,", r",10, VAL1,"")
419 TEST_R( "smulls lr, r12, r",11,VAL3,", r13")
420 TEST_UNSUPPORTED(__inst_arm(0xe0d1f392) " @ smulls pc, r1, r2, r3")
421 TEST_UNSUPPORTED(__inst_arm(0xe0df1392) " @ smulls r1, pc, r2, r3")
422
423 TEST_RRRR( "smlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
424 TEST_RRRR( "smlalle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
425 TEST_RRR( "smlal r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
426 TEST_UNSUPPORTED(__inst_arm(0xe0ef1392) " @ smlal pc, r1, r2, r3")
427 TEST_UNSUPPORTED(__inst_arm(0xe0e1f392) " @ smlal r1, pc, r2, r3")
428 TEST_RRRR( "smlals r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
429 TEST_RRRR( "smlalles r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
430 TEST_RRR( "smlals r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
431 TEST_UNSUPPORTED(__inst_arm(0xe0ff1392) " @ smlals pc, r1, r2, r3")
432 TEST_UNSUPPORTED(__inst_arm(0xe0f0f392) " @ smlals r0, pc, r2, r3")
433 TEST_UNSUPPORTED(__inst_arm(0xe0f0139f) " @ smlals r0, r1, pc, r3")
434 TEST_UNSUPPORTED(__inst_arm(0xe0f01f92) " @ smlals r0, r1, r2, pc")
435
436 TEST_GROUP("Synchronization primitives")
437
438#if __LINUX_ARM_ARCH__ < 6
439 TEST_RP("swp lr, r",7,VAL2,", [r",8,0,"]")
440 TEST_R( "swpvs r0, r",1,VAL1,", [sp]")
441 TEST_RP("swp sp, r",14,VAL2,", [r",12,13*4,"]")
442#else
443 TEST_UNSUPPORTED(__inst_arm(0xe108e097) " @ swp lr, r7, [r8]")
444 TEST_UNSUPPORTED(__inst_arm(0x610d0091) " @ swpvs r0, r1, [sp]")
445 TEST_UNSUPPORTED(__inst_arm(0xe10cd09e) " @ swp sp, r14 [r12]")
446#endif
447 TEST_UNSUPPORTED(__inst_arm(0xe102f091) " @ swp pc, r1, [r2]")
448 TEST_UNSUPPORTED(__inst_arm(0xe102009f) " @ swp r0, pc, [r2]")
449 TEST_UNSUPPORTED(__inst_arm(0xe10f0091) " @ swp r0, r1, [pc]")
450#if __LINUX_ARM_ARCH__ < 6
451 TEST_RP("swpb lr, r",7,VAL2,", [r",8,0,"]")
452 TEST_R( "swpvsb r0, r",1,VAL1,", [sp]")
453#else
454 TEST_UNSUPPORTED(__inst_arm(0xe148e097) " @ swpb lr, r7, [r8]")
455 TEST_UNSUPPORTED(__inst_arm(0x614d0091) " @ swpvsb r0, r1, [sp]")
456#endif
457 TEST_UNSUPPORTED(__inst_arm(0xe142f091) " @ swpb pc, r1, [r2]")
458
459 TEST_UNSUPPORTED(__inst_arm(0xe1100090)) /* Unallocated space */
460 TEST_UNSUPPORTED(__inst_arm(0xe1200090)) /* Unallocated space */
461 TEST_UNSUPPORTED(__inst_arm(0xe1300090)) /* Unallocated space */
462 TEST_UNSUPPORTED(__inst_arm(0xe1500090)) /* Unallocated space */
463 TEST_UNSUPPORTED(__inst_arm(0xe1600090)) /* Unallocated space */
464 TEST_UNSUPPORTED(__inst_arm(0xe1700090)) /* Unallocated space */
465#if __LINUX_ARM_ARCH__ >= 6
466 TEST_UNSUPPORTED("ldrex r2, [sp]")
467#endif
468#if (__LINUX_ARM_ARCH__ >= 7) || defined(CONFIG_CPU_32v6K)
469 TEST_UNSUPPORTED("strexd r0, r2, r3, [sp]")
470 TEST_UNSUPPORTED("ldrexd r2, r3, [sp]")
471 TEST_UNSUPPORTED("strexb r0, r2, [sp]")
472 TEST_UNSUPPORTED("ldrexb r2, [sp]")
473 TEST_UNSUPPORTED("strexh r0, r2, [sp]")
474 TEST_UNSUPPORTED("ldrexh r2, [sp]")
475#endif
476 TEST_GROUP("Extra load/store instructions")
477
478 TEST_RPR( "strh r",0, VAL1,", [r",1, 48,", -r",2, 24,"]")
479 TEST_RPR( "streqh r",14,VAL2,", [r",13,0, ", r",12, 48,"]")
480 TEST_RPR( "strh r",1, VAL1,", [r",2, 24,", r",3, 48,"]!")
481 TEST_RPR( "strneh r",12,VAL2,", [r",11,48,", -r",10,24,"]!")
482 TEST_RPR( "strh r",2, VAL1,", [r",3, 24,"], r",4, 48,"")
483 TEST_RPR( "strh r",10,VAL2,", [r",9, 48,"], -r",11,24,"")
484 TEST_UNSUPPORTED(__inst_arm(0xe1afc0ba) " @ strh r12, [pc, r10]!")
485 TEST_UNSUPPORTED(__inst_arm(0xe089f0bb) " @ strh pc, [r9], r11")
486 TEST_UNSUPPORTED(__inst_arm(0xe089a0bf) " @ strh r10, [r9], pc")
487
488 TEST_PR( "ldrh r0, [r",0, 48,", -r",2, 24,"]")
489 TEST_PR( "ldrcsh r14, [r",13,0, ", r",12, 48,"]")
490 TEST_PR( "ldrh r1, [r",2, 24,", r",3, 48,"]!")
491 TEST_PR( "ldrcch r12, [r",11,48,", -r",10,24,"]!")
492 TEST_PR( "ldrh r2, [r",3, 24,"], r",4, 48,"")
493 TEST_PR( "ldrh r10, [r",9, 48,"], -r",11,24,"")
494 TEST_UNSUPPORTED(__inst_arm(0xe1bfc0ba) " @ ldrh r12, [pc, r10]!")
495 TEST_UNSUPPORTED(__inst_arm(0xe099f0bb) " @ ldrh pc, [r9], r11")
496 TEST_UNSUPPORTED(__inst_arm(0xe099a0bf) " @ ldrh r10, [r9], pc")
497
498 TEST_RP( "strh r",0, VAL1,", [r",1, 24,", #-2]")
499 TEST_RP( "strmih r",14,VAL2,", [r",13,0, ", #2]")
500 TEST_RP( "strh r",1, VAL1,", [r",2, 24,", #4]!")
501 TEST_RP( "strplh r",12,VAL2,", [r",11,24,", #-4]!")
502 TEST_RP( "strh r",2, VAL1,", [r",3, 24,"], #48")
503 TEST_RP( "strh r",10,VAL2,", [r",9, 64,"], #-48")
504 TEST_UNSUPPORTED(__inst_arm(0xe1efc3b0) " @ strh r12, [pc, #48]!")
505 TEST_UNSUPPORTED(__inst_arm(0xe0c9f3b0) " @ strh pc, [r9], #48")
506
507 TEST_P( "ldrh r0, [r",0, 24,", #-2]")
508 TEST_P( "ldrvsh r14, [r",13,0, ", #2]")
509 TEST_P( "ldrh r1, [r",2, 24,", #4]!")
510 TEST_P( "ldrvch r12, [r",11,24,", #-4]!")
511 TEST_P( "ldrh r2, [r",3, 24,"], #48")
512 TEST_P( "ldrh r10, [r",9, 64,"], #-48")
513 TEST( "ldrh r0, [pc, #0]")
514 TEST_UNSUPPORTED(__inst_arm(0xe1ffc3b0) " @ ldrh r12, [pc, #48]!")
515 TEST_UNSUPPORTED(__inst_arm(0xe0d9f3b0) " @ ldrh pc, [r9], #48")
516
517 TEST_PR( "ldrsb r0, [r",0, 48,", -r",2, 24,"]")
518 TEST_PR( "ldrhisb r14, [r",13,0,", r",12, 48,"]")
519 TEST_PR( "ldrsb r1, [r",2, 24,", r",3, 48,"]!")
520 TEST_PR( "ldrlssb r12, [r",11,48,", -r",10,24,"]!")
521 TEST_PR( "ldrsb r2, [r",3, 24,"], r",4, 48,"")
522 TEST_PR( "ldrsb r10, [r",9, 48,"], -r",11,24,"")
523 TEST_UNSUPPORTED(__inst_arm(0xe1bfc0da) " @ ldrsb r12, [pc, r10]!")
524 TEST_UNSUPPORTED(__inst_arm(0xe099f0db) " @ ldrsb pc, [r9], r11")
525
526 TEST_P( "ldrsb r0, [r",0, 24,", #-1]")
527 TEST_P( "ldrgesb r14, [r",13,0, ", #1]")
528 TEST_P( "ldrsb r1, [r",2, 24,", #4]!")
529 TEST_P( "ldrltsb r12, [r",11,24,", #-4]!")
530 TEST_P( "ldrsb r2, [r",3, 24,"], #48")
531 TEST_P( "ldrsb r10, [r",9, 64,"], #-48")
532 TEST( "ldrsb r0, [pc, #0]")
533 TEST_UNSUPPORTED(__inst_arm(0xe1ffc3d0) " @ ldrsb r12, [pc, #48]!")
534 TEST_UNSUPPORTED(__inst_arm(0xe0d9f3d0) " @ ldrsb pc, [r9], #48")
535
536 TEST_PR( "ldrsh r0, [r",0, 48,", -r",2, 24,"]")
537 TEST_PR( "ldrgtsh r14, [r",13,0, ", r",12, 48,"]")
538 TEST_PR( "ldrsh r1, [r",2, 24,", r",3, 48,"]!")
539 TEST_PR( "ldrlesh r12, [r",11,48,", -r",10,24,"]!")
540 TEST_PR( "ldrsh r2, [r",3, 24,"], r",4, 48,"")
541 TEST_PR( "ldrsh r10, [r",9, 48,"], -r",11,24,"")
542 TEST_UNSUPPORTED(__inst_arm(0xe1bfc0fa) " @ ldrsh r12, [pc, r10]!")
543 TEST_UNSUPPORTED(__inst_arm(0xe099f0fb) " @ ldrsh pc, [r9], r11")
544
545 TEST_P( "ldrsh r0, [r",0, 24,", #-1]")
546 TEST_P( "ldreqsh r14, [r",13,0 ,", #1]")
547 TEST_P( "ldrsh r1, [r",2, 24,", #4]!")
548 TEST_P( "ldrnesh r12, [r",11,24,", #-4]!")
549 TEST_P( "ldrsh r2, [r",3, 24,"], #48")
550 TEST_P( "ldrsh r10, [r",9, 64,"], #-48")
551 TEST( "ldrsh r0, [pc, #0]")
552 TEST_UNSUPPORTED(__inst_arm(0xe1ffc3f0) " @ ldrsh r12, [pc, #48]!")
553 TEST_UNSUPPORTED(__inst_arm(0xe0d9f3f0) " @ ldrsh pc, [r9], #48")
554
555#if __LINUX_ARM_ARCH__ >= 7
556 TEST_UNSUPPORTED("strht r1, [r2], r3")
557 TEST_UNSUPPORTED("ldrht r1, [r2], r3")
558 TEST_UNSUPPORTED("strht r1, [r2], #48")
559 TEST_UNSUPPORTED("ldrht r1, [r2], #48")
560 TEST_UNSUPPORTED("ldrsbt r1, [r2], r3")
561 TEST_UNSUPPORTED("ldrsbt r1, [r2], #48")
562 TEST_UNSUPPORTED("ldrsht r1, [r2], r3")
563 TEST_UNSUPPORTED("ldrsht r1, [r2], #48")
564#endif
565
566#if __LINUX_ARM_ARCH__ >= 5
567 TEST_RPR( "strd r",0, VAL1,", [r",1, 48,", -r",2,24,"]")
568 TEST_RPR( "strccd r",8, VAL2,", [r",13,0, ", r",12,48,"]")
569 TEST_RPR( "strd r",4, VAL1,", [r",2, 24,", r",3, 48,"]!")
570 TEST_RPR( "strcsd r",12,VAL2,", [r",11,48,", -r",10,24,"]!")
571 TEST_RPR( "strd r",2, VAL1,", [r",5, 24,"], r",4,48,"")
572 TEST_RPR( "strd r",10,VAL2,", [r",9, 48,"], -r",7,24,"")
573 TEST_UNSUPPORTED(__inst_arm(0xe1afc0fa) " @ strd r12, [pc, r10]!")
574
575 TEST_PR( "ldrd r0, [r",0, 48,", -r",2,24,"]")
576 TEST_PR( "ldrmid r8, [r",13,0, ", r",12,48,"]")
577 TEST_PR( "ldrd r4, [r",2, 24,", r",3, 48,"]!")
578 TEST_PR( "ldrpld r6, [r",11,48,", -r",10,24,"]!")
579 TEST_PR( "ldrd r2, [r",5, 24,"], r",4,48,"")
580 TEST_PR( "ldrd r10, [r",9,48,"], -r",7,24,"")
581 TEST_UNSUPPORTED(__inst_arm(0xe1afc0da) " @ ldrd r12, [pc, r10]!")
582 TEST_UNSUPPORTED(__inst_arm(0xe089f0db) " @ ldrd pc, [r9], r11")
583 TEST_UNSUPPORTED(__inst_arm(0xe089e0db) " @ ldrd lr, [r9], r11")
584 TEST_UNSUPPORTED(__inst_arm(0xe089c0df) " @ ldrd r12, [r9], pc")
585
586 TEST_RP( "strd r",0, VAL1,", [r",1, 24,", #-8]")
587 TEST_RP( "strvsd r",8, VAL2,", [r",13,0, ", #8]")
588 TEST_RP( "strd r",4, VAL1,", [r",2, 24,", #16]!")
589 TEST_RP( "strvcd r",12,VAL2,", [r",11,24,", #-16]!")
590 TEST_RP( "strd r",2, VAL1,", [r",4, 24,"], #48")
591 TEST_RP( "strd r",10,VAL2,", [r",9, 64,"], #-48")
592 TEST_UNSUPPORTED(__inst_arm(0xe1efc3f0) " @ strd r12, [pc, #48]!")
593
594 TEST_P( "ldrd r0, [r",0, 24,", #-8]")
595 TEST_P( "ldrhid r8, [r",13,0, ", #8]")
596 TEST_P( "ldrd r4, [r",2, 24,", #16]!")
597 TEST_P( "ldrlsd r6, [r",11,24,", #-16]!")
598 TEST_P( "ldrd r2, [r",5, 24,"], #48")
599 TEST_P( "ldrd r10, [r",9,6,"], #-48")
600 TEST_UNSUPPORTED(__inst_arm(0xe1efc3d0) " @ ldrd r12, [pc, #48]!")
601 TEST_UNSUPPORTED(__inst_arm(0xe0c9f3d0) " @ ldrd pc, [r9], #48")
602 TEST_UNSUPPORTED(__inst_arm(0xe0c9e3d0) " @ ldrd lr, [r9], #48")
603#endif
604
605 TEST_GROUP("Miscellaneous")
606
607#if __LINUX_ARM_ARCH__ >= 7
608 TEST("movw r0, #0")
609 TEST("movw r0, #0xffff")
610 TEST("movw lr, #0xffff")
611 TEST_UNSUPPORTED(__inst_arm(0xe300f000) " @ movw pc, #0")
612 TEST_R("movt r",0, VAL1,", #0")
613 TEST_R("movt r",0, VAL2,", #0xffff")
614 TEST_R("movt r",14,VAL1,", #0xffff")
615 TEST_UNSUPPORTED(__inst_arm(0xe340f000) " @ movt pc, #0")
616#endif
617
618 TEST_UNSUPPORTED("msr cpsr, 0x13")
619 TEST_UNSUPPORTED("msr cpsr_f, 0xf0000000")
620 TEST_UNSUPPORTED("msr spsr, 0x13")
621
622#if __LINUX_ARM_ARCH__ >= 7
623 TEST_SUPPORTED("yield")
624 TEST("sev")
625 TEST("nop")
626 TEST("wfi")
627 TEST_SUPPORTED("wfe")
628 TEST_UNSUPPORTED("dbg #0")
629#endif
630
631 TEST_GROUP("Load/store word and unsigned byte")
632
633#define LOAD_STORE(byte) \
634 TEST_RP( "str"byte" r",0, VAL1,", [r",1, 24,", #-2]") \
635 TEST_RP( "str"byte" r",14,VAL2,", [r",13,0, ", #2]") \
636 TEST_RP( "str"byte" r",1, VAL1,", [r",2, 24,", #4]!") \
637 TEST_RP( "str"byte" r",12,VAL2,", [r",11,24,", #-4]!") \
638 TEST_RP( "str"byte" r",2, VAL1,", [r",3, 24,"], #48") \
639 TEST_RP( "str"byte" r",10,VAL2,", [r",9, 64,"], #-48") \
640 TEST_RPR("str"byte" r",0, VAL1,", [r",1, 48,", -r",2, 24,"]") \
641 TEST_RPR("str"byte" r",14,VAL2,", [r",13,0, ", r",12, 48,"]") \
642 TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 48,"]!") \
643 TEST_RPR("str"byte" r",12,VAL2,", [r",11,48,", -r",10,24,"]!") \
644 TEST_RPR("str"byte" r",2, VAL1,", [r",3, 24,"], r",4, 48,"") \
645 TEST_RPR("str"byte" r",10,VAL2,", [r",9, 48,"], -r",11,24,"") \
646 TEST_RPR("str"byte" r",0, VAL1,", [r",1, 24,", r",2, 32,", asl #1]")\
647 TEST_RPR("str"byte" r",14,VAL2,", [r",13,0, ", r",12, 32,", lsr #2]")\
648 TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 32,", asr #3]!")\
649 TEST_RPR("str"byte" r",12,VAL2,", [r",11,24,", r",10, 4,", ror #31]!")\
650 TEST_P( "ldr"byte" r0, [r",0, 24,", #-2]") \
651 TEST_P( "ldr"byte" r14, [r",13,0, ", #2]") \
652 TEST_P( "ldr"byte" r1, [r",2, 24,", #4]!") \
653 TEST_P( "ldr"byte" r12, [r",11,24,", #-4]!") \
654 TEST_P( "ldr"byte" r2, [r",3, 24,"], #48") \
655 TEST_P( "ldr"byte" r10, [r",9, 64,"], #-48") \
656 TEST_PR( "ldr"byte" r0, [r",0, 48,", -r",2, 24,"]") \
657 TEST_PR( "ldr"byte" r14, [r",13,0, ", r",12, 48,"]") \
658 TEST_PR( "ldr"byte" r1, [r",2, 24,", r",3, 48,"]!") \
659 TEST_PR( "ldr"byte" r12, [r",11,48,", -r",10,24,"]!") \
660 TEST_PR( "ldr"byte" r2, [r",3, 24,"], r",4, 48,"") \
661 TEST_PR( "ldr"byte" r10, [r",9, 48,"], -r",11,24,"") \
662 TEST_PR( "ldr"byte" r0, [r",0, 24,", r",2, 32,", asl #1]") \
663 TEST_PR( "ldr"byte" r14, [r",13,0, ", r",12, 32,", lsr #2]") \
664 TEST_PR( "ldr"byte" r1, [r",2, 24,", r",3, 32,", asr #3]!") \
665 TEST_PR( "ldr"byte" r12, [r",11,24,", r",10, 4,", ror #31]!") \
666 TEST( "ldr"byte" r0, [pc, #0]") \
667 TEST_R( "ldr"byte" r12, [pc, r",14,0,"]")
668
669 LOAD_STORE("")
670 TEST_P( "str pc, [r",0,0,", #15*4]")
671 TEST_R( "str pc, [sp, r",2,15*4,"]")
672 TEST_BF( "ldr pc, [sp, #15*4]")
673 TEST_BF_R("ldr pc, [sp, r",2,15*4,"]")
674
675 TEST_P( "str sp, [r",0,0,", #13*4]")
676 TEST_R( "str sp, [sp, r",2,13*4,"]")
677 TEST_BF( "ldr sp, [sp, #13*4]")
678 TEST_BF_R("ldr sp, [sp, r",2,13*4,"]")
679
680#ifdef CONFIG_THUMB2_KERNEL
681 TEST_ARM_TO_THUMB_INTERWORK_P("ldr pc, [r",0,0,", #15*4]")
682#endif
683 TEST_UNSUPPORTED(__inst_arm(0xe5af6008) " @ str r6, [pc, #8]!")
684 TEST_UNSUPPORTED(__inst_arm(0xe7af6008) " @ str r6, [pc, r8]!")
685 TEST_UNSUPPORTED(__inst_arm(0xe5bf6008) " @ ldr r6, [pc, #8]!")
686 TEST_UNSUPPORTED(__inst_arm(0xe7bf6008) " @ ldr r6, [pc, r8]!")
687 TEST_UNSUPPORTED(__inst_arm(0xe788600f) " @ str r6, [r8, pc]")
688 TEST_UNSUPPORTED(__inst_arm(0xe798600f) " @ ldr r6, [r8, pc]")
689
690 LOAD_STORE("b")
691 TEST_UNSUPPORTED(__inst_arm(0xe5f7f008) " @ ldrb pc, [r7, #8]!")
692 TEST_UNSUPPORTED(__inst_arm(0xe7f7f008) " @ ldrb pc, [r7, r8]!")
693 TEST_UNSUPPORTED(__inst_arm(0xe5ef6008) " @ strb r6, [pc, #8]!")
694 TEST_UNSUPPORTED(__inst_arm(0xe7ef6008) " @ strb r6, [pc, r3]!")
695 TEST_UNSUPPORTED(__inst_arm(0xe5ff6008) " @ ldrb r6, [pc, #8]!")
696 TEST_UNSUPPORTED(__inst_arm(0xe7ff6008) " @ ldrb r6, [pc, r3]!")
697
698 TEST_UNSUPPORTED("ldrt r0, [r1], #4")
699 TEST_UNSUPPORTED("ldrt r1, [r2], r3")
700 TEST_UNSUPPORTED("strt r2, [r3], #4")
701 TEST_UNSUPPORTED("strt r3, [r4], r5")
702 TEST_UNSUPPORTED("ldrbt r4, [r5], #4")
703 TEST_UNSUPPORTED("ldrbt r5, [r6], r7")
704 TEST_UNSUPPORTED("strbt r6, [r7], #4")
705 TEST_UNSUPPORTED("strbt r7, [r8], r9")
706
707#if __LINUX_ARM_ARCH__ >= 7
708 TEST_GROUP("Parallel addition and subtraction, signed")
709
710 TEST_UNSUPPORTED(__inst_arm(0xe6000010) "") /* Unallocated space */
711 TEST_UNSUPPORTED(__inst_arm(0xe60fffff) "") /* Unallocated space */
712
713 TEST_RR( "sadd16 r0, r",0, HH1,", r",1, HH2,"")
714 TEST_RR( "sadd16 r14, r",12,HH2,", r",10,HH1,"")
715 TEST_UNSUPPORTED(__inst_arm(0xe61cff1a) " @ sadd16 pc, r12, r10")
716 TEST_RR( "sasx r0, r",0, HH1,", r",1, HH2,"")
717 TEST_RR( "sasx r14, r",12,HH2,", r",10,HH1,"")
718 TEST_UNSUPPORTED(__inst_arm(0xe61cff3a) " @ sasx pc, r12, r10")
719 TEST_RR( "ssax r0, r",0, HH1,", r",1, HH2,"")
720 TEST_RR( "ssax r14, r",12,HH2,", r",10,HH1,"")
721 TEST_UNSUPPORTED(__inst_arm(0xe61cff5a) " @ ssax pc, r12, r10")
722 TEST_RR( "ssub16 r0, r",0, HH1,", r",1, HH2,"")
723 TEST_RR( "ssub16 r14, r",12,HH2,", r",10,HH1,"")
724 TEST_UNSUPPORTED(__inst_arm(0xe61cff7a) " @ ssub16 pc, r12, r10")
725 TEST_RR( "sadd8 r0, r",0, HH1,", r",1, HH2,"")
726 TEST_RR( "sadd8 r14, r",12,HH2,", r",10,HH1,"")
727 TEST_UNSUPPORTED(__inst_arm(0xe61cff9a) " @ sadd8 pc, r12, r10")
728 TEST_UNSUPPORTED(__inst_arm(0xe61000b0) "") /* Unallocated space */
729 TEST_UNSUPPORTED(__inst_arm(0xe61fffbf) "") /* Unallocated space */
730 TEST_UNSUPPORTED(__inst_arm(0xe61000d0) "") /* Unallocated space */
731 TEST_UNSUPPORTED(__inst_arm(0xe61fffdf) "") /* Unallocated space */
732 TEST_RR( "ssub8 r0, r",0, HH1,", r",1, HH2,"")
733 TEST_RR( "ssub8 r14, r",12,HH2,", r",10,HH1,"")
734 TEST_UNSUPPORTED(__inst_arm(0xe61cfffa) " @ ssub8 pc, r12, r10")
735
736 TEST_RR( "qadd16 r0, r",0, HH1,", r",1, HH2,"")
737 TEST_RR( "qadd16 r14, r",12,HH2,", r",10,HH1,"")
738 TEST_UNSUPPORTED(__inst_arm(0xe62cff1a) " @ qadd16 pc, r12, r10")
739 TEST_RR( "qasx r0, r",0, HH1,", r",1, HH2,"")
740 TEST_RR( "qasx r14, r",12,HH2,", r",10,HH1,"")
741 TEST_UNSUPPORTED(__inst_arm(0xe62cff3a) " @ qasx pc, r12, r10")
742 TEST_RR( "qsax r0, r",0, HH1,", r",1, HH2,"")
743 TEST_RR( "qsax r14, r",12,HH2,", r",10,HH1,"")
744 TEST_UNSUPPORTED(__inst_arm(0xe62cff5a) " @ qsax pc, r12, r10")
745 TEST_RR( "qsub16 r0, r",0, HH1,", r",1, HH2,"")
746 TEST_RR( "qsub16 r14, r",12,HH2,", r",10,HH1,"")
747 TEST_UNSUPPORTED(__inst_arm(0xe62cff7a) " @ qsub16 pc, r12, r10")
748 TEST_RR( "qadd8 r0, r",0, HH1,", r",1, HH2,"")
749 TEST_RR( "qadd8 r14, r",12,HH2,", r",10,HH1,"")
750 TEST_UNSUPPORTED(__inst_arm(0xe62cff9a) " @ qadd8 pc, r12, r10")
751 TEST_UNSUPPORTED(__inst_arm(0xe62000b0) "") /* Unallocated space */
752 TEST_UNSUPPORTED(__inst_arm(0xe62fffbf) "") /* Unallocated space */
753 TEST_UNSUPPORTED(__inst_arm(0xe62000d0) "") /* Unallocated space */
754 TEST_UNSUPPORTED(__inst_arm(0xe62fffdf) "") /* Unallocated space */
755 TEST_RR( "qsub8 r0, r",0, HH1,", r",1, HH2,"")
756 TEST_RR( "qsub8 r14, r",12,HH2,", r",10,HH1,"")
757 TEST_UNSUPPORTED(__inst_arm(0xe62cfffa) " @ qsub8 pc, r12, r10")
758
759 TEST_RR( "shadd16 r0, r",0, HH1,", r",1, HH2,"")
760 TEST_RR( "shadd16 r14, r",12,HH2,", r",10,HH1,"")
761 TEST_UNSUPPORTED(__inst_arm(0xe63cff1a) " @ shadd16 pc, r12, r10")
762 TEST_RR( "shasx r0, r",0, HH1,", r",1, HH2,"")
763 TEST_RR( "shasx r14, r",12,HH2,", r",10,HH1,"")
764 TEST_UNSUPPORTED(__inst_arm(0xe63cff3a) " @ shasx pc, r12, r10")
765 TEST_RR( "shsax r0, r",0, HH1,", r",1, HH2,"")
766 TEST_RR( "shsax r14, r",12,HH2,", r",10,HH1,"")
767 TEST_UNSUPPORTED(__inst_arm(0xe63cff5a) " @ shsax pc, r12, r10")
768 TEST_RR( "shsub16 r0, r",0, HH1,", r",1, HH2,"")
769 TEST_RR( "shsub16 r14, r",12,HH2,", r",10,HH1,"")
770 TEST_UNSUPPORTED(__inst_arm(0xe63cff7a) " @ shsub16 pc, r12, r10")
771 TEST_RR( "shadd8 r0, r",0, HH1,", r",1, HH2,"")
772 TEST_RR( "shadd8 r14, r",12,HH2,", r",10,HH1,"")
773 TEST_UNSUPPORTED(__inst_arm(0xe63cff9a) " @ shadd8 pc, r12, r10")
774 TEST_UNSUPPORTED(__inst_arm(0xe63000b0) "") /* Unallocated space */
775 TEST_UNSUPPORTED(__inst_arm(0xe63fffbf) "") /* Unallocated space */
776 TEST_UNSUPPORTED(__inst_arm(0xe63000d0) "") /* Unallocated space */
777 TEST_UNSUPPORTED(__inst_arm(0xe63fffdf) "") /* Unallocated space */
778 TEST_RR( "shsub8 r0, r",0, HH1,", r",1, HH2,"")
779 TEST_RR( "shsub8 r14, r",12,HH2,", r",10,HH1,"")
780 TEST_UNSUPPORTED(__inst_arm(0xe63cfffa) " @ shsub8 pc, r12, r10")
781
782 TEST_GROUP("Parallel addition and subtraction, unsigned")
783
784 TEST_UNSUPPORTED(__inst_arm(0xe6400010) "") /* Unallocated space */
785 TEST_UNSUPPORTED(__inst_arm(0xe64fffff) "") /* Unallocated space */
786
787 TEST_RR( "uadd16 r0, r",0, HH1,", r",1, HH2,"")
788 TEST_RR( "uadd16 r14, r",12,HH2,", r",10,HH1,"")
789 TEST_UNSUPPORTED(__inst_arm(0xe65cff1a) " @ uadd16 pc, r12, r10")
790 TEST_RR( "uasx r0, r",0, HH1,", r",1, HH2,"")
791 TEST_RR( "uasx r14, r",12,HH2,", r",10,HH1,"")
792 TEST_UNSUPPORTED(__inst_arm(0xe65cff3a) " @ uasx pc, r12, r10")
793 TEST_RR( "usax r0, r",0, HH1,", r",1, HH2,"")
794 TEST_RR( "usax r14, r",12,HH2,", r",10,HH1,"")
795 TEST_UNSUPPORTED(__inst_arm(0xe65cff5a) " @ usax pc, r12, r10")
796 TEST_RR( "usub16 r0, r",0, HH1,", r",1, HH2,"")
797 TEST_RR( "usub16 r14, r",12,HH2,", r",10,HH1,"")
798 TEST_UNSUPPORTED(__inst_arm(0xe65cff7a) " @ usub16 pc, r12, r10")
799 TEST_RR( "uadd8 r0, r",0, HH1,", r",1, HH2,"")
800 TEST_RR( "uadd8 r14, r",12,HH2,", r",10,HH1,"")
801 TEST_UNSUPPORTED(__inst_arm(0xe65cff9a) " @ uadd8 pc, r12, r10")
802 TEST_UNSUPPORTED(__inst_arm(0xe65000b0) "") /* Unallocated space */
803 TEST_UNSUPPORTED(__inst_arm(0xe65fffbf) "") /* Unallocated space */
804 TEST_UNSUPPORTED(__inst_arm(0xe65000d0) "") /* Unallocated space */
805 TEST_UNSUPPORTED(__inst_arm(0xe65fffdf) "") /* Unallocated space */
806 TEST_RR( "usub8 r0, r",0, HH1,", r",1, HH2,"")
807 TEST_RR( "usub8 r14, r",12,HH2,", r",10,HH1,"")
808 TEST_UNSUPPORTED(__inst_arm(0xe65cfffa) " @ usub8 pc, r12, r10")
809
810 TEST_RR( "uqadd16 r0, r",0, HH1,", r",1, HH2,"")
811 TEST_RR( "uqadd16 r14, r",12,HH2,", r",10,HH1,"")
812 TEST_UNSUPPORTED(__inst_arm(0xe66cff1a) " @ uqadd16 pc, r12, r10")
813 TEST_RR( "uqasx r0, r",0, HH1,", r",1, HH2,"")
814 TEST_RR( "uqasx r14, r",12,HH2,", r",10,HH1,"")
815 TEST_UNSUPPORTED(__inst_arm(0xe66cff3a) " @ uqasx pc, r12, r10")
816 TEST_RR( "uqsax r0, r",0, HH1,", r",1, HH2,"")
817 TEST_RR( "uqsax r14, r",12,HH2,", r",10,HH1,"")
818 TEST_UNSUPPORTED(__inst_arm(0xe66cff5a) " @ uqsax pc, r12, r10")
819 TEST_RR( "uqsub16 r0, r",0, HH1,", r",1, HH2,"")
820 TEST_RR( "uqsub16 r14, r",12,HH2,", r",10,HH1,"")
821 TEST_UNSUPPORTED(__inst_arm(0xe66cff7a) " @ uqsub16 pc, r12, r10")
822 TEST_RR( "uqadd8 r0, r",0, HH1,", r",1, HH2,"")
823 TEST_RR( "uqadd8 r14, r",12,HH2,", r",10,HH1,"")
824 TEST_UNSUPPORTED(__inst_arm(0xe66cff9a) " @ uqadd8 pc, r12, r10")
825 TEST_UNSUPPORTED(__inst_arm(0xe66000b0) "") /* Unallocated space */
826 TEST_UNSUPPORTED(__inst_arm(0xe66fffbf) "") /* Unallocated space */
827 TEST_UNSUPPORTED(__inst_arm(0xe66000d0) "") /* Unallocated space */
828 TEST_UNSUPPORTED(__inst_arm(0xe66fffdf) "") /* Unallocated space */
829 TEST_RR( "uqsub8 r0, r",0, HH1,", r",1, HH2,"")
830 TEST_RR( "uqsub8 r14, r",12,HH2,", r",10,HH1,"")
831 TEST_UNSUPPORTED(__inst_arm(0xe66cfffa) " @ uqsub8 pc, r12, r10")
832
833 TEST_RR( "uhadd16 r0, r",0, HH1,", r",1, HH2,"")
834 TEST_RR( "uhadd16 r14, r",12,HH2,", r",10,HH1,"")
835 TEST_UNSUPPORTED(__inst_arm(0xe67cff1a) " @ uhadd16 pc, r12, r10")
836 TEST_RR( "uhasx r0, r",0, HH1,", r",1, HH2,"")
837 TEST_RR( "uhasx r14, r",12,HH2,", r",10,HH1,"")
838 TEST_UNSUPPORTED(__inst_arm(0xe67cff3a) " @ uhasx pc, r12, r10")
839 TEST_RR( "uhsax r0, r",0, HH1,", r",1, HH2,"")
840 TEST_RR( "uhsax r14, r",12,HH2,", r",10,HH1,"")
841 TEST_UNSUPPORTED(__inst_arm(0xe67cff5a) " @ uhsax pc, r12, r10")
842 TEST_RR( "uhsub16 r0, r",0, HH1,", r",1, HH2,"")
843 TEST_RR( "uhsub16 r14, r",12,HH2,", r",10,HH1,"")
844 TEST_UNSUPPORTED(__inst_arm(0xe67cff7a) " @ uhsub16 pc, r12, r10")
845 TEST_RR( "uhadd8 r0, r",0, HH1,", r",1, HH2,"")
846 TEST_RR( "uhadd8 r14, r",12,HH2,", r",10,HH1,"")
847 TEST_UNSUPPORTED(__inst_arm(0xe67cff9a) " @ uhadd8 pc, r12, r10")
848 TEST_UNSUPPORTED(__inst_arm(0xe67000b0) "") /* Unallocated space */
849 TEST_UNSUPPORTED(__inst_arm(0xe67fffbf) "") /* Unallocated space */
850 TEST_UNSUPPORTED(__inst_arm(0xe67000d0) "") /* Unallocated space */
851 TEST_UNSUPPORTED(__inst_arm(0xe67fffdf) "") /* Unallocated space */
852 TEST_RR( "uhsub8 r0, r",0, HH1,", r",1, HH2,"")
853 TEST_RR( "uhsub8 r14, r",12,HH2,", r",10,HH1,"")
854 TEST_UNSUPPORTED(__inst_arm(0xe67cfffa) " @ uhsub8 pc, r12, r10")
855 TEST_UNSUPPORTED(__inst_arm(0xe67feffa) " @ uhsub8 r14, pc, r10")
856 TEST_UNSUPPORTED(__inst_arm(0xe67cefff) " @ uhsub8 r14, r12, pc")
857#endif /* __LINUX_ARM_ARCH__ >= 7 */
858
859#if __LINUX_ARM_ARCH__ >= 6
860 TEST_GROUP("Packing, unpacking, saturation, and reversal")
861
862 TEST_RR( "pkhbt r0, r",0, HH1,", r",1, HH2,"")
863 TEST_RR( "pkhbt r14,r",12, HH1,", r",10,HH2,", lsl #2")
864 TEST_UNSUPPORTED(__inst_arm(0xe68cf11a) " @ pkhbt pc, r12, r10, lsl #2")
865 TEST_RR( "pkhtb r0, r",0, HH1,", r",1, HH2,"")
866 TEST_RR( "pkhtb r14,r",12, HH1,", r",10,HH2,", asr #2")
867 TEST_UNSUPPORTED(__inst_arm(0xe68cf15a) " @ pkhtb pc, r12, r10, asr #2")
868 TEST_UNSUPPORTED(__inst_arm(0xe68fe15a) " @ pkhtb r14, pc, r10, asr #2")
869 TEST_UNSUPPORTED(__inst_arm(0xe68ce15f) " @ pkhtb r14, r12, pc, asr #2")
870 TEST_UNSUPPORTED(__inst_arm(0xe6900010) "") /* Unallocated space */
871 TEST_UNSUPPORTED(__inst_arm(0xe69fffdf) "") /* Unallocated space */
872
873 TEST_R( "ssat r0, #24, r",0, VAL1,"")
874 TEST_R( "ssat r14, #24, r",12, VAL2,"")
875 TEST_R( "ssat r0, #24, r",0, VAL1,", lsl #8")
876 TEST_R( "ssat r14, #24, r",12, VAL2,", asr #8")
877 TEST_UNSUPPORTED(__inst_arm(0xe6b7f01c) " @ ssat pc, #24, r12")
878
879 TEST_R( "usat r0, #24, r",0, VAL1,"")
880 TEST_R( "usat r14, #24, r",12, VAL2,"")
881 TEST_R( "usat r0, #24, r",0, VAL1,", lsl #8")
882 TEST_R( "usat r14, #24, r",12, VAL2,", asr #8")
883 TEST_UNSUPPORTED(__inst_arm(0xe6f7f01c) " @ usat pc, #24, r12")
884
885 TEST_RR( "sxtab16 r0, r",0, HH1,", r",1, HH2,"")
886 TEST_RR( "sxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8")
887 TEST_R( "sxtb16 r8, r",7, HH1,"")
888 TEST_UNSUPPORTED(__inst_arm(0xe68cf47a) " @ sxtab16 pc,r12, r10, ror #8")
889
890 TEST_RR( "sel r0, r",0, VAL1,", r",1, VAL2,"")
891 TEST_RR( "sel r14, r",12,VAL1,", r",10, VAL2,"")
892 TEST_UNSUPPORTED(__inst_arm(0xe68cffba) " @ sel pc, r12, r10")
893 TEST_UNSUPPORTED(__inst_arm(0xe68fefba) " @ sel r14, pc, r10")
894 TEST_UNSUPPORTED(__inst_arm(0xe68cefbf) " @ sel r14, r12, pc")
895
896 TEST_R( "ssat16 r0, #12, r",0, HH1,"")
897 TEST_R( "ssat16 r14, #12, r",12, HH2,"")
898 TEST_UNSUPPORTED(__inst_arm(0xe6abff3c) " @ ssat16 pc, #12, r12")
899
900 TEST_RR( "sxtab r0, r",0, HH1,", r",1, HH2,"")
901 TEST_RR( "sxtab r14,r",12, HH2,", r",10,HH1,", ror #8")
902 TEST_R( "sxtb r8, r",7, HH1,"")
903 TEST_UNSUPPORTED(__inst_arm(0xe6acf47a) " @ sxtab pc,r12, r10, ror #8")
904
905 TEST_R( "rev r0, r",0, VAL1,"")
906 TEST_R( "rev r14, r",12, VAL2,"")
907 TEST_UNSUPPORTED(__inst_arm(0xe6bfff3c) " @ rev pc, r12")
908
909 TEST_RR( "sxtah r0, r",0, HH1,", r",1, HH2,"")
910 TEST_RR( "sxtah r14,r",12, HH2,", r",10,HH1,", ror #8")
911 TEST_R( "sxth r8, r",7, HH1,"")
912 TEST_UNSUPPORTED(__inst_arm(0xe6bcf47a) " @ sxtah pc,r12, r10, ror #8")
913
914 TEST_R( "rev16 r0, r",0, VAL1,"")
915 TEST_R( "rev16 r14, r",12, VAL2,"")
916 TEST_UNSUPPORTED(__inst_arm(0xe6bfffbc) " @ rev16 pc, r12")
917
918 TEST_RR( "uxtab16 r0, r",0, HH1,", r",1, HH2,"")
919 TEST_RR( "uxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8")
920 TEST_R( "uxtb16 r8, r",7, HH1,"")
921 TEST_UNSUPPORTED(__inst_arm(0xe6ccf47a) " @ uxtab16 pc,r12, r10, ror #8")
922
923 TEST_R( "usat16 r0, #12, r",0, HH1,"")
924 TEST_R( "usat16 r14, #12, r",12, HH2,"")
925 TEST_UNSUPPORTED(__inst_arm(0xe6ecff3c) " @ usat16 pc, #12, r12")
926 TEST_UNSUPPORTED(__inst_arm(0xe6ecef3f) " @ usat16 r14, #12, pc")
927
928 TEST_RR( "uxtab r0, r",0, HH1,", r",1, HH2,"")
929 TEST_RR( "uxtab r14,r",12, HH2,", r",10,HH1,", ror #8")
930 TEST_R( "uxtb r8, r",7, HH1,"")
931 TEST_UNSUPPORTED(__inst_arm(0xe6ecf47a) " @ uxtab pc,r12, r10, ror #8")
932
933#if __LINUX_ARM_ARCH__ >= 7
934 TEST_R( "rbit r0, r",0, VAL1,"")
935 TEST_R( "rbit r14, r",12, VAL2,"")
936 TEST_UNSUPPORTED(__inst_arm(0xe6ffff3c) " @ rbit pc, r12")
937#endif
938
939 TEST_RR( "uxtah r0, r",0, HH1,", r",1, HH2,"")
940 TEST_RR( "uxtah r14,r",12, HH2,", r",10,HH1,", ror #8")
941 TEST_R( "uxth r8, r",7, HH1,"")
942 TEST_UNSUPPORTED(__inst_arm(0xe6fff077) " @ uxth pc, r7")
943 TEST_UNSUPPORTED(__inst_arm(0xe6ff807f) " @ uxth r8, pc")
944 TEST_UNSUPPORTED(__inst_arm(0xe6fcf47a) " @ uxtah pc, r12, r10, ror #8")
945 TEST_UNSUPPORTED(__inst_arm(0xe6fce47f) " @ uxtah r14, r12, pc, ror #8")
946
947 TEST_R( "revsh r0, r",0, VAL1,"")
948 TEST_R( "revsh r14, r",12, VAL2,"")
949 TEST_UNSUPPORTED(__inst_arm(0xe6ffff3c) " @ revsh pc, r12")
950 TEST_UNSUPPORTED(__inst_arm(0xe6ffef3f) " @ revsh r14, pc")
951
952 TEST_UNSUPPORTED(__inst_arm(0xe6900070) "") /* Unallocated space */
953 TEST_UNSUPPORTED(__inst_arm(0xe69fff7f) "") /* Unallocated space */
954
955 TEST_UNSUPPORTED(__inst_arm(0xe6d00070) "") /* Unallocated space */
956 TEST_UNSUPPORTED(__inst_arm(0xe6dfff7f) "") /* Unallocated space */
957#endif /* __LINUX_ARM_ARCH__ >= 6 */
958
959#if __LINUX_ARM_ARCH__ >= 6
960 TEST_GROUP("Signed multiplies")
961
962 TEST_RRR( "smlad r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
963 TEST_RRR( "smlad r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
964 TEST_UNSUPPORTED(__inst_arm(0xe70f8a1c) " @ smlad pc, r12, r10, r8")
965 TEST_RRR( "smladx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
966 TEST_RRR( "smladx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
967 TEST_UNSUPPORTED(__inst_arm(0xe70f8a3c) " @ smladx pc, r12, r10, r8")
968
969 TEST_RR( "smuad r0, r",0, HH1,", r",1, HH2,"")
970 TEST_RR( "smuad r14, r",12,HH2,", r",10,HH1,"")
971 TEST_UNSUPPORTED(__inst_arm(0xe70ffa1c) " @ smuad pc, r12, r10")
972 TEST_RR( "smuadx r0, r",0, HH1,", r",1, HH2,"")
973 TEST_RR( "smuadx r14, r",12,HH2,", r",10,HH1,"")
974 TEST_UNSUPPORTED(__inst_arm(0xe70ffa3c) " @ smuadx pc, r12, r10")
975
976 TEST_RRR( "smlsd r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
977 TEST_RRR( "smlsd r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
978 TEST_UNSUPPORTED(__inst_arm(0xe70f8a5c) " @ smlsd pc, r12, r10, r8")
979 TEST_RRR( "smlsdx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
980 TEST_RRR( "smlsdx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
981 TEST_UNSUPPORTED(__inst_arm(0xe70f8a7c) " @ smlsdx pc, r12, r10, r8")
982
983 TEST_RR( "smusd r0, r",0, HH1,", r",1, HH2,"")
984 TEST_RR( "smusd r14, r",12,HH2,", r",10,HH1,"")
985 TEST_UNSUPPORTED(__inst_arm(0xe70ffa5c) " @ smusd pc, r12, r10")
986 TEST_RR( "smusdx r0, r",0, HH1,", r",1, HH2,"")
987 TEST_RR( "smusdx r14, r",12,HH2,", r",10,HH1,"")
988 TEST_UNSUPPORTED(__inst_arm(0xe70ffa7c) " @ smusdx pc, r12, r10")
989
990 TEST_RRRR( "smlald r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
991 TEST_RRRR( "smlald r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
992 TEST_UNSUPPORTED(__inst_arm(0xe74af819) " @ smlald pc, r10, r9, r8")
993 TEST_UNSUPPORTED(__inst_arm(0xe74fb819) " @ smlald r11, pc, r9, r8")
994 TEST_UNSUPPORTED(__inst_arm(0xe74ab81f) " @ smlald r11, r10, pc, r8")
995 TEST_UNSUPPORTED(__inst_arm(0xe74abf19) " @ smlald r11, r10, r9, pc")
996
997 TEST_RRRR( "smlaldx r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
998 TEST_RRRR( "smlaldx r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
999 TEST_UNSUPPORTED(__inst_arm(0xe74af839) " @ smlaldx pc, r10, r9, r8")
1000 TEST_UNSUPPORTED(__inst_arm(0xe74fb839) " @ smlaldx r11, pc, r9, r8")
1001
1002 TEST_RRR( "smmla r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
1003 TEST_RRR( "smmla r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
1004 TEST_UNSUPPORTED(__inst_arm(0xe75f8a1c) " @ smmla pc, r12, r10, r8")
1005 TEST_RRR( "smmlar r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
1006 TEST_RRR( "smmlar r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
1007 TEST_UNSUPPORTED(__inst_arm(0xe75f8a3c) " @ smmlar pc, r12, r10, r8")
1008
1009 TEST_RR( "smmul r0, r",0, VAL1,", r",1, VAL2,"")
1010 TEST_RR( "smmul r14, r",12,VAL2,", r",10,VAL1,"")
1011 TEST_UNSUPPORTED(__inst_arm(0xe75ffa1c) " @ smmul pc, r12, r10")
1012 TEST_RR( "smmulr r0, r",0, VAL1,", r",1, VAL2,"")
1013 TEST_RR( "smmulr r14, r",12,VAL2,", r",10,VAL1,"")
1014 TEST_UNSUPPORTED(__inst_arm(0xe75ffa3c) " @ smmulr pc, r12, r10")
1015
1016 TEST_RRR( "smmls r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
1017 TEST_RRR( "smmls r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
1018 TEST_UNSUPPORTED(__inst_arm(0xe75f8adc) " @ smmls pc, r12, r10, r8")
1019 TEST_RRR( "smmlsr r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
1020 TEST_RRR( "smmlsr r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
1021 TEST_UNSUPPORTED(__inst_arm(0xe75f8afc) " @ smmlsr pc, r12, r10, r8")
1022 TEST_UNSUPPORTED(__inst_arm(0xe75e8aff) " @ smmlsr r14, pc, r10, r8")
1023 TEST_UNSUPPORTED(__inst_arm(0xe75e8ffc) " @ smmlsr r14, r12, pc, r8")
1024 TEST_UNSUPPORTED(__inst_arm(0xe75efafc) " @ smmlsr r14, r12, r10, pc")
1025
1026 TEST_RR( "usad8 r0, r",0, VAL1,", r",1, VAL2,"")
1027 TEST_RR( "usad8 r14, r",12,VAL2,", r",10,VAL1,"")
1028 TEST_UNSUPPORTED(__inst_arm(0xe75ffa1c) " @ usad8 pc, r12, r10")
1029 TEST_UNSUPPORTED(__inst_arm(0xe75efa1f) " @ usad8 r14, pc, r10")
1030 TEST_UNSUPPORTED(__inst_arm(0xe75eff1c) " @ usad8 r14, r12, pc")
1031
1032 TEST_RRR( "usada8 r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL3,"")
1033 TEST_RRR( "usada8 r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL3,"")
1034 TEST_UNSUPPORTED(__inst_arm(0xe78f8a1c) " @ usada8 pc, r12, r10, r8")
1035 TEST_UNSUPPORTED(__inst_arm(0xe78e8a1f) " @ usada8 r14, pc, r10, r8")
1036 TEST_UNSUPPORTED(__inst_arm(0xe78e8f1c) " @ usada8 r14, r12, pc, r8")
1037#endif /* __LINUX_ARM_ARCH__ >= 6 */
1038
1039#if __LINUX_ARM_ARCH__ >= 7
1040 TEST_GROUP("Bit Field")
1041
1042 TEST_R( "sbfx r0, r",0 , VAL1,", #0, #31")
1043 TEST_R( "sbfxeq r14, r",12, VAL2,", #8, #16")
1044 TEST_R( "sbfx r4, r",10, VAL1,", #16, #15")
1045 TEST_UNSUPPORTED(__inst_arm(0xe7aff45c) " @ sbfx pc, r12, #8, #16")
1046
1047 TEST_R( "ubfx r0, r",0 , VAL1,", #0, #31")
1048 TEST_R( "ubfxcs r14, r",12, VAL2,", #8, #16")
1049 TEST_R( "ubfx r4, r",10, VAL1,", #16, #15")
1050 TEST_UNSUPPORTED(__inst_arm(0xe7eff45c) " @ ubfx pc, r12, #8, #16")
1051 TEST_UNSUPPORTED(__inst_arm(0xe7efc45f) " @ ubfx r12, pc, #8, #16")
1052
1053 TEST_R( "bfc r",0, VAL1,", #4, #20")
1054 TEST_R( "bfcvs r",14,VAL2,", #4, #20")
1055 TEST_R( "bfc r",7, VAL1,", #0, #31")
1056 TEST_R( "bfc r",8, VAL2,", #0, #31")
1057 TEST_UNSUPPORTED(__inst_arm(0xe7def01f) " @ bfc pc, #0, #31");
1058
1059 TEST_RR( "bfi r",0, VAL1,", r",0 , VAL2,", #0, #31")
1060 TEST_RR( "bfipl r",12,VAL1,", r",14 , VAL2,", #4, #20")
1061 TEST_UNSUPPORTED(__inst_arm(0xe7d7f21e) " @ bfi pc, r14, #4, #20")
1062
1063 TEST_UNSUPPORTED(__inst_arm(0x07f000f0) "") /* Permanently UNDEFINED */
1064 TEST_UNSUPPORTED(__inst_arm(0x07ffffff) "") /* Permanently UNDEFINED */
1065#endif /* __LINUX_ARM_ARCH__ >= 6 */
1066
1067 TEST_GROUP("Branch, branch with link, and block data transfer")
1068
1069 TEST_P( "stmda r",0, 16*4,", {r0}")
1070 TEST_P( "stmeqda r",4, 16*4,", {r0-r15}")
1071 TEST_P( "stmneda r",8, 16*4,"!, {r8-r15}")
1072 TEST_P( "stmda r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
1073 TEST_P( "stmda r",13,0, "!, {pc}")
1074
1075 TEST_P( "ldmda r",0, 16*4,", {r0}")
1076 TEST_BF_P("ldmcsda r",4, 15*4,", {r0-r15}")
1077 TEST_BF_P("ldmccda r",7, 15*4,"!, {r8-r15}")
1078 TEST_P( "ldmda r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
1079 TEST_BF_P("ldmda r",14,15*4,"!, {pc}")
1080
1081 TEST_P( "stmia r",0, 16*4,", {r0}")
1082 TEST_P( "stmmiia r",4, 16*4,", {r0-r15}")
1083 TEST_P( "stmplia r",8, 16*4,"!, {r8-r15}")
1084 TEST_P( "stmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
1085 TEST_P( "stmia r",14,0, "!, {pc}")
1086
1087 TEST_P( "ldmia r",0, 16*4,", {r0}")
1088 TEST_BF_P("ldmvsia r",4, 0, ", {r0-r15}")
1089 TEST_BF_P("ldmvcia r",7, 8*4, "!, {r8-r15}")
1090 TEST_P( "ldmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
1091 TEST_BF_P("ldmia r",14,15*4,"!, {pc}")
1092
1093 TEST_P( "stmdb r",0, 16*4,", {r0}")
1094 TEST_P( "stmhidb r",4, 16*4,", {r0-r15}")
1095 TEST_P( "stmlsdb r",8, 16*4,"!, {r8-r15}")
1096 TEST_P( "stmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
1097 TEST_P( "stmdb r",13,4, "!, {pc}")
1098
1099 TEST_P( "ldmdb r",0, 16*4,", {r0}")
1100 TEST_BF_P("ldmgedb r",4, 16*4,", {r0-r15}")
1101 TEST_BF_P("ldmltdb r",7, 16*4,"!, {r8-r15}")
1102 TEST_P( "ldmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
1103 TEST_BF_P("ldmdb r",14,16*4,"!, {pc}")
1104
1105 TEST_P( "stmib r",0, 16*4,", {r0}")
1106 TEST_P( "stmgtib r",4, 16*4,", {r0-r15}")
1107 TEST_P( "stmleib r",8, 16*4,"!, {r8-r15}")
1108 TEST_P( "stmib r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
1109 TEST_P( "stmib r",13,-4, "!, {pc}")
1110
1111 TEST_P( "ldmib r",0, 16*4,", {r0}")
1112 TEST_BF_P("ldmeqib r",4, -4,", {r0-r15}")
1113 TEST_BF_P("ldmneib r",7, 7*4,"!, {r8-r15}")
1114 TEST_P( "ldmib r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
1115 TEST_BF_P("ldmib r",14,14*4,"!, {pc}")
1116
1117 TEST_P( "stmdb r",13,16*4,"!, {r3-r12,lr}")
1118 TEST_P( "stmeqdb r",13,16*4,"!, {r3-r12}")
1119 TEST_P( "stmnedb r",2, 16*4,", {r3-r12,lr}")
1120 TEST_P( "stmdb r",13,16*4,"!, {r2-r12,lr}")
1121 TEST_P( "stmdb r",0, 16*4,", {r0-r12}")
1122 TEST_P( "stmdb r",0, 16*4,", {r0-r12,lr}")
1123
1124 TEST_BF_P("ldmia r",13,5*4, "!, {r3-r12,pc}")
1125 TEST_P( "ldmccia r",13,5*4, "!, {r3-r12}")
1126 TEST_BF_P("ldmcsia r",2, 5*4, "!, {r3-r12,pc}")
1127 TEST_BF_P("ldmia r",13,4*4, "!, {r2-r12,pc}")
1128 TEST_P( "ldmia r",0, 16*4,", {r0-r12}")
1129 TEST_P( "ldmia r",0, 16*4,", {r0-r12,lr}")
1130
1131#ifdef CONFIG_THUMB2_KERNEL
1132 TEST_ARM_TO_THUMB_INTERWORK_P("ldmplia r",0,15*4,", {pc}")
1133 TEST_ARM_TO_THUMB_INTERWORK_P("ldmmiia r",13,0,", {r0-r15}")
1134#endif
1135 TEST_BF("b 2f")
1136 TEST_BF("bl 2f")
1137 TEST_BB("b 2b")
1138 TEST_BB("bl 2b")
1139
1140 TEST_BF("beq 2f")
1141 TEST_BF("bleq 2f")
1142 TEST_BB("bne 2b")
1143 TEST_BB("blne 2b")
1144
1145 TEST_BF("bgt 2f")
1146 TEST_BF("blgt 2f")
1147 TEST_BB("blt 2b")
1148 TEST_BB("bllt 2b")
1149
1150 TEST_GROUP("Supervisor Call, and coprocessor instructions")
1151
1152 /*
1153 * We can't really test these by executing them, so all
1154 * we can do is check that probes are, or are not allowed.
1155 * At the moment none are allowed...
1156 */
1157#define TEST_COPROCESSOR(code) TEST_UNSUPPORTED(code)
1158
1159#define COPROCESSOR_INSTRUCTIONS_ST_LD(two,cc) \
1160 TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #4]") \
1161 TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #-4]") \
1162 TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #4]!") \
1163 TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #-4]!") \
1164 TEST_COPROCESSOR("stc"two" 0, cr0, [r13], #4") \
1165 TEST_COPROCESSOR("stc"two" 0, cr0, [r13], #-4") \
1166 TEST_COPROCESSOR("stc"two" 0, cr0, [r13], {1}") \
1167 TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #4]") \
1168 TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #-4]") \
1169 TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #4]!") \
1170 TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #-4]!") \
1171 TEST_COPROCESSOR("stc"two"l 0, cr0, [r13], #4") \
1172 TEST_COPROCESSOR("stc"two"l 0, cr0, [r13], #-4") \
1173 TEST_COPROCESSOR("stc"two"l 0, cr0, [r13], {1}") \
1174 TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #4]") \
1175 TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #-4]") \
1176 TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #4]!") \
1177 TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #-4]!") \
1178 TEST_COPROCESSOR("ldc"two" 0, cr0, [r13], #4") \
1179 TEST_COPROCESSOR("ldc"two" 0, cr0, [r13], #-4") \
1180 TEST_COPROCESSOR("ldc"two" 0, cr0, [r13], {1}") \
1181 TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #4]") \
1182 TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #-4]") \
1183 TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #4]!") \
1184 TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #-4]!") \
1185 TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13], #4") \
1186 TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13], #-4") \
1187 TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13], {1}") \
1188 \
1189 TEST_COPROCESSOR( "stc"two" 0, cr0, [r15, #4]") \
1190 TEST_COPROCESSOR( "stc"two" 0, cr0, [r15, #-4]") \
1191 TEST_UNSUPPORTED(__inst_arm(0x##cc##daf0001) " @ stc"two" 0, cr0, [r15, #4]!") \
1192 TEST_UNSUPPORTED(__inst_arm(0x##cc##d2f0001) " @ stc"two" 0, cr0, [r15, #-4]!") \
1193 TEST_UNSUPPORTED(__inst_arm(0x##cc##caf0001) " @ stc"two" 0, cr0, [r15], #4") \
1194 TEST_UNSUPPORTED(__inst_arm(0x##cc##c2f0001) " @ stc"two" 0, cr0, [r15], #-4") \
1195 TEST_COPROCESSOR( "stc"two" 0, cr0, [r15], {1}") \
1196 TEST_COPROCESSOR( "stc"two"l 0, cr0, [r15, #4]") \
1197 TEST_COPROCESSOR( "stc"two"l 0, cr0, [r15, #-4]") \
1198 TEST_UNSUPPORTED(__inst_arm(0x##cc##def0001) " @ stc"two"l 0, cr0, [r15, #4]!") \
1199 TEST_UNSUPPORTED(__inst_arm(0x##cc##d6f0001) " @ stc"two"l 0, cr0, [r15, #-4]!") \
1200 TEST_UNSUPPORTED(__inst_arm(0x##cc##cef0001) " @ stc"two"l 0, cr0, [r15], #4") \
1201 TEST_UNSUPPORTED(__inst_arm(0x##cc##c6f0001) " @ stc"two"l 0, cr0, [r15], #-4") \
1202 TEST_COPROCESSOR( "stc"two"l 0, cr0, [r15], {1}") \
1203 TEST_COPROCESSOR( "ldc"two" 0, cr0, [r15, #4]") \
1204 TEST_COPROCESSOR( "ldc"two" 0, cr0, [r15, #-4]") \
1205 TEST_UNSUPPORTED(__inst_arm(0x##cc##dbf0001) " @ ldc"two" 0, cr0, [r15, #4]!") \
1206 TEST_UNSUPPORTED(__inst_arm(0x##cc##d3f0001) " @ ldc"two" 0, cr0, [r15, #-4]!") \
1207 TEST_UNSUPPORTED(__inst_arm(0x##cc##cbf0001) " @ ldc"two" 0, cr0, [r15], #4") \
1208 TEST_UNSUPPORTED(__inst_arm(0x##cc##c3f0001) " @ ldc"two" 0, cr0, [r15], #-4") \
1209 TEST_COPROCESSOR( "ldc"two" 0, cr0, [r15], {1}") \
1210 TEST_COPROCESSOR( "ldc"two"l 0, cr0, [r15, #4]") \
1211 TEST_COPROCESSOR( "ldc"two"l 0, cr0, [r15, #-4]") \
1212 TEST_UNSUPPORTED(__inst_arm(0x##cc##dff0001) " @ ldc"two"l 0, cr0, [r15, #4]!") \
1213 TEST_UNSUPPORTED(__inst_arm(0x##cc##d7f0001) " @ ldc"two"l 0, cr0, [r15, #-4]!") \
1214 TEST_UNSUPPORTED(__inst_arm(0x##cc##cff0001) " @ ldc"two"l 0, cr0, [r15], #4") \
1215 TEST_UNSUPPORTED(__inst_arm(0x##cc##c7f0001) " @ ldc"two"l 0, cr0, [r15], #-4") \
1216 TEST_COPROCESSOR( "ldc"two"l 0, cr0, [r15], {1}")
1217
1218#define COPROCESSOR_INSTRUCTIONS_MC_MR(two,cc) \
1219 \
1220 TEST_COPROCESSOR( "mcrr"two" 0, 15, r0, r14, cr0") \
1221 TEST_COPROCESSOR( "mcrr"two" 15, 0, r14, r0, cr15") \
1222 TEST_UNSUPPORTED(__inst_arm(0x##cc##c4f00f0) " @ mcrr"two" 0, 15, r0, r15, cr0") \
1223 TEST_UNSUPPORTED(__inst_arm(0x##cc##c40ff0f) " @ mcrr"two" 15, 0, r15, r0, cr15") \
1224 TEST_COPROCESSOR( "mrrc"two" 0, 15, r0, r14, cr0") \
1225 TEST_COPROCESSOR( "mrrc"two" 15, 0, r14, r0, cr15") \
1226 TEST_UNSUPPORTED(__inst_arm(0x##cc##c5f00f0) " @ mrrc"two" 0, 15, r0, r15, cr0") \
1227 TEST_UNSUPPORTED(__inst_arm(0x##cc##c50ff0f) " @ mrrc"two" 15, 0, r15, r0, cr15") \
1228 TEST_COPROCESSOR( "cdp"two" 15, 15, cr15, cr15, cr15, 7") \
1229 TEST_COPROCESSOR( "cdp"two" 0, 0, cr0, cr0, cr0, 0") \
1230 TEST_COPROCESSOR( "mcr"two" 15, 7, r15, cr15, cr15, 7") \
1231 TEST_COPROCESSOR( "mcr"two" 0, 0, r0, cr0, cr0, 0") \
1232 TEST_COPROCESSOR( "mrc"two" 15, 7, r15, cr15, cr15, 7") \
1233 TEST_COPROCESSOR( "mrc"two" 0, 0, r0, cr0, cr0, 0")
1234
1235 COPROCESSOR_INSTRUCTIONS_ST_LD("",e)
1236#if __LINUX_ARM_ARCH__ >= 5
1237 COPROCESSOR_INSTRUCTIONS_MC_MR("",e)
1238#endif
1239 TEST_UNSUPPORTED("svc 0")
1240 TEST_UNSUPPORTED("svc 0xffffff")
1241
1242 TEST_UNSUPPORTED("svc 0")
1243
1244 TEST_GROUP("Unconditional instruction")
1245
1246#if __LINUX_ARM_ARCH__ >= 6
1247 TEST_UNSUPPORTED("srsda sp, 0x13")
1248 TEST_UNSUPPORTED("srsdb sp, 0x13")
1249 TEST_UNSUPPORTED("srsia sp, 0x13")
1250 TEST_UNSUPPORTED("srsib sp, 0x13")
1251 TEST_UNSUPPORTED("srsda sp!, 0x13")
1252 TEST_UNSUPPORTED("srsdb sp!, 0x13")
1253 TEST_UNSUPPORTED("srsia sp!, 0x13")
1254 TEST_UNSUPPORTED("srsib sp!, 0x13")
1255
1256 TEST_UNSUPPORTED("rfeda sp")
1257 TEST_UNSUPPORTED("rfedb sp")
1258 TEST_UNSUPPORTED("rfeia sp")
1259 TEST_UNSUPPORTED("rfeib sp")
1260 TEST_UNSUPPORTED("rfeda sp!")
1261 TEST_UNSUPPORTED("rfedb sp!")
1262 TEST_UNSUPPORTED("rfeia sp!")
1263 TEST_UNSUPPORTED("rfeib sp!")
1264 TEST_UNSUPPORTED(__inst_arm(0xf81d0a00) " @ rfeda pc")
1265 TEST_UNSUPPORTED(__inst_arm(0xf91d0a00) " @ rfedb pc")
1266 TEST_UNSUPPORTED(__inst_arm(0xf89d0a00) " @ rfeia pc")
1267 TEST_UNSUPPORTED(__inst_arm(0xf99d0a00) " @ rfeib pc")
1268 TEST_UNSUPPORTED(__inst_arm(0xf83d0a00) " @ rfeda pc!")
1269 TEST_UNSUPPORTED(__inst_arm(0xf93d0a00) " @ rfedb pc!")
1270 TEST_UNSUPPORTED(__inst_arm(0xf8bd0a00) " @ rfeia pc!")
1271 TEST_UNSUPPORTED(__inst_arm(0xf9bd0a00) " @ rfeib pc!")
1272#endif /* __LINUX_ARM_ARCH__ >= 6 */
1273
1274#if __LINUX_ARM_ARCH__ >= 6
1275 TEST_X( "blx __dummy_thumb_subroutine_even",
1276 ".thumb \n\t"
1277 ".space 4 \n\t"
1278 ".type __dummy_thumb_subroutine_even, %%function \n\t"
1279 "__dummy_thumb_subroutine_even: \n\t"
1280 "mov r0, pc \n\t"
1281 "bx lr \n\t"
1282 ".arm \n\t"
1283 )
1284 TEST( "blx __dummy_thumb_subroutine_even")
1285
1286 TEST_X( "blx __dummy_thumb_subroutine_odd",
1287 ".thumb \n\t"
1288 ".space 2 \n\t"
1289 ".type __dummy_thumb_subroutine_odd, %%function \n\t"
1290 "__dummy_thumb_subroutine_odd: \n\t"
1291 "mov r0, pc \n\t"
1292 "bx lr \n\t"
1293 ".arm \n\t"
1294 )
1295 TEST( "blx __dummy_thumb_subroutine_odd")
1296#endif /* __LINUX_ARM_ARCH__ >= 6 */
1297
1298#if __LINUX_ARM_ARCH__ >= 5
1299 COPROCESSOR_INSTRUCTIONS_ST_LD("2",f)
1300#endif
1301#if __LINUX_ARM_ARCH__ >= 6
1302 COPROCESSOR_INSTRUCTIONS_MC_MR("2",f)
1303#endif
1304
1305 TEST_GROUP("Miscellaneous instructions, memory hints, and Advanced SIMD instructions")
1306
1307#if __LINUX_ARM_ARCH__ >= 6
1308 TEST_UNSUPPORTED("cps 0x13")
1309 TEST_UNSUPPORTED("cpsie i")
1310 TEST_UNSUPPORTED("cpsid i")
1311 TEST_UNSUPPORTED("cpsie i,0x13")
1312 TEST_UNSUPPORTED("cpsid i,0x13")
1313 TEST_UNSUPPORTED("setend le")
1314 TEST_UNSUPPORTED("setend be")
1315#endif
1316
1317#if __LINUX_ARM_ARCH__ >= 7
1318 TEST_P("pli [r",0,0b,", #16]")
1319 TEST( "pli [pc, #0]")
1320 TEST_RR("pli [r",12,0b,", r",0, 16,"]")
1321 TEST_RR("pli [r",0, 0b,", -r",12,16,", lsl #4]")
1322#endif
1323
1324#if __LINUX_ARM_ARCH__ >= 5
1325 TEST_P("pld [r",0,32,", #-16]")
1326 TEST( "pld [pc, #0]")
1327 TEST_PR("pld [r",7, 24, ", r",0, 16,"]")
1328 TEST_PR("pld [r",8, 24, ", -r",12,16,", lsl #4]")
1329#endif
1330
1331#if __LINUX_ARM_ARCH__ >= 7
1332 TEST_SUPPORTED( __inst_arm(0xf590f000) " @ pldw [r0, #0]")
1333 TEST_SUPPORTED( __inst_arm(0xf797f000) " @ pldw [r7, r0]")
1334 TEST_SUPPORTED( __inst_arm(0xf798f18c) " @ pldw [r8, r12, lsl #3]");
1335#endif
1336
1337#if __LINUX_ARM_ARCH__ >= 7
1338 TEST_UNSUPPORTED("clrex")
1339 TEST_UNSUPPORTED("dsb")
1340 TEST_UNSUPPORTED("dmb")
1341 TEST_UNSUPPORTED("isb")
1342#endif
1343
1344 verbose("\n");
1345}
1346
diff --git a/arch/arm/kernel/kprobes-test-thumb.c b/arch/arm/kernel/kprobes-test-thumb.c
deleted file mode 100644
index 844dd10d8593..000000000000
--- a/arch/arm/kernel/kprobes-test-thumb.c
+++ /dev/null
@@ -1,1188 +0,0 @@
1/*
2 * arch/arm/kernel/kprobes-test-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/kernel.h>
12#include <linux/module.h>
13#include <asm/opcodes.h>
14
15#include "kprobes-test.h"
16
17
18#define TEST_ISA "16"
19
20#define DONT_TEST_IN_ITBLOCK(tests) \
21 kprobe_test_flags |= TEST_FLAG_NO_ITBLOCK; \
22 tests \
23 kprobe_test_flags &= ~TEST_FLAG_NO_ITBLOCK;
24
25#define CONDITION_INSTRUCTIONS(cc_pos, tests) \
26 kprobe_test_cc_position = cc_pos; \
27 DONT_TEST_IN_ITBLOCK(tests) \
28 kprobe_test_cc_position = 0;
29
30#define TEST_ITBLOCK(code) \
31 kprobe_test_flags |= TEST_FLAG_FULL_ITBLOCK; \
32 TESTCASE_START(code) \
33 TEST_ARG_END("") \
34 "50: nop \n\t" \
35 "1: "code" \n\t" \
36 " mov r1, #0x11 \n\t" \
37 " mov r2, #0x22 \n\t" \
38 " mov r3, #0x33 \n\t" \
39 "2: nop \n\t" \
40 TESTCASE_END \
41 kprobe_test_flags &= ~TEST_FLAG_FULL_ITBLOCK;
42
43#define TEST_THUMB_TO_ARM_INTERWORK_P(code1, reg, val, code2) \
44 TESTCASE_START(code1 #reg code2) \
45 TEST_ARG_PTR(reg, val) \
46 TEST_ARG_REG(14, 99f+1) \
47 TEST_ARG_MEM(15, 3f) \
48 TEST_ARG_END("") \
49 " nop \n\t" /* To align 1f */ \
50 "50: nop \n\t" \
51 "1: "code1 #reg code2" \n\t" \
52 " bx lr \n\t" \
53 ".arm \n\t" \
54 "3: adr lr, 2f+1 \n\t" \
55 " bx lr \n\t" \
56 ".thumb \n\t" \
57 "2: nop \n\t" \
58 TESTCASE_END
59
60
61void kprobe_thumb16_test_cases(void)
62{
63 kprobe_test_flags = TEST_FLAG_NARROW_INSTR;
64
65 TEST_GROUP("Shift (immediate), add, subtract, move, and compare")
66
67 TEST_R( "lsls r7, r",0,VAL1,", #5")
68 TEST_R( "lsls r0, r",7,VAL2,", #11")
69 TEST_R( "lsrs r7, r",0,VAL1,", #5")
70 TEST_R( "lsrs r0, r",7,VAL2,", #11")
71 TEST_R( "asrs r7, r",0,VAL1,", #5")
72 TEST_R( "asrs r0, r",7,VAL2,", #11")
73 TEST_RR( "adds r2, r",0,VAL1,", r",7,VAL2,"")
74 TEST_RR( "adds r5, r",7,VAL2,", r",0,VAL2,"")
75 TEST_RR( "subs r2, r",0,VAL1,", r",7,VAL2,"")
76 TEST_RR( "subs r5, r",7,VAL2,", r",0,VAL2,"")
77 TEST_R( "adds r7, r",0,VAL1,", #5")
78 TEST_R( "adds r0, r",7,VAL2,", #2")
79 TEST_R( "subs r7, r",0,VAL1,", #5")
80 TEST_R( "subs r0, r",7,VAL2,", #2")
81 TEST( "movs.n r0, #0x5f")
82 TEST( "movs.n r7, #0xa0")
83 TEST_R( "cmp.n r",0,0x5e, ", #0x5f")
84 TEST_R( "cmp.n r",5,0x15f,", #0x5f")
85 TEST_R( "cmp.n r",7,0xa0, ", #0xa0")
86 TEST_R( "adds.n r",0,VAL1,", #0x5f")
87 TEST_R( "adds.n r",7,VAL2,", #0xa0")
88 TEST_R( "subs.n r",0,VAL1,", #0x5f")
89 TEST_R( "subs.n r",7,VAL2,", #0xa0")
90
91 TEST_GROUP("16-bit Thumb data-processing instructions")
92
93#define DATA_PROCESSING16(op,val) \
94 TEST_RR( op" r",0,VAL1,", r",7,val,"") \
95 TEST_RR( op" r",7,VAL2,", r",0,val,"")
96
97 DATA_PROCESSING16("ands",0xf00f00ff)
98 DATA_PROCESSING16("eors",0xf00f00ff)
99 DATA_PROCESSING16("lsls",11)
100 DATA_PROCESSING16("lsrs",11)
101 DATA_PROCESSING16("asrs",11)
102 DATA_PROCESSING16("adcs",VAL2)
103 DATA_PROCESSING16("sbcs",VAL2)
104 DATA_PROCESSING16("rors",11)
105 DATA_PROCESSING16("tst",0xf00f00ff)
106 TEST_R("rsbs r",0,VAL1,", #0")
107 TEST_R("rsbs r",7,VAL2,", #0")
108 DATA_PROCESSING16("cmp",0xf00f00ff)
109 DATA_PROCESSING16("cmn",0xf00f00ff)
110 DATA_PROCESSING16("orrs",0xf00f00ff)
111 DATA_PROCESSING16("muls",VAL2)
112 DATA_PROCESSING16("bics",0xf00f00ff)
113 DATA_PROCESSING16("mvns",VAL2)
114
115 TEST_GROUP("Special data instructions and branch and exchange")
116
117 TEST_RR( "add r",0, VAL1,", r",7,VAL2,"")
118 TEST_RR( "add r",3, VAL2,", r",8,VAL3,"")
119 TEST_RR( "add r",8, VAL3,", r",0,VAL1,"")
120 TEST_R( "add sp" ", r",8,-8, "")
121 TEST_R( "add r",14,VAL1,", pc")
122 TEST_BF_R("add pc" ", r",0,2f-1f-8,"")
123 TEST_UNSUPPORTED(__inst_thumb16(0x44ff) " @ add pc, pc")
124
125 TEST_RR( "cmp r",3,VAL1,", r",8,VAL2,"")
126 TEST_RR( "cmp r",8,VAL2,", r",0,VAL1,"")
127 TEST_R( "cmp sp" ", r",8,-8, "")
128
129 TEST_R( "mov r0, r",7,VAL2,"")
130 TEST_R( "mov r3, r",8,VAL3,"")
131 TEST_R( "mov r8, r",0,VAL1,"")
132 TEST_P( "mov sp, r",8,-8, "")
133 TEST( "mov lr, pc")
134 TEST_BF_R("mov pc, r",0,2f, "")
135
136 TEST_BF_R("bx r",0, 2f+1,"")
137 TEST_BF_R("bx r",14,2f+1,"")
138 TESTCASE_START("bx pc")
139 TEST_ARG_REG(14, 99f+1)
140 TEST_ARG_END("")
141 " nop \n\t" /* To align the bx pc*/
142 "50: nop \n\t"
143 "1: bx pc \n\t"
144 " bx lr \n\t"
145 ".arm \n\t"
146 " adr lr, 2f+1 \n\t"
147 " bx lr \n\t"
148 ".thumb \n\t"
149 "2: nop \n\t"
150 TESTCASE_END
151
152 TEST_BF_R("blx r",0, 2f+1,"")
153 TEST_BB_R("blx r",14,2f+1,"")
154 TEST_UNSUPPORTED(__inst_thumb16(0x47f8) " @ blx pc")
155
156 TEST_GROUP("Load from Literal Pool")
157
158 TEST_X( "ldr r0, 3f",
159 ".align \n\t"
160 "3: .word "__stringify(VAL1))
161 TEST_X( "ldr r7, 3f",
162 ".space 128 \n\t"
163 ".align \n\t"
164 "3: .word "__stringify(VAL2))
165
166 TEST_GROUP("16-bit Thumb Load/store instructions")
167
168 TEST_RPR("str r",0, VAL1,", [r",1, 24,", r",2, 48,"]")
169 TEST_RPR("str r",7, VAL2,", [r",6, 24,", r",5, 48,"]")
170 TEST_RPR("strh r",0, VAL1,", [r",1, 24,", r",2, 48,"]")
171 TEST_RPR("strh r",7, VAL2,", [r",6, 24,", r",5, 48,"]")
172 TEST_RPR("strb r",0, VAL1,", [r",1, 24,", r",2, 48,"]")
173 TEST_RPR("strb r",7, VAL2,", [r",6, 24,", r",5, 48,"]")
174 TEST_PR( "ldrsb r0, [r",1, 24,", r",2, 48,"]")
175 TEST_PR( "ldrsb r7, [r",6, 24,", r",5, 50,"]")
176 TEST_PR( "ldr r0, [r",1, 24,", r",2, 48,"]")
177 TEST_PR( "ldr r7, [r",6, 24,", r",5, 48,"]")
178 TEST_PR( "ldrh r0, [r",1, 24,", r",2, 48,"]")
179 TEST_PR( "ldrh r7, [r",6, 24,", r",5, 50,"]")
180 TEST_PR( "ldrb r0, [r",1, 24,", r",2, 48,"]")
181 TEST_PR( "ldrb r7, [r",6, 24,", r",5, 50,"]")
182 TEST_PR( "ldrsh r0, [r",1, 24,", r",2, 48,"]")
183 TEST_PR( "ldrsh r7, [r",6, 24,", r",5, 50,"]")
184
185 TEST_RP("str r",0, VAL1,", [r",1, 24,", #120]")
186 TEST_RP("str r",7, VAL2,", [r",6, 24,", #120]")
187 TEST_P( "ldr r0, [r",1, 24,", #120]")
188 TEST_P( "ldr r7, [r",6, 24,", #120]")
189 TEST_RP("strb r",0, VAL1,", [r",1, 24,", #30]")
190 TEST_RP("strb r",7, VAL2,", [r",6, 24,", #30]")
191 TEST_P( "ldrb r0, [r",1, 24,", #30]")
192 TEST_P( "ldrb r7, [r",6, 24,", #30]")
193 TEST_RP("strh r",0, VAL1,", [r",1, 24,", #60]")
194 TEST_RP("strh r",7, VAL2,", [r",6, 24,", #60]")
195 TEST_P( "ldrh r0, [r",1, 24,", #60]")
196 TEST_P( "ldrh r7, [r",6, 24,", #60]")
197
198 TEST_R( "str r",0, VAL1,", [sp, #0]")
199 TEST_R( "str r",7, VAL2,", [sp, #160]")
200 TEST( "ldr r0, [sp, #0]")
201 TEST( "ldr r7, [sp, #160]")
202
203 TEST_RP("str r",0, VAL1,", [r",0, 24,"]")
204 TEST_P( "ldr r0, [r",0, 24,"]")
205
206 TEST_GROUP("Generate PC-/SP-relative address")
207
208 TEST("add r0, pc, #4")
209 TEST("add r7, pc, #1020")
210 TEST("add r0, sp, #4")
211 TEST("add r7, sp, #1020")
212
213 TEST_GROUP("Miscellaneous 16-bit instructions")
214
215 TEST_UNSUPPORTED( "cpsie i")
216 TEST_UNSUPPORTED( "cpsid i")
217 TEST_UNSUPPORTED( "setend le")
218 TEST_UNSUPPORTED( "setend be")
219
220 TEST("add sp, #"__stringify(TEST_MEMORY_SIZE)) /* Assumes TEST_MEMORY_SIZE < 0x400 */
221 TEST("sub sp, #0x7f*4")
222
223DONT_TEST_IN_ITBLOCK(
224 TEST_BF_R( "cbnz r",0,0, ", 2f")
225 TEST_BF_R( "cbz r",2,-1,", 2f")
226 TEST_BF_RX( "cbnz r",4,1, ", 2f", SPACE_0x20)
227 TEST_BF_RX( "cbz r",7,0, ", 2f", SPACE_0x40)
228)
229 TEST_R("sxth r0, r",7, HH1,"")
230 TEST_R("sxth r7, r",0, HH2,"")
231 TEST_R("sxtb r0, r",7, HH1,"")
232 TEST_R("sxtb r7, r",0, HH2,"")
233 TEST_R("uxth r0, r",7, HH1,"")
234 TEST_R("uxth r7, r",0, HH2,"")
235 TEST_R("uxtb r0, r",7, HH1,"")
236 TEST_R("uxtb r7, r",0, HH2,"")
237 TEST_R("rev r0, r",7, VAL1,"")
238 TEST_R("rev r7, r",0, VAL2,"")
239 TEST_R("rev16 r0, r",7, VAL1,"")
240 TEST_R("rev16 r7, r",0, VAL2,"")
241 TEST_UNSUPPORTED(__inst_thumb16(0xba80) "")
242 TEST_UNSUPPORTED(__inst_thumb16(0xbabf) "")
243 TEST_R("revsh r0, r",7, VAL1,"")
244 TEST_R("revsh r7, r",0, VAL2,"")
245
246#define TEST_POPPC(code, offset) \
247 TESTCASE_START(code) \
248 TEST_ARG_PTR(13, offset) \
249 TEST_ARG_END("") \
250 TEST_BRANCH_F(code) \
251 TESTCASE_END
252
253 TEST("push {r0}")
254 TEST("push {r7}")
255 TEST("push {r14}")
256 TEST("push {r0-r7,r14}")
257 TEST("push {r0,r2,r4,r6,r14}")
258 TEST("push {r1,r3,r5,r7}")
259 TEST("pop {r0}")
260 TEST("pop {r7}")
261 TEST("pop {r0,r2,r4,r6}")
262 TEST_POPPC("pop {pc}",15*4)
263 TEST_POPPC("pop {r0-r7,pc}",7*4)
264 TEST_POPPC("pop {r1,r3,r5,r7,pc}",11*4)
265 TEST_THUMB_TO_ARM_INTERWORK_P("pop {pc} @ ",13,15*4,"")
266 TEST_THUMB_TO_ARM_INTERWORK_P("pop {r0-r7,pc} @ ",13,7*4,"")
267
268 TEST_UNSUPPORTED("bkpt.n 0")
269 TEST_UNSUPPORTED("bkpt.n 255")
270
271 TEST_SUPPORTED("yield")
272 TEST("sev")
273 TEST("nop")
274 TEST("wfi")
275 TEST_SUPPORTED("wfe")
276 TEST_UNSUPPORTED(__inst_thumb16(0xbf50) "") /* Unassigned hints */
277 TEST_UNSUPPORTED(__inst_thumb16(0xbff0) "") /* Unassigned hints */
278
279#define TEST_IT(code, code2) \
280 TESTCASE_START(code) \
281 TEST_ARG_END("") \
282 "50: nop \n\t" \
283 "1: "code" \n\t" \
284 " "code2" \n\t" \
285 "2: nop \n\t" \
286 TESTCASE_END
287
288DONT_TEST_IN_ITBLOCK(
289 TEST_IT("it eq","moveq r0,#0")
290 TEST_IT("it vc","movvc r0,#0")
291 TEST_IT("it le","movle r0,#0")
292 TEST_IT("ite eq","moveq r0,#0\n\t movne r1,#1")
293 TEST_IT("itet vc","movvc r0,#0\n\t movvs r1,#1\n\t movvc r2,#2")
294 TEST_IT("itete le","movle r0,#0\n\t movgt r1,#1\n\t movle r2,#2\n\t movgt r3,#3")
295 TEST_IT("itttt le","movle r0,#0\n\t movle r1,#1\n\t movle r2,#2\n\t movle r3,#3")
296 TEST_IT("iteee le","movle r0,#0\n\t movgt r1,#1\n\t movgt r2,#2\n\t movgt r3,#3")
297)
298
299 TEST_GROUP("Load and store multiple")
300
301 TEST_P("ldmia r",4, 16*4,"!, {r0,r7}")
302 TEST_P("ldmia r",7, 16*4,"!, {r0-r6}")
303 TEST_P("stmia r",4, 16*4,"!, {r0,r7}")
304 TEST_P("stmia r",0, 16*4,"!, {r0-r7}")
305
306 TEST_GROUP("Conditional branch and Supervisor Call instructions")
307
308CONDITION_INSTRUCTIONS(8,
309 TEST_BF("beq 2f")
310 TEST_BB("bne 2b")
311 TEST_BF("bgt 2f")
312 TEST_BB("blt 2b")
313)
314 TEST_UNSUPPORTED(__inst_thumb16(0xde00) "")
315 TEST_UNSUPPORTED(__inst_thumb16(0xdeff) "")
316 TEST_UNSUPPORTED("svc #0x00")
317 TEST_UNSUPPORTED("svc #0xff")
318
319 TEST_GROUP("Unconditional branch")
320
321 TEST_BF( "b 2f")
322 TEST_BB( "b 2b")
323 TEST_BF_X("b 2f", SPACE_0x400)
324 TEST_BB_X("b 2b", SPACE_0x400)
325
326 TEST_GROUP("Testing instructions in IT blocks")
327
328 TEST_ITBLOCK("subs.n r0, r0")
329
330 verbose("\n");
331}
332
333
334void kprobe_thumb32_test_cases(void)
335{
336 kprobe_test_flags = 0;
337
338 TEST_GROUP("Load/store multiple")
339
340 TEST_UNSUPPORTED("rfedb sp")
341 TEST_UNSUPPORTED("rfeia sp")
342 TEST_UNSUPPORTED("rfedb sp!")
343 TEST_UNSUPPORTED("rfeia sp!")
344
345 TEST_P( "stmia r",0, 16*4,", {r0,r8}")
346 TEST_P( "stmia r",4, 16*4,", {r0-r12,r14}")
347 TEST_P( "stmia r",7, 16*4,"!, {r8-r12,r14}")
348 TEST_P( "stmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
349
350 TEST_P( "ldmia r",0, 16*4,", {r0,r8}")
351 TEST_P( "ldmia r",4, 0, ", {r0-r12,r14}")
352 TEST_BF_P("ldmia r",5, 8*4, "!, {r6-r12,r15}")
353 TEST_P( "ldmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
354 TEST_BF_P("ldmia r",14,14*4,"!, {r4,pc}")
355
356 TEST_P( "stmdb r",0, 16*4,", {r0,r8}")
357 TEST_P( "stmdb r",4, 16*4,", {r0-r12,r14}")
358 TEST_P( "stmdb r",5, 16*4,"!, {r8-r12,r14}")
359 TEST_P( "stmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
360
361 TEST_P( "ldmdb r",0, 16*4,", {r0,r8}")
362 TEST_P( "ldmdb r",4, 16*4,", {r0-r12,r14}")
363 TEST_BF_P("ldmdb r",5, 16*4,"!, {r6-r12,r15}")
364 TEST_P( "ldmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
365 TEST_BF_P("ldmdb r",14,16*4,"!, {r4,pc}")
366
367 TEST_P( "stmdb r",13,16*4,"!, {r3-r12,lr}")
368 TEST_P( "stmdb r",13,16*4,"!, {r3-r12}")
369 TEST_P( "stmdb r",2, 16*4,", {r3-r12,lr}")
370 TEST_P( "stmdb r",13,16*4,"!, {r2-r12,lr}")
371 TEST_P( "stmdb r",0, 16*4,", {r0-r12}")
372 TEST_P( "stmdb r",0, 16*4,", {r0-r12,lr}")
373
374 TEST_BF_P("ldmia r",13,5*4, "!, {r3-r12,pc}")
375 TEST_P( "ldmia r",13,5*4, "!, {r3-r12}")
376 TEST_BF_P("ldmia r",2, 5*4, "!, {r3-r12,pc}")
377 TEST_BF_P("ldmia r",13,4*4, "!, {r2-r12,pc}")
378 TEST_P( "ldmia r",0, 16*4,", {r0-r12}")
379 TEST_P( "ldmia r",0, 16*4,", {r0-r12,lr}")
380
381 TEST_THUMB_TO_ARM_INTERWORK_P("ldmia r",0,14*4,", {r12,pc}")
382 TEST_THUMB_TO_ARM_INTERWORK_P("ldmia r",13,2*4,", {r0-r12,pc}")
383
384 TEST_UNSUPPORTED(__inst_thumb32(0xe88f0101) " @ stmia pc, {r0,r8}")
385 TEST_UNSUPPORTED(__inst_thumb32(0xe92f5f00) " @ stmdb pc!, {r8-r12,r14}")
386 TEST_UNSUPPORTED(__inst_thumb32(0xe8bdc000) " @ ldmia r13!, {r14,pc}")
387 TEST_UNSUPPORTED(__inst_thumb32(0xe93ec000) " @ ldmdb r14!, {r14,pc}")
388 TEST_UNSUPPORTED(__inst_thumb32(0xe8a73f00) " @ stmia r7!, {r8-r12,sp}")
389 TEST_UNSUPPORTED(__inst_thumb32(0xe8a79f00) " @ stmia r7!, {r8-r12,pc}")
390 TEST_UNSUPPORTED(__inst_thumb32(0xe93e2010) " @ ldmdb r14!, {r4,sp}")
391
392 TEST_GROUP("Load/store double or exclusive, table branch")
393
394 TEST_P( "ldrd r0, r1, [r",1, 24,", #-16]")
395 TEST( "ldrd r12, r14, [sp, #16]")
396 TEST_P( "ldrd r1, r0, [r",7, 24,", #-16]!")
397 TEST( "ldrd r14, r12, [sp, #16]!")
398 TEST_P( "ldrd r1, r0, [r",7, 24,"], #16")
399 TEST( "ldrd r7, r8, [sp], #-16")
400
401 TEST_X( "ldrd r12, r14, 3f",
402 ".align 3 \n\t"
403 "3: .word "__stringify(VAL1)" \n\t"
404 " .word "__stringify(VAL2))
405
406 TEST_UNSUPPORTED(__inst_thumb32(0xe9ffec04) " @ ldrd r14, r12, [pc, #16]!")
407 TEST_UNSUPPORTED(__inst_thumb32(0xe8ffec04) " @ ldrd r14, r12, [pc], #16")
408 TEST_UNSUPPORTED(__inst_thumb32(0xe9d4d800) " @ ldrd sp, r8, [r4]")
409 TEST_UNSUPPORTED(__inst_thumb32(0xe9d4f800) " @ ldrd pc, r8, [r4]")
410 TEST_UNSUPPORTED(__inst_thumb32(0xe9d47d00) " @ ldrd r7, sp, [r4]")
411 TEST_UNSUPPORTED(__inst_thumb32(0xe9d47f00) " @ ldrd r7, pc, [r4]")
412
413 TEST_RRP("strd r",0, VAL1,", r",1, VAL2,", [r",1, 24,", #-16]")
414 TEST_RR( "strd r",12,VAL2,", r",14,VAL1,", [sp, #16]")
415 TEST_RRP("strd r",1, VAL1,", r",0, VAL2,", [r",7, 24,", #-16]!")
416 TEST_RR( "strd r",14,VAL2,", r",12,VAL1,", [sp, #16]!")
417 TEST_RRP("strd r",1, VAL1,", r",0, VAL2,", [r",7, 24,"], #16")
418 TEST_RR( "strd r",7, VAL2,", r",8, VAL1,", [sp], #-16")
419 TEST_UNSUPPORTED(__inst_thumb32(0xe9efec04) " @ strd r14, r12, [pc, #16]!")
420 TEST_UNSUPPORTED(__inst_thumb32(0xe8efec04) " @ strd r14, r12, [pc], #16")
421
422 TEST_RX("tbb [pc, r",0, (9f-(1f+4)),"]",
423 "9: \n\t"
424 ".byte (2f-1b-4)>>1 \n\t"
425 ".byte (3f-1b-4)>>1 \n\t"
426 "3: mvn r0, r0 \n\t"
427 "2: nop \n\t")
428
429 TEST_RX("tbb [pc, r",4, (9f-(1f+4)+1),"]",
430 "9: \n\t"
431 ".byte (2f-1b-4)>>1 \n\t"
432 ".byte (3f-1b-4)>>1 \n\t"
433 "3: mvn r0, r0 \n\t"
434 "2: nop \n\t")
435
436 TEST_RRX("tbb [r",1,9f,", r",2,0,"]",
437 "9: \n\t"
438 ".byte (2f-1b-4)>>1 \n\t"
439 ".byte (3f-1b-4)>>1 \n\t"
440 "3: mvn r0, r0 \n\t"
441 "2: nop \n\t")
442
443 TEST_RX("tbh [pc, r",7, (9f-(1f+4))>>1,"]",
444 "9: \n\t"
445 ".short (2f-1b-4)>>1 \n\t"
446 ".short (3f-1b-4)>>1 \n\t"
447 "3: mvn r0, r0 \n\t"
448 "2: nop \n\t")
449
450 TEST_RX("tbh [pc, r",12, ((9f-(1f+4))>>1)+1,"]",
451 "9: \n\t"
452 ".short (2f-1b-4)>>1 \n\t"
453 ".short (3f-1b-4)>>1 \n\t"
454 "3: mvn r0, r0 \n\t"
455 "2: nop \n\t")
456
457 TEST_RRX("tbh [r",1,9f, ", r",14,1,"]",
458 "9: \n\t"
459 ".short (2f-1b-4)>>1 \n\t"
460 ".short (3f-1b-4)>>1 \n\t"
461 "3: mvn r0, r0 \n\t"
462 "2: nop \n\t")
463
464 TEST_UNSUPPORTED(__inst_thumb32(0xe8d1f01f) " @ tbh [r1, pc]")
465 TEST_UNSUPPORTED(__inst_thumb32(0xe8d1f01d) " @ tbh [r1, sp]")
466 TEST_UNSUPPORTED(__inst_thumb32(0xe8ddf012) " @ tbh [sp, r2]")
467
468 TEST_UNSUPPORTED("strexb r0, r1, [r2]")
469 TEST_UNSUPPORTED("strexh r0, r1, [r2]")
470 TEST_UNSUPPORTED("strexd r0, r1, [r2]")
471 TEST_UNSUPPORTED("ldrexb r0, [r1]")
472 TEST_UNSUPPORTED("ldrexh r0, [r1]")
473 TEST_UNSUPPORTED("ldrexd r0, [r1]")
474
475 TEST_GROUP("Data-processing (shifted register) and (modified immediate)")
476
477#define _DATA_PROCESSING32_DNM(op,s,val) \
478 TEST_RR(op s".w r0, r",1, VAL1,", r",2, val, "") \
479 TEST_RR(op s" r1, r",1, VAL1,", r",2, val, ", lsl #3") \
480 TEST_RR(op s" r2, r",3, VAL1,", r",2, val, ", lsr #4") \
481 TEST_RR(op s" r3, r",3, VAL1,", r",2, val, ", asr #5") \
482 TEST_RR(op s" r4, r",5, VAL1,", r",2, N(val),", asr #6") \
483 TEST_RR(op s" r5, r",5, VAL1,", r",2, val, ", ror #7") \
484 TEST_RR(op s" r8, r",9, VAL1,", r",10,val, ", rrx") \
485 TEST_R( op s" r0, r",11,VAL1,", #0x00010001") \
486 TEST_R( op s" r11, r",0, VAL1,", #0xf5000000") \
487 TEST_R( op s" r7, r",8, VAL2,", #0x000af000")
488
489#define DATA_PROCESSING32_DNM(op,val) \
490 _DATA_PROCESSING32_DNM(op,"",val) \
491 _DATA_PROCESSING32_DNM(op,"s",val)
492
493#define DATA_PROCESSING32_NM(op,val) \
494 TEST_RR(op".w r",1, VAL1,", r",2, val, "") \
495 TEST_RR(op" r",1, VAL1,", r",2, val, ", lsl #3") \
496 TEST_RR(op" r",3, VAL1,", r",2, val, ", lsr #4") \
497 TEST_RR(op" r",3, VAL1,", r",2, val, ", asr #5") \
498 TEST_RR(op" r",5, VAL1,", r",2, N(val),", asr #6") \
499 TEST_RR(op" r",5, VAL1,", r",2, val, ", ror #7") \
500 TEST_RR(op" r",9, VAL1,", r",10,val, ", rrx") \
501 TEST_R( op" r",11,VAL1,", #0x00010001") \
502 TEST_R( op" r",0, VAL1,", #0xf5000000") \
503 TEST_R( op" r",8, VAL2,", #0x000af000")
504
505#define _DATA_PROCESSING32_DM(op,s,val) \
506 TEST_R( op s".w r0, r",14, val, "") \
507 TEST_R( op s" r1, r",12, val, ", lsl #3") \
508 TEST_R( op s" r2, r",11, val, ", lsr #4") \
509 TEST_R( op s" r3, r",10, val, ", asr #5") \
510 TEST_R( op s" r4, r",9, N(val),", asr #6") \
511 TEST_R( op s" r5, r",8, val, ", ror #7") \
512 TEST_R( op s" r8, r",7,val, ", rrx") \
513 TEST( op s" r0, #0x00010001") \
514 TEST( op s" r11, #0xf5000000") \
515 TEST( op s" r7, #0x000af000") \
516 TEST( op s" r4, #0x00005a00")
517
518#define DATA_PROCESSING32_DM(op,val) \
519 _DATA_PROCESSING32_DM(op,"",val) \
520 _DATA_PROCESSING32_DM(op,"s",val)
521
522 DATA_PROCESSING32_DNM("and",0xf00f00ff)
523 DATA_PROCESSING32_NM("tst",0xf00f00ff)
524 DATA_PROCESSING32_DNM("bic",0xf00f00ff)
525 DATA_PROCESSING32_DNM("orr",0xf00f00ff)
526 DATA_PROCESSING32_DM("mov",VAL2)
527 DATA_PROCESSING32_DNM("orn",0xf00f00ff)
528 DATA_PROCESSING32_DM("mvn",VAL2)
529 DATA_PROCESSING32_DNM("eor",0xf00f00ff)
530 DATA_PROCESSING32_NM("teq",0xf00f00ff)
531 DATA_PROCESSING32_DNM("add",VAL2)
532 DATA_PROCESSING32_NM("cmn",VAL2)
533 DATA_PROCESSING32_DNM("adc",VAL2)
534 DATA_PROCESSING32_DNM("sbc",VAL2)
535 DATA_PROCESSING32_DNM("sub",VAL2)
536 DATA_PROCESSING32_NM("cmp",VAL2)
537 DATA_PROCESSING32_DNM("rsb",VAL2)
538
539 TEST_RR("pkhbt r0, r",0, HH1,", r",1, HH2,"")
540 TEST_RR("pkhbt r14,r",12, HH1,", r",10,HH2,", lsl #2")
541 TEST_RR("pkhtb r0, r",0, HH1,", r",1, HH2,"")
542 TEST_RR("pkhtb r14,r",12, HH1,", r",10,HH2,", asr #2")
543
544 TEST_UNSUPPORTED(__inst_thumb32(0xea170f0d) " @ tst.w r7, sp")
545 TEST_UNSUPPORTED(__inst_thumb32(0xea170f0f) " @ tst.w r7, pc")
546 TEST_UNSUPPORTED(__inst_thumb32(0xea1d0f07) " @ tst.w sp, r7")
547 TEST_UNSUPPORTED(__inst_thumb32(0xea1f0f07) " @ tst.w pc, r7")
548 TEST_UNSUPPORTED(__inst_thumb32(0xf01d1f08) " @ tst sp, #0x00080008")
549 TEST_UNSUPPORTED(__inst_thumb32(0xf01f1f08) " @ tst pc, #0x00080008")
550
551 TEST_UNSUPPORTED(__inst_thumb32(0xea970f0d) " @ teq.w r7, sp")
552 TEST_UNSUPPORTED(__inst_thumb32(0xea970f0f) " @ teq.w r7, pc")
553 TEST_UNSUPPORTED(__inst_thumb32(0xea9d0f07) " @ teq.w sp, r7")
554 TEST_UNSUPPORTED(__inst_thumb32(0xea9f0f07) " @ teq.w pc, r7")
555 TEST_UNSUPPORTED(__inst_thumb32(0xf09d1f08) " @ tst sp, #0x00080008")
556 TEST_UNSUPPORTED(__inst_thumb32(0xf09f1f08) " @ tst pc, #0x00080008")
557
558 TEST_UNSUPPORTED(__inst_thumb32(0xeb170f0d) " @ cmn.w r7, sp")
559 TEST_UNSUPPORTED(__inst_thumb32(0xeb170f0f) " @ cmn.w r7, pc")
560 TEST_P("cmn.w sp, r",7,0,"")
561 TEST_UNSUPPORTED(__inst_thumb32(0xeb1f0f07) " @ cmn.w pc, r7")
562 TEST( "cmn sp, #0x00080008")
563 TEST_UNSUPPORTED(__inst_thumb32(0xf11f1f08) " @ cmn pc, #0x00080008")
564
565 TEST_UNSUPPORTED(__inst_thumb32(0xebb70f0d) " @ cmp.w r7, sp")
566 TEST_UNSUPPORTED(__inst_thumb32(0xebb70f0f) " @ cmp.w r7, pc")
567 TEST_P("cmp.w sp, r",7,0,"")
568 TEST_UNSUPPORTED(__inst_thumb32(0xebbf0f07) " @ cmp.w pc, r7")
569 TEST( "cmp sp, #0x00080008")
570 TEST_UNSUPPORTED(__inst_thumb32(0xf1bf1f08) " @ cmp pc, #0x00080008")
571
572 TEST_UNSUPPORTED(__inst_thumb32(0xea5f070d) " @ movs.w r7, sp")
573 TEST_UNSUPPORTED(__inst_thumb32(0xea5f070f) " @ movs.w r7, pc")
574 TEST_UNSUPPORTED(__inst_thumb32(0xea5f0d07) " @ movs.w sp, r7")
575 TEST_UNSUPPORTED(__inst_thumb32(0xea4f0f07) " @ mov.w pc, r7")
576 TEST_UNSUPPORTED(__inst_thumb32(0xf04f1d08) " @ mov sp, #0x00080008")
577 TEST_UNSUPPORTED(__inst_thumb32(0xf04f1f08) " @ mov pc, #0x00080008")
578
579 TEST_R("add.w r0, sp, r",1, 4,"")
580 TEST_R("adds r0, sp, r",1, 4,", asl #3")
581 TEST_R("add r0, sp, r",1, 4,", asl #4")
582 TEST_R("add r0, sp, r",1, 16,", ror #1")
583 TEST_R("add.w sp, sp, r",1, 4,"")
584 TEST_R("add sp, sp, r",1, 4,", asl #3")
585 TEST_UNSUPPORTED(__inst_thumb32(0xeb0d1d01) " @ add sp, sp, r1, asl #4")
586 TEST_UNSUPPORTED(__inst_thumb32(0xeb0d0d71) " @ add sp, sp, r1, ror #1")
587 TEST( "add.w r0, sp, #24")
588 TEST( "add.w sp, sp, #24")
589 TEST_UNSUPPORTED(__inst_thumb32(0xeb0d0f01) " @ add pc, sp, r1")
590 TEST_UNSUPPORTED(__inst_thumb32(0xeb0d000f) " @ add r0, sp, pc")
591 TEST_UNSUPPORTED(__inst_thumb32(0xeb0d000d) " @ add r0, sp, sp")
592 TEST_UNSUPPORTED(__inst_thumb32(0xeb0d0d0f) " @ add sp, sp, pc")
593 TEST_UNSUPPORTED(__inst_thumb32(0xeb0d0d0d) " @ add sp, sp, sp")
594
595 TEST_R("sub.w r0, sp, r",1, 4,"")
596 TEST_R("subs r0, sp, r",1, 4,", asl #3")
597 TEST_R("sub r0, sp, r",1, 4,", asl #4")
598 TEST_R("sub r0, sp, r",1, 16,", ror #1")
599 TEST_R("sub.w sp, sp, r",1, 4,"")
600 TEST_R("sub sp, sp, r",1, 4,", asl #3")
601 TEST_UNSUPPORTED(__inst_thumb32(0xebad1d01) " @ sub sp, sp, r1, asl #4")
602 TEST_UNSUPPORTED(__inst_thumb32(0xebad0d71) " @ sub sp, sp, r1, ror #1")
603 TEST_UNSUPPORTED(__inst_thumb32(0xebad0f01) " @ sub pc, sp, r1")
604 TEST( "sub.w r0, sp, #24")
605 TEST( "sub.w sp, sp, #24")
606
607 TEST_UNSUPPORTED(__inst_thumb32(0xea02010f) " @ and r1, r2, pc")
608 TEST_UNSUPPORTED(__inst_thumb32(0xea0f0103) " @ and r1, pc, r3")
609 TEST_UNSUPPORTED(__inst_thumb32(0xea020f03) " @ and pc, r2, r3")
610 TEST_UNSUPPORTED(__inst_thumb32(0xea02010d) " @ and r1, r2, sp")
611 TEST_UNSUPPORTED(__inst_thumb32(0xea0d0103) " @ and r1, sp, r3")
612 TEST_UNSUPPORTED(__inst_thumb32(0xea020d03) " @ and sp, r2, r3")
613 TEST_UNSUPPORTED(__inst_thumb32(0xf00d1108) " @ and r1, sp, #0x00080008")
614 TEST_UNSUPPORTED(__inst_thumb32(0xf00f1108) " @ and r1, pc, #0x00080008")
615 TEST_UNSUPPORTED(__inst_thumb32(0xf0021d08) " @ and sp, r8, #0x00080008")
616 TEST_UNSUPPORTED(__inst_thumb32(0xf0021f08) " @ and pc, r8, #0x00080008")
617
618 TEST_UNSUPPORTED(__inst_thumb32(0xeb02010f) " @ add r1, r2, pc")
619 TEST_UNSUPPORTED(__inst_thumb32(0xeb0f0103) " @ add r1, pc, r3")
620 TEST_UNSUPPORTED(__inst_thumb32(0xeb020f03) " @ add pc, r2, r3")
621 TEST_UNSUPPORTED(__inst_thumb32(0xeb02010d) " @ add r1, r2, sp")
622 TEST_SUPPORTED( __inst_thumb32(0xeb0d0103) " @ add r1, sp, r3")
623 TEST_UNSUPPORTED(__inst_thumb32(0xeb020d03) " @ add sp, r2, r3")
624 TEST_SUPPORTED( __inst_thumb32(0xf10d1108) " @ add r1, sp, #0x00080008")
625 TEST_UNSUPPORTED(__inst_thumb32(0xf10d1f08) " @ add pc, sp, #0x00080008")
626 TEST_UNSUPPORTED(__inst_thumb32(0xf10f1108) " @ add r1, pc, #0x00080008")
627 TEST_UNSUPPORTED(__inst_thumb32(0xf1021d08) " @ add sp, r8, #0x00080008")
628 TEST_UNSUPPORTED(__inst_thumb32(0xf1021f08) " @ add pc, r8, #0x00080008")
629
630 TEST_UNSUPPORTED(__inst_thumb32(0xeaa00000) "")
631 TEST_UNSUPPORTED(__inst_thumb32(0xeaf00000) "")
632 TEST_UNSUPPORTED(__inst_thumb32(0xeb200000) "")
633 TEST_UNSUPPORTED(__inst_thumb32(0xeb800000) "")
634 TEST_UNSUPPORTED(__inst_thumb32(0xebe00000) "")
635
636 TEST_UNSUPPORTED(__inst_thumb32(0xf0a00000) "")
637 TEST_UNSUPPORTED(__inst_thumb32(0xf0c00000) "")
638 TEST_UNSUPPORTED(__inst_thumb32(0xf0f00000) "")
639 TEST_UNSUPPORTED(__inst_thumb32(0xf1200000) "")
640 TEST_UNSUPPORTED(__inst_thumb32(0xf1800000) "")
641 TEST_UNSUPPORTED(__inst_thumb32(0xf1e00000) "")
642
643 TEST_GROUP("Coprocessor instructions")
644
645 TEST_UNSUPPORTED(__inst_thumb32(0xec000000) "")
646 TEST_UNSUPPORTED(__inst_thumb32(0xeff00000) "")
647 TEST_UNSUPPORTED(__inst_thumb32(0xfc000000) "")
648 TEST_UNSUPPORTED(__inst_thumb32(0xfff00000) "")
649
650 TEST_GROUP("Data-processing (plain binary immediate)")
651
652 TEST_R("addw r0, r",1, VAL1,", #0x123")
653 TEST( "addw r14, sp, #0xf5a")
654 TEST( "addw sp, sp, #0x20")
655 TEST( "addw r7, pc, #0x888")
656 TEST_UNSUPPORTED(__inst_thumb32(0xf20f1f20) " @ addw pc, pc, #0x120")
657 TEST_UNSUPPORTED(__inst_thumb32(0xf20d1f20) " @ addw pc, sp, #0x120")
658 TEST_UNSUPPORTED(__inst_thumb32(0xf20f1d20) " @ addw sp, pc, #0x120")
659 TEST_UNSUPPORTED(__inst_thumb32(0xf2001d20) " @ addw sp, r0, #0x120")
660
661 TEST_R("subw r0, r",1, VAL1,", #0x123")
662 TEST( "subw r14, sp, #0xf5a")
663 TEST( "subw sp, sp, #0x20")
664 TEST( "subw r7, pc, #0x888")
665 TEST_UNSUPPORTED(__inst_thumb32(0xf2af1f20) " @ subw pc, pc, #0x120")
666 TEST_UNSUPPORTED(__inst_thumb32(0xf2ad1f20) " @ subw pc, sp, #0x120")
667 TEST_UNSUPPORTED(__inst_thumb32(0xf2af1d20) " @ subw sp, pc, #0x120")
668 TEST_UNSUPPORTED(__inst_thumb32(0xf2a01d20) " @ subw sp, r0, #0x120")
669
670 TEST("movw r0, #0")
671 TEST("movw r0, #0xffff")
672 TEST("movw lr, #0xffff")
673 TEST_UNSUPPORTED(__inst_thumb32(0xf2400d00) " @ movw sp, #0")
674 TEST_UNSUPPORTED(__inst_thumb32(0xf2400f00) " @ movw pc, #0")
675
676 TEST_R("movt r",0, VAL1,", #0")
677 TEST_R("movt r",0, VAL2,", #0xffff")
678 TEST_R("movt r",14,VAL1,", #0xffff")
679 TEST_UNSUPPORTED(__inst_thumb32(0xf2c00d00) " @ movt sp, #0")
680 TEST_UNSUPPORTED(__inst_thumb32(0xf2c00f00) " @ movt pc, #0")
681
682 TEST_R( "ssat r0, #24, r",0, VAL1,"")
683 TEST_R( "ssat r14, #24, r",12, VAL2,"")
684 TEST_R( "ssat r0, #24, r",0, VAL1,", lsl #8")
685 TEST_R( "ssat r14, #24, r",12, VAL2,", asr #8")
686 TEST_UNSUPPORTED(__inst_thumb32(0xf30c0d17) " @ ssat sp, #24, r12")
687 TEST_UNSUPPORTED(__inst_thumb32(0xf30c0f17) " @ ssat pc, #24, r12")
688 TEST_UNSUPPORTED(__inst_thumb32(0xf30d0c17) " @ ssat r12, #24, sp")
689 TEST_UNSUPPORTED(__inst_thumb32(0xf30f0c17) " @ ssat r12, #24, pc")
690
691 TEST_R( "usat r0, #24, r",0, VAL1,"")
692 TEST_R( "usat r14, #24, r",12, VAL2,"")
693 TEST_R( "usat r0, #24, r",0, VAL1,", lsl #8")
694 TEST_R( "usat r14, #24, r",12, VAL2,", asr #8")
695 TEST_UNSUPPORTED(__inst_thumb32(0xf38c0d17) " @ usat sp, #24, r12")
696 TEST_UNSUPPORTED(__inst_thumb32(0xf38c0f17) " @ usat pc, #24, r12")
697 TEST_UNSUPPORTED(__inst_thumb32(0xf38d0c17) " @ usat r12, #24, sp")
698 TEST_UNSUPPORTED(__inst_thumb32(0xf38f0c17) " @ usat r12, #24, pc")
699
700 TEST_R( "ssat16 r0, #12, r",0, HH1,"")
701 TEST_R( "ssat16 r14, #12, r",12, HH2,"")
702 TEST_UNSUPPORTED(__inst_thumb32(0xf32c0d0b) " @ ssat16 sp, #12, r12")
703 TEST_UNSUPPORTED(__inst_thumb32(0xf32c0f0b) " @ ssat16 pc, #12, r12")
704 TEST_UNSUPPORTED(__inst_thumb32(0xf32d0c0b) " @ ssat16 r12, #12, sp")
705 TEST_UNSUPPORTED(__inst_thumb32(0xf32f0c0b) " @ ssat16 r12, #12, pc")
706
707 TEST_R( "usat16 r0, #12, r",0, HH1,"")
708 TEST_R( "usat16 r14, #12, r",12, HH2,"")
709 TEST_UNSUPPORTED(__inst_thumb32(0xf3ac0d0b) " @ usat16 sp, #12, r12")
710 TEST_UNSUPPORTED(__inst_thumb32(0xf3ac0f0b) " @ usat16 pc, #12, r12")
711 TEST_UNSUPPORTED(__inst_thumb32(0xf3ad0c0b) " @ usat16 r12, #12, sp")
712 TEST_UNSUPPORTED(__inst_thumb32(0xf3af0c0b) " @ usat16 r12, #12, pc")
713
714 TEST_R( "sbfx r0, r",0 , VAL1,", #0, #31")
715 TEST_R( "sbfx r14, r",12, VAL2,", #8, #16")
716 TEST_R( "sbfx r4, r",10, VAL1,", #16, #15")
717 TEST_UNSUPPORTED(__inst_thumb32(0xf34c2d0f) " @ sbfx sp, r12, #8, #16")
718 TEST_UNSUPPORTED(__inst_thumb32(0xf34c2f0f) " @ sbfx pc, r12, #8, #16")
719 TEST_UNSUPPORTED(__inst_thumb32(0xf34d2c0f) " @ sbfx r12, sp, #8, #16")
720 TEST_UNSUPPORTED(__inst_thumb32(0xf34f2c0f) " @ sbfx r12, pc, #8, #16")
721
722 TEST_R( "ubfx r0, r",0 , VAL1,", #0, #31")
723 TEST_R( "ubfx r14, r",12, VAL2,", #8, #16")
724 TEST_R( "ubfx r4, r",10, VAL1,", #16, #15")
725 TEST_UNSUPPORTED(__inst_thumb32(0xf3cc2d0f) " @ ubfx sp, r12, #8, #16")
726 TEST_UNSUPPORTED(__inst_thumb32(0xf3cc2f0f) " @ ubfx pc, r12, #8, #16")
727 TEST_UNSUPPORTED(__inst_thumb32(0xf3cd2c0f) " @ ubfx r12, sp, #8, #16")
728 TEST_UNSUPPORTED(__inst_thumb32(0xf3cf2c0f) " @ ubfx r12, pc, #8, #16")
729
730 TEST_R( "bfc r",0, VAL1,", #4, #20")
731 TEST_R( "bfc r",14,VAL2,", #4, #20")
732 TEST_R( "bfc r",7, VAL1,", #0, #31")
733 TEST_R( "bfc r",8, VAL2,", #0, #31")
734 TEST_UNSUPPORTED(__inst_thumb32(0xf36f0d1e) " @ bfc sp, #0, #31")
735 TEST_UNSUPPORTED(__inst_thumb32(0xf36f0f1e) " @ bfc pc, #0, #31")
736
737 TEST_RR( "bfi r",0, VAL1,", r",0 , VAL2,", #0, #31")
738 TEST_RR( "bfi r",12,VAL1,", r",14 , VAL2,", #4, #20")
739 TEST_UNSUPPORTED(__inst_thumb32(0xf36e1d17) " @ bfi sp, r14, #4, #20")
740 TEST_UNSUPPORTED(__inst_thumb32(0xf36e1f17) " @ bfi pc, r14, #4, #20")
741 TEST_UNSUPPORTED(__inst_thumb32(0xf36d1e17) " @ bfi r14, sp, #4, #20")
742
743 TEST_GROUP("Branches and miscellaneous control")
744
745CONDITION_INSTRUCTIONS(22,
746 TEST_BF("beq.w 2f")
747 TEST_BB("bne.w 2b")
748 TEST_BF("bgt.w 2f")
749 TEST_BB("blt.w 2b")
750 TEST_BF_X("bpl.w 2f", SPACE_0x1000)
751)
752
753 TEST_UNSUPPORTED("msr cpsr, r0")
754 TEST_UNSUPPORTED("msr cpsr_f, r1")
755 TEST_UNSUPPORTED("msr spsr, r2")
756
757 TEST_UNSUPPORTED("cpsie.w i")
758 TEST_UNSUPPORTED("cpsid.w i")
759 TEST_UNSUPPORTED("cps 0x13")
760
761 TEST_SUPPORTED("yield.w")
762 TEST("sev.w")
763 TEST("nop.w")
764 TEST("wfi.w")
765 TEST_SUPPORTED("wfe.w")
766 TEST_UNSUPPORTED("dbg.w #0")
767
768 TEST_UNSUPPORTED("clrex")
769 TEST_UNSUPPORTED("dsb")
770 TEST_UNSUPPORTED("dmb")
771 TEST_UNSUPPORTED("isb")
772
773 TEST_UNSUPPORTED("bxj r0")
774
775 TEST_UNSUPPORTED("subs pc, lr, #4")
776
777 TEST("mrs r0, cpsr")
778 TEST("mrs r14, cpsr")
779 TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8d00) " @ mrs sp, spsr")
780 TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8f00) " @ mrs pc, spsr")
781 TEST_UNSUPPORTED("mrs r0, spsr")
782 TEST_UNSUPPORTED("mrs lr, spsr")
783
784 TEST_UNSUPPORTED(__inst_thumb32(0xf7f08000) " @ smc #0")
785
786 TEST_UNSUPPORTED(__inst_thumb32(0xf7f0a000) " @ undefeined")
787
788 TEST_BF( "b.w 2f")
789 TEST_BB( "b.w 2b")
790 TEST_BF_X("b.w 2f", SPACE_0x1000)
791
792 TEST_BF( "bl.w 2f")
793 TEST_BB( "bl.w 2b")
794 TEST_BB_X("bl.w 2b", SPACE_0x1000)
795
796 TEST_X( "blx __dummy_arm_subroutine",
797 ".arm \n\t"
798 ".align \n\t"
799 ".type __dummy_arm_subroutine, %%function \n\t"
800 "__dummy_arm_subroutine: \n\t"
801 "mov r0, pc \n\t"
802 "bx lr \n\t"
803 ".thumb \n\t"
804 )
805 TEST( "blx __dummy_arm_subroutine")
806
807 TEST_GROUP("Store single data item")
808
809#define SINGLE_STORE(size) \
810 TEST_RP( "str"size" r",0, VAL1,", [r",11,-1024,", #1024]") \
811 TEST_RP( "str"size" r",14,VAL2,", [r",1, -1024,", #1080]") \
812 TEST_RP( "str"size" r",0, VAL1,", [r",11,256, ", #-120]") \
813 TEST_RP( "str"size" r",14,VAL2,", [r",1, 256, ", #-128]") \
814 TEST_RP( "str"size" r",0, VAL1,", [r",11,24, "], #120") \
815 TEST_RP( "str"size" r",14,VAL2,", [r",1, 24, "], #128") \
816 TEST_RP( "str"size" r",0, VAL1,", [r",11,24, "], #-120") \
817 TEST_RP( "str"size" r",14,VAL2,", [r",1, 24, "], #-128") \
818 TEST_RP( "str"size" r",0, VAL1,", [r",11,24, ", #120]!") \
819 TEST_RP( "str"size" r",14,VAL2,", [r",1, 24, ", #128]!") \
820 TEST_RP( "str"size" r",0, VAL1,", [r",11,256, ", #-120]!") \
821 TEST_RP( "str"size" r",14,VAL2,", [r",1, 256, ", #-128]!") \
822 TEST_RPR("str"size".w r",0, VAL1,", [r",1, 0,", r",2, 4,"]") \
823 TEST_RPR("str"size" r",14,VAL2,", [r",10,0,", r",11,4,", lsl #1]") \
824 TEST_R( "str"size".w r",7, VAL1,", [sp, #24]") \
825 TEST_RP( "str"size".w r",0, VAL2,", [r",0,0, "]") \
826 TEST_UNSUPPORTED("str"size"t r0, [r1, #4]")
827
828 SINGLE_STORE("b")
829 SINGLE_STORE("h")
830 SINGLE_STORE("")
831
832 TEST("str sp, [sp]")
833 TEST_UNSUPPORTED(__inst_thumb32(0xf8cfe000) " @ str r14, [pc]")
834 TEST_UNSUPPORTED(__inst_thumb32(0xf8cef000) " @ str pc, [r14]")
835
836 TEST_GROUP("Advanced SIMD element or structure load/store instructions")
837
838 TEST_UNSUPPORTED(__inst_thumb32(0xf9000000) "")
839 TEST_UNSUPPORTED(__inst_thumb32(0xf92fffff) "")
840 TEST_UNSUPPORTED(__inst_thumb32(0xf9800000) "")
841 TEST_UNSUPPORTED(__inst_thumb32(0xf9efffff) "")
842
843 TEST_GROUP("Load single data item and memory hints")
844
845#define SINGLE_LOAD(size) \
846 TEST_P( "ldr"size" r0, [r",11,-1024, ", #1024]") \
847 TEST_P( "ldr"size" r14, [r",1, -1024,", #1080]") \
848 TEST_P( "ldr"size" r0, [r",11,256, ", #-120]") \
849 TEST_P( "ldr"size" r14, [r",1, 256, ", #-128]") \
850 TEST_P( "ldr"size" r0, [r",11,24, "], #120") \
851 TEST_P( "ldr"size" r14, [r",1, 24, "], #128") \
852 TEST_P( "ldr"size" r0, [r",11,24, "], #-120") \
853 TEST_P( "ldr"size" r14, [r",1,24, "], #-128") \
854 TEST_P( "ldr"size" r0, [r",11,24, ", #120]!") \
855 TEST_P( "ldr"size" r14, [r",1, 24, ", #128]!") \
856 TEST_P( "ldr"size" r0, [r",11,256, ", #-120]!") \
857 TEST_P( "ldr"size" r14, [r",1, 256, ", #-128]!") \
858 TEST_PR("ldr"size".w r0, [r",1, 0,", r",2, 4,"]") \
859 TEST_PR("ldr"size" r14, [r",10,0,", r",11,4,", lsl #1]") \
860 TEST_X( "ldr"size".w r0, 3f", \
861 ".align 3 \n\t" \
862 "3: .word "__stringify(VAL1)) \
863 TEST_X( "ldr"size".w r14, 3f", \
864 ".align 3 \n\t" \
865 "3: .word "__stringify(VAL2)) \
866 TEST( "ldr"size".w r7, 3b") \
867 TEST( "ldr"size".w r7, [sp, #24]") \
868 TEST_P( "ldr"size".w r0, [r",0,0, "]") \
869 TEST_UNSUPPORTED("ldr"size"t r0, [r1, #4]")
870
871 SINGLE_LOAD("b")
872 SINGLE_LOAD("sb")
873 SINGLE_LOAD("h")
874 SINGLE_LOAD("sh")
875 SINGLE_LOAD("")
876
877 TEST_BF_P("ldr pc, [r",14, 15*4,"]")
878 TEST_P( "ldr sp, [r",14, 13*4,"]")
879 TEST_BF_R("ldr pc, [sp, r",14, 15*4,"]")
880 TEST_R( "ldr sp, [sp, r",14, 13*4,"]")
881 TEST_THUMB_TO_ARM_INTERWORK_P("ldr pc, [r",0,0,", #15*4]")
882 TEST_SUPPORTED("ldr sp, 99f")
883 TEST_SUPPORTED("ldr pc, 99f")
884
885 TEST_UNSUPPORTED(__inst_thumb32(0xf854700d) " @ ldr r7, [r4, sp]")
886 TEST_UNSUPPORTED(__inst_thumb32(0xf854700f) " @ ldr r7, [r4, pc]")
887 TEST_UNSUPPORTED(__inst_thumb32(0xf814700d) " @ ldrb r7, [r4, sp]")
888 TEST_UNSUPPORTED(__inst_thumb32(0xf814700f) " @ ldrb r7, [r4, pc]")
889 TEST_UNSUPPORTED(__inst_thumb32(0xf89fd004) " @ ldrb sp, 99f")
890 TEST_UNSUPPORTED(__inst_thumb32(0xf814d008) " @ ldrb sp, [r4, r8]")
891 TEST_UNSUPPORTED(__inst_thumb32(0xf894d000) " @ ldrb sp, [r4]")
892
893 TEST_UNSUPPORTED(__inst_thumb32(0xf8600000) "") /* Unallocated space */
894 TEST_UNSUPPORTED(__inst_thumb32(0xf9ffffff) "") /* Unallocated space */
895 TEST_UNSUPPORTED(__inst_thumb32(0xf9500000) "") /* Unallocated space */
896 TEST_UNSUPPORTED(__inst_thumb32(0xf95fffff) "") /* Unallocated space */
897 TEST_UNSUPPORTED(__inst_thumb32(0xf8000800) "") /* Unallocated space */
898 TEST_UNSUPPORTED(__inst_thumb32(0xf97ffaff) "") /* Unallocated space */
899
900 TEST( "pli [pc, #4]")
901 TEST( "pli [pc, #-4]")
902 TEST( "pld [pc, #4]")
903 TEST( "pld [pc, #-4]")
904
905 TEST_P( "pld [r",0,-1024,", #1024]")
906 TEST( __inst_thumb32(0xf8b0f400) " @ pldw [r0, #1024]")
907 TEST_P( "pli [r",4, 0b,", #1024]")
908 TEST_P( "pld [r",7, 120,", #-120]")
909 TEST( __inst_thumb32(0xf837fc78) " @ pldw [r7, #-120]")
910 TEST_P( "pli [r",11,120,", #-120]")
911 TEST( "pld [sp, #0]")
912
913 TEST_PR("pld [r",7, 24, ", r",0, 16,"]")
914 TEST_PR("pld [r",8, 24, ", r",12,16,", lsl #3]")
915 TEST_SUPPORTED(__inst_thumb32(0xf837f000) " @ pldw [r7, r0]")
916 TEST_SUPPORTED(__inst_thumb32(0xf838f03c) " @ pldw [r8, r12, lsl #3]");
917 TEST_RR("pli [r",12,0b,", r",0, 16,"]")
918 TEST_RR("pli [r",0, 0b,", r",12,16,", lsl #3]")
919 TEST_R( "pld [sp, r",1, 16,"]")
920 TEST_UNSUPPORTED(__inst_thumb32(0xf817f00d) " @pld [r7, sp]")
921 TEST_UNSUPPORTED(__inst_thumb32(0xf817f00f) " @pld [r7, pc]")
922
923 TEST_GROUP("Data-processing (register)")
924
925#define SHIFTS32(op) \
926 TEST_RR(op" r0, r",1, VAL1,", r",2, 3, "") \
927 TEST_RR(op" r14, r",12,VAL2,", r",11,10,"")
928
929 SHIFTS32("lsl")
930 SHIFTS32("lsls")
931 SHIFTS32("lsr")
932 SHIFTS32("lsrs")
933 SHIFTS32("asr")
934 SHIFTS32("asrs")
935 SHIFTS32("ror")
936 SHIFTS32("rors")
937
938 TEST_UNSUPPORTED(__inst_thumb32(0xfa01ff02) " @ lsl pc, r1, r2")
939 TEST_UNSUPPORTED(__inst_thumb32(0xfa01fd02) " @ lsl sp, r1, r2")
940 TEST_UNSUPPORTED(__inst_thumb32(0xfa0ff002) " @ lsl r0, pc, r2")
941 TEST_UNSUPPORTED(__inst_thumb32(0xfa0df002) " @ lsl r0, sp, r2")
942 TEST_UNSUPPORTED(__inst_thumb32(0xfa01f00f) " @ lsl r0, r1, pc")
943 TEST_UNSUPPORTED(__inst_thumb32(0xfa01f00d) " @ lsl r0, r1, sp")
944
945 TEST_RR( "sxtah r0, r",0, HH1,", r",1, HH2,"")
946 TEST_RR( "sxtah r14,r",12, HH2,", r",10,HH1,", ror #8")
947 TEST_R( "sxth r8, r",7, HH1,"")
948
949 TEST_UNSUPPORTED(__inst_thumb32(0xfa0fff87) " @ sxth pc, r7");
950 TEST_UNSUPPORTED(__inst_thumb32(0xfa0ffd87) " @ sxth sp, r7");
951 TEST_UNSUPPORTED(__inst_thumb32(0xfa0ff88f) " @ sxth r8, pc");
952 TEST_UNSUPPORTED(__inst_thumb32(0xfa0ff88d) " @ sxth r8, sp");
953
954 TEST_RR( "uxtah r0, r",0, HH1,", r",1, HH2,"")
955 TEST_RR( "uxtah r14,r",12, HH2,", r",10,HH1,", ror #8")
956 TEST_R( "uxth r8, r",7, HH1,"")
957
958 TEST_RR( "sxtab16 r0, r",0, HH1,", r",1, HH2,"")
959 TEST_RR( "sxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8")
960 TEST_R( "sxtb16 r8, r",7, HH1,"")
961
962 TEST_RR( "uxtab16 r0, r",0, HH1,", r",1, HH2,"")
963 TEST_RR( "uxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8")
964 TEST_R( "uxtb16 r8, r",7, HH1,"")
965
966 TEST_RR( "sxtab r0, r",0, HH1,", r",1, HH2,"")
967 TEST_RR( "sxtab r14,r",12, HH2,", r",10,HH1,", ror #8")
968 TEST_R( "sxtb r8, r",7, HH1,"")
969
970 TEST_RR( "uxtab r0, r",0, HH1,", r",1, HH2,"")
971 TEST_RR( "uxtab r14,r",12, HH2,", r",10,HH1,", ror #8")
972 TEST_R( "uxtb r8, r",7, HH1,"")
973
974 TEST_UNSUPPORTED(__inst_thumb32(0xfa6000f0) "")
975 TEST_UNSUPPORTED(__inst_thumb32(0xfa7fffff) "")
976
977#define PARALLEL_ADD_SUB(op) \
978 TEST_RR( op"add16 r0, r",0, HH1,", r",1, HH2,"") \
979 TEST_RR( op"add16 r14, r",12,HH2,", r",10,HH1,"") \
980 TEST_RR( op"asx r0, r",0, HH1,", r",1, HH2,"") \
981 TEST_RR( op"asx r14, r",12,HH2,", r",10,HH1,"") \
982 TEST_RR( op"sax r0, r",0, HH1,", r",1, HH2,"") \
983 TEST_RR( op"sax r14, r",12,HH2,", r",10,HH1,"") \
984 TEST_RR( op"sub16 r0, r",0, HH1,", r",1, HH2,"") \
985 TEST_RR( op"sub16 r14, r",12,HH2,", r",10,HH1,"") \
986 TEST_RR( op"add8 r0, r",0, HH1,", r",1, HH2,"") \
987 TEST_RR( op"add8 r14, r",12,HH2,", r",10,HH1,"") \
988 TEST_RR( op"sub8 r0, r",0, HH1,", r",1, HH2,"") \
989 TEST_RR( op"sub8 r14, r",12,HH2,", r",10,HH1,"")
990
991 TEST_GROUP("Parallel addition and subtraction, signed")
992
993 PARALLEL_ADD_SUB("s")
994 PARALLEL_ADD_SUB("q")
995 PARALLEL_ADD_SUB("sh")
996
997 TEST_GROUP("Parallel addition and subtraction, unsigned")
998
999 PARALLEL_ADD_SUB("u")
1000 PARALLEL_ADD_SUB("uq")
1001 PARALLEL_ADD_SUB("uh")
1002
1003 TEST_GROUP("Miscellaneous operations")
1004
1005 TEST_RR("qadd r0, r",1, VAL1,", r",2, VAL2,"")
1006 TEST_RR("qadd lr, r",9, VAL2,", r",8, VAL1,"")
1007 TEST_RR("qsub r0, r",1, VAL1,", r",2, VAL2,"")
1008 TEST_RR("qsub lr, r",9, VAL2,", r",8, VAL1,"")
1009 TEST_RR("qdadd r0, r",1, VAL1,", r",2, VAL2,"")
1010 TEST_RR("qdadd lr, r",9, VAL2,", r",8, VAL1,"")
1011 TEST_RR("qdsub r0, r",1, VAL1,", r",2, VAL2,"")
1012 TEST_RR("qdsub lr, r",9, VAL2,", r",8, VAL1,"")
1013
1014 TEST_R("rev.w r0, r",0, VAL1,"")
1015 TEST_R("rev r14, r",12, VAL2,"")
1016 TEST_R("rev16.w r0, r",0, VAL1,"")
1017 TEST_R("rev16 r14, r",12, VAL2,"")
1018 TEST_R("rbit r0, r",0, VAL1,"")
1019 TEST_R("rbit r14, r",12, VAL2,"")
1020 TEST_R("revsh.w r0, r",0, VAL1,"")
1021 TEST_R("revsh r14, r",12, VAL2,"")
1022
1023 TEST_UNSUPPORTED(__inst_thumb32(0xfa9cff8c) " @ rev pc, r12");
1024 TEST_UNSUPPORTED(__inst_thumb32(0xfa9cfd8c) " @ rev sp, r12");
1025 TEST_UNSUPPORTED(__inst_thumb32(0xfa9ffe8f) " @ rev r14, pc");
1026 TEST_UNSUPPORTED(__inst_thumb32(0xfa9dfe8d) " @ rev r14, sp");
1027
1028 TEST_RR("sel r0, r",0, VAL1,", r",1, VAL2,"")
1029 TEST_RR("sel r14, r",12,VAL1,", r",10, VAL2,"")
1030
1031 TEST_R("clz r0, r",0, 0x0,"")
1032 TEST_R("clz r7, r",14,0x1,"")
1033 TEST_R("clz lr, r",7, 0xffffffff,"")
1034
1035 TEST_UNSUPPORTED(__inst_thumb32(0xfa80f030) "") /* Unallocated space */
1036 TEST_UNSUPPORTED(__inst_thumb32(0xfaffff7f) "") /* Unallocated space */
1037 TEST_UNSUPPORTED(__inst_thumb32(0xfab0f000) "") /* Unallocated space */
1038 TEST_UNSUPPORTED(__inst_thumb32(0xfaffff7f) "") /* Unallocated space */
1039
1040 TEST_GROUP("Multiply, multiply accumulate, and absolute difference operations")
1041
1042 TEST_RR( "mul r0, r",1, VAL1,", r",2, VAL2,"")
1043 TEST_RR( "mul r7, r",8, VAL2,", r",9, VAL2,"")
1044 TEST_UNSUPPORTED(__inst_thumb32(0xfb08ff09) " @ mul pc, r8, r9")
1045 TEST_UNSUPPORTED(__inst_thumb32(0xfb08fd09) " @ mul sp, r8, r9")
1046 TEST_UNSUPPORTED(__inst_thumb32(0xfb0ff709) " @ mul r7, pc, r9")
1047 TEST_UNSUPPORTED(__inst_thumb32(0xfb0df709) " @ mul r7, sp, r9")
1048 TEST_UNSUPPORTED(__inst_thumb32(0xfb08f70f) " @ mul r7, r8, pc")
1049 TEST_UNSUPPORTED(__inst_thumb32(0xfb08f70d) " @ mul r7, r8, sp")
1050
1051 TEST_RRR( "mla r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
1052 TEST_RRR( "mla r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
1053 TEST_UNSUPPORTED(__inst_thumb32(0xfb08af09) " @ mla pc, r8, r9, r10");
1054 TEST_UNSUPPORTED(__inst_thumb32(0xfb08ad09) " @ mla sp, r8, r9, r10");
1055 TEST_UNSUPPORTED(__inst_thumb32(0xfb0fa709) " @ mla r7, pc, r9, r10");
1056 TEST_UNSUPPORTED(__inst_thumb32(0xfb0da709) " @ mla r7, sp, r9, r10");
1057 TEST_UNSUPPORTED(__inst_thumb32(0xfb08a70f) " @ mla r7, r8, pc, r10");
1058 TEST_UNSUPPORTED(__inst_thumb32(0xfb08a70d) " @ mla r7, r8, sp, r10");
1059 TEST_UNSUPPORTED(__inst_thumb32(0xfb08d709) " @ mla r7, r8, r9, sp");
1060
1061 TEST_RRR( "mls r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
1062 TEST_RRR( "mls r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
1063
1064 TEST_RRR( "smlabb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
1065 TEST_RRR( "smlabb r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
1066 TEST_RRR( "smlatb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
1067 TEST_RRR( "smlatb r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
1068 TEST_RRR( "smlabt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
1069 TEST_RRR( "smlabt r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
1070 TEST_RRR( "smlatt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
1071 TEST_RRR( "smlatt r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
1072 TEST_RR( "smulbb r0, r",1, VAL1,", r",2, VAL2,"")
1073 TEST_RR( "smulbb r7, r",8, VAL3,", r",9, VAL1,"")
1074 TEST_RR( "smultb r0, r",1, VAL1,", r",2, VAL2,"")
1075 TEST_RR( "smultb r7, r",8, VAL3,", r",9, VAL1,"")
1076 TEST_RR( "smulbt r0, r",1, VAL1,", r",2, VAL2,"")
1077 TEST_RR( "smulbt r7, r",8, VAL3,", r",9, VAL1,"")
1078 TEST_RR( "smultt r0, r",1, VAL1,", r",2, VAL2,"")
1079 TEST_RR( "smultt r7, r",8, VAL3,", r",9, VAL1,"")
1080
1081 TEST_RRR( "smlad r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
1082 TEST_RRR( "smlad r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
1083 TEST_RRR( "smladx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
1084 TEST_RRR( "smladx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
1085 TEST_RR( "smuad r0, r",0, HH1,", r",1, HH2,"")
1086 TEST_RR( "smuad r14, r",12,HH2,", r",10,HH1,"")
1087 TEST_RR( "smuadx r0, r",0, HH1,", r",1, HH2,"")
1088 TEST_RR( "smuadx r14, r",12,HH2,", r",10,HH1,"")
1089
1090 TEST_RRR( "smlawb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
1091 TEST_RRR( "smlawb r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
1092 TEST_RRR( "smlawt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
1093 TEST_RRR( "smlawt r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
1094 TEST_RR( "smulwb r0, r",1, VAL1,", r",2, VAL2,"")
1095 TEST_RR( "smulwb r7, r",8, VAL3,", r",9, VAL1,"")
1096 TEST_RR( "smulwt r0, r",1, VAL1,", r",2, VAL2,"")
1097 TEST_RR( "smulwt r7, r",8, VAL3,", r",9, VAL1,"")
1098
1099 TEST_RRR( "smlsd r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
1100 TEST_RRR( "smlsd r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
1101 TEST_RRR( "smlsdx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
1102 TEST_RRR( "smlsdx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
1103 TEST_RR( "smusd r0, r",0, HH1,", r",1, HH2,"")
1104 TEST_RR( "smusd r14, r",12,HH2,", r",10,HH1,"")
1105 TEST_RR( "smusdx r0, r",0, HH1,", r",1, HH2,"")
1106 TEST_RR( "smusdx r14, r",12,HH2,", r",10,HH1,"")
1107
1108 TEST_RRR( "smmla r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
1109 TEST_RRR( "smmla r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
1110 TEST_RRR( "smmlar r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
1111 TEST_RRR( "smmlar r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
1112 TEST_RR( "smmul r0, r",0, VAL1,", r",1, VAL2,"")
1113 TEST_RR( "smmul r14, r",12,VAL2,", r",10,VAL1,"")
1114 TEST_RR( "smmulr r0, r",0, VAL1,", r",1, VAL2,"")
1115 TEST_RR( "smmulr r14, r",12,VAL2,", r",10,VAL1,"")
1116
1117 TEST_RRR( "smmls r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
1118 TEST_RRR( "smmls r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
1119 TEST_RRR( "smmlsr r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
1120 TEST_RRR( "smmlsr r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
1121
1122 TEST_RRR( "usada8 r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL3,"")
1123 TEST_RRR( "usada8 r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL3,"")
1124 TEST_RR( "usad8 r0, r",0, VAL1,", r",1, VAL2,"")
1125 TEST_RR( "usad8 r14, r",12,VAL2,", r",10,VAL1,"")
1126
1127 TEST_UNSUPPORTED(__inst_thumb32(0xfb00f010) "") /* Unallocated space */
1128 TEST_UNSUPPORTED(__inst_thumb32(0xfb0fff1f) "") /* Unallocated space */
1129 TEST_UNSUPPORTED(__inst_thumb32(0xfb70f010) "") /* Unallocated space */
1130 TEST_UNSUPPORTED(__inst_thumb32(0xfb7fff1f) "") /* Unallocated space */
1131 TEST_UNSUPPORTED(__inst_thumb32(0xfb700010) "") /* Unallocated space */
1132 TEST_UNSUPPORTED(__inst_thumb32(0xfb7fff1f) "") /* Unallocated space */
1133
1134 TEST_GROUP("Long multiply, long multiply accumulate, and divide")
1135
1136 TEST_RR( "smull r0, r1, r",2, VAL1,", r",3, VAL2,"")
1137 TEST_RR( "smull r7, r8, r",9, VAL2,", r",10, VAL1,"")
1138 TEST_UNSUPPORTED(__inst_thumb32(0xfb89f80a) " @ smull pc, r8, r9, r10");
1139 TEST_UNSUPPORTED(__inst_thumb32(0xfb89d80a) " @ smull sp, r8, r9, r10");
1140 TEST_UNSUPPORTED(__inst_thumb32(0xfb897f0a) " @ smull r7, pc, r9, r10");
1141 TEST_UNSUPPORTED(__inst_thumb32(0xfb897d0a) " @ smull r7, sp, r9, r10");
1142 TEST_UNSUPPORTED(__inst_thumb32(0xfb8f780a) " @ smull r7, r8, pc, r10");
1143 TEST_UNSUPPORTED(__inst_thumb32(0xfb8d780a) " @ smull r7, r8, sp, r10");
1144 TEST_UNSUPPORTED(__inst_thumb32(0xfb89780f) " @ smull r7, r8, r9, pc");
1145 TEST_UNSUPPORTED(__inst_thumb32(0xfb89780d) " @ smull r7, r8, r9, sp");
1146
1147 TEST_RR( "umull r0, r1, r",2, VAL1,", r",3, VAL2,"")
1148 TEST_RR( "umull r7, r8, r",9, VAL2,", r",10, VAL1,"")
1149
1150 TEST_RRRR( "smlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
1151 TEST_RRRR( "smlal r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
1152
1153 TEST_RRRR( "smlalbb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
1154 TEST_RRRR( "smlalbb r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
1155 TEST_RRRR( "smlalbt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
1156 TEST_RRRR( "smlalbt r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
1157 TEST_RRRR( "smlaltb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
1158 TEST_RRRR( "smlaltb r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
1159 TEST_RRRR( "smlaltt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
1160 TEST_RRRR( "smlaltt r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
1161
1162 TEST_RRRR( "smlald r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
1163 TEST_RRRR( "smlald r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
1164 TEST_RRRR( "smlaldx r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
1165 TEST_RRRR( "smlaldx r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
1166
1167 TEST_RRRR( "smlsld r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
1168 TEST_RRRR( "smlsld r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
1169 TEST_RRRR( "smlsldx r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
1170 TEST_RRRR( "smlsldx r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
1171
1172 TEST_RRRR( "umlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
1173 TEST_RRRR( "umlal r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
1174 TEST_RRRR( "umaal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
1175 TEST_RRRR( "umaal r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
1176
1177 TEST_GROUP("Coprocessor instructions")
1178
1179 TEST_UNSUPPORTED(__inst_thumb32(0xfc000000) "")
1180 TEST_UNSUPPORTED(__inst_thumb32(0xffffffff) "")
1181
1182 TEST_GROUP("Testing instructions in IT blocks")
1183
1184 TEST_ITBLOCK("sub.w r0, r0")
1185
1186 verbose("\n");
1187}
1188
diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/kernel/kprobes-test.c
deleted file mode 100644
index b206d7790c77..000000000000
--- a/arch/arm/kernel/kprobes-test.c
+++ /dev/null
@@ -1,1713 +0,0 @@
1/*
2 * arch/arm/kernel/kprobes-test.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/*
12 * This file contains test code for ARM kprobes.
13 *
14 * The top level function run_all_tests() executes tests for all of the
15 * supported instruction sets: ARM, 16-bit Thumb, and 32-bit Thumb. These tests
16 * fall into two categories; run_api_tests() checks basic functionality of the
17 * kprobes API, and run_test_cases() is a comprehensive test for kprobes
18 * instruction decoding and simulation.
19 *
20 * run_test_cases() first checks the kprobes decoding table for self consistency
21 * (using table_test()) then executes a series of test cases for each of the CPU
22 * instruction forms. coverage_start() and coverage_end() are used to verify
23 * that these test cases cover all of the possible combinations of instructions
24 * described by the kprobes decoding tables.
25 *
26 * The individual test cases are in kprobes-test-arm.c and kprobes-test-thumb.c
27 * which use the macros defined in kprobes-test.h. The rest of this
28 * documentation will describe the operation of the framework used by these
29 * test cases.
30 */
31
32/*
33 * TESTING METHODOLOGY
34 * -------------------
35 *
36 * The methodology used to test an ARM instruction 'test_insn' is to use
37 * inline assembler like:
38 *
39 * test_before: nop
40 * test_case: test_insn
41 * test_after: nop
42 *
43 * When the test case is run a kprobe is placed of each nop. The
44 * post-handler of the test_before probe is used to modify the saved CPU
45 * register context to that which we require for the test case. The
46 * pre-handler of the of the test_after probe saves a copy of the CPU
47 * register context. In this way we can execute test_insn with a specific
48 * register context and see the results afterwards.
49 *
50 * To actually test the kprobes instruction emulation we perform the above
51 * step a second time but with an additional kprobe on the test_case
52 * instruction itself. If the emulation is accurate then the results seen
53 * by the test_after probe will be identical to the first run which didn't
54 * have a probe on test_case.
55 *
56 * Each test case is run several times with a variety of variations in the
57 * flags value of stored in CPSR, and for Thumb code, different ITState.
58 *
59 * For instructions which can modify PC, a second test_after probe is used
60 * like this:
61 *
62 * test_before: nop
63 * test_case: test_insn
64 * test_after: nop
65 * b test_done
66 * test_after2: nop
67 * test_done:
68 *
69 * The test case is constructed such that test_insn branches to
70 * test_after2, or, if testing a conditional instruction, it may just
71 * continue to test_after. The probes inserted at both locations let us
72 * determine which happened. A similar approach is used for testing
73 * backwards branches...
74 *
75 * b test_before
76 * b test_done @ helps to cope with off by 1 branches
77 * test_after2: nop
78 * b test_done
79 * test_before: nop
80 * test_case: test_insn
81 * test_after: nop
82 * test_done:
83 *
84 * The macros used to generate the assembler instructions describe above
85 * are TEST_INSTRUCTION, TEST_BRANCH_F (branch forwards) and TEST_BRANCH_B
86 * (branch backwards). In these, the local variables numbered 1, 50, 2 and
87 * 99 represent: test_before, test_case, test_after2 and test_done.
88 *
89 * FRAMEWORK
90 * ---------
91 *
92 * Each test case is wrapped between the pair of macros TESTCASE_START and
93 * TESTCASE_END. As well as performing the inline assembler boilerplate,
94 * these call out to the kprobes_test_case_start() and
95 * kprobes_test_case_end() functions which drive the execution of the test
96 * case. The specific arguments to use for each test case are stored as
97 * inline data constructed using the various TEST_ARG_* macros. Putting
98 * this all together, a simple test case may look like:
99 *
100 * TESTCASE_START("Testing mov r0, r7")
101 * TEST_ARG_REG(7, 0x12345678) // Set r7=0x12345678
102 * TEST_ARG_END("")
103 * TEST_INSTRUCTION("mov r0, r7")
104 * TESTCASE_END
105 *
106 * Note, in practice the single convenience macro TEST_R would be used for this
107 * instead.
108 *
109 * The above would expand to assembler looking something like:
110 *
111 * @ TESTCASE_START
112 * bl __kprobes_test_case_start
113 * .pushsection .rodata
114 * "10:
115 * .ascii "mov r0, r7" @ text title for test case
116 * .byte 0
117 * .popsection
118 * @ start of inline data...
119 * .word 10b @ pointer to title in .rodata section
120 *
121 * @ TEST_ARG_REG
122 * .byte ARG_TYPE_REG
123 * .byte 7
124 * .short 0
125 * .word 0x1234567
126 *
127 * @ TEST_ARG_END
128 * .byte ARG_TYPE_END
129 * .byte TEST_ISA @ flags, including ISA being tested
130 * .short 50f-0f @ offset of 'test_before'
131 * .short 2f-0f @ offset of 'test_after2' (if relevent)
132 * .short 99f-0f @ offset of 'test_done'
133 * @ start of test case code...
134 * 0:
135 * .code TEST_ISA @ switch to ISA being tested
136 *
137 * @ TEST_INSTRUCTION
138 * 50: nop @ location for 'test_before' probe
139 * 1: mov r0, r7 @ the test case instruction 'test_insn'
140 * nop @ location for 'test_after' probe
141 *
142 * // TESTCASE_END
143 * 2:
144 * 99: bl __kprobes_test_case_end_##TEST_ISA
145 * .code NONMAL_ISA
146 *
147 * When the above is execute the following happens...
148 *
149 * __kprobes_test_case_start() is an assembler wrapper which sets up space
150 * for a stack buffer and calls the C function kprobes_test_case_start().
151 * This C function will do some initial processing of the inline data and
152 * setup some global state. It then inserts the test_before and test_after
153 * kprobes and returns a value which causes the assembler wrapper to jump
154 * to the start of the test case code, (local label '0').
155 *
156 * When the test case code executes, the test_before probe will be hit and
157 * test_before_post_handler will call setup_test_context(). This fills the
158 * stack buffer and CPU registers with a test pattern and then processes
159 * the test case arguments. In our example there is one TEST_ARG_REG which
160 * indicates that R7 should be loaded with the value 0x12345678.
161 *
162 * When the test_before probe ends, the test case continues and executes
163 * the "mov r0, r7" instruction. It then hits the test_after probe and the
164 * pre-handler for this (test_after_pre_handler) will save a copy of the
165 * CPU register context. This should now have R0 holding the same value as
166 * R7.
167 *
168 * Finally we get to the call to __kprobes_test_case_end_{32,16}. This is
169 * an assembler wrapper which switches back to the ISA used by the test
170 * code and calls the C function kprobes_test_case_end().
171 *
172 * For each run through the test case, test_case_run_count is incremented
173 * by one. For even runs, kprobes_test_case_end() saves a copy of the
174 * register and stack buffer contents from the test case just run. It then
175 * inserts a kprobe on the test case instruction 'test_insn' and returns a
176 * value to cause the test case code to be re-run.
177 *
178 * For odd numbered runs, kprobes_test_case_end() compares the register and
179 * stack buffer contents to those that were saved on the previous even
180 * numbered run (the one without the kprobe on test_insn). These should be
181 * the same if the kprobe instruction simulation routine is correct.
182 *
183 * The pair of test case runs is repeated with different combinations of
184 * flag values in CPSR and, for Thumb, different ITState. This is
185 * controlled by test_context_cpsr().
186 *
187 * BUILDING TEST CASES
188 * -------------------
189 *
190 *
191 * As an aid to building test cases, the stack buffer is initialised with
192 * some special values:
193 *
194 * [SP+13*4] Contains SP+120. This can be used to test instructions
195 * which load a value into SP.
196 *
197 * [SP+15*4] When testing branching instructions using TEST_BRANCH_{F,B},
198 * this holds the target address of the branch, 'test_after2'.
199 * This can be used to test instructions which load a PC value
200 * from memory.
201 */
202
203#include <linux/kernel.h>
204#include <linux/module.h>
205#include <linux/slab.h>
206#include <linux/kprobes.h>
207#include <linux/errno.h>
208#include <linux/stddef.h>
209#include <linux/bug.h>
210#include <asm/opcodes.h>
211
212#include "kprobes.h"
213#include "probes-arm.h"
214#include "probes-thumb.h"
215#include "kprobes-test.h"
216
217
218#define BENCHMARKING 1
219
220
221/*
222 * Test basic API
223 */
224
225static bool test_regs_ok;
226static int test_func_instance;
227static int pre_handler_called;
228static int post_handler_called;
229static int jprobe_func_called;
230static int kretprobe_handler_called;
231static int tests_failed;
232
233#define FUNC_ARG1 0x12345678
234#define FUNC_ARG2 0xabcdef
235
236
237#ifndef CONFIG_THUMB2_KERNEL
238
239long arm_func(long r0, long r1);
240
241static void __used __naked __arm_kprobes_test_func(void)
242{
243 __asm__ __volatile__ (
244 ".arm \n\t"
245 ".type arm_func, %%function \n\t"
246 "arm_func: \n\t"
247 "adds r0, r0, r1 \n\t"
248 "bx lr \n\t"
249 ".code "NORMAL_ISA /* Back to Thumb if necessary */
250 : : : "r0", "r1", "cc"
251 );
252}
253
254#else /* CONFIG_THUMB2_KERNEL */
255
256long thumb16_func(long r0, long r1);
257long thumb32even_func(long r0, long r1);
258long thumb32odd_func(long r0, long r1);
259
260static void __used __naked __thumb_kprobes_test_funcs(void)
261{
262 __asm__ __volatile__ (
263 ".type thumb16_func, %%function \n\t"
264 "thumb16_func: \n\t"
265 "adds.n r0, r0, r1 \n\t"
266 "bx lr \n\t"
267
268 ".align \n\t"
269 ".type thumb32even_func, %%function \n\t"
270 "thumb32even_func: \n\t"
271 "adds.w r0, r0, r1 \n\t"
272 "bx lr \n\t"
273
274 ".align \n\t"
275 "nop.n \n\t"
276 ".type thumb32odd_func, %%function \n\t"
277 "thumb32odd_func: \n\t"
278 "adds.w r0, r0, r1 \n\t"
279 "bx lr \n\t"
280
281 : : : "r0", "r1", "cc"
282 );
283}
284
285#endif /* CONFIG_THUMB2_KERNEL */
286
287
288static int call_test_func(long (*func)(long, long), bool check_test_regs)
289{
290 long ret;
291
292 ++test_func_instance;
293 test_regs_ok = false;
294
295 ret = (*func)(FUNC_ARG1, FUNC_ARG2);
296 if (ret != FUNC_ARG1 + FUNC_ARG2) {
297 pr_err("FAIL: call_test_func: func returned %lx\n", ret);
298 return false;
299 }
300
301 if (check_test_regs && !test_regs_ok) {
302 pr_err("FAIL: test regs not OK\n");
303 return false;
304 }
305
306 return true;
307}
308
309static int __kprobes pre_handler(struct kprobe *p, struct pt_regs *regs)
310{
311 pre_handler_called = test_func_instance;
312 if (regs->ARM_r0 == FUNC_ARG1 && regs->ARM_r1 == FUNC_ARG2)
313 test_regs_ok = true;
314 return 0;
315}
316
317static void __kprobes post_handler(struct kprobe *p, struct pt_regs *regs,
318 unsigned long flags)
319{
320 post_handler_called = test_func_instance;
321 if (regs->ARM_r0 != FUNC_ARG1 + FUNC_ARG2 || regs->ARM_r1 != FUNC_ARG2)
322 test_regs_ok = false;
323}
324
325static struct kprobe the_kprobe = {
326 .addr = 0,
327 .pre_handler = pre_handler,
328 .post_handler = post_handler
329};
330
331static int test_kprobe(long (*func)(long, long))
332{
333 int ret;
334
335 the_kprobe.addr = (kprobe_opcode_t *)func;
336 ret = register_kprobe(&the_kprobe);
337 if (ret < 0) {
338 pr_err("FAIL: register_kprobe failed with %d\n", ret);
339 return ret;
340 }
341
342 ret = call_test_func(func, true);
343
344 unregister_kprobe(&the_kprobe);
345 the_kprobe.flags = 0; /* Clear disable flag to allow reuse */
346
347 if (!ret)
348 return -EINVAL;
349 if (pre_handler_called != test_func_instance) {
350 pr_err("FAIL: kprobe pre_handler not called\n");
351 return -EINVAL;
352 }
353 if (post_handler_called != test_func_instance) {
354 pr_err("FAIL: kprobe post_handler not called\n");
355 return -EINVAL;
356 }
357 if (!call_test_func(func, false))
358 return -EINVAL;
359 if (pre_handler_called == test_func_instance ||
360 post_handler_called == test_func_instance) {
361 pr_err("FAIL: probe called after unregistering\n");
362 return -EINVAL;
363 }
364
365 return 0;
366}
367
368static void __kprobes jprobe_func(long r0, long r1)
369{
370 jprobe_func_called = test_func_instance;
371 if (r0 == FUNC_ARG1 && r1 == FUNC_ARG2)
372 test_regs_ok = true;
373 jprobe_return();
374}
375
376static struct jprobe the_jprobe = {
377 .entry = jprobe_func,
378};
379
380static int test_jprobe(long (*func)(long, long))
381{
382 int ret;
383
384 the_jprobe.kp.addr = (kprobe_opcode_t *)func;
385 ret = register_jprobe(&the_jprobe);
386 if (ret < 0) {
387 pr_err("FAIL: register_jprobe failed with %d\n", ret);
388 return ret;
389 }
390
391 ret = call_test_func(func, true);
392
393 unregister_jprobe(&the_jprobe);
394 the_jprobe.kp.flags = 0; /* Clear disable flag to allow reuse */
395
396 if (!ret)
397 return -EINVAL;
398 if (jprobe_func_called != test_func_instance) {
399 pr_err("FAIL: jprobe handler function not called\n");
400 return -EINVAL;
401 }
402 if (!call_test_func(func, false))
403 return -EINVAL;
404 if (jprobe_func_called == test_func_instance) {
405 pr_err("FAIL: probe called after unregistering\n");
406 return -EINVAL;
407 }
408
409 return 0;
410}
411
412static int __kprobes
413kretprobe_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
414{
415 kretprobe_handler_called = test_func_instance;
416 if (regs_return_value(regs) == FUNC_ARG1 + FUNC_ARG2)
417 test_regs_ok = true;
418 return 0;
419}
420
421static struct kretprobe the_kretprobe = {
422 .handler = kretprobe_handler,
423};
424
425static int test_kretprobe(long (*func)(long, long))
426{
427 int ret;
428
429 the_kretprobe.kp.addr = (kprobe_opcode_t *)func;
430 ret = register_kretprobe(&the_kretprobe);
431 if (ret < 0) {
432 pr_err("FAIL: register_kretprobe failed with %d\n", ret);
433 return ret;
434 }
435
436 ret = call_test_func(func, true);
437
438 unregister_kretprobe(&the_kretprobe);
439 the_kretprobe.kp.flags = 0; /* Clear disable flag to allow reuse */
440
441 if (!ret)
442 return -EINVAL;
443 if (kretprobe_handler_called != test_func_instance) {
444 pr_err("FAIL: kretprobe handler not called\n");
445 return -EINVAL;
446 }
447 if (!call_test_func(func, false))
448 return -EINVAL;
449 if (jprobe_func_called == test_func_instance) {
450 pr_err("FAIL: kretprobe called after unregistering\n");
451 return -EINVAL;
452 }
453
454 return 0;
455}
456
457static int run_api_tests(long (*func)(long, long))
458{
459 int ret;
460
461 pr_info(" kprobe\n");
462 ret = test_kprobe(func);
463 if (ret < 0)
464 return ret;
465
466 pr_info(" jprobe\n");
467 ret = test_jprobe(func);
468#if defined(CONFIG_THUMB2_KERNEL) && !defined(MODULE)
469 if (ret == -EINVAL) {
470 pr_err("FAIL: Known longtime bug with jprobe on Thumb kernels\n");
471 tests_failed = ret;
472 ret = 0;
473 }
474#endif
475 if (ret < 0)
476 return ret;
477
478 pr_info(" kretprobe\n");
479 ret = test_kretprobe(func);
480 if (ret < 0)
481 return ret;
482
483 return 0;
484}
485
486
487/*
488 * Benchmarking
489 */
490
491#if BENCHMARKING
492
493static void __naked benchmark_nop(void)
494{
495 __asm__ __volatile__ (
496 "nop \n\t"
497 "bx lr"
498 );
499}
500
501#ifdef CONFIG_THUMB2_KERNEL
502#define wide ".w"
503#else
504#define wide
505#endif
506
507static void __naked benchmark_pushpop1(void)
508{
509 __asm__ __volatile__ (
510 "stmdb"wide" sp!, {r3-r11,lr} \n\t"
511 "ldmia"wide" sp!, {r3-r11,pc}"
512 );
513}
514
515static void __naked benchmark_pushpop2(void)
516{
517 __asm__ __volatile__ (
518 "stmdb"wide" sp!, {r0-r8,lr} \n\t"
519 "ldmia"wide" sp!, {r0-r8,pc}"
520 );
521}
522
523static void __naked benchmark_pushpop3(void)
524{
525 __asm__ __volatile__ (
526 "stmdb"wide" sp!, {r4,lr} \n\t"
527 "ldmia"wide" sp!, {r4,pc}"
528 );
529}
530
531static void __naked benchmark_pushpop4(void)
532{
533 __asm__ __volatile__ (
534 "stmdb"wide" sp!, {r0,lr} \n\t"
535 "ldmia"wide" sp!, {r0,pc}"
536 );
537}
538
539
540#ifdef CONFIG_THUMB2_KERNEL
541
542static void __naked benchmark_pushpop_thumb(void)
543{
544 __asm__ __volatile__ (
545 "push.n {r0-r7,lr} \n\t"
546 "pop.n {r0-r7,pc}"
547 );
548}
549
550#endif
551
552static int __kprobes
553benchmark_pre_handler(struct kprobe *p, struct pt_regs *regs)
554{
555 return 0;
556}
557
558static int benchmark(void(*fn)(void))
559{
560 unsigned n, i, t, t0;
561
562 for (n = 1000; ; n *= 2) {
563 t0 = sched_clock();
564 for (i = n; i > 0; --i)
565 fn();
566 t = sched_clock() - t0;
567 if (t >= 250000000)
568 break; /* Stop once we took more than 0.25 seconds */
569 }
570 return t / n; /* Time for one iteration in nanoseconds */
571};
572
573static int kprobe_benchmark(void(*fn)(void), unsigned offset)
574{
575 struct kprobe k = {
576 .addr = (kprobe_opcode_t *)((uintptr_t)fn + offset),
577 .pre_handler = benchmark_pre_handler,
578 };
579
580 int ret = register_kprobe(&k);
581 if (ret < 0) {
582 pr_err("FAIL: register_kprobe failed with %d\n", ret);
583 return ret;
584 }
585
586 ret = benchmark(fn);
587
588 unregister_kprobe(&k);
589 return ret;
590};
591
592struct benchmarks {
593 void (*fn)(void);
594 unsigned offset;
595 const char *title;
596};
597
598static int run_benchmarks(void)
599{
600 int ret;
601 struct benchmarks list[] = {
602 {&benchmark_nop, 0, "nop"},
603 /*
604 * benchmark_pushpop{1,3} will have the optimised
605 * instruction emulation, whilst benchmark_pushpop{2,4} will
606 * be the equivalent unoptimised instructions.
607 */
608 {&benchmark_pushpop1, 0, "stmdb sp!, {r3-r11,lr}"},
609 {&benchmark_pushpop1, 4, "ldmia sp!, {r3-r11,pc}"},
610 {&benchmark_pushpop2, 0, "stmdb sp!, {r0-r8,lr}"},
611 {&benchmark_pushpop2, 4, "ldmia sp!, {r0-r8,pc}"},
612 {&benchmark_pushpop3, 0, "stmdb sp!, {r4,lr}"},
613 {&benchmark_pushpop3, 4, "ldmia sp!, {r4,pc}"},
614 {&benchmark_pushpop4, 0, "stmdb sp!, {r0,lr}"},
615 {&benchmark_pushpop4, 4, "ldmia sp!, {r0,pc}"},
616#ifdef CONFIG_THUMB2_KERNEL
617 {&benchmark_pushpop_thumb, 0, "push.n {r0-r7,lr}"},
618 {&benchmark_pushpop_thumb, 2, "pop.n {r0-r7,pc}"},
619#endif
620 {0}
621 };
622
623 struct benchmarks *b;
624 for (b = list; b->fn; ++b) {
625 ret = kprobe_benchmark(b->fn, b->offset);
626 if (ret < 0)
627 return ret;
628 pr_info(" %dns for kprobe %s\n", ret, b->title);
629 }
630
631 pr_info("\n");
632 return 0;
633}
634
635#endif /* BENCHMARKING */
636
637
638/*
639 * Decoding table self-consistency tests
640 */
641
642static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
643 [DECODE_TYPE_TABLE] = sizeof(struct decode_table),
644 [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom),
645 [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate),
646 [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate),
647 [DECODE_TYPE_OR] = sizeof(struct decode_or),
648 [DECODE_TYPE_REJECT] = sizeof(struct decode_reject)
649};
650
651static int table_iter(const union decode_item *table,
652 int (*fn)(const struct decode_header *, void *),
653 void *args)
654{
655 const struct decode_header *h = (struct decode_header *)table;
656 int result;
657
658 for (;;) {
659 enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
660
661 if (type == DECODE_TYPE_END)
662 return 0;
663
664 result = fn(h, args);
665 if (result)
666 return result;
667
668 h = (struct decode_header *)
669 ((uintptr_t)h + decode_struct_sizes[type]);
670
671 }
672}
673
674static int table_test_fail(const struct decode_header *h, const char* message)
675{
676
677 pr_err("FAIL: kprobes test failure \"%s\" (mask %08x, value %08x)\n",
678 message, h->mask.bits, h->value.bits);
679 return -EINVAL;
680}
681
682struct table_test_args {
683 const union decode_item *root_table;
684 u32 parent_mask;
685 u32 parent_value;
686};
687
688static int table_test_fn(const struct decode_header *h, void *args)
689{
690 struct table_test_args *a = (struct table_test_args *)args;
691 enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
692
693 if (h->value.bits & ~h->mask.bits)
694 return table_test_fail(h, "Match value has bits not in mask");
695
696 if ((h->mask.bits & a->parent_mask) != a->parent_mask)
697 return table_test_fail(h, "Mask has bits not in parent mask");
698
699 if ((h->value.bits ^ a->parent_value) & a->parent_mask)
700 return table_test_fail(h, "Value is inconsistent with parent");
701
702 if (type == DECODE_TYPE_TABLE) {
703 struct decode_table *d = (struct decode_table *)h;
704 struct table_test_args args2 = *a;
705 args2.parent_mask = h->mask.bits;
706 args2.parent_value = h->value.bits;
707 return table_iter(d->table.table, table_test_fn, &args2);
708 }
709
710 return 0;
711}
712
713static int table_test(const union decode_item *table)
714{
715 struct table_test_args args = {
716 .root_table = table,
717 .parent_mask = 0,
718 .parent_value = 0
719 };
720 return table_iter(args.root_table, table_test_fn, &args);
721}
722
723
724/*
725 * Decoding table test coverage analysis
726 *
727 * coverage_start() builds a coverage_table which contains a list of
728 * coverage_entry's to match each entry in the specified kprobes instruction
729 * decoding table.
730 *
731 * When test cases are run, coverage_add() is called to process each case.
732 * This looks up the corresponding entry in the coverage_table and sets it as
733 * being matched, as well as clearing the regs flag appropriate for the test.
734 *
735 * After all test cases have been run, coverage_end() is called to check that
736 * all entries in coverage_table have been matched and that all regs flags are
737 * cleared. I.e. that all possible combinations of instructions described by
738 * the kprobes decoding tables have had a test case executed for them.
739 */
740
741bool coverage_fail;
742
743#define MAX_COVERAGE_ENTRIES 256
744
745struct coverage_entry {
746 const struct decode_header *header;
747 unsigned regs;
748 unsigned nesting;
749 char matched;
750};
751
752struct coverage_table {
753 struct coverage_entry *base;
754 unsigned num_entries;
755 unsigned nesting;
756};
757
758struct coverage_table coverage;
759
760#define COVERAGE_ANY_REG (1<<0)
761#define COVERAGE_SP (1<<1)
762#define COVERAGE_PC (1<<2)
763#define COVERAGE_PCWB (1<<3)
764
765static const char coverage_register_lookup[16] = {
766 [REG_TYPE_ANY] = COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC,
767 [REG_TYPE_SAMEAS16] = COVERAGE_ANY_REG,
768 [REG_TYPE_SP] = COVERAGE_SP,
769 [REG_TYPE_PC] = COVERAGE_PC,
770 [REG_TYPE_NOSP] = COVERAGE_ANY_REG | COVERAGE_SP,
771 [REG_TYPE_NOSPPC] = COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC,
772 [REG_TYPE_NOPC] = COVERAGE_ANY_REG | COVERAGE_PC,
773 [REG_TYPE_NOPCWB] = COVERAGE_ANY_REG | COVERAGE_PC | COVERAGE_PCWB,
774 [REG_TYPE_NOPCX] = COVERAGE_ANY_REG,
775 [REG_TYPE_NOSPPCX] = COVERAGE_ANY_REG | COVERAGE_SP,
776};
777
778unsigned coverage_start_registers(const struct decode_header *h)
779{
780 unsigned regs = 0;
781 int i;
782 for (i = 0; i < 20; i += 4) {
783 int r = (h->type_regs.bits >> (DECODE_TYPE_BITS + i)) & 0xf;
784 regs |= coverage_register_lookup[r] << i;
785 }
786 return regs;
787}
788
789static int coverage_start_fn(const struct decode_header *h, void *args)
790{
791 struct coverage_table *coverage = (struct coverage_table *)args;
792 enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
793 struct coverage_entry *entry = coverage->base + coverage->num_entries;
794
795 if (coverage->num_entries == MAX_COVERAGE_ENTRIES - 1) {
796 pr_err("FAIL: Out of space for test coverage data");
797 return -ENOMEM;
798 }
799
800 ++coverage->num_entries;
801
802 entry->header = h;
803 entry->regs = coverage_start_registers(h);
804 entry->nesting = coverage->nesting;
805 entry->matched = false;
806
807 if (type == DECODE_TYPE_TABLE) {
808 struct decode_table *d = (struct decode_table *)h;
809 int ret;
810 ++coverage->nesting;
811 ret = table_iter(d->table.table, coverage_start_fn, coverage);
812 --coverage->nesting;
813 return ret;
814 }
815
816 return 0;
817}
818
819static int coverage_start(const union decode_item *table)
820{
821 coverage.base = kmalloc(MAX_COVERAGE_ENTRIES *
822 sizeof(struct coverage_entry), GFP_KERNEL);
823 coverage.num_entries = 0;
824 coverage.nesting = 0;
825 return table_iter(table, coverage_start_fn, &coverage);
826}
827
828static void
829coverage_add_registers(struct coverage_entry *entry, kprobe_opcode_t insn)
830{
831 int regs = entry->header->type_regs.bits >> DECODE_TYPE_BITS;
832 int i;
833 for (i = 0; i < 20; i += 4) {
834 enum decode_reg_type reg_type = (regs >> i) & 0xf;
835 int reg = (insn >> i) & 0xf;
836 int flag;
837
838 if (!reg_type)
839 continue;
840
841 if (reg == 13)
842 flag = COVERAGE_SP;
843 else if (reg == 15)
844 flag = COVERAGE_PC;
845 else
846 flag = COVERAGE_ANY_REG;
847 entry->regs &= ~(flag << i);
848
849 switch (reg_type) {
850
851 case REG_TYPE_NONE:
852 case REG_TYPE_ANY:
853 case REG_TYPE_SAMEAS16:
854 break;
855
856 case REG_TYPE_SP:
857 if (reg != 13)
858 return;
859 break;
860
861 case REG_TYPE_PC:
862 if (reg != 15)
863 return;
864 break;
865
866 case REG_TYPE_NOSP:
867 if (reg == 13)
868 return;
869 break;
870
871 case REG_TYPE_NOSPPC:
872 case REG_TYPE_NOSPPCX:
873 if (reg == 13 || reg == 15)
874 return;
875 break;
876
877 case REG_TYPE_NOPCWB:
878 if (!is_writeback(insn))
879 break;
880 if (reg == 15) {
881 entry->regs &= ~(COVERAGE_PCWB << i);
882 return;
883 }
884 break;
885
886 case REG_TYPE_NOPC:
887 case REG_TYPE_NOPCX:
888 if (reg == 15)
889 return;
890 break;
891 }
892
893 }
894}
895
896static void coverage_add(kprobe_opcode_t insn)
897{
898 struct coverage_entry *entry = coverage.base;
899 struct coverage_entry *end = coverage.base + coverage.num_entries;
900 bool matched = false;
901 unsigned nesting = 0;
902
903 for (; entry < end; ++entry) {
904 const struct decode_header *h = entry->header;
905 enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
906
907 if (entry->nesting > nesting)
908 continue; /* Skip sub-table we didn't match */
909
910 if (entry->nesting < nesting)
911 break; /* End of sub-table we were scanning */
912
913 if (!matched) {
914 if ((insn & h->mask.bits) != h->value.bits)
915 continue;
916 entry->matched = true;
917 }
918
919 switch (type) {
920
921 case DECODE_TYPE_TABLE:
922 ++nesting;
923 break;
924
925 case DECODE_TYPE_CUSTOM:
926 case DECODE_TYPE_SIMULATE:
927 case DECODE_TYPE_EMULATE:
928 coverage_add_registers(entry, insn);
929 return;
930
931 case DECODE_TYPE_OR:
932 matched = true;
933 break;
934
935 case DECODE_TYPE_REJECT:
936 default:
937 return;
938 }
939
940 }
941}
942
943static void coverage_end(void)
944{
945 struct coverage_entry *entry = coverage.base;
946 struct coverage_entry *end = coverage.base + coverage.num_entries;
947
948 for (; entry < end; ++entry) {
949 u32 mask = entry->header->mask.bits;
950 u32 value = entry->header->value.bits;
951
952 if (entry->regs) {
953 pr_err("FAIL: Register test coverage missing for %08x %08x (%05x)\n",
954 mask, value, entry->regs);
955 coverage_fail = true;
956 }
957 if (!entry->matched) {
958 pr_err("FAIL: Test coverage entry missing for %08x %08x\n",
959 mask, value);
960 coverage_fail = true;
961 }
962 }
963
964 kfree(coverage.base);
965}
966
967
968/*
969 * Framework for instruction set test cases
970 */
971
972void __naked __kprobes_test_case_start(void)
973{
974 __asm__ __volatile__ (
975 "stmdb sp!, {r4-r11} \n\t"
976 "sub sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
977 "bic r0, lr, #1 @ r0 = inline data \n\t"
978 "mov r1, sp \n\t"
979 "bl kprobes_test_case_start \n\t"
980 "bx r0 \n\t"
981 );
982}
983
984#ifndef CONFIG_THUMB2_KERNEL
985
986void __naked __kprobes_test_case_end_32(void)
987{
988 __asm__ __volatile__ (
989 "mov r4, lr \n\t"
990 "bl kprobes_test_case_end \n\t"
991 "cmp r0, #0 \n\t"
992 "movne pc, r0 \n\t"
993 "mov r0, r4 \n\t"
994 "add sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
995 "ldmia sp!, {r4-r11} \n\t"
996 "mov pc, r0 \n\t"
997 );
998}
999
1000#else /* CONFIG_THUMB2_KERNEL */
1001
1002void __naked __kprobes_test_case_end_16(void)
1003{
1004 __asm__ __volatile__ (
1005 "mov r4, lr \n\t"
1006 "bl kprobes_test_case_end \n\t"
1007 "cmp r0, #0 \n\t"
1008 "bxne r0 \n\t"
1009 "mov r0, r4 \n\t"
1010 "add sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
1011 "ldmia sp!, {r4-r11} \n\t"
1012 "bx r0 \n\t"
1013 );
1014}
1015
1016void __naked __kprobes_test_case_end_32(void)
1017{
1018 __asm__ __volatile__ (
1019 ".arm \n\t"
1020 "orr lr, lr, #1 @ will return to Thumb code \n\t"
1021 "ldr pc, 1f \n\t"
1022 "1: \n\t"
1023 ".word __kprobes_test_case_end_16 \n\t"
1024 );
1025}
1026
1027#endif
1028
1029
1030int kprobe_test_flags;
1031int kprobe_test_cc_position;
1032
1033static int test_try_count;
1034static int test_pass_count;
1035static int test_fail_count;
1036
1037static struct pt_regs initial_regs;
1038static struct pt_regs expected_regs;
1039static struct pt_regs result_regs;
1040
1041static u32 expected_memory[TEST_MEMORY_SIZE/sizeof(u32)];
1042
1043static const char *current_title;
1044static struct test_arg *current_args;
1045static u32 *current_stack;
1046static uintptr_t current_branch_target;
1047
1048static uintptr_t current_code_start;
1049static kprobe_opcode_t current_instruction;
1050
1051
1052#define TEST_CASE_PASSED -1
1053#define TEST_CASE_FAILED -2
1054
1055static int test_case_run_count;
1056static bool test_case_is_thumb;
1057static int test_instance;
1058
1059/*
1060 * We ignore the state of the imprecise abort disable flag (CPSR.A) because this
1061 * can change randomly as the kernel doesn't take care to preserve or initialise
1062 * this across context switches. Also, with Security Extentions, the flag may
1063 * not be under control of the kernel; for this reason we ignore the state of
1064 * the FIQ disable flag CPSR.F as well.
1065 */
1066#define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT)
1067
1068static unsigned long test_check_cc(int cc, unsigned long cpsr)
1069{
1070 int ret = arm_check_condition(cc << 28, cpsr);
1071
1072 return (ret != ARM_OPCODE_CONDTEST_FAIL);
1073}
1074
1075static int is_last_scenario;
1076static int probe_should_run; /* 0 = no, 1 = yes, -1 = unknown */
1077static int memory_needs_checking;
1078
1079static unsigned long test_context_cpsr(int scenario)
1080{
1081 unsigned long cpsr;
1082
1083 probe_should_run = 1;
1084
1085 /* Default case is that we cycle through 16 combinations of flags */
1086 cpsr = (scenario & 0xf) << 28; /* N,Z,C,V flags */
1087 cpsr |= (scenario & 0xf) << 16; /* GE flags */
1088 cpsr |= (scenario & 0x1) << 27; /* Toggle Q flag */
1089
1090 if (!test_case_is_thumb) {
1091 /* Testing ARM code */
1092 int cc = current_instruction >> 28;
1093
1094 probe_should_run = test_check_cc(cc, cpsr) != 0;
1095 if (scenario == 15)
1096 is_last_scenario = true;
1097
1098 } else if (kprobe_test_flags & TEST_FLAG_NO_ITBLOCK) {
1099 /* Testing Thumb code without setting ITSTATE */
1100 if (kprobe_test_cc_position) {
1101 int cc = (current_instruction >> kprobe_test_cc_position) & 0xf;
1102 probe_should_run = test_check_cc(cc, cpsr) != 0;
1103 }
1104
1105 if (scenario == 15)
1106 is_last_scenario = true;
1107
1108 } else if (kprobe_test_flags & TEST_FLAG_FULL_ITBLOCK) {
1109 /* Testing Thumb code with all combinations of ITSTATE */
1110 unsigned x = (scenario >> 4);
1111 unsigned cond_base = x % 7; /* ITSTATE<7:5> */
1112 unsigned mask = x / 7 + 2; /* ITSTATE<4:0>, bits reversed */
1113
1114 if (mask > 0x1f) {
1115 /* Finish by testing state from instruction 'itt al' */
1116 cond_base = 7;
1117 mask = 0x4;
1118 if ((scenario & 0xf) == 0xf)
1119 is_last_scenario = true;
1120 }
1121
1122 cpsr |= cond_base << 13; /* ITSTATE<7:5> */
1123 cpsr |= (mask & 0x1) << 12; /* ITSTATE<4> */
1124 cpsr |= (mask & 0x2) << 10; /* ITSTATE<3> */
1125 cpsr |= (mask & 0x4) << 8; /* ITSTATE<2> */
1126 cpsr |= (mask & 0x8) << 23; /* ITSTATE<1> */
1127 cpsr |= (mask & 0x10) << 21; /* ITSTATE<0> */
1128
1129 probe_should_run = test_check_cc((cpsr >> 12) & 0xf, cpsr) != 0;
1130
1131 } else {
1132 /* Testing Thumb code with several combinations of ITSTATE */
1133 switch (scenario) {
1134 case 16: /* Clear NZCV flags and 'it eq' state (false as Z=0) */
1135 cpsr = 0x00000800;
1136 probe_should_run = 0;
1137 break;
1138 case 17: /* Set NZCV flags and 'it vc' state (false as V=1) */
1139 cpsr = 0xf0007800;
1140 probe_should_run = 0;
1141 break;
1142 case 18: /* Clear NZCV flags and 'it ls' state (true as C=0) */
1143 cpsr = 0x00009800;
1144 break;
1145 case 19: /* Set NZCV flags and 'it cs' state (true as C=1) */
1146 cpsr = 0xf0002800;
1147 is_last_scenario = true;
1148 break;
1149 }
1150 }
1151
1152 return cpsr;
1153}
1154
1155static void setup_test_context(struct pt_regs *regs)
1156{
1157 int scenario = test_case_run_count>>1;
1158 unsigned long val;
1159 struct test_arg *args;
1160 int i;
1161
1162 is_last_scenario = false;
1163 memory_needs_checking = false;
1164
1165 /* Initialise test memory on stack */
1166 val = (scenario & 1) ? VALM : ~VALM;
1167 for (i = 0; i < TEST_MEMORY_SIZE / sizeof(current_stack[0]); ++i)
1168 current_stack[i] = val + (i << 8);
1169 /* Put target of branch on stack for tests which load PC from memory */
1170 if (current_branch_target)
1171 current_stack[15] = current_branch_target;
1172 /* Put a value for SP on stack for tests which load SP from memory */
1173 current_stack[13] = (u32)current_stack + 120;
1174
1175 /* Initialise register values to their default state */
1176 val = (scenario & 2) ? VALR : ~VALR;
1177 for (i = 0; i < 13; ++i)
1178 regs->uregs[i] = val ^ (i << 8);
1179 regs->ARM_lr = val ^ (14 << 8);
1180 regs->ARM_cpsr &= ~(APSR_MASK | PSR_IT_MASK);
1181 regs->ARM_cpsr |= test_context_cpsr(scenario);
1182
1183 /* Perform testcase specific register setup */
1184 args = current_args;
1185 for (; args[0].type != ARG_TYPE_END; ++args)
1186 switch (args[0].type) {
1187 case ARG_TYPE_REG: {
1188 struct test_arg_regptr *arg =
1189 (struct test_arg_regptr *)args;
1190 regs->uregs[arg->reg] = arg->val;
1191 break;
1192 }
1193 case ARG_TYPE_PTR: {
1194 struct test_arg_regptr *arg =
1195 (struct test_arg_regptr *)args;
1196 regs->uregs[arg->reg] =
1197 (unsigned long)current_stack + arg->val;
1198 memory_needs_checking = true;
1199 break;
1200 }
1201 case ARG_TYPE_MEM: {
1202 struct test_arg_mem *arg = (struct test_arg_mem *)args;
1203 current_stack[arg->index] = arg->val;
1204 break;
1205 }
1206 default:
1207 break;
1208 }
1209}
1210
1211struct test_probe {
1212 struct kprobe kprobe;
1213 bool registered;
1214 int hit;
1215};
1216
1217static void unregister_test_probe(struct test_probe *probe)
1218{
1219 if (probe->registered) {
1220 unregister_kprobe(&probe->kprobe);
1221 probe->kprobe.flags = 0; /* Clear disable flag to allow reuse */
1222 }
1223 probe->registered = false;
1224}
1225
1226static int register_test_probe(struct test_probe *probe)
1227{
1228 int ret;
1229
1230 if (probe->registered)
1231 BUG();
1232
1233 ret = register_kprobe(&probe->kprobe);
1234 if (ret >= 0) {
1235 probe->registered = true;
1236 probe->hit = -1;
1237 }
1238 return ret;
1239}
1240
1241static int __kprobes
1242test_before_pre_handler(struct kprobe *p, struct pt_regs *regs)
1243{
1244 container_of(p, struct test_probe, kprobe)->hit = test_instance;
1245 return 0;
1246}
1247
1248static void __kprobes
1249test_before_post_handler(struct kprobe *p, struct pt_regs *regs,
1250 unsigned long flags)
1251{
1252 setup_test_context(regs);
1253 initial_regs = *regs;
1254 initial_regs.ARM_cpsr &= ~PSR_IGNORE_BITS;
1255}
1256
1257static int __kprobes
1258test_case_pre_handler(struct kprobe *p, struct pt_regs *regs)
1259{
1260 container_of(p, struct test_probe, kprobe)->hit = test_instance;
1261 return 0;
1262}
1263
1264static int __kprobes
1265test_after_pre_handler(struct kprobe *p, struct pt_regs *regs)
1266{
1267 if (container_of(p, struct test_probe, kprobe)->hit == test_instance)
1268 return 0; /* Already run for this test instance */
1269
1270 result_regs = *regs;
1271 result_regs.ARM_cpsr &= ~PSR_IGNORE_BITS;
1272
1273 /* Undo any changes done to SP by the test case */
1274 regs->ARM_sp = (unsigned long)current_stack;
1275
1276 container_of(p, struct test_probe, kprobe)->hit = test_instance;
1277 return 0;
1278}
1279
1280static struct test_probe test_before_probe = {
1281 .kprobe.pre_handler = test_before_pre_handler,
1282 .kprobe.post_handler = test_before_post_handler,
1283};
1284
1285static struct test_probe test_case_probe = {
1286 .kprobe.pre_handler = test_case_pre_handler,
1287};
1288
1289static struct test_probe test_after_probe = {
1290 .kprobe.pre_handler = test_after_pre_handler,
1291};
1292
1293static struct test_probe test_after2_probe = {
1294 .kprobe.pre_handler = test_after_pre_handler,
1295};
1296
1297static void test_case_cleanup(void)
1298{
1299 unregister_test_probe(&test_before_probe);
1300 unregister_test_probe(&test_case_probe);
1301 unregister_test_probe(&test_after_probe);
1302 unregister_test_probe(&test_after2_probe);
1303}
1304
1305static void print_registers(struct pt_regs *regs)
1306{
1307 pr_err("r0 %08lx | r1 %08lx | r2 %08lx | r3 %08lx\n",
1308 regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
1309 pr_err("r4 %08lx | r5 %08lx | r6 %08lx | r7 %08lx\n",
1310 regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7);
1311 pr_err("r8 %08lx | r9 %08lx | r10 %08lx | r11 %08lx\n",
1312 regs->ARM_r8, regs->ARM_r9, regs->ARM_r10, regs->ARM_fp);
1313 pr_err("r12 %08lx | sp %08lx | lr %08lx | pc %08lx\n",
1314 regs->ARM_ip, regs->ARM_sp, regs->ARM_lr, regs->ARM_pc);
1315 pr_err("cpsr %08lx\n", regs->ARM_cpsr);
1316}
1317
1318static void print_memory(u32 *mem, size_t size)
1319{
1320 int i;
1321 for (i = 0; i < size / sizeof(u32); i += 4)
1322 pr_err("%08x %08x %08x %08x\n", mem[i], mem[i+1],
1323 mem[i+2], mem[i+3]);
1324}
1325
1326static size_t expected_memory_size(u32 *sp)
1327{
1328 size_t size = sizeof(expected_memory);
1329 int offset = (uintptr_t)sp - (uintptr_t)current_stack;
1330 if (offset > 0)
1331 size -= offset;
1332 return size;
1333}
1334
1335static void test_case_failed(const char *message)
1336{
1337 test_case_cleanup();
1338
1339 pr_err("FAIL: %s\n", message);
1340 pr_err("FAIL: Test %s\n", current_title);
1341 pr_err("FAIL: Scenario %d\n", test_case_run_count >> 1);
1342}
1343
1344static unsigned long next_instruction(unsigned long pc)
1345{
1346#ifdef CONFIG_THUMB2_KERNEL
1347 if ((pc & 1) &&
1348 !is_wide_instruction(__mem_to_opcode_thumb16(*(u16 *)(pc - 1))))
1349 return pc + 2;
1350 else
1351#endif
1352 return pc + 4;
1353}
1354
1355static uintptr_t __used kprobes_test_case_start(const char **title, void *stack)
1356{
1357 struct test_arg *args;
1358 struct test_arg_end *end_arg;
1359 unsigned long test_code;
1360
1361 current_title = *title++;
1362 args = (struct test_arg *)title;
1363 current_args = args;
1364 current_stack = stack;
1365
1366 ++test_try_count;
1367
1368 while (args->type != ARG_TYPE_END)
1369 ++args;
1370 end_arg = (struct test_arg_end *)args;
1371
1372 test_code = (unsigned long)(args + 1); /* Code starts after args */
1373
1374 test_case_is_thumb = end_arg->flags & ARG_FLAG_THUMB;
1375 if (test_case_is_thumb)
1376 test_code |= 1;
1377
1378 current_code_start = test_code;
1379
1380 current_branch_target = 0;
1381 if (end_arg->branch_offset != end_arg->end_offset)
1382 current_branch_target = test_code + end_arg->branch_offset;
1383
1384 test_code += end_arg->code_offset;
1385 test_before_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
1386
1387 test_code = next_instruction(test_code);
1388 test_case_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
1389
1390 if (test_case_is_thumb) {
1391 u16 *p = (u16 *)(test_code & ~1);
1392 current_instruction = __mem_to_opcode_thumb16(p[0]);
1393 if (is_wide_instruction(current_instruction)) {
1394 u16 instr2 = __mem_to_opcode_thumb16(p[1]);
1395 current_instruction = __opcode_thumb32_compose(current_instruction, instr2);
1396 }
1397 } else {
1398 current_instruction = __mem_to_opcode_arm(*(u32 *)test_code);
1399 }
1400
1401 if (current_title[0] == '.')
1402 verbose("%s\n", current_title);
1403 else
1404 verbose("%s\t@ %0*x\n", current_title,
1405 test_case_is_thumb ? 4 : 8,
1406 current_instruction);
1407
1408 test_code = next_instruction(test_code);
1409 test_after_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
1410
1411 if (kprobe_test_flags & TEST_FLAG_NARROW_INSTR) {
1412 if (!test_case_is_thumb ||
1413 is_wide_instruction(current_instruction)) {
1414 test_case_failed("expected 16-bit instruction");
1415 goto fail;
1416 }
1417 } else {
1418 if (test_case_is_thumb &&
1419 !is_wide_instruction(current_instruction)) {
1420 test_case_failed("expected 32-bit instruction");
1421 goto fail;
1422 }
1423 }
1424
1425 coverage_add(current_instruction);
1426
1427 if (end_arg->flags & ARG_FLAG_UNSUPPORTED) {
1428 if (register_test_probe(&test_case_probe) < 0)
1429 goto pass;
1430 test_case_failed("registered probe for unsupported instruction");
1431 goto fail;
1432 }
1433
1434 if (end_arg->flags & ARG_FLAG_SUPPORTED) {
1435 if (register_test_probe(&test_case_probe) >= 0)
1436 goto pass;
1437 test_case_failed("couldn't register probe for supported instruction");
1438 goto fail;
1439 }
1440
1441 if (register_test_probe(&test_before_probe) < 0) {
1442 test_case_failed("register test_before_probe failed");
1443 goto fail;
1444 }
1445 if (register_test_probe(&test_after_probe) < 0) {
1446 test_case_failed("register test_after_probe failed");
1447 goto fail;
1448 }
1449 if (current_branch_target) {
1450 test_after2_probe.kprobe.addr =
1451 (kprobe_opcode_t *)current_branch_target;
1452 if (register_test_probe(&test_after2_probe) < 0) {
1453 test_case_failed("register test_after2_probe failed");
1454 goto fail;
1455 }
1456 }
1457
1458 /* Start first run of test case */
1459 test_case_run_count = 0;
1460 ++test_instance;
1461 return current_code_start;
1462pass:
1463 test_case_run_count = TEST_CASE_PASSED;
1464 return (uintptr_t)test_after_probe.kprobe.addr;
1465fail:
1466 test_case_run_count = TEST_CASE_FAILED;
1467 return (uintptr_t)test_after_probe.kprobe.addr;
1468}
1469
1470static bool check_test_results(void)
1471{
1472 size_t mem_size = 0;
1473 u32 *mem = 0;
1474
1475 if (memcmp(&expected_regs, &result_regs, sizeof(expected_regs))) {
1476 test_case_failed("registers differ");
1477 goto fail;
1478 }
1479
1480 if (memory_needs_checking) {
1481 mem = (u32 *)result_regs.ARM_sp;
1482 mem_size = expected_memory_size(mem);
1483 if (memcmp(expected_memory, mem, mem_size)) {
1484 test_case_failed("test memory differs");
1485 goto fail;
1486 }
1487 }
1488
1489 return true;
1490
1491fail:
1492 pr_err("initial_regs:\n");
1493 print_registers(&initial_regs);
1494 pr_err("expected_regs:\n");
1495 print_registers(&expected_regs);
1496 pr_err("result_regs:\n");
1497 print_registers(&result_regs);
1498
1499 if (mem) {
1500 pr_err("current_stack=%p\n", current_stack);
1501 pr_err("expected_memory:\n");
1502 print_memory(expected_memory, mem_size);
1503 pr_err("result_memory:\n");
1504 print_memory(mem, mem_size);
1505 }
1506
1507 return false;
1508}
1509
1510static uintptr_t __used kprobes_test_case_end(void)
1511{
1512 if (test_case_run_count < 0) {
1513 if (test_case_run_count == TEST_CASE_PASSED)
1514 /* kprobes_test_case_start did all the needed testing */
1515 goto pass;
1516 else
1517 /* kprobes_test_case_start failed */
1518 goto fail;
1519 }
1520
1521 if (test_before_probe.hit != test_instance) {
1522 test_case_failed("test_before_handler not run");
1523 goto fail;
1524 }
1525
1526 if (test_after_probe.hit != test_instance &&
1527 test_after2_probe.hit != test_instance) {
1528 test_case_failed("test_after_handler not run");
1529 goto fail;
1530 }
1531
1532 /*
1533 * Even numbered test runs ran without a probe on the test case so
1534 * we can gather reference results. The subsequent odd numbered run
1535 * will have the probe inserted.
1536 */
1537 if ((test_case_run_count & 1) == 0) {
1538 /* Save results from run without probe */
1539 u32 *mem = (u32 *)result_regs.ARM_sp;
1540 expected_regs = result_regs;
1541 memcpy(expected_memory, mem, expected_memory_size(mem));
1542
1543 /* Insert probe onto test case instruction */
1544 if (register_test_probe(&test_case_probe) < 0) {
1545 test_case_failed("register test_case_probe failed");
1546 goto fail;
1547 }
1548 } else {
1549 /* Check probe ran as expected */
1550 if (probe_should_run == 1) {
1551 if (test_case_probe.hit != test_instance) {
1552 test_case_failed("test_case_handler not run");
1553 goto fail;
1554 }
1555 } else if (probe_should_run == 0) {
1556 if (test_case_probe.hit == test_instance) {
1557 test_case_failed("test_case_handler ran");
1558 goto fail;
1559 }
1560 }
1561
1562 /* Remove probe for any subsequent reference run */
1563 unregister_test_probe(&test_case_probe);
1564
1565 if (!check_test_results())
1566 goto fail;
1567
1568 if (is_last_scenario)
1569 goto pass;
1570 }
1571
1572 /* Do next test run */
1573 ++test_case_run_count;
1574 ++test_instance;
1575 return current_code_start;
1576fail:
1577 ++test_fail_count;
1578 goto end;
1579pass:
1580 ++test_pass_count;
1581end:
1582 test_case_cleanup();
1583 return 0;
1584}
1585
1586
1587/*
1588 * Top level test functions
1589 */
1590
1591static int run_test_cases(void (*tests)(void), const union decode_item *table)
1592{
1593 int ret;
1594
1595 pr_info(" Check decoding tables\n");
1596 ret = table_test(table);
1597 if (ret)
1598 return ret;
1599
1600 pr_info(" Run test cases\n");
1601 ret = coverage_start(table);
1602 if (ret)
1603 return ret;
1604
1605 tests();
1606
1607 coverage_end();
1608 return 0;
1609}
1610
1611
1612static int __init run_all_tests(void)
1613{
1614 int ret = 0;
1615
1616 pr_info("Beginning kprobe tests...\n");
1617
1618#ifndef CONFIG_THUMB2_KERNEL
1619
1620 pr_info("Probe ARM code\n");
1621 ret = run_api_tests(arm_func);
1622 if (ret)
1623 goto out;
1624
1625 pr_info("ARM instruction simulation\n");
1626 ret = run_test_cases(kprobe_arm_test_cases, probes_decode_arm_table);
1627 if (ret)
1628 goto out;
1629
1630#else /* CONFIG_THUMB2_KERNEL */
1631
1632 pr_info("Probe 16-bit Thumb code\n");
1633 ret = run_api_tests(thumb16_func);
1634 if (ret)
1635 goto out;
1636
1637 pr_info("Probe 32-bit Thumb code, even halfword\n");
1638 ret = run_api_tests(thumb32even_func);
1639 if (ret)
1640 goto out;
1641
1642 pr_info("Probe 32-bit Thumb code, odd halfword\n");
1643 ret = run_api_tests(thumb32odd_func);
1644 if (ret)
1645 goto out;
1646
1647 pr_info("16-bit Thumb instruction simulation\n");
1648 ret = run_test_cases(kprobe_thumb16_test_cases,
1649 probes_decode_thumb16_table);
1650 if (ret)
1651 goto out;
1652
1653 pr_info("32-bit Thumb instruction simulation\n");
1654 ret = run_test_cases(kprobe_thumb32_test_cases,
1655 probes_decode_thumb32_table);
1656 if (ret)
1657 goto out;
1658#endif
1659
1660 pr_info("Total instruction simulation tests=%d, pass=%d fail=%d\n",
1661 test_try_count, test_pass_count, test_fail_count);
1662 if (test_fail_count) {
1663 ret = -EINVAL;
1664 goto out;
1665 }
1666
1667#if BENCHMARKING
1668 pr_info("Benchmarks\n");
1669 ret = run_benchmarks();
1670 if (ret)
1671 goto out;
1672#endif
1673
1674#if __LINUX_ARM_ARCH__ >= 7
1675 /* We are able to run all test cases so coverage should be complete */
1676 if (coverage_fail) {
1677 pr_err("FAIL: Test coverage checks failed\n");
1678 ret = -EINVAL;
1679 goto out;
1680 }
1681#endif
1682
1683out:
1684 if (ret == 0)
1685 ret = tests_failed;
1686 if (ret == 0)
1687 pr_info("Finished kprobe tests OK\n");
1688 else
1689 pr_err("kprobe tests failed\n");
1690
1691 return ret;
1692}
1693
1694
1695/*
1696 * Module setup
1697 */
1698
1699#ifdef MODULE
1700
1701static void __exit kprobe_test_exit(void)
1702{
1703}
1704
1705module_init(run_all_tests)
1706module_exit(kprobe_test_exit)
1707MODULE_LICENSE("GPL");
1708
1709#else /* !MODULE */
1710
1711late_initcall(run_all_tests);
1712
1713#endif
diff --git a/arch/arm/kernel/kprobes-test.h b/arch/arm/kernel/kprobes-test.h
deleted file mode 100644
index 4430990e90e7..000000000000
--- a/arch/arm/kernel/kprobes-test.h
+++ /dev/null
@@ -1,435 +0,0 @@
1/*
2 * arch/arm/kernel/kprobes-test.h
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#define VERBOSE 0 /* Set to '1' for more logging of test cases */
12
13#ifdef CONFIG_THUMB2_KERNEL
14#define NORMAL_ISA "16"
15#else
16#define NORMAL_ISA "32"
17#endif
18
19
20/* Flags used in kprobe_test_flags */
21#define TEST_FLAG_NO_ITBLOCK (1<<0)
22#define TEST_FLAG_FULL_ITBLOCK (1<<1)
23#define TEST_FLAG_NARROW_INSTR (1<<2)
24
25extern int kprobe_test_flags;
26extern int kprobe_test_cc_position;
27
28
29#define TEST_MEMORY_SIZE 256
30
31
32/*
33 * Test case structures.
34 *
35 * The arguments given to test cases can be one of three types.
36 *
37 * ARG_TYPE_REG
38 * Load a register with the given value.
39 *
40 * ARG_TYPE_PTR
41 * Load a register with a pointer into the stack buffer (SP + given value).
42 *
43 * ARG_TYPE_MEM
44 * Store the given value into the stack buffer at [SP+index].
45 *
46 */
47
48#define ARG_TYPE_END 0
49#define ARG_TYPE_REG 1
50#define ARG_TYPE_PTR 2
51#define ARG_TYPE_MEM 3
52
53#define ARG_FLAG_UNSUPPORTED 0x01
54#define ARG_FLAG_SUPPORTED 0x02
55#define ARG_FLAG_THUMB 0x10 /* Must be 16 so TEST_ISA can be used */
56#define ARG_FLAG_ARM 0x20 /* Must be 32 so TEST_ISA can be used */
57
58struct test_arg {
59 u8 type; /* ARG_TYPE_x */
60 u8 _padding[7];
61};
62
63struct test_arg_regptr {
64 u8 type; /* ARG_TYPE_REG or ARG_TYPE_PTR */
65 u8 reg;
66 u8 _padding[2];
67 u32 val;
68};
69
70struct test_arg_mem {
71 u8 type; /* ARG_TYPE_MEM */
72 u8 index;
73 u8 _padding[2];
74 u32 val;
75};
76
77struct test_arg_end {
78 u8 type; /* ARG_TYPE_END */
79 u8 flags; /* ARG_FLAG_x */
80 u16 code_offset;
81 u16 branch_offset;
82 u16 end_offset;
83};
84
85
86/*
87 * Building blocks for test cases.
88 *
89 * Each test case is wrapped between TESTCASE_START and TESTCASE_END.
90 *
91 * To specify arguments for a test case the TEST_ARG_{REG,PTR,MEM} macros are
92 * used followed by a terminating TEST_ARG_END.
93 *
94 * After this, the instruction to be tested is defined with TEST_INSTRUCTION.
95 * Or for branches, TEST_BRANCH_B and TEST_BRANCH_F (branch forwards/backwards).
96 *
97 * Some specific test cases may make use of other custom constructs.
98 */
99
100#if VERBOSE
101#define verbose(fmt, ...) pr_info(fmt, ##__VA_ARGS__)
102#else
103#define verbose(fmt, ...)
104#endif
105
106#define TEST_GROUP(title) \
107 verbose("\n"); \
108 verbose(title"\n"); \
109 verbose("---------------------------------------------------------\n");
110
111#define TESTCASE_START(title) \
112 __asm__ __volatile__ ( \
113 "bl __kprobes_test_case_start \n\t" \
114 ".pushsection .rodata \n\t" \
115 "10: \n\t" \
116 /* don't use .asciz here as 'title' may be */ \
117 /* multiple strings to be concatenated. */ \
118 ".ascii "#title" \n\t" \
119 ".byte 0 \n\t" \
120 ".popsection \n\t" \
121 ".word 10b \n\t"
122
123#define TEST_ARG_REG(reg, val) \
124 ".byte "__stringify(ARG_TYPE_REG)" \n\t" \
125 ".byte "#reg" \n\t" \
126 ".short 0 \n\t" \
127 ".word "#val" \n\t"
128
129#define TEST_ARG_PTR(reg, val) \
130 ".byte "__stringify(ARG_TYPE_PTR)" \n\t" \
131 ".byte "#reg" \n\t" \
132 ".short 0 \n\t" \
133 ".word "#val" \n\t"
134
135#define TEST_ARG_MEM(index, val) \
136 ".byte "__stringify(ARG_TYPE_MEM)" \n\t" \
137 ".byte "#index" \n\t" \
138 ".short 0 \n\t" \
139 ".word "#val" \n\t"
140
141#define TEST_ARG_END(flags) \
142 ".byte "__stringify(ARG_TYPE_END)" \n\t" \
143 ".byte "TEST_ISA flags" \n\t" \
144 ".short 50f-0f \n\t" \
145 ".short 2f-0f \n\t" \
146 ".short 99f-0f \n\t" \
147 ".code "TEST_ISA" \n\t" \
148 "0: \n\t"
149
150#define TEST_INSTRUCTION(instruction) \
151 "50: nop \n\t" \
152 "1: "instruction" \n\t" \
153 " nop \n\t"
154
155#define TEST_BRANCH_F(instruction) \
156 TEST_INSTRUCTION(instruction) \
157 " b 99f \n\t" \
158 "2: nop \n\t"
159
160#define TEST_BRANCH_B(instruction) \
161 " b 50f \n\t" \
162 " b 99f \n\t" \
163 "2: nop \n\t" \
164 " b 99f \n\t" \
165 TEST_INSTRUCTION(instruction)
166
167#define TEST_BRANCH_FX(instruction, codex) \
168 TEST_INSTRUCTION(instruction) \
169 " b 99f \n\t" \
170 codex" \n\t" \
171 " b 99f \n\t" \
172 "2: nop \n\t"
173
174#define TEST_BRANCH_BX(instruction, codex) \
175 " b 50f \n\t" \
176 " b 99f \n\t" \
177 "2: nop \n\t" \
178 " b 99f \n\t" \
179 codex" \n\t" \
180 TEST_INSTRUCTION(instruction)
181
182#define TESTCASE_END \
183 "2: \n\t" \
184 "99: \n\t" \
185 " bl __kprobes_test_case_end_"TEST_ISA" \n\t" \
186 ".code "NORMAL_ISA" \n\t" \
187 : : \
188 : "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc" \
189 );
190
191
192/*
193 * Macros to define test cases.
194 *
195 * Those of the form TEST_{R,P,M}* can be used to define test cases
196 * which take combinations of the three basic types of arguments. E.g.
197 *
198 * TEST_R One register argument
199 * TEST_RR Two register arguments
200 * TEST_RPR A register, a pointer, then a register argument
201 *
202 * For testing instructions which may branch, there are macros TEST_BF_*
203 * and TEST_BB_* for branching forwards and backwards.
204 *
205 * TEST_SUPPORTED and TEST_UNSUPPORTED don't cause the code to be executed,
206 * the just verify that a kprobe is or is not allowed on the given instruction.
207 */
208
209#define TEST(code) \
210 TESTCASE_START(code) \
211 TEST_ARG_END("") \
212 TEST_INSTRUCTION(code) \
213 TESTCASE_END
214
215#define TEST_UNSUPPORTED(code) \
216 TESTCASE_START(code) \
217 TEST_ARG_END("|"__stringify(ARG_FLAG_UNSUPPORTED)) \
218 TEST_INSTRUCTION(code) \
219 TESTCASE_END
220
221#define TEST_SUPPORTED(code) \
222 TESTCASE_START(code) \
223 TEST_ARG_END("|"__stringify(ARG_FLAG_SUPPORTED)) \
224 TEST_INSTRUCTION(code) \
225 TESTCASE_END
226
227#define TEST_R(code1, reg, val, code2) \
228 TESTCASE_START(code1 #reg code2) \
229 TEST_ARG_REG(reg, val) \
230 TEST_ARG_END("") \
231 TEST_INSTRUCTION(code1 #reg code2) \
232 TESTCASE_END
233
234#define TEST_RR(code1, reg1, val1, code2, reg2, val2, code3) \
235 TESTCASE_START(code1 #reg1 code2 #reg2 code3) \
236 TEST_ARG_REG(reg1, val1) \
237 TEST_ARG_REG(reg2, val2) \
238 TEST_ARG_END("") \
239 TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \
240 TESTCASE_END
241
242#define TEST_RRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
243 TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
244 TEST_ARG_REG(reg1, val1) \
245 TEST_ARG_REG(reg2, val2) \
246 TEST_ARG_REG(reg3, val3) \
247 TEST_ARG_END("") \
248 TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
249 TESTCASE_END
250
251#define TEST_RRRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4, reg4, val4) \
252 TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4) \
253 TEST_ARG_REG(reg1, val1) \
254 TEST_ARG_REG(reg2, val2) \
255 TEST_ARG_REG(reg3, val3) \
256 TEST_ARG_REG(reg4, val4) \
257 TEST_ARG_END("") \
258 TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4) \
259 TESTCASE_END
260
261#define TEST_P(code1, reg1, val1, code2) \
262 TESTCASE_START(code1 #reg1 code2) \
263 TEST_ARG_PTR(reg1, val1) \
264 TEST_ARG_END("") \
265 TEST_INSTRUCTION(code1 #reg1 code2) \
266 TESTCASE_END
267
268#define TEST_PR(code1, reg1, val1, code2, reg2, val2, code3) \
269 TESTCASE_START(code1 #reg1 code2 #reg2 code3) \
270 TEST_ARG_PTR(reg1, val1) \
271 TEST_ARG_REG(reg2, val2) \
272 TEST_ARG_END("") \
273 TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \
274 TESTCASE_END
275
276#define TEST_RP(code1, reg1, val1, code2, reg2, val2, code3) \
277 TESTCASE_START(code1 #reg1 code2 #reg2 code3) \
278 TEST_ARG_REG(reg1, val1) \
279 TEST_ARG_PTR(reg2, val2) \
280 TEST_ARG_END("") \
281 TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \
282 TESTCASE_END
283
284#define TEST_PRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
285 TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
286 TEST_ARG_PTR(reg1, val1) \
287 TEST_ARG_REG(reg2, val2) \
288 TEST_ARG_REG(reg3, val3) \
289 TEST_ARG_END("") \
290 TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
291 TESTCASE_END
292
293#define TEST_RPR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
294 TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
295 TEST_ARG_REG(reg1, val1) \
296 TEST_ARG_PTR(reg2, val2) \
297 TEST_ARG_REG(reg3, val3) \
298 TEST_ARG_END("") \
299 TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
300 TESTCASE_END
301
302#define TEST_RRP(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
303 TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
304 TEST_ARG_REG(reg1, val1) \
305 TEST_ARG_REG(reg2, val2) \
306 TEST_ARG_PTR(reg3, val3) \
307 TEST_ARG_END("") \
308 TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
309 TESTCASE_END
310
311#define TEST_BF_P(code1, reg1, val1, code2) \
312 TESTCASE_START(code1 #reg1 code2) \
313 TEST_ARG_PTR(reg1, val1) \
314 TEST_ARG_END("") \
315 TEST_BRANCH_F(code1 #reg1 code2) \
316 TESTCASE_END
317
318#define TEST_BF(code) \
319 TESTCASE_START(code) \
320 TEST_ARG_END("") \
321 TEST_BRANCH_F(code) \
322 TESTCASE_END
323
324#define TEST_BB(code) \
325 TESTCASE_START(code) \
326 TEST_ARG_END("") \
327 TEST_BRANCH_B(code) \
328 TESTCASE_END
329
330#define TEST_BF_R(code1, reg, val, code2) \
331 TESTCASE_START(code1 #reg code2) \
332 TEST_ARG_REG(reg, val) \
333 TEST_ARG_END("") \
334 TEST_BRANCH_F(code1 #reg code2) \
335 TESTCASE_END
336
337#define TEST_BB_R(code1, reg, val, code2) \
338 TESTCASE_START(code1 #reg code2) \
339 TEST_ARG_REG(reg, val) \
340 TEST_ARG_END("") \
341 TEST_BRANCH_B(code1 #reg code2) \
342 TESTCASE_END
343
344#define TEST_BF_RR(code1, reg1, val1, code2, reg2, val2, code3) \
345 TESTCASE_START(code1 #reg1 code2 #reg2 code3) \
346 TEST_ARG_REG(reg1, val1) \
347 TEST_ARG_REG(reg2, val2) \
348 TEST_ARG_END("") \
349 TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3) \
350 TESTCASE_END
351
352#define TEST_BF_X(code, codex) \
353 TESTCASE_START(code) \
354 TEST_ARG_END("") \
355 TEST_BRANCH_FX(code, codex) \
356 TESTCASE_END
357
358#define TEST_BB_X(code, codex) \
359 TESTCASE_START(code) \
360 TEST_ARG_END("") \
361 TEST_BRANCH_BX(code, codex) \
362 TESTCASE_END
363
364#define TEST_BF_RX(code1, reg, val, code2, codex) \
365 TESTCASE_START(code1 #reg code2) \
366 TEST_ARG_REG(reg, val) \
367 TEST_ARG_END("") \
368 TEST_BRANCH_FX(code1 #reg code2, codex) \
369 TESTCASE_END
370
371#define TEST_X(code, codex) \
372 TESTCASE_START(code) \
373 TEST_ARG_END("") \
374 TEST_INSTRUCTION(code) \
375 " b 99f \n\t" \
376 " "codex" \n\t" \
377 TESTCASE_END
378
379#define TEST_RX(code1, reg, val, code2, codex) \
380 TESTCASE_START(code1 #reg code2) \
381 TEST_ARG_REG(reg, val) \
382 TEST_ARG_END("") \
383 TEST_INSTRUCTION(code1 __stringify(reg) code2) \
384 " b 99f \n\t" \
385 " "codex" \n\t" \
386 TESTCASE_END
387
388#define TEST_RRX(code1, reg1, val1, code2, reg2, val2, code3, codex) \
389 TESTCASE_START(code1 #reg1 code2 #reg2 code3) \
390 TEST_ARG_REG(reg1, val1) \
391 TEST_ARG_REG(reg2, val2) \
392 TEST_ARG_END("") \
393 TEST_INSTRUCTION(code1 __stringify(reg1) code2 __stringify(reg2) code3) \
394 " b 99f \n\t" \
395 " "codex" \n\t" \
396 TESTCASE_END
397
398
399/*
400 * Macros for defining space directives spread over multiple lines.
401 * These are required so the compiler guesses better the length of inline asm
402 * code and will spill the literal pool early enough to avoid generating PC
403 * relative loads with out of range offsets.
404 */
405#define TWICE(x) x x
406#define SPACE_0x8 TWICE(".space 4\n\t")
407#define SPACE_0x10 TWICE(SPACE_0x8)
408#define SPACE_0x20 TWICE(SPACE_0x10)
409#define SPACE_0x40 TWICE(SPACE_0x20)
410#define SPACE_0x80 TWICE(SPACE_0x40)
411#define SPACE_0x100 TWICE(SPACE_0x80)
412#define SPACE_0x200 TWICE(SPACE_0x100)
413#define SPACE_0x400 TWICE(SPACE_0x200)
414#define SPACE_0x800 TWICE(SPACE_0x400)
415#define SPACE_0x1000 TWICE(SPACE_0x800)
416
417
418/* Various values used in test cases... */
419#define N(val) (val ^ 0xffffffff)
420#define VAL1 0x12345678
421#define VAL2 N(VAL1)
422#define VAL3 0xa5f801
423#define VAL4 N(VAL3)
424#define VALM 0x456789ab
425#define VALR 0xdeaddead
426#define HH1 0x0123fecb
427#define HH2 0xa9874567
428
429
430#ifdef CONFIG_THUMB2_KERNEL
431void kprobe_thumb16_test_cases(void);
432void kprobe_thumb32_test_cases(void);
433#else
434void kprobe_arm_test_cases(void);
435#endif
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
deleted file mode 100644
index 9495d7f3516f..000000000000
--- a/arch/arm/kernel/kprobes-thumb.c
+++ /dev/null
@@ -1,666 +0,0 @@
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/* t32 thumb actions */
24
25static void __kprobes
26t32_simulate_table_branch(probes_opcode_t insn,
27 struct arch_probes_insn *asi, struct pt_regs *regs)
28{
29 unsigned long pc = regs->ARM_pc;
30 int rn = (insn >> 16) & 0xf;
31 int rm = insn & 0xf;
32
33 unsigned long rnv = (rn == 15) ? pc : regs->uregs[rn];
34 unsigned long rmv = regs->uregs[rm];
35 unsigned int halfwords;
36
37 if (insn & 0x10) /* TBH */
38 halfwords = ((u16 *)rnv)[rmv];
39 else /* TBB */
40 halfwords = ((u8 *)rnv)[rmv];
41
42 regs->ARM_pc = pc + 2 * halfwords;
43}
44
45static void __kprobes
46t32_simulate_mrs(probes_opcode_t insn,
47 struct arch_probes_insn *asi, struct pt_regs *regs)
48{
49 int rd = (insn >> 8) & 0xf;
50 unsigned long mask = 0xf8ff03df; /* Mask out execution state */
51 regs->uregs[rd] = regs->ARM_cpsr & mask;
52}
53
54static void __kprobes
55t32_simulate_cond_branch(probes_opcode_t insn,
56 struct arch_probes_insn *asi, struct pt_regs *regs)
57{
58 unsigned long pc = regs->ARM_pc;
59
60 long offset = insn & 0x7ff; /* imm11 */
61 offset += (insn & 0x003f0000) >> 5; /* imm6 */
62 offset += (insn & 0x00002000) << 4; /* J1 */
63 offset += (insn & 0x00000800) << 7; /* J2 */
64 offset -= (insn & 0x04000000) >> 7; /* Apply sign bit */
65
66 regs->ARM_pc = pc + (offset * 2);
67}
68
69static enum probes_insn __kprobes
70t32_decode_cond_branch(probes_opcode_t insn, struct arch_probes_insn *asi,
71 const struct decode_header *d)
72{
73 int cc = (insn >> 22) & 0xf;
74 asi->insn_check_cc = probes_condition_checks[cc];
75 asi->insn_handler = t32_simulate_cond_branch;
76 return INSN_GOOD_NO_SLOT;
77}
78
79static void __kprobes
80t32_simulate_branch(probes_opcode_t insn,
81 struct arch_probes_insn *asi, struct pt_regs *regs)
82{
83 unsigned long pc = regs->ARM_pc;
84
85 long offset = insn & 0x7ff; /* imm11 */
86 offset += (insn & 0x03ff0000) >> 5; /* imm10 */
87 offset += (insn & 0x00002000) << 9; /* J1 */
88 offset += (insn & 0x00000800) << 10; /* J2 */
89 if (insn & 0x04000000)
90 offset -= 0x00800000; /* Apply sign bit */
91 else
92 offset ^= 0x00600000; /* Invert J1 and J2 */
93
94 if (insn & (1 << 14)) {
95 /* BL or BLX */
96 regs->ARM_lr = regs->ARM_pc | 1;
97 if (!(insn & (1 << 12))) {
98 /* BLX so switch to ARM mode */
99 regs->ARM_cpsr &= ~PSR_T_BIT;
100 pc &= ~3;
101 }
102 }
103
104 regs->ARM_pc = pc + (offset * 2);
105}
106
107static void __kprobes
108t32_simulate_ldr_literal(probes_opcode_t insn,
109 struct arch_probes_insn *asi, struct pt_regs *regs)
110{
111 unsigned long addr = regs->ARM_pc & ~3;
112 int rt = (insn >> 12) & 0xf;
113 unsigned long rtv;
114
115 long offset = insn & 0xfff;
116 if (insn & 0x00800000)
117 addr += offset;
118 else
119 addr -= offset;
120
121 if (insn & 0x00400000) {
122 /* LDR */
123 rtv = *(unsigned long *)addr;
124 if (rt == 15) {
125 bx_write_pc(rtv, regs);
126 return;
127 }
128 } else if (insn & 0x00200000) {
129 /* LDRH */
130 if (insn & 0x01000000)
131 rtv = *(s16 *)addr;
132 else
133 rtv = *(u16 *)addr;
134 } else {
135 /* LDRB */
136 if (insn & 0x01000000)
137 rtv = *(s8 *)addr;
138 else
139 rtv = *(u8 *)addr;
140 }
141
142 regs->uregs[rt] = rtv;
143}
144
145static enum probes_insn __kprobes
146t32_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi,
147 const struct decode_header *d)
148{
149 enum probes_insn ret = kprobe_decode_ldmstm(insn, asi, d);
150
151 /* Fixup modified instruction to have halfwords in correct order...*/
152 insn = __mem_to_opcode_arm(asi->insn[0]);
153 ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn >> 16);
154 ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0xffff);
155
156 return ret;
157}
158
159static void __kprobes
160t32_emulate_ldrdstrd(probes_opcode_t insn,
161 struct arch_probes_insn *asi, struct pt_regs *regs)
162{
163 unsigned long pc = regs->ARM_pc & ~3;
164 int rt1 = (insn >> 12) & 0xf;
165 int rt2 = (insn >> 8) & 0xf;
166 int rn = (insn >> 16) & 0xf;
167
168 register unsigned long rt1v asm("r0") = regs->uregs[rt1];
169 register unsigned long rt2v asm("r1") = regs->uregs[rt2];
170 register unsigned long rnv asm("r2") = (rn == 15) ? pc
171 : regs->uregs[rn];
172
173 __asm__ __volatile__ (
174 "blx %[fn]"
175 : "=r" (rt1v), "=r" (rt2v), "=r" (rnv)
176 : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (asi->insn_fn)
177 : "lr", "memory", "cc"
178 );
179
180 if (rn != 15)
181 regs->uregs[rn] = rnv; /* Writeback base register */
182 regs->uregs[rt1] = rt1v;
183 regs->uregs[rt2] = rt2v;
184}
185
186static void __kprobes
187t32_emulate_ldrstr(probes_opcode_t insn,
188 struct arch_probes_insn *asi, struct pt_regs *regs)
189{
190 int rt = (insn >> 12) & 0xf;
191 int rn = (insn >> 16) & 0xf;
192 int rm = insn & 0xf;
193
194 register unsigned long rtv asm("r0") = regs->uregs[rt];
195 register unsigned long rnv asm("r2") = regs->uregs[rn];
196 register unsigned long rmv asm("r3") = regs->uregs[rm];
197
198 __asm__ __volatile__ (
199 "blx %[fn]"
200 : "=r" (rtv), "=r" (rnv)
201 : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
202 : "lr", "memory", "cc"
203 );
204
205 regs->uregs[rn] = rnv; /* Writeback base register */
206 if (rt == 15) /* Can't be true for a STR as they aren't allowed */
207 bx_write_pc(rtv, regs);
208 else
209 regs->uregs[rt] = rtv;
210}
211
212static void __kprobes
213t32_emulate_rd8rn16rm0_rwflags(probes_opcode_t insn,
214 struct arch_probes_insn *asi, struct pt_regs *regs)
215{
216 int rd = (insn >> 8) & 0xf;
217 int rn = (insn >> 16) & 0xf;
218 int rm = insn & 0xf;
219
220 register unsigned long rdv asm("r1") = regs->uregs[rd];
221 register unsigned long rnv asm("r2") = regs->uregs[rn];
222 register unsigned long rmv asm("r3") = regs->uregs[rm];
223 unsigned long cpsr = regs->ARM_cpsr;
224
225 __asm__ __volatile__ (
226 "msr cpsr_fs, %[cpsr] \n\t"
227 "blx %[fn] \n\t"
228 "mrs %[cpsr], cpsr \n\t"
229 : "=r" (rdv), [cpsr] "=r" (cpsr)
230 : "0" (rdv), "r" (rnv), "r" (rmv),
231 "1" (cpsr), [fn] "r" (asi->insn_fn)
232 : "lr", "memory", "cc"
233 );
234
235 regs->uregs[rd] = rdv;
236 regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
237}
238
239static void __kprobes
240t32_emulate_rd8pc16_noflags(probes_opcode_t insn,
241 struct arch_probes_insn *asi, struct pt_regs *regs)
242{
243 unsigned long pc = regs->ARM_pc;
244 int rd = (insn >> 8) & 0xf;
245
246 register unsigned long rdv asm("r1") = regs->uregs[rd];
247 register unsigned long rnv asm("r2") = pc & ~3;
248
249 __asm__ __volatile__ (
250 "blx %[fn]"
251 : "=r" (rdv)
252 : "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn)
253 : "lr", "memory", "cc"
254 );
255
256 regs->uregs[rd] = rdv;
257}
258
259static void __kprobes
260t32_emulate_rd8rn16_noflags(probes_opcode_t insn,
261 struct arch_probes_insn *asi, struct pt_regs *regs)
262{
263 int rd = (insn >> 8) & 0xf;
264 int rn = (insn >> 16) & 0xf;
265
266 register unsigned long rdv asm("r1") = regs->uregs[rd];
267 register unsigned long rnv asm("r2") = regs->uregs[rn];
268
269 __asm__ __volatile__ (
270 "blx %[fn]"
271 : "=r" (rdv)
272 : "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn)
273 : "lr", "memory", "cc"
274 );
275
276 regs->uregs[rd] = rdv;
277}
278
279static void __kprobes
280t32_emulate_rdlo12rdhi8rn16rm0_noflags(probes_opcode_t insn,
281 struct arch_probes_insn *asi,
282 struct pt_regs *regs)
283{
284 int rdlo = (insn >> 12) & 0xf;
285 int rdhi = (insn >> 8) & 0xf;
286 int rn = (insn >> 16) & 0xf;
287 int rm = insn & 0xf;
288
289 register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
290 register unsigned long rdhiv asm("r1") = regs->uregs[rdhi];
291 register unsigned long rnv asm("r2") = regs->uregs[rn];
292 register unsigned long rmv asm("r3") = regs->uregs[rm];
293
294 __asm__ __volatile__ (
295 "blx %[fn]"
296 : "=r" (rdlov), "=r" (rdhiv)
297 : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
298 [fn] "r" (asi->insn_fn)
299 : "lr", "memory", "cc"
300 );
301
302 regs->uregs[rdlo] = rdlov;
303 regs->uregs[rdhi] = rdhiv;
304}
305/* t16 thumb actions */
306
307static void __kprobes
308t16_simulate_bxblx(probes_opcode_t insn,
309 struct arch_probes_insn *asi, struct pt_regs *regs)
310{
311 unsigned long pc = regs->ARM_pc + 2;
312 int rm = (insn >> 3) & 0xf;
313 unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm];
314
315 if (insn & (1 << 7)) /* BLX ? */
316 regs->ARM_lr = regs->ARM_pc | 1;
317
318 bx_write_pc(rmv, regs);
319}
320
321static void __kprobes
322t16_simulate_ldr_literal(probes_opcode_t insn,
323 struct arch_probes_insn *asi, struct pt_regs *regs)
324{
325 unsigned long *base = (unsigned long *)((regs->ARM_pc + 2) & ~3);
326 long index = insn & 0xff;
327 int rt = (insn >> 8) & 0x7;
328 regs->uregs[rt] = base[index];
329}
330
331static void __kprobes
332t16_simulate_ldrstr_sp_relative(probes_opcode_t insn,
333 struct arch_probes_insn *asi, struct pt_regs *regs)
334{
335 unsigned long* base = (unsigned long *)regs->ARM_sp;
336 long index = insn & 0xff;
337 int rt = (insn >> 8) & 0x7;
338 if (insn & 0x800) /* LDR */
339 regs->uregs[rt] = base[index];
340 else /* STR */
341 base[index] = regs->uregs[rt];
342}
343
344static void __kprobes
345t16_simulate_reladr(probes_opcode_t insn,
346 struct arch_probes_insn *asi, struct pt_regs *regs)
347{
348 unsigned long base = (insn & 0x800) ? regs->ARM_sp
349 : ((regs->ARM_pc + 2) & ~3);
350 long offset = insn & 0xff;
351 int rt = (insn >> 8) & 0x7;
352 regs->uregs[rt] = base + offset * 4;
353}
354
355static void __kprobes
356t16_simulate_add_sp_imm(probes_opcode_t insn,
357 struct arch_probes_insn *asi, struct pt_regs *regs)
358{
359 long imm = insn & 0x7f;
360 if (insn & 0x80) /* SUB */
361 regs->ARM_sp -= imm * 4;
362 else /* ADD */
363 regs->ARM_sp += imm * 4;
364}
365
366static void __kprobes
367t16_simulate_cbz(probes_opcode_t insn,
368 struct arch_probes_insn *asi, struct pt_regs *regs)
369{
370 int rn = insn & 0x7;
371 probes_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn;
372 if (nonzero & 0x800) {
373 long i = insn & 0x200;
374 long imm5 = insn & 0xf8;
375 unsigned long pc = regs->ARM_pc + 2;
376 regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2);
377 }
378}
379
380static void __kprobes
381t16_simulate_it(probes_opcode_t insn,
382 struct arch_probes_insn *asi, struct pt_regs *regs)
383{
384 /*
385 * The 8 IT state bits are split into two parts in CPSR:
386 * ITSTATE<1:0> are in CPSR<26:25>
387 * ITSTATE<7:2> are in CPSR<15:10>
388 * The new IT state is in the lower byte of insn.
389 */
390 unsigned long cpsr = regs->ARM_cpsr;
391 cpsr &= ~PSR_IT_MASK;
392 cpsr |= (insn & 0xfc) << 8;
393 cpsr |= (insn & 0x03) << 25;
394 regs->ARM_cpsr = cpsr;
395}
396
397static void __kprobes
398t16_singlestep_it(probes_opcode_t insn,
399 struct arch_probes_insn *asi, struct pt_regs *regs)
400{
401 regs->ARM_pc += 2;
402 t16_simulate_it(insn, asi, regs);
403}
404
405static enum probes_insn __kprobes
406t16_decode_it(probes_opcode_t insn, struct arch_probes_insn *asi,
407 const struct decode_header *d)
408{
409 asi->insn_singlestep = t16_singlestep_it;
410 return INSN_GOOD_NO_SLOT;
411}
412
413static void __kprobes
414t16_simulate_cond_branch(probes_opcode_t insn,
415 struct arch_probes_insn *asi, struct pt_regs *regs)
416{
417 unsigned long pc = regs->ARM_pc + 2;
418 long offset = insn & 0x7f;
419 offset -= insn & 0x80; /* Apply sign bit */
420 regs->ARM_pc = pc + (offset * 2);
421}
422
423static enum probes_insn __kprobes
424t16_decode_cond_branch(probes_opcode_t insn, struct arch_probes_insn *asi,
425 const struct decode_header *d)
426{
427 int cc = (insn >> 8) & 0xf;
428 asi->insn_check_cc = probes_condition_checks[cc];
429 asi->insn_handler = t16_simulate_cond_branch;
430 return INSN_GOOD_NO_SLOT;
431}
432
433static void __kprobes
434t16_simulate_branch(probes_opcode_t insn,
435 struct arch_probes_insn *asi, struct pt_regs *regs)
436{
437 unsigned long pc = regs->ARM_pc + 2;
438 long offset = insn & 0x3ff;
439 offset -= insn & 0x400; /* Apply sign bit */
440 regs->ARM_pc = pc + (offset * 2);
441}
442
443static unsigned long __kprobes
444t16_emulate_loregs(probes_opcode_t insn,
445 struct arch_probes_insn *asi, struct pt_regs *regs)
446{
447 unsigned long oldcpsr = regs->ARM_cpsr;
448 unsigned long newcpsr;
449
450 __asm__ __volatile__ (
451 "msr cpsr_fs, %[oldcpsr] \n\t"
452 "ldmia %[regs], {r0-r7} \n\t"
453 "blx %[fn] \n\t"
454 "stmia %[regs], {r0-r7} \n\t"
455 "mrs %[newcpsr], cpsr \n\t"
456 : [newcpsr] "=r" (newcpsr)
457 : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs),
458 [fn] "r" (asi->insn_fn)
459 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
460 "lr", "memory", "cc"
461 );
462
463 return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK);
464}
465
466static void __kprobes
467t16_emulate_loregs_rwflags(probes_opcode_t insn,
468 struct arch_probes_insn *asi, struct pt_regs *regs)
469{
470 regs->ARM_cpsr = t16_emulate_loregs(insn, asi, regs);
471}
472
473static void __kprobes
474t16_emulate_loregs_noitrwflags(probes_opcode_t insn,
475 struct arch_probes_insn *asi, struct pt_regs *regs)
476{
477 unsigned long cpsr = t16_emulate_loregs(insn, asi, regs);
478 if (!in_it_block(cpsr))
479 regs->ARM_cpsr = cpsr;
480}
481
482static void __kprobes
483t16_emulate_hiregs(probes_opcode_t insn,
484 struct arch_probes_insn *asi, struct pt_regs *regs)
485{
486 unsigned long pc = regs->ARM_pc + 2;
487 int rdn = (insn & 0x7) | ((insn & 0x80) >> 4);
488 int rm = (insn >> 3) & 0xf;
489
490 register unsigned long rdnv asm("r1");
491 register unsigned long rmv asm("r0");
492 unsigned long cpsr = regs->ARM_cpsr;
493
494 rdnv = (rdn == 15) ? pc : regs->uregs[rdn];
495 rmv = (rm == 15) ? pc : regs->uregs[rm];
496
497 __asm__ __volatile__ (
498 "msr cpsr_fs, %[cpsr] \n\t"
499 "blx %[fn] \n\t"
500 "mrs %[cpsr], cpsr \n\t"
501 : "=r" (rdnv), [cpsr] "=r" (cpsr)
502 : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (asi->insn_fn)
503 : "lr", "memory", "cc"
504 );
505
506 if (rdn == 15)
507 rdnv &= ~1;
508
509 regs->uregs[rdn] = rdnv;
510 regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
511}
512
513static enum probes_insn __kprobes
514t16_decode_hiregs(probes_opcode_t insn, struct arch_probes_insn *asi,
515 const struct decode_header *d)
516{
517 insn &= ~0x00ff;
518 insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */
519 ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn);
520 asi->insn_handler = t16_emulate_hiregs;
521 return INSN_GOOD;
522}
523
524static void __kprobes
525t16_emulate_push(probes_opcode_t insn,
526 struct arch_probes_insn *asi, struct pt_regs *regs)
527{
528 __asm__ __volatile__ (
529 "ldr r9, [%[regs], #13*4] \n\t"
530 "ldr r8, [%[regs], #14*4] \n\t"
531 "ldmia %[regs], {r0-r7} \n\t"
532 "blx %[fn] \n\t"
533 "str r9, [%[regs], #13*4] \n\t"
534 :
535 : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
536 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
537 "lr", "memory", "cc"
538 );
539}
540
541static enum probes_insn __kprobes
542t16_decode_push(probes_opcode_t insn, struct arch_probes_insn *asi,
543 const struct decode_header *d)
544{
545 /*
546 * To simulate a PUSH we use a Thumb-2 "STMDB R9!, {registers}"
547 * and call it with R9=SP and LR in the register list represented
548 * by R8.
549 */
550 /* 1st half STMDB R9!,{} */
551 ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe929);
552 /* 2nd half (register list) */
553 ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff);
554 asi->insn_handler = t16_emulate_push;
555 return INSN_GOOD;
556}
557
558static void __kprobes
559t16_emulate_pop_nopc(probes_opcode_t insn,
560 struct arch_probes_insn *asi, struct pt_regs *regs)
561{
562 __asm__ __volatile__ (
563 "ldr r9, [%[regs], #13*4] \n\t"
564 "ldmia %[regs], {r0-r7} \n\t"
565 "blx %[fn] \n\t"
566 "stmia %[regs], {r0-r7} \n\t"
567 "str r9, [%[regs], #13*4] \n\t"
568 :
569 : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
570 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
571 "lr", "memory", "cc"
572 );
573}
574
575static void __kprobes
576t16_emulate_pop_pc(probes_opcode_t insn,
577 struct arch_probes_insn *asi, struct pt_regs *regs)
578{
579 register unsigned long pc asm("r8");
580
581 __asm__ __volatile__ (
582 "ldr r9, [%[regs], #13*4] \n\t"
583 "ldmia %[regs], {r0-r7} \n\t"
584 "blx %[fn] \n\t"
585 "stmia %[regs], {r0-r7} \n\t"
586 "str r9, [%[regs], #13*4] \n\t"
587 : "=r" (pc)
588 : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
589 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
590 "lr", "memory", "cc"
591 );
592
593 bx_write_pc(pc, regs);
594}
595
596static enum probes_insn __kprobes
597t16_decode_pop(probes_opcode_t insn, struct arch_probes_insn *asi,
598 const struct decode_header *d)
599{
600 /*
601 * To simulate a POP we use a Thumb-2 "LDMDB R9!, {registers}"
602 * and call it with R9=SP and PC in the register list represented
603 * by R8.
604 */
605 /* 1st half LDMIA R9!,{} */
606 ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe8b9);
607 /* 2nd half (register list) */
608 ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff);
609 asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc
610 : t16_emulate_pop_nopc;
611 return INSN_GOOD;
612}
613
614const union decode_action kprobes_t16_actions[NUM_PROBES_T16_ACTIONS] = {
615 [PROBES_T16_ADD_SP] = {.handler = t16_simulate_add_sp_imm},
616 [PROBES_T16_CBZ] = {.handler = t16_simulate_cbz},
617 [PROBES_T16_SIGN_EXTEND] = {.handler = t16_emulate_loregs_rwflags},
618 [PROBES_T16_PUSH] = {.decoder = t16_decode_push},
619 [PROBES_T16_POP] = {.decoder = t16_decode_pop},
620 [PROBES_T16_SEV] = {.handler = probes_emulate_none},
621 [PROBES_T16_WFE] = {.handler = probes_simulate_nop},
622 [PROBES_T16_IT] = {.decoder = t16_decode_it},
623 [PROBES_T16_CMP] = {.handler = t16_emulate_loregs_rwflags},
624 [PROBES_T16_ADDSUB] = {.handler = t16_emulate_loregs_noitrwflags},
625 [PROBES_T16_LOGICAL] = {.handler = t16_emulate_loregs_noitrwflags},
626 [PROBES_T16_LDR_LIT] = {.handler = t16_simulate_ldr_literal},
627 [PROBES_T16_BLX] = {.handler = t16_simulate_bxblx},
628 [PROBES_T16_HIREGOPS] = {.decoder = t16_decode_hiregs},
629 [PROBES_T16_LDRHSTRH] = {.handler = t16_emulate_loregs_rwflags},
630 [PROBES_T16_LDRSTR] = {.handler = t16_simulate_ldrstr_sp_relative},
631 [PROBES_T16_ADR] = {.handler = t16_simulate_reladr},
632 [PROBES_T16_LDMSTM] = {.handler = t16_emulate_loregs_rwflags},
633 [PROBES_T16_BRANCH_COND] = {.decoder = t16_decode_cond_branch},
634 [PROBES_T16_BRANCH] = {.handler = t16_simulate_branch},
635};
636
637const union decode_action kprobes_t32_actions[NUM_PROBES_T32_ACTIONS] = {
638 [PROBES_T32_LDMSTM] = {.decoder = t32_decode_ldmstm},
639 [PROBES_T32_LDRDSTRD] = {.handler = t32_emulate_ldrdstrd},
640 [PROBES_T32_TABLE_BRANCH] = {.handler = t32_simulate_table_branch},
641 [PROBES_T32_TST] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
642 [PROBES_T32_MOV] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
643 [PROBES_T32_ADDSUB] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
644 [PROBES_T32_LOGICAL] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
645 [PROBES_T32_CMP] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
646 [PROBES_T32_ADDWSUBW_PC] = {.handler = t32_emulate_rd8pc16_noflags,},
647 [PROBES_T32_ADDWSUBW] = {.handler = t32_emulate_rd8rn16_noflags},
648 [PROBES_T32_MOVW] = {.handler = t32_emulate_rd8rn16_noflags},
649 [PROBES_T32_SAT] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
650 [PROBES_T32_BITFIELD] = {.handler = t32_emulate_rd8rn16_noflags},
651 [PROBES_T32_SEV] = {.handler = probes_emulate_none},
652 [PROBES_T32_WFE] = {.handler = probes_simulate_nop},
653 [PROBES_T32_MRS] = {.handler = t32_simulate_mrs},
654 [PROBES_T32_BRANCH_COND] = {.decoder = t32_decode_cond_branch},
655 [PROBES_T32_BRANCH] = {.handler = t32_simulate_branch},
656 [PROBES_T32_PLDI] = {.handler = probes_simulate_nop},
657 [PROBES_T32_LDR_LIT] = {.handler = t32_simulate_ldr_literal},
658 [PROBES_T32_LDRSTR] = {.handler = t32_emulate_ldrstr},
659 [PROBES_T32_SIGN_EXTEND] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
660 [PROBES_T32_MEDIA] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
661 [PROBES_T32_REVERSE] = {.handler = t32_emulate_rd8rn16_noflags},
662 [PROBES_T32_MUL_ADD] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
663 [PROBES_T32_MUL_ADD2] = {.handler = t32_emulate_rd8rn16rm0ra12_noflags},
664 [PROBES_T32_MUL_ADD_LONG] = {
665 .handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags},
666};
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
deleted file mode 100644
index 6d644202c8dc..000000000000
--- a/arch/arm/kernel/kprobes.c
+++ /dev/null
@@ -1,628 +0,0 @@
1/*
2 * arch/arm/kernel/kprobes.c
3 *
4 * Kprobes on ARM
5 *
6 * Abhishek Sagar <sagar.abhishek@gmail.com>
7 * Copyright (C) 2006, 2007 Motorola Inc.
8 *
9 * Nicolas Pitre <nico@marvell.com>
10 * Copyright (C) 2007 Marvell Ltd.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 */
21
22#include <linux/kernel.h>
23#include <linux/kprobes.h>
24#include <linux/module.h>
25#include <linux/slab.h>
26#include <linux/stop_machine.h>
27#include <linux/stringify.h>
28#include <asm/traps.h>
29#include <asm/opcodes.h>
30#include <asm/cacheflush.h>
31#include <linux/percpu.h>
32#include <linux/bug.h>
33
34#include "kprobes.h"
35#include "probes-arm.h"
36#include "probes-thumb.h"
37#include "patch.h"
38
39#define MIN_STACK_SIZE(addr) \
40 min((unsigned long)MAX_STACK_SIZE, \
41 (unsigned long)current_thread_info() + THREAD_START_SP - (addr))
42
43#define flush_insns(addr, size) \
44 flush_icache_range((unsigned long)(addr), \
45 (unsigned long)(addr) + \
46 (size))
47
48/* Used as a marker in ARM_pc to note when we're in a jprobe. */
49#define JPROBE_MAGIC_ADDR 0xffffffff
50
51DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
52DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
53
54
55int __kprobes arch_prepare_kprobe(struct kprobe *p)
56{
57 kprobe_opcode_t insn;
58 kprobe_opcode_t tmp_insn[MAX_INSN_SIZE];
59 unsigned long addr = (unsigned long)p->addr;
60 bool thumb;
61 kprobe_decode_insn_t *decode_insn;
62 const union decode_action *actions;
63 int is;
64
65 if (in_exception_text(addr))
66 return -EINVAL;
67
68#ifdef CONFIG_THUMB2_KERNEL
69 thumb = true;
70 addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */
71 insn = __mem_to_opcode_thumb16(((u16 *)addr)[0]);
72 if (is_wide_instruction(insn)) {
73 u16 inst2 = __mem_to_opcode_thumb16(((u16 *)addr)[1]);
74 insn = __opcode_thumb32_compose(insn, inst2);
75 decode_insn = thumb32_probes_decode_insn;
76 actions = kprobes_t32_actions;
77 } else {
78 decode_insn = thumb16_probes_decode_insn;
79 actions = kprobes_t16_actions;
80 }
81#else /* !CONFIG_THUMB2_KERNEL */
82 thumb = false;
83 if (addr & 0x3)
84 return -EINVAL;
85 insn = __mem_to_opcode_arm(*p->addr);
86 decode_insn = arm_probes_decode_insn;
87 actions = kprobes_arm_actions;
88#endif
89
90 p->opcode = insn;
91 p->ainsn.insn = tmp_insn;
92
93 switch ((*decode_insn)(insn, &p->ainsn, true, actions)) {
94 case INSN_REJECTED: /* not supported */
95 return -EINVAL;
96
97 case INSN_GOOD: /* instruction uses slot */
98 p->ainsn.insn = get_insn_slot();
99 if (!p->ainsn.insn)
100 return -ENOMEM;
101 for (is = 0; is < MAX_INSN_SIZE; ++is)
102 p->ainsn.insn[is] = tmp_insn[is];
103 flush_insns(p->ainsn.insn,
104 sizeof(p->ainsn.insn[0]) * MAX_INSN_SIZE);
105 p->ainsn.insn_fn = (probes_insn_fn_t *)
106 ((uintptr_t)p->ainsn.insn | thumb);
107 break;
108
109 case INSN_GOOD_NO_SLOT: /* instruction doesn't need insn slot */
110 p->ainsn.insn = NULL;
111 break;
112 }
113
114 return 0;
115}
116
117void __kprobes arch_arm_kprobe(struct kprobe *p)
118{
119 unsigned int brkp;
120 void *addr;
121
122 if (IS_ENABLED(CONFIG_THUMB2_KERNEL)) {
123 /* Remove any Thumb flag */
124 addr = (void *)((uintptr_t)p->addr & ~1);
125
126 if (is_wide_instruction(p->opcode))
127 brkp = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION;
128 else
129 brkp = KPROBE_THUMB16_BREAKPOINT_INSTRUCTION;
130 } else {
131 kprobe_opcode_t insn = p->opcode;
132
133 addr = p->addr;
134 brkp = KPROBE_ARM_BREAKPOINT_INSTRUCTION;
135
136 if (insn >= 0xe0000000)
137 brkp |= 0xe0000000; /* Unconditional instruction */
138 else
139 brkp |= insn & 0xf0000000; /* Copy condition from insn */
140 }
141
142 patch_text(addr, brkp);
143}
144
145/*
146 * The actual disarming is done here on each CPU and synchronized using
147 * stop_machine. This synchronization is necessary on SMP to avoid removing
148 * a probe between the moment the 'Undefined Instruction' exception is raised
149 * and the moment the exception handler reads the faulting instruction from
150 * memory. It is also needed to atomically set the two half-words of a 32-bit
151 * Thumb breakpoint.
152 */
153int __kprobes __arch_disarm_kprobe(void *p)
154{
155 struct kprobe *kp = p;
156 void *addr = (void *)((uintptr_t)kp->addr & ~1);
157
158 __patch_text(addr, kp->opcode);
159
160 return 0;
161}
162
163void __kprobes arch_disarm_kprobe(struct kprobe *p)
164{
165 stop_machine(__arch_disarm_kprobe, p, cpu_online_mask);
166}
167
168void __kprobes arch_remove_kprobe(struct kprobe *p)
169{
170 if (p->ainsn.insn) {
171 free_insn_slot(p->ainsn.insn, 0);
172 p->ainsn.insn = NULL;
173 }
174}
175
176static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
177{
178 kcb->prev_kprobe.kp = kprobe_running();
179 kcb->prev_kprobe.status = kcb->kprobe_status;
180}
181
182static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
183{
184 __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
185 kcb->kprobe_status = kcb->prev_kprobe.status;
186}
187
188static void __kprobes set_current_kprobe(struct kprobe *p)
189{
190 __this_cpu_write(current_kprobe, p);
191}
192
193static void __kprobes
194singlestep_skip(struct kprobe *p, struct pt_regs *regs)
195{
196#ifdef CONFIG_THUMB2_KERNEL
197 regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
198 if (is_wide_instruction(p->opcode))
199 regs->ARM_pc += 4;
200 else
201 regs->ARM_pc += 2;
202#else
203 regs->ARM_pc += 4;
204#endif
205}
206
207static inline void __kprobes
208singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
209{
210 p->ainsn.insn_singlestep(p->opcode, &p->ainsn, regs);
211}
212
213/*
214 * Called with IRQs disabled. IRQs must remain disabled from that point
215 * all the way until processing this kprobe is complete. The current
216 * kprobes implementation cannot process more than one nested level of
217 * kprobe, and that level is reserved for user kprobe handlers, so we can't
218 * risk encountering a new kprobe in an interrupt handler.
219 */
220void __kprobes kprobe_handler(struct pt_regs *regs)
221{
222 struct kprobe *p, *cur;
223 struct kprobe_ctlblk *kcb;
224
225 kcb = get_kprobe_ctlblk();
226 cur = kprobe_running();
227
228#ifdef CONFIG_THUMB2_KERNEL
229 /*
230 * First look for a probe which was registered using an address with
231 * bit 0 set, this is the usual situation for pointers to Thumb code.
232 * If not found, fallback to looking for one with bit 0 clear.
233 */
234 p = get_kprobe((kprobe_opcode_t *)(regs->ARM_pc | 1));
235 if (!p)
236 p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc);
237
238#else /* ! CONFIG_THUMB2_KERNEL */
239 p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc);
240#endif
241
242 if (p) {
243 if (cur) {
244 /* Kprobe is pending, so we're recursing. */
245 switch (kcb->kprobe_status) {
246 case KPROBE_HIT_ACTIVE:
247 case KPROBE_HIT_SSDONE:
248 /* A pre- or post-handler probe got us here. */
249 kprobes_inc_nmissed_count(p);
250 save_previous_kprobe(kcb);
251 set_current_kprobe(p);
252 kcb->kprobe_status = KPROBE_REENTER;
253 singlestep(p, regs, kcb);
254 restore_previous_kprobe(kcb);
255 break;
256 default:
257 /* impossible cases */
258 BUG();
259 }
260 } else if (p->ainsn.insn_check_cc(regs->ARM_cpsr)) {
261 /* Probe hit and conditional execution check ok. */
262 set_current_kprobe(p);
263 kcb->kprobe_status = KPROBE_HIT_ACTIVE;
264
265 /*
266 * If we have no pre-handler or it returned 0, we
267 * continue with normal processing. If we have a
268 * pre-handler and it returned non-zero, it prepped
269 * for calling the break_handler below on re-entry,
270 * so get out doing nothing more here.
271 */
272 if (!p->pre_handler || !p->pre_handler(p, regs)) {
273 kcb->kprobe_status = KPROBE_HIT_SS;
274 singlestep(p, regs, kcb);
275 if (p->post_handler) {
276 kcb->kprobe_status = KPROBE_HIT_SSDONE;
277 p->post_handler(p, regs, 0);
278 }
279 reset_current_kprobe();
280 }
281 } else {
282 /*
283 * Probe hit but conditional execution check failed,
284 * so just skip the instruction and continue as if
285 * nothing had happened.
286 */
287 singlestep_skip(p, regs);
288 }
289 } else if (cur) {
290 /* We probably hit a jprobe. Call its break handler. */
291 if (cur->break_handler && cur->break_handler(cur, regs)) {
292 kcb->kprobe_status = KPROBE_HIT_SS;
293 singlestep(cur, regs, kcb);
294 if (cur->post_handler) {
295 kcb->kprobe_status = KPROBE_HIT_SSDONE;
296 cur->post_handler(cur, regs, 0);
297 }
298 }
299 reset_current_kprobe();
300 } else {
301 /*
302 * The probe was removed and a race is in progress.
303 * There is nothing we can do about it. Let's restart
304 * the instruction. By the time we can restart, the
305 * real instruction will be there.
306 */
307 }
308}
309
310static int __kprobes kprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
311{
312 unsigned long flags;
313 local_irq_save(flags);
314 kprobe_handler(regs);
315 local_irq_restore(flags);
316 return 0;
317}
318
319int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
320{
321 struct kprobe *cur = kprobe_running();
322 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
323
324 switch (kcb->kprobe_status) {
325 case KPROBE_HIT_SS:
326 case KPROBE_REENTER:
327 /*
328 * We are here because the instruction being single
329 * stepped caused a page fault. We reset the current
330 * kprobe and the PC to point back to the probe address
331 * and allow the page fault handler to continue as a
332 * normal page fault.
333 */
334 regs->ARM_pc = (long)cur->addr;
335 if (kcb->kprobe_status == KPROBE_REENTER) {
336 restore_previous_kprobe(kcb);
337 } else {
338 reset_current_kprobe();
339 }
340 break;
341
342 case KPROBE_HIT_ACTIVE:
343 case KPROBE_HIT_SSDONE:
344 /*
345 * We increment the nmissed count for accounting,
346 * we can also use npre/npostfault count for accounting
347 * these specific fault cases.
348 */
349 kprobes_inc_nmissed_count(cur);
350
351 /*
352 * We come here because instructions in the pre/post
353 * handler caused the page_fault, this could happen
354 * if handler tries to access user space by
355 * copy_from_user(), get_user() etc. Let the
356 * user-specified handler try to fix it.
357 */
358 if (cur->fault_handler && cur->fault_handler(cur, regs, fsr))
359 return 1;
360 break;
361
362 default:
363 break;
364 }
365
366 return 0;
367}
368
369int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
370 unsigned long val, void *data)
371{
372 /*
373 * notify_die() is currently never called on ARM,
374 * so this callback is currently empty.
375 */
376 return NOTIFY_DONE;
377}
378
379/*
380 * When a retprobed function returns, trampoline_handler() is called,
381 * calling the kretprobe's handler. We construct a struct pt_regs to
382 * give a view of registers r0-r11 to the user return-handler. This is
383 * not a complete pt_regs structure, but that should be plenty sufficient
384 * for kretprobe handlers which should normally be interested in r0 only
385 * anyway.
386 */
387void __naked __kprobes kretprobe_trampoline(void)
388{
389 __asm__ __volatile__ (
390 "stmdb sp!, {r0 - r11} \n\t"
391 "mov r0, sp \n\t"
392 "bl trampoline_handler \n\t"
393 "mov lr, r0 \n\t"
394 "ldmia sp!, {r0 - r11} \n\t"
395#ifdef CONFIG_THUMB2_KERNEL
396 "bx lr \n\t"
397#else
398 "mov pc, lr \n\t"
399#endif
400 : : : "memory");
401}
402
403/* Called from kretprobe_trampoline */
404static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
405{
406 struct kretprobe_instance *ri = NULL;
407 struct hlist_head *head, empty_rp;
408 struct hlist_node *tmp;
409 unsigned long flags, orig_ret_address = 0;
410 unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
411
412 INIT_HLIST_HEAD(&empty_rp);
413 kretprobe_hash_lock(current, &head, &flags);
414
415 /*
416 * It is possible to have multiple instances associated with a given
417 * task either because multiple functions in the call path have
418 * a return probe installed on them, and/or more than one return
419 * probe was registered for a target function.
420 *
421 * We can handle this because:
422 * - instances are always inserted at the head of the list
423 * - when multiple return probes are registered for the same
424 * function, the first instance's ret_addr will point to the
425 * real return address, and all the rest will point to
426 * kretprobe_trampoline
427 */
428 hlist_for_each_entry_safe(ri, tmp, head, hlist) {
429 if (ri->task != current)
430 /* another task is sharing our hash bucket */
431 continue;
432
433 if (ri->rp && ri->rp->handler) {
434 __this_cpu_write(current_kprobe, &ri->rp->kp);
435 get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE;
436 ri->rp->handler(ri, regs);
437 __this_cpu_write(current_kprobe, NULL);
438 }
439
440 orig_ret_address = (unsigned long)ri->ret_addr;
441 recycle_rp_inst(ri, &empty_rp);
442
443 if (orig_ret_address != trampoline_address)
444 /*
445 * This is the real return address. Any other
446 * instances associated with this task are for
447 * other calls deeper on the call stack
448 */
449 break;
450 }
451
452 kretprobe_assert(ri, orig_ret_address, trampoline_address);
453 kretprobe_hash_unlock(current, &flags);
454
455 hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
456 hlist_del(&ri->hlist);
457 kfree(ri);
458 }
459
460 return (void *)orig_ret_address;
461}
462
463void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
464 struct pt_regs *regs)
465{
466 ri->ret_addr = (kprobe_opcode_t *)regs->ARM_lr;
467
468 /* Replace the return addr with trampoline addr. */
469 regs->ARM_lr = (unsigned long)&kretprobe_trampoline;
470}
471
472int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
473{
474 struct jprobe *jp = container_of(p, struct jprobe, kp);
475 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
476 long sp_addr = regs->ARM_sp;
477 long cpsr;
478
479 kcb->jprobe_saved_regs = *regs;
480 memcpy(kcb->jprobes_stack, (void *)sp_addr, MIN_STACK_SIZE(sp_addr));
481 regs->ARM_pc = (long)jp->entry;
482
483 cpsr = regs->ARM_cpsr | PSR_I_BIT;
484#ifdef CONFIG_THUMB2_KERNEL
485 /* Set correct Thumb state in cpsr */
486 if (regs->ARM_pc & 1)
487 cpsr |= PSR_T_BIT;
488 else
489 cpsr &= ~PSR_T_BIT;
490#endif
491 regs->ARM_cpsr = cpsr;
492
493 preempt_disable();
494 return 1;
495}
496
497void __kprobes jprobe_return(void)
498{
499 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
500
501 __asm__ __volatile__ (
502 /*
503 * Setup an empty pt_regs. Fill SP and PC fields as
504 * they're needed by longjmp_break_handler.
505 *
506 * We allocate some slack between the original SP and start of
507 * our fabricated regs. To be precise we want to have worst case
508 * covered which is STMFD with all 16 regs so we allocate 2 *
509 * sizeof(struct_pt_regs)).
510 *
511 * This is to prevent any simulated instruction from writing
512 * over the regs when they are accessing the stack.
513 */
514#ifdef CONFIG_THUMB2_KERNEL
515 "sub r0, %0, %1 \n\t"
516 "mov sp, r0 \n\t"
517#else
518 "sub sp, %0, %1 \n\t"
519#endif
520 "ldr r0, ="__stringify(JPROBE_MAGIC_ADDR)"\n\t"
521 "str %0, [sp, %2] \n\t"
522 "str r0, [sp, %3] \n\t"
523 "mov r0, sp \n\t"
524 "bl kprobe_handler \n\t"
525
526 /*
527 * Return to the context saved by setjmp_pre_handler
528 * and restored by longjmp_break_handler.
529 */
530#ifdef CONFIG_THUMB2_KERNEL
531 "ldr lr, [sp, %2] \n\t" /* lr = saved sp */
532 "ldrd r0, r1, [sp, %5] \n\t" /* r0,r1 = saved lr,pc */
533 "ldr r2, [sp, %4] \n\t" /* r2 = saved psr */
534 "stmdb lr!, {r0, r1, r2} \n\t" /* push saved lr and */
535 /* rfe context */
536 "ldmia sp, {r0 - r12} \n\t"
537 "mov sp, lr \n\t"
538 "ldr lr, [sp], #4 \n\t"
539 "rfeia sp! \n\t"
540#else
541 "ldr r0, [sp, %4] \n\t"
542 "msr cpsr_cxsf, r0 \n\t"
543 "ldmia sp, {r0 - pc} \n\t"
544#endif
545 :
546 : "r" (kcb->jprobe_saved_regs.ARM_sp),
547 "I" (sizeof(struct pt_regs) * 2),
548 "J" (offsetof(struct pt_regs, ARM_sp)),
549 "J" (offsetof(struct pt_regs, ARM_pc)),
550 "J" (offsetof(struct pt_regs, ARM_cpsr)),
551 "J" (offsetof(struct pt_regs, ARM_lr))
552 : "memory", "cc");
553}
554
555int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
556{
557 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
558 long stack_addr = kcb->jprobe_saved_regs.ARM_sp;
559 long orig_sp = regs->ARM_sp;
560 struct jprobe *jp = container_of(p, struct jprobe, kp);
561
562 if (regs->ARM_pc == JPROBE_MAGIC_ADDR) {
563 if (orig_sp != stack_addr) {
564 struct pt_regs *saved_regs =
565 (struct pt_regs *)kcb->jprobe_saved_regs.ARM_sp;
566 printk("current sp %lx does not match saved sp %lx\n",
567 orig_sp, stack_addr);
568 printk("Saved registers for jprobe %p\n", jp);
569 show_regs(saved_regs);
570 printk("Current registers\n");
571 show_regs(regs);
572 BUG();
573 }
574 *regs = kcb->jprobe_saved_regs;
575 memcpy((void *)stack_addr, kcb->jprobes_stack,
576 MIN_STACK_SIZE(stack_addr));
577 preempt_enable_no_resched();
578 return 1;
579 }
580 return 0;
581}
582
583int __kprobes arch_trampoline_kprobe(struct kprobe *p)
584{
585 return 0;
586}
587
588#ifdef CONFIG_THUMB2_KERNEL
589
590static struct undef_hook kprobes_thumb16_break_hook = {
591 .instr_mask = 0xffff,
592 .instr_val = KPROBE_THUMB16_BREAKPOINT_INSTRUCTION,
593 .cpsr_mask = MODE_MASK,
594 .cpsr_val = SVC_MODE,
595 .fn = kprobe_trap_handler,
596};
597
598static struct undef_hook kprobes_thumb32_break_hook = {
599 .instr_mask = 0xffffffff,
600 .instr_val = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION,
601 .cpsr_mask = MODE_MASK,
602 .cpsr_val = SVC_MODE,
603 .fn = kprobe_trap_handler,
604};
605
606#else /* !CONFIG_THUMB2_KERNEL */
607
608static struct undef_hook kprobes_arm_break_hook = {
609 .instr_mask = 0x0fffffff,
610 .instr_val = KPROBE_ARM_BREAKPOINT_INSTRUCTION,
611 .cpsr_mask = MODE_MASK,
612 .cpsr_val = SVC_MODE,
613 .fn = kprobe_trap_handler,
614};
615
616#endif /* !CONFIG_THUMB2_KERNEL */
617
618int __init arch_init_kprobes()
619{
620 arm_probes_decode_init();
621#ifdef CONFIG_THUMB2_KERNEL
622 register_undef_hook(&kprobes_thumb16_break_hook);
623 register_undef_hook(&kprobes_thumb32_break_hook);
624#else
625 register_undef_hook(&kprobes_arm_break_hook);
626#endif
627 return 0;
628}
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
deleted file mode 100644
index 9a2712ecefc3..000000000000
--- a/arch/arm/kernel/kprobes.h
+++ /dev/null
@@ -1,52 +0,0 @@
1/*
2 * arch/arm/kernel/kprobes.h
3 *
4 * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
5 *
6 * Some contents moved here from arch/arm/include/asm/kprobes.h which is
7 * Copyright (C) 2006, 2007 Motorola Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 */
18
19#ifndef _ARM_KERNEL_KPROBES_H
20#define _ARM_KERNEL_KPROBES_H
21
22#include "probes.h"
23
24/*
25 * These undefined instructions must be unique and
26 * reserved solely for kprobes' use.
27 */
28#define KPROBE_ARM_BREAKPOINT_INSTRUCTION 0x07f001f8
29#define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION 0xde18
30#define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION 0xf7f0a018
31
32enum probes_insn __kprobes
33kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_probes_insn *asi,
34 const struct decode_header *h);
35
36typedef enum probes_insn (kprobe_decode_insn_t)(probes_opcode_t,
37 struct arch_probes_insn *,
38 bool,
39 const union decode_action *);
40
41#ifdef CONFIG_THUMB2_KERNEL
42
43extern const union decode_action kprobes_t32_actions[];
44extern const union decode_action kprobes_t16_actions[];
45
46#else /* !CONFIG_THUMB2_KERNEL */
47
48extern const union decode_action kprobes_arm_actions[];
49
50#endif
51
52#endif /* _ARM_KERNEL_KPROBES_H */
diff --git a/arch/arm/kernel/patch.c b/arch/arm/kernel/patch.c
index 5038960e3c55..69bda1a5707e 100644
--- a/arch/arm/kernel/patch.c
+++ b/arch/arm/kernel/patch.c
@@ -8,8 +8,7 @@
8#include <asm/fixmap.h> 8#include <asm/fixmap.h>
9#include <asm/smp_plat.h> 9#include <asm/smp_plat.h>
10#include <asm/opcodes.h> 10#include <asm/opcodes.h>
11 11#include <asm/patch.h>
12#include "patch.h"
13 12
14struct patch { 13struct patch {
15 void *addr; 14 void *addr;
diff --git a/arch/arm/kernel/patch.h b/arch/arm/kernel/patch.h
deleted file mode 100644
index 77e054c2f6cd..000000000000
--- a/arch/arm/kernel/patch.h
+++ /dev/null
@@ -1,17 +0,0 @@
1#ifndef _ARM_KERNEL_PATCH_H
2#define _ARM_KERNEL_PATCH_H
3
4void patch_text(void *addr, unsigned int insn);
5void __patch_text_real(void *addr, unsigned int insn, bool remap);
6
7static inline void __patch_text(void *addr, unsigned int insn)
8{
9 __patch_text_real(addr, insn, true);
10}
11
12static inline void __patch_text_early(void *addr, unsigned int insn)
13{
14 __patch_text_real(addr, insn, false);
15}
16
17#endif
diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c
deleted file mode 100644
index 8eaef81d8344..000000000000
--- a/arch/arm/kernel/probes-arm.c
+++ /dev/null
@@ -1,734 +0,0 @@
1/*
2 * arch/arm/kernel/probes-arm.c
3 *
4 * Some code moved here from arch/arm/kernel/kprobes-arm.c
5 *
6 * Copyright (C) 2006, 2007 Motorola Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 */
17
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/stddef.h>
21#include <linux/ptrace.h>
22
23#include "probes.h"
24#include "probes-arm.h"
25
26#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
27
28#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
29
30/*
31 * To avoid the complications of mimicing single-stepping on a
32 * processor without a Next-PC or a single-step mode, and to
33 * avoid having to deal with the side-effects of boosting, we
34 * simulate or emulate (almost) all ARM instructions.
35 *
36 * "Simulation" is where the instruction's behavior is duplicated in
37 * C code. "Emulation" is where the original instruction is rewritten
38 * and executed, often by altering its registers.
39 *
40 * By having all behavior of the kprobe'd instruction completed before
41 * returning from the kprobe_handler(), all locks (scheduler and
42 * interrupt) can safely be released. There is no need for secondary
43 * breakpoints, no race with MP or preemptable kernels, nor having to
44 * clean up resources counts at a later time impacting overall system
45 * performance. By rewriting the instruction, only the minimum registers
46 * need to be loaded and saved back optimizing performance.
47 *
48 * Calling the insnslot_*_rwflags version of a function doesn't hurt
49 * anything even when the CPSR flags aren't updated by the
50 * instruction. It's just a little slower in return for saving
51 * a little space by not having a duplicate function that doesn't
52 * update the flags. (The same optimization can be said for
53 * instructions that do or don't perform register writeback)
54 * Also, instructions can either read the flags, only write the
55 * flags, or read and write the flags. To save combinations
56 * rather than for sheer performance, flag functions just assume
57 * read and write of flags.
58 */
59
60void __kprobes simulate_bbl(probes_opcode_t insn,
61 struct arch_probes_insn *asi, struct pt_regs *regs)
62{
63 long iaddr = (long) regs->ARM_pc - 4;
64 int disp = branch_displacement(insn);
65
66 if (insn & (1 << 24))
67 regs->ARM_lr = iaddr + 4;
68
69 regs->ARM_pc = iaddr + 8 + disp;
70}
71
72void __kprobes simulate_blx1(probes_opcode_t insn,
73 struct arch_probes_insn *asi, struct pt_regs *regs)
74{
75 long iaddr = (long) regs->ARM_pc - 4;
76 int disp = branch_displacement(insn);
77
78 regs->ARM_lr = iaddr + 4;
79 regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2);
80 regs->ARM_cpsr |= PSR_T_BIT;
81}
82
83void __kprobes simulate_blx2bx(probes_opcode_t insn,
84 struct arch_probes_insn *asi, struct pt_regs *regs)
85{
86 int rm = insn & 0xf;
87 long rmv = regs->uregs[rm];
88
89 if (insn & (1 << 5))
90 regs->ARM_lr = (long) regs->ARM_pc;
91
92 regs->ARM_pc = rmv & ~0x1;
93 regs->ARM_cpsr &= ~PSR_T_BIT;
94 if (rmv & 0x1)
95 regs->ARM_cpsr |= PSR_T_BIT;
96}
97
98void __kprobes simulate_mrs(probes_opcode_t insn,
99 struct arch_probes_insn *asi, struct pt_regs *regs)
100{
101 int rd = (insn >> 12) & 0xf;
102 unsigned long mask = 0xf8ff03df; /* Mask out execution state */
103 regs->uregs[rd] = regs->ARM_cpsr & mask;
104}
105
106void __kprobes simulate_mov_ipsp(probes_opcode_t insn,
107 struct arch_probes_insn *asi, struct pt_regs *regs)
108{
109 regs->uregs[12] = regs->uregs[13];
110}
111
112/*
113 * For the instruction masking and comparisons in all the "space_*"
114 * functions below, Do _not_ rearrange the order of tests unless
115 * you're very, very sure of what you are doing. For the sake of
116 * efficiency, the masks for some tests sometimes assume other test
117 * have been done prior to them so the number of patterns to test
118 * for an instruction set can be as broad as possible to reduce the
119 * number of tests needed.
120 */
121
122static const union decode_item arm_1111_table[] = {
123 /* Unconditional instructions */
124
125 /* memory hint 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx */
126 /* PLDI (immediate) 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx */
127 /* PLDW (immediate) 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx */
128 /* PLD (immediate) 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx */
129 DECODE_SIMULATE (0xfe300000, 0xf4100000, PROBES_PRELOAD_IMM),
130
131 /* memory hint 1111 0110 x001 xxxx xxxx xxxx xxx0 xxxx */
132 /* PLDI (register) 1111 0110 x101 xxxx xxxx xxxx xxx0 xxxx */
133 /* PLDW (register) 1111 0111 x001 xxxx xxxx xxxx xxx0 xxxx */
134 /* PLD (register) 1111 0111 x101 xxxx xxxx xxxx xxx0 xxxx */
135 DECODE_SIMULATE (0xfe300010, 0xf6100000, PROBES_PRELOAD_REG),
136
137 /* BLX (immediate) 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx */
138 DECODE_SIMULATE (0xfe000000, 0xfa000000, PROBES_BRANCH_IMM),
139
140 /* CPS 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */
141 /* SETEND 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
142 /* SRS 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
143 /* RFE 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
144
145 /* Coprocessor instructions... */
146 /* MCRR2 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx */
147 /* MRRC2 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx */
148 /* LDC2 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
149 /* STC2 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
150 /* CDP2 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
151 /* MCR2 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
152 /* MRC2 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
153
154 /* Other unallocated instructions... */
155 DECODE_END
156};
157
158static const union decode_item arm_cccc_0001_0xx0____0xxx_table[] = {
159 /* Miscellaneous instructions */
160
161 /* MRS cpsr cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
162 DECODE_SIMULATEX(0x0ff000f0, 0x01000000, PROBES_MRS,
163 REGS(0, NOPC, 0, 0, 0)),
164
165 /* BX cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
166 DECODE_SIMULATE (0x0ff000f0, 0x01200010, PROBES_BRANCH_REG),
167
168 /* BLX (register) cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
169 DECODE_SIMULATEX(0x0ff000f0, 0x01200030, PROBES_BRANCH_REG,
170 REGS(0, 0, 0, 0, NOPC)),
171
172 /* CLZ cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
173 DECODE_EMULATEX (0x0ff000f0, 0x01600010, PROBES_CLZ,
174 REGS(0, NOPC, 0, 0, NOPC)),
175
176 /* QADD cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx */
177 /* QSUB cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx */
178 /* QDADD cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx */
179 /* QDSUB cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx */
180 DECODE_EMULATEX (0x0f9000f0, 0x01000050, PROBES_SATURATING_ARITHMETIC,
181 REGS(NOPC, NOPC, 0, 0, NOPC)),
182
183 /* BXJ cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
184 /* MSR cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
185 /* MRS spsr cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */
186 /* BKPT 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
187 /* SMC cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */
188 /* And unallocated instructions... */
189 DECODE_END
190};
191
192static const union decode_item arm_cccc_0001_0xx0____1xx0_table[] = {
193 /* Halfword multiply and multiply-accumulate */
194
195 /* SMLALxy cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
196 DECODE_EMULATEX (0x0ff00090, 0x01400080, PROBES_MUL1,
197 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
198
199 /* SMULWy cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
200 DECODE_OR (0x0ff000b0, 0x012000a0),
201 /* SMULxy cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
202 DECODE_EMULATEX (0x0ff00090, 0x01600080, PROBES_MUL2,
203 REGS(NOPC, 0, NOPC, 0, NOPC)),
204
205 /* SMLAxy cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx */
206 DECODE_OR (0x0ff00090, 0x01000080),
207 /* SMLAWy cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx */
208 DECODE_EMULATEX (0x0ff000b0, 0x01200080, PROBES_MUL2,
209 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
210
211 DECODE_END
212};
213
214static const union decode_item arm_cccc_0000_____1001_table[] = {
215 /* Multiply and multiply-accumulate */
216
217 /* MUL cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx */
218 /* MULS cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx */
219 DECODE_EMULATEX (0x0fe000f0, 0x00000090, PROBES_MUL2,
220 REGS(NOPC, 0, NOPC, 0, NOPC)),
221
222 /* MLA cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx */
223 /* MLAS cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx */
224 DECODE_OR (0x0fe000f0, 0x00200090),
225 /* MLS cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx */
226 DECODE_EMULATEX (0x0ff000f0, 0x00600090, PROBES_MUL2,
227 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
228
229 /* UMAAL cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx */
230 DECODE_OR (0x0ff000f0, 0x00400090),
231 /* UMULL cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx */
232 /* UMULLS cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx */
233 /* UMLAL cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx */
234 /* UMLALS cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx */
235 /* SMULL cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx */
236 /* SMULLS cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx */
237 /* SMLAL cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx */
238 /* SMLALS cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx */
239 DECODE_EMULATEX (0x0f8000f0, 0x00800090, PROBES_MUL1,
240 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
241
242 DECODE_END
243};
244
245static const union decode_item arm_cccc_0001_____1001_table[] = {
246 /* Synchronization primitives */
247
248#if __LINUX_ARM_ARCH__ < 6
249 /* Deprecated on ARMv6 and may be UNDEFINED on v7 */
250 /* SMP/SWPB cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */
251 DECODE_EMULATEX (0x0fb000f0, 0x01000090, PROBES_SWP,
252 REGS(NOPC, NOPC, 0, 0, NOPC)),
253#endif
254 /* LDREX/STREX{,D,B,H} cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */
255 /* And unallocated instructions... */
256 DECODE_END
257};
258
259static const union decode_item arm_cccc_000x_____1xx1_table[] = {
260 /* Extra load/store instructions */
261
262 /* STRHT cccc 0000 xx10 xxxx xxxx xxxx 1011 xxxx */
263 /* ??? cccc 0000 xx10 xxxx xxxx xxxx 11x1 xxxx */
264 /* LDRHT cccc 0000 xx11 xxxx xxxx xxxx 1011 xxxx */
265 /* LDRSBT cccc 0000 xx11 xxxx xxxx xxxx 1101 xxxx */
266 /* LDRSHT cccc 0000 xx11 xxxx xxxx xxxx 1111 xxxx */
267 DECODE_REJECT (0x0f200090, 0x00200090),
268
269 /* LDRD/STRD lr,pc,{... cccc 000x x0x0 xxxx 111x xxxx 1101 xxxx */
270 DECODE_REJECT (0x0e10e0d0, 0x0000e0d0),
271
272 /* LDRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1101 xxxx */
273 /* STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx */
274 DECODE_EMULATEX (0x0e5000d0, 0x000000d0, PROBES_LDRSTRD,
275 REGS(NOPCWB, NOPCX, 0, 0, NOPC)),
276
277 /* LDRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1101 xxxx */
278 /* STRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1111 xxxx */
279 DECODE_EMULATEX (0x0e5000d0, 0x004000d0, PROBES_LDRSTRD,
280 REGS(NOPCWB, NOPCX, 0, 0, 0)),
281
282 /* STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */
283 DECODE_EMULATEX (0x0e5000f0, 0x000000b0, PROBES_STORE_EXTRA,
284 REGS(NOPCWB, NOPC, 0, 0, NOPC)),
285
286 /* LDRH (register) cccc 000x x0x1 xxxx xxxx xxxx 1011 xxxx */
287 /* LDRSB (register) cccc 000x x0x1 xxxx xxxx xxxx 1101 xxxx */
288 /* LDRSH (register) cccc 000x x0x1 xxxx xxxx xxxx 1111 xxxx */
289 DECODE_EMULATEX (0x0e500090, 0x00100090, PROBES_LOAD_EXTRA,
290 REGS(NOPCWB, NOPC, 0, 0, NOPC)),
291
292 /* STRH (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */
293 DECODE_EMULATEX (0x0e5000f0, 0x004000b0, PROBES_STORE_EXTRA,
294 REGS(NOPCWB, NOPC, 0, 0, 0)),
295
296 /* LDRH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1011 xxxx */
297 /* LDRSB (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1101 xxxx */
298 /* LDRSH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1111 xxxx */
299 DECODE_EMULATEX (0x0e500090, 0x00500090, PROBES_LOAD_EXTRA,
300 REGS(NOPCWB, NOPC, 0, 0, 0)),
301
302 DECODE_END
303};
304
305static const union decode_item arm_cccc_000x_table[] = {
306 /* Data-processing (register) */
307
308 /* <op>S PC, ... cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx */
309 DECODE_REJECT (0x0e10f000, 0x0010f000),
310
311 /* MOV IP, SP 1110 0001 1010 0000 1100 0000 0000 1101 */
312 DECODE_SIMULATE (0xffffffff, 0xe1a0c00d, PROBES_MOV_IP_SP),
313
314 /* TST (register) cccc 0001 0001 xxxx xxxx xxxx xxx0 xxxx */
315 /* TEQ (register) cccc 0001 0011 xxxx xxxx xxxx xxx0 xxxx */
316 /* CMP (register) cccc 0001 0101 xxxx xxxx xxxx xxx0 xxxx */
317 /* CMN (register) cccc 0001 0111 xxxx xxxx xxxx xxx0 xxxx */
318 DECODE_EMULATEX (0x0f900010, 0x01100000, PROBES_DATA_PROCESSING_REG,
319 REGS(ANY, 0, 0, 0, ANY)),
320
321 /* MOV (register) cccc 0001 101x xxxx xxxx xxxx xxx0 xxxx */
322 /* MVN (register) cccc 0001 111x xxxx xxxx xxxx xxx0 xxxx */
323 DECODE_EMULATEX (0x0fa00010, 0x01a00000, PROBES_DATA_PROCESSING_REG,
324 REGS(0, ANY, 0, 0, ANY)),
325
326 /* AND (register) cccc 0000 000x xxxx xxxx xxxx xxx0 xxxx */
327 /* EOR (register) cccc 0000 001x xxxx xxxx xxxx xxx0 xxxx */
328 /* SUB (register) cccc 0000 010x xxxx xxxx xxxx xxx0 xxxx */
329 /* RSB (register) cccc 0000 011x xxxx xxxx xxxx xxx0 xxxx */
330 /* ADD (register) cccc 0000 100x xxxx xxxx xxxx xxx0 xxxx */
331 /* ADC (register) cccc 0000 101x xxxx xxxx xxxx xxx0 xxxx */
332 /* SBC (register) cccc 0000 110x xxxx xxxx xxxx xxx0 xxxx */
333 /* RSC (register) cccc 0000 111x xxxx xxxx xxxx xxx0 xxxx */
334 /* ORR (register) cccc 0001 100x xxxx xxxx xxxx xxx0 xxxx */
335 /* BIC (register) cccc 0001 110x xxxx xxxx xxxx xxx0 xxxx */
336 DECODE_EMULATEX (0x0e000010, 0x00000000, PROBES_DATA_PROCESSING_REG,
337 REGS(ANY, ANY, 0, 0, ANY)),
338
339 /* TST (reg-shift reg) cccc 0001 0001 xxxx xxxx xxxx 0xx1 xxxx */
340 /* TEQ (reg-shift reg) cccc 0001 0011 xxxx xxxx xxxx 0xx1 xxxx */
341 /* CMP (reg-shift reg) cccc 0001 0101 xxxx xxxx xxxx 0xx1 xxxx */
342 /* CMN (reg-shift reg) cccc 0001 0111 xxxx xxxx xxxx 0xx1 xxxx */
343 DECODE_EMULATEX (0x0f900090, 0x01100010, PROBES_DATA_PROCESSING_REG,
344 REGS(NOPC, 0, NOPC, 0, NOPC)),
345
346 /* MOV (reg-shift reg) cccc 0001 101x xxxx xxxx xxxx 0xx1 xxxx */
347 /* MVN (reg-shift reg) cccc 0001 111x xxxx xxxx xxxx 0xx1 xxxx */
348 DECODE_EMULATEX (0x0fa00090, 0x01a00010, PROBES_DATA_PROCESSING_REG,
349 REGS(0, NOPC, NOPC, 0, NOPC)),
350
351 /* AND (reg-shift reg) cccc 0000 000x xxxx xxxx xxxx 0xx1 xxxx */
352 /* EOR (reg-shift reg) cccc 0000 001x xxxx xxxx xxxx 0xx1 xxxx */
353 /* SUB (reg-shift reg) cccc 0000 010x xxxx xxxx xxxx 0xx1 xxxx */
354 /* RSB (reg-shift reg) cccc 0000 011x xxxx xxxx xxxx 0xx1 xxxx */
355 /* ADD (reg-shift reg) cccc 0000 100x xxxx xxxx xxxx 0xx1 xxxx */
356 /* ADC (reg-shift reg) cccc 0000 101x xxxx xxxx xxxx 0xx1 xxxx */
357 /* SBC (reg-shift reg) cccc 0000 110x xxxx xxxx xxxx 0xx1 xxxx */
358 /* RSC (reg-shift reg) cccc 0000 111x xxxx xxxx xxxx 0xx1 xxxx */
359 /* ORR (reg-shift reg) cccc 0001 100x xxxx xxxx xxxx 0xx1 xxxx */
360 /* BIC (reg-shift reg) cccc 0001 110x xxxx xxxx xxxx 0xx1 xxxx */
361 DECODE_EMULATEX (0x0e000090, 0x00000010, PROBES_DATA_PROCESSING_REG,
362 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
363
364 DECODE_END
365};
366
367static const union decode_item arm_cccc_001x_table[] = {
368 /* Data-processing (immediate) */
369
370 /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */
371 /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */
372 DECODE_EMULATEX (0x0fb00000, 0x03000000, PROBES_DATA_PROCESSING_IMM,
373 REGS(0, NOPC, 0, 0, 0)),
374
375 /* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */
376 DECODE_OR (0x0fff00ff, 0x03200001),
377 /* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */
378 DECODE_EMULATE (0x0fff00ff, 0x03200004, PROBES_EMULATE_NONE),
379 /* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */
380 /* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */
381 /* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */
382 DECODE_SIMULATE (0x0fff00fc, 0x03200000, PROBES_SIMULATE_NOP),
383 /* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */
384 /* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */
385 /* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */
386 DECODE_REJECT (0x0fb00000, 0x03200000),
387
388 /* <op>S PC, ... cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx */
389 DECODE_REJECT (0x0e10f000, 0x0210f000),
390
391 /* TST (immediate) cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx */
392 /* TEQ (immediate) cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx */
393 /* CMP (immediate) cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx */
394 /* CMN (immediate) cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx */
395 DECODE_EMULATEX (0x0f900000, 0x03100000, PROBES_DATA_PROCESSING_IMM,
396 REGS(ANY, 0, 0, 0, 0)),
397
398 /* MOV (immediate) cccc 0011 101x xxxx xxxx xxxx xxxx xxxx */
399 /* MVN (immediate) cccc 0011 111x xxxx xxxx xxxx xxxx xxxx */
400 DECODE_EMULATEX (0x0fa00000, 0x03a00000, PROBES_DATA_PROCESSING_IMM,
401 REGS(0, ANY, 0, 0, 0)),
402
403 /* AND (immediate) cccc 0010 000x xxxx xxxx xxxx xxxx xxxx */
404 /* EOR (immediate) cccc 0010 001x xxxx xxxx xxxx xxxx xxxx */
405 /* SUB (immediate) cccc 0010 010x xxxx xxxx xxxx xxxx xxxx */
406 /* RSB (immediate) cccc 0010 011x xxxx xxxx xxxx xxxx xxxx */
407 /* ADD (immediate) cccc 0010 100x xxxx xxxx xxxx xxxx xxxx */
408 /* ADC (immediate) cccc 0010 101x xxxx xxxx xxxx xxxx xxxx */
409 /* SBC (immediate) cccc 0010 110x xxxx xxxx xxxx xxxx xxxx */
410 /* RSC (immediate) cccc 0010 111x xxxx xxxx xxxx xxxx xxxx */
411 /* ORR (immediate) cccc 0011 100x xxxx xxxx xxxx xxxx xxxx */
412 /* BIC (immediate) cccc 0011 110x xxxx xxxx xxxx xxxx xxxx */
413 DECODE_EMULATEX (0x0e000000, 0x02000000, PROBES_DATA_PROCESSING_IMM,
414 REGS(ANY, ANY, 0, 0, 0)),
415
416 DECODE_END
417};
418
419static const union decode_item arm_cccc_0110_____xxx1_table[] = {
420 /* Media instructions */
421
422 /* SEL cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx */
423 DECODE_EMULATEX (0x0ff000f0, 0x068000b0, PROBES_SATURATE,
424 REGS(NOPC, NOPC, 0, 0, NOPC)),
425
426 /* SSAT cccc 0110 101x xxxx xxxx xxxx xx01 xxxx */
427 /* USAT cccc 0110 111x xxxx xxxx xxxx xx01 xxxx */
428 DECODE_OR(0x0fa00030, 0x06a00010),
429 /* SSAT16 cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx */
430 /* USAT16 cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx */
431 DECODE_EMULATEX (0x0fb000f0, 0x06a00030, PROBES_SATURATE,
432 REGS(0, NOPC, 0, 0, NOPC)),
433
434 /* REV cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */
435 /* REV16 cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */
436 /* RBIT cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */
437 /* REVSH cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */
438 DECODE_EMULATEX (0x0fb00070, 0x06b00030, PROBES_REV,
439 REGS(0, NOPC, 0, 0, NOPC)),
440
441 /* ??? cccc 0110 0x00 xxxx xxxx xxxx xxx1 xxxx */
442 DECODE_REJECT (0x0fb00010, 0x06000010),
443 /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1011 xxxx */
444 DECODE_REJECT (0x0f8000f0, 0x060000b0),
445 /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1101 xxxx */
446 DECODE_REJECT (0x0f8000f0, 0x060000d0),
447 /* SADD16 cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx */
448 /* SADDSUBX cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx */
449 /* SSUBADDX cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx */
450 /* SSUB16 cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx */
451 /* SADD8 cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx */
452 /* SSUB8 cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx */
453 /* QADD16 cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx */
454 /* QADDSUBX cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx */
455 /* QSUBADDX cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx */
456 /* QSUB16 cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx */
457 /* QADD8 cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx */
458 /* QSUB8 cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx */
459 /* SHADD16 cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx */
460 /* SHADDSUBX cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx */
461 /* SHSUBADDX cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx */
462 /* SHSUB16 cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx */
463 /* SHADD8 cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx */
464 /* SHSUB8 cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx */
465 /* UADD16 cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx */
466 /* UADDSUBX cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx */
467 /* USUBADDX cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx */
468 /* USUB16 cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx */
469 /* UADD8 cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx */
470 /* USUB8 cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx */
471 /* UQADD16 cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx */
472 /* UQADDSUBX cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx */
473 /* UQSUBADDX cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx */
474 /* UQSUB16 cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx */
475 /* UQADD8 cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx */
476 /* UQSUB8 cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx */
477 /* UHADD16 cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx */
478 /* UHADDSUBX cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx */
479 /* UHSUBADDX cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx */
480 /* UHSUB16 cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx */
481 /* UHADD8 cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx */
482 /* UHSUB8 cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx */
483 DECODE_EMULATEX (0x0f800010, 0x06000010, PROBES_MMI,
484 REGS(NOPC, NOPC, 0, 0, NOPC)),
485
486 /* PKHBT cccc 0110 1000 xxxx xxxx xxxx x001 xxxx */
487 /* PKHTB cccc 0110 1000 xxxx xxxx xxxx x101 xxxx */
488 DECODE_EMULATEX (0x0ff00030, 0x06800010, PROBES_PACK,
489 REGS(NOPC, NOPC, 0, 0, NOPC)),
490
491 /* ??? cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx */
492 /* ??? cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx */
493 DECODE_REJECT (0x0fb000f0, 0x06900070),
494
495 /* SXTB16 cccc 0110 1000 1111 xxxx xxxx 0111 xxxx */
496 /* SXTB cccc 0110 1010 1111 xxxx xxxx 0111 xxxx */
497 /* SXTH cccc 0110 1011 1111 xxxx xxxx 0111 xxxx */
498 /* UXTB16 cccc 0110 1100 1111 xxxx xxxx 0111 xxxx */
499 /* UXTB cccc 0110 1110 1111 xxxx xxxx 0111 xxxx */
500 /* UXTH cccc 0110 1111 1111 xxxx xxxx 0111 xxxx */
501 DECODE_EMULATEX (0x0f8f00f0, 0x068f0070, PROBES_EXTEND,
502 REGS(0, NOPC, 0, 0, NOPC)),
503
504 /* SXTAB16 cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx */
505 /* SXTAB cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx */
506 /* SXTAH cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx */
507 /* UXTAB16 cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx */
508 /* UXTAB cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx */
509 /* UXTAH cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx */
510 DECODE_EMULATEX (0x0f8000f0, 0x06800070, PROBES_EXTEND_ADD,
511 REGS(NOPCX, NOPC, 0, 0, NOPC)),
512
513 DECODE_END
514};
515
516static const union decode_item arm_cccc_0111_____xxx1_table[] = {
517 /* Media instructions */
518
519 /* UNDEFINED cccc 0111 1111 xxxx xxxx xxxx 1111 xxxx */
520 DECODE_REJECT (0x0ff000f0, 0x07f000f0),
521
522 /* SMLALD cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */
523 /* SMLSLD cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */
524 DECODE_EMULATEX (0x0ff00090, 0x07400010, PROBES_MUL_ADD_LONG,
525 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
526
527 /* SMUAD cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx */
528 /* SMUSD cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx */
529 DECODE_OR (0x0ff0f090, 0x0700f010),
530 /* SMMUL cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx */
531 DECODE_OR (0x0ff0f0d0, 0x0750f010),
532 /* USAD8 cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */
533 DECODE_EMULATEX (0x0ff0f0f0, 0x0780f010, PROBES_MUL_ADD,
534 REGS(NOPC, 0, NOPC, 0, NOPC)),
535
536 /* SMLAD cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx */
537 /* SMLSD cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx */
538 DECODE_OR (0x0ff00090, 0x07000010),
539 /* SMMLA cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx */
540 DECODE_OR (0x0ff000d0, 0x07500010),
541 /* USADA8 cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */
542 DECODE_EMULATEX (0x0ff000f0, 0x07800010, PROBES_MUL_ADD,
543 REGS(NOPC, NOPCX, NOPC, 0, NOPC)),
544
545 /* SMMLS cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx */
546 DECODE_EMULATEX (0x0ff000d0, 0x075000d0, PROBES_MUL_ADD,
547 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
548
549 /* SBFX cccc 0111 101x xxxx xxxx xxxx x101 xxxx */
550 /* UBFX cccc 0111 111x xxxx xxxx xxxx x101 xxxx */
551 DECODE_EMULATEX (0x0fa00070, 0x07a00050, PROBES_BITFIELD,
552 REGS(0, NOPC, 0, 0, NOPC)),
553
554 /* BFC cccc 0111 110x xxxx xxxx xxxx x001 1111 */
555 DECODE_EMULATEX (0x0fe0007f, 0x07c0001f, PROBES_BITFIELD,
556 REGS(0, NOPC, 0, 0, 0)),
557
558 /* BFI cccc 0111 110x xxxx xxxx xxxx x001 xxxx */
559 DECODE_EMULATEX (0x0fe00070, 0x07c00010, PROBES_BITFIELD,
560 REGS(0, NOPC, 0, 0, NOPCX)),
561
562 DECODE_END
563};
564
565static const union decode_item arm_cccc_01xx_table[] = {
566 /* Load/store word and unsigned byte */
567
568 /* LDRB/STRB pc,[...] cccc 01xx x0xx xxxx xxxx xxxx xxxx xxxx */
569 DECODE_REJECT (0x0c40f000, 0x0440f000),
570
571 /* STRT cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */
572 /* LDRT cccc 01x0 x011 xxxx xxxx xxxx xxxx xxxx */
573 /* STRBT cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */
574 /* LDRBT cccc 01x0 x111 xxxx xxxx xxxx xxxx xxxx */
575 DECODE_REJECT (0x0d200000, 0x04200000),
576
577 /* STR (immediate) cccc 010x x0x0 xxxx xxxx xxxx xxxx xxxx */
578 /* STRB (immediate) cccc 010x x1x0 xxxx xxxx xxxx xxxx xxxx */
579 DECODE_EMULATEX (0x0e100000, 0x04000000, PROBES_STORE,
580 REGS(NOPCWB, ANY, 0, 0, 0)),
581
582 /* LDR (immediate) cccc 010x x0x1 xxxx xxxx xxxx xxxx xxxx */
583 /* LDRB (immediate) cccc 010x x1x1 xxxx xxxx xxxx xxxx xxxx */
584 DECODE_EMULATEX (0x0e100000, 0x04100000, PROBES_LOAD,
585 REGS(NOPCWB, ANY, 0, 0, 0)),
586
587 /* STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx */
588 /* STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx */
589 DECODE_EMULATEX (0x0e100000, 0x06000000, PROBES_STORE,
590 REGS(NOPCWB, ANY, 0, 0, NOPC)),
591
592 /* LDR (register) cccc 011x x0x1 xxxx xxxx xxxx xxxx xxxx */
593 /* LDRB (register) cccc 011x x1x1 xxxx xxxx xxxx xxxx xxxx */
594 DECODE_EMULATEX (0x0e100000, 0x06100000, PROBES_LOAD,
595 REGS(NOPCWB, ANY, 0, 0, NOPC)),
596
597 DECODE_END
598};
599
600static const union decode_item arm_cccc_100x_table[] = {
601 /* Block data transfer instructions */
602
603 /* LDM cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
604 /* STM cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
605 DECODE_CUSTOM (0x0e400000, 0x08000000, PROBES_LDMSTM),
606
607 /* STM (user registers) cccc 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
608 /* LDM (user registers) cccc 100x x1x1 xxxx 0xxx xxxx xxxx xxxx */
609 /* LDM (exception ret) cccc 100x x1x1 xxxx 1xxx xxxx xxxx xxxx */
610 DECODE_END
611};
612
613const union decode_item probes_decode_arm_table[] = {
614 /*
615 * Unconditional instructions
616 * 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx
617 */
618 DECODE_TABLE (0xf0000000, 0xf0000000, arm_1111_table),
619
620 /*
621 * Miscellaneous instructions
622 * cccc 0001 0xx0 xxxx xxxx xxxx 0xxx xxxx
623 */
624 DECODE_TABLE (0x0f900080, 0x01000000, arm_cccc_0001_0xx0____0xxx_table),
625
626 /*
627 * Halfword multiply and multiply-accumulate
628 * cccc 0001 0xx0 xxxx xxxx xxxx 1xx0 xxxx
629 */
630 DECODE_TABLE (0x0f900090, 0x01000080, arm_cccc_0001_0xx0____1xx0_table),
631
632 /*
633 * Multiply and multiply-accumulate
634 * cccc 0000 xxxx xxxx xxxx xxxx 1001 xxxx
635 */
636 DECODE_TABLE (0x0f0000f0, 0x00000090, arm_cccc_0000_____1001_table),
637
638 /*
639 * Synchronization primitives
640 * cccc 0001 xxxx xxxx xxxx xxxx 1001 xxxx
641 */
642 DECODE_TABLE (0x0f0000f0, 0x01000090, arm_cccc_0001_____1001_table),
643
644 /*
645 * Extra load/store instructions
646 * cccc 000x xxxx xxxx xxxx xxxx 1xx1 xxxx
647 */
648 DECODE_TABLE (0x0e000090, 0x00000090, arm_cccc_000x_____1xx1_table),
649
650 /*
651 * Data-processing (register)
652 * cccc 000x xxxx xxxx xxxx xxxx xxx0 xxxx
653 * Data-processing (register-shifted register)
654 * cccc 000x xxxx xxxx xxxx xxxx 0xx1 xxxx
655 */
656 DECODE_TABLE (0x0e000000, 0x00000000, arm_cccc_000x_table),
657
658 /*
659 * Data-processing (immediate)
660 * cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx
661 */
662 DECODE_TABLE (0x0e000000, 0x02000000, arm_cccc_001x_table),
663
664 /*
665 * Media instructions
666 * cccc 011x xxxx xxxx xxxx xxxx xxx1 xxxx
667 */
668 DECODE_TABLE (0x0f000010, 0x06000010, arm_cccc_0110_____xxx1_table),
669 DECODE_TABLE (0x0f000010, 0x07000010, arm_cccc_0111_____xxx1_table),
670
671 /*
672 * Load/store word and unsigned byte
673 * cccc 01xx xxxx xxxx xxxx xxxx xxxx xxxx
674 */
675 DECODE_TABLE (0x0c000000, 0x04000000, arm_cccc_01xx_table),
676
677 /*
678 * Block data transfer instructions
679 * cccc 100x xxxx xxxx xxxx xxxx xxxx xxxx
680 */
681 DECODE_TABLE (0x0e000000, 0x08000000, arm_cccc_100x_table),
682
683 /* B cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */
684 /* BL cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */
685 DECODE_SIMULATE (0x0e000000, 0x0a000000, PROBES_BRANCH),
686
687 /*
688 * Supervisor Call, and coprocessor instructions
689 */
690
691 /* MCRR cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx */
692 /* MRRC cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx */
693 /* LDC cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
694 /* STC cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
695 /* CDP cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
696 /* MCR cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
697 /* MRC cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
698 /* SVC cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
699 DECODE_REJECT (0x0c000000, 0x0c000000),
700
701 DECODE_END
702};
703#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
704EXPORT_SYMBOL_GPL(probes_decode_arm_table);
705#endif
706
707static void __kprobes arm_singlestep(probes_opcode_t insn,
708 struct arch_probes_insn *asi, struct pt_regs *regs)
709{
710 regs->ARM_pc += 4;
711 asi->insn_handler(insn, asi, regs);
712}
713
714/* Return:
715 * INSN_REJECTED If instruction is one not allowed to kprobe,
716 * INSN_GOOD If instruction is supported and uses instruction slot,
717 * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot.
718 *
719 * For instructions we don't want to kprobe (INSN_REJECTED return result):
720 * These are generally ones that modify the processor state making
721 * them "hard" to simulate such as switches processor modes or
722 * make accesses in alternate modes. Any of these could be simulated
723 * if the work was put into it, but low return considering they
724 * should also be very rare.
725 */
726enum probes_insn __kprobes
727arm_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
728 bool emulate, const union decode_action *actions)
729{
730 asi->insn_singlestep = arm_singlestep;
731 asi->insn_check_cc = probes_condition_checks[insn>>28];
732 return probes_decode_insn(insn, asi, probes_decode_arm_table, false,
733 emulate, actions);
734}
diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/kernel/probes-arm.h
deleted file mode 100644
index ace6572f6e26..000000000000
--- a/arch/arm/kernel/probes-arm.h
+++ /dev/null
@@ -1,73 +0,0 @@
1/*
2 * arch/arm/kernel/probes-arm.h
3 *
4 * Copyright 2013 Linaro Ltd.
5 * Written by: David A. Long
6 *
7 * The code contained herein is licensed under the GNU General Public
8 * License. You may obtain a copy of the GNU General Public License
9 * Version 2 or later at the following locations:
10 *
11 * http://www.opensource.org/licenses/gpl-license.html
12 * http://www.gnu.org/copyleft/gpl.html
13 */
14
15#ifndef _ARM_KERNEL_PROBES_ARM_H
16#define _ARM_KERNEL_PROBES_ARM_H
17
18enum probes_arm_action {
19 PROBES_EMULATE_NONE,
20 PROBES_SIMULATE_NOP,
21 PROBES_PRELOAD_IMM,
22 PROBES_PRELOAD_REG,
23 PROBES_BRANCH_IMM,
24 PROBES_BRANCH_REG,
25 PROBES_MRS,
26 PROBES_CLZ,
27 PROBES_SATURATING_ARITHMETIC,
28 PROBES_MUL1,
29 PROBES_MUL2,
30 PROBES_SWP,
31 PROBES_LDRSTRD,
32 PROBES_LOAD,
33 PROBES_STORE,
34 PROBES_LOAD_EXTRA,
35 PROBES_STORE_EXTRA,
36 PROBES_MOV_IP_SP,
37 PROBES_DATA_PROCESSING_REG,
38 PROBES_DATA_PROCESSING_IMM,
39 PROBES_MOV_HALFWORD,
40 PROBES_SEV,
41 PROBES_WFE,
42 PROBES_SATURATE,
43 PROBES_REV,
44 PROBES_MMI,
45 PROBES_PACK,
46 PROBES_EXTEND,
47 PROBES_EXTEND_ADD,
48 PROBES_MUL_ADD_LONG,
49 PROBES_MUL_ADD,
50 PROBES_BITFIELD,
51 PROBES_BRANCH,
52 PROBES_LDMSTM,
53 NUM_PROBES_ARM_ACTIONS
54};
55
56void __kprobes simulate_bbl(probes_opcode_t opcode,
57 struct arch_probes_insn *asi, struct pt_regs *regs);
58void __kprobes simulate_blx1(probes_opcode_t opcode,
59 struct arch_probes_insn *asi, struct pt_regs *regs);
60void __kprobes simulate_blx2bx(probes_opcode_t opcode,
61 struct arch_probes_insn *asi, struct pt_regs *regs);
62void __kprobes simulate_mrs(probes_opcode_t opcode,
63 struct arch_probes_insn *asi, struct pt_regs *regs);
64void __kprobes simulate_mov_ipsp(probes_opcode_t opcode,
65 struct arch_probes_insn *asi, struct pt_regs *regs);
66
67extern const union decode_item probes_decode_arm_table[];
68
69enum probes_insn arm_probes_decode_insn(probes_opcode_t,
70 struct arch_probes_insn *, bool emulate,
71 const union decode_action *actions);
72
73#endif
diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c
deleted file mode 100644
index 4131351e812f..000000000000
--- a/arch/arm/kernel/probes-thumb.c
+++ /dev/null
@@ -1,882 +0,0 @@
1/*
2 * arch/arm/kernel/probes-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/stddef.h>
12#include <linux/kernel.h>
13#include <linux/module.h>
14
15#include "probes.h"
16#include "probes-thumb.h"
17
18
19static const union decode_item t32_table_1110_100x_x0xx[] = {
20 /* Load/store multiple instructions */
21
22 /* Rn is PC 1110 100x x0xx 1111 xxxx xxxx xxxx xxxx */
23 DECODE_REJECT (0xfe4f0000, 0xe80f0000),
24
25 /* SRS 1110 1000 00x0 xxxx xxxx xxxx xxxx xxxx */
26 /* RFE 1110 1000 00x1 xxxx xxxx xxxx xxxx xxxx */
27 DECODE_REJECT (0xffc00000, 0xe8000000),
28 /* SRS 1110 1001 10x0 xxxx xxxx xxxx xxxx xxxx */
29 /* RFE 1110 1001 10x1 xxxx xxxx xxxx xxxx xxxx */
30 DECODE_REJECT (0xffc00000, 0xe9800000),
31
32 /* STM Rn, {...pc} 1110 100x x0x0 xxxx 1xxx xxxx xxxx xxxx */
33 DECODE_REJECT (0xfe508000, 0xe8008000),
34 /* LDM Rn, {...lr,pc} 1110 100x x0x1 xxxx 11xx xxxx xxxx xxxx */
35 DECODE_REJECT (0xfe50c000, 0xe810c000),
36 /* LDM/STM Rn, {...sp} 1110 100x x0xx xxxx xx1x xxxx xxxx xxxx */
37 DECODE_REJECT (0xfe402000, 0xe8002000),
38
39 /* STMIA 1110 1000 10x0 xxxx xxxx xxxx xxxx xxxx */
40 /* LDMIA 1110 1000 10x1 xxxx xxxx xxxx xxxx xxxx */
41 /* STMDB 1110 1001 00x0 xxxx xxxx xxxx xxxx xxxx */
42 /* LDMDB 1110 1001 00x1 xxxx xxxx xxxx xxxx xxxx */
43 DECODE_CUSTOM (0xfe400000, 0xe8000000, PROBES_T32_LDMSTM),
44
45 DECODE_END
46};
47
48static const union decode_item t32_table_1110_100x_x1xx[] = {
49 /* Load/store dual, load/store exclusive, table branch */
50
51 /* STRD (immediate) 1110 1000 x110 xxxx xxxx xxxx xxxx xxxx */
52 /* LDRD (immediate) 1110 1000 x111 xxxx xxxx xxxx xxxx xxxx */
53 DECODE_OR (0xff600000, 0xe8600000),
54 /* STRD (immediate) 1110 1001 x1x0 xxxx xxxx xxxx xxxx xxxx */
55 /* LDRD (immediate) 1110 1001 x1x1 xxxx xxxx xxxx xxxx xxxx */
56 DECODE_EMULATEX (0xff400000, 0xe9400000, PROBES_T32_LDRDSTRD,
57 REGS(NOPCWB, NOSPPC, NOSPPC, 0, 0)),
58
59 /* TBB 1110 1000 1101 xxxx xxxx xxxx 0000 xxxx */
60 /* TBH 1110 1000 1101 xxxx xxxx xxxx 0001 xxxx */
61 DECODE_SIMULATEX(0xfff000e0, 0xe8d00000, PROBES_T32_TABLE_BRANCH,
62 REGS(NOSP, 0, 0, 0, NOSPPC)),
63
64 /* STREX 1110 1000 0100 xxxx xxxx xxxx xxxx xxxx */
65 /* LDREX 1110 1000 0101 xxxx xxxx xxxx xxxx xxxx */
66 /* STREXB 1110 1000 1100 xxxx xxxx xxxx 0100 xxxx */
67 /* STREXH 1110 1000 1100 xxxx xxxx xxxx 0101 xxxx */
68 /* STREXD 1110 1000 1100 xxxx xxxx xxxx 0111 xxxx */
69 /* LDREXB 1110 1000 1101 xxxx xxxx xxxx 0100 xxxx */
70 /* LDREXH 1110 1000 1101 xxxx xxxx xxxx 0101 xxxx */
71 /* LDREXD 1110 1000 1101 xxxx xxxx xxxx 0111 xxxx */
72 /* And unallocated instructions... */
73 DECODE_END
74};
75
76static const union decode_item t32_table_1110_101x[] = {
77 /* Data-processing (shifted register) */
78
79 /* TST 1110 1010 0001 xxxx xxxx 1111 xxxx xxxx */
80 /* TEQ 1110 1010 1001 xxxx xxxx 1111 xxxx xxxx */
81 DECODE_EMULATEX (0xff700f00, 0xea100f00, PROBES_T32_TST,
82 REGS(NOSPPC, 0, 0, 0, NOSPPC)),
83
84 /* CMN 1110 1011 0001 xxxx xxxx 1111 xxxx xxxx */
85 DECODE_OR (0xfff00f00, 0xeb100f00),
86 /* CMP 1110 1011 1011 xxxx xxxx 1111 xxxx xxxx */
87 DECODE_EMULATEX (0xfff00f00, 0xebb00f00, PROBES_T32_TST,
88 REGS(NOPC, 0, 0, 0, NOSPPC)),
89
90 /* MOV 1110 1010 010x 1111 xxxx xxxx xxxx xxxx */
91 /* MVN 1110 1010 011x 1111 xxxx xxxx xxxx xxxx */
92 DECODE_EMULATEX (0xffcf0000, 0xea4f0000, PROBES_T32_MOV,
93 REGS(0, 0, NOSPPC, 0, NOSPPC)),
94
95 /* ??? 1110 1010 101x xxxx xxxx xxxx xxxx xxxx */
96 /* ??? 1110 1010 111x xxxx xxxx xxxx xxxx xxxx */
97 DECODE_REJECT (0xffa00000, 0xeaa00000),
98 /* ??? 1110 1011 001x xxxx xxxx xxxx xxxx xxxx */
99 DECODE_REJECT (0xffe00000, 0xeb200000),
100 /* ??? 1110 1011 100x xxxx xxxx xxxx xxxx xxxx */
101 DECODE_REJECT (0xffe00000, 0xeb800000),
102 /* ??? 1110 1011 111x xxxx xxxx xxxx xxxx xxxx */
103 DECODE_REJECT (0xffe00000, 0xebe00000),
104
105 /* ADD/SUB SP, SP, Rm, LSL #0..3 */
106 /* 1110 1011 x0xx 1101 x000 1101 xx00 xxxx */
107 DECODE_EMULATEX (0xff4f7f30, 0xeb0d0d00, PROBES_T32_ADDSUB,
108 REGS(SP, 0, SP, 0, NOSPPC)),
109
110 /* ADD/SUB SP, SP, Rm, shift */
111 /* 1110 1011 x0xx 1101 xxxx 1101 xxxx xxxx */
112 DECODE_REJECT (0xff4f0f00, 0xeb0d0d00),
113
114 /* ADD/SUB Rd, SP, Rm, shift */
115 /* 1110 1011 x0xx 1101 xxxx xxxx xxxx xxxx */
116 DECODE_EMULATEX (0xff4f0000, 0xeb0d0000, PROBES_T32_ADDSUB,
117 REGS(SP, 0, NOPC, 0, NOSPPC)),
118
119 /* AND 1110 1010 000x xxxx xxxx xxxx xxxx xxxx */
120 /* BIC 1110 1010 001x xxxx xxxx xxxx xxxx xxxx */
121 /* ORR 1110 1010 010x xxxx xxxx xxxx xxxx xxxx */
122 /* ORN 1110 1010 011x xxxx xxxx xxxx xxxx xxxx */
123 /* EOR 1110 1010 100x xxxx xxxx xxxx xxxx xxxx */
124 /* PKH 1110 1010 110x xxxx xxxx xxxx xxxx xxxx */
125 /* ADD 1110 1011 000x xxxx xxxx xxxx xxxx xxxx */
126 /* ADC 1110 1011 010x xxxx xxxx xxxx xxxx xxxx */
127 /* SBC 1110 1011 011x xxxx xxxx xxxx xxxx xxxx */
128 /* SUB 1110 1011 101x xxxx xxxx xxxx xxxx xxxx */
129 /* RSB 1110 1011 110x xxxx xxxx xxxx xxxx xxxx */
130 DECODE_EMULATEX (0xfe000000, 0xea000000, PROBES_T32_LOGICAL,
131 REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
132
133 DECODE_END
134};
135
136static const union decode_item t32_table_1111_0x0x___0[] = {
137 /* Data-processing (modified immediate) */
138
139 /* TST 1111 0x00 0001 xxxx 0xxx 1111 xxxx xxxx */
140 /* TEQ 1111 0x00 1001 xxxx 0xxx 1111 xxxx xxxx */
141 DECODE_EMULATEX (0xfb708f00, 0xf0100f00, PROBES_T32_TST,
142 REGS(NOSPPC, 0, 0, 0, 0)),
143
144 /* CMN 1111 0x01 0001 xxxx 0xxx 1111 xxxx xxxx */
145 DECODE_OR (0xfbf08f00, 0xf1100f00),
146 /* CMP 1111 0x01 1011 xxxx 0xxx 1111 xxxx xxxx */
147 DECODE_EMULATEX (0xfbf08f00, 0xf1b00f00, PROBES_T32_CMP,
148 REGS(NOPC, 0, 0, 0, 0)),
149
150 /* MOV 1111 0x00 010x 1111 0xxx xxxx xxxx xxxx */
151 /* MVN 1111 0x00 011x 1111 0xxx xxxx xxxx xxxx */
152 DECODE_EMULATEX (0xfbcf8000, 0xf04f0000, PROBES_T32_MOV,
153 REGS(0, 0, NOSPPC, 0, 0)),
154
155 /* ??? 1111 0x00 101x xxxx 0xxx xxxx xxxx xxxx */
156 DECODE_REJECT (0xfbe08000, 0xf0a00000),
157 /* ??? 1111 0x00 110x xxxx 0xxx xxxx xxxx xxxx */
158 /* ??? 1111 0x00 111x xxxx 0xxx xxxx xxxx xxxx */
159 DECODE_REJECT (0xfbc08000, 0xf0c00000),
160 /* ??? 1111 0x01 001x xxxx 0xxx xxxx xxxx xxxx */
161 DECODE_REJECT (0xfbe08000, 0xf1200000),
162 /* ??? 1111 0x01 100x xxxx 0xxx xxxx xxxx xxxx */
163 DECODE_REJECT (0xfbe08000, 0xf1800000),
164 /* ??? 1111 0x01 111x xxxx 0xxx xxxx xxxx xxxx */
165 DECODE_REJECT (0xfbe08000, 0xf1e00000),
166
167 /* ADD Rd, SP, #imm 1111 0x01 000x 1101 0xxx xxxx xxxx xxxx */
168 /* SUB Rd, SP, #imm 1111 0x01 101x 1101 0xxx xxxx xxxx xxxx */
169 DECODE_EMULATEX (0xfb4f8000, 0xf10d0000, PROBES_T32_ADDSUB,
170 REGS(SP, 0, NOPC, 0, 0)),
171
172 /* AND 1111 0x00 000x xxxx 0xxx xxxx xxxx xxxx */
173 /* BIC 1111 0x00 001x xxxx 0xxx xxxx xxxx xxxx */
174 /* ORR 1111 0x00 010x xxxx 0xxx xxxx xxxx xxxx */
175 /* ORN 1111 0x00 011x xxxx 0xxx xxxx xxxx xxxx */
176 /* EOR 1111 0x00 100x xxxx 0xxx xxxx xxxx xxxx */
177 /* ADD 1111 0x01 000x xxxx 0xxx xxxx xxxx xxxx */
178 /* ADC 1111 0x01 010x xxxx 0xxx xxxx xxxx xxxx */
179 /* SBC 1111 0x01 011x xxxx 0xxx xxxx xxxx xxxx */
180 /* SUB 1111 0x01 101x xxxx 0xxx xxxx xxxx xxxx */
181 /* RSB 1111 0x01 110x xxxx 0xxx xxxx xxxx xxxx */
182 DECODE_EMULATEX (0xfa008000, 0xf0000000, PROBES_T32_LOGICAL,
183 REGS(NOSPPC, 0, NOSPPC, 0, 0)),
184
185 DECODE_END
186};
187
188static const union decode_item t32_table_1111_0x1x___0[] = {
189 /* Data-processing (plain binary immediate) */
190
191 /* ADDW Rd, PC, #imm 1111 0x10 0000 1111 0xxx xxxx xxxx xxxx */
192 DECODE_OR (0xfbff8000, 0xf20f0000),
193 /* SUBW Rd, PC, #imm 1111 0x10 1010 1111 0xxx xxxx xxxx xxxx */
194 DECODE_EMULATEX (0xfbff8000, 0xf2af0000, PROBES_T32_ADDWSUBW_PC,
195 REGS(PC, 0, NOSPPC, 0, 0)),
196
197 /* ADDW SP, SP, #imm 1111 0x10 0000 1101 0xxx 1101 xxxx xxxx */
198 DECODE_OR (0xfbff8f00, 0xf20d0d00),
199 /* SUBW SP, SP, #imm 1111 0x10 1010 1101 0xxx 1101 xxxx xxxx */
200 DECODE_EMULATEX (0xfbff8f00, 0xf2ad0d00, PROBES_T32_ADDWSUBW,
201 REGS(SP, 0, SP, 0, 0)),
202
203 /* ADDW 1111 0x10 0000 xxxx 0xxx xxxx xxxx xxxx */
204 DECODE_OR (0xfbf08000, 0xf2000000),
205 /* SUBW 1111 0x10 1010 xxxx 0xxx xxxx xxxx xxxx */
206 DECODE_EMULATEX (0xfbf08000, 0xf2a00000, PROBES_T32_ADDWSUBW,
207 REGS(NOPCX, 0, NOSPPC, 0, 0)),
208
209 /* MOVW 1111 0x10 0100 xxxx 0xxx xxxx xxxx xxxx */
210 /* MOVT 1111 0x10 1100 xxxx 0xxx xxxx xxxx xxxx */
211 DECODE_EMULATEX (0xfb708000, 0xf2400000, PROBES_T32_MOVW,
212 REGS(0, 0, NOSPPC, 0, 0)),
213
214 /* SSAT16 1111 0x11 0010 xxxx 0000 xxxx 00xx xxxx */
215 /* SSAT 1111 0x11 00x0 xxxx 0xxx xxxx xxxx xxxx */
216 /* USAT16 1111 0x11 1010 xxxx 0000 xxxx 00xx xxxx */
217 /* USAT 1111 0x11 10x0 xxxx 0xxx xxxx xxxx xxxx */
218 DECODE_EMULATEX (0xfb508000, 0xf3000000, PROBES_T32_SAT,
219 REGS(NOSPPC, 0, NOSPPC, 0, 0)),
220
221 /* SFBX 1111 0x11 0100 xxxx 0xxx xxxx xxxx xxxx */
222 /* UFBX 1111 0x11 1100 xxxx 0xxx xxxx xxxx xxxx */
223 DECODE_EMULATEX (0xfb708000, 0xf3400000, PROBES_T32_BITFIELD,
224 REGS(NOSPPC, 0, NOSPPC, 0, 0)),
225
226 /* BFC 1111 0x11 0110 1111 0xxx xxxx xxxx xxxx */
227 DECODE_EMULATEX (0xfbff8000, 0xf36f0000, PROBES_T32_BITFIELD,
228 REGS(0, 0, NOSPPC, 0, 0)),
229
230 /* BFI 1111 0x11 0110 xxxx 0xxx xxxx xxxx xxxx */
231 DECODE_EMULATEX (0xfbf08000, 0xf3600000, PROBES_T32_BITFIELD,
232 REGS(NOSPPCX, 0, NOSPPC, 0, 0)),
233
234 DECODE_END
235};
236
237static const union decode_item t32_table_1111_0xxx___1[] = {
238 /* Branches and miscellaneous control */
239
240 /* YIELD 1111 0011 1010 xxxx 10x0 x000 0000 0001 */
241 DECODE_OR (0xfff0d7ff, 0xf3a08001),
242 /* SEV 1111 0011 1010 xxxx 10x0 x000 0000 0100 */
243 DECODE_EMULATE (0xfff0d7ff, 0xf3a08004, PROBES_T32_SEV),
244 /* NOP 1111 0011 1010 xxxx 10x0 x000 0000 0000 */
245 /* WFE 1111 0011 1010 xxxx 10x0 x000 0000 0010 */
246 /* WFI 1111 0011 1010 xxxx 10x0 x000 0000 0011 */
247 DECODE_SIMULATE (0xfff0d7fc, 0xf3a08000, PROBES_T32_WFE),
248
249 /* MRS Rd, CPSR 1111 0011 1110 xxxx 10x0 xxxx xxxx xxxx */
250 DECODE_SIMULATEX(0xfff0d000, 0xf3e08000, PROBES_T32_MRS,
251 REGS(0, 0, NOSPPC, 0, 0)),
252
253 /*
254 * Unsupported instructions
255 * 1111 0x11 1xxx xxxx 10x0 xxxx xxxx xxxx
256 *
257 * MSR 1111 0011 100x xxxx 10x0 xxxx xxxx xxxx
258 * DBG hint 1111 0011 1010 xxxx 10x0 x000 1111 xxxx
259 * Unallocated hints 1111 0011 1010 xxxx 10x0 x000 xxxx xxxx
260 * CPS 1111 0011 1010 xxxx 10x0 xxxx xxxx xxxx
261 * CLREX/DSB/DMB/ISB 1111 0011 1011 xxxx 10x0 xxxx xxxx xxxx
262 * BXJ 1111 0011 1100 xxxx 10x0 xxxx xxxx xxxx
263 * SUBS PC,LR,#<imm8> 1111 0011 1101 xxxx 10x0 xxxx xxxx xxxx
264 * MRS Rd, SPSR 1111 0011 1111 xxxx 10x0 xxxx xxxx xxxx
265 * SMC 1111 0111 1111 xxxx 1000 xxxx xxxx xxxx
266 * UNDEFINED 1111 0111 1111 xxxx 1010 xxxx xxxx xxxx
267 * ??? 1111 0111 1xxx xxxx 1010 xxxx xxxx xxxx
268 */
269 DECODE_REJECT (0xfb80d000, 0xf3808000),
270
271 /* Bcc 1111 0xxx xxxx xxxx 10x0 xxxx xxxx xxxx */
272 DECODE_CUSTOM (0xf800d000, 0xf0008000, PROBES_T32_BRANCH_COND),
273
274 /* BLX 1111 0xxx xxxx xxxx 11x0 xxxx xxxx xxx0 */
275 DECODE_OR (0xf800d001, 0xf000c000),
276 /* B 1111 0xxx xxxx xxxx 10x1 xxxx xxxx xxxx */
277 /* BL 1111 0xxx xxxx xxxx 11x1 xxxx xxxx xxxx */
278 DECODE_SIMULATE (0xf8009000, 0xf0009000, PROBES_T32_BRANCH),
279
280 DECODE_END
281};
282
283static const union decode_item t32_table_1111_100x_x0x1__1111[] = {
284 /* Memory hints */
285
286 /* PLD (literal) 1111 1000 x001 1111 1111 xxxx xxxx xxxx */
287 /* PLI (literal) 1111 1001 x001 1111 1111 xxxx xxxx xxxx */
288 DECODE_SIMULATE (0xfe7ff000, 0xf81ff000, PROBES_T32_PLDI),
289
290 /* PLD{W} (immediate) 1111 1000 10x1 xxxx 1111 xxxx xxxx xxxx */
291 DECODE_OR (0xffd0f000, 0xf890f000),
292 /* PLD{W} (immediate) 1111 1000 00x1 xxxx 1111 1100 xxxx xxxx */
293 DECODE_OR (0xffd0ff00, 0xf810fc00),
294 /* PLI (immediate) 1111 1001 1001 xxxx 1111 xxxx xxxx xxxx */
295 DECODE_OR (0xfff0f000, 0xf990f000),
296 /* PLI (immediate) 1111 1001 0001 xxxx 1111 1100 xxxx xxxx */
297 DECODE_SIMULATEX(0xfff0ff00, 0xf910fc00, PROBES_T32_PLDI,
298 REGS(NOPCX, 0, 0, 0, 0)),
299
300 /* PLD{W} (register) 1111 1000 00x1 xxxx 1111 0000 00xx xxxx */
301 DECODE_OR (0xffd0ffc0, 0xf810f000),
302 /* PLI (register) 1111 1001 0001 xxxx 1111 0000 00xx xxxx */
303 DECODE_SIMULATEX(0xfff0ffc0, 0xf910f000, PROBES_T32_PLDI,
304 REGS(NOPCX, 0, 0, 0, NOSPPC)),
305
306 /* Other unallocated instructions... */
307 DECODE_END
308};
309
310static const union decode_item t32_table_1111_100x[] = {
311 /* Store/Load single data item */
312
313 /* ??? 1111 100x x11x xxxx xxxx xxxx xxxx xxxx */
314 DECODE_REJECT (0xfe600000, 0xf8600000),
315
316 /* ??? 1111 1001 0101 xxxx xxxx xxxx xxxx xxxx */
317 DECODE_REJECT (0xfff00000, 0xf9500000),
318
319 /* ??? 1111 100x 0xxx xxxx xxxx 10x0 xxxx xxxx */
320 DECODE_REJECT (0xfe800d00, 0xf8000800),
321
322 /* STRBT 1111 1000 0000 xxxx xxxx 1110 xxxx xxxx */
323 /* STRHT 1111 1000 0010 xxxx xxxx 1110 xxxx xxxx */
324 /* STRT 1111 1000 0100 xxxx xxxx 1110 xxxx xxxx */
325 /* LDRBT 1111 1000 0001 xxxx xxxx 1110 xxxx xxxx */
326 /* LDRSBT 1111 1001 0001 xxxx xxxx 1110 xxxx xxxx */
327 /* LDRHT 1111 1000 0011 xxxx xxxx 1110 xxxx xxxx */
328 /* LDRSHT 1111 1001 0011 xxxx xxxx 1110 xxxx xxxx */
329 /* LDRT 1111 1000 0101 xxxx xxxx 1110 xxxx xxxx */
330 DECODE_REJECT (0xfe800f00, 0xf8000e00),
331
332 /* STR{,B,H} Rn,[PC...] 1111 1000 xxx0 1111 xxxx xxxx xxxx xxxx */
333 DECODE_REJECT (0xff1f0000, 0xf80f0000),
334
335 /* STR{,B,H} PC,[Rn...] 1111 1000 xxx0 xxxx 1111 xxxx xxxx xxxx */
336 DECODE_REJECT (0xff10f000, 0xf800f000),
337
338 /* LDR (literal) 1111 1000 x101 1111 xxxx xxxx xxxx xxxx */
339 DECODE_SIMULATEX(0xff7f0000, 0xf85f0000, PROBES_T32_LDR_LIT,
340 REGS(PC, ANY, 0, 0, 0)),
341
342 /* STR (immediate) 1111 1000 0100 xxxx xxxx 1xxx xxxx xxxx */
343 /* LDR (immediate) 1111 1000 0101 xxxx xxxx 1xxx xxxx xxxx */
344 DECODE_OR (0xffe00800, 0xf8400800),
345 /* STR (immediate) 1111 1000 1100 xxxx xxxx xxxx xxxx xxxx */
346 /* LDR (immediate) 1111 1000 1101 xxxx xxxx xxxx xxxx xxxx */
347 DECODE_EMULATEX (0xffe00000, 0xf8c00000, PROBES_T32_LDRSTR,
348 REGS(NOPCX, ANY, 0, 0, 0)),
349
350 /* STR (register) 1111 1000 0100 xxxx xxxx 0000 00xx xxxx */
351 /* LDR (register) 1111 1000 0101 xxxx xxxx 0000 00xx xxxx */
352 DECODE_EMULATEX (0xffe00fc0, 0xf8400000, PROBES_T32_LDRSTR,
353 REGS(NOPCX, ANY, 0, 0, NOSPPC)),
354
355 /* LDRB (literal) 1111 1000 x001 1111 xxxx xxxx xxxx xxxx */
356 /* LDRSB (literal) 1111 1001 x001 1111 xxxx xxxx xxxx xxxx */
357 /* LDRH (literal) 1111 1000 x011 1111 xxxx xxxx xxxx xxxx */
358 /* LDRSH (literal) 1111 1001 x011 1111 xxxx xxxx xxxx xxxx */
359 DECODE_SIMULATEX(0xfe5f0000, 0xf81f0000, PROBES_T32_LDR_LIT,
360 REGS(PC, NOSPPCX, 0, 0, 0)),
361
362 /* STRB (immediate) 1111 1000 0000 xxxx xxxx 1xxx xxxx xxxx */
363 /* STRH (immediate) 1111 1000 0010 xxxx xxxx 1xxx xxxx xxxx */
364 /* LDRB (immediate) 1111 1000 0001 xxxx xxxx 1xxx xxxx xxxx */
365 /* LDRSB (immediate) 1111 1001 0001 xxxx xxxx 1xxx xxxx xxxx */
366 /* LDRH (immediate) 1111 1000 0011 xxxx xxxx 1xxx xxxx xxxx */
367 /* LDRSH (immediate) 1111 1001 0011 xxxx xxxx 1xxx xxxx xxxx */
368 DECODE_OR (0xfec00800, 0xf8000800),
369 /* STRB (immediate) 1111 1000 1000 xxxx xxxx xxxx xxxx xxxx */
370 /* STRH (immediate) 1111 1000 1010 xxxx xxxx xxxx xxxx xxxx */
371 /* LDRB (immediate) 1111 1000 1001 xxxx xxxx xxxx xxxx xxxx */
372 /* LDRSB (immediate) 1111 1001 1001 xxxx xxxx xxxx xxxx xxxx */
373 /* LDRH (immediate) 1111 1000 1011 xxxx xxxx xxxx xxxx xxxx */
374 /* LDRSH (immediate) 1111 1001 1011 xxxx xxxx xxxx xxxx xxxx */
375 DECODE_EMULATEX (0xfec00000, 0xf8800000, PROBES_T32_LDRSTR,
376 REGS(NOPCX, NOSPPCX, 0, 0, 0)),
377
378 /* STRB (register) 1111 1000 0000 xxxx xxxx 0000 00xx xxxx */
379 /* STRH (register) 1111 1000 0010 xxxx xxxx 0000 00xx xxxx */
380 /* LDRB (register) 1111 1000 0001 xxxx xxxx 0000 00xx xxxx */
381 /* LDRSB (register) 1111 1001 0001 xxxx xxxx 0000 00xx xxxx */
382 /* LDRH (register) 1111 1000 0011 xxxx xxxx 0000 00xx xxxx */
383 /* LDRSH (register) 1111 1001 0011 xxxx xxxx 0000 00xx xxxx */
384 DECODE_EMULATEX (0xfe800fc0, 0xf8000000, PROBES_T32_LDRSTR,
385 REGS(NOPCX, NOSPPCX, 0, 0, NOSPPC)),
386
387 /* Other unallocated instructions... */
388 DECODE_END
389};
390
391static const union decode_item t32_table_1111_1010___1111[] = {
392 /* Data-processing (register) */
393
394 /* ??? 1111 1010 011x xxxx 1111 xxxx 1xxx xxxx */
395 DECODE_REJECT (0xffe0f080, 0xfa60f080),
396
397 /* SXTH 1111 1010 0000 1111 1111 xxxx 1xxx xxxx */
398 /* UXTH 1111 1010 0001 1111 1111 xxxx 1xxx xxxx */
399 /* SXTB16 1111 1010 0010 1111 1111 xxxx 1xxx xxxx */
400 /* UXTB16 1111 1010 0011 1111 1111 xxxx 1xxx xxxx */
401 /* SXTB 1111 1010 0100 1111 1111 xxxx 1xxx xxxx */
402 /* UXTB 1111 1010 0101 1111 1111 xxxx 1xxx xxxx */
403 DECODE_EMULATEX (0xff8ff080, 0xfa0ff080, PROBES_T32_SIGN_EXTEND,
404 REGS(0, 0, NOSPPC, 0, NOSPPC)),
405
406
407 /* ??? 1111 1010 1xxx xxxx 1111 xxxx 0x11 xxxx */
408 DECODE_REJECT (0xff80f0b0, 0xfa80f030),
409 /* ??? 1111 1010 1x11 xxxx 1111 xxxx 0xxx xxxx */
410 DECODE_REJECT (0xffb0f080, 0xfab0f000),
411
412 /* SADD16 1111 1010 1001 xxxx 1111 xxxx 0000 xxxx */
413 /* SASX 1111 1010 1010 xxxx 1111 xxxx 0000 xxxx */
414 /* SSAX 1111 1010 1110 xxxx 1111 xxxx 0000 xxxx */
415 /* SSUB16 1111 1010 1101 xxxx 1111 xxxx 0000 xxxx */
416 /* SADD8 1111 1010 1000 xxxx 1111 xxxx 0000 xxxx */
417 /* SSUB8 1111 1010 1100 xxxx 1111 xxxx 0000 xxxx */
418
419 /* QADD16 1111 1010 1001 xxxx 1111 xxxx 0001 xxxx */
420 /* QASX 1111 1010 1010 xxxx 1111 xxxx 0001 xxxx */
421 /* QSAX 1111 1010 1110 xxxx 1111 xxxx 0001 xxxx */
422 /* QSUB16 1111 1010 1101 xxxx 1111 xxxx 0001 xxxx */
423 /* QADD8 1111 1010 1000 xxxx 1111 xxxx 0001 xxxx */
424 /* QSUB8 1111 1010 1100 xxxx 1111 xxxx 0001 xxxx */
425
426 /* SHADD16 1111 1010 1001 xxxx 1111 xxxx 0010 xxxx */
427 /* SHASX 1111 1010 1010 xxxx 1111 xxxx 0010 xxxx */
428 /* SHSAX 1111 1010 1110 xxxx 1111 xxxx 0010 xxxx */
429 /* SHSUB16 1111 1010 1101 xxxx 1111 xxxx 0010 xxxx */
430 /* SHADD8 1111 1010 1000 xxxx 1111 xxxx 0010 xxxx */
431 /* SHSUB8 1111 1010 1100 xxxx 1111 xxxx 0010 xxxx */
432
433 /* UADD16 1111 1010 1001 xxxx 1111 xxxx 0100 xxxx */
434 /* UASX 1111 1010 1010 xxxx 1111 xxxx 0100 xxxx */
435 /* USAX 1111 1010 1110 xxxx 1111 xxxx 0100 xxxx */
436 /* USUB16 1111 1010 1101 xxxx 1111 xxxx 0100 xxxx */
437 /* UADD8 1111 1010 1000 xxxx 1111 xxxx 0100 xxxx */
438 /* USUB8 1111 1010 1100 xxxx 1111 xxxx 0100 xxxx */
439
440 /* UQADD16 1111 1010 1001 xxxx 1111 xxxx 0101 xxxx */
441 /* UQASX 1111 1010 1010 xxxx 1111 xxxx 0101 xxxx */
442 /* UQSAX 1111 1010 1110 xxxx 1111 xxxx 0101 xxxx */
443 /* UQSUB16 1111 1010 1101 xxxx 1111 xxxx 0101 xxxx */
444 /* UQADD8 1111 1010 1000 xxxx 1111 xxxx 0101 xxxx */
445 /* UQSUB8 1111 1010 1100 xxxx 1111 xxxx 0101 xxxx */
446
447 /* UHADD16 1111 1010 1001 xxxx 1111 xxxx 0110 xxxx */
448 /* UHASX 1111 1010 1010 xxxx 1111 xxxx 0110 xxxx */
449 /* UHSAX 1111 1010 1110 xxxx 1111 xxxx 0110 xxxx */
450 /* UHSUB16 1111 1010 1101 xxxx 1111 xxxx 0110 xxxx */
451 /* UHADD8 1111 1010 1000 xxxx 1111 xxxx 0110 xxxx */
452 /* UHSUB8 1111 1010 1100 xxxx 1111 xxxx 0110 xxxx */
453 DECODE_OR (0xff80f080, 0xfa80f000),
454
455 /* SXTAH 1111 1010 0000 xxxx 1111 xxxx 1xxx xxxx */
456 /* UXTAH 1111 1010 0001 xxxx 1111 xxxx 1xxx xxxx */
457 /* SXTAB16 1111 1010 0010 xxxx 1111 xxxx 1xxx xxxx */
458 /* UXTAB16 1111 1010 0011 xxxx 1111 xxxx 1xxx xxxx */
459 /* SXTAB 1111 1010 0100 xxxx 1111 xxxx 1xxx xxxx */
460 /* UXTAB 1111 1010 0101 xxxx 1111 xxxx 1xxx xxxx */
461 DECODE_OR (0xff80f080, 0xfa00f080),
462
463 /* QADD 1111 1010 1000 xxxx 1111 xxxx 1000 xxxx */
464 /* QDADD 1111 1010 1000 xxxx 1111 xxxx 1001 xxxx */
465 /* QSUB 1111 1010 1000 xxxx 1111 xxxx 1010 xxxx */
466 /* QDSUB 1111 1010 1000 xxxx 1111 xxxx 1011 xxxx */
467 DECODE_OR (0xfff0f0c0, 0xfa80f080),
468
469 /* SEL 1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */
470 DECODE_OR (0xfff0f0f0, 0xfaa0f080),
471
472 /* LSL 1111 1010 000x xxxx 1111 xxxx 0000 xxxx */
473 /* LSR 1111 1010 001x xxxx 1111 xxxx 0000 xxxx */
474 /* ASR 1111 1010 010x xxxx 1111 xxxx 0000 xxxx */
475 /* ROR 1111 1010 011x xxxx 1111 xxxx 0000 xxxx */
476 DECODE_EMULATEX (0xff80f0f0, 0xfa00f000, PROBES_T32_MEDIA,
477 REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
478
479 /* CLZ 1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */
480 DECODE_OR (0xfff0f0f0, 0xfab0f080),
481
482 /* REV 1111 1010 1001 xxxx 1111 xxxx 1000 xxxx */
483 /* REV16 1111 1010 1001 xxxx 1111 xxxx 1001 xxxx */
484 /* RBIT 1111 1010 1001 xxxx 1111 xxxx 1010 xxxx */
485 /* REVSH 1111 1010 1001 xxxx 1111 xxxx 1011 xxxx */
486 DECODE_EMULATEX (0xfff0f0c0, 0xfa90f080, PROBES_T32_REVERSE,
487 REGS(NOSPPC, 0, NOSPPC, 0, SAMEAS16)),
488
489 /* Other unallocated instructions... */
490 DECODE_END
491};
492
493static const union decode_item t32_table_1111_1011_0[] = {
494 /* Multiply, multiply accumulate, and absolute difference */
495
496 /* ??? 1111 1011 0000 xxxx 1111 xxxx 0001 xxxx */
497 DECODE_REJECT (0xfff0f0f0, 0xfb00f010),
498 /* ??? 1111 1011 0111 xxxx 1111 xxxx 0001 xxxx */
499 DECODE_REJECT (0xfff0f0f0, 0xfb70f010),
500
501 /* SMULxy 1111 1011 0001 xxxx 1111 xxxx 00xx xxxx */
502 DECODE_OR (0xfff0f0c0, 0xfb10f000),
503 /* MUL 1111 1011 0000 xxxx 1111 xxxx 0000 xxxx */
504 /* SMUAD{X} 1111 1011 0010 xxxx 1111 xxxx 000x xxxx */
505 /* SMULWy 1111 1011 0011 xxxx 1111 xxxx 000x xxxx */
506 /* SMUSD{X} 1111 1011 0100 xxxx 1111 xxxx 000x xxxx */
507 /* SMMUL{R} 1111 1011 0101 xxxx 1111 xxxx 000x xxxx */
508 /* USAD8 1111 1011 0111 xxxx 1111 xxxx 0000 xxxx */
509 DECODE_EMULATEX (0xff80f0e0, 0xfb00f000, PROBES_T32_MUL_ADD,
510 REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
511
512 /* ??? 1111 1011 0111 xxxx xxxx xxxx 0001 xxxx */
513 DECODE_REJECT (0xfff000f0, 0xfb700010),
514
515 /* SMLAxy 1111 1011 0001 xxxx xxxx xxxx 00xx xxxx */
516 DECODE_OR (0xfff000c0, 0xfb100000),
517 /* MLA 1111 1011 0000 xxxx xxxx xxxx 0000 xxxx */
518 /* MLS 1111 1011 0000 xxxx xxxx xxxx 0001 xxxx */
519 /* SMLAD{X} 1111 1011 0010 xxxx xxxx xxxx 000x xxxx */
520 /* SMLAWy 1111 1011 0011 xxxx xxxx xxxx 000x xxxx */
521 /* SMLSD{X} 1111 1011 0100 xxxx xxxx xxxx 000x xxxx */
522 /* SMMLA{R} 1111 1011 0101 xxxx xxxx xxxx 000x xxxx */
523 /* SMMLS{R} 1111 1011 0110 xxxx xxxx xxxx 000x xxxx */
524 /* USADA8 1111 1011 0111 xxxx xxxx xxxx 0000 xxxx */
525 DECODE_EMULATEX (0xff8000c0, 0xfb000000, PROBES_T32_MUL_ADD2,
526 REGS(NOSPPC, NOSPPCX, NOSPPC, 0, NOSPPC)),
527
528 /* Other unallocated instructions... */
529 DECODE_END
530};
531
532static const union decode_item t32_table_1111_1011_1[] = {
533 /* Long multiply, long multiply accumulate, and divide */
534
535 /* UMAAL 1111 1011 1110 xxxx xxxx xxxx 0110 xxxx */
536 DECODE_OR (0xfff000f0, 0xfbe00060),
537 /* SMLALxy 1111 1011 1100 xxxx xxxx xxxx 10xx xxxx */
538 DECODE_OR (0xfff000c0, 0xfbc00080),
539 /* SMLALD{X} 1111 1011 1100 xxxx xxxx xxxx 110x xxxx */
540 /* SMLSLD{X} 1111 1011 1101 xxxx xxxx xxxx 110x xxxx */
541 DECODE_OR (0xffe000e0, 0xfbc000c0),
542 /* SMULL 1111 1011 1000 xxxx xxxx xxxx 0000 xxxx */
543 /* UMULL 1111 1011 1010 xxxx xxxx xxxx 0000 xxxx */
544 /* SMLAL 1111 1011 1100 xxxx xxxx xxxx 0000 xxxx */
545 /* UMLAL 1111 1011 1110 xxxx xxxx xxxx 0000 xxxx */
546 DECODE_EMULATEX (0xff9000f0, 0xfb800000, PROBES_T32_MUL_ADD_LONG,
547 REGS(NOSPPC, NOSPPC, NOSPPC, 0, NOSPPC)),
548
549 /* SDIV 1111 1011 1001 xxxx xxxx xxxx 1111 xxxx */
550 /* UDIV 1111 1011 1011 xxxx xxxx xxxx 1111 xxxx */
551 /* Other unallocated instructions... */
552 DECODE_END
553};
554
555const union decode_item probes_decode_thumb32_table[] = {
556
557 /*
558 * Load/store multiple instructions
559 * 1110 100x x0xx xxxx xxxx xxxx xxxx xxxx
560 */
561 DECODE_TABLE (0xfe400000, 0xe8000000, t32_table_1110_100x_x0xx),
562
563 /*
564 * Load/store dual, load/store exclusive, table branch
565 * 1110 100x x1xx xxxx xxxx xxxx xxxx xxxx
566 */
567 DECODE_TABLE (0xfe400000, 0xe8400000, t32_table_1110_100x_x1xx),
568
569 /*
570 * Data-processing (shifted register)
571 * 1110 101x xxxx xxxx xxxx xxxx xxxx xxxx
572 */
573 DECODE_TABLE (0xfe000000, 0xea000000, t32_table_1110_101x),
574
575 /*
576 * Coprocessor instructions
577 * 1110 11xx xxxx xxxx xxxx xxxx xxxx xxxx
578 */
579 DECODE_REJECT (0xfc000000, 0xec000000),
580
581 /*
582 * Data-processing (modified immediate)
583 * 1111 0x0x xxxx xxxx 0xxx xxxx xxxx xxxx
584 */
585 DECODE_TABLE (0xfa008000, 0xf0000000, t32_table_1111_0x0x___0),
586
587 /*
588 * Data-processing (plain binary immediate)
589 * 1111 0x1x xxxx xxxx 0xxx xxxx xxxx xxxx
590 */
591 DECODE_TABLE (0xfa008000, 0xf2000000, t32_table_1111_0x1x___0),
592
593 /*
594 * Branches and miscellaneous control
595 * 1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx
596 */
597 DECODE_TABLE (0xf8008000, 0xf0008000, t32_table_1111_0xxx___1),
598
599 /*
600 * Advanced SIMD element or structure load/store instructions
601 * 1111 1001 xxx0 xxxx xxxx xxxx xxxx xxxx
602 */
603 DECODE_REJECT (0xff100000, 0xf9000000),
604
605 /*
606 * Memory hints
607 * 1111 100x x0x1 xxxx 1111 xxxx xxxx xxxx
608 */
609 DECODE_TABLE (0xfe50f000, 0xf810f000, t32_table_1111_100x_x0x1__1111),
610
611 /*
612 * Store single data item
613 * 1111 1000 xxx0 xxxx xxxx xxxx xxxx xxxx
614 * Load single data items
615 * 1111 100x xxx1 xxxx xxxx xxxx xxxx xxxx
616 */
617 DECODE_TABLE (0xfe000000, 0xf8000000, t32_table_1111_100x),
618
619 /*
620 * Data-processing (register)
621 * 1111 1010 xxxx xxxx 1111 xxxx xxxx xxxx
622 */
623 DECODE_TABLE (0xff00f000, 0xfa00f000, t32_table_1111_1010___1111),
624
625 /*
626 * Multiply, multiply accumulate, and absolute difference
627 * 1111 1011 0xxx xxxx xxxx xxxx xxxx xxxx
628 */
629 DECODE_TABLE (0xff800000, 0xfb000000, t32_table_1111_1011_0),
630
631 /*
632 * Long multiply, long multiply accumulate, and divide
633 * 1111 1011 1xxx xxxx xxxx xxxx xxxx xxxx
634 */
635 DECODE_TABLE (0xff800000, 0xfb800000, t32_table_1111_1011_1),
636
637 /*
638 * Coprocessor instructions
639 * 1111 11xx xxxx xxxx xxxx xxxx xxxx xxxx
640 */
641 DECODE_END
642};
643#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
644EXPORT_SYMBOL_GPL(probes_decode_thumb32_table);
645#endif
646
647static const union decode_item t16_table_1011[] = {
648 /* Miscellaneous 16-bit instructions */
649
650 /* ADD (SP plus immediate) 1011 0000 0xxx xxxx */
651 /* SUB (SP minus immediate) 1011 0000 1xxx xxxx */
652 DECODE_SIMULATE (0xff00, 0xb000, PROBES_T16_ADD_SP),
653
654 /* CBZ 1011 00x1 xxxx xxxx */
655 /* CBNZ 1011 10x1 xxxx xxxx */
656 DECODE_SIMULATE (0xf500, 0xb100, PROBES_T16_CBZ),
657
658 /* SXTH 1011 0010 00xx xxxx */
659 /* SXTB 1011 0010 01xx xxxx */
660 /* UXTH 1011 0010 10xx xxxx */
661 /* UXTB 1011 0010 11xx xxxx */
662 /* REV 1011 1010 00xx xxxx */
663 /* REV16 1011 1010 01xx xxxx */
664 /* ??? 1011 1010 10xx xxxx */
665 /* REVSH 1011 1010 11xx xxxx */
666 DECODE_REJECT (0xffc0, 0xba80),
667 DECODE_EMULATE (0xf500, 0xb000, PROBES_T16_SIGN_EXTEND),
668
669 /* PUSH 1011 010x xxxx xxxx */
670 DECODE_CUSTOM (0xfe00, 0xb400, PROBES_T16_PUSH),
671 /* POP 1011 110x xxxx xxxx */
672 DECODE_CUSTOM (0xfe00, 0xbc00, PROBES_T16_POP),
673
674 /*
675 * If-Then, and hints
676 * 1011 1111 xxxx xxxx
677 */
678
679 /* YIELD 1011 1111 0001 0000 */
680 DECODE_OR (0xffff, 0xbf10),
681 /* SEV 1011 1111 0100 0000 */
682 DECODE_EMULATE (0xffff, 0xbf40, PROBES_T16_SEV),
683 /* NOP 1011 1111 0000 0000 */
684 /* WFE 1011 1111 0010 0000 */
685 /* WFI 1011 1111 0011 0000 */
686 DECODE_SIMULATE (0xffcf, 0xbf00, PROBES_T16_WFE),
687 /* Unassigned hints 1011 1111 xxxx 0000 */
688 DECODE_REJECT (0xff0f, 0xbf00),
689 /* IT 1011 1111 xxxx xxxx */
690 DECODE_CUSTOM (0xff00, 0xbf00, PROBES_T16_IT),
691
692 /* SETEND 1011 0110 010x xxxx */
693 /* CPS 1011 0110 011x xxxx */
694 /* BKPT 1011 1110 xxxx xxxx */
695 /* And unallocated instructions... */
696 DECODE_END
697};
698
699const union decode_item probes_decode_thumb16_table[] = {
700
701 /*
702 * Shift (immediate), add, subtract, move, and compare
703 * 00xx xxxx xxxx xxxx
704 */
705
706 /* CMP (immediate) 0010 1xxx xxxx xxxx */
707 DECODE_EMULATE (0xf800, 0x2800, PROBES_T16_CMP),
708
709 /* ADD (register) 0001 100x xxxx xxxx */
710 /* SUB (register) 0001 101x xxxx xxxx */
711 /* LSL (immediate) 0000 0xxx xxxx xxxx */
712 /* LSR (immediate) 0000 1xxx xxxx xxxx */
713 /* ASR (immediate) 0001 0xxx xxxx xxxx */
714 /* ADD (immediate, Thumb) 0001 110x xxxx xxxx */
715 /* SUB (immediate, Thumb) 0001 111x xxxx xxxx */
716 /* MOV (immediate) 0010 0xxx xxxx xxxx */
717 /* ADD (immediate, Thumb) 0011 0xxx xxxx xxxx */
718 /* SUB (immediate, Thumb) 0011 1xxx xxxx xxxx */
719 DECODE_EMULATE (0xc000, 0x0000, PROBES_T16_ADDSUB),
720
721 /*
722 * 16-bit Thumb data-processing instructions
723 * 0100 00xx xxxx xxxx
724 */
725
726 /* TST (register) 0100 0010 00xx xxxx */
727 DECODE_EMULATE (0xffc0, 0x4200, PROBES_T16_CMP),
728 /* CMP (register) 0100 0010 10xx xxxx */
729 /* CMN (register) 0100 0010 11xx xxxx */
730 DECODE_EMULATE (0xff80, 0x4280, PROBES_T16_CMP),
731 /* AND (register) 0100 0000 00xx xxxx */
732 /* EOR (register) 0100 0000 01xx xxxx */
733 /* LSL (register) 0100 0000 10xx xxxx */
734 /* LSR (register) 0100 0000 11xx xxxx */
735 /* ASR (register) 0100 0001 00xx xxxx */
736 /* ADC (register) 0100 0001 01xx xxxx */
737 /* SBC (register) 0100 0001 10xx xxxx */
738 /* ROR (register) 0100 0001 11xx xxxx */
739 /* RSB (immediate) 0100 0010 01xx xxxx */
740 /* ORR (register) 0100 0011 00xx xxxx */
741 /* MUL 0100 0011 00xx xxxx */
742 /* BIC (register) 0100 0011 10xx xxxx */
743 /* MVN (register) 0100 0011 10xx xxxx */
744 DECODE_EMULATE (0xfc00, 0x4000, PROBES_T16_LOGICAL),
745
746 /*
747 * Special data instructions and branch and exchange
748 * 0100 01xx xxxx xxxx
749 */
750
751 /* BLX pc 0100 0111 1111 1xxx */
752 DECODE_REJECT (0xfff8, 0x47f8),
753
754 /* BX (register) 0100 0111 0xxx xxxx */
755 /* BLX (register) 0100 0111 1xxx xxxx */
756 DECODE_SIMULATE (0xff00, 0x4700, PROBES_T16_BLX),
757
758 /* ADD pc, pc 0100 0100 1111 1111 */
759 DECODE_REJECT (0xffff, 0x44ff),
760
761 /* ADD (register) 0100 0100 xxxx xxxx */
762 /* CMP (register) 0100 0101 xxxx xxxx */
763 /* MOV (register) 0100 0110 xxxx xxxx */
764 DECODE_CUSTOM (0xfc00, 0x4400, PROBES_T16_HIREGOPS),
765
766 /*
767 * Load from Literal Pool
768 * LDR (literal) 0100 1xxx xxxx xxxx
769 */
770 DECODE_SIMULATE (0xf800, 0x4800, PROBES_T16_LDR_LIT),
771
772 /*
773 * 16-bit Thumb Load/store instructions
774 * 0101 xxxx xxxx xxxx
775 * 011x xxxx xxxx xxxx
776 * 100x xxxx xxxx xxxx
777 */
778
779 /* STR (register) 0101 000x xxxx xxxx */
780 /* STRH (register) 0101 001x xxxx xxxx */
781 /* STRB (register) 0101 010x xxxx xxxx */
782 /* LDRSB (register) 0101 011x xxxx xxxx */
783 /* LDR (register) 0101 100x xxxx xxxx */
784 /* LDRH (register) 0101 101x xxxx xxxx */
785 /* LDRB (register) 0101 110x xxxx xxxx */
786 /* LDRSH (register) 0101 111x xxxx xxxx */
787 /* STR (immediate, Thumb) 0110 0xxx xxxx xxxx */
788 /* LDR (immediate, Thumb) 0110 1xxx xxxx xxxx */
789 /* STRB (immediate, Thumb) 0111 0xxx xxxx xxxx */
790 /* LDRB (immediate, Thumb) 0111 1xxx xxxx xxxx */
791 DECODE_EMULATE (0xc000, 0x4000, PROBES_T16_LDRHSTRH),
792 /* STRH (immediate, Thumb) 1000 0xxx xxxx xxxx */
793 /* LDRH (immediate, Thumb) 1000 1xxx xxxx xxxx */
794 DECODE_EMULATE (0xf000, 0x8000, PROBES_T16_LDRHSTRH),
795 /* STR (immediate, Thumb) 1001 0xxx xxxx xxxx */
796 /* LDR (immediate, Thumb) 1001 1xxx xxxx xxxx */
797 DECODE_SIMULATE (0xf000, 0x9000, PROBES_T16_LDRSTR),
798
799 /*
800 * Generate PC-/SP-relative address
801 * ADR (literal) 1010 0xxx xxxx xxxx
802 * ADD (SP plus immediate) 1010 1xxx xxxx xxxx
803 */
804 DECODE_SIMULATE (0xf000, 0xa000, PROBES_T16_ADR),
805
806 /*
807 * Miscellaneous 16-bit instructions
808 * 1011 xxxx xxxx xxxx
809 */
810 DECODE_TABLE (0xf000, 0xb000, t16_table_1011),
811
812 /* STM 1100 0xxx xxxx xxxx */
813 /* LDM 1100 1xxx xxxx xxxx */
814 DECODE_EMULATE (0xf000, 0xc000, PROBES_T16_LDMSTM),
815
816 /*
817 * Conditional branch, and Supervisor Call
818 */
819
820 /* Permanently UNDEFINED 1101 1110 xxxx xxxx */
821 /* SVC 1101 1111 xxxx xxxx */
822 DECODE_REJECT (0xfe00, 0xde00),
823
824 /* Conditional branch 1101 xxxx xxxx xxxx */
825 DECODE_CUSTOM (0xf000, 0xd000, PROBES_T16_BRANCH_COND),
826
827 /*
828 * Unconditional branch
829 * B 1110 0xxx xxxx xxxx
830 */
831 DECODE_SIMULATE (0xf800, 0xe000, PROBES_T16_BRANCH),
832
833 DECODE_END
834};
835#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
836EXPORT_SYMBOL_GPL(probes_decode_thumb16_table);
837#endif
838
839static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
840{
841 if (unlikely(in_it_block(cpsr)))
842 return probes_condition_checks[current_cond(cpsr)](cpsr);
843 return true;
844}
845
846static void __kprobes thumb16_singlestep(probes_opcode_t opcode,
847 struct arch_probes_insn *asi,
848 struct pt_regs *regs)
849{
850 regs->ARM_pc += 2;
851 asi->insn_handler(opcode, asi, regs);
852 regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
853}
854
855static void __kprobes thumb32_singlestep(probes_opcode_t opcode,
856 struct arch_probes_insn *asi,
857 struct pt_regs *regs)
858{
859 regs->ARM_pc += 4;
860 asi->insn_handler(opcode, asi, regs);
861 regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
862}
863
864enum probes_insn __kprobes
865thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
866 bool emulate, const union decode_action *actions)
867{
868 asi->insn_singlestep = thumb16_singlestep;
869 asi->insn_check_cc = thumb_check_cc;
870 return probes_decode_insn(insn, asi, probes_decode_thumb16_table, true,
871 emulate, actions);
872}
873
874enum probes_insn __kprobes
875thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
876 bool emulate, const union decode_action *actions)
877{
878 asi->insn_singlestep = thumb32_singlestep;
879 asi->insn_check_cc = thumb_check_cc;
880 return probes_decode_insn(insn, asi, probes_decode_thumb32_table, true,
881 emulate, actions);
882}
diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h
deleted file mode 100644
index 7c6f6ebe514f..000000000000
--- a/arch/arm/kernel/probes-thumb.h
+++ /dev/null
@@ -1,97 +0,0 @@
1/*
2 * arch/arm/kernel/probes-thumb.h
3 *
4 * Copyright 2013 Linaro Ltd.
5 * Written by: David A. Long
6 *
7 * The code contained herein is licensed under the GNU General Public
8 * License. You may obtain a copy of the GNU General Public License
9 * Version 2 or later at the following locations:
10 *
11 * http://www.opensource.org/licenses/gpl-license.html
12 * http://www.gnu.org/copyleft/gpl.html
13 */
14
15#ifndef _ARM_KERNEL_PROBES_THUMB_H
16#define _ARM_KERNEL_PROBES_THUMB_H
17
18/*
19 * True if current instruction is in an IT block.
20 */
21#define in_it_block(cpsr) ((cpsr & 0x06000c00) != 0x00000000)
22
23/*
24 * Return the condition code to check for the currently executing instruction.
25 * This is in ITSTATE<7:4> which is in CPSR<15:12> but is only valid if
26 * in_it_block returns true.
27 */
28#define current_cond(cpsr) ((cpsr >> 12) & 0xf)
29
30enum probes_t32_action {
31 PROBES_T32_EMULATE_NONE,
32 PROBES_T32_SIMULATE_NOP,
33 PROBES_T32_LDMSTM,
34 PROBES_T32_LDRDSTRD,
35 PROBES_T32_TABLE_BRANCH,
36 PROBES_T32_TST,
37 PROBES_T32_CMP,
38 PROBES_T32_MOV,
39 PROBES_T32_ADDSUB,
40 PROBES_T32_LOGICAL,
41 PROBES_T32_ADDWSUBW_PC,
42 PROBES_T32_ADDWSUBW,
43 PROBES_T32_MOVW,
44 PROBES_T32_SAT,
45 PROBES_T32_BITFIELD,
46 PROBES_T32_SEV,
47 PROBES_T32_WFE,
48 PROBES_T32_MRS,
49 PROBES_T32_BRANCH_COND,
50 PROBES_T32_BRANCH,
51 PROBES_T32_PLDI,
52 PROBES_T32_LDR_LIT,
53 PROBES_T32_LDRSTR,
54 PROBES_T32_SIGN_EXTEND,
55 PROBES_T32_MEDIA,
56 PROBES_T32_REVERSE,
57 PROBES_T32_MUL_ADD,
58 PROBES_T32_MUL_ADD2,
59 PROBES_T32_MUL_ADD_LONG,
60 NUM_PROBES_T32_ACTIONS
61};
62
63enum probes_t16_action {
64 PROBES_T16_ADD_SP,
65 PROBES_T16_CBZ,
66 PROBES_T16_SIGN_EXTEND,
67 PROBES_T16_PUSH,
68 PROBES_T16_POP,
69 PROBES_T16_SEV,
70 PROBES_T16_WFE,
71 PROBES_T16_IT,
72 PROBES_T16_CMP,
73 PROBES_T16_ADDSUB,
74 PROBES_T16_LOGICAL,
75 PROBES_T16_BLX,
76 PROBES_T16_HIREGOPS,
77 PROBES_T16_LDR_LIT,
78 PROBES_T16_LDRHSTRH,
79 PROBES_T16_LDRSTR,
80 PROBES_T16_ADR,
81 PROBES_T16_LDMSTM,
82 PROBES_T16_BRANCH_COND,
83 PROBES_T16_BRANCH,
84 NUM_PROBES_T16_ACTIONS
85};
86
87extern const union decode_item probes_decode_thumb32_table[];
88extern const union decode_item probes_decode_thumb16_table[];
89
90enum probes_insn __kprobes
91thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
92 bool emulate, const union decode_action *actions);
93enum probes_insn __kprobes
94thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
95 bool emulate, const union decode_action *actions);
96
97#endif
diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c
deleted file mode 100644
index a8ab540d7e73..000000000000
--- a/arch/arm/kernel/probes.c
+++ /dev/null
@@ -1,456 +0,0 @@
1/*
2 * arch/arm/kernel/probes.c
3 *
4 * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
5 *
6 * Some contents moved here from arch/arm/include/asm/kprobes-arm.c which is
7 * Copyright (C) 2006, 2007 Motorola Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/kernel.h>
15#include <linux/types.h>
16#include <asm/system_info.h>
17#include <asm/ptrace.h>
18#include <linux/bug.h>
19
20#include "probes.h"
21
22
23#ifndef find_str_pc_offset
24
25/*
26 * For STR and STM instructions, an ARM core may choose to use either
27 * a +8 or a +12 displacement from the current instruction's address.
28 * Whichever value is chosen for a given core, it must be the same for
29 * both instructions and may not change. This function measures it.
30 */
31
32int str_pc_offset;
33
34void __init find_str_pc_offset(void)
35{
36 int addr, scratch, ret;
37
38 __asm__ (
39 "sub %[ret], pc, #4 \n\t"
40 "str pc, %[addr] \n\t"
41 "ldr %[scr], %[addr] \n\t"
42 "sub %[ret], %[scr], %[ret] \n\t"
43 : [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr));
44
45 str_pc_offset = ret;
46}
47
48#endif /* !find_str_pc_offset */
49
50
51#ifndef test_load_write_pc_interworking
52
53bool load_write_pc_interworks;
54
55void __init test_load_write_pc_interworking(void)
56{
57 int arch = cpu_architecture();
58 BUG_ON(arch == CPU_ARCH_UNKNOWN);
59 load_write_pc_interworks = arch >= CPU_ARCH_ARMv5T;
60}
61
62#endif /* !test_load_write_pc_interworking */
63
64
65#ifndef test_alu_write_pc_interworking
66
67bool alu_write_pc_interworks;
68
69void __init test_alu_write_pc_interworking(void)
70{
71 int arch = cpu_architecture();
72 BUG_ON(arch == CPU_ARCH_UNKNOWN);
73 alu_write_pc_interworks = arch >= CPU_ARCH_ARMv7;
74}
75
76#endif /* !test_alu_write_pc_interworking */
77
78
79void __init arm_probes_decode_init(void)
80{
81 find_str_pc_offset();
82 test_load_write_pc_interworking();
83 test_alu_write_pc_interworking();
84}
85
86
87static unsigned long __kprobes __check_eq(unsigned long cpsr)
88{
89 return cpsr & PSR_Z_BIT;
90}
91
92static unsigned long __kprobes __check_ne(unsigned long cpsr)
93{
94 return (~cpsr) & PSR_Z_BIT;
95}
96
97static unsigned long __kprobes __check_cs(unsigned long cpsr)
98{
99 return cpsr & PSR_C_BIT;
100}
101
102static unsigned long __kprobes __check_cc(unsigned long cpsr)
103{
104 return (~cpsr) & PSR_C_BIT;
105}
106
107static unsigned long __kprobes __check_mi(unsigned long cpsr)
108{
109 return cpsr & PSR_N_BIT;
110}
111
112static unsigned long __kprobes __check_pl(unsigned long cpsr)
113{
114 return (~cpsr) & PSR_N_BIT;
115}
116
117static unsigned long __kprobes __check_vs(unsigned long cpsr)
118{
119 return cpsr & PSR_V_BIT;
120}
121
122static unsigned long __kprobes __check_vc(unsigned long cpsr)
123{
124 return (~cpsr) & PSR_V_BIT;
125}
126
127static unsigned long __kprobes __check_hi(unsigned long cpsr)
128{
129 cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
130 return cpsr & PSR_C_BIT;
131}
132
133static unsigned long __kprobes __check_ls(unsigned long cpsr)
134{
135 cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
136 return (~cpsr) & PSR_C_BIT;
137}
138
139static unsigned long __kprobes __check_ge(unsigned long cpsr)
140{
141 cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
142 return (~cpsr) & PSR_N_BIT;
143}
144
145static unsigned long __kprobes __check_lt(unsigned long cpsr)
146{
147 cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
148 return cpsr & PSR_N_BIT;
149}
150
151static unsigned long __kprobes __check_gt(unsigned long cpsr)
152{
153 unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
154 temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
155 return (~temp) & PSR_N_BIT;
156}
157
158static unsigned long __kprobes __check_le(unsigned long cpsr)
159{
160 unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
161 temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
162 return temp & PSR_N_BIT;
163}
164
165static unsigned long __kprobes __check_al(unsigned long cpsr)
166{
167 return true;
168}
169
170probes_check_cc * const probes_condition_checks[16] = {
171 &__check_eq, &__check_ne, &__check_cs, &__check_cc,
172 &__check_mi, &__check_pl, &__check_vs, &__check_vc,
173 &__check_hi, &__check_ls, &__check_ge, &__check_lt,
174 &__check_gt, &__check_le, &__check_al, &__check_al
175};
176
177
178void __kprobes probes_simulate_nop(probes_opcode_t opcode,
179 struct arch_probes_insn *asi,
180 struct pt_regs *regs)
181{
182}
183
184void __kprobes probes_emulate_none(probes_opcode_t opcode,
185 struct arch_probes_insn *asi,
186 struct pt_regs *regs)
187{
188 asi->insn_fn();
189}
190
191/*
192 * Prepare an instruction slot to receive an instruction for emulating.
193 * This is done by placing a subroutine return after the location where the
194 * instruction will be placed. We also modify ARM instructions to be
195 * unconditional as the condition code will already be checked before any
196 * emulation handler is called.
197 */
198static probes_opcode_t __kprobes
199prepare_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
200 bool thumb)
201{
202#ifdef CONFIG_THUMB2_KERNEL
203 if (thumb) {
204 u16 *thumb_insn = (u16 *)asi->insn;
205 /* Thumb bx lr */
206 thumb_insn[1] = __opcode_to_mem_thumb16(0x4770);
207 thumb_insn[2] = __opcode_to_mem_thumb16(0x4770);
208 return insn;
209 }
210 asi->insn[1] = __opcode_to_mem_arm(0xe12fff1e); /* ARM bx lr */
211#else
212 asi->insn[1] = __opcode_to_mem_arm(0xe1a0f00e); /* mov pc, lr */
213#endif
214 /* Make an ARM instruction unconditional */
215 if (insn < 0xe0000000)
216 insn = (insn | 0xe0000000) & ~0x10000000;
217 return insn;
218}
219
220/*
221 * Write a (probably modified) instruction into the slot previously prepared by
222 * prepare_emulated_insn
223 */
224static void __kprobes
225set_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
226 bool thumb)
227{
228#ifdef CONFIG_THUMB2_KERNEL
229 if (thumb) {
230 u16 *ip = (u16 *)asi->insn;
231 if (is_wide_instruction(insn))
232 *ip++ = __opcode_to_mem_thumb16(insn >> 16);
233 *ip++ = __opcode_to_mem_thumb16(insn);
234 return;
235 }
236#endif
237 asi->insn[0] = __opcode_to_mem_arm(insn);
238}
239
240/*
241 * When we modify the register numbers encoded in an instruction to be emulated,
242 * the new values come from this define. For ARM and 32-bit Thumb instructions
243 * this gives...
244 *
245 * bit position 16 12 8 4 0
246 * ---------------+---+---+---+---+---+
247 * register r2 r0 r1 -- r3
248 */
249#define INSN_NEW_BITS 0x00020103
250
251/* Each nibble has same value as that at INSN_NEW_BITS bit 16 */
252#define INSN_SAMEAS16_BITS 0x22222222
253
254/*
255 * Validate and modify each of the registers encoded in an instruction.
256 *
257 * Each nibble in regs contains a value from enum decode_reg_type. For each
258 * non-zero value, the corresponding nibble in pinsn is validated and modified
259 * according to the type.
260 */
261static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs, bool modify)
262{
263 probes_opcode_t insn = *pinsn;
264 probes_opcode_t mask = 0xf; /* Start at least significant nibble */
265
266 for (; regs != 0; regs >>= 4, mask <<= 4) {
267
268 probes_opcode_t new_bits = INSN_NEW_BITS;
269
270 switch (regs & 0xf) {
271
272 case REG_TYPE_NONE:
273 /* Nibble not a register, skip to next */
274 continue;
275
276 case REG_TYPE_ANY:
277 /* Any register is allowed */
278 break;
279
280 case REG_TYPE_SAMEAS16:
281 /* Replace register with same as at bit position 16 */
282 new_bits = INSN_SAMEAS16_BITS;
283 break;
284
285 case REG_TYPE_SP:
286 /* Only allow SP (R13) */
287 if ((insn ^ 0xdddddddd) & mask)
288 goto reject;
289 break;
290
291 case REG_TYPE_PC:
292 /* Only allow PC (R15) */
293 if ((insn ^ 0xffffffff) & mask)
294 goto reject;
295 break;
296
297 case REG_TYPE_NOSP:
298 /* Reject SP (R13) */
299 if (((insn ^ 0xdddddddd) & mask) == 0)
300 goto reject;
301 break;
302
303 case REG_TYPE_NOSPPC:
304 case REG_TYPE_NOSPPCX:
305 /* Reject SP and PC (R13 and R15) */
306 if (((insn ^ 0xdddddddd) & 0xdddddddd & mask) == 0)
307 goto reject;
308 break;
309
310 case REG_TYPE_NOPCWB:
311 if (!is_writeback(insn))
312 break; /* No writeback, so any register is OK */
313 /* fall through... */
314 case REG_TYPE_NOPC:
315 case REG_TYPE_NOPCX:
316 /* Reject PC (R15) */
317 if (((insn ^ 0xffffffff) & mask) == 0)
318 goto reject;
319 break;
320 }
321
322 /* Replace value of nibble with new register number... */
323 insn &= ~mask;
324 insn |= new_bits & mask;
325 }
326
327 if (modify)
328 *pinsn = insn;
329
330 return true;
331
332reject:
333 return false;
334}
335
336static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
337 [DECODE_TYPE_TABLE] = sizeof(struct decode_table),
338 [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom),
339 [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate),
340 [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate),
341 [DECODE_TYPE_OR] = sizeof(struct decode_or),
342 [DECODE_TYPE_REJECT] = sizeof(struct decode_reject)
343};
344
345/*
346 * probes_decode_insn operates on data tables in order to decode an ARM
347 * architecture instruction onto which a kprobe has been placed.
348 *
349 * These instruction decoding tables are a concatenation of entries each
350 * of which consist of one of the following structs:
351 *
352 * decode_table
353 * decode_custom
354 * decode_simulate
355 * decode_emulate
356 * decode_or
357 * decode_reject
358 *
359 * Each of these starts with a struct decode_header which has the following
360 * fields:
361 *
362 * type_regs
363 * mask
364 * value
365 *
366 * The least significant DECODE_TYPE_BITS of type_regs contains a value
367 * from enum decode_type, this indicates which of the decode_* structs
368 * the entry contains. The value DECODE_TYPE_END indicates the end of the
369 * table.
370 *
371 * When the table is parsed, each entry is checked in turn to see if it
372 * matches the instruction to be decoded using the test:
373 *
374 * (insn & mask) == value
375 *
376 * If no match is found before the end of the table is reached then decoding
377 * fails with INSN_REJECTED.
378 *
379 * When a match is found, decode_regs() is called to validate and modify each
380 * of the registers encoded in the instruction; the data it uses to do this
381 * is (type_regs >> DECODE_TYPE_BITS). A validation failure will cause decoding
382 * to fail with INSN_REJECTED.
383 *
384 * Once the instruction has passed the above tests, further processing
385 * depends on the type of the table entry's decode struct.
386 *
387 */
388int __kprobes
389probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
390 const union decode_item *table, bool thumb,
391 bool emulate, const union decode_action *actions)
392{
393 const struct decode_header *h = (struct decode_header *)table;
394 const struct decode_header *next;
395 bool matched = false;
396
397 if (emulate)
398 insn = prepare_emulated_insn(insn, asi, thumb);
399
400 for (;; h = next) {
401 enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
402 u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS;
403
404 if (type == DECODE_TYPE_END)
405 return INSN_REJECTED;
406
407 next = (struct decode_header *)
408 ((uintptr_t)h + decode_struct_sizes[type]);
409
410 if (!matched && (insn & h->mask.bits) != h->value.bits)
411 continue;
412
413 if (!decode_regs(&insn, regs, emulate))
414 return INSN_REJECTED;
415
416 switch (type) {
417
418 case DECODE_TYPE_TABLE: {
419 struct decode_table *d = (struct decode_table *)h;
420 next = (struct decode_header *)d->table.table;
421 break;
422 }
423
424 case DECODE_TYPE_CUSTOM: {
425 struct decode_custom *d = (struct decode_custom *)h;
426 return actions[d->decoder.action].decoder(insn, asi, h);
427 }
428
429 case DECODE_TYPE_SIMULATE: {
430 struct decode_simulate *d = (struct decode_simulate *)h;
431 asi->insn_handler = actions[d->handler.action].handler;
432 return INSN_GOOD_NO_SLOT;
433 }
434
435 case DECODE_TYPE_EMULATE: {
436 struct decode_emulate *d = (struct decode_emulate *)h;
437
438 if (!emulate)
439 return actions[d->handler.action].decoder(insn,
440 asi, h);
441
442 asi->insn_handler = actions[d->handler.action].handler;
443 set_emulated_insn(insn, asi, thumb);
444 return INSN_GOOD;
445 }
446
447 case DECODE_TYPE_OR:
448 matched = true;
449 break;
450
451 case DECODE_TYPE_REJECT:
452 default:
453 return INSN_REJECTED;
454 }
455 }
456}
diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h
deleted file mode 100644
index dba9f2466a93..000000000000
--- a/arch/arm/kernel/probes.h
+++ /dev/null
@@ -1,407 +0,0 @@
1/*
2 * arch/arm/kernel/probes.h
3 *
4 * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
5 *
6 * Some contents moved here from arch/arm/include/asm/kprobes.h which is
7 * Copyright (C) 2006, 2007 Motorola Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 */
18
19#ifndef _ARM_KERNEL_PROBES_H
20#define _ARM_KERNEL_PROBES_H
21
22#include <linux/types.h>
23#include <linux/stddef.h>
24#include <asm/probes.h>
25
26void __init arm_probes_decode_init(void);
27
28extern probes_check_cc * const probes_condition_checks[16];
29
30#if __LINUX_ARM_ARCH__ >= 7
31
32/* str_pc_offset is architecturally defined from ARMv7 onwards */
33#define str_pc_offset 8
34#define find_str_pc_offset()
35
36#else /* __LINUX_ARM_ARCH__ < 7 */
37
38/* We need a run-time check to determine str_pc_offset */
39extern int str_pc_offset;
40void __init find_str_pc_offset(void);
41
42#endif
43
44
45/*
46 * Update ITSTATE after normal execution of an IT block instruction.
47 *
48 * The 8 IT state bits are split into two parts in CPSR:
49 * ITSTATE<1:0> are in CPSR<26:25>
50 * ITSTATE<7:2> are in CPSR<15:10>
51 */
52static inline unsigned long it_advance(unsigned long cpsr)
53 {
54 if ((cpsr & 0x06000400) == 0) {
55 /* ITSTATE<2:0> == 0 means end of IT block, so clear IT state */
56 cpsr &= ~PSR_IT_MASK;
57 } else {
58 /* We need to shift left ITSTATE<4:0> */
59 const unsigned long mask = 0x06001c00; /* Mask ITSTATE<4:0> */
60 unsigned long it = cpsr & mask;
61 it <<= 1;
62 it |= it >> (27 - 10); /* Carry ITSTATE<2> to correct place */
63 it &= mask;
64 cpsr &= ~mask;
65 cpsr |= it;
66 }
67 return cpsr;
68}
69
70static inline void __kprobes bx_write_pc(long pcv, struct pt_regs *regs)
71{
72 long cpsr = regs->ARM_cpsr;
73 if (pcv & 0x1) {
74 cpsr |= PSR_T_BIT;
75 pcv &= ~0x1;
76 } else {
77 cpsr &= ~PSR_T_BIT;
78 pcv &= ~0x2; /* Avoid UNPREDICTABLE address allignment */
79 }
80 regs->ARM_cpsr = cpsr;
81 regs->ARM_pc = pcv;
82}
83
84
85#if __LINUX_ARM_ARCH__ >= 6
86
87/* Kernels built for >= ARMv6 should never run on <= ARMv5 hardware, so... */
88#define load_write_pc_interworks true
89#define test_load_write_pc_interworking()
90
91#else /* __LINUX_ARM_ARCH__ < 6 */
92
93/* We need run-time testing to determine if load_write_pc() should interwork. */
94extern bool load_write_pc_interworks;
95void __init test_load_write_pc_interworking(void);
96
97#endif
98
99static inline void __kprobes load_write_pc(long pcv, struct pt_regs *regs)
100{
101 if (load_write_pc_interworks)
102 bx_write_pc(pcv, regs);
103 else
104 regs->ARM_pc = pcv;
105}
106
107
108#if __LINUX_ARM_ARCH__ >= 7
109
110#define alu_write_pc_interworks true
111#define test_alu_write_pc_interworking()
112
113#elif __LINUX_ARM_ARCH__ <= 5
114
115/* Kernels built for <= ARMv5 should never run on >= ARMv6 hardware, so... */
116#define alu_write_pc_interworks false
117#define test_alu_write_pc_interworking()
118
119#else /* __LINUX_ARM_ARCH__ == 6 */
120
121/* We could be an ARMv6 binary on ARMv7 hardware so we need a run-time check. */
122extern bool alu_write_pc_interworks;
123void __init test_alu_write_pc_interworking(void);
124
125#endif /* __LINUX_ARM_ARCH__ == 6 */
126
127static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs)
128{
129 if (alu_write_pc_interworks)
130 bx_write_pc(pcv, regs);
131 else
132 regs->ARM_pc = pcv;
133}
134
135
136/*
137 * Test if load/store instructions writeback the address register.
138 * if P (bit 24) == 0 or W (bit 21) == 1
139 */
140#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000)
141
142/*
143 * The following definitions and macros are used to build instruction
144 * decoding tables for use by probes_decode_insn.
145 *
146 * These tables are a concatenation of entries each of which consist of one of
147 * the decode_* structs. All of the fields in every type of decode structure
148 * are of the union type decode_item, therefore the entire decode table can be
149 * viewed as an array of these and declared like:
150 *
151 * static const union decode_item table_name[] = {};
152 *
153 * In order to construct each entry in the table, macros are used to
154 * initialise a number of sequential decode_item values in a layout which
155 * matches the relevant struct. E.g. DECODE_SIMULATE initialise a struct
156 * decode_simulate by initialising four decode_item objects like this...
157 *
158 * {.bits = _type},
159 * {.bits = _mask},
160 * {.bits = _value},
161 * {.action = _handler},
162 *
163 * Initialising a specified member of the union means that the compiler
164 * will produce a warning if the argument is of an incorrect type.
165 *
166 * Below is a list of each of the macros used to initialise entries and a
167 * description of the action performed when that entry is matched to an
168 * instruction. A match is found when (instruction & mask) == value.
169 *
170 * DECODE_TABLE(mask, value, table)
171 * Instruction decoding jumps to parsing the new sub-table 'table'.
172 *
173 * DECODE_CUSTOM(mask, value, decoder)
174 * The value of 'decoder' is used as an index into the array of
175 * action functions, and the retrieved decoder function is invoked
176 * to complete decoding of the instruction.
177 *
178 * DECODE_SIMULATE(mask, value, handler)
179 * The probes instruction handler is set to the value found by
180 * indexing into the action array using the value of 'handler'. This
181 * will be used to simulate the instruction when the probe is hit.
182 * Decoding returns with INSN_GOOD_NO_SLOT.
183 *
184 * DECODE_EMULATE(mask, value, handler)
185 * The probes instruction handler is set to the value found by
186 * indexing into the action array using the value of 'handler'. This
187 * will be used to emulate the instruction when the probe is hit. The
188 * modified instruction (see below) is placed in the probes instruction
189 * slot so it may be called by the emulation code. Decoding returns
190 * with INSN_GOOD.
191 *
192 * DECODE_REJECT(mask, value)
193 * Instruction decoding fails with INSN_REJECTED
194 *
195 * DECODE_OR(mask, value)
196 * This allows the mask/value test of multiple table entries to be
197 * logically ORed. Once an 'or' entry is matched the decoding action to
198 * be performed is that of the next entry which isn't an 'or'. E.g.
199 *
200 * DECODE_OR (mask1, value1)
201 * DECODE_OR (mask2, value2)
202 * DECODE_SIMULATE (mask3, value3, simulation_handler)
203 *
204 * This means that if any of the three mask/value pairs match the
205 * instruction being decoded, then 'simulation_handler' will be used
206 * for it.
207 *
208 * Both the SIMULATE and EMULATE macros have a second form which take an
209 * additional 'regs' argument.
210 *
211 * DECODE_SIMULATEX(mask, value, handler, regs)
212 * DECODE_EMULATEX (mask, value, handler, regs)
213 *
214 * These are used to specify what kind of CPU register is encoded in each of the
215 * least significant 5 nibbles of the instruction being decoded. The regs value
216 * is specified using the REGS macro, this takes any of the REG_TYPE_* values
217 * from enum decode_reg_type as arguments; only the '*' part of the name is
218 * given. E.g.
219 *
220 * REGS(0, ANY, NOPC, 0, ANY)
221 *
222 * This indicates an instruction is encoded like:
223 *
224 * bits 19..16 ignore
225 * bits 15..12 any register allowed here
226 * bits 11.. 8 any register except PC allowed here
227 * bits 7.. 4 ignore
228 * bits 3.. 0 any register allowed here
229 *
230 * This register specification is checked after a decode table entry is found to
231 * match an instruction (through the mask/value test). Any invalid register then
232 * found in the instruction will cause decoding to fail with INSN_REJECTED. In
233 * the above example this would happen if bits 11..8 of the instruction were
234 * 1111, indicating R15 or PC.
235 *
236 * As well as checking for legal combinations of registers, this data is also
237 * used to modify the registers encoded in the instructions so that an
238 * emulation routines can use it. (See decode_regs() and INSN_NEW_BITS.)
239 *
240 * Here is a real example which matches ARM instructions of the form
241 * "AND <Rd>,<Rn>,<Rm>,<shift> <Rs>"
242 *
243 * DECODE_EMULATEX (0x0e000090, 0x00000010, PROBES_DATA_PROCESSING_REG,
244 * REGS(ANY, ANY, NOPC, 0, ANY)),
245 * ^ ^ ^ ^
246 * Rn Rd Rs Rm
247 *
248 * Decoding the instruction "AND R4, R5, R6, ASL R15" will be rejected because
249 * Rs == R15
250 *
251 * Decoding the instruction "AND R4, R5, R6, ASL R7" will be accepted and the
252 * instruction will be modified to "AND R0, R2, R3, ASL R1" and then placed into
253 * the kprobes instruction slot. This can then be called later by the handler
254 * function emulate_rd12rn16rm0rs8_rwflags (a pointer to which is retrieved from
255 * the indicated slot in the action array), in order to simulate the instruction.
256 */
257
258enum decode_type {
259 DECODE_TYPE_END,
260 DECODE_TYPE_TABLE,
261 DECODE_TYPE_CUSTOM,
262 DECODE_TYPE_SIMULATE,
263 DECODE_TYPE_EMULATE,
264 DECODE_TYPE_OR,
265 DECODE_TYPE_REJECT,
266 NUM_DECODE_TYPES /* Must be last enum */
267};
268
269#define DECODE_TYPE_BITS 4
270#define DECODE_TYPE_MASK ((1 << DECODE_TYPE_BITS) - 1)
271
272enum decode_reg_type {
273 REG_TYPE_NONE = 0, /* Not a register, ignore */
274 REG_TYPE_ANY, /* Any register allowed */
275 REG_TYPE_SAMEAS16, /* Register should be same as that at bits 19..16 */
276 REG_TYPE_SP, /* Register must be SP */
277 REG_TYPE_PC, /* Register must be PC */
278 REG_TYPE_NOSP, /* Register must not be SP */
279 REG_TYPE_NOSPPC, /* Register must not be SP or PC */
280 REG_TYPE_NOPC, /* Register must not be PC */
281 REG_TYPE_NOPCWB, /* No PC if load/store write-back flag also set */
282
283 /* The following types are used when the encoding for PC indicates
284 * another instruction form. This distiction only matters for test
285 * case coverage checks.
286 */
287 REG_TYPE_NOPCX, /* Register must not be PC */
288 REG_TYPE_NOSPPCX, /* Register must not be SP or PC */
289
290 /* Alias to allow '0' arg to be used in REGS macro. */
291 REG_TYPE_0 = REG_TYPE_NONE
292};
293
294#define REGS(r16, r12, r8, r4, r0) \
295 (((REG_TYPE_##r16) << 16) + \
296 ((REG_TYPE_##r12) << 12) + \
297 ((REG_TYPE_##r8) << 8) + \
298 ((REG_TYPE_##r4) << 4) + \
299 (REG_TYPE_##r0))
300
301union decode_item {
302 u32 bits;
303 const union decode_item *table;
304 int action;
305};
306
307struct decode_header;
308typedef enum probes_insn (probes_custom_decode_t)(probes_opcode_t,
309 struct arch_probes_insn *,
310 const struct decode_header *);
311
312union decode_action {
313 probes_insn_handler_t *handler;
314 probes_custom_decode_t *decoder;
315};
316
317#define DECODE_END \
318 {.bits = DECODE_TYPE_END}
319
320
321struct decode_header {
322 union decode_item type_regs;
323 union decode_item mask;
324 union decode_item value;
325};
326
327#define DECODE_HEADER(_type, _mask, _value, _regs) \
328 {.bits = (_type) | ((_regs) << DECODE_TYPE_BITS)}, \
329 {.bits = (_mask)}, \
330 {.bits = (_value)}
331
332
333struct decode_table {
334 struct decode_header header;
335 union decode_item table;
336};
337
338#define DECODE_TABLE(_mask, _value, _table) \
339 DECODE_HEADER(DECODE_TYPE_TABLE, _mask, _value, 0), \
340 {.table = (_table)}
341
342
343struct decode_custom {
344 struct decode_header header;
345 union decode_item decoder;
346};
347
348#define DECODE_CUSTOM(_mask, _value, _decoder) \
349 DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0), \
350 {.action = (_decoder)}
351
352
353struct decode_simulate {
354 struct decode_header header;
355 union decode_item handler;
356};
357
358#define DECODE_SIMULATEX(_mask, _value, _handler, _regs) \
359 DECODE_HEADER(DECODE_TYPE_SIMULATE, _mask, _value, _regs), \
360 {.action = (_handler)}
361
362#define DECODE_SIMULATE(_mask, _value, _handler) \
363 DECODE_SIMULATEX(_mask, _value, _handler, 0)
364
365
366struct decode_emulate {
367 struct decode_header header;
368 union decode_item handler;
369};
370
371#define DECODE_EMULATEX(_mask, _value, _handler, _regs) \
372 DECODE_HEADER(DECODE_TYPE_EMULATE, _mask, _value, _regs), \
373 {.action = (_handler)}
374
375#define DECODE_EMULATE(_mask, _value, _handler) \
376 DECODE_EMULATEX(_mask, _value, _handler, 0)
377
378
379struct decode_or {
380 struct decode_header header;
381};
382
383#define DECODE_OR(_mask, _value) \
384 DECODE_HEADER(DECODE_TYPE_OR, _mask, _value, 0)
385
386enum probes_insn {
387 INSN_REJECTED,
388 INSN_GOOD,
389 INSN_GOOD_NO_SLOT
390};
391
392struct decode_reject {
393 struct decode_header header;
394};
395
396#define DECODE_REJECT(_mask, _value) \
397 DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0)
398
399probes_insn_handler_t probes_simulate_nop;
400probes_insn_handler_t probes_emulate_none;
401
402int __kprobes
403probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
404 const union decode_item *table, bool thumb, bool emulate,
405 const union decode_action *actions);
406
407#endif
diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c
index 2835d35234ca..9a2f882a0a2d 100644
--- a/arch/arm/kernel/suspend.c
+++ b/arch/arm/kernel/suspend.c
@@ -14,10 +14,6 @@ extern int __cpu_suspend(unsigned long, int (*)(unsigned long), u32 cpuid);
14extern void cpu_resume_mmu(void); 14extern void cpu_resume_mmu(void);
15 15
16#ifdef CONFIG_MMU 16#ifdef CONFIG_MMU
17/*
18 * Hide the first two arguments to __cpu_suspend - these are an implementation
19 * detail which platform code shouldn't have to know about.
20 */
21int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) 17int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
22{ 18{
23 struct mm_struct *mm = current->active_mm; 19 struct mm_struct *mm = current->active_mm;
diff --git a/arch/arm/kernel/uprobes-arm.c b/arch/arm/kernel/uprobes-arm.c
deleted file mode 100644
index d3b655ff17da..000000000000
--- a/arch/arm/kernel/uprobes-arm.c
+++ /dev/null
@@ -1,234 +0,0 @@
1/*
2 * Copyright (C) 2012 Rabin Vincent <rabin at rab.in>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/kernel.h>
10#include <linux/types.h>
11#include <linux/stddef.h>
12#include <linux/wait.h>
13#include <linux/uprobes.h>
14#include <linux/module.h>
15
16#include "probes.h"
17#include "probes-arm.h"
18#include "uprobes.h"
19
20static int uprobes_substitute_pc(unsigned long *pinsn, u32 oregs)
21{
22 probes_opcode_t insn = __mem_to_opcode_arm(*pinsn);
23 probes_opcode_t temp;
24 probes_opcode_t mask;
25 int freereg;
26 u32 free = 0xffff;
27 u32 regs;
28
29 for (regs = oregs; regs; regs >>= 4, insn >>= 4) {
30 if ((regs & 0xf) == REG_TYPE_NONE)
31 continue;
32
33 free &= ~(1 << (insn & 0xf));
34 }
35
36 /* No PC, no problem */
37 if (free & (1 << 15))
38 return 15;
39
40 if (!free)
41 return -1;
42
43 /*
44 * fls instead of ffs ensures that for "ldrd r0, r1, [pc]" we would
45 * pick LR instead of R1.
46 */
47 freereg = free = fls(free) - 1;
48
49 temp = __mem_to_opcode_arm(*pinsn);
50 insn = temp;
51 regs = oregs;
52 mask = 0xf;
53
54 for (; regs; regs >>= 4, mask <<= 4, free <<= 4, temp >>= 4) {
55 if ((regs & 0xf) == REG_TYPE_NONE)
56 continue;
57
58 if ((temp & 0xf) != 15)
59 continue;
60
61 insn &= ~mask;
62 insn |= free & mask;
63 }
64
65 *pinsn = __opcode_to_mem_arm(insn);
66 return freereg;
67}
68
69static void uprobe_set_pc(struct arch_uprobe *auprobe,
70 struct arch_uprobe_task *autask,
71 struct pt_regs *regs)
72{
73 u32 pcreg = auprobe->pcreg;
74
75 autask->backup = regs->uregs[pcreg];
76 regs->uregs[pcreg] = regs->ARM_pc + 8;
77}
78
79static void uprobe_unset_pc(struct arch_uprobe *auprobe,
80 struct arch_uprobe_task *autask,
81 struct pt_regs *regs)
82{
83 /* PC will be taken care of by common code */
84 regs->uregs[auprobe->pcreg] = autask->backup;
85}
86
87static void uprobe_aluwrite_pc(struct arch_uprobe *auprobe,
88 struct arch_uprobe_task *autask,
89 struct pt_regs *regs)
90{
91 u32 pcreg = auprobe->pcreg;
92
93 alu_write_pc(regs->uregs[pcreg], regs);
94 regs->uregs[pcreg] = autask->backup;
95}
96
97static void uprobe_write_pc(struct arch_uprobe *auprobe,
98 struct arch_uprobe_task *autask,
99 struct pt_regs *regs)
100{
101 u32 pcreg = auprobe->pcreg;
102
103 load_write_pc(regs->uregs[pcreg], regs);
104 regs->uregs[pcreg] = autask->backup;
105}
106
107enum probes_insn
108decode_pc_ro(probes_opcode_t insn, struct arch_probes_insn *asi,
109 const struct decode_header *d)
110{
111 struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe,
112 asi);
113 struct decode_emulate *decode = (struct decode_emulate *) d;
114 u32 regs = decode->header.type_regs.bits >> DECODE_TYPE_BITS;
115 int reg;
116
117 reg = uprobes_substitute_pc(&auprobe->ixol[0], regs);
118 if (reg == 15)
119 return INSN_GOOD;
120
121 if (reg == -1)
122 return INSN_REJECTED;
123
124 auprobe->pcreg = reg;
125 auprobe->prehandler = uprobe_set_pc;
126 auprobe->posthandler = uprobe_unset_pc;
127
128 return INSN_GOOD;
129}
130
131enum probes_insn
132decode_wb_pc(probes_opcode_t insn, struct arch_probes_insn *asi,
133 const struct decode_header *d, bool alu)
134{
135 struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe,
136 asi);
137 enum probes_insn ret = decode_pc_ro(insn, asi, d);
138
139 if (((insn >> 12) & 0xf) == 15)
140 auprobe->posthandler = alu ? uprobe_aluwrite_pc
141 : uprobe_write_pc;
142
143 return ret;
144}
145
146enum probes_insn
147decode_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,
148 struct arch_probes_insn *asi,
149 const struct decode_header *d)
150{
151 return decode_wb_pc(insn, asi, d, true);
152}
153
154enum probes_insn
155decode_ldr(probes_opcode_t insn, struct arch_probes_insn *asi,
156 const struct decode_header *d)
157{
158 return decode_wb_pc(insn, asi, d, false);
159}
160
161enum probes_insn
162uprobe_decode_ldmstm(probes_opcode_t insn,
163 struct arch_probes_insn *asi,
164 const struct decode_header *d)
165{
166 struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe,
167 asi);
168 unsigned reglist = insn & 0xffff;
169 int rn = (insn >> 16) & 0xf;
170 int lbit = insn & (1 << 20);
171 unsigned used = reglist | (1 << rn);
172
173 if (rn == 15)
174 return INSN_REJECTED;
175
176 if (!(used & (1 << 15)))
177 return INSN_GOOD;
178
179 if (used & (1 << 14))
180 return INSN_REJECTED;
181
182 /* Use LR instead of PC */
183 insn ^= 0xc000;
184
185 auprobe->pcreg = 14;
186 auprobe->ixol[0] = __opcode_to_mem_arm(insn);
187
188 auprobe->prehandler = uprobe_set_pc;
189 if (lbit)
190 auprobe->posthandler = uprobe_write_pc;
191 else
192 auprobe->posthandler = uprobe_unset_pc;
193
194 return INSN_GOOD;
195}
196
197const union decode_action uprobes_probes_actions[] = {
198 [PROBES_EMULATE_NONE] = {.handler = probes_simulate_nop},
199 [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop},
200 [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop},
201 [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop},
202 [PROBES_BRANCH_IMM] = {.handler = simulate_blx1},
203 [PROBES_MRS] = {.handler = simulate_mrs},
204 [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx},
205 [PROBES_CLZ] = {.handler = probes_simulate_nop},
206 [PROBES_SATURATING_ARITHMETIC] = {.handler = probes_simulate_nop},
207 [PROBES_MUL1] = {.handler = probes_simulate_nop},
208 [PROBES_MUL2] = {.handler = probes_simulate_nop},
209 [PROBES_SWP] = {.handler = probes_simulate_nop},
210 [PROBES_LDRSTRD] = {.decoder = decode_pc_ro},
211 [PROBES_LOAD_EXTRA] = {.decoder = decode_pc_ro},
212 [PROBES_LOAD] = {.decoder = decode_ldr},
213 [PROBES_STORE_EXTRA] = {.decoder = decode_pc_ro},
214 [PROBES_STORE] = {.decoder = decode_pc_ro},
215 [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp},
216 [PROBES_DATA_PROCESSING_REG] = {
217 .decoder = decode_rd12rn16rm0rs8_rwflags},
218 [PROBES_DATA_PROCESSING_IMM] = {
219 .decoder = decode_rd12rn16rm0rs8_rwflags},
220 [PROBES_MOV_HALFWORD] = {.handler = probes_simulate_nop},
221 [PROBES_SEV] = {.handler = probes_simulate_nop},
222 [PROBES_WFE] = {.handler = probes_simulate_nop},
223 [PROBES_SATURATE] = {.handler = probes_simulate_nop},
224 [PROBES_REV] = {.handler = probes_simulate_nop},
225 [PROBES_MMI] = {.handler = probes_simulate_nop},
226 [PROBES_PACK] = {.handler = probes_simulate_nop},
227 [PROBES_EXTEND] = {.handler = probes_simulate_nop},
228 [PROBES_EXTEND_ADD] = {.handler = probes_simulate_nop},
229 [PROBES_MUL_ADD_LONG] = {.handler = probes_simulate_nop},
230 [PROBES_MUL_ADD] = {.handler = probes_simulate_nop},
231 [PROBES_BITFIELD] = {.handler = probes_simulate_nop},
232 [PROBES_BRANCH] = {.handler = simulate_bbl},
233 [PROBES_LDMSTM] = {.decoder = uprobe_decode_ldmstm}
234};
diff --git a/arch/arm/kernel/uprobes.c b/arch/arm/kernel/uprobes.c
deleted file mode 100644
index 56adf9c1fde0..000000000000
--- a/arch/arm/kernel/uprobes.c
+++ /dev/null
@@ -1,230 +0,0 @@
1/*
2 * Copyright (C) 2012 Rabin Vincent <rabin at rab.in>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/kernel.h>
10#include <linux/stddef.h>
11#include <linux/errno.h>
12#include <linux/highmem.h>
13#include <linux/sched.h>
14#include <linux/uprobes.h>
15#include <linux/notifier.h>
16
17#include <asm/opcodes.h>
18#include <asm/traps.h>
19
20#include "probes.h"
21#include "probes-arm.h"
22#include "uprobes.h"
23
24#define UPROBE_TRAP_NR UINT_MAX
25
26bool is_swbp_insn(uprobe_opcode_t *insn)
27{
28 return (__mem_to_opcode_arm(*insn) & 0x0fffffff) ==
29 (UPROBE_SWBP_ARM_INSN & 0x0fffffff);
30}
31
32int set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm,
33 unsigned long vaddr)
34{
35 return uprobe_write_opcode(mm, vaddr,
36 __opcode_to_mem_arm(auprobe->bpinsn));
37}
38
39bool arch_uprobe_ignore(struct arch_uprobe *auprobe, struct pt_regs *regs)
40{
41 if (!auprobe->asi.insn_check_cc(regs->ARM_cpsr)) {
42 regs->ARM_pc += 4;
43 return true;
44 }
45
46 return false;
47}
48
49bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
50{
51 probes_opcode_t opcode;
52
53 if (!auprobe->simulate)
54 return false;
55
56 opcode = __mem_to_opcode_arm(*(unsigned int *) auprobe->insn);
57
58 auprobe->asi.insn_singlestep(opcode, &auprobe->asi, regs);
59
60 return true;
61}
62
63unsigned long
64arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
65 struct pt_regs *regs)
66{
67 unsigned long orig_ret_vaddr;
68
69 orig_ret_vaddr = regs->ARM_lr;
70 /* Replace the return addr with trampoline addr */
71 regs->ARM_lr = trampoline_vaddr;
72 return orig_ret_vaddr;
73}
74
75int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
76 unsigned long addr)
77{
78 unsigned int insn;
79 unsigned int bpinsn;
80 enum probes_insn ret;
81
82 /* Thumb not yet support */
83 if (addr & 0x3)
84 return -EINVAL;
85
86 insn = __mem_to_opcode_arm(*(unsigned int *)auprobe->insn);
87 auprobe->ixol[0] = __opcode_to_mem_arm(insn);
88 auprobe->ixol[1] = __opcode_to_mem_arm(UPROBE_SS_ARM_INSN);
89
90 ret = arm_probes_decode_insn(insn, &auprobe->asi, false,
91 uprobes_probes_actions);
92 switch (ret) {
93 case INSN_REJECTED:
94 return -EINVAL;
95
96 case INSN_GOOD_NO_SLOT:
97 auprobe->simulate = true;
98 break;
99
100 case INSN_GOOD:
101 default:
102 break;
103 }
104
105 bpinsn = UPROBE_SWBP_ARM_INSN & 0x0fffffff;
106 if (insn >= 0xe0000000)
107 bpinsn |= 0xe0000000; /* Unconditional instruction */
108 else
109 bpinsn |= insn & 0xf0000000; /* Copy condition from insn */
110
111 auprobe->bpinsn = bpinsn;
112
113 return 0;
114}
115
116void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
117 void *src, unsigned long len)
118{
119 void *xol_page_kaddr = kmap_atomic(page);
120 void *dst = xol_page_kaddr + (vaddr & ~PAGE_MASK);
121
122 preempt_disable();
123
124 /* Initialize the slot */
125 memcpy(dst, src, len);
126
127 /* flush caches (dcache/icache) */
128 flush_uprobe_xol_access(page, vaddr, dst, len);
129
130 preempt_enable();
131
132 kunmap_atomic(xol_page_kaddr);
133}
134
135
136int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
137{
138 struct uprobe_task *utask = current->utask;
139
140 if (auprobe->prehandler)
141 auprobe->prehandler(auprobe, &utask->autask, regs);
142
143 utask->autask.saved_trap_no = current->thread.trap_no;
144 current->thread.trap_no = UPROBE_TRAP_NR;
145 regs->ARM_pc = utask->xol_vaddr;
146
147 return 0;
148}
149
150int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
151{
152 struct uprobe_task *utask = current->utask;
153
154 WARN_ON_ONCE(current->thread.trap_no != UPROBE_TRAP_NR);
155
156 current->thread.trap_no = utask->autask.saved_trap_no;
157 regs->ARM_pc = utask->vaddr + 4;
158
159 if (auprobe->posthandler)
160 auprobe->posthandler(auprobe, &utask->autask, regs);
161
162 return 0;
163}
164
165bool arch_uprobe_xol_was_trapped(struct task_struct *t)
166{
167 if (t->thread.trap_no != UPROBE_TRAP_NR)
168 return true;
169
170 return false;
171}
172
173void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
174{
175 struct uprobe_task *utask = current->utask;
176
177 current->thread.trap_no = utask->autask.saved_trap_no;
178 instruction_pointer_set(regs, utask->vaddr);
179}
180
181int arch_uprobe_exception_notify(struct notifier_block *self,
182 unsigned long val, void *data)
183{
184 return NOTIFY_DONE;
185}
186
187static int uprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
188{
189 unsigned long flags;
190
191 local_irq_save(flags);
192 instr &= 0x0fffffff;
193 if (instr == (UPROBE_SWBP_ARM_INSN & 0x0fffffff))
194 uprobe_pre_sstep_notifier(regs);
195 else if (instr == (UPROBE_SS_ARM_INSN & 0x0fffffff))
196 uprobe_post_sstep_notifier(regs);
197 local_irq_restore(flags);
198
199 return 0;
200}
201
202unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
203{
204 return instruction_pointer(regs);
205}
206
207static struct undef_hook uprobes_arm_break_hook = {
208 .instr_mask = 0x0fffffff,
209 .instr_val = (UPROBE_SWBP_ARM_INSN & 0x0fffffff),
210 .cpsr_mask = MODE_MASK,
211 .cpsr_val = USR_MODE,
212 .fn = uprobe_trap_handler,
213};
214
215static struct undef_hook uprobes_arm_ss_hook = {
216 .instr_mask = 0x0fffffff,
217 .instr_val = (UPROBE_SS_ARM_INSN & 0x0fffffff),
218 .cpsr_mask = MODE_MASK,
219 .cpsr_val = USR_MODE,
220 .fn = uprobe_trap_handler,
221};
222
223static int arch_uprobes_init(void)
224{
225 register_undef_hook(&uprobes_arm_break_hook);
226 register_undef_hook(&uprobes_arm_ss_hook);
227
228 return 0;
229}
230device_initcall(arch_uprobes_init);
diff --git a/arch/arm/kernel/uprobes.h b/arch/arm/kernel/uprobes.h
deleted file mode 100644
index 1d0c12dfbd03..000000000000
--- a/arch/arm/kernel/uprobes.h
+++ /dev/null
@@ -1,35 +0,0 @@
1/*
2 * Copyright (C) 2012 Rabin Vincent <rabin at rab.in>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef __ARM_KERNEL_UPROBES_H
10#define __ARM_KERNEL_UPROBES_H
11
12enum probes_insn uprobe_decode_ldmstm(probes_opcode_t insn,
13 struct arch_probes_insn *asi,
14 const struct decode_header *d);
15
16enum probes_insn decode_ldr(probes_opcode_t insn,
17 struct arch_probes_insn *asi,
18 const struct decode_header *d);
19
20enum probes_insn
21decode_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,
22 struct arch_probes_insn *asi,
23 const struct decode_header *d);
24
25enum probes_insn
26decode_wb_pc(probes_opcode_t insn, struct arch_probes_insn *asi,
27 const struct decode_header *d, bool alu);
28
29enum probes_insn
30decode_pc_ro(probes_opcode_t insn, struct arch_probes_insn *asi,
31 const struct decode_header *d);
32
33extern const union decode_action uprobes_probes_actions[];
34
35#endif