ARM: Implement the saturation instructions.
authorGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:06 +0000 (12:58 -0500)
committerGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:06 +0000 (12:58 -0500)
src/arch/arm/insts/static_inst.hh
src/arch/arm/isa/insts/misc.isa

index 3ff1d20cd42a3808b1021d14a349ce883d91419c..2c83ee79c7d47a47a572ed391da2a79b54d96a87 100644 (file)
@@ -67,9 +67,9 @@ class ArmStaticInst : public StaticInst
         int64_t midRes = sub ? (op1 - op2) : (op1 + op2);
         if (bits(midRes, width) != bits(midRes, width - 1)) {
             if (midRes > 0)
-                res = (1LL << (width - 1)) - 1;
+                res = (LL(1) << (width - 1)) - 1;
             else
-                res = -(1LL << (width - 1));
+                res = -(LL(1) << (width - 1));
             return true;
         } else {
             res = midRes;
@@ -77,13 +77,29 @@ class ArmStaticInst : public StaticInst
         }
     }
 
+    static bool
+    satInt(int32_t &res, int64_t op, int width)
+    {
+        width--;
+        if (op >= (LL(1) << width)) {
+            res = (LL(1) << width) - 1;
+            return true;
+        } else if (op < -(LL(1) << width)) {
+            res = -(LL(1) << width);
+            return true;
+        } else {
+            res = op;
+            return false;
+        }
+    }
+
     template<int width>
     static bool
     uSaturateOp(uint32_t &res, int64_t op1, int64_t op2, bool sub=false)
     {
         int64_t midRes = sub ? (op1 - op2) : (op1 + op2);
-        if (midRes >= (1 << width)) {
-            res = (1 << width) - 1;
+        if (midRes >= (LL(1) << width)) {
+            res = (LL(1) << width) - 1;
             return true;
         } else if (midRes < 0) {
             res = 0;
@@ -94,6 +110,21 @@ class ArmStaticInst : public StaticInst
         }
     }
 
+    static bool
+    uSatInt(int32_t &res, int64_t op, int width)
+    {
+        if (op >= (LL(1) << width)) {
+            res = (LL(1) << width) - 1;
+            return true;
+        } else if (op < 0) {
+            res = 0;
+            return true;
+        } else {
+            res = op;
+            return false;
+        }
+    }
+
     // Constructor
     ArmStaticInst(const char *mnem, ExtMachInst _machInst,
                   OpClass __opClass)
index 3195bea65c018a91f713501c802f9078891c1136..db0bfac18c465c1f65f969d8c8285409eb11f21a 100644 (file)
@@ -153,4 +153,78 @@ let {{
     header_output += RevOpDeclare.subst(revshIop)
     decoder_output += RevOpConstructor.subst(revshIop)
     exec_output += PredOpExecute.subst(revshIop)
+
+    ssatCode = '''
+        int32_t operand = shift_rm_imm(Op1, shiftAmt, shiftType, 0);
+        int32_t res;
+        if (satInt(res, operand, satImm))
+            CondCodes = CondCodes | (1 << 27);
+        else
+            CondCodes = CondCodes;
+        Dest = res;
+    '''
+    ssatIop = InstObjParams("ssat", "Ssat", "SatShiftOp",
+                            { "code": ssatCode,
+                              "predicate_test": predicateTest }, [])
+    header_output += SatShiftOpDeclare.subst(ssatIop)
+    decoder_output += SatShiftOpConstructor.subst(ssatIop)
+    exec_output += PredOpExecute.subst(ssatIop)
+
+    usatCode = '''
+        int32_t operand = shift_rm_imm(Op1, shiftAmt, shiftType, 0);
+        int32_t res;
+        if (uSatInt(res, operand, satImm))
+            CondCodes = CondCodes | (1 << 27);
+        else
+            CondCodes = CondCodes;
+        Dest = res;
+    '''
+    usatIop = InstObjParams("usat", "Usat", "SatShiftOp",
+                            { "code": usatCode,
+                              "predicate_test": predicateTest }, [])
+    header_output += SatShiftOpDeclare.subst(usatIop)
+    decoder_output += SatShiftOpConstructor.subst(usatIop)
+    exec_output += PredOpExecute.subst(usatIop)
+
+    ssat16Code = '''
+        int32_t res;
+        uint32_t resTemp = 0;
+        CondCodes = CondCodes;
+        int32_t argLow = sext<16>(bits(Op1, 15, 0));
+        int32_t argHigh = sext<16>(bits(Op1, 31, 16));
+        if (satInt(res, argLow, satImm))
+            CondCodes = CondCodes | (1 << 27);
+        replaceBits(resTemp, 15, 0, res);
+        if (satInt(res, argHigh, satImm))
+            CondCodes = CondCodes | (1 << 27);
+        replaceBits(resTemp, 31, 16, res);
+        Dest = resTemp;
+    '''
+    ssat16Iop = InstObjParams("ssat16", "Ssat16", "SatOp",
+                              { "code": ssat16Code,
+                                "predicate_test": predicateTest }, [])
+    header_output += SatOpDeclare.subst(ssat16Iop)
+    decoder_output += SatOpConstructor.subst(ssat16Iop)
+    exec_output += PredOpExecute.subst(ssat16Iop)
+
+    usat16Code = '''
+        int32_t res;
+        uint32_t resTemp = 0;
+        CondCodes = CondCodes;
+        int32_t argLow = sext<16>(bits(Op1, 15, 0));
+        int32_t argHigh = sext<16>(bits(Op1, 31, 16));
+        if (uSatInt(res, argLow, satImm))
+            CondCodes = CondCodes | (1 << 27);
+        replaceBits(resTemp, 15, 0, res);
+        if (uSatInt(res, argHigh, satImm))
+            CondCodes = CondCodes | (1 << 27);
+        replaceBits(resTemp, 31, 16, res);
+        Dest = resTemp;
+    '''
+    usat16Iop = InstObjParams("usat16", "Usat16", "SatOp",
+                              { "code": usat16Code,
+                                "predicate_test": predicateTest }, [])
+    header_output += SatOpDeclare.subst(usat16Iop)
+    decoder_output += SatOpConstructor.subst(usat16Iop)
+    exec_output += PredOpExecute.subst(usat16Iop)
 }};