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