]> git.proxmox.com Git - mirror_qemu.git/blame - target/riscv/insn_trans/trans_xthead.c.inc
RISC-V: Adding XTheadBa ISA extension
[mirror_qemu.git] / target / riscv / insn_trans / trans_xthead.c.inc
CommitLineData
49a7f3aa
CM
1/*
2 * RISC-V translation routines for the T-Head vendor extensions (xthead*).
3 *
4 * Copyright (c) 2022 VRULL GmbH.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2 or later, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
c9410a68
CM
19#define REQUIRE_XTHEADBA(ctx) do { \
20 if (!ctx->cfg_ptr->ext_xtheadba) { \
21 return false; \
22 } \
23} while (0)
24
49a7f3aa
CM
25#define REQUIRE_XTHEADCMO(ctx) do { \
26 if (!ctx->cfg_ptr->ext_xtheadcmo) { \
27 return false; \
28 } \
29} while (0)
30
134c3ffa
CM
31#define REQUIRE_XTHEADSYNC(ctx) do { \
32 if (!ctx->cfg_ptr->ext_xtheadsync) { \
33 return false; \
34 } \
35} while (0)
36
c9410a68
CM
37/* XTheadBa */
38
39/*
40 * th.addsl is similar to sh[123]add (from Zba), but not an
41 * alternative encoding: while sh[123] applies the shift to rs1,
42 * th.addsl shifts rs2.
43 */
44
45#define GEN_TH_ADDSL(SHAMT) \
46static void gen_th_addsl##SHAMT(TCGv ret, TCGv arg1, TCGv arg2) \
47{ \
48 TCGv t = tcg_temp_new(); \
49 tcg_gen_shli_tl(t, arg2, SHAMT); \
50 tcg_gen_add_tl(ret, t, arg1); \
51 tcg_temp_free(t); \
52}
53
54GEN_TH_ADDSL(1)
55GEN_TH_ADDSL(2)
56GEN_TH_ADDSL(3)
57
58#define GEN_TRANS_TH_ADDSL(SHAMT) \
59static bool trans_th_addsl##SHAMT(DisasContext *ctx, \
60 arg_th_addsl##SHAMT * a) \
61{ \
62 REQUIRE_XTHEADBA(ctx); \
63 return gen_arith(ctx, a, EXT_NONE, gen_th_addsl##SHAMT, NULL); \
64}
65
66GEN_TRANS_TH_ADDSL(1)
67GEN_TRANS_TH_ADDSL(2)
68GEN_TRANS_TH_ADDSL(3)
69
49a7f3aa
CM
70/* XTheadCmo */
71
72static inline int priv_level(DisasContext *ctx)
73{
74#ifdef CONFIG_USER_ONLY
75 return PRV_U;
76#else
77 /* Priv level is part of mem_idx. */
78 return ctx->mem_idx & TB_FLAGS_PRIV_MMU_MASK;
79#endif
80}
81
82/* Test if priv level is M, S, or U (cannot fail). */
83#define REQUIRE_PRIV_MSU(ctx)
84
85/* Test if priv level is M or S. */
86#define REQUIRE_PRIV_MS(ctx) \
87do { \
88 int priv = priv_level(ctx); \
89 if (!(priv == PRV_M || \
90 priv == PRV_S)) { \
91 return false; \
92 } \
93} while (0)
94
95#define NOP_PRIVCHECK(insn, extcheck, privcheck) \
96static bool trans_ ## insn(DisasContext *ctx, arg_ ## insn * a) \
97{ \
98 (void) a; \
99 extcheck(ctx); \
100 privcheck(ctx); \
101 return true; \
102}
103
104NOP_PRIVCHECK(th_dcache_call, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
105NOP_PRIVCHECK(th_dcache_ciall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
106NOP_PRIVCHECK(th_dcache_iall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
107NOP_PRIVCHECK(th_dcache_cpa, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
108NOP_PRIVCHECK(th_dcache_cipa, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
109NOP_PRIVCHECK(th_dcache_ipa, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
110NOP_PRIVCHECK(th_dcache_cva, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MSU)
111NOP_PRIVCHECK(th_dcache_civa, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MSU)
112NOP_PRIVCHECK(th_dcache_iva, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MSU)
113NOP_PRIVCHECK(th_dcache_csw, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
114NOP_PRIVCHECK(th_dcache_cisw, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
115NOP_PRIVCHECK(th_dcache_isw, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
116NOP_PRIVCHECK(th_dcache_cpal1, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
117NOP_PRIVCHECK(th_dcache_cval1, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
118
119NOP_PRIVCHECK(th_icache_iall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
120NOP_PRIVCHECK(th_icache_ialls, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
121NOP_PRIVCHECK(th_icache_ipa, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
122NOP_PRIVCHECK(th_icache_iva, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MSU)
123
124NOP_PRIVCHECK(th_l2cache_call, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
125NOP_PRIVCHECK(th_l2cache_ciall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
126NOP_PRIVCHECK(th_l2cache_iall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
134c3ffa
CM
127
128/* XTheadSync */
129
130static bool trans_th_sfence_vmas(DisasContext *ctx, arg_th_sfence_vmas *a)
131{
132 (void) a;
133 REQUIRE_XTHEADSYNC(ctx);
134
135#ifndef CONFIG_USER_ONLY
136 REQUIRE_PRIV_MS(ctx);
137 gen_helper_tlb_flush_all(cpu_env);
138 return true;
139#else
140 return false;
141#endif
142}
143
144#ifndef CONFIG_USER_ONLY
145static void gen_th_sync_local(DisasContext *ctx)
146{
147 /*
148 * Emulate out-of-order barriers with pipeline flush
149 * by exiting the translation block.
150 */
151 gen_set_pc_imm(ctx, ctx->pc_succ_insn);
152 tcg_gen_exit_tb(NULL, 0);
153 ctx->base.is_jmp = DISAS_NORETURN;
154}
155#endif
156
157static bool trans_th_sync(DisasContext *ctx, arg_th_sync *a)
158{
159 (void) a;
160 REQUIRE_XTHEADSYNC(ctx);
161
162#ifndef CONFIG_USER_ONLY
163 REQUIRE_PRIV_MSU(ctx);
164
165 /*
166 * th.sync is an out-of-order barrier.
167 */
168 gen_th_sync_local(ctx);
169
170 return true;
171#else
172 return false;
173#endif
174}
175
176static bool trans_th_sync_i(DisasContext *ctx, arg_th_sync_i *a)
177{
178 (void) a;
179 REQUIRE_XTHEADSYNC(ctx);
180
181#ifndef CONFIG_USER_ONLY
182 REQUIRE_PRIV_MSU(ctx);
183
184 /*
185 * th.sync.i is th.sync plus pipeline flush.
186 */
187 gen_th_sync_local(ctx);
188
189 return true;
190#else
191 return false;
192#endif
193}
194
195static bool trans_th_sync_is(DisasContext *ctx, arg_th_sync_is *a)
196{
197 /* This instruction has the same behaviour like th.sync.i. */
198 return trans_th_sync_i(ctx, a);
199}
200
201static bool trans_th_sync_s(DisasContext *ctx, arg_th_sync_s *a)
202{
203 /* This instruction has the same behaviour like th.sync. */
204 return trans_th_sync(ctx, a);
205}