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
19#ifdef CONFIG_USER_ONLY
20#define do_hlv(ctx, a, func)  false
21#define do_hsv(ctx, a, func)  false
22#else
23static void gen_helper_hyp_hlv_b(TCGv r, TCGv_env e, TCGv a)
24{
25    gen_helper_hyp_hlv_bu(r, e, a);
26    tcg_gen_ext8s_tl(r, r);
27}
28
29static void gen_helper_hyp_hlv_h(TCGv r, TCGv_env e, TCGv a)
30{
31    gen_helper_hyp_hlv_hu(r, e, a);
32    tcg_gen_ext16s_tl(r, r);
33}
34
35static void gen_helper_hyp_hlv_w(TCGv r, TCGv_env e, TCGv a)
36{
37    gen_helper_hyp_hlv_wu(r, e, a);
38    tcg_gen_ext32s_tl(r, r);
39}
40
41static bool do_hlv(DisasContext *ctx, arg_r2 *a,
42                   void (*func)(TCGv, TCGv_env, TCGv))
43{
44    TCGv dest = dest_gpr(ctx, a->rd);
45    TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
46
47    decode_save_opc(ctx);
48    func(dest, cpu_env, addr);
49    gen_set_gpr(ctx, a->rd, dest);
50    return true;
51}
52
53static bool do_hsv(DisasContext *ctx, arg_r2_s *a,
54                   void (*func)(TCGv_env, TCGv, TCGv))
55{
56    TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
57    TCGv data = get_gpr(ctx, a->rs2, EXT_NONE);
58
59    decode_save_opc(ctx);
60    func(cpu_env, addr, data);
61    return true;
62}
63#endif /* CONFIG_USER_ONLY */
64
65static bool trans_hlv_b(DisasContext *ctx, arg_hlv_b *a)
66{
67    REQUIRE_EXT(ctx, RVH);
68    return do_hlv(ctx, a, gen_helper_hyp_hlv_b);
69}
70
71static bool trans_hlv_h(DisasContext *ctx, arg_hlv_h *a)
72{
73    REQUIRE_EXT(ctx, RVH);
74    return do_hlv(ctx, a, gen_helper_hyp_hlv_h);
75}
76
77static bool trans_hlv_w(DisasContext *ctx, arg_hlv_w *a)
78{
79    REQUIRE_EXT(ctx, RVH);
80    return do_hlv(ctx, a, gen_helper_hyp_hlv_w);
81}
82
83static bool trans_hlv_bu(DisasContext *ctx, arg_hlv_bu *a)
84{
85    REQUIRE_EXT(ctx, RVH);
86    return do_hlv(ctx, a, gen_helper_hyp_hlv_bu);
87}
88
89static bool trans_hlv_hu(DisasContext *ctx, arg_hlv_hu *a)
90{
91    REQUIRE_EXT(ctx, RVH);
92    return do_hlv(ctx, a, gen_helper_hyp_hlv_hu);
93}
94
95static bool trans_hsv_b(DisasContext *ctx, arg_hsv_b *a)
96{
97    REQUIRE_EXT(ctx, RVH);
98    return do_hsv(ctx, a, gen_helper_hyp_hsv_b);
99}
100
101static bool trans_hsv_h(DisasContext *ctx, arg_hsv_h *a)
102{
103    REQUIRE_EXT(ctx, RVH);
104    return do_hsv(ctx, a, gen_helper_hyp_hsv_h);
105}
106
107static bool trans_hsv_w(DisasContext *ctx, arg_hsv_w *a)
108{
109    REQUIRE_EXT(ctx, RVH);
110    return do_hsv(ctx, a, gen_helper_hyp_hsv_w);
111}
112
113static bool trans_hlv_wu(DisasContext *ctx, arg_hlv_wu *a)
114{
115    REQUIRE_64BIT(ctx);
116    REQUIRE_EXT(ctx, RVH);
117    return do_hlv(ctx, a, gen_helper_hyp_hlv_wu);
118}
119
120static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a)
121{
122    REQUIRE_64BIT(ctx);
123    REQUIRE_EXT(ctx, RVH);
124    return do_hlv(ctx, a, gen_helper_hyp_hlv_d);
125}
126
127static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a)
128{
129    REQUIRE_64BIT(ctx);
130    REQUIRE_EXT(ctx, RVH);
131    return do_hsv(ctx, a, gen_helper_hyp_hsv_d);
132}
133
134static bool trans_hlvx_hu(DisasContext *ctx, arg_hlvx_hu *a)
135{
136    REQUIRE_EXT(ctx, RVH);
137    return do_hlv(ctx, a, gen_helper_hyp_hlvx_hu);
138}
139
140static bool trans_hlvx_wu(DisasContext *ctx, arg_hlvx_wu *a)
141{
142    REQUIRE_EXT(ctx, RVH);
143    return do_hlv(ctx, a, gen_helper_hyp_hlvx_wu);
144}
145
146static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a)
147{
148    REQUIRE_EXT(ctx, RVH);
149#ifndef CONFIG_USER_ONLY
150    decode_save_opc(ctx);
151    gen_helper_hyp_gvma_tlb_flush(cpu_env);
152    return true;
153#endif
154    return false;
155}
156
157static bool trans_hfence_vvma(DisasContext *ctx, arg_sfence_vma *a)
158{
159    REQUIRE_EXT(ctx, RVH);
160#ifndef CONFIG_USER_ONLY
161    decode_save_opc(ctx);
162    gen_helper_hyp_tlb_flush(cpu_env);
163    return true;
164#endif
165    return false;
166}
167