2 * RISC-V translation routines for the RVB draft and Zba Standard Extension.
4 * Copyright (c) 2020 Kito Cheng, kito.cheng@sifive.com
5 * Copyright (c) 2020 Frank Chang, frank.chang@sifive.com
6 * Copyright (c) 2021 Philipp Tomsich, philipp.tomsich@vrull.eu
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2 or later, as published by the Free Software Foundation.
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
21 #define REQUIRE_ZBA(ctx) do { \
22 if (!RISCV_CPU(ctx->cs)->cfg.ext_zba) { \
27 static void gen_clz(TCGv ret, TCGv arg1)
29 tcg_gen_clzi_tl(ret, arg1, TARGET_LONG_BITS);
32 static bool trans_clz(DisasContext *ctx, arg_clz *a)
34 REQUIRE_EXT(ctx, RVB);
35 return gen_unary(ctx, a, EXT_ZERO, gen_clz);
38 static void gen_ctz(TCGv ret, TCGv arg1)
40 tcg_gen_ctzi_tl(ret, arg1, TARGET_LONG_BITS);
43 static bool trans_ctz(DisasContext *ctx, arg_ctz *a)
45 REQUIRE_EXT(ctx, RVB);
46 return gen_unary(ctx, a, EXT_ZERO, gen_ctz);
49 static bool trans_cpop(DisasContext *ctx, arg_cpop *a)
51 REQUIRE_EXT(ctx, RVB);
52 return gen_unary(ctx, a, EXT_ZERO, tcg_gen_ctpop_tl);
55 static bool trans_andn(DisasContext *ctx, arg_andn *a)
57 REQUIRE_EXT(ctx, RVB);
58 return gen_arith(ctx, a, EXT_NONE, tcg_gen_andc_tl);
61 static bool trans_orn(DisasContext *ctx, arg_orn *a)
63 REQUIRE_EXT(ctx, RVB);
64 return gen_arith(ctx, a, EXT_NONE, tcg_gen_orc_tl);
67 static bool trans_xnor(DisasContext *ctx, arg_xnor *a)
69 REQUIRE_EXT(ctx, RVB);
70 return gen_arith(ctx, a, EXT_NONE, tcg_gen_eqv_tl);
73 static void gen_pack(TCGv ret, TCGv arg1, TCGv arg2)
75 tcg_gen_deposit_tl(ret, arg1, arg2,
77 TARGET_LONG_BITS / 2);
80 static bool trans_pack(DisasContext *ctx, arg_pack *a)
82 REQUIRE_EXT(ctx, RVB);
83 return gen_arith(ctx, a, EXT_NONE, gen_pack);
86 static void gen_packu(TCGv ret, TCGv arg1, TCGv arg2)
88 TCGv t = tcg_temp_new();
89 tcg_gen_shri_tl(t, arg1, TARGET_LONG_BITS / 2);
90 tcg_gen_deposit_tl(ret, arg2, t, 0, TARGET_LONG_BITS / 2);
94 static bool trans_packu(DisasContext *ctx, arg_packu *a)
96 REQUIRE_EXT(ctx, RVB);
97 return gen_arith(ctx, a, EXT_NONE, gen_packu);
100 static void gen_packh(TCGv ret, TCGv arg1, TCGv arg2)
102 TCGv t = tcg_temp_new();
103 tcg_gen_ext8u_tl(t, arg2);
104 tcg_gen_deposit_tl(ret, arg1, t, 8, TARGET_LONG_BITS - 8);
108 static bool trans_packh(DisasContext *ctx, arg_packh *a)
110 REQUIRE_EXT(ctx, RVB);
111 return gen_arith(ctx, a, EXT_NONE, gen_packh);
114 static bool trans_min(DisasContext *ctx, arg_min *a)
116 REQUIRE_EXT(ctx, RVB);
117 return gen_arith(ctx, a, EXT_SIGN, tcg_gen_smin_tl);
120 static bool trans_max(DisasContext *ctx, arg_max *a)
122 REQUIRE_EXT(ctx, RVB);
123 return gen_arith(ctx, a, EXT_SIGN, tcg_gen_smax_tl);
126 static bool trans_minu(DisasContext *ctx, arg_minu *a)
128 REQUIRE_EXT(ctx, RVB);
129 return gen_arith(ctx, a, EXT_SIGN, tcg_gen_umin_tl);
132 static bool trans_maxu(DisasContext *ctx, arg_maxu *a)
134 REQUIRE_EXT(ctx, RVB);
135 return gen_arith(ctx, a, EXT_SIGN, tcg_gen_umax_tl);
138 static bool trans_sext_b(DisasContext *ctx, arg_sext_b *a)
140 REQUIRE_EXT(ctx, RVB);
141 return gen_unary(ctx, a, EXT_NONE, tcg_gen_ext8s_tl);
144 static bool trans_sext_h(DisasContext *ctx, arg_sext_h *a)
146 REQUIRE_EXT(ctx, RVB);
147 return gen_unary(ctx, a, EXT_NONE, tcg_gen_ext16s_tl);
150 static void gen_sbop_mask(TCGv ret, TCGv shamt)
152 tcg_gen_movi_tl(ret, 1);
153 tcg_gen_shl_tl(ret, ret, shamt);
156 static void gen_bset(TCGv ret, TCGv arg1, TCGv shamt)
158 TCGv t = tcg_temp_new();
160 gen_sbop_mask(t, shamt);
161 tcg_gen_or_tl(ret, arg1, t);
166 static bool trans_bset(DisasContext *ctx, arg_bset *a)
168 REQUIRE_EXT(ctx, RVB);
169 return gen_shift(ctx, a, EXT_NONE, gen_bset);
172 static bool trans_bseti(DisasContext *ctx, arg_bseti *a)
174 REQUIRE_EXT(ctx, RVB);
175 return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_bset);
178 static void gen_bclr(TCGv ret, TCGv arg1, TCGv shamt)
180 TCGv t = tcg_temp_new();
182 gen_sbop_mask(t, shamt);
183 tcg_gen_andc_tl(ret, arg1, t);
188 static bool trans_bclr(DisasContext *ctx, arg_bclr *a)
190 REQUIRE_EXT(ctx, RVB);
191 return gen_shift(ctx, a, EXT_NONE, gen_bclr);
194 static bool trans_bclri(DisasContext *ctx, arg_bclri *a)
196 REQUIRE_EXT(ctx, RVB);
197 return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_bclr);
200 static void gen_binv(TCGv ret, TCGv arg1, TCGv shamt)
202 TCGv t = tcg_temp_new();
204 gen_sbop_mask(t, shamt);
205 tcg_gen_xor_tl(ret, arg1, t);
210 static bool trans_binv(DisasContext *ctx, arg_binv *a)
212 REQUIRE_EXT(ctx, RVB);
213 return gen_shift(ctx, a, EXT_NONE, gen_binv);
216 static bool trans_binvi(DisasContext *ctx, arg_binvi *a)
218 REQUIRE_EXT(ctx, RVB);
219 return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_binv);
222 static void gen_bext(TCGv ret, TCGv arg1, TCGv shamt)
224 tcg_gen_shr_tl(ret, arg1, shamt);
225 tcg_gen_andi_tl(ret, ret, 1);
228 static bool trans_bext(DisasContext *ctx, arg_bext *a)
230 REQUIRE_EXT(ctx, RVB);
231 return gen_shift(ctx, a, EXT_NONE, gen_bext);
234 static bool trans_bexti(DisasContext *ctx, arg_bexti *a)
236 REQUIRE_EXT(ctx, RVB);
237 return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_bext);
240 static void gen_slo(TCGv ret, TCGv arg1, TCGv arg2)
242 tcg_gen_not_tl(ret, arg1);
243 tcg_gen_shl_tl(ret, ret, arg2);
244 tcg_gen_not_tl(ret, ret);
247 static bool trans_slo(DisasContext *ctx, arg_slo *a)
249 REQUIRE_EXT(ctx, RVB);
250 return gen_shift(ctx, a, EXT_NONE, gen_slo);
253 static bool trans_sloi(DisasContext *ctx, arg_sloi *a)
255 REQUIRE_EXT(ctx, RVB);
256 return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_slo);
259 static void gen_sro(TCGv ret, TCGv arg1, TCGv arg2)
261 tcg_gen_not_tl(ret, arg1);
262 tcg_gen_shr_tl(ret, ret, arg2);
263 tcg_gen_not_tl(ret, ret);
266 static bool trans_sro(DisasContext *ctx, arg_sro *a)
268 REQUIRE_EXT(ctx, RVB);
269 return gen_shift(ctx, a, EXT_ZERO, gen_sro);
272 static bool trans_sroi(DisasContext *ctx, arg_sroi *a)
274 REQUIRE_EXT(ctx, RVB);
275 return gen_shift_imm_tl(ctx, a, EXT_ZERO, gen_sro);
278 static bool trans_ror(DisasContext *ctx, arg_ror *a)
280 REQUIRE_EXT(ctx, RVB);
281 return gen_shift(ctx, a, EXT_NONE, tcg_gen_rotr_tl);
284 static bool trans_rori(DisasContext *ctx, arg_rori *a)
286 REQUIRE_EXT(ctx, RVB);
287 return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_rotri_tl);
290 static bool trans_rol(DisasContext *ctx, arg_rol *a)
292 REQUIRE_EXT(ctx, RVB);
293 return gen_shift(ctx, a, EXT_NONE, tcg_gen_rotl_tl);
296 static bool trans_grev(DisasContext *ctx, arg_grev *a)
298 REQUIRE_EXT(ctx, RVB);
299 return gen_shift(ctx, a, EXT_NONE, gen_helper_grev);
302 static void gen_grevi(TCGv dest, TCGv src, target_long shamt)
304 if (shamt == TARGET_LONG_BITS - 8) {
305 /* rev8, byte swaps */
306 tcg_gen_bswap_tl(dest, src);
308 gen_helper_grev(dest, src, tcg_constant_tl(shamt));
312 static bool trans_grevi(DisasContext *ctx, arg_grevi *a)
314 REQUIRE_EXT(ctx, RVB);
315 return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_grevi);
318 static bool trans_gorc(DisasContext *ctx, arg_gorc *a)
320 REQUIRE_EXT(ctx, RVB);
321 return gen_shift(ctx, a, EXT_ZERO, gen_helper_gorc);
324 static bool trans_gorci(DisasContext *ctx, arg_gorci *a)
326 REQUIRE_EXT(ctx, RVB);
327 return gen_shift_imm_tl(ctx, a, EXT_ZERO, gen_helper_gorc);
330 #define GEN_SHADD(SHAMT) \
331 static void gen_sh##SHAMT##add(TCGv ret, TCGv arg1, TCGv arg2) \
333 TCGv t = tcg_temp_new(); \
335 tcg_gen_shli_tl(t, arg1, SHAMT); \
336 tcg_gen_add_tl(ret, t, arg2); \
345 #define GEN_TRANS_SHADD(SHAMT) \
346 static bool trans_sh##SHAMT##add(DisasContext *ctx, arg_sh##SHAMT##add *a) \
349 return gen_arith(ctx, a, EXT_NONE, gen_sh##SHAMT##add); \
356 static void gen_clzw(TCGv ret, TCGv arg1)
358 TCGv t = tcg_temp_new();
359 tcg_gen_shli_tl(t, arg1, 32);
360 tcg_gen_clzi_tl(ret, t, 32);
364 static bool trans_clzw(DisasContext *ctx, arg_clzw *a)
367 REQUIRE_EXT(ctx, RVB);
368 return gen_unary(ctx, a, EXT_NONE, gen_clzw);
371 static void gen_ctzw(TCGv ret, TCGv arg1)
373 tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32));
374 tcg_gen_ctzi_tl(ret, ret, 64);
377 static bool trans_ctzw(DisasContext *ctx, arg_ctzw *a)
380 REQUIRE_EXT(ctx, RVB);
381 return gen_unary(ctx, a, EXT_NONE, gen_ctzw);
384 static bool trans_cpopw(DisasContext *ctx, arg_cpopw *a)
387 REQUIRE_EXT(ctx, RVB);
389 return gen_unary(ctx, a, EXT_ZERO, tcg_gen_ctpop_tl);
392 static void gen_packw(TCGv ret, TCGv arg1, TCGv arg2)
394 TCGv t = tcg_temp_new();
395 tcg_gen_ext16s_tl(t, arg2);
396 tcg_gen_deposit_tl(ret, arg1, t, 16, 48);
400 static bool trans_packw(DisasContext *ctx, arg_packw *a)
403 REQUIRE_EXT(ctx, RVB);
404 return gen_arith(ctx, a, EXT_NONE, gen_packw);
407 static void gen_packuw(TCGv ret, TCGv arg1, TCGv arg2)
409 TCGv t = tcg_temp_new();
410 tcg_gen_shri_tl(t, arg1, 16);
411 tcg_gen_deposit_tl(ret, arg2, t, 0, 16);
412 tcg_gen_ext32s_tl(ret, ret);
416 static bool trans_packuw(DisasContext *ctx, arg_packuw *a)
419 REQUIRE_EXT(ctx, RVB);
420 return gen_arith(ctx, a, EXT_NONE, gen_packuw);
423 static bool trans_slow(DisasContext *ctx, arg_slow *a)
426 REQUIRE_EXT(ctx, RVB);
428 return gen_shift(ctx, a, EXT_NONE, gen_slo);
431 static bool trans_sloiw(DisasContext *ctx, arg_sloiw *a)
434 REQUIRE_EXT(ctx, RVB);
436 return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_slo);
439 static bool trans_srow(DisasContext *ctx, arg_srow *a)
442 REQUIRE_EXT(ctx, RVB);
444 return gen_shift(ctx, a, EXT_ZERO, gen_sro);
447 static bool trans_sroiw(DisasContext *ctx, arg_sroiw *a)
450 REQUIRE_EXT(ctx, RVB);
452 return gen_shift_imm_tl(ctx, a, EXT_ZERO, gen_sro);
455 static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2)
457 TCGv_i32 t1 = tcg_temp_new_i32();
458 TCGv_i32 t2 = tcg_temp_new_i32();
460 /* truncate to 32-bits */
461 tcg_gen_trunc_tl_i32(t1, arg1);
462 tcg_gen_trunc_tl_i32(t2, arg2);
464 tcg_gen_rotr_i32(t1, t1, t2);
466 /* sign-extend 64-bits */
467 tcg_gen_ext_i32_tl(ret, t1);
469 tcg_temp_free_i32(t1);
470 tcg_temp_free_i32(t2);
473 static bool trans_rorw(DisasContext *ctx, arg_rorw *a)
476 REQUIRE_EXT(ctx, RVB);
478 return gen_shift(ctx, a, EXT_NONE, gen_rorw);
481 static bool trans_roriw(DisasContext *ctx, arg_roriw *a)
484 REQUIRE_EXT(ctx, RVB);
486 return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_rorw);
489 static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2)
491 TCGv_i32 t1 = tcg_temp_new_i32();
492 TCGv_i32 t2 = tcg_temp_new_i32();
494 /* truncate to 32-bits */
495 tcg_gen_trunc_tl_i32(t1, arg1);
496 tcg_gen_trunc_tl_i32(t2, arg2);
498 tcg_gen_rotl_i32(t1, t1, t2);
500 /* sign-extend 64-bits */
501 tcg_gen_ext_i32_tl(ret, t1);
503 tcg_temp_free_i32(t1);
504 tcg_temp_free_i32(t2);
507 static bool trans_rolw(DisasContext *ctx, arg_rolw *a)
510 REQUIRE_EXT(ctx, RVB);
512 return gen_shift(ctx, a, EXT_NONE, gen_rolw);
515 static bool trans_grevw(DisasContext *ctx, arg_grevw *a)
518 REQUIRE_EXT(ctx, RVB);
520 return gen_shift(ctx, a, EXT_ZERO, gen_helper_grev);
523 static bool trans_greviw(DisasContext *ctx, arg_greviw *a)
526 REQUIRE_EXT(ctx, RVB);
528 return gen_shift_imm_tl(ctx, a, EXT_ZERO, gen_helper_grev);
531 static bool trans_gorcw(DisasContext *ctx, arg_gorcw *a)
534 REQUIRE_EXT(ctx, RVB);
536 return gen_shift(ctx, a, EXT_ZERO, gen_helper_gorc);
539 static bool trans_gorciw(DisasContext *ctx, arg_gorciw *a)
542 REQUIRE_EXT(ctx, RVB);
544 return gen_shift_imm_tl(ctx, a, EXT_ZERO, gen_helper_gorc);
547 #define GEN_SHADD_UW(SHAMT) \
548 static void gen_sh##SHAMT##add_uw(TCGv ret, TCGv arg1, TCGv arg2) \
550 TCGv t = tcg_temp_new(); \
552 tcg_gen_ext32u_tl(t, arg1); \
554 tcg_gen_shli_tl(t, t, SHAMT); \
555 tcg_gen_add_tl(ret, t, arg2); \
564 #define GEN_TRANS_SHADD_UW(SHAMT) \
565 static bool trans_sh##SHAMT##add_uw(DisasContext *ctx, \
566 arg_sh##SHAMT##add_uw *a) \
568 REQUIRE_64BIT(ctx); \
570 return gen_arith(ctx, a, EXT_NONE, gen_sh##SHAMT##add_uw); \
573 GEN_TRANS_SHADD_UW(1)
574 GEN_TRANS_SHADD_UW(2)
575 GEN_TRANS_SHADD_UW(3)
577 static void gen_add_uw(TCGv ret, TCGv arg1, TCGv arg2)
579 TCGv t = tcg_temp_new();
580 tcg_gen_ext32u_tl(t, arg1);
581 tcg_gen_add_tl(ret, t, arg2);
585 static bool trans_add_uw(DisasContext *ctx, arg_add_uw *a)
589 return gen_arith(ctx, a, EXT_NONE, gen_add_uw);
592 static void gen_slli_uw(TCGv dest, TCGv src, target_long shamt)
594 tcg_gen_deposit_z_tl(dest, src, shamt, MIN(32, TARGET_LONG_BITS - shamt));
597 static bool trans_slli_uw(DisasContext *ctx, arg_slli_uw *a)
601 return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_slli_uw);