1/*
2 * RISC-V translation routines for the RVXI Base Integer Instruction Set.
3 *
4 * Copyright (c) 2020 Western Digital
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
19static bool trans_hlv_b(DisasContext *ctx, arg_hlv_b *a)
20{
21    REQUIRE_EXT(ctx, RVH);
22#ifndef CONFIG_USER_ONLY
23    TCGv t0 = tcg_temp_new();
24    TCGv t1 = tcg_temp_new();
25    TCGv mem_idx = tcg_temp_new();
26    TCGv memop = tcg_temp_new();
27
28    gen_get_gpr(t0, a->rs1);
29    tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
30    tcg_gen_movi_tl(memop, MO_SB);
31
32    gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
33    gen_set_gpr(a->rd, t1);
34
35    tcg_temp_free(t0);
36    tcg_temp_free(t1);
37    tcg_temp_free(mem_idx);
38    tcg_temp_free(memop);
39    return true;
40#else
41    return false;
42#endif
43}
44
45static bool trans_hlv_h(DisasContext *ctx, arg_hlv_h *a)
46{
47    REQUIRE_EXT(ctx, RVH);
48#ifndef CONFIG_USER_ONLY
49    TCGv t0 = tcg_temp_new();
50    TCGv t1 = tcg_temp_new();
51    TCGv mem_idx = tcg_temp_new();
52    TCGv memop = tcg_temp_new();
53
54    gen_get_gpr(t0, a->rs1);
55    tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
56    tcg_gen_movi_tl(memop, MO_TESW);
57
58    gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
59    gen_set_gpr(a->rd, t1);
60
61    tcg_temp_free(t0);
62    tcg_temp_free(t1);
63    tcg_temp_free(mem_idx);
64    tcg_temp_free(memop);
65    return true;
66#else
67    return false;
68#endif
69}
70
71static bool trans_hlv_w(DisasContext *ctx, arg_hlv_w *a)
72{
73    REQUIRE_EXT(ctx, RVH);
74#ifndef CONFIG_USER_ONLY
75    TCGv t0 = tcg_temp_new();
76    TCGv t1 = tcg_temp_new();
77    TCGv mem_idx = tcg_temp_new();
78    TCGv memop = tcg_temp_new();
79
80    gen_get_gpr(t0, a->rs1);
81    tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
82    tcg_gen_movi_tl(memop, MO_TESL);
83
84    gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
85    gen_set_gpr(a->rd, t1);
86
87    tcg_temp_free(t0);
88    tcg_temp_free(t1);
89    tcg_temp_free(mem_idx);
90    tcg_temp_free(memop);
91    return true;
92#else
93    return false;
94#endif
95}
96
97static bool trans_hlv_bu(DisasContext *ctx, arg_hlv_bu *a)
98{
99    REQUIRE_EXT(ctx, RVH);
100#ifndef CONFIG_USER_ONLY
101    TCGv t0 = tcg_temp_new();
102    TCGv t1 = tcg_temp_new();
103    TCGv mem_idx = tcg_temp_new();
104    TCGv memop = tcg_temp_new();
105
106    gen_get_gpr(t0, a->rs1);
107    tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
108    tcg_gen_movi_tl(memop, MO_UB);
109
110    gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
111    gen_set_gpr(a->rd, t1);
112
113    tcg_temp_free(t0);
114    tcg_temp_free(t1);
115    tcg_temp_free(mem_idx);
116    tcg_temp_free(memop);
117    return true;
118#else
119    return false;
120#endif
121}
122
123static bool trans_hlv_hu(DisasContext *ctx, arg_hlv_hu *a)
124{
125    REQUIRE_EXT(ctx, RVH);
126#ifndef CONFIG_USER_ONLY
127    TCGv t0 = tcg_temp_new();
128    TCGv t1 = tcg_temp_new();
129    TCGv mem_idx = tcg_temp_new();
130    TCGv memop = tcg_temp_new();
131
132    gen_get_gpr(t0, a->rs1);
133    tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
134    tcg_gen_movi_tl(memop, MO_TEUW);
135
136    gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
137    gen_set_gpr(a->rd, t1);
138
139    tcg_temp_free(t0);
140    tcg_temp_free(t1);
141    tcg_temp_free(mem_idx);
142    tcg_temp_free(memop);
143    return true;
144#else
145    return false;
146#endif
147}
148
149static bool trans_hsv_b(DisasContext *ctx, arg_hsv_b *a)
150{
151    REQUIRE_EXT(ctx, RVH);
152#ifndef CONFIG_USER_ONLY
153    TCGv t0 = tcg_temp_new();
154    TCGv dat = tcg_temp_new();
155    TCGv mem_idx = tcg_temp_new();
156    TCGv memop = tcg_temp_new();
157
158    gen_get_gpr(t0, a->rs1);
159    gen_get_gpr(dat, a->rs2);
160    tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
161    tcg_gen_movi_tl(memop, MO_SB);
162
163    gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop);
164
165    tcg_temp_free(t0);
166    tcg_temp_free(dat);
167    tcg_temp_free(mem_idx);
168    tcg_temp_free(memop);
169    return true;
170#else
171    return false;
172#endif
173}
174
175static bool trans_hsv_h(DisasContext *ctx, arg_hsv_h *a)
176{
177    REQUIRE_EXT(ctx, RVH);
178#ifndef CONFIG_USER_ONLY
179    TCGv t0 = tcg_temp_new();
180    TCGv dat = tcg_temp_new();
181    TCGv mem_idx = tcg_temp_new();
182    TCGv memop = tcg_temp_new();
183
184    gen_get_gpr(t0, a->rs1);
185    gen_get_gpr(dat, a->rs2);
186    tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
187    tcg_gen_movi_tl(memop, MO_TESW);
188
189    gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop);
190
191    tcg_temp_free(t0);
192    tcg_temp_free(dat);
193    tcg_temp_free(mem_idx);
194    tcg_temp_free(memop);
195    return true;
196#else
197    return false;
198#endif
199}
200
201static bool trans_hsv_w(DisasContext *ctx, arg_hsv_w *a)
202{
203    REQUIRE_EXT(ctx, RVH);
204#ifndef CONFIG_USER_ONLY
205    TCGv t0 = tcg_temp_new();
206    TCGv dat = tcg_temp_new();
207    TCGv mem_idx = tcg_temp_new();
208    TCGv memop = tcg_temp_new();
209
210    gen_get_gpr(t0, a->rs1);
211    gen_get_gpr(dat, a->rs2);
212    tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
213    tcg_gen_movi_tl(memop, MO_TESL);
214
215    gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop);
216
217    tcg_temp_free(t0);
218    tcg_temp_free(dat);
219    tcg_temp_free(mem_idx);
220    tcg_temp_free(memop);
221    return true;
222#else
223    return false;
224#endif
225}
226
227#ifdef TARGET_RISCV64
228static bool trans_hlv_wu(DisasContext *ctx, arg_hlv_wu *a)
229{
230    REQUIRE_EXT(ctx, RVH);
231#ifndef CONFIG_USER_ONLY
232    TCGv t0 = tcg_temp_new();
233    TCGv t1 = tcg_temp_new();
234    TCGv mem_idx = tcg_temp_new();
235    TCGv memop = tcg_temp_new();
236
237    gen_get_gpr(t0, a->rs1);
238    tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
239    tcg_gen_movi_tl(memop, MO_TEUL);
240
241    gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
242    gen_set_gpr(a->rd, t1);
243
244    tcg_temp_free(t0);
245    tcg_temp_free(t1);
246    tcg_temp_free(mem_idx);
247    tcg_temp_free(memop);
248    return true;
249#else
250    return false;
251#endif
252}
253
254static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a)
255{
256    REQUIRE_EXT(ctx, RVH);
257#ifndef CONFIG_USER_ONLY
258    TCGv t0 = tcg_temp_new();
259    TCGv t1 = tcg_temp_new();
260    TCGv mem_idx = tcg_temp_new();
261    TCGv memop = tcg_temp_new();
262
263    gen_get_gpr(t0, a->rs1);
264    tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
265    tcg_gen_movi_tl(memop, MO_TEQ);
266
267    gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
268    gen_set_gpr(a->rd, t1);
269
270    tcg_temp_free(t0);
271    tcg_temp_free(t1);
272    tcg_temp_free(mem_idx);
273    tcg_temp_free(memop);
274    return true;
275#else
276    return false;
277#endif
278}
279
280static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a)
281{
282    REQUIRE_EXT(ctx, RVH);
283#ifndef CONFIG_USER_ONLY
284    TCGv t0 = tcg_temp_new();
285    TCGv dat = tcg_temp_new();
286    TCGv mem_idx = tcg_temp_new();
287    TCGv memop = tcg_temp_new();
288
289    gen_get_gpr(t0, a->rs1);
290    gen_get_gpr(dat, a->rs2);
291    tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
292    tcg_gen_movi_tl(memop, MO_TEQ);
293
294    gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop);
295
296    tcg_temp_free(t0);
297    tcg_temp_free(dat);
298    tcg_temp_free(mem_idx);
299    tcg_temp_free(memop);
300    return true;
301#else
302    return false;
303#endif
304}
305#endif
306
307static bool trans_hlvx_hu(DisasContext *ctx, arg_hlvx_hu *a)
308{
309    REQUIRE_EXT(ctx, RVH);
310#ifndef CONFIG_USER_ONLY
311    TCGv t0 = tcg_temp_new();
312    TCGv t1 = tcg_temp_new();
313    TCGv mem_idx = tcg_temp_new();
314    TCGv memop = tcg_temp_new();
315
316    gen_get_gpr(t0, a->rs1);
317    tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
318    tcg_gen_movi_tl(memop, MO_TEUW);
319
320    gen_helper_hyp_x_load(t1, cpu_env, t0, mem_idx, memop);
321    gen_set_gpr(a->rd, t1);
322
323    tcg_temp_free(t0);
324    tcg_temp_free(t1);
325    tcg_temp_free(mem_idx);
326    tcg_temp_free(memop);
327    return true;
328#else
329    return false;
330#endif
331}
332
333static bool trans_hlvx_wu(DisasContext *ctx, arg_hlvx_wu *a)
334{
335    REQUIRE_EXT(ctx, RVH);
336#ifndef CONFIG_USER_ONLY
337    TCGv t0 = tcg_temp_new();
338    TCGv t1 = tcg_temp_new();
339    TCGv mem_idx = tcg_temp_new();
340    TCGv memop = tcg_temp_new();
341
342    gen_get_gpr(t0, a->rs1);
343    tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
344    tcg_gen_movi_tl(memop, MO_TEUL);
345
346    gen_helper_hyp_x_load(t1, cpu_env, t0, mem_idx, memop);
347    gen_set_gpr(a->rd, t1);
348
349    tcg_temp_free(t0);
350    tcg_temp_free(t1);
351    tcg_temp_free(mem_idx);
352    tcg_temp_free(memop);
353    return true;
354#else
355    return false;
356#endif
357}
358
359static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a)
360{
361    REQUIRE_EXT(ctx, RVH);
362#ifndef CONFIG_USER_ONLY
363    gen_helper_hyp_gvma_tlb_flush(cpu_env);
364    return true;
365#endif
366    return false;
367}
368
369static bool trans_hfence_vvma(DisasContext *ctx, arg_sfence_vma *a)
370{
371    REQUIRE_EXT(ctx, RVH);
372#ifndef CONFIG_USER_ONLY
373    gen_helper_hyp_tlb_flush(cpu_env);
374    return true;
375#endif
376    return false;
377}
378