master
inc 614 lines 15.9 KB
Raw
1 /*
2 * RISC-V translation routines for the RV64F Standard Extension.
3 *
4 * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
5 * Copyright (c) 2018 Peer Adelt, peer.adelt@hni.uni-paderborn.de
6 * Bastian Koppelmann, kbastian@mail.uni-paderborn.de
7 *
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.
11 *
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
15 * more details.
16 *
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/>.
19 */
20
21 #define REQUIRE_FPU do {\
22 if (ctx->mstatus_fs == EXT_STATUS_DISABLED) { \
23 ctx->virt_inst_excp = ctx->virt_enabled && ctx->cfg_ptr->ext_zfinx; \
24 return false; \
25 } \
26 } while (0)
27
28 #define REQUIRE_ZFINX_OR_F(ctx) do {\
29 if (!ctx->cfg_ptr->ext_zfinx) { \
30 REQUIRE_EXT(ctx, RVF); \
31 } \
32 } while (0)
33
34 #define REQUIRE_ZCF_OR_FC(ctx) do { \
35 if (!ctx->cfg_ptr->ext_zcf) { \
36 if (!has_ext(ctx, RVF) || !has_ext(ctx, RVC)) { \
37 return false; \
38 } \
39 } \
40 } while (0)
41
42 static bool trans_flw(DisasContext *ctx, arg_flw *a)
43 {
44 TCGv_i64 dest;
45 TCGv addr;
46 MemOp memop = MO_UL;
47
48 REQUIRE_FPU;
49 REQUIRE_EXT(ctx, RVF);
50
51 memop |= ctx->mo_endianness;
52 if (ctx->cfg_ptr->ext_zama16b) {
53 memop |= MO_ATOM_WITHIN16;
54 }
55 if (!ctx->cfg_ptr->ext_zicclsm) {
56 memop |= MO_ALIGN;
57 }
58
59 decode_save_opc(ctx, 0);
60 addr = get_address(ctx, a->rs1, a->imm);
61 dest = cpu_fpr[a->rd];
62 tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, memop);
63 gen_nanbox_s(dest, dest);
64
65 mark_fs_dirty(ctx);
66 return true;
67 }
68
69 static bool trans_fsw(DisasContext *ctx, arg_fsw *a)
70 {
71 TCGv addr;
72 MemOp memop = MO_UL;
73
74 REQUIRE_FPU;
75 REQUIRE_EXT(ctx, RVF);
76
77 memop |= ctx->mo_endianness;
78 if (ctx->cfg_ptr->ext_zama16b) {
79 memop |= MO_ATOM_WITHIN16;
80 }
81 if (!ctx->cfg_ptr->ext_zicclsm) {
82 memop |= MO_ALIGN;
83 }
84
85 decode_save_opc(ctx, 0);
86 addr = get_address(ctx, a->rs1, a->imm);
87 tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, memop);
88 return true;
89 }
90
91 static bool trans_c_flw(DisasContext *ctx, arg_flw *a)
92 {
93 REQUIRE_ZCF_OR_FC(ctx);
94 return trans_flw(ctx, a);
95 }
96
97 static bool trans_c_fsw(DisasContext *ctx, arg_fsw *a)
98 {
99 REQUIRE_ZCF_OR_FC(ctx);
100 return trans_fsw(ctx, a);
101 }
102
103 static bool trans_fmadd_s(DisasContext *ctx, arg_fmadd_s *a)
104 {
105 REQUIRE_FPU;
106 REQUIRE_ZFINX_OR_F(ctx);
107
108 TCGv_i64 dest = dest_fpr(ctx, a->rd);
109 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
110 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
111 TCGv_i64 src3 = get_fpr_hs(ctx, a->rs3);
112
113 gen_set_rm(ctx, a->rm);
114 gen_helper_fmadd_s(dest, tcg_env, src1, src2, src3);
115 gen_set_fpr_hs(ctx, a->rd, dest);
116 mark_fs_dirty(ctx);
117 return true;
118 }
119
120 static bool trans_fmsub_s(DisasContext *ctx, arg_fmsub_s *a)
121 {
122 REQUIRE_FPU;
123 REQUIRE_ZFINX_OR_F(ctx);
124
125 TCGv_i64 dest = dest_fpr(ctx, a->rd);
126 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
127 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
128 TCGv_i64 src3 = get_fpr_hs(ctx, a->rs3);
129
130 gen_set_rm(ctx, a->rm);
131 gen_helper_fmsub_s(dest, tcg_env, src1, src2, src3);
132 gen_set_fpr_hs(ctx, a->rd, dest);
133 mark_fs_dirty(ctx);
134 return true;
135 }
136
137 static bool trans_fnmsub_s(DisasContext *ctx, arg_fnmsub_s *a)
138 {
139 REQUIRE_FPU;
140 REQUIRE_ZFINX_OR_F(ctx);
141
142 TCGv_i64 dest = dest_fpr(ctx, a->rd);
143 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
144 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
145 TCGv_i64 src3 = get_fpr_hs(ctx, a->rs3);
146
147 gen_set_rm(ctx, a->rm);
148 gen_helper_fnmsub_s(dest, tcg_env, src1, src2, src3);
149 gen_set_fpr_hs(ctx, a->rd, dest);
150 mark_fs_dirty(ctx);
151 return true;
152 }
153
154 static bool trans_fnmadd_s(DisasContext *ctx, arg_fnmadd_s *a)
155 {
156 REQUIRE_FPU;
157 REQUIRE_ZFINX_OR_F(ctx);
158
159 TCGv_i64 dest = dest_fpr(ctx, a->rd);
160 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
161 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
162 TCGv_i64 src3 = get_fpr_hs(ctx, a->rs3);
163
164 gen_set_rm(ctx, a->rm);
165 gen_helper_fnmadd_s(dest, tcg_env, src1, src2, src3);
166 gen_set_fpr_hs(ctx, a->rd, dest);
167 mark_fs_dirty(ctx);
168 return true;
169 }
170
171 static bool trans_fadd_s(DisasContext *ctx, arg_fadd_s *a)
172 {
173 REQUIRE_FPU;
174 REQUIRE_ZFINX_OR_F(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_fadd_s(dest, tcg_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_fsub_s(DisasContext *ctx, arg_fsub_s *a)
188 {
189 REQUIRE_FPU;
190 REQUIRE_ZFINX_OR_F(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_fsub_s(dest, tcg_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_fmul_s(DisasContext *ctx, arg_fmul_s *a)
204 {
205 REQUIRE_FPU;
206 REQUIRE_ZFINX_OR_F(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_fmul_s(dest, tcg_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_fdiv_s(DisasContext *ctx, arg_fdiv_s *a)
220 {
221 REQUIRE_FPU;
222 REQUIRE_ZFINX_OR_F(ctx);
223
224 TCGv_i64 dest = dest_fpr(ctx, a->rd);
225 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
226 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
227
228 gen_set_rm(ctx, a->rm);
229 gen_helper_fdiv_s(dest, tcg_env, src1, src2);
230 gen_set_fpr_hs(ctx, a->rd, dest);
231 mark_fs_dirty(ctx);
232 return true;
233 }
234
235 static bool trans_fsqrt_s(DisasContext *ctx, arg_fsqrt_s *a)
236 {
237 REQUIRE_FPU;
238 REQUIRE_ZFINX_OR_F(ctx);
239
240 TCGv_i64 dest = dest_fpr(ctx, a->rd);
241 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
242
243 gen_set_rm(ctx, a->rm);
244 gen_helper_fsqrt_s(dest, tcg_env, src1);
245 gen_set_fpr_hs(ctx, a->rd, dest);
246 mark_fs_dirty(ctx);
247 return true;
248 }
249
250 static bool trans_fsgnj_s(DisasContext *ctx, arg_fsgnj_s *a)
251 {
252 REQUIRE_FPU;
253 REQUIRE_ZFINX_OR_F(ctx);
254
255 TCGv_i64 dest = dest_fpr(ctx, a->rd);
256 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
257
258 if (a->rs1 == a->rs2) { /* FMOV */
259 if (!ctx->cfg_ptr->ext_zfinx) {
260 gen_check_nanbox_s(dest, src1);
261 } else {
262 tcg_gen_ext32s_i64(dest, src1);
263 }
264 } else { /* FSGNJ */
265 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
266
267 if (!ctx->cfg_ptr->ext_zfinx) {
268 TCGv_i64 rs1 = tcg_temp_new_i64();
269 TCGv_i64 rs2 = tcg_temp_new_i64();
270 gen_check_nanbox_s(rs1, src1);
271 gen_check_nanbox_s(rs2, src2);
272
273 /* This formulation retains the nanboxing of rs2 in normal 'F'. */
274 tcg_gen_deposit_i64(dest, rs2, rs1, 0, 31);
275 } else {
276 tcg_gen_deposit_i64(dest, src2, src1, 0, 31);
277 tcg_gen_ext32s_i64(dest, dest);
278 }
279 }
280 gen_set_fpr_hs(ctx, a->rd, dest);
281 mark_fs_dirty(ctx);
282 return true;
283 }
284
285 static bool trans_fsgnjn_s(DisasContext *ctx, arg_fsgnjn_s *a)
286 {
287 TCGv_i64 rs1, rs2, mask;
288
289 REQUIRE_FPU;
290 REQUIRE_ZFINX_OR_F(ctx);
291
292 TCGv_i64 dest = dest_fpr(ctx, a->rd);
293 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
294
295 rs1 = tcg_temp_new_i64();
296 if (!ctx->cfg_ptr->ext_zfinx) {
297 gen_check_nanbox_s(rs1, src1);
298 } else {
299 tcg_gen_mov_i64(rs1, src1);
300 }
301 if (a->rs1 == a->rs2) { /* FNEG */
302 tcg_gen_xori_i64(dest, rs1, MAKE_64BIT_MASK(31, 1));
303 } else {
304 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
305 rs2 = tcg_temp_new_i64();
306 if (!ctx->cfg_ptr->ext_zfinx) {
307 gen_check_nanbox_s(rs2, src2);
308 } else {
309 tcg_gen_mov_i64(rs2, src2);
310 }
311
312 /*
313 * Replace bit 31 in rs1 with inverse in rs2.
314 * This formulation retains the nanboxing of rs1.
315 */
316 mask = tcg_constant_i64(~MAKE_64BIT_MASK(31, 1));
317 tcg_gen_nor_i64(rs2, rs2, mask);
318 tcg_gen_and_i64(dest, mask, rs1);
319 tcg_gen_or_i64(dest, dest, rs2);
320 }
321 /* signed-extended instead of nanboxing for result if enable zfinx */
322 if (ctx->cfg_ptr->ext_zfinx) {
323 tcg_gen_ext32s_i64(dest, dest);
324 }
325 gen_set_fpr_hs(ctx, a->rd, dest);
326 mark_fs_dirty(ctx);
327 return true;
328 }
329
330 static bool trans_fsgnjx_s(DisasContext *ctx, arg_fsgnjx_s *a)
331 {
332 TCGv_i64 rs1, rs2;
333
334 REQUIRE_FPU;
335 REQUIRE_ZFINX_OR_F(ctx);
336
337 TCGv_i64 dest = dest_fpr(ctx, a->rd);
338 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
339 rs1 = tcg_temp_new_i64();
340
341 if (!ctx->cfg_ptr->ext_zfinx) {
342 gen_check_nanbox_s(rs1, src1);
343 } else {
344 tcg_gen_mov_i64(rs1, src1);
345 }
346
347 if (a->rs1 == a->rs2) { /* FABS */
348 tcg_gen_andi_i64(dest, rs1, ~MAKE_64BIT_MASK(31, 1));
349 } else {
350 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
351 rs2 = tcg_temp_new_i64();
352
353 if (!ctx->cfg_ptr->ext_zfinx) {
354 gen_check_nanbox_s(rs2, src2);
355 } else {
356 tcg_gen_mov_i64(rs2, src2);
357 }
358
359 /*
360 * Xor bit 31 in rs1 with that in rs2.
361 * This formulation retains the nanboxing of rs1.
362 */
363 tcg_gen_andi_i64(dest, rs2, MAKE_64BIT_MASK(31, 1));
364 tcg_gen_xor_i64(dest, rs1, dest);
365 }
366 /* signed-extended instead of nanboxing for result if enable zfinx */
367 if (ctx->cfg_ptr->ext_zfinx) {
368 tcg_gen_ext32s_i64(dest, dest);
369 }
370 gen_set_fpr_hs(ctx, a->rd, dest);
371 mark_fs_dirty(ctx);
372 return true;
373 }
374
375 static bool trans_fmin_s(DisasContext *ctx, arg_fmin_s *a)
376 {
377 REQUIRE_FPU;
378 REQUIRE_ZFINX_OR_F(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_fmin_s(dest, tcg_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_fmax_s(DisasContext *ctx, arg_fmax_s *a)
391 {
392 REQUIRE_FPU;
393 REQUIRE_ZFINX_OR_F(ctx);
394
395 TCGv_i64 dest = dest_fpr(ctx, a->rd);
396 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
397 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
398
399 gen_helper_fmax_s(dest, tcg_env, src1, src2);
400 gen_set_fpr_hs(ctx, a->rd, dest);
401 mark_fs_dirty(ctx);
402 return true;
403 }
404
405 static bool trans_fcvt_w_s(DisasContext *ctx, arg_fcvt_w_s *a)
406 {
407 REQUIRE_FPU;
408 REQUIRE_ZFINX_OR_F(ctx);
409
410 TCGv dest = dest_gpr(ctx, a->rd);
411 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
412
413 gen_set_rm(ctx, a->rm);
414 gen_helper_fcvt_w_s(dest, tcg_env, src1);
415 gen_set_gpr(ctx, a->rd, dest);
416 return true;
417 }
418
419 static bool trans_fcvt_wu_s(DisasContext *ctx, arg_fcvt_wu_s *a)
420 {
421 REQUIRE_FPU;
422 REQUIRE_ZFINX_OR_F(ctx);
423
424 TCGv dest = dest_gpr(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_wu_s(dest, tcg_env, src1);
429 gen_set_gpr(ctx, a->rd, dest);
430 return true;
431 }
432
433 static bool trans_fmv_x_w(DisasContext *ctx, arg_fmv_x_w *a)
434 {
435 /* NOTE: This was FMV.X.S in an earlier version of the ISA spec! */
436 REQUIRE_FPU;
437 /* Zfinx explicitly excludes the FMV transfer instructions. */
438 REQUIRE_EXT(ctx, RVF);
439
440 TCGv dest = dest_gpr(ctx, a->rd);
441 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
442 #if defined(TARGET_RISCV64)
443 tcg_gen_ext32s_tl(dest, src1);
444 #else
445 tcg_gen_extrl_i64_i32(dest, src1);
446 #endif
447
448 gen_set_gpr(ctx, a->rd, dest);
449 return true;
450 }
451
452 static bool trans_feq_s(DisasContext *ctx, arg_feq_s *a)
453 {
454 REQUIRE_FPU;
455 REQUIRE_ZFINX_OR_F(ctx);
456
457 TCGv dest = dest_gpr(ctx, a->rd);
458 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
459 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
460
461 gen_helper_feq_s(dest, tcg_env, src1, src2);
462 gen_set_gpr(ctx, a->rd, dest);
463 return true;
464 }
465
466 static bool trans_flt_s(DisasContext *ctx, arg_flt_s *a)
467 {
468 REQUIRE_FPU;
469 REQUIRE_ZFINX_OR_F(ctx);
470
471 TCGv dest = dest_gpr(ctx, a->rd);
472 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
473 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
474
475 gen_helper_flt_s(dest, tcg_env, src1, src2);
476 gen_set_gpr(ctx, a->rd, dest);
477 return true;
478 }
479
480 static bool trans_fle_s(DisasContext *ctx, arg_fle_s *a)
481 {
482 REQUIRE_FPU;
483 REQUIRE_ZFINX_OR_F(ctx);
484
485 TCGv dest = dest_gpr(ctx, a->rd);
486 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
487 TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
488
489 gen_helper_fle_s(dest, tcg_env, src1, src2);
490 gen_set_gpr(ctx, a->rd, dest);
491 return true;
492 }
493
494 static bool trans_fclass_s(DisasContext *ctx, arg_fclass_s *a)
495 {
496 REQUIRE_FPU;
497 REQUIRE_ZFINX_OR_F(ctx);
498
499 TCGv dest = dest_gpr(ctx, a->rd);
500 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
501
502 gen_helper_fclass_s(dest, tcg_env, src1);
503 gen_set_gpr(ctx, a->rd, dest);
504 return true;
505 }
506
507 static bool trans_fcvt_s_w(DisasContext *ctx, arg_fcvt_s_w *a)
508 {
509 REQUIRE_FPU;
510 REQUIRE_ZFINX_OR_F(ctx);
511
512 TCGv_i64 dest = dest_fpr(ctx, a->rd);
513 TCGv src = get_gpr(ctx, a->rs1, EXT_SIGN);
514
515 gen_set_rm(ctx, a->rm);
516 gen_helper_fcvt_s_w(dest, tcg_env, src);
517 gen_set_fpr_hs(ctx, a->rd, dest);
518 mark_fs_dirty(ctx);
519 return true;
520 }
521
522 static bool trans_fcvt_s_wu(DisasContext *ctx, arg_fcvt_s_wu *a)
523 {
524 REQUIRE_FPU;
525 REQUIRE_ZFINX_OR_F(ctx);
526
527 TCGv_i64 dest = dest_fpr(ctx, a->rd);
528 TCGv src = get_gpr(ctx, a->rs1, EXT_ZERO);
529
530 gen_set_rm(ctx, a->rm);
531 gen_helper_fcvt_s_wu(dest, tcg_env, src);
532 gen_set_fpr_hs(ctx, a->rd, dest);
533 mark_fs_dirty(ctx);
534 return true;
535 }
536
537 static bool trans_fmv_w_x(DisasContext *ctx, arg_fmv_w_x *a)
538 {
539 /* NOTE: This was FMV.S.X in an earlier version of the ISA spec! */
540 REQUIRE_FPU;
541 /* Zfinx explicitly excludes the FMV transfer instructions. */
542 REQUIRE_EXT(ctx, RVF);
543
544 TCGv_i64 dest = dest_fpr(ctx, a->rd);
545 TCGv src = get_gpr(ctx, a->rs1, EXT_ZERO);
546
547 tcg_gen_extu_tl_i64(dest, src);
548 gen_nanbox_s(dest, dest);
549 gen_set_fpr_hs(ctx, a->rd, dest);
550 mark_fs_dirty(ctx);
551 return true;
552 }
553
554 static bool trans_fcvt_l_s(DisasContext *ctx, arg_fcvt_l_s *a)
555 {
556 REQUIRE_64BIT(ctx);
557 REQUIRE_FPU;
558 REQUIRE_ZFINX_OR_F(ctx);
559
560 TCGv dest = dest_gpr(ctx, a->rd);
561 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
562
563 gen_set_rm(ctx, a->rm);
564 gen_helper_fcvt_l_s(dest, tcg_env, src1);
565 gen_set_gpr(ctx, a->rd, dest);
566 return true;
567 }
568
569 static bool trans_fcvt_lu_s(DisasContext *ctx, arg_fcvt_lu_s *a)
570 {
571 REQUIRE_64BIT(ctx);
572 REQUIRE_FPU;
573 REQUIRE_ZFINX_OR_F(ctx);
574
575 TCGv dest = dest_gpr(ctx, a->rd);
576 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
577
578 gen_set_rm(ctx, a->rm);
579 gen_helper_fcvt_lu_s(dest, tcg_env, src1);
580 gen_set_gpr(ctx, a->rd, dest);
581 return true;
582 }
583
584 static bool trans_fcvt_s_l(DisasContext *ctx, arg_fcvt_s_l *a)
585 {
586 REQUIRE_64BIT(ctx);
587 REQUIRE_FPU;
588 REQUIRE_ZFINX_OR_F(ctx);
589
590 TCGv_i64 dest = dest_fpr(ctx, a->rd);
591 TCGv src = get_gpr(ctx, a->rs1, EXT_SIGN);
592
593 gen_set_rm(ctx, a->rm);
594 gen_helper_fcvt_s_l(dest, tcg_env, src);
595 gen_set_fpr_hs(ctx, a->rd, dest);
596 mark_fs_dirty(ctx);
597 return true;
598 }
599
600 static bool trans_fcvt_s_lu(DisasContext *ctx, arg_fcvt_s_lu *a)
601 {
602 REQUIRE_64BIT(ctx);
603 REQUIRE_FPU;
604 REQUIRE_ZFINX_OR_F(ctx);
605
606 TCGv_i64 dest = dest_fpr(ctx, a->rd);
607 TCGv src = get_gpr(ctx, a->rs1, EXT_ZERO);
608
609 gen_set_rm(ctx, a->rm);
610 gen_helper_fcvt_s_lu(dest, tcg_env, src);
611 gen_set_fpr_hs(ctx, a->rd, dest);
612 mark_fs_dirty(ctx);
613 return true;
614 }