1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * Copyright (c) 2021 Loongson Technology Corporation Limited
4 */
5
6static bool gen_rr(DisasContext *ctx, arg_rr *a,
7                   DisasExtend src_ext, DisasExtend dst_ext,
8                   void (*func)(TCGv, TCGv))
9{
10    TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
11    TCGv src1 = gpr_src(ctx, a->rj, src_ext);
12
13    func(dest, src1);
14    gen_set_gpr(a->rd, dest, dst_ext);
15
16    return true;
17}
18
19static void gen_bytepick_w(TCGv dest, TCGv src1, TCGv src2, target_long sa)
20{
21    tcg_gen_concat_tl_i64(dest, src1, src2);
22    tcg_gen_sextract_i64(dest, dest, (32 - sa * 8), 32);
23}
24
25static void gen_bytepick_d(TCGv dest, TCGv src1, TCGv src2, target_long sa)
26{
27    tcg_gen_extract2_i64(dest, src1, src2, (64 - sa * 8));
28}
29
30static bool gen_bstrins(DisasContext *ctx, arg_rr_ms_ls *a,
31                        DisasExtend dst_ext)
32{
33    TCGv src1 = gpr_src(ctx, a->rd, EXT_NONE);
34    TCGv src2 = gpr_src(ctx, a->rj, EXT_NONE);
35    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
36
37    if (a->ls > a->ms) {
38        return false;
39    }
40
41    tcg_gen_deposit_tl(dest, src1, src2, a->ls, a->ms - a->ls + 1);
42    gen_set_gpr(a->rd, dest, dst_ext);
43    return true;
44}
45
46static bool gen_bstrpick(DisasContext *ctx, arg_rr_ms_ls *a,
47                         DisasExtend dst_ext)
48{
49    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
50    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
51
52    if (a->ls > a->ms) {
53        return false;
54    }
55
56    tcg_gen_extract_tl(dest, src1, a->ls, a->ms - a->ls + 1);
57    gen_set_gpr(a->rd, dest, dst_ext);
58    return true;
59}
60
61static void gen_clz_w(TCGv dest, TCGv src1)
62{
63    tcg_gen_clzi_tl(dest, src1, TARGET_LONG_BITS);
64    tcg_gen_subi_tl(dest, dest, TARGET_LONG_BITS - 32);
65}
66
67static void gen_clo_w(TCGv dest, TCGv src1)
68{
69    tcg_gen_not_tl(dest, src1);
70    tcg_gen_ext32u_tl(dest, dest);
71    gen_clz_w(dest, dest);
72}
73
74static void gen_ctz_w(TCGv dest, TCGv src1)
75{
76    tcg_gen_ori_tl(dest, src1, (target_ulong)MAKE_64BIT_MASK(32, 32));
77    tcg_gen_ctzi_tl(dest, dest, TARGET_LONG_BITS);
78}
79
80static void gen_cto_w(TCGv dest, TCGv src1)
81{
82    tcg_gen_not_tl(dest, src1);
83    gen_ctz_w(dest, dest);
84}
85
86static void gen_clz_d(TCGv dest, TCGv src1)
87{
88    tcg_gen_clzi_i64(dest, src1, TARGET_LONG_BITS);
89}
90
91static void gen_clo_d(TCGv dest, TCGv src1)
92{
93    tcg_gen_not_tl(dest, src1);
94    gen_clz_d(dest, dest);
95}
96
97static void gen_ctz_d(TCGv dest, TCGv src1)
98{
99    tcg_gen_ctzi_tl(dest, src1, TARGET_LONG_BITS);
100}
101
102static void gen_cto_d(TCGv dest, TCGv src1)
103{
104    tcg_gen_not_tl(dest, src1);
105    gen_ctz_d(dest, dest);
106}
107
108static void gen_revb_2w(TCGv dest, TCGv src1)
109{
110    tcg_gen_bswap64_i64(dest, src1);
111    tcg_gen_rotri_i64(dest, dest, 32);
112}
113
114static void gen_revb_2h(TCGv dest, TCGv src1)
115{
116    TCGv mask = tcg_constant_tl(0x00FF00FF);
117    TCGv t0 = tcg_temp_new();
118    TCGv t1 = tcg_temp_new();
119
120    tcg_gen_shri_tl(t0, src1, 8);
121    tcg_gen_and_tl(t0, t0, mask);
122    tcg_gen_and_tl(t1, src1, mask);
123    tcg_gen_shli_tl(t1, t1, 8);
124    tcg_gen_or_tl(dest, t0, t1);
125
126    tcg_temp_free(t0);
127    tcg_temp_free(t1);
128}
129
130static void gen_revb_4h(TCGv dest, TCGv src1)
131{
132    TCGv mask = tcg_constant_tl(0x00FF00FF00FF00FFULL);
133    TCGv t0 = tcg_temp_new();
134    TCGv t1 = tcg_temp_new();
135
136    tcg_gen_shri_tl(t0, src1, 8);
137    tcg_gen_and_tl(t0, t0, mask);
138    tcg_gen_and_tl(t1, src1, mask);
139    tcg_gen_shli_tl(t1, t1, 8);
140    tcg_gen_or_tl(dest, t0, t1);
141
142    tcg_temp_free(t0);
143    tcg_temp_free(t1);
144}
145
146static void gen_revh_2w(TCGv dest, TCGv src1)
147{
148    TCGv_i64 t0 = tcg_temp_new_i64();
149    TCGv_i64 t1 = tcg_temp_new_i64();
150    TCGv_i64 mask = tcg_constant_i64(0x0000ffff0000ffffull);
151
152    tcg_gen_shri_i64(t0, src1, 16);
153    tcg_gen_and_i64(t1, src1, mask);
154    tcg_gen_and_i64(t0, t0, mask);
155    tcg_gen_shli_i64(t1, t1, 16);
156    tcg_gen_or_i64(dest, t1, t0);
157
158    tcg_temp_free_i64(t0);
159    tcg_temp_free_i64(t1);
160}
161
162static void gen_revh_d(TCGv dest, TCGv src1)
163{
164    TCGv t0 = tcg_temp_new();
165    TCGv t1 = tcg_temp_new();
166    TCGv mask = tcg_constant_tl(0x0000FFFF0000FFFFULL);
167
168    tcg_gen_shri_tl(t1, src1, 16);
169    tcg_gen_and_tl(t1, t1, mask);
170    tcg_gen_and_tl(t0, src1, mask);
171    tcg_gen_shli_tl(t0, t0, 16);
172    tcg_gen_or_tl(t0, t0, t1);
173    tcg_gen_rotri_tl(dest, t0, 32);
174
175    tcg_temp_free(t0);
176    tcg_temp_free(t1);
177}
178
179static void gen_maskeqz(TCGv dest, TCGv src1, TCGv src2)
180{
181    TCGv zero = tcg_constant_tl(0);
182
183    tcg_gen_movcond_tl(TCG_COND_EQ, dest, src2, zero, zero, src1);
184}
185
186static void gen_masknez(TCGv dest, TCGv src1, TCGv src2)
187{
188    TCGv zero = tcg_constant_tl(0);
189
190    tcg_gen_movcond_tl(TCG_COND_NE, dest, src2, zero, zero, src1);
191}
192
193TRANS(ext_w_h, gen_rr, EXT_NONE, EXT_NONE, tcg_gen_ext16s_tl)
194TRANS(ext_w_b, gen_rr, EXT_NONE, EXT_NONE, tcg_gen_ext8s_tl)
195TRANS(clo_w, gen_rr, EXT_NONE, EXT_NONE, gen_clo_w)
196TRANS(clz_w, gen_rr, EXT_ZERO, EXT_NONE, gen_clz_w)
197TRANS(cto_w, gen_rr, EXT_NONE, EXT_NONE, gen_cto_w)
198TRANS(ctz_w, gen_rr, EXT_NONE, EXT_NONE, gen_ctz_w)
199TRANS(clo_d, gen_rr, EXT_NONE, EXT_NONE, gen_clo_d)
200TRANS(clz_d, gen_rr, EXT_NONE, EXT_NONE, gen_clz_d)
201TRANS(cto_d, gen_rr, EXT_NONE, EXT_NONE, gen_cto_d)
202TRANS(ctz_d, gen_rr, EXT_NONE, EXT_NONE, gen_ctz_d)
203TRANS(revb_2h, gen_rr, EXT_NONE, EXT_SIGN, gen_revb_2h)
204TRANS(revb_4h, gen_rr, EXT_NONE, EXT_NONE, gen_revb_4h)
205TRANS(revb_2w, gen_rr, EXT_NONE, EXT_NONE, gen_revb_2w)
206TRANS(revb_d, gen_rr, EXT_NONE, EXT_NONE, tcg_gen_bswap64_i64)
207TRANS(revh_2w, gen_rr, EXT_NONE, EXT_NONE, gen_revh_2w)
208TRANS(revh_d, gen_rr, EXT_NONE, EXT_NONE, gen_revh_d)
209TRANS(bitrev_4b, gen_rr, EXT_ZERO, EXT_SIGN, gen_helper_bitswap)
210TRANS(bitrev_8b, gen_rr, EXT_NONE, EXT_NONE, gen_helper_bitswap)
211TRANS(bitrev_w, gen_rr, EXT_NONE, EXT_SIGN, gen_helper_bitrev_w)
212TRANS(bitrev_d, gen_rr, EXT_NONE, EXT_NONE, gen_helper_bitrev_d)
213TRANS(maskeqz, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_maskeqz)
214TRANS(masknez, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_masknez)
215TRANS(bytepick_w, gen_rrr_sa, EXT_NONE, EXT_NONE, gen_bytepick_w)
216TRANS(bytepick_d, gen_rrr_sa, EXT_NONE, EXT_NONE, gen_bytepick_d)
217TRANS(bstrins_w, gen_bstrins, EXT_SIGN)
218TRANS(bstrins_d, gen_bstrins, EXT_NONE)
219TRANS(bstrpick_w, gen_bstrpick, EXT_SIGN)
220TRANS(bstrpick_d, gen_bstrpick, EXT_NONE)
221