data.isa revision 10037
110259SAndrew.Bardsley@arm.com// -*- mode:c++ -*-
210259SAndrew.Bardsley@arm.com
310259SAndrew.Bardsley@arm.com// Copyright (c) 2010, 2013 ARM Limited
410259SAndrew.Bardsley@arm.com// All rights reserved
510259SAndrew.Bardsley@arm.com//
610259SAndrew.Bardsley@arm.com// The license below extends only to copyright in the software and shall
710259SAndrew.Bardsley@arm.com// not be construed as granting a license to any other intellectual
810259SAndrew.Bardsley@arm.com// property including but not limited to intellectual property relating
910259SAndrew.Bardsley@arm.com// to a hardware implementation of the functionality of the software
1010259SAndrew.Bardsley@arm.com// licensed hereunder.  You may use the software subject to the license
1110259SAndrew.Bardsley@arm.com// terms below provided that you ensure that this notice is replicated
1210259SAndrew.Bardsley@arm.com// unmodified and in its entirety in all distributions of the software,
1310259SAndrew.Bardsley@arm.com// modified or unmodified, in source code or in binary form.
1410259SAndrew.Bardsley@arm.com//
1510259SAndrew.Bardsley@arm.com// Redistribution and use in source and binary forms, with or without
1610259SAndrew.Bardsley@arm.com// modification, are permitted provided that the following conditions are
1710259SAndrew.Bardsley@arm.com// met: redistributions of source code must retain the above copyright
1810259SAndrew.Bardsley@arm.com// notice, this list of conditions and the following disclaimer;
1910259SAndrew.Bardsley@arm.com// redistributions in binary form must reproduce the above copyright
2010259SAndrew.Bardsley@arm.com// notice, this list of conditions and the following disclaimer in the
2110259SAndrew.Bardsley@arm.com// documentation and/or other materials provided with the distribution;
2210259SAndrew.Bardsley@arm.com// neither the name of the copyright holders nor the names of its
2310259SAndrew.Bardsley@arm.com// contributors may be used to endorse or promote products derived from
2410259SAndrew.Bardsley@arm.com// this software without specific prior written permission.
2510259SAndrew.Bardsley@arm.com//
2610259SAndrew.Bardsley@arm.com// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2710259SAndrew.Bardsley@arm.com// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2810259SAndrew.Bardsley@arm.com// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2910259SAndrew.Bardsley@arm.com// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3010259SAndrew.Bardsley@arm.com// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3110259SAndrew.Bardsley@arm.com// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3210259SAndrew.Bardsley@arm.com// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3310259SAndrew.Bardsley@arm.com// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3410259SAndrew.Bardsley@arm.com// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3510259SAndrew.Bardsley@arm.com// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3610259SAndrew.Bardsley@arm.com// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3710259SAndrew.Bardsley@arm.com//
3810259SAndrew.Bardsley@arm.com// Authors: Gabe Black
3910259SAndrew.Bardsley@arm.com
4010259SAndrew.Bardsley@arm.comlet {{
4110259SAndrew.Bardsley@arm.com
4210259SAndrew.Bardsley@arm.com    header_output = ""
4310259SAndrew.Bardsley@arm.com    decoder_output = ""
4410259SAndrew.Bardsley@arm.com    exec_output = ""
4510259SAndrew.Bardsley@arm.com
4610259SAndrew.Bardsley@arm.com    calcGECode = '''
4710259SAndrew.Bardsley@arm.com        CondCodesGE = resTemp;
4810259SAndrew.Bardsley@arm.com    '''
4910259SAndrew.Bardsley@arm.com
5010259SAndrew.Bardsley@arm.com    calcQCode = '''
5110259SAndrew.Bardsley@arm.com        CpsrQ = (resTemp & 1) << 27;
5210259SAndrew.Bardsley@arm.com    '''
5310259SAndrew.Bardsley@arm.com
5410259SAndrew.Bardsley@arm.com    def createCcCode(negBit, carry, overflow):
5510259SAndrew.Bardsley@arm.com        code = ""
5610259SAndrew.Bardsley@arm.com        code += '''
5710259SAndrew.Bardsley@arm.com            uint16_t _iz, _in;
5810259SAndrew.Bardsley@arm.com            _in = (resTemp >> %d) & 1;
5910259SAndrew.Bardsley@arm.com            _iz = (resTemp == 0);
6010259SAndrew.Bardsley@arm.com            CondCodesNZ = (_in << 1) | _iz;
6110259SAndrew.Bardsley@arm.com            DPRINTF(Arm, "(in, iz) = (%%d, %%d)\\n", _in, _iz);
6210259SAndrew.Bardsley@arm.com        ''' % negBit
6310259SAndrew.Bardsley@arm.com        if overflow and overflow != "none":
6410259SAndrew.Bardsley@arm.com            code +=  '''
6510259SAndrew.Bardsley@arm.com                uint16_t _iv;
6610259SAndrew.Bardsley@arm.com                _iv = %s & 1;
6710259SAndrew.Bardsley@arm.com                CondCodesV =  _iv;
6810259SAndrew.Bardsley@arm.com                DPRINTF(Arm, "(iv) = (%%d)\\n", _iv);
6910259SAndrew.Bardsley@arm.com            ''' % overflow
7010259SAndrew.Bardsley@arm.com        if carry and carry != "none":
7110259SAndrew.Bardsley@arm.com            code += '''
7210259SAndrew.Bardsley@arm.com                uint16_t _ic;
7310259SAndrew.Bardsley@arm.com                _ic = %s & 1;
7410259SAndrew.Bardsley@arm.com                CondCodesC =  _ic;
7510259SAndrew.Bardsley@arm.com                DPRINTF(Arm, "(ic) = (%%d)\\n", _ic);
7610259SAndrew.Bardsley@arm.com            ''' % carry
7710259SAndrew.Bardsley@arm.com        return code
7810259SAndrew.Bardsley@arm.com
7910259SAndrew.Bardsley@arm.com    # Dict of code to set the carry flag. (imm, reg, reg-reg)
8010259SAndrew.Bardsley@arm.com    oldC = 'CondCodesC'
8110259SAndrew.Bardsley@arm.com    carryCode = {
8210259SAndrew.Bardsley@arm.com        "none": ("none", "none", "none"),
8310259SAndrew.Bardsley@arm.com        "llbit": ("none", "none", "none"),
8410259SAndrew.Bardsley@arm.com        "saturate": ('0', '0', '0'),
8510259SAndrew.Bardsley@arm.com        "overflow": ('0', '0', '0'),
8610259SAndrew.Bardsley@arm.com        "ge": ('0', '0', '0'),
8710259SAndrew.Bardsley@arm.com        "add": ('findCarry(32, resTemp, Op1, secondOp)',
8810259SAndrew.Bardsley@arm.com                'findCarry(32, resTemp, Op1, secondOp)',
8910259SAndrew.Bardsley@arm.com                'findCarry(32, resTemp, Op1, secondOp)'),
9010259SAndrew.Bardsley@arm.com        "sub": ('findCarry(32, resTemp, Op1, ~secondOp)',
9110259SAndrew.Bardsley@arm.com                'findCarry(32, resTemp, Op1, ~secondOp)',
9210259SAndrew.Bardsley@arm.com                'findCarry(32, resTemp, Op1, ~secondOp)'),
9310259SAndrew.Bardsley@arm.com        "rsb": ('findCarry(32, resTemp, secondOp, ~Op1)',
9410259SAndrew.Bardsley@arm.com                'findCarry(32, resTemp, secondOp, ~Op1)',
9510259SAndrew.Bardsley@arm.com                'findCarry(32, resTemp, secondOp, ~Op1)'),
9610259SAndrew.Bardsley@arm.com        "logic": ('(rotC ? bits(secondOp, 31) : %s)' % oldC,
9710259SAndrew.Bardsley@arm.com                  'shift_carry_imm(Op2, shiftAmt, shiftType, %s)' % oldC,
9810259SAndrew.Bardsley@arm.com                  'shift_carry_rs(Op2, Shift<7:0>, shiftType, %s)' % oldC)
9910259SAndrew.Bardsley@arm.com    }
10010259SAndrew.Bardsley@arm.com    # Dict of code to set the overflow flag.
10110259SAndrew.Bardsley@arm.com    overflowCode = {
10210259SAndrew.Bardsley@arm.com        "none": "none",
10310259SAndrew.Bardsley@arm.com        "llbit": "none",
10410259SAndrew.Bardsley@arm.com        "saturate": '0',
10510259SAndrew.Bardsley@arm.com        "overflow": '0',
10610259SAndrew.Bardsley@arm.com        "ge": '0',
10710259SAndrew.Bardsley@arm.com        "add": 'findOverflow(32, resTemp, Op1, secondOp)',
10810259SAndrew.Bardsley@arm.com        "sub": 'findOverflow(32, resTemp, Op1, ~secondOp)',
10910259SAndrew.Bardsley@arm.com        "rsb": 'findOverflow(32, resTemp, secondOp, ~Op1)',
11010259SAndrew.Bardsley@arm.com        "logic": "none"
11110259SAndrew.Bardsley@arm.com    }
11210259SAndrew.Bardsley@arm.com
11310259SAndrew.Bardsley@arm.com    secondOpRe = re.compile("secondOp")
11410259SAndrew.Bardsley@arm.com    immOp2 = "imm"
11510259SAndrew.Bardsley@arm.com    regOp2 = "shift_rm_imm(Op2, shiftAmt, shiftType, OptShiftRmCondCodesC)"
11610259SAndrew.Bardsley@arm.com    regRegOp2 = "shift_rm_rs(Op2, Shift<7:0>, shiftType, 0)"
11710259SAndrew.Bardsley@arm.com
11810259SAndrew.Bardsley@arm.com    def buildImmDataInst(mnem, code, flagType = "logic", suffix = "Imm", \
11910259SAndrew.Bardsley@arm.com                         buildCc = True, buildNonCc = True, isBranch = "0", \
12010259SAndrew.Bardsley@arm.com                         instFlags = []):
12110259SAndrew.Bardsley@arm.com        cCode = carryCode[flagType]
12210259SAndrew.Bardsley@arm.com        vCode = overflowCode[flagType]
12310259SAndrew.Bardsley@arm.com        negBit = 31
12410259SAndrew.Bardsley@arm.com        if flagType == "llbit":
12510259SAndrew.Bardsley@arm.com            negBit = 63
12610259SAndrew.Bardsley@arm.com        if flagType == "saturate":
12710259SAndrew.Bardsley@arm.com            immCcCode = calcQCode
12810259SAndrew.Bardsley@arm.com        elif flagType == "ge":
12910259SAndrew.Bardsley@arm.com            immCcCode = calcGECode
13010259SAndrew.Bardsley@arm.com        else:
13110259SAndrew.Bardsley@arm.com            immCcCode = createCcCode(negBit, secondOpRe.sub(immOp2, cCode[0]),
13210259SAndrew.Bardsley@arm.com                                     secondOpRe.sub(immOp2, vCode))
13310259SAndrew.Bardsley@arm.com
13410259SAndrew.Bardsley@arm.com        immCode = secondOpRe.sub(immOp2, code)
13510259SAndrew.Bardsley@arm.com        immIop = InstObjParams(mnem, mnem.capitalize() + suffix, "DataImmOp",
13610259SAndrew.Bardsley@arm.com                       {"code" : immCode,
13710259SAndrew.Bardsley@arm.com                        "is_branch" : isBranch,
13810259SAndrew.Bardsley@arm.com                        "predicate_test": pickPredicate(immCode)}, instFlags)
13910259SAndrew.Bardsley@arm.com        immIopCc = InstObjParams(mnem + "s", mnem.capitalize() + suffix + "Cc",
14010259SAndrew.Bardsley@arm.com             "DataImmOp",
14110259SAndrew.Bardsley@arm.com             {"code" : immCode + immCcCode,
14210259SAndrew.Bardsley@arm.com              "is_branch" : isBranch,
14310259SAndrew.Bardsley@arm.com              "predicate_test": pickPredicate(immCode + immCcCode)}, instFlags)
14410259SAndrew.Bardsley@arm.com
14510259SAndrew.Bardsley@arm.com        def subst(iop):
14610259SAndrew.Bardsley@arm.com            global header_output, decoder_output, exec_output
14710259SAndrew.Bardsley@arm.com            header_output += DataImmDeclare.subst(iop)
14810259SAndrew.Bardsley@arm.com            decoder_output += DataImmConstructor.subst(iop)
14910905Sandreas.sandberg@arm.com            exec_output += PredOpExecute.subst(iop)
15010905Sandreas.sandberg@arm.com
15110905Sandreas.sandberg@arm.com        if buildNonCc:
15210259SAndrew.Bardsley@arm.com            subst(immIop)
15310259SAndrew.Bardsley@arm.com        if buildCc:
15410905Sandreas.sandberg@arm.com            subst(immIopCc)
15510905Sandreas.sandberg@arm.com
15610259SAndrew.Bardsley@arm.com    def buildRegDataInst(mnem, code, flagType = "logic", suffix = "Reg", \
15710259SAndrew.Bardsley@arm.com                         buildCc = True, buildNonCc = True, isRasPop = "0", \
15810259SAndrew.Bardsley@arm.com                         isBranch = "0", instFlags = []):
15910259SAndrew.Bardsley@arm.com        cCode = carryCode[flagType]
16010259SAndrew.Bardsley@arm.com        vCode = overflowCode[flagType]
16110259SAndrew.Bardsley@arm.com        negBit = 31
16210259SAndrew.Bardsley@arm.com        regCcCode = ""
16310259SAndrew.Bardsley@arm.com        if flagType == "llbit":
16410259SAndrew.Bardsley@arm.com            negBit = 63
16510259SAndrew.Bardsley@arm.com        if flagType == "saturate":
16610259SAndrew.Bardsley@arm.com            regCcCode = calcQCode
16710259SAndrew.Bardsley@arm.com        elif flagType == "ge":
16810259SAndrew.Bardsley@arm.com            regCcCode = calcGECode
16910259SAndrew.Bardsley@arm.com        else:
17010407Smitch.hayenga@arm.com            regCcCode = createCcCode(negBit,secondOpRe.sub(regOp2, cCode[1]),
17110259SAndrew.Bardsley@arm.com                                     secondOpRe.sub(regOp2, vCode))
17210259SAndrew.Bardsley@arm.com
17310259SAndrew.Bardsley@arm.com        regCode = secondOpRe.sub(regOp2, code)
17410259SAndrew.Bardsley@arm.com
17510259SAndrew.Bardsley@arm.com        # If we end up needing CondCodesC then remove any trace of the OptShift
17610259SAndrew.Bardsley@arm.com        if re.search('(?<!OptShiftRm)CondCodesC(?!.*=)', regCode + regCcCode):
17710259SAndrew.Bardsley@arm.com            regCode = re.sub('OptShiftRmCondCodesC', 'CondCodesC', regCode)
17810259SAndrew.Bardsley@arm.com            regCcCode = re.sub('OptShiftRmCondCodesC', 'CondCodesC', regCcCode)
17910259SAndrew.Bardsley@arm.com
18010259SAndrew.Bardsley@arm.com        regIop = InstObjParams(mnem, mnem.capitalize() + suffix, "DataRegOp",
181                       {"code" : regCode, "is_ras_pop" : isRasPop,
182                        "is_branch" : isBranch,
183                        "predicate_test": pickPredicate(regCode)}, instFlags)
184        regIopCc = InstObjParams(mnem + "s", mnem.capitalize() + suffix + "Cc",
185                         "DataRegOp",
186                         {"code" : regCode + regCcCode,
187                          "predicate_test": pickPredicate(regCode + regCcCode),
188                          "is_ras_pop" : isRasPop,
189                          "is_branch" : isBranch}, instFlags)
190
191        def subst(iop):
192            global header_output, decoder_output, exec_output
193            header_output += DataRegDeclare.subst(iop)
194            decoder_output += DataRegConstructor.subst(iop)
195            exec_output += PredOpExecute.subst(iop)
196
197        if buildNonCc:
198            subst(regIop)
199        if buildCc:
200            subst(regIopCc)
201
202    def buildRegRegDataInst(mnem, code, flagType = "logic", \
203                            suffix = "RegReg", \
204                            buildCc = True, buildNonCc = True):
205        cCode = carryCode[flagType]
206        vCode = overflowCode[flagType]
207        negBit = 31
208        if flagType == "llbit":
209            negBit = 63
210        if flagType == "saturate":
211            regRegCcCode = calcQCode
212        elif flagType == "ge":
213            regRegCcCode = calcGECode
214        else:
215            regRegCcCode = createCcCode(negBit,
216                                        secondOpRe.sub(regRegOp2, cCode[2]),
217                                        secondOpRe.sub(regRegOp2, vCode))
218
219        regRegCode = secondOpRe.sub(regRegOp2, code)
220        regRegIop = InstObjParams(mnem, mnem.capitalize() + suffix,
221                          "DataRegRegOp",
222                          {"code" : regRegCode,
223                           "predicate_test": pickPredicate(regRegCode)})
224        regRegIopCc = InstObjParams(mnem + "s",
225                mnem.capitalize() + suffix + "Cc",
226                "DataRegRegOp",
227                {"code" : regRegCode + regRegCcCode,
228                 "predicate_test": pickPredicate(regRegCode + regRegCcCode)})
229
230        def subst(iop):
231            global header_output, decoder_output, exec_output
232            header_output += DataRegRegDeclare.subst(iop)
233            decoder_output += DataRegRegConstructor.subst(iop)
234            exec_output += PredOpExecute.subst(iop)
235
236        if buildNonCc:
237            subst(regRegIop)
238        if buildCc:
239            subst(regRegIopCc)
240
241    def buildDataInst(mnem, code, flagType = "logic", \
242                      aiw = True, regRegAiw = True,
243                      subsPcLr = True, isRasPop = "0", isBranch = "0"):
244        regRegCode = instCode = code
245        if aiw:
246            instCode = "AIW" + instCode
247            if regRegAiw:
248                regRegCode = "AIW" + regRegCode
249
250        buildImmDataInst(mnem, instCode, flagType, isBranch = isBranch)
251        buildRegDataInst(mnem, instCode, flagType,
252                         isRasPop = isRasPop, isBranch = isBranch)
253        buildRegRegDataInst(mnem, regRegCode, flagType)
254        if subsPcLr:
255            code += '''
256            SCTLR sctlr = Sctlr;
257            CPSR old_cpsr = Cpsr;
258
259            CPSR new_cpsr =
260                cpsrWriteByInstr(old_cpsr, Spsr, Scr, Nsacr, 0xF, true,
261                                 sctlr.nmfi, xc->tcBase());
262            Cpsr = ~CondCodesMask & new_cpsr;
263            CondCodesNZ = new_cpsr.nz;
264            CondCodesC = new_cpsr.c;
265            CondCodesV = new_cpsr.v;
266            CondCodesGE = new_cpsr.ge;
267
268            NextThumb = (new_cpsr).t;
269            NextJazelle = (new_cpsr).j;
270            NextItState = (((new_cpsr).it2 << 2) & 0xFC)
271                | ((new_cpsr).it1 & 0x3);
272            SevMailbox = 1;
273            '''
274            buildImmDataInst(mnem + 's', code, flagType,
275                             suffix = "ImmPclr", buildCc = False,
276                             instFlags = ["IsSerializeAfter","IsNonSpeculative"])
277            buildRegDataInst(mnem + 's', code, flagType,
278                             suffix = "RegPclr", buildCc = False,
279                             instFlags = ["IsSerializeAfter","IsNonSpeculative"])
280
281    buildDataInst("and", "Dest = resTemp = Op1 & secondOp;")
282    buildDataInst("eor", "Dest = resTemp = Op1 ^ secondOp;")
283    buildDataInst("sub", "Dest = resTemp = Op1 - secondOp;", "sub",
284                  isBranch = "dest == INTREG_PC")
285    buildDataInst("rsb", "Dest = resTemp = secondOp - Op1;", "rsb")
286    buildDataInst("add", "Dest = resTemp = Op1 + secondOp;", "add",
287                  isBranch = "dest == INTREG_PC")
288    buildImmDataInst("adr", '''
289                               Dest = resTemp = (PC & ~0x3) +
290                               (op1 ? secondOp : -secondOp);
291                            ''', isBranch = "dest == INTREG_PC")
292    buildDataInst("adc", "Dest = resTemp = Op1 + secondOp + %s;" % oldC, "add")
293    buildDataInst("sbc", "Dest = resTemp = Op1 - secondOp - !%s;" % oldC, "sub")
294    buildDataInst("rsc", "Dest = resTemp = secondOp - Op1 - !%s;" % oldC, "rsb")
295    buildDataInst("tst", "resTemp = Op1 & secondOp;", aiw = False)
296    buildDataInst("teq", "resTemp = Op1 ^ secondOp;", aiw = False)
297    buildDataInst("cmp", "resTemp = Op1 - secondOp;", "sub", aiw = False)
298    buildDataInst("cmn", "resTemp = Op1 + secondOp;", "add", aiw = False)
299    buildDataInst("orr", "Dest = resTemp = Op1 | secondOp;")
300    buildDataInst("orn", "Dest = resTemp = Op1 | ~secondOp;", aiw = False)
301    buildDataInst("mov", "Dest = resTemp = secondOp;", regRegAiw = False,
302                  isRasPop = "op2 == INTREG_LR", isBranch = "dest == INTREG_PC")
303    buildDataInst("bic", "Dest = resTemp = Op1 & ~secondOp;")
304    buildDataInst("mvn", "Dest = resTemp = ~secondOp;")
305    buildDataInst("movt",
306                  "Dest = resTemp = insertBits(Op1, 31, 16, secondOp);",
307                  aiw = False)
308
309    buildRegDataInst("qadd", '''
310            int32_t midRes;
311            resTemp = saturateOp<32>(midRes, Op1_sw, Op2_sw);
312                                     Dest = midRes;
313        ''', flagType="saturate", buildNonCc=False)
314    buildRegDataInst("qadd16", '''
315            int32_t midRes;
316            for (unsigned i = 0; i < 2; i++) {
317                int high = (i + 1) * 16 - 1;
318                int low = i * 16;
319                int64_t arg1 = sext<16>(bits(Op1_sw, high, low));
320                int64_t arg2 = sext<16>(bits(Op2_sw, high, low));
321                saturateOp<16>(midRes, arg1, arg2);
322                replaceBits(resTemp, high, low, midRes);
323            }
324            Dest = resTemp;
325        ''', flagType="none", buildCc=False)
326    buildRegDataInst("qadd8", '''
327            int32_t midRes;
328            for (unsigned i = 0; i < 4; i++) {
329                int high = (i + 1) * 8 - 1;
330                int low = i * 8;
331                int64_t arg1 = sext<8>(bits(Op1_sw, high, low));
332                int64_t arg2 = sext<8>(bits(Op2_sw, high, low));
333                saturateOp<8>(midRes, arg1, arg2);
334                replaceBits(resTemp, high, low, midRes);
335            }
336            Dest = resTemp;
337        ''', flagType="none", buildCc=False)
338    buildRegDataInst("qdadd", '''
339            int32_t midRes;
340            resTemp = saturateOp<32>(midRes, Op2_sw, Op2_sw) |
341                      saturateOp<32>(midRes, Op1_sw, midRes);
342            Dest = midRes;
343        ''', flagType="saturate", buildNonCc=False)
344    buildRegDataInst("qsub", '''
345            int32_t midRes;
346            resTemp = saturateOp<32>(midRes, Op1_sw, Op2_sw, true);
347            Dest = midRes;
348        ''', flagType="saturate")
349    buildRegDataInst("qsub16", '''
350            int32_t midRes;
351            for (unsigned i = 0; i < 2; i++) {
352                 int high = (i + 1) * 16 - 1;
353                 int low = i * 16;
354                 int64_t arg1 = sext<16>(bits(Op1_sw, high, low));
355                 int64_t arg2 = sext<16>(bits(Op2_sw, high, low));
356                 saturateOp<16>(midRes, arg1, arg2, true);
357                 replaceBits(resTemp, high, low, midRes);
358            }
359            Dest = resTemp;
360        ''', flagType="none", buildCc=False)
361    buildRegDataInst("qsub8", '''
362            int32_t midRes;
363            for (unsigned i = 0; i < 4; i++) {
364                 int high = (i + 1) * 8 - 1;
365                 int low = i * 8;
366                 int64_t arg1 = sext<8>(bits(Op1_sw, high, low));
367                 int64_t arg2 = sext<8>(bits(Op2_sw, high, low));
368                 saturateOp<8>(midRes, arg1, arg2, true);
369                 replaceBits(resTemp, high, low, midRes);
370            }
371            Dest = resTemp;
372        ''', flagType="none", buildCc=False)
373    buildRegDataInst("qdsub", '''
374            int32_t midRes;
375            resTemp = saturateOp<32>(midRes, Op2_sw, Op2_sw) |
376                      saturateOp<32>(midRes, Op1_sw, midRes, true);
377            Dest = midRes;
378        ''', flagType="saturate", buildNonCc=False)
379    buildRegDataInst("qasx", '''
380            int32_t midRes;
381            int64_t arg1Low = sext<16>(bits(Op1_sw, 15, 0));
382            int64_t arg1High = sext<16>(bits(Op1_sw, 31, 16));
383            int64_t arg2Low = sext<16>(bits(Op2_sw, 15, 0));
384            int64_t arg2High = sext<16>(bits(Op2_sw, 31, 16));
385            saturateOp<16>(midRes, arg1Low, arg2High, true);
386            replaceBits(resTemp, 15, 0, midRes);
387            saturateOp<16>(midRes, arg1High, arg2Low);
388            replaceBits(resTemp, 31, 16, midRes);
389            Dest = resTemp;
390        ''', flagType="none", buildCc=False)
391    buildRegDataInst("qsax", '''
392            int32_t midRes;
393            int64_t arg1Low = sext<16>(bits(Op1_sw, 15, 0));
394            int64_t arg1High = sext<16>(bits(Op1_sw, 31, 16));
395            int64_t arg2Low = sext<16>(bits(Op2_sw, 15, 0));
396            int64_t arg2High = sext<16>(bits(Op2_sw, 31, 16));
397            saturateOp<16>(midRes, arg1Low, arg2High);
398            replaceBits(resTemp, 15, 0, midRes);
399            saturateOp<16>(midRes, arg1High, arg2Low, true);
400            replaceBits(resTemp, 31, 16, midRes);
401            Dest = resTemp;
402        ''', flagType="none", buildCc=False)
403
404    buildRegDataInst("sadd8", '''
405            uint32_t geBits = 0;
406            resTemp = 0;
407            for (unsigned i = 0; i < 4; i++) {
408                int high = (i + 1) * 8 - 1;
409                int low = i * 8;
410                int32_t midRes = sext<8>(bits(Op1_sw, high, low)) +
411                                 sext<8>(bits(Op2_sw, high, low));
412                replaceBits(resTemp, high, low, midRes);
413                if (midRes >= 0) {
414                    geBits = geBits | (1 << i);
415                }
416            }
417            Dest = resTemp;
418            resTemp = geBits;
419        ''', flagType="ge", buildNonCc=False)
420    buildRegDataInst("sadd16", '''
421            uint32_t geBits = 0;
422            resTemp = 0;
423            for (unsigned i = 0; i < 2; i++) {
424                int high = (i + 1) * 16 - 1;
425                int low = i * 16;
426                int32_t midRes = sext<16>(bits(Op1_sw, high, low)) +
427                                 sext<16>(bits(Op2_sw, high, low));
428                replaceBits(resTemp, high, low, midRes);
429                if (midRes >= 0) {
430                    geBits = geBits | (0x3 << (i * 2));
431                }
432            }
433            Dest = resTemp;
434            resTemp = geBits;
435        ''', flagType="ge", buildNonCc=False)
436
437    buildRegDataInst("ssub8", '''
438            uint32_t geBits = 0;
439            resTemp = 0;
440            for (unsigned i = 0; i < 4; i++) {
441                int high = (i + 1) * 8 - 1;
442                int low = i * 8;
443                int32_t midRes = sext<8>(bits(Op1_sw, high, low)) -
444                                 sext<8>(bits(Op2_sw, high, low));
445                replaceBits(resTemp, high, low, midRes);
446                if (midRes >= 0) {
447                    geBits = geBits | (1 << i);
448                }
449            }
450            Dest = resTemp;
451            resTemp = geBits;
452        ''', flagType="ge", buildNonCc=False)
453    buildRegDataInst("ssub16", '''
454            uint32_t geBits = 0;
455            resTemp = 0;
456            for (unsigned i = 0; i < 2; i++) {
457                int high = (i + 1) * 16 - 1;
458                int low = i * 16;
459                int32_t midRes = sext<16>(bits(Op1_sw, high, low)) -
460                                 sext<16>(bits(Op2_sw, high, low));
461                replaceBits(resTemp, high, low, midRes);
462                if (midRes >= 0) {
463                    geBits = geBits | (0x3 << (i * 2));
464                }
465            }
466            Dest = resTemp;
467            resTemp = geBits;
468        ''', flagType="ge", buildNonCc=False)
469    buildRegDataInst("sasx", '''
470            int32_t midRes, geBits = 0;
471            resTemp = 0;
472            int64_t arg1Low = sext<16>(bits(Op1_sw, 15, 0));
473            int64_t arg1High = sext<16>(bits(Op1_sw, 31, 16));
474            int64_t arg2Low = sext<16>(bits(Op2_sw, 15, 0));
475            int64_t arg2High = sext<16>(bits(Op2_sw, 31, 16));
476            midRes = arg1Low - arg2High;
477            if (midRes >= 0) {
478                geBits = geBits | 0x3;
479            }
480            replaceBits(resTemp, 15, 0, midRes);
481            midRes = arg1High + arg2Low;
482            if (midRes >= 0) {
483                geBits = geBits | 0xc;
484            }
485            replaceBits(resTemp, 31, 16, midRes);
486            Dest = resTemp;
487            resTemp = geBits;
488        ''', flagType="ge", buildNonCc=True)
489    buildRegDataInst("ssax", '''
490            int32_t midRes, geBits = 0;
491            resTemp = 0;
492            int64_t arg1Low = sext<16>(bits(Op1_sw, 15, 0));
493            int64_t arg1High = sext<16>(bits(Op1_sw, 31, 16));
494            int64_t arg2Low = sext<16>(bits(Op2_sw, 15, 0));
495            int64_t arg2High = sext<16>(bits(Op2_sw, 31, 16));
496            midRes = arg1Low + arg2High;
497            if (midRes >= 0) {
498                geBits = geBits | 0x3;
499            }
500            replaceBits(resTemp, 15, 0, midRes);
501            midRes = arg1High - arg2Low;
502            if (midRes >= 0) {
503                geBits = geBits | 0xc;
504            }
505            replaceBits(resTemp, 31, 16, midRes);
506            Dest = resTemp;
507            resTemp = geBits;
508        ''', flagType="ge", buildNonCc=True)
509
510    buildRegDataInst("shadd8", '''
511            resTemp = 0;
512            for (unsigned i = 0; i < 4; i++) {
513                int high = (i + 1) * 8 - 1;
514                int low = i * 8;
515                int32_t midRes =
516                    (uint64_t)(sext<8>(bits(Op1_sw, high, low)) +
517                               sext<8>(bits(Op2_sw, high, low))) >> 1;
518                replaceBits(resTemp, high, low, midRes);
519            }
520            Dest = resTemp;
521        ''', flagType="none", buildCc=False)
522    buildRegDataInst("shadd16", '''
523            resTemp = 0;
524            for (unsigned i = 0; i < 2; i++) {
525                int high = (i + 1) * 16 - 1;
526                int low = i * 16;
527                int32_t midRes =
528                    (uint64_t)(sext<16>(bits(Op1_sw, high, low)) +
529                               sext<16>(bits(Op2_sw, high, low))) >> 1;
530                replaceBits(resTemp, high, low, midRes);
531            }
532            Dest = resTemp;
533        ''', flagType="none", buildCc=False)
534    buildRegDataInst("shsub8", '''
535            resTemp = 0;
536            for (unsigned i = 0; i < 4; i++) {
537                int high = (i + 1) * 8 - 1;
538                int low = i * 8;
539                int32_t midRes =
540                    (uint64_t)(sext<8>(bits(Op1_sw, high, low)) -
541                               sext<8>(bits(Op2_sw, high, low))) >> 1;
542                replaceBits(resTemp, high, low, midRes);
543            }
544            Dest = resTemp;
545        ''', flagType="none", buildCc=False)
546    buildRegDataInst("shsub16", '''
547            resTemp = 0;
548            for (unsigned i = 0; i < 2; i++) {
549                int high = (i + 1) * 16 - 1;
550                int low = i * 16;
551                int32_t midRes =
552                    (uint64_t)(sext<16>(bits(Op1_sw, high, low)) -
553                               sext<16>(bits(Op2_sw, high, low))) >> 1;
554                replaceBits(resTemp, high, low, midRes);
555            }
556            Dest = resTemp;
557        ''', flagType="none", buildCc=False)
558    buildRegDataInst("shasx", '''
559            int32_t midRes;
560            resTemp = 0;
561            int64_t arg1Low = sext<16>(bits(Op1_sw, 15, 0));
562            int64_t arg1High = sext<16>(bits(Op1_sw, 31, 16));
563            int64_t arg2Low = sext<16>(bits(Op2_sw, 15, 0));
564            int64_t arg2High = sext<16>(bits(Op2_sw, 31, 16));
565            midRes = (uint64_t)(arg1Low - arg2High) >> 1;
566            replaceBits(resTemp, 15, 0, midRes);
567            midRes = (arg1High + arg2Low) >> 1;
568            replaceBits(resTemp, 31, 16, midRes);
569            Dest = resTemp;
570        ''', flagType="none", buildCc=True)
571    buildRegDataInst("shsax", '''
572            int32_t midRes;
573            resTemp = 0;
574            int64_t arg1Low = sext<16>(bits(Op1_sw, 15, 0));
575            int64_t arg1High = sext<16>(bits(Op1_sw, 31, 16));
576            int64_t arg2Low = sext<16>(bits(Op2_sw, 15, 0));
577            int64_t arg2High = sext<16>(bits(Op2_sw, 31, 16));
578            midRes = (uint64_t)(arg1Low + arg2High) >> 1;
579            replaceBits(resTemp, 15, 0, midRes);
580            midRes = (uint64_t)(arg1High - arg2Low) >> 1;
581            replaceBits(resTemp, 31, 16, midRes);
582            Dest = resTemp;
583        ''', flagType="none", buildCc=True)
584
585    buildRegDataInst("uqadd16", '''
586            uint32_t midRes;
587            for (unsigned i = 0; i < 2; i++) {
588                int high = (i + 1) * 16 - 1;
589                int low = i * 16;
590                uint64_t arg1 = bits(Op1, high, low);
591                uint64_t arg2 = bits(Op2, high, low);
592                uSaturateOp<16>(midRes, arg1, arg2);
593                replaceBits(resTemp, high, low, midRes);
594            }
595            Dest = resTemp;
596        ''', flagType="none", buildCc=False)
597    buildRegDataInst("uqadd8", '''
598            uint32_t midRes;
599            for (unsigned i = 0; i < 4; i++) {
600                int high = (i + 1) * 8 - 1;
601                int low = i * 8;
602                uint64_t arg1 = bits(Op1, high, low);
603                uint64_t arg2 = bits(Op2, high, low);
604                uSaturateOp<8>(midRes, arg1, arg2);
605                replaceBits(resTemp, high, low, midRes);
606            }
607            Dest = resTemp;
608        ''', flagType="none", buildCc=False)
609    buildRegDataInst("uqsub16", '''
610            uint32_t midRes;
611            for (unsigned i = 0; i < 2; i++) {
612                 int high = (i + 1) * 16 - 1;
613                 int low = i * 16;
614                 uint64_t arg1 = bits(Op1, high, low);
615                 uint64_t arg2 = bits(Op2, high, low);
616                 uSaturateOp<16>(midRes, arg1, arg2, true);
617                 replaceBits(resTemp, high, low, midRes);
618            }
619            Dest = resTemp;
620        ''', flagType="none", buildCc=False)
621    buildRegDataInst("uqsub8", '''
622            uint32_t midRes;
623            for (unsigned i = 0; i < 4; i++) {
624                 int high = (i + 1) * 8 - 1;
625                 int low = i * 8;
626                 uint64_t arg1 = bits(Op1, high, low);
627                 uint64_t arg2 = bits(Op2, high, low);
628                 uSaturateOp<8>(midRes, arg1, arg2, true);
629                 replaceBits(resTemp, high, low, midRes);
630            }
631            Dest = resTemp;
632        ''', flagType="none", buildCc=False)
633    buildRegDataInst("uqasx", '''
634            uint32_t midRes;
635            uint64_t arg1Low = bits(Op1_sw, 15, 0);
636            uint64_t arg1High = bits(Op1_sw, 31, 16);
637            uint64_t arg2Low = bits(Op2_sw, 15, 0);
638            uint64_t arg2High = bits(Op2_sw, 31, 16);
639            uSaturateOp<16>(midRes, arg1Low, arg2High, true);
640            replaceBits(resTemp, 15, 0, midRes);
641            uSaturateOp<16>(midRes, arg1High, arg2Low);
642            replaceBits(resTemp, 31, 16, midRes);
643            Dest = resTemp;
644        ''', flagType="none", buildCc=False)
645    buildRegDataInst("uqsax", '''
646            uint32_t midRes;
647            uint64_t arg1Low = bits(Op1_sw, 15, 0);
648            uint64_t arg1High = bits(Op1_sw, 31, 16);
649            uint64_t arg2Low = bits(Op2_sw, 15, 0);
650            uint64_t arg2High = bits(Op2_sw, 31, 16);
651            uSaturateOp<16>(midRes, arg1Low, arg2High);
652            replaceBits(resTemp, 15, 0, midRes);
653            uSaturateOp<16>(midRes, arg1High, arg2Low, true);
654            replaceBits(resTemp, 31, 16, midRes);
655            Dest = resTemp;
656        ''', flagType="none", buildCc=False)
657
658    buildRegDataInst("uadd16", '''
659            uint32_t geBits = 0;
660            resTemp = 0;
661            for (unsigned i = 0; i < 2; i++) {
662                int high = (i + 1) * 16 - 1;
663                int low = i * 16;
664                int32_t midRes = bits(Op1, high, low) +
665                                 bits(Op2, high, low);
666                if (midRes >= 0x10000) {
667                    geBits = geBits | (0x3 << (i * 2));
668                }
669                replaceBits(resTemp, high, low, midRes);
670            }
671            Dest = resTemp;
672            resTemp = geBits;
673        ''', flagType="ge", buildNonCc=False)
674    buildRegDataInst("uadd8", '''
675            uint32_t geBits = 0;
676            resTemp = 0;
677            for (unsigned i = 0; i < 4; i++) {
678                int high = (i + 1) * 8 - 1;
679                int low = i * 8;
680                int32_t midRes = bits(Op1, high, low) +
681                                 bits(Op2, high, low);
682                if (midRes >= 0x100) {
683                    geBits = geBits | (1 << i);
684                }
685                replaceBits(resTemp, high, low, midRes);
686            }
687            Dest = resTemp;
688            resTemp = geBits;
689        ''', flagType="ge", buildNonCc=False)
690    buildRegDataInst("usub16", '''
691            uint32_t geBits = 0;
692            resTemp = 0;
693            for (unsigned i = 0; i < 2; i++) {
694                int high = (i + 1) * 16 - 1;
695                int low = i * 16;
696                int32_t midRes = bits(Op1, high, low) -
697                                 bits(Op2, high, low);
698                if (midRes >= 0) {
699                    geBits = geBits | (0x3 << (i * 2));
700                }
701                replaceBits(resTemp, high, low, midRes);
702            }
703            Dest = resTemp;
704            resTemp = geBits;
705        ''', flagType="ge", buildNonCc=False)
706    buildRegDataInst("usub8", '''
707            uint32_t geBits = 0;
708            resTemp = 0;
709            for (unsigned i = 0; i < 4; i++) {
710                int high = (i + 1) * 8 - 1;
711                int low = i * 8;
712                int32_t midRes = bits(Op1, high, low) -
713                                 bits(Op2, high, low);
714                if (midRes >= 0) {
715                    geBits = geBits | (1 << i);
716                }
717                replaceBits(resTemp, high, low, midRes);
718            }
719            Dest = resTemp;
720            resTemp = geBits;
721        ''', flagType="ge", buildNonCc=False)
722    buildRegDataInst("uasx", '''
723            int32_t midRes, geBits = 0;
724            resTemp = 0;
725            int64_t arg1Low = bits(Op1_sw, 15, 0);
726            int64_t arg1High = bits(Op1_sw, 31, 16);
727            int64_t arg2Low = bits(Op2_sw, 15, 0);
728            int64_t arg2High = bits(Op2_sw, 31, 16);
729            midRes = arg1Low - arg2High;
730            if (midRes >= 0) {
731                geBits = geBits | 0x3;
732            }
733            replaceBits(resTemp, 15, 0, midRes);
734            midRes = arg1High + arg2Low;
735            if (midRes >= 0x10000) {
736                geBits = geBits | 0xc;
737            }
738            replaceBits(resTemp, 31, 16, midRes);
739            Dest = resTemp;
740            resTemp = geBits;
741        ''', flagType="ge", buildNonCc=False)
742    buildRegDataInst("usax", '''
743            int32_t midRes, geBits = 0;
744            resTemp = 0;
745            int64_t arg1Low = bits(Op1_sw, 15, 0);
746            int64_t arg1High = bits(Op1_sw, 31, 16);
747            int64_t arg2Low = bits(Op2_sw, 15, 0);
748            int64_t arg2High = bits(Op2_sw, 31, 16);
749            midRes = arg1Low + arg2High;
750            if (midRes >= 0x10000) {
751                geBits = geBits | 0x3;
752            }
753            replaceBits(resTemp, 15, 0, midRes);
754            midRes = arg1High - arg2Low;
755            if (midRes >= 0) {
756                geBits = geBits | 0xc;
757            }
758            replaceBits(resTemp, 31, 16, midRes);
759            Dest = resTemp;
760            resTemp = geBits;
761        ''', flagType="ge", buildNonCc=False)
762
763    buildRegDataInst("uhadd16", '''
764            resTemp = 0;
765            for (unsigned i = 0; i < 2; i++) {
766                int high = (i + 1) * 16 - 1;
767                int low = i * 16;
768                int32_t midRes = (bits(Op1, high, low) +
769                                  bits(Op2, high, low)) >> 1;
770                replaceBits(resTemp, high, low, midRes);
771            }
772            Dest = resTemp;
773        ''', flagType="none", buildCc=False)
774    buildRegDataInst("uhadd8", '''
775            resTemp = 0;
776            for (unsigned i = 0; i < 4; i++) {
777                int high = (i + 1) * 8 - 1;
778                int low = i * 8;
779                int32_t midRes = (bits(Op1, high, low) +
780                                  bits(Op2, high, low)) >> 1;
781                replaceBits(resTemp, high, low, midRes);
782            }
783            Dest = resTemp;
784        ''', flagType="none", buildCc=False)
785    buildRegDataInst("uhsub16", '''
786            resTemp = 0;
787            for (unsigned i = 0; i < 2; i++) {
788                int high = (i + 1) * 16 - 1;
789                int low = i * 16;
790                int32_t midRes = (bits(Op1, high, low) -
791                                  bits(Op2, high, low)) >> 1;
792                replaceBits(resTemp, high, low, midRes);
793            }
794            Dest = resTemp;
795        ''', flagType="none", buildCc=False)
796    buildRegDataInst("uhsub8", '''
797            resTemp = 0;
798            for (unsigned i = 0; i < 4; i++) {
799                int high = (i + 1) * 8 - 1;
800                int low = i * 8;
801                int32_t midRes = (bits(Op1, high, low) -
802                                  bits(Op2, high, low)) >> 1;
803                replaceBits(resTemp, high, low, midRes);
804            }
805            Dest = resTemp;
806        ''', flagType="none", buildCc=False)
807    buildRegDataInst("uhasx", '''
808            int32_t midRes;
809            resTemp = 0;
810            int64_t arg1Low = bits(Op1_sw, 15, 0);
811            int64_t arg1High = bits(Op1_sw, 31, 16);
812            int64_t arg2Low = bits(Op2_sw, 15, 0);
813            int64_t arg2High = bits(Op2_sw, 31, 16);
814            midRes = (arg1Low - arg2High) >> 1;
815            replaceBits(resTemp, 15, 0, midRes);
816            midRes = (arg1High + arg2Low) >> 1;
817            replaceBits(resTemp, 31, 16, midRes);
818            Dest = resTemp;
819        ''', flagType="none", buildCc=False)
820    buildRegDataInst("uhsax", '''
821            int32_t midRes;
822            resTemp = 0;
823            int64_t arg1Low = bits(Op1_sw, 15, 0);
824            int64_t arg1High = bits(Op1_sw, 31, 16);
825            int64_t arg2Low = bits(Op2_sw, 15, 0);
826            int64_t arg2High = bits(Op2_sw, 31, 16);
827            midRes = (arg1Low + arg2High) >> 1;
828            replaceBits(resTemp, 15, 0, midRes);
829            midRes = (arg1High - arg2Low) >> 1;
830            replaceBits(resTemp, 31, 16, midRes);
831            Dest = resTemp;
832        ''', flagType="none", buildCc=False)
833
834    buildRegDataInst("pkhbt", '''
835            uint32_t resTemp = 0;
836            uint16_t arg1Low = bits(Op1, 15, 0);
837            uint16_t arg2High = bits(secondOp, 31, 16);
838            replaceBits(resTemp, 15, 0, arg1Low);
839            replaceBits(resTemp, 31, 16, arg2High);
840            Dest = resTemp;
841        ''', flagType="none", buildCc=False)
842    buildRegDataInst("pkhtb", '''
843            uint32_t resTemp = 0;
844            uint16_t arg1High = bits(Op1, 31, 16);
845            uint16_t arg2Low = bits(secondOp, 15, 0);
846            replaceBits(resTemp, 15, 0, arg2Low);
847            replaceBits(resTemp, 31, 16, arg1High);
848            Dest = resTemp;
849        ''', flagType="none", buildCc=False)
850}};
851