summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2010-06-02 12:58:05 -0500
committerGabe Black <gblack@eecs.umich.edu>2010-06-02 12:58:05 -0500
commit62e8487d57796a15887af82034c8283611032ce0 (patch)
treec0b9bd4933daae68b91a9c4e106dec40ebeac1cc /src
parenta1253ec6442b217322a6a0104fb9e99f6ab958b1 (diff)
downloadgem5-62e8487d57796a15887af82034c8283611032ce0.tar.xz
ARM: Implement signed saturating add and/or subtract instructions.
Diffstat (limited to 'src')
-rw-r--r--src/arch/arm/insts/static_inst.hh17
-rw-r--r--src/arch/arm/isa/insts/data.isa126
2 files changed, 130 insertions, 13 deletions
diff --git a/src/arch/arm/insts/static_inst.hh b/src/arch/arm/insts/static_inst.hh
index 485d6997e..634cf0812 100644
--- a/src/arch/arm/insts/static_inst.hh
+++ b/src/arch/arm/insts/static_inst.hh
@@ -60,6 +60,23 @@ class ArmStaticInst : public StaticInst
bool shift_carry_rs(uint32_t base, uint32_t shamt,
uint32_t type, uint32_t cfval) const;
+ template<int width>
+ static bool
+ saturateOp(int32_t &res, int64_t op1, int64_t op2, bool sub=false)
+ {
+ int64_t midRes = sub ? (op1 - op2) : (op1 + op2);
+ if (bits(midRes, width) != bits(midRes, width - 1)) {
+ if (midRes > 0)
+ res = (1LL << (width - 1)) - 1;
+ else
+ res = -(1LL << (width - 1));
+ 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 69e813d25..9de42807e 100644
--- a/src/arch/arm/isa/insts/data.isa
+++ b/src/arch/arm/isa/insts/data.isa
@@ -44,8 +44,7 @@ let {{
exec_output = ""
calcQCode = '''
- cprintf("canOverflow: %%d\\n", Dest < resTemp);
- replaceBits(CondCodes, 27, Dest < resTemp);
+ CondCodes = CondCodes | ((resTemp & 1) << 27);
'''
calcCcCode = '''
@@ -68,6 +67,7 @@ let {{
carryCode = {
"none": (oldC, oldC, oldC),
"llbit": (oldC, oldC, oldC),
+ "saturate": ('0', '0', '0'),
"overflow": ('0', '0', '0'),
"add": ('findCarry(32, resTemp, Op1, secondOp)',
'findCarry(32, resTemp, Op1, secondOp)',
@@ -86,6 +86,7 @@ let {{
overflowCode = {
"none": oldV,
"llbit": oldV,
+ "saturate": '0',
"overflow": '0',
"add": 'findOverflow(32, resTemp, Op1, secondOp)',
"sub": 'findOverflow(32, resTemp, Op1, ~secondOp)',
@@ -98,14 +99,14 @@ let {{
regOp2 = "shift_rm_imm(Op2, shiftAmt, shiftType, CondCodes<29:>)"
regRegOp2 = "shift_rm_rs(Op2, Shift<7:0>, shiftType, CondCodes<29:>)"
- def buildImmDataInst(mnem, code, flagType = "logic", \
- suffix = "Imm", buildCc = True):
+ def buildImmDataInst(mnem, code, flagType = "logic", suffix = "Imm", \
+ buildCc = True, buildNonCc = True):
cCode = carryCode[flagType]
vCode = overflowCode[flagType]
negBit = 31
if flagType == "llbit":
negBit = 63
- if flagType == "overflow":
+ if flagType == "saturate":
immCcCode = calcQCode
else:
immCcCode = calcCcCode % {
@@ -128,18 +129,19 @@ let {{
decoder_output += DataImmConstructor.subst(iop)
exec_output += PredOpExecute.subst(iop)
- subst(immIop)
+ if buildNonCc:
+ subst(immIop)
if buildCc:
subst(immIopCc)
- def buildRegDataInst(mnem, code, flagType = "logic", \
- suffix = "Reg", buildCc = True):
+ def buildRegDataInst(mnem, code, flagType = "logic", suffix = "Reg", \
+ buildCc = True, buildNonCc = True):
cCode = carryCode[flagType]
vCode = overflowCode[flagType]
negBit = 31
if flagType == "llbit":
negBit = 63
- if flagType == "overflow":
+ if flagType == "saturate":
regCcCode = calcQCode
else:
regCcCode = calcCcCode % {
@@ -162,18 +164,20 @@ let {{
decoder_output += DataRegConstructor.subst(iop)
exec_output += PredOpExecute.subst(iop)
- subst(regIop)
+ if buildNonCc:
+ subst(regIop)
if buildCc:
subst(regIopCc)
def buildRegRegDataInst(mnem, code, flagType = "logic", \
- suffix = "RegReg", buildCc = True):
+ suffix = "RegReg", \
+ buildCc = True, buildNonCc = True):
cCode = carryCode[flagType]
vCode = overflowCode[flagType]
negBit = 31
if flagType == "llbit":
negBit = 63
- if flagType == "overflow":
+ if flagType == "saturate":
regRegCcCode = calcQCode
else:
regRegCcCode = calcCcCode % {
@@ -198,7 +202,8 @@ let {{
decoder_output += DataRegRegConstructor.subst(iop)
exec_output += PredOpExecute.subst(iop)
- subst(regRegIop)
+ if buildNonCc:
+ subst(regRegIop)
if buildCc:
subst(regRegIopCc)
@@ -250,4 +255,99 @@ let {{
buildDataInst("movt",
"Dest = resTemp = insertBits(Op1, 31, 16, secondOp);",
aiw = False)
+
+ buildRegDataInst("qadd", '''
+ int32_t midRes;
+ resTemp = saturateOp<32>(midRes, Op1.sw, Op2.sw);
+ Dest = midRes;
+ ''', flagType="saturate", buildNonCc=False)
+ buildRegDataInst("qadd16", '''
+ int32_t midRes;
+ for (unsigned i = 0; i < 2; i++) {
+ int high = (i + 1) * 16 - 1;
+ int low = i * 16;
+ int64_t arg1 = sext<16>(bits(Op1.sw, high, low));
+ int64_t arg2 = sext<16>(bits(Op2.sw, high, low));
+ saturateOp<16>(midRes, arg1, arg2);
+ replaceBits(resTemp, high, low, midRes);
+ }
+ Dest = resTemp;
+ ''', flagType="none", buildCc=False)
+ buildRegDataInst("qadd8", '''
+ int32_t midRes;
+ for (unsigned i = 0; i < 4; i++) {
+ int high = (i + 1) * 8 - 1;
+ int low = i * 8;
+ int64_t arg1 = sext<8>(bits(Op1.sw, high, low));
+ int64_t arg2 = sext<8>(bits(Op2.sw, high, low));
+ saturateOp<8>(midRes, arg1, arg2);
+ replaceBits(resTemp, high, low, midRes);
+ }
+ Dest = resTemp;
+ ''', flagType="none", buildCc=False)
+ buildRegDataInst("qdadd", '''
+ int32_t midRes;
+ resTemp = saturateOp<32>(midRes, Op2.sw, Op2.sw) |
+ saturateOp<32>(midRes, Op1.sw, midRes);
+ Dest = midRes;
+ ''', flagType="saturate", buildNonCc=False)
+ buildRegDataInst("qsub", '''
+ int32_t midRes;
+ resTemp = saturateOp<32>(midRes, Op1.sw, Op2.sw, true);
+ Dest = midRes;
+ ''', flagType="saturate")
+ buildRegDataInst("qsub16", '''
+ int32_t midRes;
+ for (unsigned i = 0; i < 2; i++) {
+ int high = (i + 1) * 16 - 1;
+ int low = i * 16;
+ int64_t arg1 = sext<16>(bits(Op1.sw, high, low));
+ int64_t arg2 = sext<16>(bits(Op2.sw, high, low));
+ saturateOp<16>(midRes, arg1, arg2, true);
+ replaceBits(resTemp, high, low, midRes);
+ }
+ Dest = resTemp;
+ ''', flagType="none", buildCc=False)
+ buildRegDataInst("qsub8", '''
+ int32_t midRes;
+ for (unsigned i = 0; i < 4; i++) {
+ int high = (i + 1) * 8 - 1;
+ int low = i * 8;
+ int64_t arg1 = sext<8>(bits(Op1.sw, high, low));
+ int64_t arg2 = sext<8>(bits(Op2.sw, high, low));
+ saturateOp<8>(midRes, arg1, arg2, true);
+ replaceBits(resTemp, high, low, midRes);
+ }
+ Dest = resTemp;
+ ''', flagType="none", buildCc=False)
+ buildRegDataInst("qdsub", '''
+ int32_t midRes;
+ resTemp = saturateOp<32>(midRes, Op2.sw, Op2.sw) |
+ saturateOp<32>(midRes, Op1.sw, midRes, true);
+ Dest = midRes;
+ ''', flagType="saturate", buildNonCc=False)
+ buildRegDataInst("qasx", '''
+ int32_t midRes;
+ int64_t arg1Low = sext<16>(bits(Op1.sw, 15, 0));
+ int64_t arg1High = sext<16>(bits(Op1.sw, 31, 16));
+ int64_t arg2Low = sext<16>(bits(Op2.sw, 15, 0));
+ int64_t arg2High = sext<16>(bits(Op2.sw, 31, 16));
+ saturateOp<16>(midRes, arg1Low, arg2High, true);
+ replaceBits(resTemp, 15, 0, midRes);
+ saturateOp<16>(midRes, arg1High, arg2Low);
+ replaceBits(resTemp, 31, 16, midRes);
+ Dest = resTemp;
+ ''', flagType="none", buildCc=False)
+ buildRegDataInst("qsax", '''
+ int32_t midRes;
+ int64_t arg1Low = sext<16>(bits(Op1.sw, 15, 0));
+ int64_t arg1High = sext<16>(bits(Op1.sw, 31, 16));
+ int64_t arg2Low = sext<16>(bits(Op2.sw, 15, 0));
+ int64_t arg2High = sext<16>(bits(Op2.sw, 31, 16));
+ saturateOp<16>(midRes, arg1Low, arg2High);
+ replaceBits(resTemp, 15, 0, midRes);
+ saturateOp<16>(midRes, arg1High, arg2Low, true);
+ replaceBits(resTemp, 31, 16, midRes);
+ Dest = resTemp;
+ ''', flagType="none", buildCc=False)
}};