[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 50/60] AArch64: Add "Floating-point<->fixed-point
From: |
Alexander Graf |
Subject: |
[Qemu-devel] [PATCH 50/60] AArch64: Add "Floating-point<->fixed-point |
Date: |
Fri, 27 Sep 2013 02:48:44 +0200 |
This patch adds emulation for the instruction group labeled
"Floating-point <-> fixed-point conversions" in the ARM ARM.
Namely this includes the instructions SCVTF, UCVTF, FCVTZS, FCVTZU
(scalar, fixed-point).
Signed-off-by: Alexander Graf <address@hidden>
---
target-arm/helper-a64.c | 22 ++++++
target-arm/helper-a64.h | 1 +
target-arm/translate-a64.c | 173 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 196 insertions(+)
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index a46b00e..0b7aee1 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -275,3 +275,25 @@ uint64_t HELPER(smulh)(uint64_t n, uint64_t m)
muls64(&rl, &rh, n, m);
return rh;
}
+
+void HELPER(set_rmode)(uint32_t rmode, void *fp_status)
+{
+ switch (rmode) {
+ case ROUND_MODE_TIEEVEN:
+ default:
+ rmode = float_round_nearest_even;
+ break;
+ case ROUND_MODE_UP:
+ rmode = float_round_up;
+ break;
+ case ROUND_MODE_DOWN:
+ rmode = float_round_down;
+ break;
+ case ROUND_MODE_ZERO:
+ rmode = float_round_to_zero;
+ break;
+ /* XXX add fpcr rounding (exact and not exact) */
+ }
+
+ set_float_rounding_mode(rmode, fp_status);
+}
diff --git a/target-arm/helper-a64.h b/target-arm/helper-a64.h
index 41dedd7..f42edf8 100644
--- a/target-arm/helper-a64.h
+++ b/target-arm/helper-a64.h
@@ -30,3 +30,4 @@ DEF_HELPER_FLAGS_1(rbit64, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_FLAGS_1(clz64, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_FLAGS_2(umulh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(smulh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_2(set_rmode, void, i32, ptr)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 5985c01..654e011 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -183,6 +183,17 @@ static void clear_fpreg(int dest)
tcg_gen_st_i64(tcg_zero, cpu_env, freg_offs + sizeof(float64));
}
+static TCGv_ptr get_fpstatus_ptr(void)
+{
+ TCGv_ptr statusptr = tcg_temp_new_ptr();
+ int offset;
+
+ offset = offsetof(CPUARMState, vfp.standard_fp_status);
+ tcg_gen_addi_ptr(statusptr, cpu_env, offset);
+
+ return statusptr;
+}
+
static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
{
TranslationBlock *tb;
@@ -1718,6 +1729,161 @@ static void handle_dp3s(DisasContext *s, uint32_t insn)
tcg_temp_free_i64(tcg_tmp);
}
+static void handle_fpfpcvt(DisasContext *s, uint32_t insn, bool direction,
+ int rmode)
+{
+ int rd = get_reg(insn);
+ int rn = get_bits(insn, 5, 5);
+ int scale = get_bits(insn, 10, 6);
+ int opcode = get_bits(insn, 16, 3);
+ int type = get_bits(insn, 22, 2);
+ bool is_32bit = !get_bits(insn, 31, 1);
+ bool is_double = get_bits(type, 0, 1);
+ bool is_signed = !get_bits(opcode, 0, 1);
+ int freg_offs;
+ int fp_reg;
+ TCGv_i64 tcg_int;
+ TCGv_i64 tcg_single;
+ TCGv_i64 tcg_double;
+ TCGv_i64 tcg_fpstatus = get_fpstatus_ptr();
+ TCGv_i32 tcg_shift = tcg_const_i32(scale);
+ TCGv_i32 tcg_rmode = tcg_const_i32(rmode);
+ TCGv_i64 tcg_tmp;
+
+ if (direction) {
+ fp_reg = rn;
+ tcg_int = cpu_reg(rd);
+ } else {
+ fp_reg = rd;
+ tcg_int = cpu_reg(rn);
+ }
+ freg_offs = offsetof(CPUARMState, vfp.regs[fp_reg * 2]);
+
+ if (!direction) {
+ clear_fpreg(fp_reg);
+ }
+
+ if (is_32bit && !direction) {
+ tcg_tmp = tcg_temp_new_i64();
+ if (is_signed) {
+ tcg_gen_ext32s_i64(tcg_tmp, tcg_int);
+ } else {
+ tcg_gen_ext32u_i64(tcg_tmp, tcg_int);
+ }
+ tcg_int = tcg_tmp;
+ }
+
+ gen_helper_set_rmode(tcg_rmode, tcg_fpstatus);
+
+ switch ((direction ? 0x10 : 0)|
+ (is_double ? 0x1 : 0) |
+ (is_signed ? 0x2 : 0)) {
+ case 0x0: /* unsigned scalar->single */
+ tcg_single = tcg_temp_new_i32();
+ tcg_tmp = tcg_temp_new_i64();
+ gen_helper_vfp_uqtos(tcg_single, tcg_int, tcg_shift, tcg_fpstatus);
+ tcg_gen_extu_i32_i64(tcg_tmp, tcg_single);
+ tcg_gen_st32_i64(tcg_tmp, cpu_env, freg_offs);
+ tcg_temp_free_i32(tcg_single);
+ tcg_temp_free_i64(tcg_tmp);
+ break;
+ case 0x1: /* unsigned scalar->double */
+ tcg_double = tcg_temp_new_i64();
+ gen_helper_vfp_uqtod(tcg_double, tcg_int, tcg_shift, tcg_fpstatus);
+ tcg_gen_st_i64(tcg_double, cpu_env, freg_offs);
+ tcg_temp_free_i64(tcg_double);
+ break;
+ case 0x2: /* signed scalar->single */
+ tcg_single = tcg_temp_new_i32();
+ tcg_tmp = tcg_temp_new_i64();
+ gen_helper_vfp_sqtos(tcg_single, tcg_int, tcg_shift, tcg_fpstatus);
+ tcg_gen_extu_i32_i64(tcg_tmp, tcg_single);
+ tcg_gen_st32_i64(tcg_tmp, cpu_env, freg_offs);
+ tcg_temp_free_i32(tcg_single);
+ tcg_temp_free_i64(tcg_tmp);
+ break;
+ case 0x3: /* signed scalar->double */
+ tcg_double = tcg_temp_new_i64();
+ gen_helper_vfp_sqtod(tcg_double, tcg_int, tcg_shift, tcg_fpstatus);
+ tcg_gen_st_i64(tcg_double, cpu_env, freg_offs);
+ tcg_temp_free_i64(tcg_double);
+ break;
+ case 0x10: /* unsigned single->scalar */
+ tcg_single = tcg_temp_new_i32();
+ tcg_tmp = tcg_temp_new_i64();
+ tcg_gen_ld32u_i64(tcg_tmp, cpu_env, freg_offs);
+ tcg_gen_trunc_i64_i32(tcg_single, tcg_tmp);
+ gen_helper_vfp_touqs(tcg_int, tcg_single, tcg_shift, tcg_fpstatus);
+ tcg_temp_free_i32(tcg_single);
+ tcg_temp_free_i64(tcg_tmp);
+ break;
+ case 0x11: /* unsigned single->double */
+ tcg_double = tcg_temp_new_i64();
+ tcg_gen_ld_i64(tcg_double, cpu_env, freg_offs);
+ gen_helper_vfp_touqd(tcg_int, tcg_double, tcg_shift, tcg_fpstatus);
+ tcg_temp_free_i64(tcg_double);
+ break;
+ case 0x12: /* signed single->scalar */
+ tcg_single = tcg_temp_new_i32();
+ tcg_tmp = tcg_temp_new_i64();
+ tcg_gen_ld32u_i64(tcg_tmp, cpu_env, freg_offs);
+ tcg_gen_trunc_i64_i32(tcg_single, tcg_tmp);
+ gen_helper_vfp_tosqs(tcg_int, tcg_single, tcg_shift, tcg_fpstatus);
+ tcg_temp_free_i32(tcg_single);
+ tcg_temp_free_i64(tcg_tmp);
+ break;
+ case 0x13: /* signed single->double */
+ tcg_double = tcg_temp_new_i64();
+ tcg_gen_ld_i64(tcg_double, cpu_env, freg_offs);
+ gen_helper_vfp_tosqd(tcg_int, tcg_double, tcg_shift, tcg_fpstatus);
+ tcg_temp_free_i64(tcg_double);
+ break;
+ default:
+ unallocated_encoding(s);
+ }
+
+ /* XXX use fpcr */
+ tcg_gen_movi_i32(tcg_rmode, -1);
+ gen_helper_set_rmode(tcg_rmode, tcg_fpstatus);
+
+ if (is_32bit && direction) {
+ tcg_gen_ext32u_i64(tcg_int, tcg_int);
+ }
+
+ tcg_temp_free_i64(tcg_fpstatus);
+ tcg_temp_free_i32(tcg_shift);
+ tcg_temp_free_i32(tcg_rmode);
+}
+
+/* fixed <-> floating conversion */
+static void handle_fpfpconv(DisasContext *s, uint32_t insn)
+{
+ int opcode = get_bits(insn, 16, 3);
+ int rmode = get_bits(insn, 20, 2);
+ int type = get_bits(insn, 22, 2);
+ bool is_s = get_bits(insn, 29, 1);
+ bool direction;
+
+ if (is_s || (type > 1) || (opcode > 1)) {
+ unallocated_encoding(s);
+ return;
+ }
+
+ switch (rmode) {
+ case 0x1: /* [S|U]CVTF (scalar->float) */
+ direction = 0;
+ break;
+ case 0x3: /* FCVTZ[S|U] (float->scalar) */
+ direction = 1;
+ break;
+ default:
+ unallocated_encoding(s);
+ return;
+ }
+
+ handle_fpfpcvt(s, insn, direction, ROUND_MODE_ZERO);
+}
+
/* SIMD ORR */
static void handle_simdorr(DisasContext *s, uint32_t insn)
{
@@ -2297,6 +2463,13 @@ void disas_a64_insn(CPUARMState *env, DisasContext *s)
case 0x1b:
handle_dp3s(s, insn);
break;
+ case 0x1e:
+ if (!get_bits(insn, 21, 1) && !get_bits(insn, 30, 1)) {
+ handle_fpfpconv(s, insn);
+ } else {
+ unallocated_encoding(s);
+ }
+ break;
default:
unallocated_encoding(s);
break;
--
1.7.12.4
- [Qemu-devel] [PATCH 48/60] AArch64: Add 0x1a encoding of add instructions, (continued)
- [Qemu-devel] [PATCH 48/60] AArch64: Add 0x1a encoding of add instructions, Alexander Graf, 2013/09/26
- [Qemu-devel] [PATCH 44/60] AArch64: Add division instruction family emulation, Alexander Graf, 2013/09/26
- [Qemu-devel] [PATCH 41/60] AArch64: Add ldr/str instruction family emulation, Alexander Graf, 2013/09/26
- [Qemu-devel] [PATCH 49/60] AArch64: Add "Data-processing (3 source)" instruction, Alexander Graf, 2013/09/26
- [Qemu-devel] [PATCH 51/60] AArch64: Add fmov (scalar, immediate) instruction, Alexander Graf, 2013/09/26
- [Qemu-devel] [PATCH 56/60] AArch64: Add "Floating-point data-processing (2, Alexander Graf, 2013/09/26
- [Qemu-devel] [PATCH 58/60] AArch64: Add "ADD (vector)" instruction emulation, Alexander Graf, 2013/09/26
- [Qemu-devel] [PATCH 57/60] AArch64: Add "Floating-point data-processing (2, Alexander Graf, 2013/09/26
- [Qemu-devel] [PATCH 42/60] AArch64: Add literal ld instruction emulation, Alexander Graf, 2013/09/26
- [Qemu-devel] [PATCH 50/60] AArch64: Add "Floating-point<->fixed-point,
Alexander Graf <=
- [Qemu-devel] [PATCH 52/60] AArch64: Add "Floating-point<->integer conversions", Alexander Graf, 2013/09/26
- [Qemu-devel] [PATCH 59/60] AArch64: Add "Floating-point data-processing (3, Alexander Graf, 2013/09/26
- [Qemu-devel] [PATCH 53/60] AArch64: Add "Floating-point compare" instruction, Alexander Graf, 2013/09/26
- [Qemu-devel] [PATCH 54/60] AArch64: Add "Floating-point data-processing (1, Alexander Graf, 2013/09/26
- [Qemu-devel] [PATCH 60/60] AArch64: Add "Floating-point data-processing (3, Alexander Graf, 2013/09/26
- [Qemu-devel] [PATCH 55/60] AArch64: Add "Floating-point data-processing (1, Alexander Graf, 2013/09/26
- Re: [Qemu-devel] [PATCH 00/60] AArch64 TCG emulation support, Alexander Graf, 2013/09/26