1// -*- mode:c++ -*-
2
3// Copyright (c) 2010, 2013 ARM Limited
4// All rights reserved
5//
6// The license below extends only to copyright in the software and shall
7// not be construed as granting a license to any other intellectual
8// property including but not limited to intellectual property relating
9// to a hardware implementation of the functionality of the software
10// licensed hereunder.  You may use the software subject to the license
11// terms below provided that you ensure that this notice is replicated
12// unmodified and in its entirety in all distributions of the software,
13// modified or unmodified, in source code or in binary form.
14//
15// Redistribution and use in source and binary forms, with or without
16// modification, are permitted provided that the following conditions are
17// met: redistributions of source code must retain the above copyright
18// notice, this list of conditions and the following disclaimer;
19// redistributions in binary form must reproduce the above copyright
20// notice, this list of conditions and the following disclaimer in the
21// documentation and/or other materials provided with the distribution;
22// neither the name of the copyright holders nor the names of its
23// contributors may be used to endorse or promote products derived from
24// this software without specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Authors: Gabe Black
39
40let {{
41
42    header_output = ""
43    decoder_output = ""
44    exec_output = ""
45
46    calcGECode = '''
47        CondCodesGE = resTemp;
48    '''
49
50    calcQCode = '''
51        CpsrQ = (resTemp & 1) << 27;
52    '''
53
54    def createCcCode(negBit, carry, overflow):
55        code = ""
56        code += '''
57            uint16_t _iz, _in;
58            _in = (resTemp >> %d) & 1;
59            _iz = (resTemp == 0);
60            CondCodesNZ = (_in << 1) | _iz;
61            DPRINTF(Arm, "(in, iz) = (%%d, %%d)\\n", _in, _iz);
62        ''' % negBit
63        if overflow and overflow != "none":
64            code +=  '''
65                uint16_t _iv;
66                _iv = %s & 1;
67                CondCodesV =  _iv;
68                DPRINTF(Arm, "(iv) = (%%d)\\n", _iv);
69            ''' % overflow
70        if carry and carry != "none":
71            code += '''
72                uint16_t _ic;
73                _ic = %s & 1;
74                CondCodesC =  _ic;
75                DPRINTF(Arm, "(ic) = (%%d)\\n", _ic);
76            ''' % carry
77        return code
78
79    # Dict of code to set the carry flag. (imm, reg, reg-reg)
80    oldC = 'CondCodesC'
81    carryCode = {
82        "none": ("none", "none", "none"),
83        "llbit": ("none", "none", "none"),
84        "saturate": ('0', '0', '0'),
85        "overflow": ('0', '0', '0'),
86        "ge": ('0', '0', '0'),
87        "add": ('findCarry(32, resTemp, Op1, secondOp)',
88                'findCarry(32, resTemp, Op1, secondOp)',
89                'findCarry(32, resTemp, Op1, secondOp)'),
90        "sub": ('findCarry(32, resTemp, Op1, ~secondOp)',
91                'findCarry(32, resTemp, Op1, ~secondOp)',
92                'findCarry(32, resTemp, Op1, ~secondOp)'),
93        "rsb": ('findCarry(32, resTemp, secondOp, ~Op1)',
94                'findCarry(32, resTemp, secondOp, ~Op1)',
95                'findCarry(32, resTemp, secondOp, ~Op1)'),
96        "logic": ('(rotC ? bits(secondOp, 31) : %s)' % oldC,
97                  'shift_carry_imm(Op2, shiftAmt, shiftType, %s)' % oldC,
98                  'shift_carry_rs(Op2, Shift<7:0>, shiftType, %s)' % oldC)
99    }
100    # Dict of code to set the overflow flag.
101    overflowCode = {
102        "none": "none",
103        "llbit": "none",
104        "saturate": '0',
105        "overflow": '0',
106        "ge": '0',
107        "add": 'findOverflow(32, resTemp, Op1, secondOp)',
108        "sub": 'findOverflow(32, resTemp, Op1, ~secondOp)',
109        "rsb": 'findOverflow(32, resTemp, secondOp, ~Op1)',
110        "logic": "none"
111    }
112
113    secondOpRe = re.compile("secondOp")
114    immOp2 = "imm"
115    regOp2 = "shift_rm_imm(Op2, shiftAmt, shiftType, OptShiftRmCondCodesC)"
116    regRegOp2 = "shift_rm_rs(Op2, Shift<7:0>, shiftType, 0)"
117
118    def buildImmDataInst(mnem, code, flagType = "logic", suffix = "Imm", \
119                         buildCc = True, buildNonCc = True, isBranch = "0", \
120                         instFlags = []):
121        cCode = carryCode[flagType]
122        vCode = overflowCode[flagType]
123        negBit = 31
124        if flagType == "llbit":
125            negBit = 63
126        if flagType == "saturate":
127            immCcCode = calcQCode
128        elif flagType == "ge":
129            immCcCode = calcGECode
130        else:
131            immCcCode = createCcCode(negBit, secondOpRe.sub(immOp2, cCode[0]),
132                                     secondOpRe.sub(immOp2, vCode))
133
134        immCode = secondOpRe.sub(immOp2, code)
135        immIop = InstObjParams(mnem, mnem.capitalize() + suffix, "DataImmOp",
136                       {"code" : immCode,
137                        "is_branch" : isBranch,
138                        "predicate_test": pickPredicate(immCode)}, instFlags)
139        immIopCc = InstObjParams(mnem + "s", mnem.capitalize() + suffix + "Cc",
140             "DataImmOp",
141             {"code" : immCode + immCcCode,
142              "is_branch" : isBranch,
143              "predicate_test": pickPredicate(immCode + immCcCode)}, instFlags)
144
145        def subst(iop):
146            global header_output, decoder_output, exec_output
147            header_output += DataImmDeclare.subst(iop)
148            decoder_output += DataImmConstructor.subst(iop)
149            exec_output += PredOpExecute.subst(iop)
150
151        if buildNonCc:
152            subst(immIop)
153        if buildCc:
154            subst(immIopCc)
155
156    def buildRegDataInst(mnem, code, flagType = "logic", suffix = "Reg", \
157                         buildCc = True, buildNonCc = True, isRasPop = "0", \
158                         isBranch = "0", instFlags = []):
159        cCode = carryCode[flagType]
160        vCode = overflowCode[flagType]
161        negBit = 31
162        regCcCode = ""
163        if flagType == "llbit":
164            negBit = 63
165        if flagType == "saturate":
166            regCcCode = calcQCode
167        elif flagType == "ge":
168            regCcCode = calcGECode
169        else:
170            regCcCode = createCcCode(negBit,secondOpRe.sub(regOp2, cCode[1]),
171                                     secondOpRe.sub(regOp2, vCode))
172
173        regCode = secondOpRe.sub(regOp2, code)
174
175        # If we end up needing CondCodesC then remove any trace of the OptShift
176        if re.search('(?<!OptShiftRm)CondCodesC(?!.*=)', regCode + regCcCode):
177            regCode = re.sub('OptShiftRmCondCodesC', 'CondCodesC', regCode)
178            regCcCode = re.sub('OptShiftRmCondCodesC', 'CondCodesC', regCcCode)
179
180        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                                          "IsSquashAfter"])
278            buildRegDataInst(mnem + 's', code, flagType,
279                             suffix = "RegPclr", buildCc = False,
280                             instFlags = ["IsSerializeAfter","IsNonSpeculative",
281                                          "IsSquashAfter"])
282
283    buildDataInst("and", "Dest = resTemp = Op1 & secondOp;")
284    buildDataInst("eor", "Dest = resTemp = Op1 ^ secondOp;")
285    buildDataInst("sub", "Dest = resTemp = Op1 - secondOp;", "sub",
286                  isBranch = "dest == INTREG_PC")
287    buildDataInst("rsb", "Dest = resTemp = secondOp - Op1;", "rsb")
288    buildDataInst("add", "Dest = resTemp = Op1 + secondOp;", "add",
289                  isBranch = "dest == INTREG_PC")
290    buildImmDataInst("adr", '''
291                               Dest = resTemp = (PC & ~0x3) +
292                               (op1 ? secondOp : -secondOp);
293                            ''', isBranch = "dest == INTREG_PC")
294    buildDataInst("adc", "Dest = resTemp = Op1 + secondOp + %s;" % oldC, "add")
295    buildDataInst("sbc", "Dest = resTemp = Op1 - secondOp - !%s;" % oldC, "sub")
296    buildDataInst("rsc", "Dest = resTemp = secondOp - Op1 - !%s;" % oldC, "rsb")
297    buildDataInst("tst", "resTemp = Op1 & secondOp;", aiw = False)
298    buildDataInst("teq", "resTemp = Op1 ^ secondOp;", aiw = False)
299    buildDataInst("cmp", "resTemp = Op1 - secondOp;", "sub", aiw = False)
300    buildDataInst("cmn", "resTemp = Op1 + secondOp;", "add", aiw = False)
301    buildDataInst("orr", "Dest = resTemp = Op1 | secondOp;")
302    buildDataInst("orn", "Dest = resTemp = Op1 | ~secondOp;", aiw = False)
303    buildDataInst("mov", "Dest = resTemp = secondOp;", regRegAiw = False,
304                  isRasPop = "op2 == INTREG_LR", isBranch = "dest == INTREG_PC")
305    buildDataInst("bic", "Dest = resTemp = Op1 & ~secondOp;")
306    buildDataInst("mvn", "Dest = resTemp = ~secondOp;")
307    buildDataInst("movt",
308                  "Dest = resTemp = insertBits(Op1, 31, 16, secondOp);",
309                  aiw = False)
310
311    buildRegDataInst("qadd", '''
312            int32_t midRes;
313            resTemp = saturateOp<32>(midRes, Op1_sw, Op2_sw);
314                                     Dest = midRes;
315        ''', flagType="saturate", buildNonCc=False)
316    buildRegDataInst("qadd16", '''
317            int32_t midRes;
318            for (unsigned i = 0; i < 2; i++) {
319                int high = (i + 1) * 16 - 1;
320                int low = i * 16;
321                int64_t arg1 = sext<16>(bits(Op1_sw, high, low));
322                int64_t arg2 = sext<16>(bits(Op2_sw, high, low));
323                saturateOp<16>(midRes, arg1, arg2);
324                replaceBits(resTemp, high, low, midRes);
325            }
326            Dest = resTemp;
327        ''', flagType="none", buildCc=False)
328    buildRegDataInst("qadd8", '''
329            int32_t midRes;
330            for (unsigned i = 0; i < 4; i++) {
331                int high = (i + 1) * 8 - 1;
332                int low = i * 8;
333                int64_t arg1 = sext<8>(bits(Op1_sw, high, low));
334                int64_t arg2 = sext<8>(bits(Op2_sw, high, low));
335                saturateOp<8>(midRes, arg1, arg2);
336                replaceBits(resTemp, high, low, midRes);
337            }
338            Dest = resTemp;
339        ''', flagType="none", buildCc=False)
340    buildRegDataInst("qdadd", '''
341            int32_t midRes;
342            resTemp = saturateOp<32>(midRes, Op2_sw, Op2_sw) |
343                      saturateOp<32>(midRes, Op1_sw, midRes);
344            Dest = midRes;
345        ''', flagType="saturate", buildNonCc=False)
346    buildRegDataInst("qsub", '''
347            int32_t midRes;
348            resTemp = saturateOp<32>(midRes, Op1_sw, Op2_sw, true);
349            Dest = midRes;
350        ''', flagType="saturate")
351    buildRegDataInst("qsub16", '''
352            int32_t midRes;
353            for (unsigned i = 0; i < 2; i++) {
354                 int high = (i + 1) * 16 - 1;
355                 int low = i * 16;
356                 int64_t arg1 = sext<16>(bits(Op1_sw, high, low));
357                 int64_t arg2 = sext<16>(bits(Op2_sw, high, low));
358                 saturateOp<16>(midRes, arg1, arg2, true);
359                 replaceBits(resTemp, high, low, midRes);
360            }
361            Dest = resTemp;
362        ''', flagType="none", buildCc=False)
363    buildRegDataInst("qsub8", '''
364            int32_t midRes;
365            for (unsigned i = 0; i < 4; i++) {
366                 int high = (i + 1) * 8 - 1;
367                 int low = i * 8;
368                 int64_t arg1 = sext<8>(bits(Op1_sw, high, low));
369                 int64_t arg2 = sext<8>(bits(Op2_sw, high, low));
370                 saturateOp<8>(midRes, arg1, arg2, true);
371                 replaceBits(resTemp, high, low, midRes);
372            }
373            Dest = resTemp;
374        ''', flagType="none", buildCc=False)
375    buildRegDataInst("qdsub", '''
376            int32_t midRes;
377            resTemp = saturateOp<32>(midRes, Op2_sw, Op2_sw) |
378                      saturateOp<32>(midRes, Op1_sw, midRes, true);
379            Dest = midRes;
380        ''', flagType="saturate", buildNonCc=False)
381    buildRegDataInst("qasx", '''
382            int32_t midRes;
383            int64_t arg1Low = sext<16>(bits(Op1_sw, 15, 0));
384            int64_t arg1High = sext<16>(bits(Op1_sw, 31, 16));
385            int64_t arg2Low = sext<16>(bits(Op2_sw, 15, 0));
386            int64_t arg2High = sext<16>(bits(Op2_sw, 31, 16));
387            saturateOp<16>(midRes, arg1Low, arg2High, true);
388            replaceBits(resTemp, 15, 0, midRes);
389            saturateOp<16>(midRes, arg1High, arg2Low);
390            replaceBits(resTemp, 31, 16, midRes);
391            Dest = resTemp;
392        ''', flagType="none", buildCc=False)
393    buildRegDataInst("qsax", '''
394            int32_t midRes;
395            int64_t arg1Low = sext<16>(bits(Op1_sw, 15, 0));
396            int64_t arg1High = sext<16>(bits(Op1_sw, 31, 16));
397            int64_t arg2Low = sext<16>(bits(Op2_sw, 15, 0));
398            int64_t arg2High = sext<16>(bits(Op2_sw, 31, 16));
399            saturateOp<16>(midRes, arg1Low, arg2High);
400            replaceBits(resTemp, 15, 0, midRes);
401            saturateOp<16>(midRes, arg1High, arg2Low, true);
402            replaceBits(resTemp, 31, 16, midRes);
403            Dest = resTemp;
404        ''', flagType="none", buildCc=False)
405
406    buildRegDataInst("sadd8", '''
407            uint32_t geBits = 0;
408            resTemp = 0;
409            for (unsigned i = 0; i < 4; i++) {
410                int high = (i + 1) * 8 - 1;
411                int low = i * 8;
412                int32_t midRes = sext<8>(bits(Op1_sw, high, low)) +
413                                 sext<8>(bits(Op2_sw, high, low));
414                replaceBits(resTemp, high, low, midRes);
415                if (midRes >= 0) {
416                    geBits = geBits | (1 << i);
417                }
418            }
419            Dest = resTemp;
420            resTemp = geBits;
421        ''', flagType="ge", buildNonCc=False)
422    buildRegDataInst("sadd16", '''
423            uint32_t geBits = 0;
424            resTemp = 0;
425            for (unsigned i = 0; i < 2; i++) {
426                int high = (i + 1) * 16 - 1;
427                int low = i * 16;
428                int32_t midRes = sext<16>(bits(Op1_sw, high, low)) +
429                                 sext<16>(bits(Op2_sw, high, low));
430                replaceBits(resTemp, high, low, midRes);
431                if (midRes >= 0) {
432                    geBits = geBits | (0x3 << (i * 2));
433                }
434            }
435            Dest = resTemp;
436            resTemp = geBits;
437        ''', flagType="ge", buildNonCc=False)
438
439    buildRegDataInst("ssub8", '''
440            uint32_t geBits = 0;
441            resTemp = 0;
442            for (unsigned i = 0; i < 4; i++) {
443                int high = (i + 1) * 8 - 1;
444                int low = i * 8;
445                int32_t midRes = sext<8>(bits(Op1_sw, high, low)) -
446                                 sext<8>(bits(Op2_sw, high, low));
447                replaceBits(resTemp, high, low, midRes);
448                if (midRes >= 0) {
449                    geBits = geBits | (1 << i);
450                }
451            }
452            Dest = resTemp;
453            resTemp = geBits;
454        ''', flagType="ge", buildNonCc=False)
455    buildRegDataInst("ssub16", '''
456            uint32_t geBits = 0;
457            resTemp = 0;
458            for (unsigned i = 0; i < 2; i++) {
459                int high = (i + 1) * 16 - 1;
460                int low = i * 16;
461                int32_t midRes = sext<16>(bits(Op1_sw, high, low)) -
462                                 sext<16>(bits(Op2_sw, high, low));
463                replaceBits(resTemp, high, low, midRes);
464                if (midRes >= 0) {
465                    geBits = geBits | (0x3 << (i * 2));
466                }
467            }
468            Dest = resTemp;
469            resTemp = geBits;
470        ''', flagType="ge", buildNonCc=False)
471    buildRegDataInst("sasx", '''
472            int32_t midRes, geBits = 0;
473            resTemp = 0;
474            int64_t arg1Low = sext<16>(bits(Op1_sw, 15, 0));
475            int64_t arg1High = sext<16>(bits(Op1_sw, 31, 16));
476            int64_t arg2Low = sext<16>(bits(Op2_sw, 15, 0));
477            int64_t arg2High = sext<16>(bits(Op2_sw, 31, 16));
478            midRes = arg1Low - arg2High;
479            if (midRes >= 0) {
480                geBits = geBits | 0x3;
481            }
482            replaceBits(resTemp, 15, 0, midRes);
483            midRes = arg1High + arg2Low;
484            if (midRes >= 0) {
485                geBits = geBits | 0xc;
486            }
487            replaceBits(resTemp, 31, 16, midRes);
488            Dest = resTemp;
489            resTemp = geBits;
490        ''', flagType="ge", buildNonCc=True)
491    buildRegDataInst("ssax", '''
492            int32_t midRes, geBits = 0;
493            resTemp = 0;
494            int64_t arg1Low = sext<16>(bits(Op1_sw, 15, 0));
495            int64_t arg1High = sext<16>(bits(Op1_sw, 31, 16));
496            int64_t arg2Low = sext<16>(bits(Op2_sw, 15, 0));
497            int64_t arg2High = sext<16>(bits(Op2_sw, 31, 16));
498            midRes = arg1Low + arg2High;
499            if (midRes >= 0) {
500                geBits = geBits | 0x3;
501            }
502            replaceBits(resTemp, 15, 0, midRes);
503            midRes = arg1High - arg2Low;
504            if (midRes >= 0) {
505                geBits = geBits | 0xc;
506            }
507            replaceBits(resTemp, 31, 16, midRes);
508            Dest = resTemp;
509            resTemp = geBits;
510        ''', flagType="ge", buildNonCc=True)
511
512    buildRegDataInst("shadd8", '''
513            resTemp = 0;
514            for (unsigned i = 0; i < 4; i++) {
515                int high = (i + 1) * 8 - 1;
516                int low = i * 8;
517                int32_t midRes =
518                    (uint64_t)(sext<8>(bits(Op1_sw, high, low)) +
519                               sext<8>(bits(Op2_sw, high, low))) >> 1;
520                replaceBits(resTemp, high, low, midRes);
521            }
522            Dest = resTemp;
523        ''', flagType="none", buildCc=False)
524    buildRegDataInst("shadd16", '''
525            resTemp = 0;
526            for (unsigned i = 0; i < 2; i++) {
527                int high = (i + 1) * 16 - 1;
528                int low = i * 16;
529                int32_t midRes =
530                    (uint64_t)(sext<16>(bits(Op1_sw, high, low)) +
531                               sext<16>(bits(Op2_sw, high, low))) >> 1;
532                replaceBits(resTemp, high, low, midRes);
533            }
534            Dest = resTemp;
535        ''', flagType="none", buildCc=False)
536    buildRegDataInst("shsub8", '''
537            resTemp = 0;
538            for (unsigned i = 0; i < 4; i++) {
539                int high = (i + 1) * 8 - 1;
540                int low = i * 8;
541                int32_t midRes =
542                    (uint64_t)(sext<8>(bits(Op1_sw, high, low)) -
543                               sext<8>(bits(Op2_sw, high, low))) >> 1;
544                replaceBits(resTemp, high, low, midRes);
545            }
546            Dest = resTemp;
547        ''', flagType="none", buildCc=False)
548    buildRegDataInst("shsub16", '''
549            resTemp = 0;
550            for (unsigned i = 0; i < 2; i++) {
551                int high = (i + 1) * 16 - 1;
552                int low = i * 16;
553                int32_t midRes =
554                    (uint64_t)(sext<16>(bits(Op1_sw, high, low)) -
555                               sext<16>(bits(Op2_sw, high, low))) >> 1;
556                replaceBits(resTemp, high, low, midRes);
557            }
558            Dest = resTemp;
559        ''', flagType="none", buildCc=False)
560    buildRegDataInst("shasx", '''
561            int32_t midRes;
562            resTemp = 0;
563            int64_t arg1Low = sext<16>(bits(Op1_sw, 15, 0));
564            int64_t arg1High = sext<16>(bits(Op1_sw, 31, 16));
565            int64_t arg2Low = sext<16>(bits(Op2_sw, 15, 0));
566            int64_t arg2High = sext<16>(bits(Op2_sw, 31, 16));
567            midRes = (uint64_t)(arg1Low - arg2High) >> 1;
568            replaceBits(resTemp, 15, 0, midRes);
569            midRes = (arg1High + arg2Low) >> 1;
570            replaceBits(resTemp, 31, 16, midRes);
571            Dest = resTemp;
572        ''', flagType="none", buildCc=True)
573    buildRegDataInst("shsax", '''
574            int32_t midRes;
575            resTemp = 0;
576            int64_t arg1Low = sext<16>(bits(Op1_sw, 15, 0));
577            int64_t arg1High = sext<16>(bits(Op1_sw, 31, 16));
578            int64_t arg2Low = sext<16>(bits(Op2_sw, 15, 0));
579            int64_t arg2High = sext<16>(bits(Op2_sw, 31, 16));
580            midRes = (uint64_t)(arg1Low + arg2High) >> 1;
581            replaceBits(resTemp, 15, 0, midRes);
582            midRes = (uint64_t)(arg1High - arg2Low) >> 1;
583            replaceBits(resTemp, 31, 16, midRes);
584            Dest = resTemp;
585        ''', flagType="none", buildCc=True)
586
587    buildRegDataInst("uqadd16", '''
588            uint32_t midRes;
589            for (unsigned i = 0; i < 2; i++) {
590                int high = (i + 1) * 16 - 1;
591                int low = i * 16;
592                uint64_t arg1 = bits(Op1, high, low);
593                uint64_t arg2 = bits(Op2, high, low);
594                uSaturateOp<16>(midRes, arg1, arg2);
595                replaceBits(resTemp, high, low, midRes);
596            }
597            Dest = resTemp;
598        ''', flagType="none", buildCc=False)
599    buildRegDataInst("uqadd8", '''
600            uint32_t midRes;
601            for (unsigned i = 0; i < 4; i++) {
602                int high = (i + 1) * 8 - 1;
603                int low = i * 8;
604                uint64_t arg1 = bits(Op1, high, low);
605                uint64_t arg2 = bits(Op2, high, low);
606                uSaturateOp<8>(midRes, arg1, arg2);
607                replaceBits(resTemp, high, low, midRes);
608            }
609            Dest = resTemp;
610        ''', flagType="none", buildCc=False)
611    buildRegDataInst("uqsub16", '''
612            uint32_t midRes;
613            for (unsigned i = 0; i < 2; i++) {
614                 int high = (i + 1) * 16 - 1;
615                 int low = i * 16;
616                 uint64_t arg1 = bits(Op1, high, low);
617                 uint64_t arg2 = bits(Op2, high, low);
618                 uSaturateOp<16>(midRes, arg1, arg2, true);
619                 replaceBits(resTemp, high, low, midRes);
620            }
621            Dest = resTemp;
622        ''', flagType="none", buildCc=False)
623    buildRegDataInst("uqsub8", '''
624            uint32_t midRes;
625            for (unsigned i = 0; i < 4; i++) {
626                 int high = (i + 1) * 8 - 1;
627                 int low = i * 8;
628                 uint64_t arg1 = bits(Op1, high, low);
629                 uint64_t arg2 = bits(Op2, high, low);
630                 uSaturateOp<8>(midRes, arg1, arg2, true);
631                 replaceBits(resTemp, high, low, midRes);
632            }
633            Dest = resTemp;
634        ''', flagType="none", buildCc=False)
635    buildRegDataInst("uqasx", '''
636            uint32_t midRes;
637            uint64_t arg1Low = bits(Op1_sw, 15, 0);
638            uint64_t arg1High = bits(Op1_sw, 31, 16);
639            uint64_t arg2Low = bits(Op2_sw, 15, 0);
640            uint64_t arg2High = bits(Op2_sw, 31, 16);
641            uSaturateOp<16>(midRes, arg1Low, arg2High, true);
642            replaceBits(resTemp, 15, 0, midRes);
643            uSaturateOp<16>(midRes, arg1High, arg2Low);
644            replaceBits(resTemp, 31, 16, midRes);
645            Dest = resTemp;
646        ''', flagType="none", buildCc=False)
647    buildRegDataInst("uqsax", '''
648            uint32_t midRes;
649            uint64_t arg1Low = bits(Op1_sw, 15, 0);
650            uint64_t arg1High = bits(Op1_sw, 31, 16);
651            uint64_t arg2Low = bits(Op2_sw, 15, 0);
652            uint64_t arg2High = bits(Op2_sw, 31, 16);
653            uSaturateOp<16>(midRes, arg1Low, arg2High);
654            replaceBits(resTemp, 15, 0, midRes);
655            uSaturateOp<16>(midRes, arg1High, arg2Low, true);
656            replaceBits(resTemp, 31, 16, midRes);
657            Dest = resTemp;
658        ''', flagType="none", buildCc=False)
659
660    buildRegDataInst("uadd16", '''
661            uint32_t geBits = 0;
662            resTemp = 0;
663            for (unsigned i = 0; i < 2; i++) {
664                int high = (i + 1) * 16 - 1;
665                int low = i * 16;
666                int32_t midRes = bits(Op1, high, low) +
667                                 bits(Op2, high, low);
668                if (midRes >= 0x10000) {
669                    geBits = geBits | (0x3 << (i * 2));
670                }
671                replaceBits(resTemp, high, low, midRes);
672            }
673            Dest = resTemp;
674            resTemp = geBits;
675        ''', flagType="ge", buildNonCc=False)
676    buildRegDataInst("uadd8", '''
677            uint32_t geBits = 0;
678            resTemp = 0;
679            for (unsigned i = 0; i < 4; i++) {
680                int high = (i + 1) * 8 - 1;
681                int low = i * 8;
682                int32_t midRes = bits(Op1, high, low) +
683                                 bits(Op2, high, low);
684                if (midRes >= 0x100) {
685                    geBits = geBits | (1 << i);
686                }
687                replaceBits(resTemp, high, low, midRes);
688            }
689            Dest = resTemp;
690            resTemp = geBits;
691        ''', flagType="ge", buildNonCc=False)
692    buildRegDataInst("usub16", '''
693            uint32_t geBits = 0;
694            resTemp = 0;
695            for (unsigned i = 0; i < 2; i++) {
696                int high = (i + 1) * 16 - 1;
697                int low = i * 16;
698                int32_t midRes = bits(Op1, high, low) -
699                                 bits(Op2, high, low);
700                if (midRes >= 0) {
701                    geBits = geBits | (0x3 << (i * 2));
702                }
703                replaceBits(resTemp, high, low, midRes);
704            }
705            Dest = resTemp;
706            resTemp = geBits;
707        ''', flagType="ge", buildNonCc=False)
708    buildRegDataInst("usub8", '''
709            uint32_t geBits = 0;
710            resTemp = 0;
711            for (unsigned i = 0; i < 4; i++) {
712                int high = (i + 1) * 8 - 1;
713                int low = i * 8;
714                int32_t midRes = bits(Op1, high, low) -
715                                 bits(Op2, high, low);
716                if (midRes >= 0) {
717                    geBits = geBits | (1 << i);
718                }
719                replaceBits(resTemp, high, low, midRes);
720            }
721            Dest = resTemp;
722            resTemp = geBits;
723        ''', flagType="ge", buildNonCc=False)
724    buildRegDataInst("uasx", '''
725            int32_t midRes, geBits = 0;
726            resTemp = 0;
727            int64_t arg1Low = bits(Op1_sw, 15, 0);
728            int64_t arg1High = bits(Op1_sw, 31, 16);
729            int64_t arg2Low = bits(Op2_sw, 15, 0);
730            int64_t arg2High = bits(Op2_sw, 31, 16);
731            midRes = arg1Low - arg2High;
732            if (midRes >= 0) {
733                geBits = geBits | 0x3;
734            }
735            replaceBits(resTemp, 15, 0, midRes);
736            midRes = arg1High + arg2Low;
737            if (midRes >= 0x10000) {
738                geBits = geBits | 0xc;
739            }
740            replaceBits(resTemp, 31, 16, midRes);
741            Dest = resTemp;
742            resTemp = geBits;
743        ''', flagType="ge", buildNonCc=False)
744    buildRegDataInst("usax", '''
745            int32_t midRes, geBits = 0;
746            resTemp = 0;
747            int64_t arg1Low = bits(Op1_sw, 15, 0);
748            int64_t arg1High = bits(Op1_sw, 31, 16);
749            int64_t arg2Low = bits(Op2_sw, 15, 0);
750            int64_t arg2High = bits(Op2_sw, 31, 16);
751            midRes = arg1Low + arg2High;
752            if (midRes >= 0x10000) {
753                geBits = geBits | 0x3;
754            }
755            replaceBits(resTemp, 15, 0, midRes);
756            midRes = arg1High - arg2Low;
757            if (midRes >= 0) {
758                geBits = geBits | 0xc;
759            }
760            replaceBits(resTemp, 31, 16, midRes);
761            Dest = resTemp;
762            resTemp = geBits;
763        ''', flagType="ge", buildNonCc=False)
764
765    buildRegDataInst("uhadd16", '''
766            resTemp = 0;
767            for (unsigned i = 0; i < 2; i++) {
768                int high = (i + 1) * 16 - 1;
769                int low = i * 16;
770                int32_t midRes = (bits(Op1, high, low) +
771                                  bits(Op2, high, low)) >> 1;
772                replaceBits(resTemp, high, low, midRes);
773            }
774            Dest = resTemp;
775        ''', flagType="none", buildCc=False)
776    buildRegDataInst("uhadd8", '''
777            resTemp = 0;
778            for (unsigned i = 0; i < 4; i++) {
779                int high = (i + 1) * 8 - 1;
780                int low = i * 8;
781                int32_t midRes = (bits(Op1, high, low) +
782                                  bits(Op2, high, low)) >> 1;
783                replaceBits(resTemp, high, low, midRes);
784            }
785            Dest = resTemp;
786        ''', flagType="none", buildCc=False)
787    buildRegDataInst("uhsub16", '''
788            resTemp = 0;
789            for (unsigned i = 0; i < 2; i++) {
790                int high = (i + 1) * 16 - 1;
791                int low = i * 16;
792                int32_t midRes = (bits(Op1, high, low) -
793                                  bits(Op2, high, low)) >> 1;
794                replaceBits(resTemp, high, low, midRes);
795            }
796            Dest = resTemp;
797        ''', flagType="none", buildCc=False)
798    buildRegDataInst("uhsub8", '''
799            resTemp = 0;
800            for (unsigned i = 0; i < 4; i++) {
801                int high = (i + 1) * 8 - 1;
802                int low = i * 8;
803                int32_t midRes = (bits(Op1, high, low) -
804                                  bits(Op2, high, low)) >> 1;
805                replaceBits(resTemp, high, low, midRes);
806            }
807            Dest = resTemp;
808        ''', flagType="none", buildCc=False)
809    buildRegDataInst("uhasx", '''
810            int32_t midRes;
811            resTemp = 0;
812            int64_t arg1Low = bits(Op1_sw, 15, 0);
813            int64_t arg1High = bits(Op1_sw, 31, 16);
814            int64_t arg2Low = bits(Op2_sw, 15, 0);
815            int64_t arg2High = bits(Op2_sw, 31, 16);
816            midRes = (arg1Low - arg2High) >> 1;
817            replaceBits(resTemp, 15, 0, midRes);
818            midRes = (arg1High + arg2Low) >> 1;
819            replaceBits(resTemp, 31, 16, midRes);
820            Dest = resTemp;
821        ''', flagType="none", buildCc=False)
822    buildRegDataInst("uhsax", '''
823            int32_t midRes;
824            resTemp = 0;
825            int64_t arg1Low = bits(Op1_sw, 15, 0);
826            int64_t arg1High = bits(Op1_sw, 31, 16);
827            int64_t arg2Low = bits(Op2_sw, 15, 0);
828            int64_t arg2High = bits(Op2_sw, 31, 16);
829            midRes = (arg1Low + arg2High) >> 1;
830            replaceBits(resTemp, 15, 0, midRes);
831            midRes = (arg1High - arg2Low) >> 1;
832            replaceBits(resTemp, 31, 16, midRes);
833            Dest = resTemp;
834        ''', flagType="none", buildCc=False)
835
836    buildRegDataInst("pkhbt", '''
837            uint32_t resTemp = 0;
838            uint16_t arg1Low = bits(Op1, 15, 0);
839            uint16_t arg2High = bits(secondOp, 31, 16);
840            replaceBits(resTemp, 15, 0, arg1Low);
841            replaceBits(resTemp, 31, 16, arg2High);
842            Dest = resTemp;
843        ''', flagType="none", buildCc=False)
844    buildRegDataInst("pkhtb", '''
845            uint32_t resTemp = 0;
846            uint16_t arg1High = bits(Op1, 31, 16);
847            uint16_t arg2Low = bits(secondOp, 15, 0);
848            replaceBits(resTemp, 15, 0, arg2Low);
849            replaceBits(resTemp, 31, 16, arg1High);
850            Dest = resTemp;
851        ''', flagType="none", buildCc=False)
852}};
853