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
127static void gen_revb_4h(TCGv dest, TCGv src1)
128{
129    TCGv mask = tcg_constant_tl(0x00FF00FF00FF00FFULL);
130    TCGv t0 = tcg_temp_new();
131    TCGv t1 = tcg_temp_new();
132
133    tcg_gen_shri_tl(t0, src1, 8);
134    tcg_gen_and_tl(t0, t0, mask);
135    tcg_gen_and_tl(t1, src1, mask);
136    tcg_gen_shli_tl(t1, t1, 8);
137    tcg_gen_or_tl(dest, t0, t1);
138}
139
140static void gen_revh_2w(TCGv dest, TCGv src1)
141{
142    TCGv_i64 t0 = tcg_temp_new_i64();
143    TCGv_i64 t1 = tcg_temp_new_i64();
144    TCGv_i64 mask = tcg_constant_i64(0x0000ffff0000ffffull);
145
146    tcg_gen_shri_i64(t0, src1, 16);
147    tcg_gen_and_i64(t1, src1, mask);
148    tcg_gen_and_i64(t0, t0, mask);
149    tcg_gen_shli_i64(t1, t1, 16);
150    tcg_gen_or_i64(dest, t1, t0);
151}
152
153static void gen_revh_d(TCGv dest, TCGv src1)
154{
155    TCGv t0 = tcg_temp_new();
156    TCGv t1 = tcg_temp_new();
157    TCGv mask = tcg_constant_tl(0x0000FFFF0000FFFFULL);
158
159    tcg_gen_shri_tl(t1, src1, 16);
160    tcg_gen_and_tl(t1, t1, mask);
161    tcg_gen_and_tl(t0, src1, mask);
162    tcg_gen_shli_tl(t0, t0, 16);
163    tcg_gen_or_tl(t0, t0, t1);
164    tcg_gen_rotri_tl(dest, t0, 32);
165}
166
167static void gen_maskeqz(TCGv dest, TCGv src1, TCGv src2)
168{
169    TCGv zero = tcg_constant_tl(0);
170
171    tcg_gen_movcond_tl(TCG_COND_EQ, dest, src2, zero, zero, src1);
172}
173
174static void gen_masknez(TCGv dest, TCGv src1, TCGv src2)
175{
176    TCGv zero = tcg_constant_tl(0);
177
178    tcg_gen_movcond_tl(TCG_COND_NE, dest, src2, zero, zero, src1);
179}
180
181TRANS(ext_w_h, ALL, gen_rr, EXT_NONE, EXT_NONE, tcg_gen_ext16s_tl)
182TRANS(ext_w_b, ALL, gen_rr, EXT_NONE, EXT_NONE, tcg_gen_ext8s_tl)
183TRANS(clo_w, ALL, gen_rr, EXT_NONE, EXT_NONE, gen_clo_w)
184TRANS(clz_w, ALL, gen_rr, EXT_ZERO, EXT_NONE, gen_clz_w)
185TRANS(cto_w, ALL, gen_rr, EXT_NONE, EXT_NONE, gen_cto_w)
186TRANS(ctz_w, ALL, gen_rr, EXT_NONE, EXT_NONE, gen_ctz_w)
187TRANS(clo_d, 64, gen_rr, EXT_NONE, EXT_NONE, gen_clo_d)
188TRANS(clz_d, 64, gen_rr, EXT_NONE, EXT_NONE, gen_clz_d)
189TRANS(cto_d, 64, gen_rr, EXT_NONE, EXT_NONE, gen_cto_d)
190TRANS(ctz_d, 64, gen_rr, EXT_NONE, EXT_NONE, gen_ctz_d)
191TRANS(revb_2h, ALL, gen_rr, EXT_NONE, EXT_SIGN, gen_revb_2h)
192TRANS(revb_4h, 64, gen_rr, EXT_NONE, EXT_NONE, gen_revb_4h)
193TRANS(revb_2w, 64, gen_rr, EXT_NONE, EXT_NONE, gen_revb_2w)
194TRANS(revb_d, 64, gen_rr, EXT_NONE, EXT_NONE, tcg_gen_bswap64_i64)
195TRANS(revh_2w, 64, gen_rr, EXT_NONE, EXT_NONE, gen_revh_2w)
196TRANS(revh_d, 64, gen_rr, EXT_NONE, EXT_NONE, gen_revh_d)
197TRANS(bitrev_4b, ALL, gen_rr, EXT_ZERO, EXT_SIGN, gen_helper_bitswap)
198TRANS(bitrev_8b, 64, gen_rr, EXT_NONE, EXT_NONE, gen_helper_bitswap)
199TRANS(bitrev_w, ALL, gen_rr, EXT_NONE, EXT_SIGN, gen_helper_bitrev_w)
200TRANS(bitrev_d, 64, gen_rr, EXT_NONE, EXT_NONE, gen_helper_bitrev_d)
201TRANS(maskeqz, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_maskeqz)
202TRANS(masknez, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_masknez)
203TRANS(bytepick_w, ALL, gen_rrr_sa, EXT_NONE, EXT_NONE, gen_bytepick_w)
204TRANS(bytepick_d, 64, gen_rrr_sa, EXT_NONE, EXT_NONE, gen_bytepick_d)
205TRANS(bstrins_w, ALL, gen_bstrins, EXT_SIGN)
206TRANS(bstrins_d, 64, gen_bstrins, EXT_NONE)
207TRANS(bstrpick_w, ALL, gen_bstrpick, EXT_SIGN)
208TRANS(bstrpick_d, 64, gen_bstrpick, EXT_NONE)
209