aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2016-05-06 10:35:33 +0100
committerNick Clifton <nickc@redhat.com>2016-05-06 10:35:33 +0100
commitfd7ed446fbee07c70ebc7d1e92f1ece665d7fc64 (patch)
tree497fe5576d87e1593eb021acb990920ae9c75bfc
parent405b757bdf23ea6612e0943bca05297049291612 (diff)
downloadfsf-binutils-gdb-fd7ed446fbee07c70ebc7d1e92f1ece665d7fc64.zip
fsf-binutils-gdb-fd7ed446fbee07c70ebc7d1e92f1ece665d7fc64.tar.gz
fsf-binutils-gdb-fd7ed446fbee07c70ebc7d1e92f1ece665d7fc64.tar.bz2
Add support for FMLA (by element) to AArch64 sim.
* simulator.c (do_FMLA_by_element): New function. (do_vec_op2): Call it.
-rw-r--r--sim/aarch64/ChangeLog5
-rw-r--r--sim/aarch64/simulator.c74
2 files changed, 77 insertions, 2 deletions
diff --git a/sim/aarch64/ChangeLog b/sim/aarch64/ChangeLog
index f031596..90e501a 100644
--- a/sim/aarch64/ChangeLog
+++ b/sim/aarch64/ChangeLog
@@ -1,3 +1,8 @@
+2016-05-06 Nick Clifton <nickc@redhat.com>
+
+ * simulator.c (do_FMLA_by_element): New function.
+ (do_vec_op2): Call it.
+
2016-04-27 Nick Clifton <nickc@redhat.com>
* simulator.c: Add TRACE_DECODE statements to all emulation
diff --git a/sim/aarch64/simulator.c b/sim/aarch64/simulator.c
index 2441cce..88cb03d 100644
--- a/sim/aarch64/simulator.c
+++ b/sim/aarch64/simulator.c
@@ -6034,6 +6034,67 @@ do_vec_MUL_by_element (sim_cpu *cpu)
}
static void
+do_FMLA_by_element (sim_cpu *cpu)
+{
+ /* instr[31] = 0
+ instr[30] = half/full
+ instr[29,23] = 00 1111 1
+ instr[22] = size
+ instr[21] = L
+ instr[20,16] = m
+ instr[15,12] = 0001
+ instr[11] = H
+ instr[10] = 0
+ instr[9,5] = Vn
+ instr[4,0] = Vd */
+
+ unsigned full = INSTR (30, 30);
+ unsigned size = INSTR (22, 22);
+ unsigned L = INSTR (21, 21);
+ unsigned vm = INSTR (20, 16);
+ unsigned H = INSTR (11, 11);
+ unsigned vn = INSTR (9, 5);
+ unsigned vd = INSTR (4, 0);
+ unsigned e;
+
+ NYI_assert (29, 23, 0x1F);
+ NYI_assert (15, 12, 0x1);
+ NYI_assert (10, 10, 0);
+
+ TRACE_DECODE (cpu, "emulated at line %d", __LINE__);
+ if (size)
+ {
+ double element1, element2;
+
+ if (! full || L)
+ HALT_UNALLOC;
+
+ element2 = aarch64_get_vec_double (cpu, vm, H);
+
+ for (e = 0; e < 2; e++)
+ {
+ element1 = aarch64_get_vec_double (cpu, vn, e);
+ element1 *= element2;
+ element1 += aarch64_get_vec_double (cpu, vd, e);
+ aarch64_set_vec_double (cpu, vd, e, element1);
+ }
+ }
+ else
+ {
+ float element1;
+ float element2 = aarch64_get_vec_float (cpu, vm, (H << 1) | L);
+
+ for (e = 0; e < (full ? 4 : 2); e++)
+ {
+ element1 = aarch64_get_vec_float (cpu, vn, e);
+ element1 *= element2;
+ element1 += aarch64_get_vec_float (cpu, vd, e);
+ aarch64_set_vec_float (cpu, vd, e, element1);
+ }
+ }
+}
+
+static void
do_vec_op2 (sim_cpu *cpu)
{
/* instr[31] = 0
@@ -6051,9 +6112,18 @@ do_vec_op2 (sim_cpu *cpu)
{
switch (INSTR (15, 10))
{
+ case 0x04:
+ case 0x06:
+ do_FMLA_by_element (cpu);
+ return;
+
case 0x20:
- case 0x22: do_vec_MUL_by_element (cpu); return;
- default: HALT_NYI;
+ case 0x22:
+ do_vec_MUL_by_element (cpu);
+ return;
+
+ default:
+ HALT_NYI;
}
}
else