1/* 2 * RISC-V translation routines for the RV64D 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_ZDINX_OR_D(ctx) do { \ 22 if (!ctx->cfg_ptr->ext_zdinx) { \ 23 REQUIRE_EXT(ctx, RVD); \ 24 } \ 25} while (0) 26 27#define REQUIRE_EVEN(ctx, reg) do { \ 28 if (ctx->cfg_ptr->ext_zdinx && (get_xl(ctx) == MXL_RV32) && \ 29 ((reg) & 0x1)) { \ 30 return false; \ 31 } \ 32} while (0) 33 34#define REQUIRE_ZCD_OR_DC(ctx) do { \ 35 if (!ctx->cfg_ptr->ext_zcd) { \ 36 if (!has_ext(ctx, RVD) || !has_ext(ctx, RVC)) { \ 37 return false; \ 38 } \ 39 } \ 40} while (0) 41 42static bool trans_fld(DisasContext *ctx, arg_fld *a) 43{ 44 TCGv addr; 45 MemOp memop = MO_TEUQ; 46 47 REQUIRE_FPU; 48 REQUIRE_EXT(ctx, RVD); 49 50 /* 51 * FLD and FSD are only guaranteed to execute atomically if the effective 52 * address is naturally aligned and XLEN≥64. Also, zama16b applies to 53 * loads and stores of no more than MXLEN bits defined in the F, D, and 54 * Q extensions. 55 */ 56 if (get_xl_max(ctx) == MXL_RV32) { 57 memop |= MO_ATOM_NONE; 58 } else if (ctx->cfg_ptr->ext_zama16b) { 59 memop |= MO_ATOM_WITHIN16; 60 } else { 61 memop |= MO_ATOM_IFALIGN; 62 } 63 64 decode_save_opc(ctx, 0); 65 addr = get_address(ctx, a->rs1, a->imm); 66 tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], addr, ctx->mem_idx, memop); 67 68 mark_fs_dirty(ctx); 69 return true; 70} 71 72static bool trans_fsd(DisasContext *ctx, arg_fsd *a) 73{ 74 TCGv addr; 75 MemOp memop = MO_TEUQ; 76 77 REQUIRE_FPU; 78 REQUIRE_EXT(ctx, RVD); 79 80 if (get_xl_max(ctx) == MXL_RV32) { 81 memop |= MO_ATOM_NONE; 82 } else if (ctx->cfg_ptr->ext_zama16b) { 83 memop |= MO_ATOM_WITHIN16; 84 } else { 85 memop |= MO_ATOM_IFALIGN; 86 } 87 88 decode_save_opc(ctx, 0); 89 addr = get_address(ctx, a->rs1, a->imm); 90 tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, memop); 91 return true; 92} 93 94static bool trans_c_fld(DisasContext *ctx, arg_fld *a) 95{ 96 REQUIRE_ZCD_OR_DC(ctx); 97 return trans_fld(ctx, a); 98} 99 100static bool trans_c_fsd(DisasContext *ctx, arg_fsd *a) 101{ 102 REQUIRE_ZCD_OR_DC(ctx); 103 return trans_fsd(ctx, a); 104} 105 106static bool trans_fmadd_d(DisasContext *ctx, arg_fmadd_d *a) 107{ 108 REQUIRE_FPU; 109 REQUIRE_ZDINX_OR_D(ctx); 110 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2 | a->rs3); 111 112 TCGv_i64 dest = dest_fpr(ctx, a->rd); 113 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 114 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2); 115 TCGv_i64 src3 = get_fpr_d(ctx, a->rs3); 116 117 gen_set_rm(ctx, a->rm); 118 gen_helper_fmadd_d(dest, tcg_env, src1, src2, src3); 119 gen_set_fpr_d(ctx, a->rd, dest); 120 mark_fs_dirty(ctx); 121 return true; 122} 123 124static bool trans_fmsub_d(DisasContext *ctx, arg_fmsub_d *a) 125{ 126 REQUIRE_FPU; 127 REQUIRE_ZDINX_OR_D(ctx); 128 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2 | a->rs3); 129 130 TCGv_i64 dest = dest_fpr(ctx, a->rd); 131 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 132 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2); 133 TCGv_i64 src3 = get_fpr_d(ctx, a->rs3); 134 135 gen_set_rm(ctx, a->rm); 136 gen_helper_fmsub_d(dest, tcg_env, src1, src2, src3); 137 gen_set_fpr_d(ctx, a->rd, dest); 138 mark_fs_dirty(ctx); 139 return true; 140} 141 142static bool trans_fnmsub_d(DisasContext *ctx, arg_fnmsub_d *a) 143{ 144 REQUIRE_FPU; 145 REQUIRE_ZDINX_OR_D(ctx); 146 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2 | a->rs3); 147 148 TCGv_i64 dest = dest_fpr(ctx, a->rd); 149 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 150 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2); 151 TCGv_i64 src3 = get_fpr_d(ctx, a->rs3); 152 153 gen_set_rm(ctx, a->rm); 154 gen_helper_fnmsub_d(dest, tcg_env, src1, src2, src3); 155 gen_set_fpr_d(ctx, a->rd, dest); 156 mark_fs_dirty(ctx); 157 return true; 158} 159 160static bool trans_fnmadd_d(DisasContext *ctx, arg_fnmadd_d *a) 161{ 162 REQUIRE_FPU; 163 REQUIRE_ZDINX_OR_D(ctx); 164 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2 | a->rs3); 165 166 TCGv_i64 dest = dest_fpr(ctx, a->rd); 167 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 168 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2); 169 TCGv_i64 src3 = get_fpr_d(ctx, a->rs3); 170 171 gen_set_rm(ctx, a->rm); 172 gen_helper_fnmadd_d(dest, tcg_env, src1, src2, src3); 173 gen_set_fpr_d(ctx, a->rd, dest); 174 mark_fs_dirty(ctx); 175 return true; 176} 177 178static bool trans_fadd_d(DisasContext *ctx, arg_fadd_d *a) 179{ 180 REQUIRE_FPU; 181 REQUIRE_ZDINX_OR_D(ctx); 182 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2); 183 184 TCGv_i64 dest = dest_fpr(ctx, a->rd); 185 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 186 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2); 187 188 gen_set_rm(ctx, a->rm); 189 gen_helper_fadd_d(dest, tcg_env, src1, src2); 190 gen_set_fpr_d(ctx, a->rd, dest); 191 mark_fs_dirty(ctx); 192 return true; 193} 194 195static bool trans_fsub_d(DisasContext *ctx, arg_fsub_d *a) 196{ 197 REQUIRE_FPU; 198 REQUIRE_ZDINX_OR_D(ctx); 199 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2); 200 201 TCGv_i64 dest = dest_fpr(ctx, a->rd); 202 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 203 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2); 204 205 gen_set_rm(ctx, a->rm); 206 gen_helper_fsub_d(dest, tcg_env, src1, src2); 207 gen_set_fpr_d(ctx, a->rd, dest); 208 mark_fs_dirty(ctx); 209 return true; 210} 211 212static bool trans_fmul_d(DisasContext *ctx, arg_fmul_d *a) 213{ 214 REQUIRE_FPU; 215 REQUIRE_ZDINX_OR_D(ctx); 216 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2); 217 218 TCGv_i64 dest = dest_fpr(ctx, a->rd); 219 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 220 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2); 221 222 gen_set_rm(ctx, a->rm); 223 gen_helper_fmul_d(dest, tcg_env, src1, src2); 224 gen_set_fpr_d(ctx, a->rd, dest); 225 mark_fs_dirty(ctx); 226 return true; 227} 228 229static bool trans_fdiv_d(DisasContext *ctx, arg_fdiv_d *a) 230{ 231 REQUIRE_FPU; 232 REQUIRE_ZDINX_OR_D(ctx); 233 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2); 234 235 TCGv_i64 dest = dest_fpr(ctx, a->rd); 236 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 237 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2); 238 239 gen_set_rm(ctx, a->rm); 240 gen_helper_fdiv_d(dest, tcg_env, src1, src2); 241 gen_set_fpr_d(ctx, a->rd, dest); 242 mark_fs_dirty(ctx); 243 return true; 244} 245 246static bool trans_fsqrt_d(DisasContext *ctx, arg_fsqrt_d *a) 247{ 248 REQUIRE_FPU; 249 REQUIRE_ZDINX_OR_D(ctx); 250 REQUIRE_EVEN(ctx, a->rd | a->rs1); 251 252 TCGv_i64 dest = dest_fpr(ctx, a->rd); 253 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 254 255 gen_set_rm(ctx, a->rm); 256 gen_helper_fsqrt_d(dest, tcg_env, src1); 257 gen_set_fpr_d(ctx, a->rd, dest); 258 mark_fs_dirty(ctx); 259 return true; 260} 261 262static bool trans_fsgnj_d(DisasContext *ctx, arg_fsgnj_d *a) 263{ 264 REQUIRE_FPU; 265 REQUIRE_ZDINX_OR_D(ctx); 266 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2); 267 268 TCGv_i64 dest = dest_fpr(ctx, a->rd); 269 if (a->rs1 == a->rs2) { /* FMOV */ 270 dest = get_fpr_d(ctx, a->rs1); 271 } else { 272 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 273 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2); 274 tcg_gen_deposit_i64(dest, src2, src1, 0, 63); 275 } 276 gen_set_fpr_d(ctx, a->rd, dest); 277 mark_fs_dirty(ctx); 278 return true; 279} 280 281static bool trans_fsgnjn_d(DisasContext *ctx, arg_fsgnjn_d *a) 282{ 283 REQUIRE_FPU; 284 REQUIRE_ZDINX_OR_D(ctx); 285 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2); 286 287 TCGv_i64 dest = dest_fpr(ctx, a->rd); 288 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 289 290 if (a->rs1 == a->rs2) { /* FNEG */ 291 tcg_gen_xori_i64(dest, src1, INT64_MIN); 292 } else { 293 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2); 294 TCGv_i64 t0 = tcg_temp_new_i64(); 295 tcg_gen_not_i64(t0, src2); 296 tcg_gen_deposit_i64(dest, t0, src1, 0, 63); 297 } 298 gen_set_fpr_d(ctx, a->rd, dest); 299 mark_fs_dirty(ctx); 300 return true; 301} 302 303static bool trans_fsgnjx_d(DisasContext *ctx, arg_fsgnjx_d *a) 304{ 305 REQUIRE_FPU; 306 REQUIRE_ZDINX_OR_D(ctx); 307 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2); 308 309 TCGv_i64 dest = dest_fpr(ctx, a->rd); 310 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 311 312 if (a->rs1 == a->rs2) { /* FABS */ 313 tcg_gen_andi_i64(dest, src1, ~INT64_MIN); 314 } else { 315 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2); 316 TCGv_i64 t0 = tcg_temp_new_i64(); 317 tcg_gen_andi_i64(t0, src2, INT64_MIN); 318 tcg_gen_xor_i64(dest, src1, t0); 319 } 320 gen_set_fpr_d(ctx, a->rd, dest); 321 mark_fs_dirty(ctx); 322 return true; 323} 324 325static bool trans_fmin_d(DisasContext *ctx, arg_fmin_d *a) 326{ 327 REQUIRE_FPU; 328 REQUIRE_ZDINX_OR_D(ctx); 329 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2); 330 331 TCGv_i64 dest = dest_fpr(ctx, a->rd); 332 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 333 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2); 334 335 gen_helper_fmin_d(dest, tcg_env, src1, src2); 336 gen_set_fpr_d(ctx, a->rd, dest); 337 mark_fs_dirty(ctx); 338 return true; 339} 340 341static bool trans_fmax_d(DisasContext *ctx, arg_fmax_d *a) 342{ 343 REQUIRE_FPU; 344 REQUIRE_ZDINX_OR_D(ctx); 345 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2); 346 347 TCGv_i64 dest = dest_fpr(ctx, a->rd); 348 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 349 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2); 350 351 gen_helper_fmax_d(dest, tcg_env, src1, src2); 352 gen_set_fpr_d(ctx, a->rd, dest); 353 mark_fs_dirty(ctx); 354 return true; 355} 356 357static bool trans_fcvt_s_d(DisasContext *ctx, arg_fcvt_s_d *a) 358{ 359 REQUIRE_FPU; 360 REQUIRE_ZDINX_OR_D(ctx); 361 REQUIRE_EVEN(ctx, a->rs1); 362 363 TCGv_i64 dest = dest_fpr(ctx, a->rd); 364 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 365 366 gen_set_rm(ctx, a->rm); 367 gen_helper_fcvt_s_d(dest, tcg_env, src1); 368 gen_set_fpr_hs(ctx, a->rd, dest); 369 mark_fs_dirty(ctx); 370 return true; 371} 372 373static bool trans_fcvt_d_s(DisasContext *ctx, arg_fcvt_d_s *a) 374{ 375 REQUIRE_FPU; 376 REQUIRE_ZDINX_OR_D(ctx); 377 REQUIRE_EVEN(ctx, a->rd); 378 379 TCGv_i64 dest = dest_fpr(ctx, a->rd); 380 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1); 381 382 gen_set_rm(ctx, a->rm); 383 gen_helper_fcvt_d_s(dest, tcg_env, src1); 384 gen_set_fpr_d(ctx, a->rd, dest); 385 mark_fs_dirty(ctx); 386 return true; 387} 388 389static bool trans_feq_d(DisasContext *ctx, arg_feq_d *a) 390{ 391 REQUIRE_FPU; 392 REQUIRE_ZDINX_OR_D(ctx); 393 REQUIRE_EVEN(ctx, a->rs1 | a->rs2); 394 395 TCGv dest = dest_gpr(ctx, a->rd); 396 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 397 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2); 398 399 gen_helper_feq_d(dest, tcg_env, src1, src2); 400 gen_set_gpr(ctx, a->rd, dest); 401 return true; 402} 403 404static bool trans_flt_d(DisasContext *ctx, arg_flt_d *a) 405{ 406 REQUIRE_FPU; 407 REQUIRE_ZDINX_OR_D(ctx); 408 REQUIRE_EVEN(ctx, a->rs1 | a->rs2); 409 410 TCGv dest = dest_gpr(ctx, a->rd); 411 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 412 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2); 413 414 gen_helper_flt_d(dest, tcg_env, src1, src2); 415 gen_set_gpr(ctx, a->rd, dest); 416 return true; 417} 418 419static bool trans_fle_d(DisasContext *ctx, arg_fle_d *a) 420{ 421 REQUIRE_FPU; 422 REQUIRE_ZDINX_OR_D(ctx); 423 REQUIRE_EVEN(ctx, a->rs1 | a->rs2); 424 425 TCGv dest = dest_gpr(ctx, a->rd); 426 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 427 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2); 428 429 gen_helper_fle_d(dest, tcg_env, src1, src2); 430 gen_set_gpr(ctx, a->rd, dest); 431 return true; 432} 433 434static bool trans_fclass_d(DisasContext *ctx, arg_fclass_d *a) 435{ 436 REQUIRE_FPU; 437 REQUIRE_ZDINX_OR_D(ctx); 438 REQUIRE_EVEN(ctx, a->rs1); 439 440 TCGv dest = dest_gpr(ctx, a->rd); 441 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 442 443 gen_helper_fclass_d(dest, src1); 444 gen_set_gpr(ctx, a->rd, dest); 445 return true; 446} 447 448static bool trans_fcvt_w_d(DisasContext *ctx, arg_fcvt_w_d *a) 449{ 450 REQUIRE_FPU; 451 REQUIRE_ZDINX_OR_D(ctx); 452 REQUIRE_EVEN(ctx, a->rs1); 453 454 TCGv dest = dest_gpr(ctx, a->rd); 455 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 456 457 gen_set_rm(ctx, a->rm); 458 gen_helper_fcvt_w_d(dest, tcg_env, src1); 459 gen_set_gpr(ctx, a->rd, dest); 460 return true; 461} 462 463static bool trans_fcvt_wu_d(DisasContext *ctx, arg_fcvt_wu_d *a) 464{ 465 REQUIRE_FPU; 466 REQUIRE_ZDINX_OR_D(ctx); 467 REQUIRE_EVEN(ctx, a->rs1); 468 469 TCGv dest = dest_gpr(ctx, a->rd); 470 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 471 472 gen_set_rm(ctx, a->rm); 473 gen_helper_fcvt_wu_d(dest, tcg_env, src1); 474 gen_set_gpr(ctx, a->rd, dest); 475 return true; 476} 477 478static bool trans_fcvt_d_w(DisasContext *ctx, arg_fcvt_d_w *a) 479{ 480 REQUIRE_FPU; 481 REQUIRE_ZDINX_OR_D(ctx); 482 REQUIRE_EVEN(ctx, a->rd); 483 484 TCGv_i64 dest = dest_fpr(ctx, a->rd); 485 TCGv src = get_gpr(ctx, a->rs1, EXT_SIGN); 486 487 gen_set_rm(ctx, a->rm); 488 gen_helper_fcvt_d_w(dest, tcg_env, src); 489 gen_set_fpr_d(ctx, a->rd, dest); 490 491 mark_fs_dirty(ctx); 492 return true; 493} 494 495static bool trans_fcvt_d_wu(DisasContext *ctx, arg_fcvt_d_wu *a) 496{ 497 REQUIRE_FPU; 498 REQUIRE_ZDINX_OR_D(ctx); 499 REQUIRE_EVEN(ctx, a->rd); 500 501 TCGv_i64 dest = dest_fpr(ctx, a->rd); 502 TCGv src = get_gpr(ctx, a->rs1, EXT_ZERO); 503 504 gen_set_rm(ctx, a->rm); 505 gen_helper_fcvt_d_wu(dest, tcg_env, src); 506 gen_set_fpr_d(ctx, a->rd, dest); 507 508 mark_fs_dirty(ctx); 509 return true; 510} 511 512static bool trans_fcvt_l_d(DisasContext *ctx, arg_fcvt_l_d *a) 513{ 514 REQUIRE_64BIT(ctx); 515 REQUIRE_FPU; 516 REQUIRE_ZDINX_OR_D(ctx); 517 REQUIRE_EVEN(ctx, a->rs1); 518 519 TCGv dest = dest_gpr(ctx, a->rd); 520 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 521 522 gen_set_rm(ctx, a->rm); 523 gen_helper_fcvt_l_d(dest, tcg_env, src1); 524 gen_set_gpr(ctx, a->rd, dest); 525 return true; 526} 527 528static bool trans_fcvt_lu_d(DisasContext *ctx, arg_fcvt_lu_d *a) 529{ 530 REQUIRE_64BIT(ctx); 531 REQUIRE_FPU; 532 REQUIRE_ZDINX_OR_D(ctx); 533 REQUIRE_EVEN(ctx, a->rs1); 534 535 TCGv dest = dest_gpr(ctx, a->rd); 536 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1); 537 538 gen_set_rm(ctx, a->rm); 539 gen_helper_fcvt_lu_d(dest, tcg_env, src1); 540 gen_set_gpr(ctx, a->rd, dest); 541 return true; 542} 543 544static bool trans_fmv_x_d(DisasContext *ctx, arg_fmv_x_d *a) 545{ 546 REQUIRE_64BIT(ctx); 547 REQUIRE_FPU; 548 REQUIRE_EXT(ctx, RVD); 549 550#ifdef TARGET_RISCV64 551 gen_set_gpr(ctx, a->rd, cpu_fpr[a->rs1]); 552 return true; 553#else 554 qemu_build_not_reached(); 555#endif 556} 557 558static bool trans_fcvt_d_l(DisasContext *ctx, arg_fcvt_d_l *a) 559{ 560 REQUIRE_64BIT(ctx); 561 REQUIRE_FPU; 562 REQUIRE_ZDINX_OR_D(ctx); 563 REQUIRE_EVEN(ctx, a->rd); 564 565 TCGv_i64 dest = dest_fpr(ctx, a->rd); 566 TCGv src = get_gpr(ctx, a->rs1, EXT_SIGN); 567 568 gen_set_rm(ctx, a->rm); 569 gen_helper_fcvt_d_l(dest, tcg_env, src); 570 gen_set_fpr_d(ctx, a->rd, dest); 571 572 mark_fs_dirty(ctx); 573 return true; 574} 575 576static bool trans_fcvt_d_lu(DisasContext *ctx, arg_fcvt_d_lu *a) 577{ 578 REQUIRE_64BIT(ctx); 579 REQUIRE_FPU; 580 REQUIRE_ZDINX_OR_D(ctx); 581 REQUIRE_EVEN(ctx, a->rd); 582 583 TCGv_i64 dest = dest_fpr(ctx, a->rd); 584 TCGv src = get_gpr(ctx, a->rs1, EXT_ZERO); 585 586 gen_set_rm(ctx, a->rm); 587 gen_helper_fcvt_d_lu(dest, tcg_env, src); 588 gen_set_fpr_d(ctx, a->rd, dest); 589 590 mark_fs_dirty(ctx); 591 return true; 592} 593 594static bool trans_fmv_d_x(DisasContext *ctx, arg_fmv_d_x *a) 595{ 596 REQUIRE_64BIT(ctx); 597 REQUIRE_FPU; 598 REQUIRE_EXT(ctx, RVD); 599 600#ifdef TARGET_RISCV64 601 tcg_gen_mov_tl(cpu_fpr[a->rd], get_gpr(ctx, a->rs1, EXT_NONE)); 602 mark_fs_dirty(ctx); 603 return true; 604#else 605 qemu_build_not_reached(); 606#endif 607} 608