2 * RISC-V translation routines for the RV64F Standard Extension.
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
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.
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
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/>.
21 #define REQUIRE_FPU do {\
22 if (ctx->mstatus_fs == 0) \
26 static bool trans_flw(DisasContext
*ctx
, arg_flw
*a
)
28 TCGv t0
= tcg_temp_new();
29 gen_get_gpr(t0
, a
->rs1
);
31 REQUIRE_EXT(ctx
, RVF
);
32 tcg_gen_addi_tl(t0
, t0
, a
->imm
);
34 tcg_gen_qemu_ld_i64(cpu_fpr
[a
->rd
], t0
, ctx
->mem_idx
, MO_TEUL
);
35 /* RISC-V requires NaN-boxing of narrower width floating point values */
36 tcg_gen_ori_i64(cpu_fpr
[a
->rd
], cpu_fpr
[a
->rd
], 0xffffffff00000000ULL
);
43 static bool trans_fsw(DisasContext
*ctx
, arg_fsw
*a
)
45 TCGv t0
= tcg_temp_new();
46 gen_get_gpr(t0
, a
->rs1
);
49 REQUIRE_EXT(ctx
, RVF
);
50 tcg_gen_addi_tl(t0
, t0
, a
->imm
);
52 tcg_gen_qemu_st_i64(cpu_fpr
[a
->rs2
], t0
, ctx
->mem_idx
, MO_TEUL
);
59 static bool trans_fmadd_s(DisasContext
*ctx
, arg_fmadd_s
*a
)
62 REQUIRE_EXT(ctx
, RVF
);
63 gen_set_rm(ctx
, a
->rm
);
64 gen_helper_fmadd_s(cpu_fpr
[a
->rd
], cpu_env
, cpu_fpr
[a
->rs1
],
65 cpu_fpr
[a
->rs2
], cpu_fpr
[a
->rs3
]);
70 static bool trans_fmsub_s(DisasContext
*ctx
, arg_fmsub_s
*a
)
73 REQUIRE_EXT(ctx
, RVF
);
74 gen_set_rm(ctx
, a
->rm
);
75 gen_helper_fmsub_s(cpu_fpr
[a
->rd
], cpu_env
, cpu_fpr
[a
->rs1
],
76 cpu_fpr
[a
->rs2
], cpu_fpr
[a
->rs3
]);
81 static bool trans_fnmsub_s(DisasContext
*ctx
, arg_fnmsub_s
*a
)
84 REQUIRE_EXT(ctx
, RVF
);
85 gen_set_rm(ctx
, a
->rm
);
86 gen_helper_fnmsub_s(cpu_fpr
[a
->rd
], cpu_env
, cpu_fpr
[a
->rs1
],
87 cpu_fpr
[a
->rs2
], cpu_fpr
[a
->rs3
]);
92 static bool trans_fnmadd_s(DisasContext
*ctx
, arg_fnmadd_s
*a
)
95 REQUIRE_EXT(ctx
, RVF
);
96 gen_set_rm(ctx
, a
->rm
);
97 gen_helper_fnmadd_s(cpu_fpr
[a
->rd
], cpu_env
, cpu_fpr
[a
->rs1
],
98 cpu_fpr
[a
->rs2
], cpu_fpr
[a
->rs3
]);
103 static bool trans_fadd_s(DisasContext
*ctx
, arg_fadd_s
*a
)
106 REQUIRE_EXT(ctx
, RVF
);
108 gen_set_rm(ctx
, a
->rm
);
109 gen_helper_fadd_s(cpu_fpr
[a
->rd
], cpu_env
,
110 cpu_fpr
[a
->rs1
], cpu_fpr
[a
->rs2
]);
115 static bool trans_fsub_s(DisasContext
*ctx
, arg_fsub_s
*a
)
118 REQUIRE_EXT(ctx
, RVF
);
120 gen_set_rm(ctx
, a
->rm
);
121 gen_helper_fsub_s(cpu_fpr
[a
->rd
], cpu_env
,
122 cpu_fpr
[a
->rs1
], cpu_fpr
[a
->rs2
]);
127 static bool trans_fmul_s(DisasContext
*ctx
, arg_fmul_s
*a
)
130 REQUIRE_EXT(ctx
, RVF
);
132 gen_set_rm(ctx
, a
->rm
);
133 gen_helper_fmul_s(cpu_fpr
[a
->rd
], cpu_env
,
134 cpu_fpr
[a
->rs1
], cpu_fpr
[a
->rs2
]);
139 static bool trans_fdiv_s(DisasContext
*ctx
, arg_fdiv_s
*a
)
142 REQUIRE_EXT(ctx
, RVF
);
144 gen_set_rm(ctx
, a
->rm
);
145 gen_helper_fdiv_s(cpu_fpr
[a
->rd
], cpu_env
,
146 cpu_fpr
[a
->rs1
], cpu_fpr
[a
->rs2
]);
151 static bool trans_fsqrt_s(DisasContext
*ctx
, arg_fsqrt_s
*a
)
154 REQUIRE_EXT(ctx
, RVF
);
156 gen_set_rm(ctx
, a
->rm
);
157 gen_helper_fsqrt_s(cpu_fpr
[a
->rd
], cpu_env
, cpu_fpr
[a
->rs1
]);
162 static bool trans_fsgnj_s(DisasContext
*ctx
, arg_fsgnj_s
*a
)
165 REQUIRE_EXT(ctx
, RVF
);
166 if (a
->rs1
== a
->rs2
) { /* FMOV */
167 tcg_gen_mov_i64(cpu_fpr
[a
->rd
], cpu_fpr
[a
->rs1
]);
169 tcg_gen_deposit_i64(cpu_fpr
[a
->rd
], cpu_fpr
[a
->rs2
], cpu_fpr
[a
->rs1
],
176 static bool trans_fsgnjn_s(DisasContext
*ctx
, arg_fsgnjn_s
*a
)
179 REQUIRE_EXT(ctx
, RVF
);
180 if (a
->rs1
== a
->rs2
) { /* FNEG */
181 tcg_gen_xori_i64(cpu_fpr
[a
->rd
], cpu_fpr
[a
->rs1
], INT32_MIN
);
183 TCGv_i64 t0
= tcg_temp_new_i64();
184 tcg_gen_not_i64(t0
, cpu_fpr
[a
->rs2
]);
185 tcg_gen_deposit_i64(cpu_fpr
[a
->rd
], t0
, cpu_fpr
[a
->rs1
], 0, 31);
186 tcg_temp_free_i64(t0
);
192 static bool trans_fsgnjx_s(DisasContext
*ctx
, arg_fsgnjx_s
*a
)
195 REQUIRE_EXT(ctx
, RVF
);
196 if (a
->rs1
== a
->rs2
) { /* FABS */
197 tcg_gen_andi_i64(cpu_fpr
[a
->rd
], cpu_fpr
[a
->rs1
], ~INT32_MIN
);
199 TCGv_i64 t0
= tcg_temp_new_i64();
200 tcg_gen_andi_i64(t0
, cpu_fpr
[a
->rs2
], INT32_MIN
);
201 tcg_gen_xor_i64(cpu_fpr
[a
->rd
], cpu_fpr
[a
->rs1
], t0
);
202 tcg_temp_free_i64(t0
);
208 static bool trans_fmin_s(DisasContext
*ctx
, arg_fmin_s
*a
)
211 REQUIRE_EXT(ctx
, RVF
);
213 gen_helper_fmin_s(cpu_fpr
[a
->rd
], cpu_env
, cpu_fpr
[a
->rs1
],
219 static bool trans_fmax_s(DisasContext
*ctx
, arg_fmax_s
*a
)
222 REQUIRE_EXT(ctx
, RVF
);
224 gen_helper_fmax_s(cpu_fpr
[a
->rd
], cpu_env
, cpu_fpr
[a
->rs1
],
230 static bool trans_fcvt_w_s(DisasContext
*ctx
, arg_fcvt_w_s
*a
)
233 REQUIRE_EXT(ctx
, RVF
);
235 TCGv t0
= tcg_temp_new();
236 gen_set_rm(ctx
, a
->rm
);
237 gen_helper_fcvt_w_s(t0
, cpu_env
, cpu_fpr
[a
->rs1
]);
238 gen_set_gpr(a
->rd
, t0
);
244 static bool trans_fcvt_wu_s(DisasContext
*ctx
, arg_fcvt_wu_s
*a
)
247 REQUIRE_EXT(ctx
, RVF
);
249 TCGv t0
= tcg_temp_new();
250 gen_set_rm(ctx
, a
->rm
);
251 gen_helper_fcvt_wu_s(t0
, cpu_env
, cpu_fpr
[a
->rs1
]);
252 gen_set_gpr(a
->rd
, t0
);
258 static bool trans_fmv_x_w(DisasContext
*ctx
, arg_fmv_x_w
*a
)
260 /* NOTE: This was FMV.X.S in an earlier version of the ISA spec! */
262 REQUIRE_EXT(ctx
, RVF
);
264 TCGv t0
= tcg_temp_new();
266 #if defined(TARGET_RISCV64)
267 tcg_gen_ext32s_tl(t0
, cpu_fpr
[a
->rs1
]);
269 tcg_gen_extrl_i64_i32(t0
, cpu_fpr
[a
->rs1
]);
272 gen_set_gpr(a
->rd
, t0
);
278 static bool trans_feq_s(DisasContext
*ctx
, arg_feq_s
*a
)
281 REQUIRE_EXT(ctx
, RVF
);
282 TCGv t0
= tcg_temp_new();
283 gen_helper_feq_s(t0
, cpu_env
, cpu_fpr
[a
->rs1
], cpu_fpr
[a
->rs2
]);
284 gen_set_gpr(a
->rd
, t0
);
289 static bool trans_flt_s(DisasContext
*ctx
, arg_flt_s
*a
)
292 REQUIRE_EXT(ctx
, RVF
);
293 TCGv t0
= tcg_temp_new();
294 gen_helper_flt_s(t0
, cpu_env
, cpu_fpr
[a
->rs1
], cpu_fpr
[a
->rs2
]);
295 gen_set_gpr(a
->rd
, t0
);
300 static bool trans_fle_s(DisasContext
*ctx
, arg_fle_s
*a
)
303 REQUIRE_EXT(ctx
, RVF
);
304 TCGv t0
= tcg_temp_new();
305 gen_helper_fle_s(t0
, cpu_env
, cpu_fpr
[a
->rs1
], cpu_fpr
[a
->rs2
]);
306 gen_set_gpr(a
->rd
, t0
);
311 static bool trans_fclass_s(DisasContext
*ctx
, arg_fclass_s
*a
)
314 REQUIRE_EXT(ctx
, RVF
);
316 TCGv t0
= tcg_temp_new();
318 gen_helper_fclass_s(t0
, cpu_fpr
[a
->rs1
]);
320 gen_set_gpr(a
->rd
, t0
);
326 static bool trans_fcvt_s_w(DisasContext
*ctx
, arg_fcvt_s_w
*a
)
329 REQUIRE_EXT(ctx
, RVF
);
331 TCGv t0
= tcg_temp_new();
332 gen_get_gpr(t0
, a
->rs1
);
334 gen_set_rm(ctx
, a
->rm
);
335 gen_helper_fcvt_s_w(cpu_fpr
[a
->rd
], cpu_env
, t0
);
343 static bool trans_fcvt_s_wu(DisasContext
*ctx
, arg_fcvt_s_wu
*a
)
346 REQUIRE_EXT(ctx
, RVF
);
348 TCGv t0
= tcg_temp_new();
349 gen_get_gpr(t0
, a
->rs1
);
351 gen_set_rm(ctx
, a
->rm
);
352 gen_helper_fcvt_s_wu(cpu_fpr
[a
->rd
], cpu_env
, t0
);
360 static bool trans_fmv_w_x(DisasContext
*ctx
, arg_fmv_w_x
*a
)
362 /* NOTE: This was FMV.S.X in an earlier version of the ISA spec! */
364 REQUIRE_EXT(ctx
, RVF
);
366 TCGv t0
= tcg_temp_new();
367 gen_get_gpr(t0
, a
->rs1
);
369 #if defined(TARGET_RISCV64)
370 tcg_gen_mov_i64(cpu_fpr
[a
->rd
], t0
);
372 tcg_gen_extu_i32_i64(cpu_fpr
[a
->rd
], t0
);
381 #ifdef TARGET_RISCV64
382 static bool trans_fcvt_l_s(DisasContext
*ctx
, arg_fcvt_l_s
*a
)
385 REQUIRE_EXT(ctx
, RVF
);
387 TCGv t0
= tcg_temp_new();
388 gen_set_rm(ctx
, a
->rm
);
389 gen_helper_fcvt_l_s(t0
, cpu_env
, cpu_fpr
[a
->rs1
]);
390 gen_set_gpr(a
->rd
, t0
);
395 static bool trans_fcvt_lu_s(DisasContext
*ctx
, arg_fcvt_lu_s
*a
)
398 REQUIRE_EXT(ctx
, RVF
);
400 TCGv t0
= tcg_temp_new();
401 gen_set_rm(ctx
, a
->rm
);
402 gen_helper_fcvt_lu_s(t0
, cpu_env
, cpu_fpr
[a
->rs1
]);
403 gen_set_gpr(a
->rd
, t0
);
408 static bool trans_fcvt_s_l(DisasContext
*ctx
, arg_fcvt_s_l
*a
)
411 REQUIRE_EXT(ctx
, RVF
);
413 TCGv t0
= tcg_temp_new();
414 gen_get_gpr(t0
, a
->rs1
);
416 gen_set_rm(ctx
, a
->rm
);
417 gen_helper_fcvt_s_l(cpu_fpr
[a
->rd
], cpu_env
, t0
);
424 static bool trans_fcvt_s_lu(DisasContext
*ctx
, arg_fcvt_s_lu
*a
)
427 REQUIRE_EXT(ctx
, RVF
);
429 TCGv t0
= tcg_temp_new();
430 gen_get_gpr(t0
, a
->rs1
);
432 gen_set_rm(ctx
, a
->rm
);
433 gen_helper_fcvt_s_lu(cpu_fpr
[a
->rd
], cpu_env
, t0
);