summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/arm/insts/static_inst.hh17
-rw-r--r--src/arch/arm/isa/insts/data.isa73
2 files changed, 90 insertions, 0 deletions
diff --git a/src/arch/arm/insts/static_inst.hh b/src/arch/arm/insts/static_inst.hh
index 634cf0812..3ff1d20cd 100644
--- a/src/arch/arm/insts/static_inst.hh
+++ b/src/arch/arm/insts/static_inst.hh
@@ -77,6 +77,23 @@ class ArmStaticInst : public StaticInst
}
}
+ 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;
+ return true;
+ } else if (midRes < 0) {
+ res = 0;
+ return true;
+ } else {
+ res = midRes;
+ return false;
+ }
+ }
+
// Constructor
ArmStaticInst(const char *mnem, ExtMachInst _machInst,
OpClass __opClass)
diff --git a/src/arch/arm/isa/insts/data.isa b/src/arch/arm/isa/insts/data.isa
index 206c218e1..04e62f27b 100644
--- a/src/arch/arm/isa/insts/data.isa
+++ b/src/arch/arm/isa/insts/data.isa
@@ -428,4 +428,77 @@ let {{
Dest = resTemp;
resTemp = geBits;
''', flagType="ge", buildNonCc=False)
+
+ buildRegDataInst("uqadd16", '''
+ uint32_t midRes;
+ for (unsigned i = 0; i < 2; i++) {
+ int high = (i + 1) * 16 - 1;
+ int low = i * 16;
+ uint64_t arg1 = bits(Op1, high, low);
+ uint64_t arg2 = bits(Op2, high, low);
+ uSaturateOp<16>(midRes, arg1, arg2);
+ replaceBits(resTemp, high, low, midRes);
+ }
+ Dest = resTemp;
+ ''', flagType="none", buildCc=False)
+ buildRegDataInst("uqadd8", '''
+ uint32_t midRes;
+ for (unsigned i = 0; i < 4; i++) {
+ int high = (i + 1) * 8 - 1;
+ int low = i * 8;
+ uint64_t arg1 = bits(Op1, high, low);
+ uint64_t arg2 = bits(Op2, high, low);
+ uSaturateOp<8>(midRes, arg1, arg2);
+ replaceBits(resTemp, high, low, midRes);
+ }
+ Dest = resTemp;
+ ''', flagType="none", buildCc=False)
+ buildRegDataInst("uqsub16", '''
+ uint32_t midRes;
+ for (unsigned i = 0; i < 2; i++) {
+ int high = (i + 1) * 16 - 1;
+ int low = i * 16;
+ uint64_t arg1 = bits(Op1, high, low);
+ uint64_t arg2 = bits(Op2, high, low);
+ uSaturateOp<16>(midRes, arg1, arg2, true);
+ replaceBits(resTemp, high, low, midRes);
+ }
+ Dest = resTemp;
+ ''', flagType="none", buildCc=False)
+ buildRegDataInst("uqsub8", '''
+ uint32_t midRes;
+ for (unsigned i = 0; i < 4; i++) {
+ int high = (i + 1) * 8 - 1;
+ int low = i * 8;
+ uint64_t arg1 = bits(Op1, high, low);
+ uint64_t arg2 = bits(Op2, high, low);
+ uSaturateOp<8>(midRes, arg1, arg2, true);
+ replaceBits(resTemp, high, low, midRes);
+ }
+ Dest = resTemp;
+ ''', flagType="none", buildCc=False)
+ buildRegDataInst("uqasx", '''
+ uint32_t midRes;
+ uint64_t arg1Low = bits(Op1.sw, 15, 0);
+ uint64_t arg1High = bits(Op1.sw, 31, 16);
+ uint64_t arg2Low = bits(Op2.sw, 15, 0);
+ uint64_t arg2High = bits(Op2.sw, 31, 16);
+ uSaturateOp<16>(midRes, arg1Low, arg2High, true);
+ replaceBits(resTemp, 15, 0, midRes);
+ uSaturateOp<16>(midRes, arg1High, arg2Low);
+ replaceBits(resTemp, 31, 16, midRes);
+ Dest = resTemp;
+ ''', flagType="none", buildCc=False)
+ buildRegDataInst("uqsax", '''
+ uint32_t midRes;
+ uint64_t arg1Low = bits(Op1.sw, 15, 0);
+ uint64_t arg1High = bits(Op1.sw, 31, 16);
+ uint64_t arg2Low = bits(Op2.sw, 15, 0);
+ uint64_t arg2High = bits(Op2.sw, 31, 16);
+ uSaturateOp<16>(midRes, arg1Low, arg2High);
+ replaceBits(resTemp, 15, 0, midRes);
+ uSaturateOp<16>(midRes, arg1High, arg2Low, true);
+ replaceBits(resTemp, 31, 16, midRes);
+ Dest = resTemp;
+ ''', flagType="none", buildCc=False)
}};