get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.2/patches/805762/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 805762,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/805762/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/1503639722-19121-2-git-send-email-paulus@ozlabs.org/",
    "project": {
        "id": 2,
        "url": "http://patchwork.ozlabs.org/api/1.2/projects/2/?format=api",
        "name": "Linux PPC development",
        "link_name": "linuxppc-dev",
        "list_id": "linuxppc-dev.lists.ozlabs.org",
        "list_email": "linuxppc-dev@lists.ozlabs.org",
        "web_url": "https://github.com/linuxppc/wiki/wiki",
        "scm_url": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git",
        "webscm_url": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/",
        "list_archive_url": "https://lore.kernel.org/linuxppc-dev/",
        "list_archive_url_format": "https://lore.kernel.org/linuxppc-dev/{}/",
        "commit_url_format": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/commit/?id={}"
    },
    "msgid": "<1503639722-19121-2-git-send-email-paulus@ozlabs.org>",
    "list_archive_url": "https://lore.kernel.org/linuxppc-dev/1503639722-19121-2-git-send-email-paulus@ozlabs.org/",
    "date": "2017-08-25T05:41:53",
    "name": "[v2,01/10] powerpc: Handle most loads and stores in instruction emulation code",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "cdf50aba7ce5c9c8ba2e16b177e58d75addfac80",
    "submitter": {
        "id": 67079,
        "url": "http://patchwork.ozlabs.org/api/1.2/people/67079/?format=api",
        "name": "Paul Mackerras",
        "email": "paulus@ozlabs.org"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/1503639722-19121-2-git-send-email-paulus@ozlabs.org/mbox/",
    "series": [],
    "comments": "http://patchwork.ozlabs.org/api/patches/805762/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/805762/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org>",
        "X-Original-To": [
            "patchwork-incoming@ozlabs.org",
            "linuxppc-dev@lists.ozlabs.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@ozlabs.org",
            "linuxppc-dev@lists.ozlabs.org",
            "linuxppc-dev@ozlabs.org"
        ],
        "Received": [
            "from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68])\n\t(using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xdrJR3CDkz9sR9\n\tfor <patchwork-incoming@ozlabs.org>;\n\tFri, 25 Aug 2017 16:06:15 +1000 (AEST)",
            "from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 3xdrJR1v5LzDrVx\n\tfor <patchwork-incoming@ozlabs.org>;\n\tFri, 25 Aug 2017 16:06:15 +1000 (AEST)",
            "from ozlabs.org (bilbo.ozlabs.org [103.22.144.67])\n\t(using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby lists.ozlabs.org (Postfix) with ESMTPS id 3xdrDV4g4HzDrS2\n\tfor <linuxppc-dev@lists.ozlabs.org>;\n\tFri, 25 Aug 2017 16:02:50 +1000 (AEST)",
            "by ozlabs.org (Postfix)\n\tid 3xdrDV45glz9sR9; Fri, 25 Aug 2017 16:02:50 +1000 (AEST)",
            "from authenticated.ozlabs.org (localhost [127.0.0.1])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPSA id 3xdrDV36vyz9sRY\n\tfor <linuxppc-dev@ozlabs.org>; Fri, 25 Aug 2017 16:02:50 +1000 (AEST)"
        ],
        "Authentication-Results": [
            "ozlabs.org; dkim=pass (2048-bit key;\n\tsecure) header.d=ozlabs.org header.i=@ozlabs.org header.b=\"SKHVnMIE\";\n\tdkim-atps=neutral",
            "lists.ozlabs.org; dkim=pass (2048-bit key;\n\tsecure) header.d=ozlabs.org header.i=@ozlabs.org header.b=\"SKHVnMIE\";\n\tdkim-atps=neutral",
            "lists.ozlabs.org; dkim=pass (2048-bit key;\n\tsecure) header.d=ozlabs.org header.i=@ozlabs.org header.b=\"SKHVnMIE\"; \n\tdkim-atps=neutral"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ozlabs.org; s=201707; \n\tt=1503640970; bh=zn4sSVgB3s8KsKI7aoGceAK2dPH+xJlw82jwZxbsg0Y=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=SKHVnMIELQ/G8lOgeyDP4daUH3Zu3nD91bxPXnd21ar7s4mdNho2HuL/1dSkFBugm\n\tXSFsS7kWfpWlFxUQzgmWqp59tksP8yY0bZFQ0zVhzhjbHsiLPb6UNOCCbCIo6WpScq\n\tSelFxDS/XBoIN9SHvs2Rc9KsdUQZNx8X9z06DEfT+oFHez1MXXUdspRQDA8OlpJIJ9\n\tpIFLXmZifHa2tZIwPGASGVsnXJu/qNIEgT3J3SPzRRXaICZQg2oB32cIuuRaUVAA0X\n\tyeFrPiof4rvgk7nEsxwL/k20RlLA3UuR8igIH5qfmttEPyTL/LAIp5ZPYqK0iQzFGc\n\t1S/jCIsKqZ2bA==",
        "From": "Paul Mackerras <paulus@ozlabs.org>",
        "To": "linuxppc-dev@ozlabs.org",
        "Subject": "[PATCH v2 01/10] powerpc: Handle most loads and stores in\n\tinstruction emulation code",
        "Date": "Fri, 25 Aug 2017 15:41:53 +1000",
        "Message-Id": "<1503639722-19121-2-git-send-email-paulus@ozlabs.org>",
        "X-Mailer": "git-send-email 2.7.4",
        "In-Reply-To": "<1503639722-19121-1-git-send-email-paulus@ozlabs.org>",
        "References": "<1503639722-19121-1-git-send-email-paulus@ozlabs.org>",
        "X-BeenThere": "linuxppc-dev@lists.ozlabs.org",
        "X-Mailman-Version": "2.1.23",
        "Precedence": "list",
        "List-Id": "Linux on PowerPC Developers Mail List\n\t<linuxppc-dev.lists.ozlabs.org>",
        "List-Unsubscribe": "<https://lists.ozlabs.org/options/linuxppc-dev>,\n\t<mailto:linuxppc-dev-request@lists.ozlabs.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.ozlabs.org/pipermail/linuxppc-dev/>",
        "List-Post": "<mailto:linuxppc-dev@lists.ozlabs.org>",
        "List-Help": "<mailto:linuxppc-dev-request@lists.ozlabs.org?subject=help>",
        "List-Subscribe": "<https://lists.ozlabs.org/listinfo/linuxppc-dev>,\n\t<mailto:linuxppc-dev-request@lists.ozlabs.org?subject=subscribe>",
        "Errors-To": "linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org",
        "Sender": "\"Linuxppc-dev\"\n\t<linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org>"
    },
    "content": "This extends the instruction emulation infrastructure in sstep.c to\nhandle all the load and store instructions defined in the Power ISA\nv3.0, except for the atomic memory operations, ldmx (which was never\nimplemented), lfdp/stfdp, and the vector element load/stores.\n\nThe instructions added are:\n\nInteger loads and stores: lbarx, lharx, lqarx, stbcx., sthcx., stqcx.,\nlq, stq.\n\nVSX loads and stores: lxsiwzx, lxsiwax, stxsiwx, lxvx, lxvl, lxvll,\nlxvdsx, lxvwsx, stxvx, stxvl, stxvll, lxsspx, lxsdx, stxsspx, stxsdx,\nlxvw4x, lxsibzx, lxvh8x, lxsihzx, lxvb16x, stxvw4x, stxsibx, stxvh8x,\nstxsihx, stxvb16x, lxsd, lxssp, lxv, stxsd, stxssp, stxv.\n\nThese instructions are handled both in the analyse_instr phase and in\nthe emulate_step phase.\n\nThe code for lxvd2ux and stxvd2ux has been taken out, as those\ninstructions were never implemented in any processor and have been\ntaken out of the architecture, and their opcodes have been reused for\nother instructions in POWER9 (lxvb16x and stxvb16x).\n\nThe emulation for the VSX loads and stores uses helper functions\nwhich don't access registers or memory directly, which can hopefully\nbe reused by KVM later.\n\nSigned-off-by: Paul Mackerras <paulus@ozlabs.org>\n---\n arch/powerpc/include/asm/sstep.h |  20 ++\n arch/powerpc/lib/Makefile        |   2 +-\n arch/powerpc/lib/ldstfp.S        |  70 ++--\n arch/powerpc/lib/quad.S          |  62 ++++\n arch/powerpc/lib/sstep.c         | 688 ++++++++++++++++++++++++++++++++++++---\n 5 files changed, 781 insertions(+), 61 deletions(-)\n create mode 100644 arch/powerpc/lib/quad.S",
    "diff": "diff --git a/arch/powerpc/include/asm/sstep.h b/arch/powerpc/include/asm/sstep.h\nindex d3a42cc..863e1e4 100644\n--- a/arch/powerpc/include/asm/sstep.h\n+++ b/arch/powerpc/include/asm/sstep.h\n@@ -68,6 +68,11 @@ enum instruction_type {\n #define DCBT\t\t0x300\n #define ICBI\t\t0x400\n \n+/* VSX flags values */\n+#define VSX_FPCONV\t1\t/* do floating point SP/DP conversion */\n+#define VSX_SPLAT\t2\t/* store loaded value into all elements */\n+#define VSX_LDLEFT\t4\t/* load VSX register from left */\n+\n /* Size field in type word */\n #define SIZE(n)\t\t((n) << 8)\n #define GETSIZE(w)\t((w) >> 8)\n@@ -83,7 +88,22 @@ struct instruction_op {\n \tint update_reg;\n \t/* For MFSPR */\n \tint spr;\n+\tu8 element_size;\t/* for VSX/VMX loads/stores */\n+\tu8 vsx_flags;\n+};\n+\n+union vsx_reg {\n+\tu8\tb[16];\n+\tu16\th[8];\n+\tu32\tw[4];\n+\tunsigned long d[2];\n+\tfloat\tfp[4];\n+\tdouble\tdp[2];\n };\n \n extern int analyse_instr(struct instruction_op *op, struct pt_regs *regs,\n \t\t\t unsigned int instr);\n+extern void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,\n+\t\t\t     const void *mem);\n+extern void emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg,\n+\t\t\t      void *mem);\ndiff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile\nindex 3c3146b..7921fed 100644\n--- a/arch/powerpc/lib/Makefile\n+++ b/arch/powerpc/lib/Makefile\n@@ -31,7 +31,7 @@ obj64-$(CONFIG_KPROBES_SANITY_TEST) += test_emulate_step.o\n \n obj-y\t\t\t+= checksum_$(BITS).o checksum_wrappers.o\n \n-obj-$(CONFIG_PPC_EMULATE_SSTEP)\t+= sstep.o ldstfp.o\n+obj-$(CONFIG_PPC_EMULATE_SSTEP)\t+= sstep.o ldstfp.o quad.o\n \n obj-$(CONFIG_PPC_LIB_RHEAP) += rheap.o\n \ndiff --git a/arch/powerpc/lib/ldstfp.S b/arch/powerpc/lib/ldstfp.S\nindex a58777c..6840911 100644\n--- a/arch/powerpc/lib/ldstfp.S\n+++ b/arch/powerpc/lib/ldstfp.S\n@@ -178,10 +178,10 @@ _GLOBAL(do_stfd)\n \tEX_TABLE(2b,3b)\n \n #ifdef CONFIG_ALTIVEC\n-/* Get the contents of vrN into v0; N is in r3. */\n+/* Get the contents of vrN into v0; N is in r3. Doesn't touch r3 or r4. */\n _GLOBAL(get_vr)\n \tmflr\tr0\n-\trlwinm\tr3,r3,3,0xf8\n+\trlwinm\tr6,r3,3,0xf8\n \tbcl\t20,31,1f\n \tblr\t\t\t/* v0 is already in v0 */\n \tnop\n@@ -192,15 +192,15 @@ reg = 1\n reg = reg + 1\n \t.endr\n 1:\tmflr\tr5\n-\tadd\tr5,r3,r5\n+\tadd\tr5,r6,r5\n \tmtctr\tr5\n \tmtlr\tr0\n \tbctr\n \n-/* Put the contents of v0 into vrN; N is in r3. */\n+/* Put the contents of v0 into vrN; N is in r3. Doesn't touch r3 or r4. */\n _GLOBAL(put_vr)\n \tmflr\tr0\n-\trlwinm\tr3,r3,3,0xf8\n+\trlwinm\tr6,r3,3,0xf8\n \tbcl\t20,31,1f\n \tblr\t\t\t/* v0 is already in v0 */\n \tnop\n@@ -211,7 +211,7 @@ reg = 1\n reg = reg + 1\n \t.endr\n 1:\tmflr\tr5\n-\tadd\tr5,r3,r5\n+\tadd\tr5,r6,r5\n \tmtctr\tr5\n \tmtlr\tr0\n \tbctr\n@@ -313,7 +313,7 @@ reg = reg + 1\n \tbctr\n \n /* Load VSX reg N from vector doubleword *p.  N is in r3, p in r4. */\n-_GLOBAL(do_lxvd2x)\n+_GLOBAL(load_vsrn)\n \tPPC_STLU r1,-STKFRM(r1)\n \tmflr\tr0\n \tPPC_STL\tr0,STKFRM+PPC_LR_STKOFF(r1)\n@@ -325,41 +325,38 @@ _GLOBAL(do_lxvd2x)\n \tisync\n \tbeq\tcr7,1f\n \tSTXVD2X(0,R1,R8)\n-1:\tli\tr9,-EFAULT\n-2:\tLXVD2X(0,R0,R4)\n-\tli\tr9,0\n-3:\tbeq\tcr7,4f\n+1:\tLXVD2X(0,R0,R4)\n+#ifdef __LITTLE_ENDIAN__\n+\tXXSWAPD(0,0)\n+#endif\n+\tbeq\tcr7,4f\n \tbl\tput_vsr\n \tLXVD2X(0,R1,R8)\n 4:\tPPC_LL\tr0,STKFRM+PPC_LR_STKOFF(r1)\n \tmtlr\tr0\n \tMTMSRD(r6)\n \tisync\n-\tmr\tr3,r9\n \taddi\tr1,r1,STKFRM\n \tblr\n-\tEX_TABLE(2b,3b)\n \n /* Store VSX reg N to vector doubleword *p.  N is in r3, p in r4. */\n-_GLOBAL(do_stxvd2x)\n+_GLOBAL(store_vsrn)\n \tPPC_STLU r1,-STKFRM(r1)\n \tmflr\tr0\n \tPPC_STL\tr0,STKFRM+PPC_LR_STKOFF(r1)\n \tmfmsr\tr6\n \toris\tr7,r6,MSR_VSX@h\n-\tcmpwi\tcr7,r3,0\n \tli\tr8,STKFRM-16\n \tMTMSRD(r7)\n \tisync\n-\tbeq\tcr7,1f\n \tSTXVD2X(0,R1,R8)\n \tbl\tget_vsr\n-1:\tli\tr9,-EFAULT\n-2:\tSTXVD2X(0,R0,R4)\n-\tli\tr9,0\n-3:\tbeq\tcr7,4f\n+#ifdef __LITTLE_ENDIAN__\n+\tXXSWAPD(0,0)\n+#endif\n+\tSTXVD2X(0,R0,R4)\n \tLXVD2X(0,R1,R8)\n-4:\tPPC_LL\tr0,STKFRM+PPC_LR_STKOFF(r1)\n+\tPPC_LL\tr0,STKFRM+PPC_LR_STKOFF(r1)\n \tmtlr\tr0\n \tMTMSRD(r6)\n \tisync\n@@ -367,7 +364,36 @@ _GLOBAL(do_stxvd2x)\n \taddi\tr1,r1,STKFRM\n \tblr\n \tEX_TABLE(2b,3b)\n-\n #endif /* CONFIG_VSX */\n \n+/* Convert single-precision to double, without disturbing FPRs. */\n+/* conv_sp_to_dp(float *sp, double *dp) */\n+_GLOBAL(conv_sp_to_dp)\n+\tmfmsr\tr6\n+\tori\tr7, r6, MSR_FP\n+\tMTMSRD(r7)\n+\tisync\n+\tstfd\tfr0, -16(r1)\n+\tlfs\tfr0, 0(r3)\n+\tstfd\tfr0, 0(r4)\n+\tlfd\tfr0, -16(r1)\n+\tMTMSRD(r6)\n+\tisync\n+\tblr\n+\n+/* Convert single-precision to double, without disturbing FPRs. */\n+/* conv_sp_to_dp(double *dp, float *sp) */\n+_GLOBAL(conv_dp_to_sp)\n+\tmfmsr\tr6\n+\tori\tr7, r6, MSR_FP\n+\tMTMSRD(r7)\n+\tisync\n+\tstfd\tfr0, -16(r1)\n+\tlfd\tfr0, 0(r3)\n+\tstfs\tfr0, 0(r4)\n+\tlfd\tfr0, -16(r1)\n+\tMTMSRD(r6)\n+\tisync\n+\tblr\n+\n #endif\t/* CONFIG_PPC_FPU */\ndiff --git a/arch/powerpc/lib/quad.S b/arch/powerpc/lib/quad.S\nnew file mode 100644\nindex 0000000..2cc77dc\n--- /dev/null\n+++ b/arch/powerpc/lib/quad.S\n@@ -0,0 +1,62 @@\n+/*\n+ * Quadword loads and stores\n+ * for use in instruction emulation.\n+ *\n+ * Copyright 2017 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>\n+ *\n+ *  This program is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public License\n+ *  as published by the Free Software Foundation; either version\n+ *  2 of the License, or (at your option) any later version.\n+ */\n+\n+#include <asm/processor.h>\n+#include <asm/ppc_asm.h>\n+#include <asm/ppc-opcode.h>\n+#include <asm/reg.h>\n+#include <asm/asm-offsets.h>\n+#include <linux/errno.h>\n+\n+/* do_lq(unsigned long ea, unsigned long *regs) */\n+_GLOBAL(do_lq)\n+1:\tlq\tr6, 0(r3)\n+\tstd\tr6, 0(r4)\n+\tstd\tr7, 8(r4)\n+\tli\tr3, 0\n+\tblr\n+2:\tli\tr3, -EFAULT\n+\tblr\n+\tEX_TABLE(1b, 2b)\n+\n+/* do_stq(unsigned long ea, unsigned long val0, unsigned long val1) */\n+_GLOBAL(do_stq)\n+1:\tstq\tr4, 0(r3)\n+\tli\tr3, 0\n+\tblr\n+2:\tli\tr3, -EFAULT\n+\tblr\n+\tEX_TABLE(1b, 2b)\n+\n+/* do_lqarx(unsigned long ea, unsigned long *regs) */\n+_GLOBAL(do_lqarx)\n+1:\tlqarx\tr6, 0, r3\n+\tstd\tr6, 0(r4)\n+\tstd\tr7, 8(r4)\n+\tli\tr3, 0\n+\tblr\n+2:\tli\tr3, -EFAULT\n+\tblr\n+\tEX_TABLE(1b, 2b)\n+\n+/* do_stqcx(unsigned long ea, unsigned long val0, unsigned long val1,\n+\t    unsigned int *crp) */\n+\n+_GLOBAL(do_stqcx)\n+1:\tstqcx.\tr4, 0, r3\n+\tmfcr\tr5\n+\tstw\tr5, 0(r6)\n+\tli\tr3, 0\n+\tblr\n+2:\tli\tr3, -EFAULT\n+\tblr\n+\tEX_TABLE(1b, 2b)\ndiff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c\nindex a85b82c..6aa0ba6 100644\n--- a/arch/powerpc/lib/sstep.c\n+++ b/arch/powerpc/lib/sstep.c\n@@ -42,8 +42,29 @@ extern int do_stfs(int rn, unsigned long ea);\n extern int do_stfd(int rn, unsigned long ea);\n extern int do_lvx(int rn, unsigned long ea);\n extern int do_stvx(int rn, unsigned long ea);\n-extern int do_lxvd2x(int rn, unsigned long ea);\n-extern int do_stxvd2x(int rn, unsigned long ea);\n+extern void load_vsrn(int vsr, const void *p);\n+extern void store_vsrn(int vsr, void *p);\n+extern void conv_sp_to_dp(const float *sp, double *dp);\n+extern void conv_dp_to_sp(const double *dp, float *sp);\n+#endif\n+\n+#ifdef __powerpc64__\n+/*\n+ * Functions in quad.S\n+ */\n+extern int do_lq(unsigned long ea, unsigned long *regs);\n+extern int do_stq(unsigned long ea, unsigned long val0, unsigned long val1);\n+extern int do_lqarx(unsigned long ea, unsigned long *regs);\n+extern int do_stqcx(unsigned long ea, unsigned long val0, unsigned long val1,\n+\t\t    unsigned int *crp);\n+#endif\n+\n+#ifdef __LITTLE_ENDIAN__\n+#define IS_LE\t1\n+#define IS_BE\t0\n+#else\n+#define IS_LE\t0\n+#define IS_BE\t1\n #endif\n \n /*\n@@ -121,6 +142,22 @@ static nokprobe_inline unsigned long dsform_ea(unsigned int instr, struct pt_reg\n \n \treturn truncate_if_32bit(regs->msr, ea);\n }\n+\n+/*\n+ * Calculate effective address for a DQ-form instruction\n+ */\n+static nokprobe_inline unsigned long dqform_ea(unsigned int instr, struct pt_regs *regs)\n+{\n+\tint ra;\n+\tunsigned long ea;\n+\n+\tra = (instr >> 16) & 0x1f;\n+\tea = (signed short) (instr & ~0xf);\t/* sign-extend */\n+\tif (ra)\n+\t\tea += regs->gpr[ra];\n+\n+\treturn truncate_if_32bit(regs->msr, ea);\n+}\n #endif /* __powerpc64 */\n \n /*\n@@ -450,43 +487,197 @@ static nokprobe_inline int do_vec_store(int rn, int (*func)(int, unsigned long),\n }\n #endif /* CONFIG_ALTIVEC */\n \n-#ifdef CONFIG_VSX\n-static nokprobe_inline int do_vsx_load(int rn, int (*func)(int, unsigned long),\n-\t\t\t\t unsigned long ea, struct pt_regs *regs)\n+#ifdef __powerpc64__\n+static nokprobe_inline int emulate_lq(struct pt_regs *regs, unsigned long ea,\n+\t\t\t\t      int reg)\n {\n \tint err;\n-\tunsigned long val[2];\n \n \tif (!address_ok(regs, ea, 16))\n \t\treturn -EFAULT;\n-\tif ((ea & 3) == 0)\n-\t\treturn (*func)(rn, ea);\n-\terr = read_mem_unaligned(&val[0], ea, 8, regs);\n-\tif (!err)\n-\t\terr = read_mem_unaligned(&val[1], ea + 8, 8, regs);\n+\t/* if aligned, should be atomic */\n+\tif ((ea & 0xf) == 0)\n+\t\treturn do_lq(ea, &regs->gpr[reg]);\n+\n+\terr = read_mem(&regs->gpr[reg + IS_LE], ea, 8, regs);\n \tif (!err)\n-\t\terr = (*func)(rn, (unsigned long) &val[0]);\n+\t\terr = read_mem(&regs->gpr[reg + IS_BE], ea + 8, 8, regs);\n \treturn err;\n }\n \n-static nokprobe_inline int do_vsx_store(int rn, int (*func)(int, unsigned long),\n-\t\t\t\t unsigned long ea, struct pt_regs *regs)\n+static nokprobe_inline int emulate_stq(struct pt_regs *regs, unsigned long ea,\n+\t\t\t\t       int reg)\n {\n \tint err;\n-\tunsigned long val[2];\n \n \tif (!address_ok(regs, ea, 16))\n \t\treturn -EFAULT;\n-\tif ((ea & 3) == 0)\n-\t\treturn (*func)(rn, ea);\n-\terr = (*func)(rn, (unsigned long) &val[0]);\n-\tif (err)\n-\t\treturn err;\n-\terr = write_mem_unaligned(val[0], ea, 8, regs);\n+\t/* if aligned, should be atomic */\n+\tif ((ea & 0xf) == 0)\n+\t\treturn do_stq(ea, regs->gpr[reg], regs->gpr[reg + 1]);\n+\n+\terr = write_mem(regs->gpr[reg + IS_LE], ea, 8, regs);\n \tif (!err)\n-\t\terr = write_mem_unaligned(val[1], ea + 8, 8, regs);\n+\t\terr = write_mem(regs->gpr[reg + IS_BE], ea + 8, 8, regs);\n \treturn err;\n }\n+#endif /* __powerpc64 */\n+\n+#ifdef CONFIG_VSX\n+void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,\n+\t\t      const void *mem)\n+{\n+\tint size, read_size;\n+\tint i, j;\n+\tunion vsx_reg buf;\n+\tconst unsigned int *wp;\n+\tconst unsigned short *hp;\n+\tconst unsigned char *bp;\n+\n+\tsize = GETSIZE(op->type);\n+\tbuf.d[0] = buf.d[1] = 0;\n+\n+\tswitch (op->element_size) {\n+\tcase 16:\n+\t\t/* whole vector; lxv[x] or lxvl[l] */\n+\t\tif (size == 0)\n+\t\t\tbreak;\n+\t\tmemcpy(&buf, mem, size);\n+\t\tif (IS_LE && (op->vsx_flags & VSX_LDLEFT)) {\n+\t\t\t/* reverse 16 bytes */\n+\t\t\tunsigned long tmp;\n+\t\t\ttmp = byterev_8(buf.d[0]);\n+\t\t\tbuf.d[0] = byterev_8(buf.d[1]);\n+\t\t\tbuf.d[1] = tmp;\n+\t\t}\n+\t\tbreak;\n+\tcase 8:\n+\t\t/* scalar loads, lxvd2x, lxvdsx */\n+\t\tread_size = (size >= 8) ? 8 : size;\n+\t\ti = IS_LE ? 8 : 8 - read_size;\n+\t\tmemcpy(&buf.b[i], mem, read_size);\n+\t\tif (size < 8) {\n+\t\t\tif (op->type & SIGNEXT) {\n+\t\t\t\t/* size == 4 is the only case here */\n+\t\t\t\tbuf.d[IS_LE] = (signed int) buf.d[IS_LE];\n+\t\t\t} else if (op->vsx_flags & VSX_FPCONV) {\n+\t\t\t\tpreempt_disable();\n+\t\t\t\tconv_sp_to_dp(&buf.fp[1 + IS_LE],\n+\t\t\t\t\t      &buf.dp[IS_LE]);\n+\t\t\t\tpreempt_enable();\n+\t\t\t}\n+\t\t} else {\n+\t\t\tif (size == 16)\n+\t\t\t\tbuf.d[IS_BE] = *(unsigned long *)(mem + 8);\n+\t\t\telse if (op->vsx_flags & VSX_SPLAT)\n+\t\t\t\tbuf.d[IS_BE] = buf.d[IS_LE];\n+\t\t}\n+\t\tbreak;\n+\tcase 4:\n+\t\t/* lxvw4x, lxvwsx */\n+\t\twp = mem;\n+\t\tfor (j = 0; j < size / 4; ++j) {\n+\t\t\ti = IS_LE ? 3 - j : j;\n+\t\t\tbuf.w[i] = *wp++;\n+\t\t}\n+\t\tif (op->vsx_flags & VSX_SPLAT) {\n+\t\t\tu32 val = buf.w[IS_LE ? 3 : 0];\n+\t\t\tfor (; j < 4; ++j) {\n+\t\t\t\ti = IS_LE ? 3 - j : j;\n+\t\t\t\tbuf.w[i] = val;\n+\t\t\t}\n+\t\t}\n+\t\tbreak;\n+\tcase 2:\n+\t\t/* lxvh8x */\n+\t\thp = mem;\n+\t\tfor (j = 0; j < size / 2; ++j) {\n+\t\t\ti = IS_LE ? 7 - j : j;\n+\t\t\tbuf.h[i] = *hp++;\n+\t\t}\n+\t\tbreak;\n+\tcase 1:\n+\t\t/* lxvb16x */\n+\t\tbp = mem;\n+\t\tfor (j = 0; j < size; ++j) {\n+\t\t\ti = IS_LE ? 15 - j : j;\n+\t\t\tbuf.b[i] = *bp++;\n+\t\t}\n+\t\tbreak;\n+\t}\n+\t*reg = buf;\n+}\n+EXPORT_SYMBOL_GPL(emulate_vsx_load);\n+NOKPROBE_SYMBOL(emulate_vsx_load);\n+\n+void emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg,\n+\t\t       void *mem)\n+{\n+\tint size, write_size;\n+\tint i, j;\n+\tunion vsx_reg buf;\n+\tunsigned int *wp;\n+\tunsigned short *hp;\n+\tunsigned char *bp;\n+\n+\tsize = GETSIZE(op->type);\n+\n+\tswitch (op->element_size) {\n+\tcase 16:\n+\t\t/* stxv, stxvx, stxvl, stxvll */\n+\t\tif (size == 0)\n+\t\t\tbreak;\n+\t\tif (IS_LE && (op->vsx_flags & VSX_LDLEFT)) {\n+\t\t\t/* reverse 16 bytes */\n+\t\t\tbuf.d[0] = byterev_8(reg->d[1]);\n+\t\t\tbuf.d[1] = byterev_8(reg->d[0]);\n+\t\t\treg = &buf;\n+\t\t}\n+\t\tmemcpy(mem, reg, size);\n+\t\tbreak;\n+\tcase 8:\n+\t\t/* scalar stores, stxvd2x */\n+\t\twrite_size = (size >= 8) ? 8 : size;\n+\t\ti = IS_LE ? 8 : 8 - write_size;\n+\t\tif (size < 8 && op->vsx_flags & VSX_FPCONV) {\n+\t\t\tbuf.d[0] = buf.d[1] = 0;\n+\t\t\tpreempt_disable();\n+\t\t\tconv_dp_to_sp(&reg->dp[IS_LE], &buf.fp[1 + IS_LE]);\n+\t\t\tpreempt_enable();\n+\t\t\treg = &buf;\n+\t\t}\n+\t\tmemcpy(mem, &reg->b[i], write_size);\n+\t\tif (size == 16)\n+\t\t\tmemcpy(mem + 8, &reg->d[IS_BE], 8);\n+\t\tbreak;\n+\tcase 4:\n+\t\t/* stxvw4x */\n+\t\twp = mem;\n+\t\tfor (j = 0; j < size / 4; ++j) {\n+\t\t\ti = IS_LE ? 3 - j : j;\n+\t\t\t*wp++ = reg->w[i];\n+\t\t}\n+\t\tbreak;\n+\tcase 2:\n+\t\t/* stxvh8x */\n+\t\thp = mem;\n+\t\tfor (j = 0; j < size / 2; ++j) {\n+\t\t\ti = IS_LE ? 7 - j : j;\n+\t\t\t*hp++ = reg->h[i];\n+\t\t}\n+\t\tbreak;\n+\tcase 1:\n+\t\t/* stvxb16x */\n+\t\tbp = mem;\n+\t\tfor (j = 0; j < size; ++j) {\n+\t\t\ti = IS_LE ? 15 - j : j;\n+\t\t\t*bp++ = reg->b[i];\n+\t\t}\n+\t\tbreak;\n+\t}\n+}\n+EXPORT_SYMBOL_GPL(emulate_vsx_store);\n+NOKPROBE_SYMBOL(emulate_vsx_store);\n #endif /* CONFIG_VSX */\n \n #define __put_user_asmx(x, addr, err, op, cr)\t\t\\\n@@ -1453,14 +1644,15 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,\n \t\tbreak;\n \t}\n \n-\t/*\n-\t * Loads and stores.\n-\t */\n+/*\n+ * Loads and stores.\n+ */\n \top->type = UNKNOWN;\n \top->update_reg = ra;\n \top->reg = rd;\n \top->val = regs->gpr[rd];\n \tu = (instr >> 20) & UPDATE;\n+\top->vsx_flags = 0;\n \n \tswitch (opcode) {\n \tcase 31:\n@@ -1484,9 +1676,30 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,\n \t\t\top->type = MKOP(STCX, 0, 8);\n \t\t\tbreak;\n \n-\t\tcase 21:\t/* ldx */\n-\t\tcase 53:\t/* ldux */\n-\t\t\top->type = MKOP(LOAD, u, 8);\n+\t\tcase 52:\t/* lbarx */\n+\t\t\top->type = MKOP(LARX, 0, 1);\n+\t\t\tbreak;\n+\n+\t\tcase 694:\t/* stbcx. */\n+\t\t\top->type = MKOP(STCX, 0, 1);\n+\t\t\tbreak;\n+\n+\t\tcase 116:\t/* lharx */\n+\t\t\top->type = MKOP(LARX, 0, 2);\n+\t\t\tbreak;\n+\n+\t\tcase 726:\t/* sthcx. */\n+\t\t\top->type = MKOP(STCX, 0, 2);\n+\t\t\tbreak;\n+\n+\t\tcase 276:\t/* lqarx */\n+\t\t\tif (!((rd & 1) || rd == ra || rd == rb))\n+\t\t\t\top->type = MKOP(LARX, 0, 16);\n+\t\t\tbreak;\n+\n+\t\tcase 182:\t/* stqcx. */\n+\t\t\tif (!(rd & 1))\n+\t\t\t\top->type = MKOP(STCX, 0, 16);\n \t\t\tbreak;\n #endif\n \n@@ -1506,6 +1719,7 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,\n \t\t\tif (!(regs->msr & MSR_VEC))\n \t\t\t\tgoto vecunavail;\n \t\t\top->type = MKOP(LOAD_VMX, 0, 16);\n+\t\t\top->element_size = 16;\n \t\t\tbreak;\n \n \t\tcase 231:\t/* stvx */\n@@ -1517,6 +1731,11 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,\n #endif /* CONFIG_ALTIVEC */\n \n #ifdef __powerpc64__\n+\t\tcase 21:\t/* ldx */\n+\t\tcase 53:\t/* ldux */\n+\t\t\top->type = MKOP(LOAD, u, 8);\n+\t\t\tbreak;\n+\n \t\tcase 149:\t/* stdx */\n \t\tcase 181:\t/* stdux */\n \t\t\top->type = MKOP(STORE, u, 8);\n@@ -1645,20 +1864,267 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,\n \t\t\tbreak;\n \n #ifdef CONFIG_VSX\n+\t\tcase 12:\t/* lxsiwzx */\n+\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\tgoto vsxunavail;\n+\t\t\top->reg = rd | ((instr & 1) << 5);\n+\t\t\top->type = MKOP(LOAD_VSX, 0, 4);\n+\t\t\top->element_size = 8;\n+\t\t\tbreak;\n+\n+\t\tcase 76:\t/* lxsiwax */\n+\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\tgoto vsxunavail;\n+\t\t\top->reg = rd | ((instr & 1) << 5);\n+\t\t\top->type = MKOP(LOAD_VSX, SIGNEXT, 4);\n+\t\t\top->element_size = 8;\n+\t\t\tbreak;\n+\n+\t\tcase 140:\t/* stxsiwx */\n+\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\tgoto vsxunavail;\n+\t\t\top->reg = rd | ((instr & 1) << 5);\n+\t\t\top->type = MKOP(STORE_VSX, 0, 4);\n+\t\t\top->element_size = 8;\n+\t\t\tbreak;\n+\n+\t\tcase 268:\t/* lxvx */\n+\t\t\tif (!(instr & 1)) {\n+\t\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\t\tgoto vsxunavail;\n+\t\t\t} else {\n+\t\t\t\tif (!(regs->msr & MSR_VEC))\n+\t\t\t\t\tgoto vecunavail;\n+\t\t\t\top->reg = rd + 32;\n+\t\t\t}\n+\t\t\top->type = MKOP(LOAD_VSX, 0, 16);\n+\t\t\top->element_size = 16;\n+\t\t\tbreak;\n+\n+\t\tcase 269:\t/* lxvl */\n+\t\tcase 301: {\t/* lxvll */\n+\t\t\tint nb;\n+\t\t\tif (!(instr & 1)) {\n+\t\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\t\tgoto vsxunavail;\n+\t\t\t} else {\n+\t\t\t\tif (!(regs->msr & MSR_VEC))\n+\t\t\t\t\tgoto vecunavail;\n+\t\t\t\top->reg = rd + 32;\n+\t\t\t}\n+\t\t\top->ea = ra ? regs->gpr[ra] : 0;\n+\t\t\tnb = regs->gpr[rb] & 0xff;\n+\t\t\tif (nb > 16)\n+\t\t\t\tnb = 16;\n+\t\t\top->type = MKOP(LOAD_VSX, 0, nb);\n+\t\t\top->element_size = 16;\n+\t\t\top->vsx_flags = (instr & 0x20) ? VSX_LDLEFT : 0;\n+\t\t\tbreak;\n+\t\t}\n+\t\tcase 332:\t/* lxvdsx */\n+\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\tgoto vsxunavail;\n+\t\t\top->reg = rd | ((instr & 1) << 5);\n+\t\t\top->type = MKOP(LOAD_VSX, 0, 8);\n+\t\t\top->element_size = 8;\n+\t\t\top->vsx_flags = VSX_SPLAT;\n+\t\t\tbreak;\n+\n+\t\tcase 364:\t/* lxvwsx */\n+\t\t\tif (!(instr & 1)) {\n+\t\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\t\tgoto vsxunavail;\n+\t\t\t} else {\n+\t\t\t\tif (!(regs->msr & MSR_VEC))\n+\t\t\t\t\tgoto vecunavail;\n+\t\t\t\top->reg = rd + 32;\n+\t\t\t}\n+\t\t\top->type = MKOP(LOAD_VSX, 0, 4);\n+\t\t\top->element_size = 4;\n+\t\t\top->vsx_flags = VSX_SPLAT;\n+\t\t\tbreak;\n+\n+\t\tcase 396:\t/* stxvx */\n+\t\t\tif (!(instr & 1)) {\n+\t\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\t\tgoto vsxunavail;\n+\t\t\t} else {\n+\t\t\t\tif (!(regs->msr & MSR_VEC))\n+\t\t\t\t\tgoto vecunavail;\n+\t\t\t\top->reg = rd + 32;\n+\t\t\t}\n+\t\t\top->type = MKOP(STORE_VSX, 0, 16);\n+\t\t\top->element_size = 16;\n+\t\t\tbreak;\n+\n+\t\tcase 397:\t/* stxvl */\n+\t\tcase 429: {\t/* stxvll */\n+\t\t\tint nb;\n+\t\t\tif (!(instr & 1)) {\n+\t\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\t\tgoto vsxunavail;\n+\t\t\t} else {\n+\t\t\t\tif (!(regs->msr & MSR_VEC))\n+\t\t\t\t\tgoto vecunavail;\n+\t\t\t\top->reg = rd + 32;\n+\t\t\t}\n+\t\t\top->ea = ra ? regs->gpr[ra] : 0;\n+\t\t\tnb = regs->gpr[rb] & 0xff;\n+\t\t\tif (nb > 16)\n+\t\t\t\tnb = 16;\n+\t\t\top->type = MKOP(STORE_VSX, 0, nb);\n+\t\t\top->element_size = 16;\n+\t\t\top->vsx_flags = (instr & 0x20) ? VSX_LDLEFT : 0;\n+\t\t\tbreak;\n+\t\t}\n+\t\tcase 524:\t/* lxsspx */\n+\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\tgoto vsxunavail;\n+\t\t\top->reg = rd | ((instr & 1) << 5);\n+\t\t\top->type = MKOP(LOAD_VSX, 0, 4);\n+\t\t\top->element_size = 8;\n+\t\t\top->vsx_flags = VSX_FPCONV;\n+\t\t\tbreak;\n+\n+\t\tcase 588:\t/* lxsdx */\n+\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\tgoto vsxunavail;\n+\t\t\top->reg = rd | ((instr & 1) << 5);\n+\t\t\top->type = MKOP(LOAD_VSX, 0, 8);\n+\t\t\top->element_size = 8;\n+\t\t\tbreak;\n+\n+\t\tcase 652:\t/* stxsspx */\n+\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\tgoto vsxunavail;\n+\t\t\top->reg = rd | ((instr & 1) << 5);\n+\t\t\top->type = MKOP(STORE_VSX, 0, 4);\n+\t\t\top->element_size = 8;\n+\t\t\top->vsx_flags = VSX_FPCONV;\n+\t\t\tbreak;\n+\n+\t\tcase 716:\t/* stxsdx */\n+\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\tgoto vsxunavail;\n+\t\t\top->reg = rd | ((instr & 1) << 5);\n+\t\t\top->type = MKOP(STORE_VSX, 0, 8);\n+\t\t\top->element_size = 8;\n+\t\t\tbreak;\n+\n+\t\tcase 780:\t/* lxvw4x */\n+\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\tgoto vsxunavail;\n+\t\t\top->reg = rd | ((instr & 1) << 5);\n+\t\t\top->type = MKOP(LOAD_VSX, 0, 16);\n+\t\t\top->element_size = 4;\n+\t\t\tbreak;\n+\n+\t\tcase 781:\t/* lxsibzx */\n+\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\tgoto vsxunavail;\n+\t\t\top->reg = rd | ((instr & 1) << 5);\n+\t\t\top->type = MKOP(LOAD_VSX, 0, 1);\n+\t\t\top->element_size = 8;\n+\t\t\tbreak;\n+\n+\t\tcase 812:\t/* lxvh8x */\n+\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\tgoto vsxunavail;\n+\t\t\top->reg = rd | ((instr & 1) << 5);\n+\t\t\top->type = MKOP(LOAD_VSX, 0, 16);\n+\t\t\top->element_size = 2;\n+\t\t\tbreak;\n+\n+\t\tcase 813:\t/* lxsihzx */\n+\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\tgoto vsxunavail;\n+\t\t\top->reg = rd | ((instr & 1) << 5);\n+\t\t\top->type = MKOP(LOAD_VSX, 0, 2);\n+\t\t\top->element_size = 8;\n+\t\t\tbreak;\n+\n \t\tcase 844:\t/* lxvd2x */\n-\t\tcase 876:\t/* lxvd2ux */\n \t\t\tif (!(regs->msr & MSR_VSX))\n \t\t\t\tgoto vsxunavail;\n \t\t\top->reg = rd | ((instr & 1) << 5);\n-\t\t\top->type = MKOP(LOAD_VSX, u, 16);\n+\t\t\top->type = MKOP(LOAD_VSX, 0, 16);\n+\t\t\top->element_size = 8;\n+\t\t\tbreak;\n+\n+\t\tcase 876:\t/* lxvb16x */\n+\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\tgoto vsxunavail;\n+\t\t\top->reg = rd | ((instr & 1) << 5);\n+\t\t\top->type = MKOP(LOAD_VSX, 0, 16);\n+\t\t\top->element_size = 1;\n+\t\t\tbreak;\n+\n+\t\tcase 908:\t/* stxvw4x */\n+\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\tgoto vsxunavail;\n+\t\t\top->reg = rd | ((instr & 1) << 5);\n+\t\t\top->type = MKOP(STORE_VSX, 0, 16);\n+\t\t\top->element_size = 4;\n+\t\t\tbreak;\n+\n+\t\tcase 909:\t/* stxsibx */\n+\t\t\tif (!(instr & 1)) {\n+\t\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\t\tgoto vsxunavail;\n+\t\t\t} else {\n+\t\t\t\tif (!(regs->msr & MSR_VEC))\n+\t\t\t\t\tgoto vecunavail;\n+\t\t\t\top->reg = rd + 32;\n+\t\t\t}\n+\t\t\top->type = MKOP(STORE_VSX, 0, 1);\n+\t\t\top->element_size = 8;\n+\t\t\tbreak;\n+\n+\t\tcase 940:\t/* stxvh8x */\n+\t\t\tif (!(instr & 1)) {\n+\t\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\t\tgoto vsxunavail;\n+\t\t\t} else {\n+\t\t\t\tif (!(regs->msr & MSR_VEC))\n+\t\t\t\t\tgoto vecunavail;\n+\t\t\t\top->reg = rd + 32;\n+\t\t\t}\n+\t\t\top->type = MKOP(STORE_VSX, 0, 16);\n+\t\t\top->element_size = 2;\n+\t\t\tbreak;\n+\n+\t\tcase 941:\t/* stxsihx */\n+\t\t\tif (!(instr & 1)) {\n+\t\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\t\tgoto vsxunavail;\n+\t\t\t} else {\n+\t\t\t\tif (!(regs->msr & MSR_VEC))\n+\t\t\t\t\tgoto vecunavail;\n+\t\t\t\top->reg = rd + 32;\n+\t\t\t}\n+\t\t\top->type = MKOP(STORE_VSX, 0, 2);\n+\t\t\top->element_size = 8;\n \t\t\tbreak;\n \n \t\tcase 972:\t/* stxvd2x */\n-\t\tcase 1004:\t/* stxvd2ux */\n \t\t\tif (!(regs->msr & MSR_VSX))\n \t\t\t\tgoto vsxunavail;\n \t\t\top->reg = rd | ((instr & 1) << 5);\n-\t\t\top->type = MKOP(STORE_VSX, u, 16);\n+\t\t\top->type = MKOP(STORE_VSX, 0, 16);\n+\t\t\top->element_size = 8;\n+\t\t\tbreak;\n+\n+\t\tcase 1004:\t/* stxvb16x */\n+\t\t\tif (!(instr & 1)) {\n+\t\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\t\tgoto vsxunavail;\n+\t\t\t} else {\n+\t\t\t\tif (!(regs->msr & MSR_VEC))\n+\t\t\t\t\tgoto vecunavail;\n+\t\t\t\top->reg = rd + 32;\n+\t\t\t}\n+\t\t\top->type = MKOP(STORE_VSX, 0, 16);\n+\t\t\top->element_size = 1;\n \t\t\tbreak;\n \n #endif /* CONFIG_VSX */\n@@ -1754,6 +2220,37 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,\n #endif\n \n #ifdef __powerpc64__\n+\tcase 56:\t/* lq */\n+\t\tif (!((rd & 1) || (rd == ra)))\n+\t\t\top->type = MKOP(LOAD, 0, 16);\n+\t\top->ea = dqform_ea(instr, regs);\n+\t\tbreak;\n+#endif\n+\n+#ifdef CONFIG_VSX\n+\tcase 57:\t/* lxsd, lxssp */\n+\t\top->ea = dsform_ea(instr, regs);\n+\t\tswitch (instr & 3) {\n+\t\tcase 2:\t\t/* lxsd */\n+\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\tgoto vsxunavail;\n+\t\t\top->reg = rd + 32;\n+\t\t\top->type = MKOP(LOAD_VSX, 0, 8);\n+\t\t\top->element_size = 8;\n+\t\t\tbreak;\n+\t\tcase 3:\t\t/* lxssp */\n+\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\tgoto vsxunavail;\n+\t\t\top->reg = rd + 32;\n+\t\t\top->type = MKOP(LOAD_VSX, 0, 4);\n+\t\t\top->element_size = 8;\n+\t\t\top->vsx_flags = VSX_FPCONV;\n+\t\t\tbreak;\n+\t\t}\n+\t\tbreak;\n+#endif /* CONFIG_VSX */\n+\n+#ifdef __powerpc64__\n \tcase 58:\t/* ld[u], lwa */\n \t\top->ea = dsform_ea(instr, regs);\n \t\tswitch (instr & 3) {\n@@ -1768,7 +2265,64 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,\n \t\t\tbreak;\n \t\t}\n \t\tbreak;\n+#endif\n+\n+#ifdef CONFIG_VSX\n+\tcase 61:\t/* lxv, stxsd, stxssp, stxv */\n+\t\tswitch (instr & 7) {\n+\t\tcase 1:\t\t/* lxv */\n+\t\t\top->ea = dqform_ea(instr, regs);\n+\t\t\tif (!(instr & 8)) {\n+\t\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\t\tgoto vsxunavail;\n+\t\t\t} else {\n+\t\t\t\tif (!(regs->msr & MSR_VEC))\n+\t\t\t\t\tgoto vecunavail;\n+\t\t\t\top->reg = rd + 32;\n+\t\t\t}\n+\t\t\top->type = MKOP(LOAD_VSX, 0, 16);\n+\t\t\top->element_size = 16;\n+\t\t\tbreak;\n+\n+\t\tcase 2:\t\t/* stxsd with LSB of DS field = 0 */\n+\t\tcase 6:\t\t/* stxsd with LSB of DS field = 1 */\n+\t\t\top->ea = dsform_ea(instr, regs);\n+\t\t\tif (!(regs->msr & MSR_VEC))\n+\t\t\t\tgoto vecunavail;\n+\t\t\top->reg = rd + 32;\n+\t\t\top->type = MKOP(STORE_VSX, 0, 8);\n+\t\t\top->element_size = 8;\n+\t\t\tbreak;\n+\n+\t\tcase 3:\t\t/* stxssp with LSB of DS field = 0 */\n+\t\tcase 7:\t\t/* stxssp with LSB of DS field = 1 */\n+\t\t\top->ea = dsform_ea(instr, regs);\n+\t\t\tif (!(regs->msr & MSR_VEC))\n+\t\t\t\tgoto vecunavail;\n+\t\t\top->reg = rd + 32;\n+\t\t\top->type = MKOP(STORE_VSX, 0, 4);\n+\t\t\top->element_size = 8;\n+\t\t\top->vsx_flags = VSX_FPCONV;\n+\t\t\tbreak;\n+\n+\t\tcase 5:\t\t/* stxv */\n+\t\t\top->ea = dqform_ea(instr, regs);\n+\t\t\tif (!(instr & 8)) {\n+\t\t\t\tif (!(regs->msr & MSR_VSX))\n+\t\t\t\t\tgoto vsxunavail;\n+\t\t\t} else {\n+\t\t\t\tif (!(regs->msr & MSR_VEC))\n+\t\t\t\t\tgoto vecunavail;\n+\t\t\t\top->reg = rd + 32;\n+\t\t\t}\n+\t\t\top->type = MKOP(STORE_VSX, 0, 16);\n+\t\t\top->element_size = 16;\n+\t\t\tbreak;\n+\t\t}\n+\t\tbreak;\n+#endif /* CONFIG_VSX */\n \n+#ifdef __powerpc64__\n \tcase 62:\t/* std[u] */\n \t\top->ea = dsform_ea(instr, regs);\n \t\tswitch (instr & 3) {\n@@ -1778,6 +2332,10 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,\n \t\tcase 1:\t\t/* stdu */\n \t\t\top->type = MKOP(STORE, UPDATE, 8);\n \t\t\tbreak;\n+\t\tcase 2:\t\t/* stq */\n+\t\t\tif (!(rd & 1))\n+\t\t\t\top->type = MKOP(STORE, 0, 16);\n+\t\t\tbreak;\n \t\t}\n \t\tbreak;\n #endif /* __powerpc64__ */\n@@ -1941,6 +2499,14 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)\n \t\t\treturn 0;\n \t\terr = 0;\n \t\tswitch (size) {\n+#ifdef __powerpc64__\n+\t\tcase 1:\n+\t\t\t__get_user_asmx(val, op.ea, err, \"lbarx\");\n+\t\t\tbreak;\n+\t\tcase 2:\n+\t\t\t__get_user_asmx(val, op.ea, err, \"lharx\");\n+\t\t\tbreak;\n+#endif\n \t\tcase 4:\n \t\t\t__get_user_asmx(val, op.ea, err, \"lwarx\");\n \t\t\tbreak;\n@@ -1948,6 +2514,9 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)\n \t\tcase 8:\n \t\t\t__get_user_asmx(val, op.ea, err, \"ldarx\");\n \t\t\tbreak;\n+\t\tcase 16:\n+\t\t\terr = do_lqarx(op.ea, &regs->gpr[op.reg]);\n+\t\t\tgoto ldst_done;\n #endif\n \t\tdefault:\n \t\t\treturn 0;\n@@ -1963,6 +2532,14 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)\n \t\t\treturn 0;\n \t\terr = 0;\n \t\tswitch (size) {\n+#ifdef __powerpc64__\n+\t\tcase 1:\n+\t\t\t__put_user_asmx(op.val, op.ea, err, \"stbcx.\", cr);\n+\t\t\tbreak;\n+\t\tcase 2:\n+\t\t\t__put_user_asmx(op.val, op.ea, err, \"stbcx.\", cr);\n+\t\t\tbreak;\n+#endif\n \t\tcase 4:\n \t\t\t__put_user_asmx(op.val, op.ea, err, \"stwcx.\", cr);\n \t\t\tbreak;\n@@ -1970,6 +2547,10 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)\n \t\tcase 8:\n \t\t\t__put_user_asmx(op.val, op.ea, err, \"stdcx.\", cr);\n \t\t\tbreak;\n+\t\tcase 16:\n+\t\t\terr = do_stqcx(op.ea, regs->gpr[op.reg],\n+\t\t\t\t       regs->gpr[op.reg + 1], &cr);\n+\t\t\tbreak;\n #endif\n \t\tdefault:\n \t\t\treturn 0;\n@@ -1981,6 +2562,12 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)\n \t\tgoto ldst_done;\n \n \tcase LOAD:\n+#ifdef __powerpc64__\n+\t\tif (size == 16) {\n+\t\t\terr = emulate_lq(regs, op.ea, op.reg);\n+\t\t\tgoto ldst_done;\n+\t\t}\n+#endif\n \t\terr = read_mem(&regs->gpr[op.reg], op.ea, size, regs);\n \t\tif (!err) {\n \t\t\tif (op.type & SIGNEXT)\n@@ -2000,13 +2587,22 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)\n #endif\n #ifdef CONFIG_ALTIVEC\n \tcase LOAD_VMX:\n-\t\terr = do_vec_load(op.reg, do_lvx, op.ea & ~0xfUL, regs);\n+\t\terr = do_vec_load(op.reg, do_lvx, op.ea, regs);\n \t\tgoto ldst_done;\n #endif\n #ifdef CONFIG_VSX\n-\tcase LOAD_VSX:\n-\t\terr = do_vsx_load(op.reg, do_lxvd2x, op.ea, regs);\n+\tcase LOAD_VSX: {\n+\t\tchar mem[16];\n+\t\tunion vsx_reg buf;\n+\n+\t\tif (!address_ok(regs, op.ea, size) ||\n+\t\t    __copy_from_user(mem, (void __user *)op.ea, size))\n+\t\t\treturn 0;\n+\n+\t\temulate_vsx_load(&op, &buf, mem);\n+\t\tload_vsrn(op.reg, &buf);\n \t\tgoto ldst_done;\n+\t}\n #endif\n \tcase LOAD_MULTI:\n \t\tif (regs->msr & MSR_LE)\n@@ -2027,6 +2623,12 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)\n \t\tgoto instr_done;\n \n \tcase STORE:\n+#ifdef __powerpc64__\n+\t\tif (size == 16) {\n+\t\t\terr = emulate_stq(regs, op.ea, op.reg);\n+\t\t\tgoto ldst_done;\n+\t\t}\n+#endif\n \t\tif ((op.type & UPDATE) && size == sizeof(long) &&\n \t\t    op.reg == 1 && op.update_reg == 1 &&\n \t\t    !(regs->msr & MSR_PR) &&\n@@ -2047,13 +2649,23 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)\n #endif\n #ifdef CONFIG_ALTIVEC\n \tcase STORE_VMX:\n-\t\terr = do_vec_store(op.reg, do_stvx, op.ea & ~0xfUL, regs);\n+\t\terr = do_vec_store(op.reg, do_stvx, op.ea, regs);\n \t\tgoto ldst_done;\n #endif\n #ifdef CONFIG_VSX\n-\tcase STORE_VSX:\n-\t\terr = do_vsx_store(op.reg, do_stxvd2x, op.ea, regs);\n+\tcase STORE_VSX: {\n+\t\tchar mem[16];\n+\t\tunion vsx_reg buf;\n+\n+\t\tif (!address_ok(regs, op.ea, size))\n+\t\t\treturn 0;\n+\n+\t\tstore_vsrn(op.reg, &buf);\n+\t\temulate_vsx_store(&op, &buf, mem);\n+\t\tif (__copy_to_user((void __user *)op.ea, mem, size))\n+\t\t\treturn 0;\n \t\tgoto ldst_done;\n+\t}\n #endif\n \tcase STORE_MULTI:\n \t\tif (regs->msr & MSR_LE)\n",
    "prefixes": [
        "v2",
        "01/10"
    ]
}