aboutsummaryrefslogtreecommitdiff
path: root/target/arm/translate-a64.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2018-05-15 14:58:43 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-05-15 14:58:43 +0100
commit564a0632504fad840491aa9a59453f4e64a316c4 (patch)
tree21a983526571d7c54e2aa192a741b882cd30533e /target/arm/translate-a64.c
parent8c738d430796edeae5e13d6daf0895c02c62bd54 (diff)
target/arm: Implement FCVT (scalar, integer) for fp16
Cc: qemu-stable@nongnu.org Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Tested-by: Alex Bennée <alex.bennee@linaro.org> Message-id: 20180512003217.9105-4-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/translate-a64.c')
-rw-r--r--target/arm/translate-a64.c96
1 files changed, 80 insertions, 16 deletions
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 11d8c07943..93fb15d185 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -5511,11 +5511,11 @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
bool itof, int rmode, int scale, int sf, int type)
{
bool is_signed = !(opcode & 1);
- bool is_double = type;
TCGv_ptr tcg_fpstatus;
- TCGv_i32 tcg_shift;
+ TCGv_i32 tcg_shift, tcg_single;
+ TCGv_i64 tcg_double;
- tcg_fpstatus = get_fpstatus_ptr(false);
+ tcg_fpstatus = get_fpstatus_ptr(type == 3);
tcg_shift = tcg_const_i32(64 - scale);
@@ -5533,8 +5533,9 @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
tcg_int = tcg_extend;
}
- if (is_double) {
- TCGv_i64 tcg_double = tcg_temp_new_i64();
+ switch (type) {
+ case 1: /* float64 */
+ tcg_double = tcg_temp_new_i64();
if (is_signed) {
gen_helper_vfp_sqtod(tcg_double, tcg_int,
tcg_shift, tcg_fpstatus);
@@ -5544,8 +5545,10 @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
}
write_fp_dreg(s, rd, tcg_double);
tcg_temp_free_i64(tcg_double);
- } else {
- TCGv_i32 tcg_single = tcg_temp_new_i32();
+ break;
+
+ case 0: /* float32 */
+ tcg_single = tcg_temp_new_i32();
if (is_signed) {
gen_helper_vfp_sqtos(tcg_single, tcg_int,
tcg_shift, tcg_fpstatus);
@@ -5555,6 +5558,23 @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
}
write_fp_sreg(s, rd, tcg_single);
tcg_temp_free_i32(tcg_single);
+ break;
+
+ case 3: /* float16 */
+ tcg_single = tcg_temp_new_i32();
+ if (is_signed) {
+ gen_helper_vfp_sqtoh(tcg_single, tcg_int,
+ tcg_shift, tcg_fpstatus);
+ } else {
+ gen_helper_vfp_uqtoh(tcg_single, tcg_int,
+ tcg_shift, tcg_fpstatus);
+ }
+ write_fp_sreg(s, rd, tcg_single);
+ tcg_temp_free_i32(tcg_single);
+ break;
+
+ default:
+ g_assert_not_reached();
}
} else {
TCGv_i64 tcg_int = cpu_reg(s, rd);
@@ -5571,8 +5591,9 @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
- if (is_double) {
- TCGv_i64 tcg_double = read_fp_dreg(s, rn);
+ switch (type) {
+ case 1: /* float64 */
+ tcg_double = read_fp_dreg(s, rn);
if (is_signed) {
if (!sf) {
gen_helper_vfp_tosld(tcg_int, tcg_double,
@@ -5590,9 +5611,14 @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
tcg_shift, tcg_fpstatus);
}
}
+ if (!sf) {
+ tcg_gen_ext32u_i64(tcg_int, tcg_int);
+ }
tcg_temp_free_i64(tcg_double);
- } else {
- TCGv_i32 tcg_single = read_fp_sreg(s, rn);
+ break;
+
+ case 0: /* float32 */
+ tcg_single = read_fp_sreg(s, rn);
if (sf) {
if (is_signed) {
gen_helper_vfp_tosqs(tcg_int, tcg_single,
@@ -5614,14 +5640,39 @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
tcg_temp_free_i32(tcg_dest);
}
tcg_temp_free_i32(tcg_single);
+ break;
+
+ case 3: /* float16 */
+ tcg_single = read_fp_sreg(s, rn);
+ if (sf) {
+ if (is_signed) {
+ gen_helper_vfp_tosqh(tcg_int, tcg_single,
+ tcg_shift, tcg_fpstatus);
+ } else {
+ gen_helper_vfp_touqh(tcg_int, tcg_single,
+ tcg_shift, tcg_fpstatus);
+ }
+ } else {
+ TCGv_i32 tcg_dest = tcg_temp_new_i32();
+ if (is_signed) {
+ gen_helper_vfp_toslh(tcg_dest, tcg_single,
+ tcg_shift, tcg_fpstatus);
+ } else {
+ gen_helper_vfp_toulh(tcg_dest, tcg_single,
+ tcg_shift, tcg_fpstatus);
+ }
+ tcg_gen_extu_i32_i64(tcg_int, tcg_dest);
+ tcg_temp_free_i32(tcg_dest);
+ }
+ tcg_temp_free_i32(tcg_single);
+ break;
+
+ default:
+ g_assert_not_reached();
}
gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
tcg_temp_free_i32(tcg_rmode);
-
- if (!sf) {
- tcg_gen_ext32u_i64(tcg_int, tcg_int);
- }
}
tcg_temp_free_ptr(tcg_fpstatus);
@@ -5791,7 +5842,20 @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
/* actual FP conversions */
bool itof = extract32(opcode, 1, 1);
- if (type > 1 || (rmode != 0 && opcode > 1)) {
+ if (rmode != 0 && opcode > 1) {
+ unallocated_encoding(s);
+ return;
+ }
+ switch (type) {
+ case 0: /* float32 */
+ case 1: /* float64 */
+ break;
+ case 3: /* float16 */
+ if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
+ break;
+ }
+ /* fallthru */
+ default:
unallocated_encoding(s);
return;
}