sim/aarch64/ * cpustate.c: Include math.h. (aarch64_set_FP_float): Use signbit to check for signed zero. (aarch64_set_FP_double): Likewise. * simulator.c (dexSimpleFPCondSelect): Call aarch64_get_FP_double or aarch64_get_FP_float to get source register contents. sim/testsuite/sim/aarch64/ * fcsel.s: New. diff --git a/sim/aarch64/cpustate.c b/sim/aarch64/cpustate.c index 648221f..4b201a7 100644 --- a/sim/aarch64/cpustate.c +++ b/sim/aarch64/cpustate.c @@ -20,6 +20,7 @@ along with this program. If not, see . */ #include +#include #include "sim-main.h" #include "cpustate.h" @@ -369,7 +370,9 @@ aarch64_set_FP_half (sim_cpu *cpu, VReg reg, float val) void aarch64_set_FP_float (sim_cpu *cpu, VReg reg, float val) { - if (val != cpu->fr[reg].s) + if (val != cpu->fr[reg].s + /* Handle +/- zero. */ + || signbit (val) != signbit (cpu->fr[reg].s)) { FRegister v; @@ -385,7 +388,9 @@ aarch64_set_FP_float (sim_cpu *cpu, VReg reg, float val) void aarch64_set_FP_double (sim_cpu *cpu, VReg reg, double val) { - if (val != cpu->fr[reg].d) + if (val != cpu->fr[reg].d + /* Handle +/- zero. */ + || signbit (val) != signbit (cpu->fr[reg].d)) { FRegister v; diff --git a/sim/aarch64/simulator.c b/sim/aarch64/simulator.c index be3d6c7..3f56177 100644 --- a/sim/aarch64/simulator.c +++ b/sim/aarch64/simulator.c @@ -7463,9 +7463,11 @@ dexSimpleFPCondSelect (sim_cpu *cpu) TRACE_DECODE (cpu, "emulated at line %d", __LINE__); if (INSTR (22, 22)) - aarch64_set_FP_double (cpu, sd, set ? sn : sm); + aarch64_set_FP_double (cpu, sd, (set ? aarch64_get_FP_double (cpu, sn) + : aarch64_get_FP_double (cpu, sm))); else - aarch64_set_FP_float (cpu, sd, set ? sn : sm); + aarch64_set_FP_float (cpu, sd, (set ? aarch64_get_FP_float (cpu, sn) + : aarch64_get_FP_float (cpu, sm))); } /* Store 32 bit unscaled signed 9 bit. */ diff --git a/sim/testsuite/sim/aarch64/fcsel.s b/sim/testsuite/sim/aarch64/fcsel.s new file mode 100644 index 0000000..5b8443c --- /dev/null +++ b/sim/testsuite/sim/aarch64/fcsel.s @@ -0,0 +1,53 @@ +# mach: aarch64 + +# Check the FP Conditional Select instruction: fcsel. +# Check 1/1 eq/neg, and 1/2 lt/gt. + +.include "testutils.inc" + + start + fmov s0, #1.0 + fmov s1, #1.0 + fmov s2, #-1.0 + fcmp s0, s1 + fcsel s3, s0, s2, eq + fcmp s3, s0 + bne .Lfailure + fcsel s3, s0, s2, ne + fcmp s3, s2 + bne .Lfailure + + fmov s0, #1.0 + fmov s1, #2.0 + fcmp s0, s1 + fcsel s3, s0, s2, lt + fcmp s3, s0 + bne .Lfailure + fcsel s3, s0, s2, gt + fcmp s3, s2 + bne .Lfailure + + fmov d0, #1.0 + fmov d1, #1.0 + fmov d2, #-1.0 + fcmp d0, d1 + fcsel d3, d0, d2, eq + fcmp d3, d0 + bne .Lfailure + fcsel d3, d0, d2, ne + fcmp d3, d2 + bne .Lfailure + + fmov d0, #1.0 + fmov d1, #2.0 + fcmp d0, d1 + fcsel d3, d0, d2, lt + fcmp d3, d0 + bne .Lfailure + fcsel d3, d0, d2, gt + fcmp d3, d2 + bne .Lfailure + + pass +.Lfailure: + fail