1/*
2 * Power ISA decode for misc instructions
3 *
4 * Copyright (c) 2024, IBM Corporation.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20/*
21 * Memory Barrier Instructions
22 */
23
24static bool trans_SYNC(DisasContext *ctx, arg_X_sync *a)
25{
26    TCGBar bar = TCG_MO_ALL;
27    uint32_t l = a->l;
28    uint32_t sc = a->sc;
29
30    /*
31     * BookE uses the msync mnemonic. This means hwsync, except in the
32     * 440, where it an execution serialisation point that requires all
33     * previous storage accesses to have been performed to memory (which
34     * doesn't matter for TCG).
35     */
36    if (!(ctx->insns_flags & PPC_MEM_SYNC)) {
37        if (ctx->insns_flags & PPC_BOOKE) {
38            tcg_gen_mb(bar | TCG_BAR_SC);
39            return true;
40        }
41
42        return false;
43    }
44
45    /*
46     * In ISA v3.1, the L field grew one bit. Mask that out to ignore it in
47     * older processors. It also added the SC field, zero this to ignore
48     * it too.
49     */
50    if (!(ctx->insns_flags2 & PPC2_ISA310)) {
51        l &= 0x3;
52        sc = 0;
53    }
54
55    if (sc) {
56        /* Store syncs [stsync, stcisync, stncisync]. These ignore L. */
57        bar = TCG_MO_ST_ST;
58    } else {
59        if (((l == 1) && (ctx->insns_flags2 & PPC2_MEM_LWSYNC)) || (l == 5)) {
60            /* lwsync, or plwsync on POWER10 and later */
61            bar = TCG_MO_LD_LD | TCG_MO_LD_ST | TCG_MO_ST_ST;
62        }
63
64        /*
65         * We may need to check for a pending TLB flush.
66         *
67         * We do this on ptesync (l == 2) on ppc64 and any sync on ppc32.
68         *
69         * Additionally, this can only happen in kernel mode however so
70         * check MSR_PR as well.
71         */
72        if (((l == 2) || !(ctx->insns_flags & PPC_64B)) && !ctx->pr) {
73            gen_check_tlb_flush(ctx, true);
74        }
75    }
76
77    tcg_gen_mb(bar | TCG_BAR_SC);
78
79    return true;
80}
81
82static bool trans_EIEIO(DisasContext *ctx, arg_EIEIO *a)
83{
84    TCGBar bar = TCG_MO_ALL;
85
86    /*
87     * BookE uses the mbar instruction instead of eieio, which is basically
88     * full hwsync memory barrier, but is not execution synchronising. For
89     * the purpose of TCG the distinction is not relevant.
90     */
91    if (!(ctx->insns_flags & PPC_MEM_EIEIO)) {
92        if ((ctx->insns_flags & PPC_BOOKE) ||
93            (ctx->insns_flags2 & PPC2_BOOKE206)) {
94            tcg_gen_mb(bar | TCG_BAR_SC);
95            return true;
96        }
97        return false;
98    }
99
100    /*
101     * eieio has complex semanitcs. It provides memory ordering between
102     * operations in the set:
103     * - loads from CI memory.
104     * - stores to CI memory.
105     * - stores to WT memory.
106     *
107     * It separately also orders memory for operations in the set:
108     * - stores to cacheble memory.
109     *
110     * It also serializes instructions:
111     * - dcbt and dcbst.
112     *
113     * It separately serializes:
114     * - tlbie and tlbsync.
115     *
116     * And separately serializes:
117     * - slbieg, slbiag, and slbsync.
118     *
119     * The end result is that CI memory ordering requires TCG_MO_ALL
120     * and it is not possible to special-case more relaxed ordering for
121     * cacheable accesses. TCG_BAR_SC is required to provide this
122     * serialization.
123     */
124
125    /*
126     * POWER9 has a eieio instruction variant using bit 6 as a hint to
127     * tell the CPU it is a store-forwarding barrier.
128     */
129    if (ctx->opcode & 0x2000000) {
130        /*
131         * ISA says that "Reserved fields in instructions are ignored
132         * by the processor". So ignore the bit 6 on non-POWER9 CPU but
133         * as this is not an instruction software should be using,
134         * complain to the user.
135         */
136        if (!(ctx->insns_flags2 & PPC2_ISA300)) {
137            qemu_log_mask(LOG_GUEST_ERROR, "invalid eieio using bit 6 at @"
138                          TARGET_FMT_lx "\n", ctx->cia);
139        } else {
140            bar = TCG_MO_ST_LD;
141        }
142    }
143
144    tcg_gen_mb(bar | TCG_BAR_SC);
145
146    return true;
147}
148
149static bool trans_ATTN(DisasContext *ctx, arg_ATTN *a)
150{
151#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
152    gen_helper_attn(tcg_env);
153    return true;
154#else
155    return false;
156#endif
157}
158