linux/arch/powerpc/lib/test_emulate_step.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Simple sanity tests for instruction emulation infrastructure.
   4 *
   5 * Copyright IBM Corp. 2016
   6 */
   7
   8#define pr_fmt(fmt) "emulate_step_test: " fmt
   9
  10#include <linux/ptrace.h>
  11#include <asm/cpu_has_feature.h>
  12#include <asm/sstep.h>
  13#include <asm/ppc-opcode.h>
  14#include <asm/code-patching.h>
  15#include <asm/inst.h>
  16
  17#define MAX_SUBTESTS    16
  18
  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))
  55
  56
  57static void __init init_pt_regs(struct pt_regs *regs)
  58{
  59        static unsigned long msr;
  60        static bool msr_cached;
  61
  62        memset(regs, 0, sizeof(struct pt_regs));
  63
  64        if (likely(msr_cached)) {
  65                regs->msr = msr;
  66                return;
  67        }
  68
  69        asm volatile("mfmsr %0" : "=r"(regs->msr));
  70
  71        regs->msr |= MSR_FP;
  72        regs->msr |= MSR_VEC;
  73        regs->msr |= MSR_VSX;
  74
  75        msr = regs->msr;
  76        msr_cached = true;
  77}
  78
  79static void __init show_result(char *mnemonic, char *result)
  80{
  81        pr_info("%-14s : %s\n", mnemonic, result);
  82}
  83
  84static void __init show_result_with_descr(char *mnemonic, char *descr,
  85                                          char *result)
  86{
  87        pr_info("%-14s : %-50s %s\n", mnemonic, descr, result);
  88}
  89
  90static void __init test_ld(void)
  91{
  92        struct pt_regs regs;
  93        unsigned long a = 0x23;
  94        int stepped = -1;
  95
  96        init_pt_regs(&regs);
  97        regs.gpr[3] = (unsigned long) &a;
  98
  99        /* ld r5, 0(r3) */
 100        stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LD(5, 3, 0)));
 101
 102        if (stepped == 1 && regs.gpr[5] == a)
 103                show_result("ld", "PASS");
 104        else
 105                show_result("ld", "FAIL");
 106}
 107
 108static 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");
 129}
 130
 131static void __init test_lwz(void)
 132{
 133        struct pt_regs regs;
 134        unsigned int a = 0x4545;
 135        int stepped = -1;
 136
 137        init_pt_regs(&regs);
 138        regs.gpr[3] = (unsigned long) &a;
 139
 140        /* lwz r5, 0(r3) */
 141        stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LWZ(5, 3, 0)));
 142
 143        if (stepped == 1 && regs.gpr[5] == a)
 144                show_result("lwz", "PASS");
 145        else
 146                show_result("lwz", "FAIL");
 147}
 148
 149static 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");
 171}
 172
 173static void __init test_lwzx(void)
 174{
 175        struct pt_regs regs;
 176        unsigned int a[3] = {0x0, 0x0, 0x1234};
 177        int stepped = -1;
 178
 179        init_pt_regs(&regs);
 180        regs.gpr[3] = (unsigned long) a;
 181        regs.gpr[4] = 8;
 182        regs.gpr[5] = 0x8765;
 183
 184        /* lwzx r5, r3, r4 */
 185        stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LWZX(5, 3, 4)));
 186        if (stepped == 1 && regs.gpr[5] == a[2])
 187                show_result("lwzx", "PASS");
 188        else
 189                show_result("lwzx", "FAIL");
 190}
 191
 192static void __init test_std(void)
 193{
 194        struct pt_regs regs;
 195        unsigned long a = 0x1234;
 196        int stepped = -1;
 197
 198        init_pt_regs(&regs);
 199        regs.gpr[3] = (unsigned long) &a;
 200        regs.gpr[5] = 0x5678;
 201
 202        /* std r5, 0(r3) */
 203        stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STD(5, 3, 0)));
 204        if (stepped == 1 && regs.gpr[5] == a)
 205                show_result("std", "PASS");
 206        else
 207                show_result("std", "FAIL");
 208}
 209
 210static 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");
 231}
 232
 233static void __init test_ldarx_stdcx(void)
 234{
 235        struct pt_regs regs;
 236        unsigned long a = 0x1234;
 237        int stepped = -1;
 238        unsigned long cr0_eq = 0x1 << 29; /* eq bit of CR0 */
 239
 240        init_pt_regs(&regs);
 241        asm volatile("mfcr %0" : "=r"(regs.ccr));
 242
 243
 244        /*** ldarx ***/
 245
 246        regs.gpr[3] = (unsigned long) &a;
 247        regs.gpr[4] = 0;
 248        regs.gpr[5] = 0x5678;
 249
 250        /* ldarx r5, r3, r4, 0 */
 251        stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LDARX(5, 3, 4, 0)));
 252
 253        /*
 254         * Don't touch 'a' here. Touching 'a' can do Load/store
 255         * of 'a' which result in failure of subsequent stdcx.
 256         * Instead, use hardcoded value for comparison.
 257         */
 258        if (stepped <= 0 || regs.gpr[5] != 0x1234) {
 259                show_result("ldarx / stdcx.", "FAIL (ldarx)");
 260                return;
 261        }
 262
 263
 264        /*** stdcx. ***/
 265
 266        regs.gpr[5] = 0x9ABC;
 267
 268        /* stdcx. r5, r3, r4 */
 269        stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STDCX(5, 3, 4)));
 270
 271        /*
 272         * Two possible scenarios that indicates successful emulation
 273         * of stdcx. :
 274         *  1. Reservation is active and store is performed. In this
 275         *     case cr0.eq bit will be set to 1.
 276         *  2. Reservation is not active and store is not performed.
 277         *     In this case cr0.eq bit will be set to 0.
 278         */
 279        if (stepped == 1 && ((regs.gpr[5] == a && (regs.ccr & cr0_eq))
 280                        || (regs.gpr[5] != a && !(regs.ccr & cr0_eq))))
 281                show_result("ldarx / stdcx.", "PASS");
 282        else
 283                show_result("ldarx / stdcx.", "FAIL (stdcx.)");
 284}
 285
 286#ifdef CONFIG_PPC_FPU
 287static void __init test_lfsx_stfsx(void)
 288{
 289        struct pt_regs regs;
 290        union {
 291                float a;
 292                int b;
 293        } c;
 294        int cached_b;
 295        int stepped = -1;
 296
 297        init_pt_regs(&regs);
 298
 299
 300        /*** lfsx ***/
 301
 302        c.a = 123.45;
 303        cached_b = c.b;
 304
 305        regs.gpr[3] = (unsigned long) &c.a;
 306        regs.gpr[4] = 0;
 307
 308        /* lfsx frt10, r3, r4 */
 309        stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LFSX(10, 3, 4)));
 310
 311        if (stepped == 1)
 312                show_result("lfsx", "PASS");
 313        else
 314                show_result("lfsx", "FAIL");
 315
 316
 317        /*** stfsx ***/
 318
 319        c.a = 678.91;
 320
 321        /* stfsx frs10, r3, r4 */
 322        stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STFSX(10, 3, 4)));
 323
 324        if (stepped == 1 && c.b == cached_b)
 325                show_result("stfsx", "PASS");
 326        else
 327                show_result("stfsx", "FAIL");
 328}
 329
 330static 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");
 375}
 376
 377static void __init test_lfdx_stfdx(void)
 378{
 379        struct pt_regs regs;
 380        union {
 381                double a;
 382                long b;
 383        } c;
 384        long cached_b;
 385        int stepped = -1;
 386
 387        init_pt_regs(&regs);
 388
 389
 390        /*** lfdx ***/
 391
 392        c.a = 123456.78;
 393        cached_b = c.b;
 394
 395        regs.gpr[3] = (unsigned long) &c.a;
 396        regs.gpr[4] = 0;
 397
 398        /* lfdx frt10, r3, r4 */
 399        stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LFDX(10, 3, 4)));
 400
 401        if (stepped == 1)
 402                show_result("lfdx", "PASS");
 403        else
 404                show_result("lfdx", "FAIL");
 405
 406
 407        /*** stfdx ***/
 408
 409        c.a = 987654.32;
 410
 411        /* stfdx frs10, r3, r4 */
 412        stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STFDX(10, 3, 4)));
 413
 414        if (stepped == 1 && c.b == cached_b)
 415                show_result("stfdx", "PASS");
 416        else
 417                show_result("stfdx", "FAIL");
 418}
 419
 420static 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");
 465}
 466#else
 467static void __init test_lfsx_stfsx(void)
 468{
 469        show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)");
 470        show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)");
 471}
 472
 473static 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
 479static void __init test_lfdx_stfdx(void)
 480{
 481        show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)");
 482        show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)");
 483}
 484
 485static 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)");
 489}
 490#endif /* CONFIG_PPC_FPU */
 491
 492#ifdef CONFIG_ALTIVEC
 493static void __init test_lvx_stvx(void)
 494{
 495        struct pt_regs regs;
 496        union {
 497                vector128 a;
 498                u32 b[4];
 499        } c;
 500        u32 cached_b[4];
 501        int stepped = -1;
 502
 503        init_pt_regs(&regs);
 504
 505
 506        /*** lvx ***/
 507
 508        cached_b[0] = c.b[0] = 923745;
 509        cached_b[1] = c.b[1] = 2139478;
 510        cached_b[2] = c.b[2] = 9012;
 511        cached_b[3] = c.b[3] = 982134;
 512
 513        regs.gpr[3] = (unsigned long) &c.a;
 514        regs.gpr[4] = 0;
 515
 516        /* lvx vrt10, r3, r4 */
 517        stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LVX(10, 3, 4)));
 518
 519        if (stepped == 1)
 520                show_result("lvx", "PASS");
 521        else
 522                show_result("lvx", "FAIL");
 523
 524
 525        /*** stvx ***/
 526
 527        c.b[0] = 4987513;
 528        c.b[1] = 84313948;
 529        c.b[2] = 71;
 530        c.b[3] = 498532;
 531
 532        /* stvx vrs10, r3, r4 */
 533        stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STVX(10, 3, 4)));
 534
 535        if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
 536            cached_b[2] == c.b[2] && cached_b[3] == c.b[3])
 537                show_result("stvx", "PASS");
 538        else
 539                show_result("stvx", "FAIL");
 540}
 541#else
 542static void __init test_lvx_stvx(void)
 543{
 544        show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)");
 545        show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)");
 546}
 547#endif /* CONFIG_ALTIVEC */
 548
 549#ifdef CONFIG_VSX
 550static void __init test_lxvd2x_stxvd2x(void)
 551{
 552        struct pt_regs regs;
 553        union {
 554                vector128 a;
 555                u32 b[4];
 556        } c;
 557        u32 cached_b[4];
 558        int stepped = -1;
 559
 560        init_pt_regs(&regs);
 561
 562
 563        /*** lxvd2x ***/
 564
 565        cached_b[0] = c.b[0] = 18233;
 566        cached_b[1] = c.b[1] = 34863571;
 567        cached_b[2] = c.b[2] = 834;
 568        cached_b[3] = c.b[3] = 6138911;
 569
 570        regs.gpr[3] = (unsigned long) &c.a;
 571        regs.gpr[4] = 0;
 572
 573        /* lxvd2x vsr39, r3, r4 */
 574        stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LXVD2X(39, R3, R4)));
 575
 576        if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
 577                show_result("lxvd2x", "PASS");
 578        } else {
 579                if (!cpu_has_feature(CPU_FTR_VSX))
 580                        show_result("lxvd2x", "PASS (!CPU_FTR_VSX)");
 581                else
 582                        show_result("lxvd2x", "FAIL");
 583        }
 584
 585
 586        /*** stxvd2x ***/
 587
 588        c.b[0] = 21379463;
 589        c.b[1] = 87;
 590        c.b[2] = 374234;
 591        c.b[3] = 4;
 592
 593        /* stxvd2x vsr39, r3, r4 */
 594        stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STXVD2X(39, R3, R4)));
 595
 596        if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
 597            cached_b[2] == c.b[2] && cached_b[3] == c.b[3] &&
 598            cpu_has_feature(CPU_FTR_VSX)) {
 599                show_result("stxvd2x", "PASS");
 600        } else {
 601                if (!cpu_has_feature(CPU_FTR_VSX))
 602                        show_result("stxvd2x", "PASS (!CPU_FTR_VSX)");
 603                else
 604                        show_result("stxvd2x", "FAIL");
 605        }
 606}
 607#else
 608static void __init test_lxvd2x_stxvd2x(void)
 609{
 610        show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)");
 611        show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)");
 612}
 613#endif /* CONFIG_VSX */
 614
 615static void __init run_tests_load_store(void)
 616{
 617        test_ld();
 618        test_pld();
 619        test_lwz();
 620        test_plwz();
 621        test_lwzx();
 622        test_std();
 623        test_pstd();
 624        test_ldarx_stdcx();
 625        test_lfsx_stfsx();
 626        test_plfs_pstfs();
 627        test_lfdx_stfdx();
 628        test_plfd_pstfd();
 629        test_lvx_stvx();
 630        test_lxvd2x_stxvd2x();
 631}
 632
 633struct 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
 649static 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
1305static 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
1331static 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
1357static 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
1430print:
1431                        show_result_with_descr(test->mnemonic,
1432                                               test->subtests[j].descr,
1433                                               passed ? "PASS" : "FAIL");
1434                }
1435        }
1436}
1437
1438static 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();
1443
1444        return 0;
1445}
1446late_initcall(test_emulate_step);
1447