]> git.proxmox.com Git - mirror_qemu.git/blob - target/riscv/insn_trans/trans_rvzfh.c.inc
Merge tag 'pull-qapi-2023-07-10' of https://repo.or.cz/qemu/armbru into staging
[mirror_qemu.git] / target / riscv / insn_trans / trans_rvzfh.c.inc
1 /*
2 * RISC-V translation routines for the RV64Zfh Standard Extension.
3 *
4 * Copyright (c) 2020 Chih-Min Chao, chihmin.chao@sifive.com
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 #define REQUIRE_ZFH(ctx) do { \
20 if (!ctx->cfg_ptr->ext_zfh) { \
21 return false; \
22 } \
23 } while (0)
24
25 #define REQUIRE_ZHINX_OR_ZFH(ctx) do { \
26 if (!ctx->cfg_ptr->ext_zhinx && !ctx->cfg_ptr->ext_zfh) { \
27 return false; \
28 } \
29 } while (0)
30
31 #define REQUIRE_ZFHMIN_OR_ZFBFMIN(ctx) do { \
32 if (!ctx->cfg_ptr->ext_zfhmin && !ctx->cfg_ptr->ext_zfbfmin) { \
33 return false; \
34 } \
35 } while (0)
36
37 #define REQUIRE_ZFHMIN_OR_ZHINXMIN(ctx) do { \
38 if (!(ctx->cfg_ptr->ext_zfhmin || ctx->cfg_ptr->ext_zhinxmin)) { \
39 return false; \
40 } \
41 } while (0)
42
43 static bool trans_flh(DisasContext *ctx, arg_flh *a)
44 {
45 TCGv_i64 dest;
46 TCGv t0;
47
48 REQUIRE_FPU;
49 REQUIRE_ZFHMIN_OR_ZFBFMIN(ctx);
50
51 decode_save_opc(ctx);
52 t0 = get_gpr(ctx, a->rs1, EXT_NONE);
53 if (a->imm) {
54 TCGv temp = tcg_temp_new();
55 tcg_gen_addi_tl(temp, t0, a->imm);
56 t0 = temp;
57 }
58
59 dest = cpu_fpr[a->rd];
60 tcg_gen_qemu_ld_i64(dest, t0, ctx->mem_idx, MO_TEUW);
61 gen_nanbox_h(dest, dest);
62
63 mark_fs_dirty(ctx);
64 return true;
65 }
66
67 static bool trans_fsh(DisasContext *ctx, arg_fsh *a)
68 {
69 TCGv t0;
70
71 REQUIRE_FPU;
72 REQUIRE_ZFHMIN_OR_ZFBFMIN(ctx);
73
74 decode_save_opc(ctx);
75 t0 = get_gpr(ctx, a->rs1, EXT_NONE);
76 if (a->imm) {
77 TCGv temp = tcg_temp_new();
78 tcg_gen_addi_tl(temp, t0, a->imm);
79 t0 = temp;
80 }
81
82 tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, MO_TEUW);
83
84 return true;
85 }
86
87 static bool trans_fmadd_h(DisasContext *ctx, arg_fmadd_h *a)
88 {
89 REQUIRE_FPU;
90 REQUIRE_ZHINX_OR_ZFH(ctx);
91
92 TCGv_i64 dest = dest_fpr(ctx, a->rd);
93 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
94 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
95 TCGv_i64 src3 = get_fpr_hs(ctx, a->rs3);
96
97 gen_set_rm(ctx, a->rm);
98 gen_helper_fmadd_h(dest, cpu_env, src1, src2, src3);
99 gen_set_fpr_hs(ctx, a->rd, dest);
100 mark_fs_dirty(ctx);
101 return true;
102 }
103
104 static bool trans_fmsub_h(DisasContext *ctx, arg_fmsub_h *a)
105 {
106 REQUIRE_FPU;
107 REQUIRE_ZHINX_OR_ZFH(ctx);
108
109 TCGv_i64 dest = dest_fpr(ctx, a->rd);
110 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
111 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
112 TCGv_i64 src3 = get_fpr_hs(ctx, a->rs3);
113
114 gen_set_rm(ctx, a->rm);
115 gen_helper_fmsub_h(dest, cpu_env, src1, src2, src3);
116 gen_set_fpr_hs(ctx, a->rd, dest);
117 mark_fs_dirty(ctx);
118 return true;
119 }
120
121 static bool trans_fnmsub_h(DisasContext *ctx, arg_fnmsub_h *a)
122 {
123 REQUIRE_FPU;
124 REQUIRE_ZHINX_OR_ZFH(ctx);
125
126 TCGv_i64 dest = dest_fpr(ctx, a->rd);
127 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
128 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
129 TCGv_i64 src3 = get_fpr_hs(ctx, a->rs3);
130
131 gen_set_rm(ctx, a->rm);
132 gen_helper_fnmsub_h(dest, cpu_env, src1, src2, src3);
133 gen_set_fpr_hs(ctx, a->rd, dest);
134 mark_fs_dirty(ctx);
135 return true;
136 }
137
138 static bool trans_fnmadd_h(DisasContext *ctx, arg_fnmadd_h *a)
139 {
140 REQUIRE_FPU;
141 REQUIRE_ZHINX_OR_ZFH(ctx);
142
143 TCGv_i64 dest = dest_fpr(ctx, a->rd);
144 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
145 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
146 TCGv_i64 src3 = get_fpr_hs(ctx, a->rs3);
147
148 gen_set_rm(ctx, a->rm);
149 gen_helper_fnmadd_h(dest, cpu_env, src1, src2, src3);
150 gen_set_fpr_hs(ctx, a->rd, dest);
151 mark_fs_dirty(ctx);
152 return true;
153 }
154
155 static bool trans_fadd_h(DisasContext *ctx, arg_fadd_h *a)
156 {
157 REQUIRE_FPU;
158 REQUIRE_ZHINX_OR_ZFH(ctx);
159
160 TCGv_i64 dest = dest_fpr(ctx, a->rd);
161 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
162 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
163
164 gen_set_rm(ctx, a->rm);
165 gen_helper_fadd_h(dest, cpu_env, src1, src2);
166 gen_set_fpr_hs(ctx, a->rd, dest);
167 mark_fs_dirty(ctx);
168 return true;
169 }
170
171 static bool trans_fsub_h(DisasContext *ctx, arg_fsub_h *a)
172 {
173 REQUIRE_FPU;
174 REQUIRE_ZHINX_OR_ZFH(ctx);
175
176 TCGv_i64 dest = dest_fpr(ctx, a->rd);
177 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
178 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
179
180 gen_set_rm(ctx, a->rm);
181 gen_helper_fsub_h(dest, cpu_env, src1, src2);
182 gen_set_fpr_hs(ctx, a->rd, dest);
183 mark_fs_dirty(ctx);
184 return true;
185 }
186
187 static bool trans_fmul_h(DisasContext *ctx, arg_fmul_h *a)
188 {
189 REQUIRE_FPU;
190 REQUIRE_ZHINX_OR_ZFH(ctx);
191
192 TCGv_i64 dest = dest_fpr(ctx, a->rd);
193 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
194 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
195
196 gen_set_rm(ctx, a->rm);
197 gen_helper_fmul_h(dest, cpu_env, src1, src2);
198 gen_set_fpr_hs(ctx, a->rd, dest);
199 mark_fs_dirty(ctx);
200 return true;
201 }
202
203 static bool trans_fdiv_h(DisasContext *ctx, arg_fdiv_h *a)
204 {
205 REQUIRE_FPU;
206 REQUIRE_ZHINX_OR_ZFH(ctx);
207
208 TCGv_i64 dest = dest_fpr(ctx, a->rd);
209 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
210 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
211
212 gen_set_rm(ctx, a->rm);
213 gen_helper_fdiv_h(dest, cpu_env, src1, src2);
214 gen_set_fpr_hs(ctx, a->rd, dest);
215 mark_fs_dirty(ctx);
216 return true;
217 }
218
219 static bool trans_fsqrt_h(DisasContext *ctx, arg_fsqrt_h *a)
220 {
221 REQUIRE_FPU;
222 REQUIRE_ZHINX_OR_ZFH(ctx);
223
224 TCGv_i64 dest = dest_fpr(ctx, a->rd);
225 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
226
227 gen_set_rm(ctx, a->rm);
228 gen_helper_fsqrt_h(dest, cpu_env, src1);
229 gen_set_fpr_hs(ctx, a->rd, dest);
230 mark_fs_dirty(ctx);
231 return true;
232 }
233
234 static bool trans_fsgnj_h(DisasContext *ctx, arg_fsgnj_h *a)
235 {
236 REQUIRE_FPU;
237 REQUIRE_ZHINX_OR_ZFH(ctx);
238
239 TCGv_i64 dest = dest_fpr(ctx, a->rd);
240 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
241
242 if (a->rs1 == a->rs2) { /* FMOV */
243 if (!ctx->cfg_ptr->ext_zfinx) {
244 gen_check_nanbox_h(dest, src1);
245 } else {
246 tcg_gen_ext16s_i64(dest, src1);
247 }
248 } else {
249 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
250
251 if (!ctx->cfg_ptr->ext_zfinx) {
252 TCGv_i64 rs1 = tcg_temp_new_i64();
253 TCGv_i64 rs2 = tcg_temp_new_i64();
254 gen_check_nanbox_h(rs1, src1);
255 gen_check_nanbox_h(rs2, src2);
256
257 /* This formulation retains the nanboxing of rs2 in normal 'Zfh'. */
258 tcg_gen_deposit_i64(dest, rs2, rs1, 0, 15);
259 } else {
260 tcg_gen_deposit_i64(dest, src2, src1, 0, 15);
261 tcg_gen_ext16s_i64(dest, dest);
262 }
263 }
264 gen_set_fpr_hs(ctx, a->rd, dest);
265 mark_fs_dirty(ctx);
266 return true;
267 }
268
269 static bool trans_fsgnjn_h(DisasContext *ctx, arg_fsgnjn_h *a)
270 {
271 TCGv_i64 rs1, rs2, mask;
272
273 REQUIRE_FPU;
274 REQUIRE_ZHINX_OR_ZFH(ctx);
275
276 TCGv_i64 dest = dest_fpr(ctx, a->rd);
277 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
278
279 rs1 = tcg_temp_new_i64();
280 if (!ctx->cfg_ptr->ext_zfinx) {
281 gen_check_nanbox_h(rs1, src1);
282 } else {
283 tcg_gen_mov_i64(rs1, src1);
284 }
285
286 if (a->rs1 == a->rs2) { /* FNEG */
287 tcg_gen_xori_i64(dest, rs1, MAKE_64BIT_MASK(15, 1));
288 } else {
289 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
290 rs2 = tcg_temp_new_i64();
291
292 if (!ctx->cfg_ptr->ext_zfinx) {
293 gen_check_nanbox_h(rs2, src2);
294 } else {
295 tcg_gen_mov_i64(rs2, src2);
296 }
297
298 /*
299 * Replace bit 15 in rs1 with inverse in rs2.
300 * This formulation retains the nanboxing of rs1.
301 */
302 mask = tcg_constant_i64(~MAKE_64BIT_MASK(15, 1));
303 tcg_gen_not_i64(rs2, rs2);
304 tcg_gen_andc_i64(rs2, rs2, mask);
305 tcg_gen_and_i64(dest, mask, rs1);
306 tcg_gen_or_i64(dest, dest, rs2);
307 }
308 /* signed-extended intead of nanboxing for result if enable zfinx */
309 if (ctx->cfg_ptr->ext_zfinx) {
310 tcg_gen_ext16s_i64(dest, dest);
311 }
312 mark_fs_dirty(ctx);
313 return true;
314 }
315
316 static bool trans_fsgnjx_h(DisasContext *ctx, arg_fsgnjx_h *a)
317 {
318 TCGv_i64 rs1, rs2;
319
320 REQUIRE_FPU;
321 REQUIRE_ZHINX_OR_ZFH(ctx);
322
323 TCGv_i64 dest = dest_fpr(ctx, a->rd);
324 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
325
326 rs1 = tcg_temp_new_i64();
327 if (!ctx->cfg_ptr->ext_zfinx) {
328 gen_check_nanbox_h(rs1, src1);
329 } else {
330 tcg_gen_mov_i64(rs1, src1);
331 }
332
333 if (a->rs1 == a->rs2) { /* FABS */
334 tcg_gen_andi_i64(dest, rs1, ~MAKE_64BIT_MASK(15, 1));
335 } else {
336 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
337 rs2 = tcg_temp_new_i64();
338
339 if (!ctx->cfg_ptr->ext_zfinx) {
340 gen_check_nanbox_h(rs2, src2);
341 } else {
342 tcg_gen_mov_i64(rs2, src2);
343 }
344
345 /*
346 * Xor bit 15 in rs1 with that in rs2.
347 * This formulation retains the nanboxing of rs1.
348 */
349 tcg_gen_andi_i64(dest, rs2, MAKE_64BIT_MASK(15, 1));
350 tcg_gen_xor_i64(dest, rs1, dest);
351 }
352 /* signed-extended intead of nanboxing for result if enable zfinx */
353 if (ctx->cfg_ptr->ext_zfinx) {
354 tcg_gen_ext16s_i64(dest, dest);
355 }
356 mark_fs_dirty(ctx);
357 return true;
358 }
359
360 static bool trans_fmin_h(DisasContext *ctx, arg_fmin_h *a)
361 {
362 REQUIRE_FPU;
363 REQUIRE_ZHINX_OR_ZFH(ctx);
364
365 TCGv_i64 dest = dest_fpr(ctx, a->rd);
366 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
367 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
368
369 gen_helper_fmin_h(dest, cpu_env, src1, src2);
370 gen_set_fpr_hs(ctx, a->rd, dest);
371 mark_fs_dirty(ctx);
372 return true;
373 }
374
375 static bool trans_fmax_h(DisasContext *ctx, arg_fmax_h *a)
376 {
377 REQUIRE_FPU;
378 REQUIRE_ZHINX_OR_ZFH(ctx);
379
380 TCGv_i64 dest = dest_fpr(ctx, a->rd);
381 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
382 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
383
384 gen_helper_fmax_h(dest, cpu_env, src1, src2);
385 gen_set_fpr_hs(ctx, a->rd, dest);
386 mark_fs_dirty(ctx);
387 return true;
388 }
389
390 static bool trans_fcvt_s_h(DisasContext *ctx, arg_fcvt_s_h *a)
391 {
392 REQUIRE_FPU;
393 REQUIRE_ZFHMIN_OR_ZHINXMIN(ctx);
394
395 TCGv_i64 dest = dest_fpr(ctx, a->rd);
396 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
397
398 gen_set_rm(ctx, a->rm);
399 gen_helper_fcvt_s_h(dest, cpu_env, src1);
400 gen_set_fpr_hs(ctx, a->rd, dest);
401
402 mark_fs_dirty(ctx);
403
404 return true;
405 }
406
407 static bool trans_fcvt_d_h(DisasContext *ctx, arg_fcvt_d_h *a)
408 {
409 REQUIRE_FPU;
410 REQUIRE_ZFHMIN_OR_ZHINXMIN(ctx);
411 REQUIRE_ZDINX_OR_D(ctx);
412
413 TCGv_i64 dest = dest_fpr(ctx, a->rd);
414 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
415
416 gen_set_rm(ctx, a->rm);
417 gen_helper_fcvt_d_h(dest, cpu_env, src1);
418 gen_set_fpr_d(ctx, a->rd, dest);
419
420 mark_fs_dirty(ctx);
421
422 return true;
423 }
424
425 static bool trans_fcvt_h_s(DisasContext *ctx, arg_fcvt_h_s *a)
426 {
427 REQUIRE_FPU;
428 REQUIRE_ZFHMIN_OR_ZHINXMIN(ctx);
429
430 TCGv_i64 dest = dest_fpr(ctx, a->rd);
431 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
432
433 gen_set_rm(ctx, a->rm);
434 gen_helper_fcvt_h_s(dest, cpu_env, src1);
435 gen_set_fpr_hs(ctx, a->rd, dest);
436 mark_fs_dirty(ctx);
437
438 return true;
439 }
440
441 static bool trans_fcvt_h_d(DisasContext *ctx, arg_fcvt_h_d *a)
442 {
443 REQUIRE_FPU;
444 REQUIRE_ZFHMIN_OR_ZHINXMIN(ctx);
445 REQUIRE_ZDINX_OR_D(ctx);
446
447 TCGv_i64 dest = dest_fpr(ctx, a->rd);
448 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
449
450 gen_set_rm(ctx, a->rm);
451 gen_helper_fcvt_h_d(dest, cpu_env, src1);
452 gen_set_fpr_hs(ctx, a->rd, dest);
453 mark_fs_dirty(ctx);
454
455 return true;
456 }
457
458 static bool trans_feq_h(DisasContext *ctx, arg_feq_h *a)
459 {
460 REQUIRE_FPU;
461 REQUIRE_ZHINX_OR_ZFH(ctx);
462
463 TCGv dest = dest_gpr(ctx, a->rd);
464 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
465 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
466
467 gen_helper_feq_h(dest, cpu_env, src1, src2);
468 gen_set_gpr(ctx, a->rd, dest);
469 return true;
470 }
471
472 static bool trans_flt_h(DisasContext *ctx, arg_flt_h *a)
473 {
474 REQUIRE_FPU;
475 REQUIRE_ZHINX_OR_ZFH(ctx);
476
477 TCGv dest = dest_gpr(ctx, a->rd);
478 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
479 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
480
481 gen_helper_flt_h(dest, cpu_env, src1, src2);
482 gen_set_gpr(ctx, a->rd, dest);
483
484 return true;
485 }
486
487 static bool trans_fle_h(DisasContext *ctx, arg_fle_h *a)
488 {
489 REQUIRE_FPU;
490 REQUIRE_ZHINX_OR_ZFH(ctx);
491
492 TCGv dest = dest_gpr(ctx, a->rd);
493 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
494 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
495
496 gen_helper_fle_h(dest, cpu_env, src1, src2);
497 gen_set_gpr(ctx, a->rd, dest);
498 return true;
499 }
500
501 static bool trans_fclass_h(DisasContext *ctx, arg_fclass_h *a)
502 {
503 REQUIRE_FPU;
504 REQUIRE_ZHINX_OR_ZFH(ctx);
505
506 TCGv dest = dest_gpr(ctx, a->rd);
507 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
508
509 gen_helper_fclass_h(dest, cpu_env, src1);
510 gen_set_gpr(ctx, a->rd, dest);
511 return true;
512 }
513
514 static bool trans_fcvt_w_h(DisasContext *ctx, arg_fcvt_w_h *a)
515 {
516 REQUIRE_FPU;
517 REQUIRE_ZHINX_OR_ZFH(ctx);
518
519 TCGv dest = dest_gpr(ctx, a->rd);
520 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
521
522 gen_set_rm(ctx, a->rm);
523 gen_helper_fcvt_w_h(dest, cpu_env, src1);
524 gen_set_gpr(ctx, a->rd, dest);
525 return true;
526 }
527
528 static bool trans_fcvt_wu_h(DisasContext *ctx, arg_fcvt_wu_h *a)
529 {
530 REQUIRE_FPU;
531 REQUIRE_ZHINX_OR_ZFH(ctx);
532
533 TCGv dest = dest_gpr(ctx, a->rd);
534 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
535
536 gen_set_rm(ctx, a->rm);
537 gen_helper_fcvt_wu_h(dest, cpu_env, src1);
538 gen_set_gpr(ctx, a->rd, dest);
539 return true;
540 }
541
542 static bool trans_fcvt_h_w(DisasContext *ctx, arg_fcvt_h_w *a)
543 {
544 REQUIRE_FPU;
545 REQUIRE_ZHINX_OR_ZFH(ctx);
546
547 TCGv_i64 dest = dest_fpr(ctx, a->rd);
548 TCGv t0 = get_gpr(ctx, a->rs1, EXT_SIGN);
549
550 gen_set_rm(ctx, a->rm);
551 gen_helper_fcvt_h_w(dest, cpu_env, t0);
552 gen_set_fpr_hs(ctx, a->rd, dest);
553
554 mark_fs_dirty(ctx);
555 return true;
556 }
557
558 static bool trans_fcvt_h_wu(DisasContext *ctx, arg_fcvt_h_wu *a)
559 {
560 REQUIRE_FPU;
561 REQUIRE_ZHINX_OR_ZFH(ctx);
562
563 TCGv_i64 dest = dest_fpr(ctx, a->rd);
564 TCGv t0 = get_gpr(ctx, a->rs1, EXT_SIGN);
565
566 gen_set_rm(ctx, a->rm);
567 gen_helper_fcvt_h_wu(dest, cpu_env, t0);
568 gen_set_fpr_hs(ctx, a->rd, dest);
569
570 mark_fs_dirty(ctx);
571 return true;
572 }
573
574 static bool trans_fmv_x_h(DisasContext *ctx, arg_fmv_x_h *a)
575 {
576 REQUIRE_FPU;
577 REQUIRE_ZFHMIN_OR_ZFBFMIN(ctx);
578
579 TCGv dest = dest_gpr(ctx, a->rd);
580
581 #if defined(TARGET_RISCV64)
582 /* 16 bits -> 64 bits */
583 tcg_gen_ext16s_tl(dest, cpu_fpr[a->rs1]);
584 #else
585 /* 16 bits -> 32 bits */
586 tcg_gen_extrl_i64_i32(dest, cpu_fpr[a->rs1]);
587 tcg_gen_ext16s_tl(dest, dest);
588 #endif
589
590 gen_set_gpr(ctx, a->rd, dest);
591 return true;
592 }
593
594 static bool trans_fmv_h_x(DisasContext *ctx, arg_fmv_h_x *a)
595 {
596 REQUIRE_FPU;
597 REQUIRE_ZFHMIN_OR_ZFBFMIN(ctx);
598
599 TCGv t0 = get_gpr(ctx, a->rs1, EXT_ZERO);
600
601 tcg_gen_extu_tl_i64(cpu_fpr[a->rd], t0);
602 gen_nanbox_h(cpu_fpr[a->rd], cpu_fpr[a->rd]);
603
604 mark_fs_dirty(ctx);
605 return true;
606 }
607
608 static bool trans_fcvt_l_h(DisasContext *ctx, arg_fcvt_l_h *a)
609 {
610 REQUIRE_64BIT(ctx);
611 REQUIRE_FPU;
612 REQUIRE_ZHINX_OR_ZFH(ctx);
613
614 TCGv dest = dest_gpr(ctx, a->rd);
615 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
616
617 gen_set_rm(ctx, a->rm);
618 gen_helper_fcvt_l_h(dest, cpu_env, src1);
619 gen_set_gpr(ctx, a->rd, dest);
620 return true;
621 }
622
623 static bool trans_fcvt_lu_h(DisasContext *ctx, arg_fcvt_lu_h *a)
624 {
625 REQUIRE_64BIT(ctx);
626 REQUIRE_FPU;
627 REQUIRE_ZHINX_OR_ZFH(ctx);
628
629 TCGv dest = dest_gpr(ctx, a->rd);
630 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
631
632 gen_set_rm(ctx, a->rm);
633 gen_helper_fcvt_lu_h(dest, cpu_env, src1);
634 gen_set_gpr(ctx, a->rd, dest);
635 return true;
636 }
637
638 static bool trans_fcvt_h_l(DisasContext *ctx, arg_fcvt_h_l *a)
639 {
640 REQUIRE_64BIT(ctx);
641 REQUIRE_FPU;
642 REQUIRE_ZHINX_OR_ZFH(ctx);
643
644 TCGv_i64 dest = dest_fpr(ctx, a->rd);
645 TCGv t0 = get_gpr(ctx, a->rs1, EXT_SIGN);
646
647 gen_set_rm(ctx, a->rm);
648 gen_helper_fcvt_h_l(dest, cpu_env, t0);
649 gen_set_fpr_hs(ctx, a->rd, dest);
650
651 mark_fs_dirty(ctx);
652 return true;
653 }
654
655 static bool trans_fcvt_h_lu(DisasContext *ctx, arg_fcvt_h_lu *a)
656 {
657 REQUIRE_64BIT(ctx);
658 REQUIRE_FPU;
659 REQUIRE_ZHINX_OR_ZFH(ctx);
660
661 TCGv_i64 dest = dest_fpr(ctx, a->rd);
662 TCGv t0 = get_gpr(ctx, a->rs1, EXT_SIGN);
663
664 gen_set_rm(ctx, a->rm);
665 gen_helper_fcvt_h_lu(dest, cpu_env, t0);
666 gen_set_fpr_hs(ctx, a->rd, dest);
667
668 mark_fs_dirty(ctx);
669 return true;
670 }