hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/arch/powerpc/lib/test_emulate_step.c
....@@ -1,53 +1,57 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
2
- * Simple sanity test for emulate_step load/store instructions.
3
+ * Simple sanity tests for instruction emulation infrastructure.
34 *
45 * Copyright IBM Corp. 2016
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 as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version.
106 */
117
128 #define pr_fmt(fmt) "emulate_step_test: " fmt
139
1410 #include <linux/ptrace.h>
11
+#include <asm/cpu_has_feature.h>
1512 #include <asm/sstep.h>
1613 #include <asm/ppc-opcode.h>
14
+#include <asm/code-patching.h>
15
+#include <asm/inst.h>
1716
18
-#define IMM_L(i) ((uintptr_t)(i) & 0xffff)
17
+#define MAX_SUBTESTS 16
1918
20
-/*
21
- * Defined with TEST_ prefix so it does not conflict with other
22
- * definitions.
23
- */
24
-#define TEST_LD(r, base, i) (PPC_INST_LD | ___PPC_RT(r) | \
25
- ___PPC_RA(base) | IMM_L(i))
26
-#define TEST_LWZ(r, base, i) (PPC_INST_LWZ | ___PPC_RT(r) | \
27
- ___PPC_RA(base) | IMM_L(i))
28
-#define TEST_LWZX(t, a, b) (PPC_INST_LWZX | ___PPC_RT(t) | \
29
- ___PPC_RA(a) | ___PPC_RB(b))
30
-#define TEST_STD(r, base, i) (PPC_INST_STD | ___PPC_RS(r) | \
31
- ___PPC_RA(base) | ((i) & 0xfffc))
32
-#define TEST_LDARX(t, a, b, eh) (PPC_INST_LDARX | ___PPC_RT(t) | \
33
- ___PPC_RA(a) | ___PPC_RB(b) | \
34
- __PPC_EH(eh))
35
-#define TEST_STDCX(s, a, b) (PPC_INST_STDCX | ___PPC_RS(s) | \
36
- ___PPC_RA(a) | ___PPC_RB(b))
37
-#define TEST_LFSX(t, a, b) (PPC_INST_LFSX | ___PPC_RT(t) | \
38
- ___PPC_RA(a) | ___PPC_RB(b))
39
-#define TEST_STFSX(s, a, b) (PPC_INST_STFSX | ___PPC_RS(s) | \
40
- ___PPC_RA(a) | ___PPC_RB(b))
41
-#define TEST_LFDX(t, a, b) (PPC_INST_LFDX | ___PPC_RT(t) | \
42
- ___PPC_RA(a) | ___PPC_RB(b))
43
-#define TEST_STFDX(s, a, b) (PPC_INST_STFDX | ___PPC_RS(s) | \
44
- ___PPC_RA(a) | ___PPC_RB(b))
45
-#define TEST_LVX(t, a, b) (PPC_INST_LVX | ___PPC_RT(t) | \
46
- ___PPC_RA(a) | ___PPC_RB(b))
47
-#define TEST_STVX(s, a, b) (PPC_INST_STVX | ___PPC_RS(s) | \
48
- ___PPC_RA(a) | ___PPC_RB(b))
49
-#define TEST_LXVD2X(s, a, b) (PPC_INST_LXVD2X | VSX_XX1((s), R##a, R##b))
50
-#define TEST_STXVD2X(s, a, b) (PPC_INST_STXVD2X | VSX_XX1((s), R##a, R##b))
19
+#define IGNORE_GPR(n) (0x1UL << (n))
20
+#define IGNORE_XER (0x1UL << 32)
21
+#define IGNORE_CCR (0x1UL << 33)
22
+#define NEGATIVE_TEST (0x1UL << 63)
23
+
24
+#define TEST_PLD(r, base, i, pr) \
25
+ ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \
26
+ PPC_INST_PLD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
27
+
28
+#define TEST_PLWZ(r, base, i, pr) \
29
+ ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
30
+ PPC_RAW_LWZ(r, base, i))
31
+
32
+#define TEST_PSTD(r, base, i, pr) \
33
+ ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \
34
+ PPC_INST_PSTD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
35
+
36
+#define TEST_PLFS(r, base, i, pr) \
37
+ ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
38
+ PPC_INST_LFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
39
+
40
+#define TEST_PSTFS(r, base, i, pr) \
41
+ ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
42
+ PPC_INST_STFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
43
+
44
+#define TEST_PLFD(r, base, i, pr) \
45
+ ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
46
+ PPC_INST_LFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
47
+
48
+#define TEST_PSTFD(r, base, i, pr) \
49
+ ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
50
+ PPC_INST_STFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
51
+
52
+#define TEST_PADDI(t, a, i, pr) \
53
+ ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
54
+ PPC_RAW_ADDI(t, a, i))
5155
5256
5357 static void __init init_pt_regs(struct pt_regs *regs)
....@@ -72,9 +76,15 @@
7276 msr_cached = true;
7377 }
7478
75
-static void __init show_result(char *ins, char *result)
79
+static void __init show_result(char *mnemonic, char *result)
7680 {
77
- pr_info("%-14s : %s\n", ins, result);
81
+ pr_info("%-14s : %s\n", mnemonic, result);
82
+}
83
+
84
+static void __init show_result_with_descr(char *mnemonic, char *descr,
85
+ char *result)
86
+{
87
+ pr_info("%-14s : %-50s %s\n", mnemonic, descr, result);
7888 }
7989
8090 static void __init test_ld(void)
....@@ -87,12 +97,35 @@
8797 regs.gpr[3] = (unsigned long) &a;
8898
8999 /* ld r5, 0(r3) */
90
- stepped = emulate_step(&regs, TEST_LD(5, 3, 0));
100
+ stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LD(5, 3, 0)));
91101
92102 if (stepped == 1 && regs.gpr[5] == a)
93103 show_result("ld", "PASS");
94104 else
95105 show_result("ld", "FAIL");
106
+}
107
+
108
+static void __init test_pld(void)
109
+{
110
+ struct pt_regs regs;
111
+ unsigned long a = 0x23;
112
+ int stepped = -1;
113
+
114
+ if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
115
+ show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
116
+ return;
117
+ }
118
+
119
+ init_pt_regs(&regs);
120
+ regs.gpr[3] = (unsigned long)&a;
121
+
122
+ /* pld r5, 0(r3), 0 */
123
+ stepped = emulate_step(&regs, TEST_PLD(5, 3, 0, 0));
124
+
125
+ if (stepped == 1 && regs.gpr[5] == a)
126
+ show_result("pld", "PASS");
127
+ else
128
+ show_result("pld", "FAIL");
96129 }
97130
98131 static void __init test_lwz(void)
....@@ -105,12 +138,36 @@
105138 regs.gpr[3] = (unsigned long) &a;
106139
107140 /* lwz r5, 0(r3) */
108
- stepped = emulate_step(&regs, TEST_LWZ(5, 3, 0));
141
+ stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LWZ(5, 3, 0)));
109142
110143 if (stepped == 1 && regs.gpr[5] == a)
111144 show_result("lwz", "PASS");
112145 else
113146 show_result("lwz", "FAIL");
147
+}
148
+
149
+static void __init test_plwz(void)
150
+{
151
+ struct pt_regs regs;
152
+ unsigned int a = 0x4545;
153
+ int stepped = -1;
154
+
155
+ if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
156
+ show_result("plwz", "SKIP (!CPU_FTR_ARCH_31)");
157
+ return;
158
+ }
159
+
160
+ init_pt_regs(&regs);
161
+ regs.gpr[3] = (unsigned long)&a;
162
+
163
+ /* plwz r5, 0(r3), 0 */
164
+
165
+ stepped = emulate_step(&regs, TEST_PLWZ(5, 3, 0, 0));
166
+
167
+ if (stepped == 1 && regs.gpr[5] == a)
168
+ show_result("plwz", "PASS");
169
+ else
170
+ show_result("plwz", "FAIL");
114171 }
115172
116173 static void __init test_lwzx(void)
....@@ -125,7 +182,7 @@
125182 regs.gpr[5] = 0x8765;
126183
127184 /* lwzx r5, r3, r4 */
128
- stepped = emulate_step(&regs, TEST_LWZX(5, 3, 4));
185
+ stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LWZX(5, 3, 4)));
129186 if (stepped == 1 && regs.gpr[5] == a[2])
130187 show_result("lwzx", "PASS");
131188 else
....@@ -143,11 +200,34 @@
143200 regs.gpr[5] = 0x5678;
144201
145202 /* std r5, 0(r3) */
146
- stepped = emulate_step(&regs, TEST_STD(5, 3, 0));
147
- if (stepped == 1 || regs.gpr[5] == a)
203
+ stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STD(5, 3, 0)));
204
+ if (stepped == 1 && regs.gpr[5] == a)
148205 show_result("std", "PASS");
149206 else
150207 show_result("std", "FAIL");
208
+}
209
+
210
+static void __init test_pstd(void)
211
+{
212
+ struct pt_regs regs;
213
+ unsigned long a = 0x1234;
214
+ int stepped = -1;
215
+
216
+ if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
217
+ show_result("pstd", "SKIP (!CPU_FTR_ARCH_31)");
218
+ return;
219
+ }
220
+
221
+ init_pt_regs(&regs);
222
+ regs.gpr[3] = (unsigned long)&a;
223
+ regs.gpr[5] = 0x5678;
224
+
225
+ /* pstd r5, 0(r3), 0 */
226
+ stepped = emulate_step(&regs, TEST_PSTD(5, 3, 0, 0));
227
+ if (stepped == 1 || regs.gpr[5] == a)
228
+ show_result("pstd", "PASS");
229
+ else
230
+ show_result("pstd", "FAIL");
151231 }
152232
153233 static void __init test_ldarx_stdcx(void)
....@@ -168,7 +248,7 @@
168248 regs.gpr[5] = 0x5678;
169249
170250 /* ldarx r5, r3, r4, 0 */
171
- stepped = emulate_step(&regs, TEST_LDARX(5, 3, 4, 0));
251
+ stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LDARX(5, 3, 4, 0)));
172252
173253 /*
174254 * Don't touch 'a' here. Touching 'a' can do Load/store
....@@ -186,7 +266,7 @@
186266 regs.gpr[5] = 0x9ABC;
187267
188268 /* stdcx. r5, r3, r4 */
189
- stepped = emulate_step(&regs, TEST_STDCX(5, 3, 4));
269
+ stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STDCX(5, 3, 4)));
190270
191271 /*
192272 * Two possible scenarios that indicates successful emulation
....@@ -226,7 +306,7 @@
226306 regs.gpr[4] = 0;
227307
228308 /* lfsx frt10, r3, r4 */
229
- stepped = emulate_step(&regs, TEST_LFSX(10, 3, 4));
309
+ stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LFSX(10, 3, 4)));
230310
231311 if (stepped == 1)
232312 show_result("lfsx", "PASS");
....@@ -239,12 +319,59 @@
239319 c.a = 678.91;
240320
241321 /* stfsx frs10, r3, r4 */
242
- stepped = emulate_step(&regs, TEST_STFSX(10, 3, 4));
322
+ stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STFSX(10, 3, 4)));
243323
244324 if (stepped == 1 && c.b == cached_b)
245325 show_result("stfsx", "PASS");
246326 else
247327 show_result("stfsx", "FAIL");
328
+}
329
+
330
+static void __init test_plfs_pstfs(void)
331
+{
332
+ struct pt_regs regs;
333
+ union {
334
+ float a;
335
+ int b;
336
+ } c;
337
+ int cached_b;
338
+ int stepped = -1;
339
+
340
+ if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
341
+ show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
342
+ return;
343
+ }
344
+
345
+ init_pt_regs(&regs);
346
+
347
+
348
+ /*** plfs ***/
349
+
350
+ c.a = 123.45;
351
+ cached_b = c.b;
352
+
353
+ regs.gpr[3] = (unsigned long)&c.a;
354
+
355
+ /* plfs frt10, 0(r3), 0 */
356
+ stepped = emulate_step(&regs, TEST_PLFS(10, 3, 0, 0));
357
+
358
+ if (stepped == 1)
359
+ show_result("plfs", "PASS");
360
+ else
361
+ show_result("plfs", "FAIL");
362
+
363
+
364
+ /*** pstfs ***/
365
+
366
+ c.a = 678.91;
367
+
368
+ /* pstfs frs10, 0(r3), 0 */
369
+ stepped = emulate_step(&regs, TEST_PSTFS(10, 3, 0, 0));
370
+
371
+ if (stepped == 1 && c.b == cached_b)
372
+ show_result("pstfs", "PASS");
373
+ else
374
+ show_result("pstfs", "FAIL");
248375 }
249376
250377 static void __init test_lfdx_stfdx(void)
....@@ -269,7 +396,7 @@
269396 regs.gpr[4] = 0;
270397
271398 /* lfdx frt10, r3, r4 */
272
- stepped = emulate_step(&regs, TEST_LFDX(10, 3, 4));
399
+ stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LFDX(10, 3, 4)));
273400
274401 if (stepped == 1)
275402 show_result("lfdx", "PASS");
....@@ -282,12 +409,59 @@
282409 c.a = 987654.32;
283410
284411 /* stfdx frs10, r3, r4 */
285
- stepped = emulate_step(&regs, TEST_STFDX(10, 3, 4));
412
+ stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STFDX(10, 3, 4)));
286413
287414 if (stepped == 1 && c.b == cached_b)
288415 show_result("stfdx", "PASS");
289416 else
290417 show_result("stfdx", "FAIL");
418
+}
419
+
420
+static void __init test_plfd_pstfd(void)
421
+{
422
+ struct pt_regs regs;
423
+ union {
424
+ double a;
425
+ long b;
426
+ } c;
427
+ long cached_b;
428
+ int stepped = -1;
429
+
430
+ if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
431
+ show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
432
+ return;
433
+ }
434
+
435
+ init_pt_regs(&regs);
436
+
437
+
438
+ /*** plfd ***/
439
+
440
+ c.a = 123456.78;
441
+ cached_b = c.b;
442
+
443
+ regs.gpr[3] = (unsigned long)&c.a;
444
+
445
+ /* plfd frt10, 0(r3), 0 */
446
+ stepped = emulate_step(&regs, TEST_PLFD(10, 3, 0, 0));
447
+
448
+ if (stepped == 1)
449
+ show_result("plfd", "PASS");
450
+ else
451
+ show_result("plfd", "FAIL");
452
+
453
+
454
+ /*** pstfd ***/
455
+
456
+ c.a = 987654.32;
457
+
458
+ /* pstfd frs10, 0(r3), 0 */
459
+ stepped = emulate_step(&regs, TEST_PSTFD(10, 3, 0, 0));
460
+
461
+ if (stepped == 1 && c.b == cached_b)
462
+ show_result("pstfd", "PASS");
463
+ else
464
+ show_result("pstfd", "FAIL");
291465 }
292466 #else
293467 static void __init test_lfsx_stfsx(void)
....@@ -296,10 +470,22 @@
296470 show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)");
297471 }
298472
473
+static void __init test_plfs_pstfs(void)
474
+{
475
+ show_result("plfs", "SKIP (CONFIG_PPC_FPU is not set)");
476
+ show_result("pstfs", "SKIP (CONFIG_PPC_FPU is not set)");
477
+}
478
+
299479 static void __init test_lfdx_stfdx(void)
300480 {
301481 show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)");
302482 show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)");
483
+}
484
+
485
+static void __init test_plfd_pstfd(void)
486
+{
487
+ show_result("plfd", "SKIP (CONFIG_PPC_FPU is not set)");
488
+ show_result("pstfd", "SKIP (CONFIG_PPC_FPU is not set)");
303489 }
304490 #endif /* CONFIG_PPC_FPU */
305491
....@@ -328,7 +514,7 @@
328514 regs.gpr[4] = 0;
329515
330516 /* lvx vrt10, r3, r4 */
331
- stepped = emulate_step(&regs, TEST_LVX(10, 3, 4));
517
+ stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LVX(10, 3, 4)));
332518
333519 if (stepped == 1)
334520 show_result("lvx", "PASS");
....@@ -344,7 +530,7 @@
344530 c.b[3] = 498532;
345531
346532 /* stvx vrs10, r3, r4 */
347
- stepped = emulate_step(&regs, TEST_STVX(10, 3, 4));
533
+ stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STVX(10, 3, 4)));
348534
349535 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
350536 cached_b[2] == c.b[2] && cached_b[3] == c.b[3])
....@@ -385,7 +571,7 @@
385571 regs.gpr[4] = 0;
386572
387573 /* lxvd2x vsr39, r3, r4 */
388
- stepped = emulate_step(&regs, TEST_LXVD2X(39, 3, 4));
574
+ stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LXVD2X(39, R3, R4)));
389575
390576 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
391577 show_result("lxvd2x", "PASS");
....@@ -405,7 +591,7 @@
405591 c.b[3] = 4;
406592
407593 /* stxvd2x vsr39, r3, r4 */
408
- stepped = emulate_step(&regs, TEST_STXVD2X(39, 3, 4));
594
+ stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STXVD2X(39, R3, R4)));
409595
410596 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
411597 cached_b[2] == c.b[2] && cached_b[3] == c.b[3] &&
....@@ -426,17 +612,834 @@
426612 }
427613 #endif /* CONFIG_VSX */
428614
429
-static int __init test_emulate_step(void)
615
+static void __init run_tests_load_store(void)
430616 {
431617 test_ld();
618
+ test_pld();
432619 test_lwz();
620
+ test_plwz();
433621 test_lwzx();
434622 test_std();
623
+ test_pstd();
435624 test_ldarx_stdcx();
436625 test_lfsx_stfsx();
626
+ test_plfs_pstfs();
437627 test_lfdx_stfdx();
628
+ test_plfd_pstfd();
438629 test_lvx_stvx();
439630 test_lxvd2x_stxvd2x();
631
+}
632
+
633
+struct compute_test {
634
+ char *mnemonic;
635
+ unsigned long cpu_feature;
636
+ struct {
637
+ char *descr;
638
+ unsigned long flags;
639
+ struct ppc_inst instr;
640
+ struct pt_regs regs;
641
+ } subtests[MAX_SUBTESTS + 1];
642
+};
643
+
644
+/* Extreme values for si0||si1 (the MLS:D-form 34 bit immediate field) */
645
+#define SI_MIN BIT(33)
646
+#define SI_MAX (BIT(33) - 1)
647
+#define SI_UMAX (BIT(34) - 1)
648
+
649
+static struct compute_test compute_tests[] = {
650
+ {
651
+ .mnemonic = "nop",
652
+ .subtests = {
653
+ {
654
+ .descr = "R0 = LONG_MAX",
655
+ .instr = ppc_inst(PPC_INST_NOP),
656
+ .regs = {
657
+ .gpr[0] = LONG_MAX,
658
+ }
659
+ }
660
+ }
661
+ },
662
+ {
663
+ .mnemonic = "add",
664
+ .subtests = {
665
+ {
666
+ .descr = "RA = LONG_MIN, RB = LONG_MIN",
667
+ .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
668
+ .regs = {
669
+ .gpr[21] = LONG_MIN,
670
+ .gpr[22] = LONG_MIN,
671
+ }
672
+ },
673
+ {
674
+ .descr = "RA = LONG_MIN, RB = LONG_MAX",
675
+ .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
676
+ .regs = {
677
+ .gpr[21] = LONG_MIN,
678
+ .gpr[22] = LONG_MAX,
679
+ }
680
+ },
681
+ {
682
+ .descr = "RA = LONG_MAX, RB = LONG_MAX",
683
+ .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
684
+ .regs = {
685
+ .gpr[21] = LONG_MAX,
686
+ .gpr[22] = LONG_MAX,
687
+ }
688
+ },
689
+ {
690
+ .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
691
+ .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
692
+ .regs = {
693
+ .gpr[21] = ULONG_MAX,
694
+ .gpr[22] = ULONG_MAX,
695
+ }
696
+ },
697
+ {
698
+ .descr = "RA = ULONG_MAX, RB = 0x1",
699
+ .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
700
+ .regs = {
701
+ .gpr[21] = ULONG_MAX,
702
+ .gpr[22] = 0x1,
703
+ }
704
+ },
705
+ {
706
+ .descr = "RA = INT_MIN, RB = INT_MIN",
707
+ .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
708
+ .regs = {
709
+ .gpr[21] = INT_MIN,
710
+ .gpr[22] = INT_MIN,
711
+ }
712
+ },
713
+ {
714
+ .descr = "RA = INT_MIN, RB = INT_MAX",
715
+ .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
716
+ .regs = {
717
+ .gpr[21] = INT_MIN,
718
+ .gpr[22] = INT_MAX,
719
+ }
720
+ },
721
+ {
722
+ .descr = "RA = INT_MAX, RB = INT_MAX",
723
+ .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
724
+ .regs = {
725
+ .gpr[21] = INT_MAX,
726
+ .gpr[22] = INT_MAX,
727
+ }
728
+ },
729
+ {
730
+ .descr = "RA = UINT_MAX, RB = UINT_MAX",
731
+ .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
732
+ .regs = {
733
+ .gpr[21] = UINT_MAX,
734
+ .gpr[22] = UINT_MAX,
735
+ }
736
+ },
737
+ {
738
+ .descr = "RA = UINT_MAX, RB = 0x1",
739
+ .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
740
+ .regs = {
741
+ .gpr[21] = UINT_MAX,
742
+ .gpr[22] = 0x1,
743
+ }
744
+ }
745
+ }
746
+ },
747
+ {
748
+ .mnemonic = "add.",
749
+ .subtests = {
750
+ {
751
+ .descr = "RA = LONG_MIN, RB = LONG_MIN",
752
+ .flags = IGNORE_CCR,
753
+ .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
754
+ .regs = {
755
+ .gpr[21] = LONG_MIN,
756
+ .gpr[22] = LONG_MIN,
757
+ }
758
+ },
759
+ {
760
+ .descr = "RA = LONG_MIN, RB = LONG_MAX",
761
+ .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
762
+ .regs = {
763
+ .gpr[21] = LONG_MIN,
764
+ .gpr[22] = LONG_MAX,
765
+ }
766
+ },
767
+ {
768
+ .descr = "RA = LONG_MAX, RB = LONG_MAX",
769
+ .flags = IGNORE_CCR,
770
+ .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
771
+ .regs = {
772
+ .gpr[21] = LONG_MAX,
773
+ .gpr[22] = LONG_MAX,
774
+ }
775
+ },
776
+ {
777
+ .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
778
+ .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
779
+ .regs = {
780
+ .gpr[21] = ULONG_MAX,
781
+ .gpr[22] = ULONG_MAX,
782
+ }
783
+ },
784
+ {
785
+ .descr = "RA = ULONG_MAX, RB = 0x1",
786
+ .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
787
+ .regs = {
788
+ .gpr[21] = ULONG_MAX,
789
+ .gpr[22] = 0x1,
790
+ }
791
+ },
792
+ {
793
+ .descr = "RA = INT_MIN, RB = INT_MIN",
794
+ .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
795
+ .regs = {
796
+ .gpr[21] = INT_MIN,
797
+ .gpr[22] = INT_MIN,
798
+ }
799
+ },
800
+ {
801
+ .descr = "RA = INT_MIN, RB = INT_MAX",
802
+ .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
803
+ .regs = {
804
+ .gpr[21] = INT_MIN,
805
+ .gpr[22] = INT_MAX,
806
+ }
807
+ },
808
+ {
809
+ .descr = "RA = INT_MAX, RB = INT_MAX",
810
+ .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
811
+ .regs = {
812
+ .gpr[21] = INT_MAX,
813
+ .gpr[22] = INT_MAX,
814
+ }
815
+ },
816
+ {
817
+ .descr = "RA = UINT_MAX, RB = UINT_MAX",
818
+ .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
819
+ .regs = {
820
+ .gpr[21] = UINT_MAX,
821
+ .gpr[22] = UINT_MAX,
822
+ }
823
+ },
824
+ {
825
+ .descr = "RA = UINT_MAX, RB = 0x1",
826
+ .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
827
+ .regs = {
828
+ .gpr[21] = UINT_MAX,
829
+ .gpr[22] = 0x1,
830
+ }
831
+ }
832
+ }
833
+ },
834
+ {
835
+ .mnemonic = "addc",
836
+ .subtests = {
837
+ {
838
+ .descr = "RA = LONG_MIN, RB = LONG_MIN",
839
+ .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
840
+ .regs = {
841
+ .gpr[21] = LONG_MIN,
842
+ .gpr[22] = LONG_MIN,
843
+ }
844
+ },
845
+ {
846
+ .descr = "RA = LONG_MIN, RB = LONG_MAX",
847
+ .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
848
+ .regs = {
849
+ .gpr[21] = LONG_MIN,
850
+ .gpr[22] = LONG_MAX,
851
+ }
852
+ },
853
+ {
854
+ .descr = "RA = LONG_MAX, RB = LONG_MAX",
855
+ .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
856
+ .regs = {
857
+ .gpr[21] = LONG_MAX,
858
+ .gpr[22] = LONG_MAX,
859
+ }
860
+ },
861
+ {
862
+ .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
863
+ .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
864
+ .regs = {
865
+ .gpr[21] = ULONG_MAX,
866
+ .gpr[22] = ULONG_MAX,
867
+ }
868
+ },
869
+ {
870
+ .descr = "RA = ULONG_MAX, RB = 0x1",
871
+ .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
872
+ .regs = {
873
+ .gpr[21] = ULONG_MAX,
874
+ .gpr[22] = 0x1,
875
+ }
876
+ },
877
+ {
878
+ .descr = "RA = INT_MIN, RB = INT_MIN",
879
+ .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
880
+ .regs = {
881
+ .gpr[21] = INT_MIN,
882
+ .gpr[22] = INT_MIN,
883
+ }
884
+ },
885
+ {
886
+ .descr = "RA = INT_MIN, RB = INT_MAX",
887
+ .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
888
+ .regs = {
889
+ .gpr[21] = INT_MIN,
890
+ .gpr[22] = INT_MAX,
891
+ }
892
+ },
893
+ {
894
+ .descr = "RA = INT_MAX, RB = INT_MAX",
895
+ .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
896
+ .regs = {
897
+ .gpr[21] = INT_MAX,
898
+ .gpr[22] = INT_MAX,
899
+ }
900
+ },
901
+ {
902
+ .descr = "RA = UINT_MAX, RB = UINT_MAX",
903
+ .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
904
+ .regs = {
905
+ .gpr[21] = UINT_MAX,
906
+ .gpr[22] = UINT_MAX,
907
+ }
908
+ },
909
+ {
910
+ .descr = "RA = UINT_MAX, RB = 0x1",
911
+ .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
912
+ .regs = {
913
+ .gpr[21] = UINT_MAX,
914
+ .gpr[22] = 0x1,
915
+ }
916
+ },
917
+ {
918
+ .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
919
+ .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
920
+ .regs = {
921
+ .gpr[21] = LONG_MIN | (uint)INT_MIN,
922
+ .gpr[22] = LONG_MIN | (uint)INT_MIN,
923
+ }
924
+ }
925
+ }
926
+ },
927
+ {
928
+ .mnemonic = "addc.",
929
+ .subtests = {
930
+ {
931
+ .descr = "RA = LONG_MIN, RB = LONG_MIN",
932
+ .flags = IGNORE_CCR,
933
+ .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
934
+ .regs = {
935
+ .gpr[21] = LONG_MIN,
936
+ .gpr[22] = LONG_MIN,
937
+ }
938
+ },
939
+ {
940
+ .descr = "RA = LONG_MIN, RB = LONG_MAX",
941
+ .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
942
+ .regs = {
943
+ .gpr[21] = LONG_MIN,
944
+ .gpr[22] = LONG_MAX,
945
+ }
946
+ },
947
+ {
948
+ .descr = "RA = LONG_MAX, RB = LONG_MAX",
949
+ .flags = IGNORE_CCR,
950
+ .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
951
+ .regs = {
952
+ .gpr[21] = LONG_MAX,
953
+ .gpr[22] = LONG_MAX,
954
+ }
955
+ },
956
+ {
957
+ .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
958
+ .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
959
+ .regs = {
960
+ .gpr[21] = ULONG_MAX,
961
+ .gpr[22] = ULONG_MAX,
962
+ }
963
+ },
964
+ {
965
+ .descr = "RA = ULONG_MAX, RB = 0x1",
966
+ .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
967
+ .regs = {
968
+ .gpr[21] = ULONG_MAX,
969
+ .gpr[22] = 0x1,
970
+ }
971
+ },
972
+ {
973
+ .descr = "RA = INT_MIN, RB = INT_MIN",
974
+ .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
975
+ .regs = {
976
+ .gpr[21] = INT_MIN,
977
+ .gpr[22] = INT_MIN,
978
+ }
979
+ },
980
+ {
981
+ .descr = "RA = INT_MIN, RB = INT_MAX",
982
+ .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
983
+ .regs = {
984
+ .gpr[21] = INT_MIN,
985
+ .gpr[22] = INT_MAX,
986
+ }
987
+ },
988
+ {
989
+ .descr = "RA = INT_MAX, RB = INT_MAX",
990
+ .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
991
+ .regs = {
992
+ .gpr[21] = INT_MAX,
993
+ .gpr[22] = INT_MAX,
994
+ }
995
+ },
996
+ {
997
+ .descr = "RA = UINT_MAX, RB = UINT_MAX",
998
+ .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
999
+ .regs = {
1000
+ .gpr[21] = UINT_MAX,
1001
+ .gpr[22] = UINT_MAX,
1002
+ }
1003
+ },
1004
+ {
1005
+ .descr = "RA = UINT_MAX, RB = 0x1",
1006
+ .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1007
+ .regs = {
1008
+ .gpr[21] = UINT_MAX,
1009
+ .gpr[22] = 0x1,
1010
+ }
1011
+ },
1012
+ {
1013
+ .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
1014
+ .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1015
+ .regs = {
1016
+ .gpr[21] = LONG_MIN | (uint)INT_MIN,
1017
+ .gpr[22] = LONG_MIN | (uint)INT_MIN,
1018
+ }
1019
+ }
1020
+ }
1021
+ },
1022
+ {
1023
+ .mnemonic = "divde",
1024
+ .subtests = {
1025
+ {
1026
+ .descr = "RA = LONG_MIN, RB = LONG_MIN",
1027
+ .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1028
+ .regs = {
1029
+ .gpr[21] = LONG_MIN,
1030
+ .gpr[22] = LONG_MIN,
1031
+ }
1032
+ },
1033
+ {
1034
+ .descr = "RA = 1L, RB = 0",
1035
+ .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1036
+ .flags = IGNORE_GPR(20),
1037
+ .regs = {
1038
+ .gpr[21] = 1L,
1039
+ .gpr[22] = 0,
1040
+ }
1041
+ },
1042
+ {
1043
+ .descr = "RA = LONG_MIN, RB = LONG_MAX",
1044
+ .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1045
+ .regs = {
1046
+ .gpr[21] = LONG_MIN,
1047
+ .gpr[22] = LONG_MAX,
1048
+ }
1049
+ }
1050
+ }
1051
+ },
1052
+ {
1053
+ .mnemonic = "divde.",
1054
+ .subtests = {
1055
+ {
1056
+ .descr = "RA = LONG_MIN, RB = LONG_MIN",
1057
+ .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1058
+ .regs = {
1059
+ .gpr[21] = LONG_MIN,
1060
+ .gpr[22] = LONG_MIN,
1061
+ }
1062
+ },
1063
+ {
1064
+ .descr = "RA = 1L, RB = 0",
1065
+ .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1066
+ .flags = IGNORE_GPR(20),
1067
+ .regs = {
1068
+ .gpr[21] = 1L,
1069
+ .gpr[22] = 0,
1070
+ }
1071
+ },
1072
+ {
1073
+ .descr = "RA = LONG_MIN, RB = LONG_MAX",
1074
+ .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1075
+ .regs = {
1076
+ .gpr[21] = LONG_MIN,
1077
+ .gpr[22] = LONG_MAX,
1078
+ }
1079
+ }
1080
+ }
1081
+ },
1082
+ {
1083
+ .mnemonic = "divdeu",
1084
+ .subtests = {
1085
+ {
1086
+ .descr = "RA = LONG_MIN, RB = LONG_MIN",
1087
+ .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1088
+ .flags = IGNORE_GPR(20),
1089
+ .regs = {
1090
+ .gpr[21] = LONG_MIN,
1091
+ .gpr[22] = LONG_MIN,
1092
+ }
1093
+ },
1094
+ {
1095
+ .descr = "RA = 1L, RB = 0",
1096
+ .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1097
+ .flags = IGNORE_GPR(20),
1098
+ .regs = {
1099
+ .gpr[21] = 1L,
1100
+ .gpr[22] = 0,
1101
+ }
1102
+ },
1103
+ {
1104
+ .descr = "RA = LONG_MIN, RB = LONG_MAX",
1105
+ .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1106
+ .regs = {
1107
+ .gpr[21] = LONG_MIN,
1108
+ .gpr[22] = LONG_MAX,
1109
+ }
1110
+ },
1111
+ {
1112
+ .descr = "RA = LONG_MAX - 1, RB = LONG_MAX",
1113
+ .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1114
+ .regs = {
1115
+ .gpr[21] = LONG_MAX - 1,
1116
+ .gpr[22] = LONG_MAX,
1117
+ }
1118
+ },
1119
+ {
1120
+ .descr = "RA = LONG_MIN + 1, RB = LONG_MIN",
1121
+ .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1122
+ .flags = IGNORE_GPR(20),
1123
+ .regs = {
1124
+ .gpr[21] = LONG_MIN + 1,
1125
+ .gpr[22] = LONG_MIN,
1126
+ }
1127
+ }
1128
+ }
1129
+ },
1130
+ {
1131
+ .mnemonic = "divdeu.",
1132
+ .subtests = {
1133
+ {
1134
+ .descr = "RA = LONG_MIN, RB = LONG_MIN",
1135
+ .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1136
+ .flags = IGNORE_GPR(20),
1137
+ .regs = {
1138
+ .gpr[21] = LONG_MIN,
1139
+ .gpr[22] = LONG_MIN,
1140
+ }
1141
+ },
1142
+ {
1143
+ .descr = "RA = 1L, RB = 0",
1144
+ .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1145
+ .flags = IGNORE_GPR(20),
1146
+ .regs = {
1147
+ .gpr[21] = 1L,
1148
+ .gpr[22] = 0,
1149
+ }
1150
+ },
1151
+ {
1152
+ .descr = "RA = LONG_MIN, RB = LONG_MAX",
1153
+ .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1154
+ .regs = {
1155
+ .gpr[21] = LONG_MIN,
1156
+ .gpr[22] = LONG_MAX,
1157
+ }
1158
+ },
1159
+ {
1160
+ .descr = "RA = LONG_MAX - 1, RB = LONG_MAX",
1161
+ .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1162
+ .regs = {
1163
+ .gpr[21] = LONG_MAX - 1,
1164
+ .gpr[22] = LONG_MAX,
1165
+ }
1166
+ },
1167
+ {
1168
+ .descr = "RA = LONG_MIN + 1, RB = LONG_MIN",
1169
+ .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1170
+ .flags = IGNORE_GPR(20),
1171
+ .regs = {
1172
+ .gpr[21] = LONG_MIN + 1,
1173
+ .gpr[22] = LONG_MIN,
1174
+ }
1175
+ }
1176
+ }
1177
+ },
1178
+ {
1179
+ .mnemonic = "paddi",
1180
+ .cpu_feature = CPU_FTR_ARCH_31,
1181
+ .subtests = {
1182
+ {
1183
+ .descr = "RA = LONG_MIN, SI = SI_MIN, R = 0",
1184
+ .instr = TEST_PADDI(21, 22, SI_MIN, 0),
1185
+ .regs = {
1186
+ .gpr[21] = 0,
1187
+ .gpr[22] = LONG_MIN,
1188
+ }
1189
+ },
1190
+ {
1191
+ .descr = "RA = LONG_MIN, SI = SI_MAX, R = 0",
1192
+ .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1193
+ .regs = {
1194
+ .gpr[21] = 0,
1195
+ .gpr[22] = LONG_MIN,
1196
+ }
1197
+ },
1198
+ {
1199
+ .descr = "RA = LONG_MAX, SI = SI_MAX, R = 0",
1200
+ .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1201
+ .regs = {
1202
+ .gpr[21] = 0,
1203
+ .gpr[22] = LONG_MAX,
1204
+ }
1205
+ },
1206
+ {
1207
+ .descr = "RA = ULONG_MAX, SI = SI_UMAX, R = 0",
1208
+ .instr = TEST_PADDI(21, 22, SI_UMAX, 0),
1209
+ .regs = {
1210
+ .gpr[21] = 0,
1211
+ .gpr[22] = ULONG_MAX,
1212
+ }
1213
+ },
1214
+ {
1215
+ .descr = "RA = ULONG_MAX, SI = 0x1, R = 0",
1216
+ .instr = TEST_PADDI(21, 22, 0x1, 0),
1217
+ .regs = {
1218
+ .gpr[21] = 0,
1219
+ .gpr[22] = ULONG_MAX,
1220
+ }
1221
+ },
1222
+ {
1223
+ .descr = "RA = INT_MIN, SI = SI_MIN, R = 0",
1224
+ .instr = TEST_PADDI(21, 22, SI_MIN, 0),
1225
+ .regs = {
1226
+ .gpr[21] = 0,
1227
+ .gpr[22] = INT_MIN,
1228
+ }
1229
+ },
1230
+ {
1231
+ .descr = "RA = INT_MIN, SI = SI_MAX, R = 0",
1232
+ .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1233
+ .regs = {
1234
+ .gpr[21] = 0,
1235
+ .gpr[22] = INT_MIN,
1236
+ }
1237
+ },
1238
+ {
1239
+ .descr = "RA = INT_MAX, SI = SI_MAX, R = 0",
1240
+ .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1241
+ .regs = {
1242
+ .gpr[21] = 0,
1243
+ .gpr[22] = INT_MAX,
1244
+ }
1245
+ },
1246
+ {
1247
+ .descr = "RA = UINT_MAX, SI = 0x1, R = 0",
1248
+ .instr = TEST_PADDI(21, 22, 0x1, 0),
1249
+ .regs = {
1250
+ .gpr[21] = 0,
1251
+ .gpr[22] = UINT_MAX,
1252
+ }
1253
+ },
1254
+ {
1255
+ .descr = "RA = UINT_MAX, SI = SI_MAX, R = 0",
1256
+ .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1257
+ .regs = {
1258
+ .gpr[21] = 0,
1259
+ .gpr[22] = UINT_MAX,
1260
+ }
1261
+ },
1262
+ {
1263
+ .descr = "RA is r0, SI = SI_MIN, R = 0",
1264
+ .instr = TEST_PADDI(21, 0, SI_MIN, 0),
1265
+ .regs = {
1266
+ .gpr[21] = 0x0,
1267
+ }
1268
+ },
1269
+ {
1270
+ .descr = "RA = 0, SI = SI_MIN, R = 0",
1271
+ .instr = TEST_PADDI(21, 22, SI_MIN, 0),
1272
+ .regs = {
1273
+ .gpr[21] = 0x0,
1274
+ .gpr[22] = 0x0,
1275
+ }
1276
+ },
1277
+ {
1278
+ .descr = "RA is r0, SI = 0, R = 1",
1279
+ .instr = TEST_PADDI(21, 0, 0, 1),
1280
+ .regs = {
1281
+ .gpr[21] = 0,
1282
+ }
1283
+ },
1284
+ {
1285
+ .descr = "RA is r0, SI = SI_MIN, R = 1",
1286
+ .instr = TEST_PADDI(21, 0, SI_MIN, 1),
1287
+ .regs = {
1288
+ .gpr[21] = 0,
1289
+ }
1290
+ },
1291
+ /* Invalid instruction form with R = 1 and RA != 0 */
1292
+ {
1293
+ .descr = "RA = R22(0), SI = 0, R = 1",
1294
+ .instr = TEST_PADDI(21, 22, 0, 1),
1295
+ .flags = NEGATIVE_TEST,
1296
+ .regs = {
1297
+ .gpr[21] = 0,
1298
+ .gpr[22] = 0,
1299
+ }
1300
+ }
1301
+ }
1302
+ }
1303
+};
1304
+
1305
+static int __init emulate_compute_instr(struct pt_regs *regs,
1306
+ struct ppc_inst instr,
1307
+ bool negative)
1308
+{
1309
+ int analysed;
1310
+ struct instruction_op op;
1311
+
1312
+ if (!regs || !ppc_inst_val(instr))
1313
+ return -EINVAL;
1314
+
1315
+ regs->nip = patch_site_addr(&patch__exec_instr);
1316
+
1317
+ analysed = analyse_instr(&op, regs, instr);
1318
+ if (analysed != 1 || GETTYPE(op.type) != COMPUTE) {
1319
+ if (negative)
1320
+ return -EFAULT;
1321
+ pr_info("emulation failed, instruction = %s\n", ppc_inst_as_str(instr));
1322
+ return -EFAULT;
1323
+ }
1324
+ if (analysed == 1 && negative)
1325
+ pr_info("negative test failed, instruction = %s\n", ppc_inst_as_str(instr));
1326
+ if (!negative)
1327
+ emulate_update_regs(regs, &op);
1328
+ return 0;
1329
+}
1330
+
1331
+static int __init execute_compute_instr(struct pt_regs *regs,
1332
+ struct ppc_inst instr)
1333
+{
1334
+ extern int exec_instr(struct pt_regs *regs);
1335
+
1336
+ if (!regs || !ppc_inst_val(instr))
1337
+ return -EINVAL;
1338
+
1339
+ /* Patch the NOP with the actual instruction */
1340
+ patch_instruction_site(&patch__exec_instr, instr);
1341
+ if (exec_instr(regs)) {
1342
+ pr_info("execution failed, instruction = %s\n", ppc_inst_as_str(instr));
1343
+ return -EFAULT;
1344
+ }
1345
+
1346
+ return 0;
1347
+}
1348
+
1349
+#define gpr_mismatch(gprn, exp, got) \
1350
+ pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
1351
+ gprn, exp, got)
1352
+
1353
+#define reg_mismatch(name, exp, got) \
1354
+ pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
1355
+ name, exp, got)
1356
+
1357
+static void __init run_tests_compute(void)
1358
+{
1359
+ unsigned long flags;
1360
+ struct compute_test *test;
1361
+ struct pt_regs *regs, exp, got;
1362
+ unsigned int i, j, k;
1363
+ struct ppc_inst instr;
1364
+ bool ignore_gpr, ignore_xer, ignore_ccr, passed, rc, negative;
1365
+
1366
+ for (i = 0; i < ARRAY_SIZE(compute_tests); i++) {
1367
+ test = &compute_tests[i];
1368
+
1369
+ if (test->cpu_feature && !early_cpu_has_feature(test->cpu_feature)) {
1370
+ show_result(test->mnemonic, "SKIP (!CPU_FTR)");
1371
+ continue;
1372
+ }
1373
+
1374
+ for (j = 0; j < MAX_SUBTESTS && test->subtests[j].descr; j++) {
1375
+ instr = test->subtests[j].instr;
1376
+ flags = test->subtests[j].flags;
1377
+ regs = &test->subtests[j].regs;
1378
+ negative = flags & NEGATIVE_TEST;
1379
+ ignore_xer = flags & IGNORE_XER;
1380
+ ignore_ccr = flags & IGNORE_CCR;
1381
+ passed = true;
1382
+
1383
+ memcpy(&exp, regs, sizeof(struct pt_regs));
1384
+ memcpy(&got, regs, sizeof(struct pt_regs));
1385
+
1386
+ /*
1387
+ * Set a compatible MSR value explicitly to ensure
1388
+ * that XER and CR bits are updated appropriately
1389
+ */
1390
+ exp.msr = MSR_KERNEL;
1391
+ got.msr = MSR_KERNEL;
1392
+
1393
+ rc = emulate_compute_instr(&got, instr, negative) != 0;
1394
+ if (negative) {
1395
+ /* skip executing instruction */
1396
+ passed = rc;
1397
+ goto print;
1398
+ } else if (rc || execute_compute_instr(&exp, instr)) {
1399
+ passed = false;
1400
+ goto print;
1401
+ }
1402
+
1403
+ /* Verify GPR values */
1404
+ for (k = 0; k < 32; k++) {
1405
+ ignore_gpr = flags & IGNORE_GPR(k);
1406
+ if (!ignore_gpr && exp.gpr[k] != got.gpr[k]) {
1407
+ passed = false;
1408
+ gpr_mismatch(k, exp.gpr[k], got.gpr[k]);
1409
+ }
1410
+ }
1411
+
1412
+ /* Verify LR value */
1413
+ if (exp.link != got.link) {
1414
+ passed = false;
1415
+ reg_mismatch("LR", exp.link, got.link);
1416
+ }
1417
+
1418
+ /* Verify XER value */
1419
+ if (!ignore_xer && exp.xer != got.xer) {
1420
+ passed = false;
1421
+ reg_mismatch("XER", exp.xer, got.xer);
1422
+ }
1423
+
1424
+ /* Verify CR value */
1425
+ if (!ignore_ccr && exp.ccr != got.ccr) {
1426
+ passed = false;
1427
+ reg_mismatch("CR", exp.ccr, got.ccr);
1428
+ }
1429
+
1430
+print:
1431
+ show_result_with_descr(test->mnemonic,
1432
+ test->subtests[j].descr,
1433
+ passed ? "PASS" : "FAIL");
1434
+ }
1435
+ }
1436
+}
1437
+
1438
+static int __init test_emulate_step(void)
1439
+{
1440
+ printk(KERN_INFO "Running instruction emulation self-tests ...\n");
1441
+ run_tests_load_store();
1442
+ run_tests_compute();
4401443
4411444 return 0;
4421445 }