Add support for FMLA (by element) to AArch64 sim.
authorNick Clifton <nickc@redhat.com>
Fri, 6 May 2016 09:35:33 +0000 (10:35 +0100)
committerNick Clifton <nickc@redhat.com>
Fri, 6 May 2016 09:35:33 +0000 (10:35 +0100)
* simulator.c (do_FMLA_by_element): New function.
(do_vec_op2): Call it.

sim/aarch64/ChangeLog
sim/aarch64/simulator.c

index f031596b7d04a659ee6628d7ac34e57e521904da..90e501a00a43f2b9b5cbe6f3c2542cea166bf40d 100644 (file)
@@ -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
index 2441ccebbe84b08c1256c23a907826674fd9946a..88cb03d79a5848b528aa0221721d75691f84a557 100644 (file)
@@ -6033,6 +6033,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)
 {
@@ -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