qemu/target/riscv/insn_trans/trans_rvd.inc.c
<<
>>
Prefs
   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
  21static bool trans_fld(DisasContext *ctx, arg_fld *a)
  22{
  23    TCGv t0 = tcg_temp_new();
  24    gen_get_gpr(t0, a->rs1);
  25    REQUIRE_FPU;
  26    REQUIRE_EXT(ctx, RVD);
  27    tcg_gen_addi_tl(t0, t0, a->imm);
  28
  29    tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], t0, ctx->mem_idx, MO_TEQ);
  30
  31    mark_fs_dirty(ctx);
  32    tcg_temp_free(t0);
  33    return true;
  34}
  35
  36static bool trans_fsd(DisasContext *ctx, arg_fsd *a)
  37{
  38    TCGv t0 = tcg_temp_new();
  39    gen_get_gpr(t0, a->rs1);
  40    REQUIRE_FPU;
  41    REQUIRE_EXT(ctx, RVD);
  42    tcg_gen_addi_tl(t0, t0, a->imm);
  43
  44    tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, MO_TEQ);
  45
  46    mark_fs_dirty(ctx);
  47    tcg_temp_free(t0);
  48    return true;
  49}
  50
  51static bool trans_fmadd_d(DisasContext *ctx, arg_fmadd_d *a)
  52{
  53    REQUIRE_FPU;
  54    REQUIRE_EXT(ctx, RVD);
  55    gen_set_rm(ctx, a->rm);
  56    gen_helper_fmadd_d(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1],
  57                       cpu_fpr[a->rs2], cpu_fpr[a->rs3]);
  58    mark_fs_dirty(ctx);
  59    return true;
  60}
  61
  62static bool trans_fmsub_d(DisasContext *ctx, arg_fmsub_d *a)
  63{
  64    REQUIRE_FPU;
  65    REQUIRE_EXT(ctx, RVD);
  66    gen_set_rm(ctx, a->rm);
  67    gen_helper_fmsub_d(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1],
  68                       cpu_fpr[a->rs2], cpu_fpr[a->rs3]);
  69    mark_fs_dirty(ctx);
  70    return true;
  71}
  72
  73static bool trans_fnmsub_d(DisasContext *ctx, arg_fnmsub_d *a)
  74{
  75    REQUIRE_FPU;
  76    REQUIRE_EXT(ctx, RVD);
  77    gen_set_rm(ctx, a->rm);
  78    gen_helper_fnmsub_d(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1],
  79                        cpu_fpr[a->rs2], cpu_fpr[a->rs3]);
  80    mark_fs_dirty(ctx);
  81    return true;
  82}
  83
  84static bool trans_fnmadd_d(DisasContext *ctx, arg_fnmadd_d *a)
  85{
  86    REQUIRE_FPU;
  87    REQUIRE_EXT(ctx, RVD);
  88    gen_set_rm(ctx, a->rm);
  89    gen_helper_fnmadd_d(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1],
  90                        cpu_fpr[a->rs2], cpu_fpr[a->rs3]);
  91    mark_fs_dirty(ctx);
  92    return true;
  93}
  94
  95static bool trans_fadd_d(DisasContext *ctx, arg_fadd_d *a)
  96{
  97    REQUIRE_FPU;
  98    REQUIRE_EXT(ctx, RVD);
  99
 100    gen_set_rm(ctx, a->rm);
 101    gen_helper_fadd_d(cpu_fpr[a->rd], cpu_env,
 102                      cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
 103
 104    mark_fs_dirty(ctx);
 105    return true;
 106}
 107
 108static bool trans_fsub_d(DisasContext *ctx, arg_fsub_d *a)
 109{
 110    REQUIRE_FPU;
 111    REQUIRE_EXT(ctx, RVD);
 112
 113    gen_set_rm(ctx, a->rm);
 114    gen_helper_fsub_d(cpu_fpr[a->rd], cpu_env,
 115                      cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
 116
 117    mark_fs_dirty(ctx);
 118    return true;
 119}
 120
 121static bool trans_fmul_d(DisasContext *ctx, arg_fmul_d *a)
 122{
 123    REQUIRE_FPU;
 124    REQUIRE_EXT(ctx, RVD);
 125
 126    gen_set_rm(ctx, a->rm);
 127    gen_helper_fmul_d(cpu_fpr[a->rd], cpu_env,
 128                      cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
 129
 130    mark_fs_dirty(ctx);
 131    return true;
 132}
 133
 134static bool trans_fdiv_d(DisasContext *ctx, arg_fdiv_d *a)
 135{
 136    REQUIRE_FPU;
 137    REQUIRE_EXT(ctx, RVD);
 138
 139    gen_set_rm(ctx, a->rm);
 140    gen_helper_fdiv_d(cpu_fpr[a->rd], cpu_env,
 141                      cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
 142
 143    mark_fs_dirty(ctx);
 144    return true;
 145}
 146
 147static bool trans_fsqrt_d(DisasContext *ctx, arg_fsqrt_d *a)
 148{
 149    REQUIRE_FPU;
 150    REQUIRE_EXT(ctx, RVD);
 151
 152    gen_set_rm(ctx, a->rm);
 153    gen_helper_fsqrt_d(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1]);
 154
 155    mark_fs_dirty(ctx);
 156    return true;
 157}
 158
 159static bool trans_fsgnj_d(DisasContext *ctx, arg_fsgnj_d *a)
 160{
 161    if (a->rs1 == a->rs2) { /* FMOV */
 162        tcg_gen_mov_i64(cpu_fpr[a->rd], cpu_fpr[a->rs1]);
 163    } else {
 164        tcg_gen_deposit_i64(cpu_fpr[a->rd], cpu_fpr[a->rs2],
 165                            cpu_fpr[a->rs1], 0, 63);
 166    }
 167    mark_fs_dirty(ctx);
 168    return true;
 169}
 170
 171static bool trans_fsgnjn_d(DisasContext *ctx, arg_fsgnjn_d *a)
 172{
 173    REQUIRE_FPU;
 174    REQUIRE_EXT(ctx, RVD);
 175    if (a->rs1 == a->rs2) { /* FNEG */
 176        tcg_gen_xori_i64(cpu_fpr[a->rd], cpu_fpr[a->rs1], INT64_MIN);
 177    } else {
 178        TCGv_i64 t0 = tcg_temp_new_i64();
 179        tcg_gen_not_i64(t0, cpu_fpr[a->rs2]);
 180        tcg_gen_deposit_i64(cpu_fpr[a->rd], t0, cpu_fpr[a->rs1], 0, 63);
 181        tcg_temp_free_i64(t0);
 182    }
 183    mark_fs_dirty(ctx);
 184    return true;
 185}
 186
 187static bool trans_fsgnjx_d(DisasContext *ctx, arg_fsgnjx_d *a)
 188{
 189    REQUIRE_FPU;
 190    REQUIRE_EXT(ctx, RVD);
 191    if (a->rs1 == a->rs2) { /* FABS */
 192        tcg_gen_andi_i64(cpu_fpr[a->rd], cpu_fpr[a->rs1], ~INT64_MIN);
 193    } else {
 194        TCGv_i64 t0 = tcg_temp_new_i64();
 195        tcg_gen_andi_i64(t0, cpu_fpr[a->rs2], INT64_MIN);
 196        tcg_gen_xor_i64(cpu_fpr[a->rd], cpu_fpr[a->rs1], t0);
 197        tcg_temp_free_i64(t0);
 198    }
 199    mark_fs_dirty(ctx);
 200    return true;
 201}
 202
 203static bool trans_fmin_d(DisasContext *ctx, arg_fmin_d *a)
 204{
 205    REQUIRE_FPU;
 206    REQUIRE_EXT(ctx, RVD);
 207
 208    gen_helper_fmin_d(cpu_fpr[a->rd], cpu_env,
 209                      cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
 210
 211    mark_fs_dirty(ctx);
 212    return true;
 213}
 214
 215static bool trans_fmax_d(DisasContext *ctx, arg_fmax_d *a)
 216{
 217    REQUIRE_FPU;
 218    REQUIRE_EXT(ctx, RVD);
 219
 220    gen_helper_fmax_d(cpu_fpr[a->rd], cpu_env,
 221                      cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
 222
 223    mark_fs_dirty(ctx);
 224    return true;
 225}
 226
 227static bool trans_fcvt_s_d(DisasContext *ctx, arg_fcvt_s_d *a)
 228{
 229    REQUIRE_FPU;
 230    REQUIRE_EXT(ctx, RVD);
 231
 232    gen_set_rm(ctx, a->rm);
 233    gen_helper_fcvt_s_d(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1]);
 234
 235    mark_fs_dirty(ctx);
 236    return true;
 237}
 238
 239static bool trans_fcvt_d_s(DisasContext *ctx, arg_fcvt_d_s *a)
 240{
 241    REQUIRE_FPU;
 242    REQUIRE_EXT(ctx, RVD);
 243
 244    gen_set_rm(ctx, a->rm);
 245    gen_helper_fcvt_d_s(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1]);
 246
 247    mark_fs_dirty(ctx);
 248    return true;
 249}
 250
 251static bool trans_feq_d(DisasContext *ctx, arg_feq_d *a)
 252{
 253    REQUIRE_FPU;
 254    REQUIRE_EXT(ctx, RVD);
 255
 256    TCGv t0 = tcg_temp_new();
 257    gen_helper_feq_d(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
 258    gen_set_gpr(a->rd, t0);
 259    tcg_temp_free(t0);
 260
 261    return true;
 262}
 263
 264static bool trans_flt_d(DisasContext *ctx, arg_flt_d *a)
 265{
 266    REQUIRE_FPU;
 267    REQUIRE_EXT(ctx, RVD);
 268
 269    TCGv t0 = tcg_temp_new();
 270    gen_helper_flt_d(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
 271    gen_set_gpr(a->rd, t0);
 272    tcg_temp_free(t0);
 273
 274    return true;
 275}
 276
 277static bool trans_fle_d(DisasContext *ctx, arg_fle_d *a)
 278{
 279    REQUIRE_FPU;
 280    REQUIRE_EXT(ctx, RVD);
 281
 282    TCGv t0 = tcg_temp_new();
 283    gen_helper_fle_d(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
 284    gen_set_gpr(a->rd, t0);
 285    tcg_temp_free(t0);
 286
 287    return true;
 288}
 289
 290static bool trans_fclass_d(DisasContext *ctx, arg_fclass_d *a)
 291{
 292    REQUIRE_FPU;
 293    REQUIRE_EXT(ctx, RVD);
 294
 295    TCGv t0 = tcg_temp_new();
 296    gen_helper_fclass_d(t0, cpu_fpr[a->rs1]);
 297    gen_set_gpr(a->rd, t0);
 298    tcg_temp_free(t0);
 299    return true;
 300}
 301
 302static bool trans_fcvt_w_d(DisasContext *ctx, arg_fcvt_w_d *a)
 303{
 304    REQUIRE_FPU;
 305    REQUIRE_EXT(ctx, RVD);
 306
 307    TCGv t0 = tcg_temp_new();
 308    gen_set_rm(ctx, a->rm);
 309    gen_helper_fcvt_w_d(t0, cpu_env, cpu_fpr[a->rs1]);
 310    gen_set_gpr(a->rd, t0);
 311    tcg_temp_free(t0);
 312
 313    return true;
 314}
 315
 316static bool trans_fcvt_wu_d(DisasContext *ctx, arg_fcvt_wu_d *a)
 317{
 318    REQUIRE_FPU;
 319    REQUIRE_EXT(ctx, RVD);
 320
 321    TCGv t0 = tcg_temp_new();
 322    gen_set_rm(ctx, a->rm);
 323    gen_helper_fcvt_wu_d(t0, cpu_env, cpu_fpr[a->rs1]);
 324    gen_set_gpr(a->rd, t0);
 325    tcg_temp_free(t0);
 326
 327    return true;
 328}
 329
 330static bool trans_fcvt_d_w(DisasContext *ctx, arg_fcvt_d_w *a)
 331{
 332    REQUIRE_FPU;
 333    REQUIRE_EXT(ctx, RVD);
 334
 335    TCGv t0 = tcg_temp_new();
 336    gen_get_gpr(t0, a->rs1);
 337
 338    gen_set_rm(ctx, a->rm);
 339    gen_helper_fcvt_d_w(cpu_fpr[a->rd], cpu_env, t0);
 340    tcg_temp_free(t0);
 341
 342    mark_fs_dirty(ctx);
 343    return true;
 344}
 345
 346static bool trans_fcvt_d_wu(DisasContext *ctx, arg_fcvt_d_wu *a)
 347{
 348    REQUIRE_FPU;
 349    REQUIRE_EXT(ctx, RVD);
 350
 351    TCGv t0 = tcg_temp_new();
 352    gen_get_gpr(t0, a->rs1);
 353
 354    gen_set_rm(ctx, a->rm);
 355    gen_helper_fcvt_d_wu(cpu_fpr[a->rd], cpu_env, t0);
 356    tcg_temp_free(t0);
 357
 358    mark_fs_dirty(ctx);
 359    return true;
 360}
 361
 362#ifdef TARGET_RISCV64
 363
 364static bool trans_fcvt_l_d(DisasContext *ctx, arg_fcvt_l_d *a)
 365{
 366    REQUIRE_FPU;
 367    REQUIRE_EXT(ctx, RVD);
 368
 369    TCGv t0 = tcg_temp_new();
 370    gen_set_rm(ctx, a->rm);
 371    gen_helper_fcvt_l_d(t0, cpu_env, cpu_fpr[a->rs1]);
 372    gen_set_gpr(a->rd, t0);
 373    tcg_temp_free(t0);
 374    return true;
 375}
 376
 377static bool trans_fcvt_lu_d(DisasContext *ctx, arg_fcvt_lu_d *a)
 378{
 379    REQUIRE_FPU;
 380    REQUIRE_EXT(ctx, RVD);
 381
 382    TCGv t0 = tcg_temp_new();
 383    gen_set_rm(ctx, a->rm);
 384    gen_helper_fcvt_lu_d(t0, cpu_env, cpu_fpr[a->rs1]);
 385    gen_set_gpr(a->rd, t0);
 386    tcg_temp_free(t0);
 387    return true;
 388}
 389
 390static bool trans_fmv_x_d(DisasContext *ctx, arg_fmv_x_d *a)
 391{
 392    REQUIRE_FPU;
 393    REQUIRE_EXT(ctx, RVD);
 394
 395    gen_set_gpr(a->rd, cpu_fpr[a->rs1]);
 396    return true;
 397}
 398
 399static bool trans_fcvt_d_l(DisasContext *ctx, arg_fcvt_d_l *a)
 400{
 401    REQUIRE_FPU;
 402    REQUIRE_EXT(ctx, RVD);
 403
 404    TCGv t0 = tcg_temp_new();
 405    gen_get_gpr(t0, a->rs1);
 406
 407    gen_set_rm(ctx, a->rm);
 408    gen_helper_fcvt_d_l(cpu_fpr[a->rd], cpu_env, t0);
 409    tcg_temp_free(t0);
 410    mark_fs_dirty(ctx);
 411    return true;
 412}
 413
 414static bool trans_fcvt_d_lu(DisasContext *ctx, arg_fcvt_d_lu *a)
 415{
 416    REQUIRE_FPU;
 417    REQUIRE_EXT(ctx, RVD);
 418
 419    TCGv t0 = tcg_temp_new();
 420    gen_get_gpr(t0, a->rs1);
 421
 422    gen_set_rm(ctx, a->rm);
 423    gen_helper_fcvt_d_lu(cpu_fpr[a->rd], cpu_env, t0);
 424    tcg_temp_free(t0);
 425    mark_fs_dirty(ctx);
 426    return true;
 427}
 428
 429static bool trans_fmv_d_x(DisasContext *ctx, arg_fmv_d_x *a)
 430{
 431    REQUIRE_FPU;
 432    REQUIRE_EXT(ctx, RVD);
 433
 434    TCGv t0 = tcg_temp_new();
 435    gen_get_gpr(t0, a->rs1);
 436
 437    tcg_gen_mov_tl(cpu_fpr[a->rd], t0);
 438    tcg_temp_free(t0);
 439    mark_fs_dirty(ctx);
 440    return true;
 441}
 442#endif
 443