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