master
inc 304 lines 9.22 KB
Raw
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3 * Copyright (c) 2021 Loongson Technology Corporation Limited
4 */
5
6 static bool gen_rrr(DisasContext *ctx, arg_rrr *a,
7 DisasExtend src1_ext, DisasExtend src2_ext,
8 DisasExtend dst_ext, void (*func)(TCGv, TCGv, TCGv))
9 {
10 TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
11 TCGv src1 = gpr_src(ctx, a->rj, src1_ext);
12 TCGv src2 = gpr_src(ctx, a->rk, src2_ext);
13
14 func(dest, src1, src2);
15 gen_set_gpr(a->rd, dest, dst_ext);
16
17 return true;
18 }
19
20 static bool gen_rri_v(DisasContext *ctx, arg_rr_i *a,
21 DisasExtend src_ext, DisasExtend dst_ext,
22 void (*func)(TCGv, TCGv, TCGv))
23 {
24 TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
25 TCGv src1 = gpr_src(ctx, a->rj, src_ext);
26 TCGv src2 = tcg_constant_tl(a->imm);
27
28 func(dest, src1, src2);
29 gen_set_gpr(a->rd, dest, dst_ext);
30
31 return true;
32 }
33
34 static bool gen_rri_c(DisasContext *ctx, arg_rr_i *a,
35 DisasExtend src_ext, DisasExtend dst_ext,
36 void (*func)(TCGv, TCGv, target_long))
37 {
38 TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
39 TCGv src1 = gpr_src(ctx, a->rj, src_ext);
40
41 func(dest, src1, a->imm);
42 gen_set_gpr(a->rd, dest, dst_ext);
43
44 return true;
45 }
46
47 static bool gen_rrr_sa(DisasContext *ctx, arg_rrr_sa *a,
48 DisasExtend src_ext, DisasExtend dst_ext,
49 void (*func)(TCGv, TCGv, TCGv, target_long))
50 {
51 TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
52 TCGv src1 = gpr_src(ctx, a->rj, src_ext);
53 TCGv src2 = gpr_src(ctx, a->rk, src_ext);
54
55 func(dest, src1, src2, a->sa);
56 gen_set_gpr(a->rd, dest, dst_ext);
57
58 return true;
59 }
60
61 static bool trans_lu12i_w(DisasContext *ctx, arg_lu12i_w *a)
62 {
63 TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
64
65 tcg_gen_movi_tl(dest, a->imm << 12);
66 gen_set_gpr(a->rd, dest, EXT_NONE);
67
68 return true;
69 }
70
71 static bool gen_pc(DisasContext *ctx, arg_r_i *a,
72 target_ulong (*func)(target_ulong, int))
73 {
74 TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
75 target_ulong addr = make_address_pc(ctx, func(ctx->base.pc_next, a->imm));
76
77 tcg_gen_movi_tl(dest, addr);
78 gen_set_gpr(a->rd, dest, EXT_NONE);
79
80 return true;
81 }
82
83 static void gen_slt(TCGv dest, TCGv src1, TCGv src2)
84 {
85 tcg_gen_setcond_tl(TCG_COND_LT, dest, src1, src2);
86 }
87
88 static void gen_sltu(TCGv dest, TCGv src1, TCGv src2)
89 {
90 tcg_gen_setcond_tl(TCG_COND_LTU, dest, src1, src2);
91 }
92
93 static void gen_mulh_w(TCGv dest, TCGv src1, TCGv src2)
94 {
95 tcg_gen_mul_i64(dest, src1, src2);
96 tcg_gen_sari_i64(dest, dest, 32);
97 }
98
99 static void gen_mulh_d(TCGv dest, TCGv src1, TCGv src2)
100 {
101 TCGv discard = tcg_temp_new();
102 tcg_gen_muls2_tl(discard, dest, src1, src2);
103 }
104
105 static void gen_mulh_du(TCGv dest, TCGv src1, TCGv src2)
106 {
107 TCGv discard = tcg_temp_new();
108 tcg_gen_mulu2_tl(discard, dest, src1, src2);
109 }
110
111 static void prep_divisor_d(TCGv ret, TCGv src1, TCGv src2)
112 {
113 TCGv t0 = tcg_temp_new();
114 TCGv t1 = tcg_temp_new();
115 TCGv zero = tcg_constant_tl(0);
116
117 /*
118 * If min / -1, set the divisor to 1.
119 * This avoids potential host overflow trap and produces min.
120 * If x / 0, set the divisor to 1.
121 * This avoids potential host overflow trap;
122 * the required result is undefined.
123 */
124 tcg_gen_setcondi_tl(TCG_COND_EQ, ret, src1, INT64_MIN);
125 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, src2, -1);
126 tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src2, 0);
127 tcg_gen_and_tl(ret, ret, t0);
128 tcg_gen_or_tl(ret, ret, t1);
129 tcg_gen_movcond_tl(TCG_COND_NE, ret, ret, zero, ret, src2);
130 }
131
132 static void prep_divisor_du(TCGv ret, TCGv src2)
133 {
134 TCGv zero = tcg_constant_tl(0);
135 TCGv one = tcg_constant_tl(1);
136
137 /*
138 * If x / 0, set the divisor to 1.
139 * This avoids potential host overflow trap;
140 * the required result is undefined.
141 */
142 tcg_gen_movcond_tl(TCG_COND_EQ, ret, src2, zero, one, src2);
143 }
144
145 static void gen_div_d(TCGv dest, TCGv src1, TCGv src2)
146 {
147 TCGv t0 = tcg_temp_new();
148 prep_divisor_d(t0, src1, src2);
149 tcg_gen_div_tl(dest, src1, t0);
150 }
151
152 static void gen_rem_d(TCGv dest, TCGv src1, TCGv src2)
153 {
154 TCGv t0 = tcg_temp_new();
155 prep_divisor_d(t0, src1, src2);
156 tcg_gen_rem_tl(dest, src1, t0);
157 }
158
159 static void gen_div_du(TCGv dest, TCGv src1, TCGv src2)
160 {
161 TCGv t0 = tcg_temp_new();
162 prep_divisor_du(t0, src2);
163 tcg_gen_divu_tl(dest, src1, t0);
164 }
165
166 static void gen_rem_du(TCGv dest, TCGv src1, TCGv src2)
167 {
168 TCGv t0 = tcg_temp_new();
169 prep_divisor_du(t0, src2);
170 tcg_gen_remu_tl(dest, src1, t0);
171 }
172
173 static void gen_div_w(TCGv dest, TCGv src1, TCGv src2)
174 {
175 TCGv t0 = tcg_temp_new();
176 /* We need not check for integer overflow for div_w. */
177 prep_divisor_du(t0, src2);
178 tcg_gen_div_tl(dest, src1, t0);
179 }
180
181 static void gen_rem_w(TCGv dest, TCGv src1, TCGv src2)
182 {
183 TCGv t0 = tcg_temp_new();
184 /* We need not check for integer overflow for rem_w. */
185 prep_divisor_du(t0, src2);
186 tcg_gen_rem_tl(dest, src1, t0);
187 }
188
189 static void gen_alsl(TCGv dest, TCGv src1, TCGv src2, target_long sa)
190 {
191 TCGv t0 = tcg_temp_new();
192 tcg_gen_shli_tl(t0, src1, sa);
193 tcg_gen_add_tl(dest, t0, src2);
194 }
195
196 static bool trans_lu32i_d(DisasContext *ctx, arg_lu32i_d *a)
197 {
198 TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
199 TCGv src1 = gpr_src(ctx, a->rd, EXT_NONE);
200 TCGv src2 = tcg_constant_tl(a->imm);
201
202 if (!avail_64(ctx)) {
203 return false;
204 }
205
206 tcg_gen_deposit_tl(dest, src1, src2, 32, 32);
207 gen_set_gpr(a->rd, dest, EXT_NONE);
208
209 return true;
210 }
211
212 static bool trans_lu52i_d(DisasContext *ctx, arg_lu52i_d *a)
213 {
214 TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
215 TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
216 TCGv src2 = tcg_constant_tl(a->imm);
217
218 if (!avail_64(ctx)) {
219 return false;
220 }
221
222 tcg_gen_deposit_tl(dest, src1, src2, 52, 12);
223 gen_set_gpr(a->rd, dest, EXT_NONE);
224
225 return true;
226 }
227
228 static target_ulong gen_pcaddi(target_ulong pc, int imm)
229 {
230 return pc + (imm << 2);
231 }
232
233 static target_ulong gen_pcalau12i(target_ulong pc, int imm)
234 {
235 return (pc + (imm << 12)) & ~0xfff;
236 }
237
238 static target_ulong gen_pcaddu12i(target_ulong pc, int imm)
239 {
240 return pc + (imm << 12);
241 }
242
243 static target_ulong gen_pcaddu18i(target_ulong pc, int imm)
244 {
245 return pc + ((target_ulong)(imm) << 18);
246 }
247
248 static bool trans_addu16i_d(DisasContext *ctx, arg_addu16i_d *a)
249 {
250 TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
251 TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
252
253 if (!avail_64(ctx)) {
254 return false;
255 }
256
257 tcg_gen_addi_tl(dest, src1, a->imm << 16);
258 gen_set_gpr(a->rd, dest, EXT_NONE);
259
260 return true;
261 }
262
263 TRANS(add_w, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_SIGN, tcg_gen_add_tl)
264 TRANS(add_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_add_tl)
265 TRANS(sub_w, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_SIGN, tcg_gen_sub_tl)
266 TRANS(sub_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_sub_tl)
267 TRANS(and, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_and_tl)
268 TRANS(or, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_or_tl)
269 TRANS(xor, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_xor_tl)
270 TRANS(nor, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_nor_tl)
271 TRANS(andn, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_andc_tl)
272 TRANS(orn, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_orc_tl)
273 TRANS(slt, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_slt)
274 TRANS(sltu, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sltu)
275 TRANS(mul_w, ALL, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_SIGN, tcg_gen_mul_tl)
276 TRANS(mul_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_mul_tl)
277 TRANS(mulh_w, ALL, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_NONE, gen_mulh_w)
278 TRANS(mulh_wu, ALL, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_NONE, gen_mulh_w)
279 TRANS(mulh_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_d)
280 TRANS(mulh_du, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_du)
281 TRANS(mulw_d_w, 64, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_NONE, tcg_gen_mul_tl)
282 TRANS(mulw_d_wu, 64, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_NONE, tcg_gen_mul_tl)
283 TRANS(div_w, ALL, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_SIGN, gen_div_w)
284 TRANS(mod_w, ALL, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_SIGN, gen_rem_w)
285 TRANS(div_wu, ALL, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_SIGN, gen_div_du)
286 TRANS(mod_wu, ALL, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_SIGN, gen_rem_du)
287 TRANS(div_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_div_d)
288 TRANS(mod_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_rem_d)
289 TRANS(div_du, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_div_du)
290 TRANS(mod_du, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_rem_du)
291 TRANS(slti, ALL, gen_rri_v, EXT_NONE, EXT_NONE, gen_slt)
292 TRANS(sltui, ALL, gen_rri_v, EXT_NONE, EXT_NONE, gen_sltu)
293 TRANS(addi_w, ALL, gen_rri_c, EXT_NONE, EXT_SIGN, tcg_gen_addi_tl)
294 TRANS(addi_d, 64, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_addi_tl)
295 TRANS(alsl_w, ALL, gen_rrr_sa, EXT_NONE, EXT_SIGN, gen_alsl)
296 TRANS(alsl_wu, 64, gen_rrr_sa, EXT_NONE, EXT_ZERO, gen_alsl)
297 TRANS(alsl_d, 64, gen_rrr_sa, EXT_NONE, EXT_NONE, gen_alsl)
298 TRANS(pcaddi, ALL, gen_pc, gen_pcaddi)
299 TRANS(pcalau12i, ALL, gen_pc, gen_pcalau12i)
300 TRANS(pcaddu12i, ALL, gen_pc, gen_pcaddu12i)
301 TRANS(pcaddu18i, 64, gen_pc, gen_pcaddu18i)
302 TRANS(andi, ALL, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_andi_tl)
303 TRANS(ori, ALL, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_ori_tl)
304 TRANS(xori, ALL, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_xori_tl)