ARM: Add support for VFP vector mode.
authorGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:14 +0000 (12:58 -0500)
committerGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:14 +0000 (12:58 -0500)
src/arch/arm/insts/vfp.hh
src/arch/arm/isa/formats/fp.isa
src/arch/arm/isa/insts/fp.isa
src/arch/arm/miscregs.hh
src/arch/arm/predecoder.hh
src/arch/arm/types.hh

index 8cffb276e96bde0a25ad01f40b78a010a72837b5..77e104a13efbbe511e4791d58fd22872d9695ad1 100644 (file)
@@ -68,8 +68,73 @@ setVfpMicroFlags(VfpMicroMode mode, T &flags)
       case VfpNotAMicroop:
         break;
     }
+    if (mode == VfpMicroop || mode == VfpFirstMicroop) {
+        flags[StaticInst::IsDelayedCommit] = true;
+    }
 }
 
+class VfpMacroOp : public PredMacroOp
+{
+  public:
+    static bool
+    inScalarBank(IntRegIndex idx)
+    {
+        return (idx % 32) < 8;
+    }
+
+  protected:
+    bool wide;
+
+    VfpMacroOp(const char *mnem, ExtMachInst _machInst,
+            OpClass __opClass, bool _wide) :
+        PredMacroOp(mnem, _machInst, __opClass), wide(_wide)
+    {}
+
+    IntRegIndex
+    addStride(IntRegIndex idx, unsigned stride)
+    {
+        if (wide) {
+            stride *= 2;
+        }
+        unsigned offset = idx % 8;
+        idx = (IntRegIndex)(idx - offset);
+        offset += stride;
+        idx = (IntRegIndex)(idx + (offset % 8));
+        return idx;
+    }
+
+    void
+    nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2)
+    {
+        unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
+        assert(!inScalarBank(dest));
+        dest = addStride(dest, stride);
+        op1 = addStride(op1, stride);
+        if (!inScalarBank(op2)) {
+            op2 = addStride(op2, stride);
+        }
+    }
+
+    void
+    nextIdxs(IntRegIndex &dest, IntRegIndex &op1)
+    {
+        unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
+        assert(!inScalarBank(dest));
+        dest = addStride(dest, stride);
+        if (!inScalarBank(op1)) {
+            op1 = addStride(op1, stride);
+        }
+    }
+
+    void
+    nextIdxs(IntRegIndex &dest)
+    {
+        unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
+        assert(!inScalarBank(dest));
+        dest = addStride(dest, stride);
+    }
+};
+
 class VfpRegRegOp : public RegRegOp
 {
   protected:
index e92757096df0f0a5a72c33b5eb14e449c87338f7..d154128250f52dc0867f3bb765304510ed5a4ac0 100644 (file)
@@ -504,65 +504,83 @@ let {{
           case 0x0:
             if (bits(machInst, 6) == 0) {
                 if (single) {
-                    return new VmlaS(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VmlaS>(
+                            machInst, vd, vn, vm, false);
                 } else {
-                    return new VmlaD(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VmlaD>(
+                            machInst, vd, vn, vm, true);
                 }
             } else {
                 if (single) {
-                    return new VmlsS(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VmlsS>(
+                            machInst, vd, vn, vm, false);
                 } else {
-                    return new VmlsD(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VmlsD>(
+                            machInst, vd, vn, vm, true);
                 }
             }
           case 0x1:
             if (bits(machInst, 6) == 1) {
                 if (single) {
-                    return new VnmlaS(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VnmlaS>(
+                            machInst, vd, vn, vm, false);
                 } else {
-                    return new VnmlaD(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VnmlaD>(
+                            machInst, vd, vn, vm, true);
                 }
             } else {
                 if (single) {
-                    return new VnmlsS(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VnmlsS>(
+                            machInst, vd, vn, vm, false);
                 } else {
-                    return new VnmlsD(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VnmlsD>(
+                            machInst, vd, vn, vm, true);
                 }
             }
           case 0x2:
             if ((opc3 & 0x1) == 0) {
                 if (single) {
-                    return new VmulS(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VmulS>(
+                            machInst, vd, vn, vm, false);
                 } else {
-                    return new VmulD(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VmulD>(
+                            machInst, vd, vn, vm, true);
                 }
             } else {
                 if (single) {
-                    return new VnmulS(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VnmulS>(
+                            machInst, vd, vn, vm, false);
                 } else {
-                    return new VnmulD(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VnmulD>(
+                            machInst, vd, vn, vm, true);
                 }
             }
           case 0x3:
             if ((opc3 & 0x1) == 0) {
                 if (single) {
-                    return new VaddS(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VaddS>(
+                            machInst, vd, vn, vm, false);
                 } else {
-                    return new VaddD(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VaddD>(
+                            machInst, vd, vn, vm, true);
                 }
             } else {
                 if (single) {
-                    return new VsubS(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VsubS>(
+                            machInst, vd, vn, vm, false);
                 } else {
-                    return new VsubD(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VsubD>(
+                            machInst, vd, vn, vm, true);
                 }
             }
           case 0x8:
             if ((opc3 & 0x1) == 0) {
                 if (single) {
-                    return new VdivS(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VdivS>(
+                            machInst, vd, vn, vm, false);
                 } else {
-                    return new VdivD(machInst, vd, vn, vm);
+                    return decodeVfpRegRegRegOp<VdivD>(
+                            machInst, vd, vn, vm, true);
                 }
             }
             break;
@@ -572,39 +590,49 @@ let {{
                     bits(machInst, 3, 0) | (bits(machInst, 19, 16) << 4);
                 if (single) {
                     uint32_t imm = vfp_modified_imm(baseImm, false);
-                    return new VmovImmS(machInst, vd, imm);
+                    return decodeVfpRegImmOp<VmovImmS>(
+                            machInst, vd, imm, false);
                 } else {
                     uint64_t imm = vfp_modified_imm(baseImm, true);
-                    return new VmovImmD(machInst, vd, imm);
+                    return decodeVfpRegImmOp<VmovImmD>(
+                            machInst, vd, imm, true);
                 }
             }
             switch (opc2) {
               case 0x0:
                 if (opc3 == 1) {
                     if (single) {
-                        return new VmovRegS(machInst, vd, vm);
+                        return decodeVfpRegRegOp<VmovRegS>(
+                                machInst, vd, vm, false);
                     } else {
-                        return new VmovRegD(machInst, vd, vm);
+                        return decodeVfpRegRegOp<VmovRegD>(
+                                machInst, vd, vm, true);
                     }
                 } else {
                     if (single) {
-                        return new VabsS(machInst, vd, vm);
+                        return decodeVfpRegRegOp<VabsS>(
+                                machInst, vd, vm, false);
                     } else {
-                        return new VabsD(machInst, vd, vm);
+                        return decodeVfpRegRegOp<VabsD>(
+                                machInst, vd, vm, true);
                     }
                 }
               case 0x1:
                 if (opc3 == 1) {
                     if (single) {
-                        return new VnegS(machInst, vd, vm);
+                        return decodeVfpRegRegOp<VnegS>(
+                                machInst, vd, vm, false);
                     } else {
-                        return new VnegD(machInst, vd, vm);
+                        return decodeVfpRegRegOp<VnegD>(
+                                machInst, vd, vm, true);
                     }
                 } else {
                     if (single) {
-                        return new VsqrtS(machInst, vd, vm);
+                        return decodeVfpRegRegOp<VsqrtS>(
+                                machInst, vd, vm, false);
                     } else {
-                        return new VsqrtD(machInst, vd, vm);
+                        return decodeVfpRegRegOp<VsqrtD>(
+                                machInst, vd, vm, true);
                     }
                 }
               case 0x2:
index 1402da61a10addd644908659d8fc2ade9d3d878d..e2c7dd79b4d1af26ba6be8fac8882f58a88f1730 100644 (file)
 //
 // Authors: Gabe Black
 
+output header {{
+
+template <class Micro>
+class VfpMacroRegRegOp : public VfpMacroOp
+{
+  public:
+    VfpMacroRegRegOp(ExtMachInst _machInst, IntRegIndex _dest,
+                     IntRegIndex _op1, bool _wide) :
+        VfpMacroOp("VfpMacroRegRegOp", _machInst, No_OpClass, _wide)
+    {
+        numMicroops = machInst.fpscrLen + 1;
+        assert(numMicroops > 1);
+        microOps = new StaticInstPtr[numMicroops];
+        for (unsigned i = 0; i < numMicroops; i++) {
+            VfpMicroMode mode = VfpMicroop;
+            if (i == 0)
+                mode = VfpFirstMicroop;
+            else if (i == numMicroops - 1)
+                mode = VfpLastMicroop;
+            microOps[i] = new Micro(_machInst, _dest, _op1, mode);
+            nextIdxs(_dest, _op1);
+        }
+    }
+
+    %(BasicExecPanic)s
+};
+
+template <class VfpOp>
+static StaticInstPtr
+decodeVfpRegRegOp(ExtMachInst machInst,
+        IntRegIndex dest, IntRegIndex op1, bool wide)
+{
+    if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) {
+        return new VfpOp(machInst, dest, op1);
+    } else {
+        return new VfpMacroRegRegOp<VfpOp>(machInst, dest, op1, wide);
+    }
+}
+
+template <class Micro>
+class VfpMacroRegImmOp : public VfpMacroOp
+{
+  public:
+    VfpMacroRegImmOp(ExtMachInst _machInst, IntRegIndex _dest, uint64_t _imm,
+                     bool _wide) :
+        VfpMacroOp("VfpMacroRegImmOp", _machInst, No_OpClass, _wide)
+    {
+        numMicroops = machInst.fpscrLen + 1;
+        microOps = new StaticInstPtr[numMicroops];
+        for (unsigned i = 0; i < numMicroops; i++) {
+            VfpMicroMode mode = VfpMicroop;
+            if (i == 0)
+                mode = VfpFirstMicroop;
+            else if (i == numMicroops - 1)
+                mode = VfpLastMicroop;
+            microOps[i] = new Micro(_machInst, _dest, _imm, mode);
+            nextIdxs(_dest);
+        }
+    }
+
+    %(BasicExecPanic)s
+};
+
+template <class VfpOp>
+static StaticInstPtr
+decodeVfpRegImmOp(ExtMachInst machInst,
+        IntRegIndex dest, uint64_t imm, bool wide)
+{
+    if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) {
+        return new VfpOp(machInst, dest, imm);
+    } else {
+        return new VfpMacroRegImmOp<VfpOp>(machInst, dest, imm, wide);
+    }
+}
+
+template <class Micro>
+class VfpMacroRegRegImmOp : public VfpMacroOp
+{
+  public:
+    VfpMacroRegRegImmOp(ExtMachInst _machInst, IntRegIndex _dest,
+                        IntRegIndex _op1, uint64_t _imm, bool _wide) :
+        VfpMacroOp("VfpMacroRegRegImmOp", _machInst, No_OpClass, _wide)
+    {
+        numMicroops = machInst.fpscrLen + 1;
+        microOps = new StaticInstPtr[numMicroops];
+        for (unsigned i = 0; i < numMicroops; i++) {
+            VfpMicroMode mode = VfpMicroop;
+            if (i == 0)
+                mode = VfpFirstMicroop;
+            else if (i == numMicroops - 1)
+                mode = VfpLastMicroop;
+            microOps[i] = new Micro(_machInst, _dest, _op1, _imm, mode);
+            nextIdxs(_dest, _op1);
+        }
+    }
+
+    %(BasicExecPanic)s
+};
+
+template <class VfpOp>
+static StaticInstPtr
+decodeVfpRegRegImmOp(ExtMachInst machInst, IntRegIndex dest,
+                     IntRegIndex op1, uint64_t imm, bool wide)
+{
+    if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) {
+        return new VfpOp(machInst, dest, op1, imm);
+    } else {
+        return new VfpMacroRegRegImmOp<VfpOp>(machInst, dest, op1, imm, wide);
+    }
+}
+
+template <class Micro>
+class VfpMacroRegRegRegOp : public VfpMacroOp
+{
+  public:
+    VfpMacroRegRegRegOp(ExtMachInst _machInst, IntRegIndex _dest,
+                        IntRegIndex _op1, IntRegIndex _op2, bool _wide) :
+        VfpMacroOp("VfpMacroRegRegRegOp", _machInst, No_OpClass, _wide)
+    {
+        numMicroops = machInst.fpscrLen + 1;
+        microOps = new StaticInstPtr[numMicroops];
+        for (unsigned i = 0; i < numMicroops; i++) {
+            VfpMicroMode mode = VfpMicroop;
+            if (i == 0)
+                mode = VfpFirstMicroop;
+            else if (i == numMicroops - 1)
+                mode = VfpLastMicroop;
+            microOps[i] = new Micro(_machInst, _dest, _op1, _op2, mode);
+            nextIdxs(_dest, _op1, _op2);
+        }
+    }
+
+    %(BasicExecPanic)s
+};
+
+template <class VfpOp>
+static StaticInstPtr
+decodeVfpRegRegRegOp(ExtMachInst machInst, IntRegIndex dest,
+                     IntRegIndex op1, IntRegIndex op2, bool wide)
+{
+    if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) {
+        return new VfpOp(machInst, dest, op1, op2);
+    } else {
+        return new VfpMacroRegRegRegOp<VfpOp>(machInst, dest, op1, op2, wide);
+    }
+}
+}};
+
 let {{
 
     header_output = ""
index 9c781f5151dec8b0cfd4425aa64385231108e90a..b7521cbd0f736a1406392d9dc5cd43d6c861e050 100644 (file)
@@ -294,6 +294,32 @@ namespace ArmISA
         Bitfield<11> wnr;
         Bitfield<12> ext;
     EndBitUnion(FSR)
+
+    BitUnion32(FPSCR)
+        Bitfield<0> ioc;
+        Bitfield<1> dzc;
+        Bitfield<2> ofc;
+        Bitfield<3> ufc;
+        Bitfield<4> ixc;
+        Bitfield<7> idc;
+        Bitfield<8> ioe;
+        Bitfield<9> dze;
+        Bitfield<10> ofe;
+        Bitfield<11> ufe;
+        Bitfield<12> ixe;
+        Bitfield<15> ide;
+        Bitfield<18, 16> len;
+        Bitfield<21, 20> stride;
+        Bitfield<23, 22> rMode;
+        Bitfield<24> fz;
+        Bitfield<25> dn;
+        Bitfield<26> ahp;
+        Bitfield<27> qc;
+        Bitfield<28> v;
+        Bitfield<29> c;
+        Bitfield<30> z;
+        Bitfield<31> n;
+    EndBitUnion(FPSCR)
 };
 
 #endif // __ARCH_ARM_MISCREGS_HH__
index 5aba16a6f5956b2da9473af28a79470ac22f9b6b..a7519975568ce537f971396d00ca62a43965d47d 100644 (file)
@@ -142,6 +142,9 @@ namespace ArmISA
             data = inst;
             offset = (fetchPC >= pc) ? 0 : pc - fetchPC;
             emi.thumb = (pc & (ULL(1) << PcTBitShift)) ? 1 : 0;
+            FPSCR fpscr = tc->readMiscReg(MISCREG_FPSCR);
+            emi.fpscrLen = fpscr.len;
+            emi.fpscrStride = fpscr.stride;
             process();
         }
 
index 2fe4f4aa76411e19986ea2e7cd5979240c9672be..95e5a18a0ef1c239b156445b5e03d24631ce999a 100644 (file)
@@ -51,6 +51,10 @@ namespace ArmISA
     typedef uint32_t MachInst;
 
     BitUnion64(ExtMachInst)
+        // FPSCR fields
+        Bitfield<41, 40> fpscrStride;
+        Bitfield<39, 37> fpscrLen;
+
         // Bitfields to select mode.
         Bitfield<36>     thumb;
         Bitfield<35>     bigThumb;