Merge branch 'master' into att_syntax
[dyninst.git] / instructionAPI / src / InstructionDecoder-aarch64.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  *
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  *
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  *
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  *
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  *
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 #include "InstructionDecoder-aarch64.h"
32 #include <boost/assign/list_of.hpp>
33 #include "../../common/src/singleton_object_pool.h"
34
35 namespace Dyninst {
36     namespace InstructionAPI {
37         typedef void (InstructionDecoder_aarch64::*operandFactory)();
38
39         typedef std::vector<operandFactory> operandSpec;
40         typedef std::vector<aarch64_insn_entry> aarch64_insn_table;
41         typedef std::map<unsigned int, aarch64_mask_entry> aarch64_decoder_table;
42         typedef std::map<unsigned int, unsigned int> branchMap;
43         typedef uint32_t Bits_t;
44
45         std::vector<std::string> InstructionDecoder_aarch64::condStringMap;
46         std::map<unsigned int, MachRegister> InstructionDecoder_aarch64::sysRegMap;
47         std::map<entryID, std::string> InstructionDecoder_aarch64::bitfieldInsnAliasMap = boost::assign::map_list_of(
48                 aarch64_op_bfi_bfm, "bfi")(aarch64_op_bfxil_bfm, "bfxil")(aarch64_op_sbfiz_sbfm, "sbfiz")(
49                 aarch64_op_sbfx_sbfm, "sbfx")(aarch64_op_ubfiz_ubfm, "ubfiz")(aarch64_op_ubfx_ubfm, "ubfx")(
50                 aarch64_op_sxtb_sbfm, "sxtb")(aarch64_op_sxth_sbfm, "sxth")(aarch64_op_sxtw_sbfm, "sxtw")(
51                 aarch64_op_uxtb_ubfm, "uxtb")(aarch64_op_uxth_ubfm, "uxth")(aarch64_op_lsl_ubfm, "lsl")(aarch64_op_lsr_ubfm, "lsr");
52         std::map<entryID, std::string> InstructionDecoder_aarch64::condInsnAliasMap = boost::assign::map_list_of(aarch64_op_csinc, "csinc")(aarch64_op_csinv, "csinv")(aarch64_op_csneg, "csneg")
53                 (aarch64_op_cinc_csinc, "cinc")(aarch64_op_cset_csinc, "cset")
54                 (aarch64_op_cinv_csinv, "cinv")(aarch64_op_csetm_csinv, "csetm")
55                 (aarch64_op_cneg_csneg, "cneg");
56
57         struct aarch64_insn_entry {
58             aarch64_insn_entry(entryID o, const char *m, operandSpec ops) :
59                     op(o), mnemonic(m), operands(ops) {
60             }
61
62             aarch64_insn_entry(entryID o, const char *m, operandSpec ops, Bits_t enb, Bits_t mb) :
63                     op(o), mnemonic(m), operands(ops), _encodingBits(enb), _maskBits(mb) {
64             }
65
66             aarch64_insn_entry() :
67                     op(aarch64_op_INVALID), mnemonic("INVALID") {
68                 operands.reserve(5);
69             }
70
71             aarch64_insn_entry(const aarch64_insn_entry &o) :
72                     op(o.op), mnemonic(o.mnemonic), operands(o.operands),
73                     _encodingBits(o._encodingBits), _maskBits(o._maskBits) {
74             }
75
76             const aarch64_insn_entry &operator=(const aarch64_insn_entry &rhs) {
77                 operands.reserve(rhs.operands.size());
78                 op = rhs.op;
79                 mnemonic = rhs.mnemonic;
80                 operands = rhs.operands;
81                 _encodingBits = rhs._encodingBits;
82                 _maskBits = rhs._maskBits;
83
84                 return *this;
85             }
86
87             entryID op;
88             const char *mnemonic;
89             operandSpec operands;
90
91             Bits_t _encodingBits;
92             Bits_t _maskBits;
93
94             static void buildInsnTable();
95
96             static bool built_insn_table;
97
98             static aarch64_insn_table main_insn_table;
99         };
100
101         struct aarch64_mask_entry {
102             aarch64_mask_entry(unsigned int m, branchMap bm, int tabIndex) :
103                     mask(m), nodeBranches(bm), insnTableIndices(std::vector<int>()), insnTableIndex(tabIndex) {
104             }
105
106             aarch64_mask_entry(unsigned int m, branchMap bm, std::vector<int> tabIndices) :
107                     mask(m), nodeBranches(bm), insnTableIndices(tabIndices), insnTableIndex(0) {
108             }
109
110             aarch64_mask_entry() :
111                     mask(0), nodeBranches(branchMap()), insnTableIndices(std::vector<int>()), insnTableIndex(0) {
112             }
113
114             aarch64_mask_entry(const aarch64_mask_entry &e) :
115                     mask(e.mask), nodeBranches(e.nodeBranches), insnTableIndices(e.insnTableIndices),
116                     insnTableIndex(e.insnTableIndex) {
117             }
118
119             const aarch64_mask_entry &operator=(const aarch64_mask_entry &rhs) {
120                 mask = rhs.mask;
121                 nodeBranches = rhs.nodeBranches;
122                 insnTableIndices = rhs.insnTableIndices;
123                 insnTableIndex = rhs.insnTableIndex;
124
125                 return *this;
126             }
127
128             unsigned int mask;
129             branchMap nodeBranches;
130             std::vector<int> insnTableIndices;
131             int insnTableIndex;
132
133             static void buildDecoderTable();
134
135             static bool built_decoder_table;
136             static bool isAliasWeakSolution;
137             static aarch64_decoder_table main_decoder_table;
138         };
139
140         InstructionDecoder_aarch64::InstructionDecoder_aarch64(Architecture a)
141                 : InstructionDecoderImpl(a), isPstateRead(false), isPstateWritten(false), isFPInsn(false),
142                   isSIMDInsn(false), skipRn(false), skipRm(false),
143                   is64Bit(true), isValid(true), insn(0), insn_in_progress(NULL),
144                   hasHw(false), hasShift(false), hasOption(false), hasN(false),
145                   immr(0), immrLen(0), sField(0), nField(0), nLen(0),
146                   immlo(0), immloLen(0), _szField(-1), size(-1),
147                   cmode(0), op(0), simdAlphabetImm(0), _Q(1) {
148             aarch64_insn_entry::buildInsnTable();
149             aarch64_mask_entry::buildDecoderTable();
150             InstructionDecoder_aarch64::buildSysRegMap();
151
152             std::string condArray[16] = {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", "hi", "ls", "ge", "lt", "gt",
153                                          "le", "al", "nv"};
154             InstructionDecoder_aarch64::condStringMap.assign(&condArray[0], &condArray[0] + 16);
155             //InstructionDecoder_aarch64::bitfieldInsnAliasMap = boost::assign::map_list_of(aarch64_op_bfi_bfm, "bfi")(aarch64_op_bfxil_bfm, "bfxil")(aarch64_op_sbfiz_sbfm, "sbfiz")(aarch64_op_sbfx_sbfm, "sbfx")(aarch64_op_ubfiz_ubfm, "ubfiz")(aarch64_op_ubfx_ubfm, "ubfx");
156         }
157
158         InstructionDecoder_aarch64::~InstructionDecoder_aarch64() {
159         }
160
161         void InstructionDecoder_aarch64::decodeOpcode(InstructionDecoder::buffer &b) {
162             b.start += 4;
163         }
164
165         using namespace std;
166
167         Instruction::Ptr InstructionDecoder_aarch64::decode(InstructionDecoder::buffer &b) {
168             if (b.start > b.end)
169                 return Instruction::Ptr();
170
171             isPstateRead = isPstateWritten = false;
172             isFPInsn = false;
173             isSIMDInsn = false;
174             skipRm = skipRn = false;
175             isValid = true;
176             is64Bit = true;
177
178             hasHw = false;
179             hwField = 0;
180
181             hasShift = false;
182             shiftField = 0;
183
184             hasOption = false;
185             optionField = 0;
186
187             hasN = false;
188             sField = nField = nLen = 0;
189             immr = immrLen = 0;
190
191             op1Field = op2Field = crmField = 0;
192
193             immlo = immloLen = 0;
194
195             _szField = size = -1;
196             _Q = 1;
197
198             cmode = op = simdAlphabetImm = 0;
199
200             oprRotateAmt = 0;
201             hasb5 = false;
202
203             insn = b.start[3] << 24 | b.start[2] << 16 |
204                    b.start[1] << 8 | b.start[0];
205
206 #if defined(DEBUG_RAW_INSN)
207                                                                                                                                     cout.width(0);
208         cout << "0x";
209         cout.width(8);
210         cout.fill('0');
211         cout << hex << insn << "\t";
212 #endif
213
214             mainDecode();
215             b.start += 4;
216
217             return make_shared(insn_in_progress);
218         }
219
220         /* replace this function with a more generic function, which is setRegWidth
221     void InstructionDecoder_aarch64::set32Mode()
222     {
223         // NOTE: is64Bit is set by default.
224                 is64Bit = false;
225     }
226     */
227         void InstructionDecoder_aarch64::NOTHING() {
228         }
229
230         void InstructionDecoder_aarch64::setFPMode() {
231             // NOTE: if it is fp, only isFP is set.
232             isFPInsn = true;
233         }
234
235         //TODO: consistency issue
236         void InstructionDecoder_aarch64::setSIMDMode() {
237             // NOTE: if it is SIMD insn, both isFP and isSIMD are set.
238             //isFPInsn = true;
239             isSIMDInsn = true;
240         }
241
242         template<unsigned int endBit, unsigned int startBit>
243         void InstructionDecoder_aarch64::OPRtype() {
244             _typeField = field<startBit, endBit>(insn);
245         }
246
247         void InstructionDecoder_aarch64::processHwFieldInsn(int len, int val) {
248             Result_Type rT = is64Bit ? u64 : u32;
249
250             unsigned int shiftAmount = hwField * 16;
251
252             Expression::Ptr lhs = Immediate::makeImmediate(
253                     Result(rT, rT == u32 ? unsign_extend32(len, val) : unsign_extend64(len, val)));
254             Expression::Ptr rhs = Immediate::makeImmediate(Result(u32, unsign_extend32(6, shiftAmount)));
255
256             insn_in_progress->appendOperand(makeLeftShiftExpression(lhs, rhs, rT), true, false);
257         }
258
259         void InstructionDecoder_aarch64::processShiftFieldShiftedInsn(int len, int val) {
260             Result_Type rT;
261             Expression::Ptr lhs, rhs;
262
263             rT = is64Bit ? u64 : u32;
264
265             lhs = makeRmExpr();
266             rhs = Immediate::makeImmediate(Result(u32, unsign_extend32(len, val)));
267
268             switch (shiftField)                                            //add-sub (shifted) and logical (shifted)
269             {
270                 case 0:
271                     insn_in_progress->appendOperand(makeLeftShiftExpression(lhs, rhs, rT), true, false);
272                     break;
273                 case 1:
274                     insn_in_progress->appendOperand(makeRightLogicalShiftExpression(lhs, rhs, rT), true, false);
275                     break;
276                 case 2:
277                     insn_in_progress->appendOperand(makeRightArithmeticShiftExpression(lhs, rhs, rT), true, false);
278                     break;
279                 case 3:
280                     if (IS_INSN_LOGICAL_SHIFT(
281                             insn))                    //logical (shifted) -- not applicable to add-sub (shifted)
282                         insn_in_progress->appendOperand(makeRightRotateExpression(lhs, rhs, rT), true, false);
283                     else
284                         isValid = false;
285                     break;
286             }
287         }
288
289         void InstructionDecoder_aarch64::processShiftFieldImmInsn(int len, int val) {
290             if (shiftField == 0 || shiftField == 1)                        //add-sub (immediate)
291             {
292                 Result_Type rT = is64Bit ? u64 : u32;
293
294                 unsigned int shiftAmount = shiftField * 12;
295
296                 Expression::Ptr lhs = Immediate::makeImmediate(
297                         Result(rT, rT == u32 ? unsign_extend32(len, val) : unsign_extend64(len, val)));
298                 Expression::Ptr rhs = Immediate::makeImmediate(Result(u32, unsign_extend32(4, shiftAmount)));
299
300                 insn_in_progress->appendOperand(makeLeftShiftExpression(lhs, rhs, rT), true, false);
301             }
302             else {
303                 isValid = false;
304             }
305
306         }
307
308         Expression::Ptr InstructionDecoder_aarch64::makeOptionExpression(int len, int val) {
309             MachRegister reg;
310             int encoding = field<16, 20>(insn);
311
312             reg = ((optionField & 0x3) == 0x3) ? ((encoding == 31) ? aarch64::xzr : aarch64::x0) : ((encoding == 31)
313                                                                                                    ? aarch64::wzr
314                                                                                                    : aarch64::w0);
315             if (encoding != 31)
316                 reg = makeAarch64RegID(reg, encoding);
317
318             Expression::Ptr lhs;
319
320             switch (optionField) {
321                 case 0:
322                     lhs = makeRegisterExpression(reg, u8);
323                     break;
324                 case 1:
325                     lhs = makeRegisterExpression(reg, u16);
326                     break;
327                 case 2:
328                     lhs = makeRegisterExpression(reg, u32);
329                     break;
330                 case 3:
331                     lhs = makeRegisterExpression(reg, u64);
332                     break;
333                 case 4:
334                     lhs = makeRegisterExpression(reg, s8);
335                     break;
336                 case 5:
337                     lhs = makeRegisterExpression(reg, s16);
338                     break;
339                 case 6:
340                     lhs = makeRegisterExpression(reg, s32);
341                     break;
342                 case 7:
343                     lhs = makeRegisterExpression(reg, s64);
344                     break;
345                 default:
346                     isValid = false;   //invalid option field
347             }
348
349             Result_Type rT = is64Bit ? (optionField < 4 ? u64 : s64) : (optionField < 4 ? u32 : s32);
350
351             return makeLeftShiftExpression(lhs, Immediate::makeImmediate(Result(u32, unsign_extend32(len, val))), rT);
352         }
353
354         void InstructionDecoder_aarch64::processOptionFieldLSRegOffsetInsn() {
355             if (optionField == 0x3)            //option = LSL
356             {
357                 int sizeVal = field<30, 31>(insn), extend;
358
359                 if (field<23, 23>(insn) == 1)
360                     sizeVal = 4;
361
362                 extend = sField * sizeVal;
363                 int extendSize = 31;
364                 while (extendSize >= 0 && ((extend << (31 - extendSize)) & 0x80000000) == 0)
365                     extendSize--;
366
367                 //above values need to be used in a dereference expression
368             }
369             else {
370                 //sign-extend
371                 switch (optionField) {
372                     case 0x2://UXTW
373                         break;
374                     case 0x6://SXTW
375                         break;
376                     case 0x7://SXTX
377                         break;
378                     default:
379                         isValid = false;
380                         break;
381                 }
382             }
383         }
384
385         void InstructionDecoder_aarch64::processSystemInsn() {
386             int op0Field = field<19, 20>(insn), crnField = field<12, 15>(insn);
387
388             if (op0Field == 0) {
389                 if (crnField == 3)            //clrex, dendBit, dmb, iendBit
390                 {
391                     Expression::Ptr CRm = Immediate::makeImmediate(Result(u8, unsign_extend32(4, crmField)));
392
393                     insn_in_progress->appendOperand(CRm, true, false);
394                 }
395                 else if (crnField == 2)                    //hint
396                 {
397                     int immVal = (crmField << 3) | (op2Field & 7);
398
399                     Expression::Ptr imm = Immediate::makeImmediate(Result(u8, unsign_extend32(7, immVal)));
400
401                     insn_in_progress->appendOperand(imm, true, false);
402                 }
403                 else if (crnField == 4)                //msr (immediate)
404                 {
405                     int pstatefield = (op1Field << 3) | (op2Field & 7);
406                     insn_in_progress->appendOperand(
407                             Immediate::makeImmediate(Result(u8, unsign_extend32(6, pstatefield))), true, false);
408
409                     insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, unsign_extend32(4, crmField))),
410                                                     true, false);
411                     isPstateWritten = true;
412                 }
413                 else {
414                     isValid = false;
415                 }
416             }
417             else if (op0Field == 1)                  //sys, sysl
418             {
419                 insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, unsign_extend32(3, op1Field))),
420                                                 true, false);
421                 insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, unsign_extend32(4, crnField))),
422                                                 true, false);
423                 insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, unsign_extend32(4, crmField))),
424                                                 true, false);
425                 insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, unsign_extend32(3, op2Field))),
426                                                 true, false);
427
428                 bool isRtRead = (field<21, 21>(insn) == 0);
429                 insn_in_progress->appendOperand(makeRtExpr(), isRtRead, !isRtRead);
430             }
431             else                   //mrs (register), msr
432             {
433                 bool isRtRead = (field<21, 21>(insn) == 0);
434
435                 unsigned int systemRegEncoding =
436                         (op0Field << 14) | (op1Field << 11) | (crnField << 7) | (crmField << 3) | op2Field;
437                 if (InstructionDecoder_aarch64::sysRegMap.count(systemRegEncoding) <= 0)
438                     assert(!"tried to access system register not accessible in EL0");
439
440                 MachRegister reg;
441                 if ((op0Field & 0x3) == 0x3 && (crnField & 0x3) == 0x3 && (crnField & 0x8) == 0x8)
442                     reg = aarch64::IMPLEMENTATION_DEFINED_SYSREG;
443                 else
444                     reg = InstructionDecoder_aarch64::sysRegMap[systemRegEncoding];
445                 insn_in_progress->appendOperand(makeRegisterExpression(reg), !isRtRead, isRtRead);
446                 insn_in_progress->appendOperand(makeRtExpr(), isRtRead, !isRtRead);
447                 if (!isRtRead)
448                     insn_in_progress->m_Operands.reverse();
449             }
450         }
451
452         Result_Type InstructionDecoder_aarch64::makeSizeType(unsigned int) {
453             assert(0); //not implemented
454             return u32;
455         }
456
457         // ****************
458         // decoding opcodes
459         // ****************
460
461 #define fn(x) (&InstructionDecoder_aarch64::x)
462 #define    COMMA    ,
463
464         MachRegister InstructionDecoder_aarch64::makeAarch64RegID(MachRegister base, unsigned int encoding) {
465             return MachRegister(base.val() + encoding);
466         }
467
468         template<unsigned int endBit, unsigned int startBit>
469         void InstructionDecoder_aarch64::OPRsize() {
470             size = field<startBit, endBit>(insn);
471
472             entryID insnID = insn_in_progress->getOperation().operationID;
473             if((insnID == aarch64_op_pmull_advsimd && (size == 0x1 || size == 0x2)) ||
474                (IS_INSN_SIMD_3DIFF(insn) && size == 0x3) ||
475                ((insnID == aarch64_op_sqdmull_advsimd_vec || insnID == aarch64_op_sqdmlal_advsimd_vec || insnID == aarch64_op_sqdmlsl_advsimd_vec)
476                  && size == 0)) {
477                 isValid = false;
478             }
479         }
480
481         Expression::Ptr InstructionDecoder_aarch64::makeRdExpr() {
482             int encoding = field<0, 4>(insn);
483             MachRegister reg;
484
485             if (isSIMDInsn) {
486                 if (IS_INSN_SIMD_ACROSS(insn)) {
487                     //fmaxnmv, fmaxv, fminnmv, fminv
488                     if (field<14, 14>(insn) == 0x1) {
489                         if (_szField == 0x0)
490                             reg = aarch64::s0;
491                         else
492                             isValid = false;
493                     }
494                     else {
495                         int opcode = field<12, 16>(insn);
496
497                         //saddlv and uaddlv with opcode field 0x03 use different sets of registers
498                         switch (size) {
499                             case 0x0:
500                                 reg = (opcode == 0x03) ? aarch64::h0 : aarch64::b0;
501                                 break;
502                             case 0x1:
503                                 reg = (opcode == 0x03) ? aarch64::s0 : aarch64::h0;
504                                 break;
505                             case 0x2:
506                                 reg = (opcode == 0x03) ? aarch64::d0 : aarch64::s0;
507                                 break;
508                             default:
509                                 isValid = false;
510                         }
511                     }
512                 }
513                 else if (IS_INSN_SIMD_COPY(insn)) {
514                     unsigned int op = field<29, 29>(insn);
515                     unsigned int imm4 = field<11, 14>(insn);
516
517                     if (op == 0x1)
518                         reg = aarch64::q0;
519                     else {
520                         switch (imm4) {
521                             case 0x5:
522                             case 0x7:
523                                 reg = _Q == 0x1 ? aarch64::x0 : aarch64::w0;
524                                 break;
525                             default:
526                                 reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
527                                 break;
528                         }
529                     }
530                 }
531                 else if (IS_INSN_SCALAR_COPY(insn) || IS_INSN_SCALAR_SHIFT_IMM(insn)) {
532                     int switchbit;
533
534                     if (IS_INSN_SCALAR_COPY(insn))
535                         switchbit = lowest_set_bit(field<16, 20>(insn));
536                     else
537                         switchbit = highest_set_bit(field<19, 22>(insn));
538
539                     switch (switchbit) {
540                         case 0x1:
541                             reg = aarch64::b0;
542                             break;
543                         case 0x2:
544                             reg = aarch64::h0;
545                             break;
546                         case 0x3:
547                             reg = aarch64::s0;
548                             break;
549                         case 0x4:
550                             reg = aarch64::d0;
551                             break;
552                         default:
553                             isValid = false;
554                     }
555                 }
556                 else if (IS_INSN_SCALAR_3DIFF(insn)) {
557                     switch (size) {
558                         case 0x1:
559                             reg = aarch64::s0;
560                             break;
561                         case 0x2:
562                             reg = aarch64::d0;
563                             break;
564                         default:
565                             isValid = false;
566                     }
567                 }
568                 else if (IS_INSN_SCALAR_INDEX(insn)) {
569                     int opcode = field<12, 15>(insn);
570
571                     //sqdmlal, sqdmlsl, sqdmull
572                     if ((opcode & 0x3) == 0x3) {
573                         switch (size) {
574                             case 0x1:
575                                 reg = aarch64::s0;
576                                 break;
577                             case 0x2:
578                                 reg = aarch64::d0;
579                                 break;
580                             default:
581                                 isValid = false;
582                         }
583                     }
584                         //sqdmulh, sqrdmulh
585                     else if ((opcode & 0xC) == 0xC) {
586                         switch (size) {
587                             case 0x1:
588                                 reg = aarch64::h0;
589                                 break;
590                             case 0x2:
591                                 reg = aarch64::s0;
592                                 break;
593                             default:
594                                 isValid = false;
595                         }
596                     }
597                         //fmla, fmls, fmul, fmulx
598                     else if ((opcode & 0x3) == 0x1) {
599                         switch (_szField) {
600                             case 0x0:
601                                 reg = aarch64::s0;
602                                 break;
603                             case 0x1:
604                                 reg = aarch64::d0;
605                                 break;
606                             default:
607                                 isValid = false;
608                         }
609                     }
610                     else
611                         isValid = false;
612                 }
613                 else if (IS_INSN_SCALAR_2REG_MISC(insn) || IS_INSN_SCALAR_3SAME(insn)) {
614                     //some instructions in this set rely on sz for choosing the register and some on size
615                     //only one of them is set for an instruction, however
616                     if (_szField == -1) {
617                         switch (size) {
618                             case 0x0:
619                                 reg = aarch64::b0;
620                                 break;
621                             case 0x1:
622                                 reg = aarch64::h0;
623                                 break;
624                             case 0x2:
625                                 reg = aarch64::s0;
626                                 break;
627                             case 0x3:
628                                 reg = aarch64::d0;
629                                 break;
630                             default:
631                                 isValid = false;
632                         }
633                     }
634                     else {
635                         switch (_szField) {
636                             case 0x0:
637                                 reg = aarch64::s0;
638                                 break;
639                             case 0x1: {
640                                 entryID op = insn_in_progress->getOperation().operationID;
641                                 reg = (op == aarch64_op_fcvtxn_advsimd) ? aarch64::s0 : aarch64::d0;
642                             }
643                                 break;
644                             default:
645                                 isValid = false;
646                         }
647                     }
648                 }
649                 else if (IS_INSN_SCALAR_PAIR(insn)) {
650                     if (size != -1) {
651                         if (size == 0x3)
652                             reg = aarch64::d0;
653                         else
654                             isValid = false;
655                     }
656                     else if (_szField != -1) {
657                         switch (_szField) {
658                             case 0x0:
659                                 reg = aarch64::s0;
660                                 break;
661                             case 0x1:
662                                 reg = aarch64::d0;
663                                 break;
664                         }
665                     }
666                     else
667                         isValid = false;
668                 }
669                 else if (IS_INSN_SIMD_MOD_IMM(insn) && _Q == 0 && op == 1 && cmode == 0xE) {
670                     reg = aarch64::d0;
671                 }
672                 else if (IS_INSN_SIMD_VEC_INDEX(insn)) {
673                     if (field<13, 13>(insn) == 0x1)
674                         reg = aarch64::q0;
675                     else
676                         reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
677                 }
678                 else if (IS_INSN_SIMD_3DIFF(insn)) {
679                     entryID op = insn_in_progress->getOperation().operationID;
680
681                     if (op == aarch64_op_addhn_advsimd || op == aarch64_op_subhn_advsimd ||
682                         op == aarch64_op_raddhn_advsimd || op == aarch64_op_rsubhn_advsimd)
683                         reg = _Q == 0x1 ? aarch64::hq0 : aarch64::d0;
684                     else
685                         reg = aarch64::q0;
686                 }
687                     // 3SAME, 2REG_MISC, EXTRACT
688                 else
689                     reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
690
691                 reg = makeAarch64RegID(reg, encoding);
692             }
693             else if (isFPInsn && !((IS_INSN_FP_CONV_FIX(insn) || (IS_INSN_FP_CONV_INT(insn))) && !IS_SOURCE_GP(insn))) {
694                 if (IS_INSN_FP_DATAPROC_ONESRC(insn)) {
695                     int opc = field<15, 16>(insn);
696                     switch (opc) {
697                         case 0:
698                             reg = aarch64::s0;
699                             break;
700                         case 1:
701                             reg = aarch64::d0;
702                             break;
703                         case 3:
704                             reg = aarch64::h0;
705                             break;
706                         default:
707                             isValid = false;
708                     }
709                 }
710                 else
711                     reg = isSinglePrec() ? aarch64::s0 : aarch64::d0;
712
713                 reg = makeAarch64RegID(reg, encoding);
714             }
715             else {
716                 if (encoding == 31)
717                     reg = ((IS_INSN_ADDSUB_IMM(insn) || IS_INSN_ADDSUB_EXT(insn) || IS_INSN_LOGICAL_IMM(insn)) &&
718                            !isPstateWritten) ? (is64Bit ? aarch64::sp : aarch64::wsp) : (is64Bit ? aarch64::xzr
719                                                                                                  : aarch64::wzr);
720                 else
721                     reg = is64Bit ? aarch64::x0 : aarch64::w0;
722
723                 if (isValid && encoding != 31)
724                     reg = makeAarch64RegID(reg, encoding);
725             }
726
727             return makeRegisterExpression(reg);
728         }
729
730         void InstructionDecoder_aarch64::OPRRd() {
731             Expression::Ptr reg = makeRdExpr();
732             int cmode = field<12, 15>(insn);
733
734             bool isRdRead = false;
735             if (((IS_INSN_SIMD_VEC_INDEX(insn) || IS_INSN_SCALAR_INDEX(insn)) && !(cmode & 0x8)) ||
736                 (IS_INSN_SIMD_MOD_IMM(insn) &&
737                  (((cmode & 0x8) && !(cmode & 0x4) && (cmode & 0x1)) ||
738                   (!(cmode & 0x8) && (cmode & 0x1)))))
739                 isRdRead = true;
740             //for SIMD/Scalar vector indexed set, some instructions read Rd and some don't. This can be determined from the highest bit of the opcode field (bit 15)
741             insn_in_progress->appendOperand(reg, isRdRead, true);
742         }
743
744         void InstructionDecoder_aarch64::OPRcmode() {
745             cmode = field<12, 15>(insn);
746         }
747
748         void InstructionDecoder_aarch64::OPRop() {
749             op = field<29, 29>(insn);
750         }
751
752         void InstructionDecoder_aarch64::OPRa() {
753             simdAlphabetImm |= (simdAlphabetImm & 0x7F) | (field<18, 18>(insn) << 7);
754         }
755
756         void InstructionDecoder_aarch64::OPRb() {
757             simdAlphabetImm |= (simdAlphabetImm & 0xBF) | (field<17, 17>(insn) << 6);
758         }
759
760         void InstructionDecoder_aarch64::OPRc() {
761             simdAlphabetImm |= (simdAlphabetImm & 0xDF) | (field<16, 16>(insn) << 5);
762         }
763
764         void InstructionDecoder_aarch64::OPRd() {
765             simdAlphabetImm |= (simdAlphabetImm & 0xEF) | (field<9, 9>(insn) << 4);
766         }
767
768         void InstructionDecoder_aarch64::OPRe() {
769             simdAlphabetImm |= (simdAlphabetImm & 0xF7) | (field<8, 8>(insn) << 3);
770         }
771
772         void InstructionDecoder_aarch64::OPRf() {
773             simdAlphabetImm |= (simdAlphabetImm & 0xFB) | (field<7, 7>(insn) << 2);
774         }
775
776         void InstructionDecoder_aarch64::OPRg() {
777             simdAlphabetImm |= (simdAlphabetImm & 0xFD) | (field<6, 6>(insn) << 1);
778         }
779
780         void InstructionDecoder_aarch64::OPRh() {
781             simdAlphabetImm |= (simdAlphabetImm & 0xFE) | (field<5, 5>(insn));
782         }
783
784         void InstructionDecoder_aarch64::OPRlen() {
785             //reuse immlo
786             immlo = field<13, 14>(insn);
787         }
788
789         Expression::Ptr InstructionDecoder_aarch64::makeRnExpr() {
790             int encoding = field<5, 9>(insn);
791             MachRegister reg;
792
793             if (isSIMDInsn && !IS_INSN_LDST(insn)) {
794                 if (IS_INSN_SIMD_COPY(insn)) {
795                     unsigned int op = field<29, 29>(insn);
796                     unsigned int imm4 = field<11, 14>(insn);
797                     unsigned int imm5 = field<16, 20>(insn);
798
799                     //ins (element)
800                     if (op == 0x1) {
801                         reg = (imm4 & 0x8) ? aarch64::q0 : aarch64::d0;
802                     }
803                     else {
804                         switch (imm4) {
805                             //dup (element), smov, umov
806                             case 0x0:
807                             case 0x5:
808                             case 0x7:
809                                 reg = (imm5 & 0x10) ? aarch64::q0 : aarch64::d0;
810                                 break;
811                                 //dup (general), ins (general)
812                             case 0x1:
813                             case 0x3:
814                                 if (imm5 & 0x1 || imm5 & 0x2 || imm5 & 0x4) {
815                                     reg = encoding == 31 ? aarch64::wzr : aarch64::w0;
816                                 }
817                                 else {
818                                     reg = encoding == 31 ? aarch64::xzr : aarch64::x0;
819                                 }
820                                 break;
821                             default:
822                                 isValid = false;
823                                 break;
824                         }
825                     }
826                 }
827                 else if (IS_INSN_SCALAR_COPY(insn)) {
828                     int imm5 = field<16, 20>(insn);
829
830                     reg = (imm5 & 0x10) ? aarch64::q0 : aarch64::d0;
831                 }
832                 else if (IS_INSN_SCALAR_PAIR(insn)) {
833                     if (size != -1) {
834                         if (size == 0x3)
835                             reg = aarch64::q0;
836                         else
837                             isValid = false;
838                     }
839                     else if (_szField != -1) {
840                         switch (_szField) {
841                             case 0x0:
842                                 reg = aarch64::d0;
843                                 break;
844                             case 0x1:
845                                 reg = aarch64::q0;
846                                 break;
847                         }
848                     }
849                     else
850                         isValid = false;
851                 }
852                 else if (IS_INSN_SCALAR_SHIFT_IMM(insn)) {
853                     int switchbit = highest_set_bit(field<19, 22>(insn));
854                     bool isRnVa = false;
855                     int opcode = field<11, 15>(insn);
856
857                     if ((opcode & 0x1C) == 0x10)
858                         isRnVa = true;
859
860                     switch (switchbit) {
861                         case 0x1:
862                             reg = isRnVa ? aarch64::h0 : aarch64::b0;
863                             break;
864                         case 0x2:
865                             reg = isRnVa ? aarch64::s0 : aarch64::h0;
866                             break;
867                         case 0x3:
868                             reg = isRnVa ? aarch64::d0 : aarch64::s0;
869                             break;
870                         case 0x4:
871                             isRnVa ? (isValid = false) : (reg = aarch64::d0);
872                             break;
873                         default:
874                             isValid = false;
875                     }
876                 }
877                 else if (IS_INSN_SCALAR_3DIFF(insn)) {
878                     switch (size) {
879                         case 0x1:
880                             reg = aarch64::h0;
881                             break;
882                         case 0x2:
883                             reg = aarch64::s0;
884                             break;
885                         default:
886                             isValid = false;
887                     }
888                 }
889                 else if (IS_INSN_SCALAR_INDEX(insn)) {
890                     int opcode = field<12, 15>(insn);
891
892                     //sqdmlal, sqdmlsl, sqdmull
893                     //sqdmulh, sqrdmulh
894                     if ((opcode & 0xC) == 0xC || (opcode & 0x3) == 0x3) {
895                         switch (size) {
896                             case 0x1:
897                                 reg = aarch64::h0;
898                                 break;
899                             case 0x2:
900                                 reg = aarch64::s0;
901                                 break;
902                             default:
903                                 isValid = false;
904                         }
905                     }
906                         //fmla, fmls, fmul, fmulx
907                     else if ((opcode & 0x3) == 0x1) {
908                         switch (_szField) {
909                             case 0x0:
910                                 reg = aarch64::s0;
911                                 break;
912                             case 0x1:
913                                 reg = aarch64::d0;
914                                 break;
915                             default:
916                                 isValid = false;
917                         }
918                     }
919                     else
920                         isValid = false;
921                 }
922                 else if (IS_INSN_SCALAR_2REG_MISC(insn) || IS_INSN_SCALAR_3SAME(insn)) {
923                     //some instructions in this set rely on sz for choosing the register and some on size
924                     //only one of them is set for an instruction, however
925                     bool isRnVa = false;
926                     int opcode = field<12, 16>(insn);
927                     if (!IS_INSN_SCALAR_3SAME(insn) && (opcode & 0x18) == 0x10 && (opcode & 0x1) == 0x0)
928                         isRnVa = true;
929
930                     if (_szField == -1) {
931                         switch (size) {
932                             case 0x0:
933                                 reg = isRnVa ? aarch64::h0 : aarch64::b0;
934                                 break;
935                             case 0x1:
936                                 reg = isRnVa ? aarch64::s0 : aarch64::h0;
937                                 break;
938                             case 0x2:
939                                 reg = isRnVa ? aarch64::d0 : aarch64::s0;
940                                 break;
941                             case 0x3:
942                                 isRnVa ? (isValid = false) : (reg = aarch64::d0);
943                                 break;
944                             default:
945                                 isValid = false;
946                         }
947                     }
948                     else {
949                         switch (_szField) {
950                             case 0x0:
951                                 isRnVa ? (isValid = false) : (reg = aarch64::s0);
952                                 break;
953                             case 0x1:
954                                 reg = aarch64::d0;
955                                 break;
956                             default:
957                                 isValid = false;
958                         }
959                     }
960                 }
961                 else if (IS_INSN_SIMD_VEC_INDEX(insn)) {
962                     //the below two conditions can easily be combined into one, but would be difficult to understand
963                     if (field<13, 13>(insn) == 0x1)
964                         reg = _Q == 0x1 ? aarch64::hq0 : aarch64::d0;
965                     else
966                         //sqdmulh, mul, sqrdmulh, fmla, fmls, fmul, mla, mls, fmulx
967                         reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
968                 }
969                 else if (IS_INSN_SIMD_TAB_LOOKUP(insn)) {
970                     reg = _Q == 1 ? aarch64::q0 : aarch64::d0;
971
972                     for (int reg_index = immlo; reg_index > 0; reg_index--) {
973                         insn_in_progress->appendOperand(
974                                 makeRegisterExpression(makeAarch64RegID(reg, (encoding + reg_index) % 32)), true,
975                                 false);
976                     }
977                 }
978                 else if (IS_INSN_SIMD_3DIFF(insn)) {
979                     entryID op = insn_in_progress->getOperation().operationID;
980
981                     if (op == aarch64_op_saddw_advsimd || op == aarch64_op_ssubw_advsimd ||
982                         op == aarch64_op_addhn_advsimd || op == aarch64_op_subhn_advsimd ||
983                         op == aarch64_op_uaddw_advsimd || op == aarch64_op_usubw_advsimd ||
984                         op == aarch64_op_raddhn_advsimd || op == aarch64_op_rsubhn_advsimd)
985                         reg = aarch64::q0;
986                     else
987                         reg = _Q == 0x1 ? aarch64::hq0 : aarch64::d0;
988                 }
989                 else
990                     reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
991
992                 if (!(reg == aarch64::wzr || reg == aarch64::xzr))
993                     reg = makeAarch64RegID(reg, encoding);
994             }
995             else if (isFPInsn && !((IS_INSN_FP_CONV_FIX(insn) || (IS_INSN_FP_CONV_INT(insn))) && IS_SOURCE_GP(insn))) {
996                 switch (_typeField) {
997                     case 0:
998                         reg = aarch64::s0;
999                         break;
1000                     case 1:
1001                         reg = aarch64::d0;
1002                         break;
1003                     case 3:
1004                         reg = aarch64::h0;
1005                         break;
1006                     default:
1007                         isValid = false;
1008                 }
1009
1010                 reg = makeAarch64RegID(reg, encoding);
1011             }
1012             else if (IS_INSN_LDST(insn)) {
1013                 reg = encoding == 31 ? aarch64::sp : aarch64::x0;
1014
1015                 if (encoding != 31)
1016                     reg = makeAarch64RegID(reg, encoding);
1017             }
1018             else {
1019                 if (encoding == 31)
1020                     reg = (IS_INSN_ADDSUB_IMM(insn) || IS_INSN_ADDSUB_EXT(insn)) ? (is64Bit ? aarch64::sp
1021                                                                                             : aarch64::wsp) : (is64Bit
1022                                                                                                                ? aarch64::xzr
1023                                                                                                                : aarch64::wzr);
1024                 else
1025                     reg = is64Bit ? aarch64::x0 : aarch64::w0;
1026
1027                 if (isValid && encoding != 31)
1028                     reg = makeAarch64RegID(reg, encoding);
1029             }
1030
1031             return makeRegisterExpression(reg);
1032         }
1033
1034         Expression::Ptr InstructionDecoder_aarch64::makePCExpr() {
1035             MachRegister baseReg = aarch64::pc;
1036
1037             return makeRegisterExpression(makeAarch64RegID(baseReg, 0));
1038         }
1039
1040         Expression::Ptr InstructionDecoder_aarch64::makePstateExpr() {
1041             MachRegister baseReg = aarch64::pstate;
1042
1043             return makeRegisterExpression(makeAarch64RegID(baseReg, 0));
1044         }
1045
1046
1047         void InstructionDecoder_aarch64::getMemRefIndexLiteral_OffsetLen(int &immVal, int &immLen) {
1048             immVal = field<5, 23>(insn);
1049             immVal = immVal << 2; //immVal:00
1050             immLen = (23 - 5 + 1) + 2;
1051             return;
1052         }
1053
1054         void InstructionDecoder_aarch64::getMemRefIndexLiteral_RT(Result_Type &rt) {
1055             int size = field<30, 31>(insn);
1056             switch (size) {
1057                 case 0x0:
1058                     rt = u32;
1059                     break;
1060                 case 0x1:
1061                     rt = u64;
1062                     break;
1063                 case 0x2:
1064                     rt = s32;
1065                     break;
1066                 case 0x3:
1067                     break;
1068                 default:
1069                     isValid = false;
1070                     break;
1071             }
1072         }
1073
1074 // ****************************************
1075 // load/store literal
1076 // eg: load Xt, <literal>
1077 // => offset = signextend(<literal>:00, 64)
1078 // load from [PC + offset] to Xt
1079 // ****************************************
1080         Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexLiteral() {
1081             int immVal, immLen;
1082             getMemRefIndexLiteral_OffsetLen(immVal, immLen);
1083
1084             Expression::Ptr label = Immediate::makeImmediate(Result(s64, sign_extend64(immLen, immVal)));
1085
1086             Result_Type rt = invalid_type;
1087             getMemRefIndexLiteral_RT(rt);
1088
1089             return makeDereferenceExpression(makeAddExpression(makePCExpr(), label, u64), rt);
1090         }
1091
1092 // TODO potential bug: do we need to distinguish signed and unsigned here?
1093 // this funciton is to get the mem ref size
1094 // shared by ld/st uimm, post, pre, reg
1095         void InstructionDecoder_aarch64::getMemRefIndex_RT(Result_Type &rt) {
1096             unsigned int opc1 = field<23, 23>(insn);
1097             unsigned int size = field<30, 31>(insn);
1098
1099             if (opc1 == 1) {
1100                 switch (size) {
1101                     case 0:
1102                         rt = s8;
1103                         break;
1104                     case 1:
1105                         rt = s16;
1106                         break;
1107                     case 2:
1108                         rt = s32;
1109                         break;
1110                     case 3:
1111                         rt = s64;
1112                         break;
1113                     default:
1114                         isValid = false;
1115                         //should only be 2 or 3
1116                         break;
1117                 }
1118             }
1119             else {
1120                 switch (size) {
1121                     case 0:
1122                         rt = u8;
1123                         break;
1124                     case 1:
1125                         rt = u16;
1126                         break;
1127                     case 2:
1128                         rt = u32;
1129                         break;
1130                     case 3:
1131                         rt = u64;
1132                         break;
1133                     default:
1134                         isValid = false;
1135                         //should only be 2 or 3
1136                         break;
1137                 }
1138             }
1139         }
1140
1141         void InstructionDecoder_aarch64::getMemRefPair_RT(Result_Type &rt) {
1142             unsigned int isSigned = field<30, 30>(insn);
1143             unsigned int size = field<31, 31>(insn);
1144
1145             // double the width
1146             switch (isSigned) {
1147                 case 0:
1148                     switch (size) {
1149                         case 0:
1150                             //rt = u32;
1151                             rt = u64;
1152                             break;
1153                         case 1:
1154                             //rt = u64;
1155                             rt = dbl128;
1156                             break;
1157                         default:
1158                             isValid = false;
1159                     }
1160                     break;
1161                 case 1:
1162                     switch (size) {
1163                         case 0:
1164                             //rt = s32;
1165                             rt = s64;
1166                             break;
1167                         case 1:
1168                         default:
1169                             isValid = false;
1170                     }
1171                     break;
1172                 default:
1173                     isValid = false;
1174                     break;
1175             }
1176         }
1177
1178         void InstructionDecoder_aarch64::getMemRefIndex_SizeSizelen(unsigned int &size, unsigned int &sizeLen) {
1179             size = field<30, 31>(insn);
1180             if (isSIMDInsn && size == 0x0 && field<23, 23>(insn) == 0x1)
1181                 size = 4;
1182             sizeLen = 31 - 30 + 1 + (size / 4);
1183             return;
1184         }
1185
1186         void InstructionDecoder_aarch64::getMemRefIndexPrePost_ImmImmlen(unsigned int &immVal, unsigned int &immLen) {
1187             immVal = field<12, 20>(insn);
1188             immLen = 20 - 12 + 1;
1189             return;
1190         }
1191
1192         void InstructionDecoder_aarch64::getMemRefPair_ImmImmlen(unsigned int &immVal, unsigned int &immLen) {
1193             immVal = field<15, 21>(insn);
1194             immLen = 21 - 15 + 1;
1195             return;
1196         }
1197
1198 // ****************************************
1199 // load/store unsigned imm
1200 // eg: load Xt, [Xn, #imm]
1201 // => offset = unsignextend( imm , 64)
1202 // load from [PC + offset] to Xt
1203 // ****************************************
1204         Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexUImm() {
1205             assert(IS_INSN_LDST_UIMM(insn));
1206
1207             int immVal = field<10, 21>(insn);
1208             int immLen = 21 - 10 + 1;
1209
1210             unsigned int size = 0, sizeLen = 0;
1211             getMemRefIndex_SizeSizelen(size, sizeLen);
1212
1213             Expression::Ptr offset = Immediate::makeImmediate(
1214                     Result(u64, unsign_extend64(immLen + size, immVal << size)));
1215
1216             Result_Type rt;
1217             getMemRefIndex_RT(rt);
1218             return makeDereferenceExpression(makeAddExpression(makeRnExpr(), offset, u64), rt);
1219         }
1220
1221         Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndex_offset9() {
1222             unsigned int immVal = 0, immLen = 0;
1223             getMemRefIndexPrePost_ImmImmlen(immVal, immLen);
1224             return Immediate::makeImmediate(Result(u32, sign_extend32(immLen, immVal)));
1225         }
1226
1227 // scale = 2 + opc<1>
1228 // scale = 1<<scale
1229 // LSL(sign_ex(imm7 , 64), scale)
1230         Expression::Ptr InstructionDecoder_aarch64::makeMemRefPair_offset7() {
1231             /*
1232     unsigned int scaleVal = field<31, 31>(insn);
1233     unsigned int scaleLen = 8;
1234     scaleVal += 2;
1235     Expression::Ptr scale = Immediate::makeImmediate(Result(u32, unsign_extend32(scaleLen, 1<<scaleVal)));
1236     */
1237
1238             unsigned int immVal = 0, immLen = 0;
1239             getMemRefPair_ImmImmlen(immVal, immLen);
1240
1241             int scale = 2;
1242             if (isSIMDInsn)
1243                 scale += field<30, 31>(insn);
1244             else
1245                 scale += field<31, 31>(insn);
1246
1247             //return makeMultiplyExpression(imm7, scale, s64);
1248             return Immediate::makeImmediate(Result(u32, immVal << scale));
1249         }
1250
1251         Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndex_addOffset9() {
1252             Expression::Ptr offset = makeMemRefIndex_offset9();
1253             return makeAddExpression(makeRnExpr(), offset, u64);
1254         }
1255
1256         Expression::Ptr InstructionDecoder_aarch64::makeMemRefPair_addOffset7() {
1257             Expression::Ptr offset = makeMemRefPair_offset7();
1258             return makeAddExpression(makeRnExpr(), offset, u64);
1259         }
1260
1261         Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexPre() {
1262             Result_Type rt;
1263             getMemRefIndex_RT(rt);
1264             return makeDereferenceExpression(makeMemRefIndex_addOffset9(), rt);
1265         }
1266
1267         Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexPost() {
1268             Result_Type rt;
1269             getMemRefIndex_RT(rt);
1270             return makeDereferenceExpression(makeRnExpr(), rt);
1271         }
1272
1273         Expression::Ptr InstructionDecoder_aarch64::makeMemRefPairPre() {
1274             Result_Type rt;
1275             getMemRefPair_RT(rt);
1276             return makeDereferenceExpression(makeMemRefPair_addOffset7(), rt);
1277         }
1278
1279         Expression::Ptr InstructionDecoder_aarch64::makeMemRefPairPost() {
1280             Result_Type rt;
1281             getMemRefPair_RT(rt);
1282
1283             return makeDereferenceExpression(makeRnExpr(), rt);
1284         }
1285
1286         void InstructionDecoder_aarch64::getMemRefEx_RT(Result_Type &rt) {
1287             unsigned int sz = field<30, 31>(insn);
1288             switch (sz) {
1289                 case 0x00: //B
1290                     rt = u8;
1291                     break;
1292                 case 0x01: //H
1293                     rt = u16;
1294                     break;
1295                 case 0x02: //32b
1296                     rt = u32;
1297                     break;
1298                 case 0x03: //64b
1299                     rt = u64;
1300                     break;
1301                 default:
1302                     rt = u64;
1303             }
1304         }
1305
1306         Expression::Ptr InstructionDecoder_aarch64::makeMemRefEx() {
1307             Result_Type rt;
1308             getMemRefEx_RT(rt);
1309             return makeDereferenceExpression(makeRnExpr(), rt);
1310         }
1311
1312         void InstructionDecoder_aarch64::OPRQ() {
1313             _Q = field<30, 30>(insn);
1314         }
1315
1316         void InstructionDecoder_aarch64::OPRL() {
1317             _L = field<30, 30>(insn);
1318         }
1319
1320         unsigned int InstructionDecoder_aarch64::getMemRefSIMD_MULT_T() {
1321             unsigned int Q = field<30, 30>(insn);
1322             return Q ? 128 : 64;
1323         }
1324
1325         void InstructionDecoder_aarch64::getMemRefSIMD_MULT_RT(Result_Type &rt) {
1326             unsigned int tmpSize = getMemRefSIMD_MULT_T();
1327             unsigned int rpt = 0, selem = 0;
1328             getSIMD_MULT_RptSelem(rpt, selem);
1329             tmpSize = tmpSize * rpt * selem;
1330             switch (tmpSize) {
1331                 case 64:
1332                     rt = u64;
1333                     return;
1334                 case 128:
1335                     rt = dbl128;
1336                     return;
1337                 case 192:
1338                     rt = m192;
1339                     return;
1340                 case 256:
1341                     rt = m256;
1342                     return;
1343                 case 384:
1344                     rt = m384;
1345                     return;
1346                 case 512:
1347                     rt = m512;
1348                     return;
1349                 default:
1350                     isValid = false;
1351                     return;
1352             }
1353         }
1354
1355         unsigned int InstructionDecoder_aarch64::getSIMD_SING_selem() {
1356             return (((field<13, 13>(insn) << 1) & 0x2) | (field<21, 21>(insn) & 0x1)) + 0x1;
1357         }
1358
1359         void InstructionDecoder_aarch64::getMemRefSIMD_SING_RT(Result_Type &rt) {
1360             unsigned int tmpSize = getMemRefSIMD_SING_T();
1361             unsigned int selem = getSIMD_SING_selem();
1362             switch (selem * tmpSize) {
1363                 case 8:
1364                     rt = u8;
1365                     break;
1366                 case 16:
1367                     rt = u16;
1368                     break;
1369                 case 24:
1370                     rt = u24;
1371                     break;
1372                 case 32:
1373                     rt = u32;
1374                     break;
1375                 case 48:
1376                     rt = u48;
1377                     break;
1378                 case 64:
1379                     rt = u64;
1380                     break;
1381                 case 96:
1382                     rt = m96;
1383                     break;
1384                 case 128:
1385                     rt = dbl128;
1386                     break;
1387                 case 192:
1388                     rt = m192;
1389                     break;
1390                 case 256:
1391                     rt = m256;
1392                     break;
1393                 default:
1394                     isValid = false;
1395                     break;
1396             }
1397         }
1398
1399         unsigned int InstructionDecoder_aarch64::getMemRefSIMD_SING_T() {
1400             unsigned int opcode = field<14, 15>(insn);
1401             unsigned int S = field<12, 12>(insn);
1402             unsigned int size = field<10, 11>(insn);
1403
1404             switch (opcode) {
1405                 case 0x0:
1406                     return 8;
1407                 case 0x1:
1408                     if ((size & 0x1) == 0x0)
1409                         return 16;
1410                     else
1411                         isValid = false;
1412                     break;
1413                 case 0x2:
1414                     if (size == 0x0)
1415                         return 32;
1416                     else if (size == 0x1 && S == 0)
1417                         return 64;
1418                     else
1419                         isValid = false;
1420                     break;
1421                 case 0x3:
1422                     return 8 << size;
1423                 default:
1424                     isValid = false;
1425             }
1426
1427             return 0;
1428         }
1429
1430         Expression::Ptr InstructionDecoder_aarch64::makeMemRefSIMD_MULT() {
1431             Result_Type rt = invalid_type;
1432             getMemRefSIMD_MULT_RT(rt);
1433             return makeDereferenceExpression(makeRnExpr(), rt);
1434         }
1435
1436         Expression::Ptr InstructionDecoder_aarch64::makeMemRefSIMD_SING() {
1437             Result_Type rt = invalid_type;
1438             getMemRefSIMD_SING_RT(rt);
1439             return makeDereferenceExpression(makeRnExpr(), rt);
1440         }
1441
1442         void InstructionDecoder_aarch64::getMemRefExPair_RT(Result_Type &rt) {
1443             int size = field<30, 30>(insn);
1444             switch (size) {
1445                 case 0:
1446                     rt = u64;
1447                     break;
1448                 case 1:
1449                     rt = dbl128;
1450                     break;
1451                 default:
1452                     isValid = false;
1453                     break;
1454             }
1455         }
1456
1457         Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair() {
1458             Result_Type rt;
1459             getMemRefExPair_RT(rt);
1460             return makeDereferenceExpression(makeRnExpr(), rt);
1461         }
1462
1463 /*
1464 Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair16B(){
1465     return makeDereferenceExpression(makeRnExpr(), dbl128);
1466 }
1467 */
1468
1469 /*
1470 Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair2(){
1471     unsigned int immLen = 4, immVal = 8;
1472     Expression::Ptr offset = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));
1473     return makeDereferenceExpression(makeAddExpression(makeRnExpr(), offset, u64) , u64);
1474 }
1475 */
1476
1477         Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_Rm() {
1478             unsigned int option = field<13, 15>(insn);
1479             if ((option & 2) != 2)
1480                 isValid = false;
1481             MachRegister baseReg = ((option & 0x3) == 0x2) ? aarch64::w0 : aarch64::x0;
1482             unsigned int encoding = field<16, 20>(insn);
1483
1484             if (encoding == 31)//zero register
1485                 return makeRegisterExpression(makeAarch64RegID(aarch64::xzr, 0));
1486             else
1487                 return makeRegisterExpression(makeAarch64RegID(baseReg, encoding));
1488         }
1489
1490         Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_amount() {
1491             unsigned int S = field<12, 12>(insn);
1492             unsigned int amountVal = is64Bit ? (S == 0 ? 0 : 2) : (S == 0 ? 0 : 3);
1493             unsigned int amountLen = 2;
1494
1495             return Immediate::makeImmediate(Result(u32, unsign_extend32(amountLen, amountVal)));
1496         }
1497
1498         Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_ext() {
1499             int immLen = 2;
1500             int immVal = 0; //for amount
1501
1502             int size = field<30, 31>(insn);
1503
1504             if(sField == 1)
1505                 immVal = size;
1506             else
1507                 immVal = 0;
1508
1509             Expression::Ptr ext = makeOptionExpression(immLen, immVal);
1510
1511             return ext; /*extended ptr*/
1512         }
1513
1514 /**********************
1515 // ld/st reg memReg AST:
1516 //    memRef
1517 //      |
1518 //     ADD
1519 //    /    \
1520 //  [Rn]   EXT
1521 //        /   \
1522 //      [Rm] [amount]
1523 **********************/
1524         Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg() {
1525             Expression::Ptr ext = makeMemRefReg_ext();
1526             Expression::Ptr xn = makeRnExpr();
1527             Expression::Ptr add = makeAddExpression(xn, ext, u64);
1528
1529             Result_Type rt;
1530             getMemRefIndex_RT(rt);
1531             return makeDereferenceExpression(add, rt);
1532         }
1533
1534         void InstructionDecoder_aarch64::LIndex() {
1535             // never be called
1536             if (IS_INSN_LD_LITERAL(insn)) {
1537                 insn_in_progress->appendOperand(makeMemRefIndexLiteral(), true, false);
1538             }
1539                 // ******************
1540                 // load register offset
1541                 // ******************
1542             else if (IS_INSN_LDST_REG(insn)) {
1543                 insn_in_progress->appendOperand(makeMemRefReg(), true, false);
1544             }
1545                 // ******************
1546                 // load unsigned imm
1547                 // ******************
1548             else if (IS_INSN_LDST_UIMM(insn)) {
1549                 insn_in_progress->appendOperand(makeMemRefIndexUImm(), true, false);
1550             }
1551                 // ******************
1552                 // load pre, unscaled and unprivlidged
1553                 // ******************
1554             else if (IS_INSN_LDST_PRE(insn)
1555                      || IS_INSN_LDST_UNPRIV(insn)
1556                      || IS_INSN_LDST_UNSCALED(insn)) {
1557                 insn_in_progress->appendOperand(makeMemRefIndexPre(), true, false);
1558             }
1559             else if (IS_INSN_LDST_POST(insn)) {
1560                 insn_in_progress->appendOperand(makeMemRefIndexPost(), true, false);
1561             }
1562                 // ****************************
1563                 // load PAIR pre, post, offset
1564                 // ****************************
1565             else if (IS_INSN_LDST_PAIR_PRE(insn)
1566                      || IS_INSN_LDST_PAIR_NOALLOC(insn)
1567                      || IS_INSN_LDST_PAIR_OFFSET(insn)) {
1568                 insn_in_progress->appendOperand(makeMemRefPairPre(), true, false);
1569             }
1570             else if (IS_INSN_LDST_PAIR_POST(insn)) {
1571                 insn_in_progress->appendOperand(makeMemRefPairPost(), true, false);
1572             }
1573                 // ****************************
1574                 // load exclusive instructions
1575                 // ****************************
1576             else if (IS_INSN_LDST_EX(insn)) {
1577                 if (!IS_INSN_LDST_EX_PAIR(insn)) { // Rt2 field == 31, non-pair op
1578                     insn_in_progress->appendOperand(makeMemRefEx(), true, false);
1579                 }
1580                 else { // pair
1581                     insn_in_progress->appendOperand(makeMemRefExPair(), true, false);
1582                 }
1583             }
1584                 // ****************************
1585                 // load SIMD multiple structures &
1586                 // load SIMD multiple structures post increment
1587                 // ****************************
1588             else if (IS_INSN_LDST_SIMD_MULT(insn)
1589                      || IS_INSN_LDST_SIMD_MULT_POST(insn)) {
1590                 insn_in_progress->appendOperand(makeMemRefSIMD_MULT(), true, false);
1591             }
1592                 // ****************************
1593                 // load SIMD single structure &
1594                 // load SIMD single structure post increment
1595                 // ****************************
1596             else if (IS_INSN_LDST_SIMD_SING(insn)
1597                      || IS_INSN_LDST_SIMD_SING_POST(insn)) {
1598                 insn_in_progress->appendOperand(makeMemRefSIMD_SING(), true, false);
1599             }
1600             else
1601                 assert(0);
1602         }
1603
1604         void InstructionDecoder_aarch64::STIndex() {
1605             if (IS_INSN_LD_LITERAL(insn))
1606                 assert(0); // only load literal, no store literal
1607                 // ******************
1608                 // ld/st register offset
1609                 // ******************
1610             else if (IS_INSN_LDST_REG(insn)) {
1611                 insn_in_progress->appendOperand(makeMemRefReg(), false, true);
1612             }
1613             else if (IS_INSN_LDST_UIMM(insn)) {
1614                 insn_in_progress->appendOperand(makeMemRefIndexUImm(), false, true);
1615             }
1616                 // ******************
1617                 // ld/st pre and post, unscaled and unprivilidged
1618                 // ******************
1619             else if (IS_INSN_LDST_PRE(insn)
1620                      || IS_INSN_LDST_UNPRIV(insn)
1621                      || IS_INSN_LDST_UNSCALED(insn)) {
1622                 insn_in_progress->appendOperand(makeMemRefIndexPre(), false, true);
1623             }
1624             else if (IS_INSN_LDST_POST(insn)) {
1625                 insn_in_progress->appendOperand(makeMemRefIndexPost(), false, true);
1626             }
1627                 // ****************************
1628                 // ld/st PAIR pre, post, offset
1629                 // ****************************
1630             else if (IS_INSN_LDST_PAIR_PRE(insn)
1631                      || IS_INSN_LDST_PAIR_NOALLOC(insn)
1632                      || IS_INSN_LDST_PAIR_OFFSET(insn)) {
1633                 insn_in_progress->appendOperand(makeMemRefPairPre(), false, true);
1634             }
1635             else if (IS_INSN_LDST_PAIR_POST(insn)) {
1636                 insn_in_progress->appendOperand(makeMemRefPairPost(), false, true);
1637             }
1638                 // ****************************
1639                 // ld/st exclusive instructions
1640                 // ****************************
1641             else if (IS_INSN_LDST_EX(insn)) {
1642                 if (!IS_INSN_LDST_EX_PAIR(insn)) { // Rt2 field == 31, non-pair op
1643                     insn_in_progress->appendOperand(makeMemRefEx(), false, true);
1644                 }
1645                 else { // pair
1646                     insn_in_progress->appendOperand(makeMemRefExPair(), false, true);
1647                 }
1648             }
1649                 // ****************************
1650                 // store SIMD multiple structures &
1651                 // store SIMD multiple structures post increment
1652                 // ****************************
1653             else if (IS_INSN_LDST_SIMD_MULT(insn)
1654                      || IS_INSN_LDST_SIMD_MULT_POST(insn)) {
1655                 insn_in_progress->appendOperand(makeMemRefSIMD_MULT(), false, true);
1656             }
1657             else if (IS_INSN_LDST_SIMD_SING(insn)
1658                      || IS_INSN_LDST_SIMD_SING_POST(insn)) {
1659                 insn_in_progress->appendOperand(makeMemRefSIMD_SING(), false, true);
1660             }
1661             else
1662                 assert(0); //un-handled case
1663
1664         }
1665
1666 // This function is for non-writeback
1667         void InstructionDecoder_aarch64::OPRRn() {
1668             if(skipRn)
1669                 return;
1670
1671             if (IS_INSN_B_UNCOND_REG(insn))                                        //unconditional branch (register)
1672             {
1673                 int branchType = field<21, 22>(insn);
1674
1675                 insn_in_progress->appendOperand(makePCExpr(), false, true);
1676                 insn_in_progress->addSuccessor(makeRnExpr(), field<21, 21>(insn) == 1, true, false, false);
1677
1678                 if (branchType == 0x1) {
1679                     insn_in_progress->addSuccessor(makeFallThroughExpr(), false, false, false, true);
1680                 }
1681             }
1682             else
1683                 insn_in_progress->appendOperand(makeRnExpr(), true, false);
1684         }
1685
1686         void InstructionDecoder_aarch64::OPRRnL() {
1687             LIndex();
1688         }
1689
1690         void InstructionDecoder_aarch64::OPRRnS() {
1691             STIndex();
1692         }
1693
1694         void InstructionDecoder_aarch64::OPRRnU() {
1695             assert(0);
1696             /* this functions is useless
1697         insn_in_progress->appendOperand(makeRnExpr(), true, true);
1698     */
1699         }
1700
1701         void InstructionDecoder_aarch64::OPRRnLU() {
1702             if (IS_INSN_LDST_PRE(insn) || IS_INSN_LDST_POST(insn) || IS_INSN_LDST_PAIR_PRE(insn) ||
1703                 IS_INSN_LDST_PAIR_POST(insn))
1704                 LIndex();
1705         }
1706
1707         void InstructionDecoder_aarch64::OPRRnSU() {
1708             if (IS_INSN_LDST_PRE(insn) || IS_INSN_LDST_POST(insn) || IS_INSN_LDST_PAIR_PRE(insn) ||
1709                 IS_INSN_LDST_PAIR_POST(insn))
1710                 STIndex();
1711         }
1712
1713         unsigned int InstructionDecoder_aarch64::get_SIMD_MULT_POST_imm() {
1714             unsigned int rpt = 0, selem = 0;
1715             getSIMD_MULT_RptSelem(rpt, selem);
1716             unsigned int numReg = rpt * selem;
1717             return _Q == 0x1 ? numReg << 4 : numReg << 3;
1718         }
1719
1720         unsigned int InstructionDecoder_aarch64::get_SIMD_SING_POST_imm() {
1721             return (getMemRefSIMD_SING_T() >> 3) * getSIMD_SING_selem();
1722         }
1723
1724         Expression::Ptr InstructionDecoder_aarch64::makeRmExpr() {
1725             int encoding = field<16, 20>(insn);
1726             MachRegister reg;
1727
1728             if (isSIMDInsn) {
1729                 if (IS_INSN_LDST_SIMD_MULT_POST(insn)) {
1730                     if (encoding == 31) {
1731                         unsigned int immVal = get_SIMD_MULT_POST_imm();
1732                         unsigned int immLen = 8;
1733
1734                         return Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));
1735                     }
1736                     else
1737                         reg = aarch64::x0;
1738                 }
1739                 else if (IS_INSN_LDST_SIMD_SING_POST(insn)) {
1740                     if (encoding == 31) {
1741                         unsigned int immVal = get_SIMD_SING_POST_imm();
1742                         unsigned int immLen = 8;
1743
1744                         return Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));
1745                     }
1746                     else
1747                         reg = aarch64::x0;
1748                 }
1749                 else if (IS_INSN_SIMD_VEC_INDEX(insn) || IS_INSN_SCALAR_INDEX(insn)) {
1750                     reg = field<11, 11>(insn) == 0x1 ? aarch64::q0 : aarch64::d0;
1751
1752                     if (size == 0x0 || size == 0x3)
1753                         isValid = false;
1754                     else if (size == 0x1)
1755                         encoding = encoding & 0xF;
1756                 }
1757                 else if (IS_INSN_SCALAR_3DIFF(insn)) {
1758                     switch (size) {
1759                         case 0x1:
1760                             reg = aarch64::h0;
1761                             break;
1762                         case 0x2:
1763                             reg = aarch64::s0;
1764                             break;
1765                         default:
1766                             isValid = false;
1767                     }
1768                 }
1769                 else if (IS_INSN_SIMD_3DIFF(insn)) {
1770                     entryID op = insn_in_progress->getOperation().operationID;
1771
1772                     if (op == aarch64_op_addhn_advsimd || op == aarch64_op_subhn_advsimd ||
1773                         op == aarch64_op_raddhn_advsimd || op == aarch64_op_rsubhn_advsimd)
1774                         reg = aarch64::q0;
1775                     else
1776                         reg = _Q == 0x1 ? aarch64::hq0 : aarch64::d0;
1777                 }
1778                 else if (IS_INSN_SCALAR_3SAME(insn)) {
1779                     if (size != -1) {
1780                         switch (size) {
1781                             case 0x0:
1782                                 reg = aarch64::b0;
1783                                 break;
1784                             case 0x1:
1785                                 reg = aarch64::h0;
1786                                 break;
1787                             case 0x2:
1788                                 reg = aarch64::s0;
1789                                 break;
1790                             case 0x3:
1791                                 reg = aarch64::d0;
1792                                 break;
1793                             default:
1794                                 isValid = false;
1795                         }
1796                     }
1797                     else if (_szField != -1) {
1798                         switch (_szField) {
1799                             case 0x0:
1800                                 reg = aarch64::s0;
1801                                 break;
1802                             case 0x1:
1803                                 reg = aarch64::d0;
1804                                 break;
1805                             default:
1806                                 isValid = false;
1807                         }
1808                     }
1809                     else
1810                         isValid = false;
1811                 }
1812                 else
1813                     reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
1814
1815                 reg = makeAarch64RegID(reg, encoding);
1816
1817                 return makeRegisterExpression(reg);
1818             }
1819             else if (isFPInsn) {
1820                 reg = isSinglePrec() ? aarch64::s0 : aarch64::d0;
1821                 reg = makeAarch64RegID(reg, encoding);
1822             }
1823             else {
1824                 reg = is64Bit ? ((encoding == 31) ? aarch64::xzr : aarch64::x0) : ((encoding == 31) ? aarch64::wzr
1825                                                                                                    : aarch64::w0);
1826                 if (encoding != 31)
1827                     reg = makeAarch64RegID(reg, encoding);
1828             }
1829
1830             return makeRegisterExpression(reg);
1831         }
1832
1833         void InstructionDecoder_aarch64::OPRRm() {
1834             if(skipRm)
1835                 return;
1836
1837             if (IS_INSN_FP_COMPARE(insn) && field<3, 3>(insn) == 1)
1838                 insn_in_progress->appendOperand(
1839                         Immediate::makeImmediate(Result(isSinglePrec() ? sp_float : dp_float, 0.0)), true, false);
1840             else
1841                 insn_in_progress->appendOperand(makeRmExpr(), true, false);
1842         }
1843
1844         void InstructionDecoder_aarch64::OPRsf() {
1845             if (field<31, 31>(insn) == 0)
1846                 is64Bit = false;
1847         }
1848
1849         template<unsigned int endBit, unsigned int startBit>
1850         void InstructionDecoder_aarch64::OPRoption() {
1851             hasOption = true;
1852             optionField = field<startBit, endBit>(insn);
1853         }
1854
1855         void InstructionDecoder_aarch64::OPRshift() {
1856             hasShift = true;
1857             shiftField = field<22, 23>(insn);
1858         }
1859
1860         void InstructionDecoder_aarch64::OPRhw() {
1861             hasHw = true;
1862             hwField = field<21, 22>(insn);
1863
1864             if(!is64Bit && ((hwField >> 1) & 0x1) == 1)
1865                 isValid = false;
1866         }
1867
1868         template<unsigned int endBit, unsigned int startBit>
1869         void InstructionDecoder_aarch64::OPRN() {
1870             hasN = true;
1871             nField = field<startBit, endBit>(insn);
1872             nLen = endBit - startBit + 1;
1873         }
1874
1875 // the call of this function should be generated by decoder gen for ld/st class
1876 // except for ld/st{s, h, w} subclass
1877         void InstructionDecoder_aarch64::setRegWidth() {
1878             //is64Bit is by default set to TRUE
1879             unsigned int opc = 0x3 & field<22, 23>(insn);
1880             unsigned int opc0 = opc & 0x1;
1881             unsigned int opc1 = (opc & 0x2) >> 1;
1882             unsigned int sz = 0x3 & field<30, 31>(insn);
1883
1884             if (IS_INSN_LDST(insn)) {
1885                 if (IS_INSN_LDST_UIMM(insn) || IS_INSN_LDST_UNSCALED(insn)
1886                     || IS_INSN_LDST_UNPRIV(insn) || IS_INSN_LDST_POST(insn)
1887                     || IS_INSN_LDST_PRE(insn) || IS_INSN_LDST_REG(insn)) {
1888                     if (opc1 == 0) {
1889                         if (field<30, 31>(insn) != 3)
1890                             is64Bit = false;
1891                         return;
1892                     } else {
1893                         if (sz == 3) {
1894                             if (opc0 == 1)
1895                                 isValid = false;
1896                         }
1897                         else {
1898                             if (sz == 2 && opc0 == 1)
1899                                 isValid = false;
1900                             if (opc0 == 1)
1901                                 is64Bit = false;
1902                         }
1903                         return;
1904                     }
1905                 }
1906                 else if (IS_INSN_LDST_EX(insn)) {
1907                     switch (sz) {
1908                         case 2:
1909                         case 0:
1910                         case 1:
1911                             is64Bit = false;
1912                             break;
1913                         case 3:
1914                         default:
1915                             return;
1916                     }
1917                 }
1918                 else if (IS_INSN_LDST_PAIR(insn)) {
1919                     switch (sz) {
1920                         case 0:
1921                             is64Bit = false;
1922                             break;
1923                         case 1:
1924                         case 2:
1925                         case 3:
1926                         default:
1927                             return;
1928                     }
1929                 }
1930                 else if (IS_INSN_LD_LITERAL(insn)) {
1931                     switch (sz) {
1932                         case 0:
1933                             is64Bit = false;
1934                         case 1:
1935                         case 2:
1936                         case 3:
1937                         default:
1938                             return;
1939                     }
1940                 }
1941                 else {
1942                     isValid = false;
1943                 }
1944             } else {
1945                 isValid = false;
1946             }
1947             return;
1948         }
1949
1950         MachRegister InstructionDecoder_aarch64::getLoadStoreSimdRegister(int encoding) {
1951             MachRegister reg;
1952
1953             if (size != -1) {
1954                 switch (size) {
1955                     case 0x0:
1956                         reg = (field<23, 23>(insn) == 0x1) ? aarch64::q0 : aarch64::b0;
1957                         break;
1958                     case 0x1:
1959                         reg = aarch64::h0;
1960                         break;
1961                     case 0x2:
1962                         reg = aarch64::s0;
1963                         break;
1964                     case 0x3:
1965                         reg = aarch64::d0;
1966                         break;
1967                 }
1968             }
1969             else {
1970                 switch (field<30, 31>(insn)) {
1971                     case 0x0:
1972                         reg = aarch64::s0;
1973                         break;
1974                     case 0x1:
1975                         reg = aarch64::d0;
1976                         break;
1977                     case 0x2:
1978                         reg = aarch64::q0;
1979                         break;
1980                     case 0x3:
1981                         isValid = false;
1982                         break;
1983                 }
1984             }
1985
1986             return makeAarch64RegID(reg, encoding);
1987         }
1988
1989         Expression::Ptr InstructionDecoder_aarch64::makeRtExpr() {
1990             int encoding = field<0, 4>(insn);
1991             MachRegister reg;
1992
1993             if (isFPInsn) {
1994                 reg = makeAarch64RegID(isSinglePrec() ? aarch64::s0 : aarch64::d0, encoding);
1995             }
1996             else if (isSIMDInsn) {
1997                 reg = getLoadStoreSimdRegister(encoding);
1998             }
1999             else {
2000                 reg = is64Bit ? ((encoding == 31) ? aarch64::xzr : aarch64::x0) : ((encoding == 31) ? aarch64::wzr
2001                                                                                                    : aarch64::w0);
2002                 if (encoding != 31)
2003                     reg = makeAarch64RegID(reg, encoding);
2004             }
2005
2006             return makeRegisterExpression(reg);
2007         }
2008
2009         void InstructionDecoder_aarch64::getSIMD_MULT_RptSelem(unsigned int &rpt, unsigned int &selem) {
2010             unsigned opcode = field<12, 15>(insn);
2011             switch (opcode) {
2012                 case 0x0:
2013                     rpt = 1;
2014                     selem = 4;
2015                     break;
2016                 case 0x2:
2017                     rpt = 4;
2018                     selem = 1;
2019                     break;
2020                 case 0x4:
2021                     rpt = 1;
2022                     selem = 3;
2023                     break;
2024                 case 0x6:
2025                     rpt = 3;
2026                     selem = 1;
2027                     break;
2028                 case 0x7:
2029                     rpt = 1;
2030                     selem = 1;
2031                     break;
2032                 case 0x8:
2033                     rpt = 1;
2034                     selem = 2;
2035                     break;
2036                 case 0xa:
2037                     rpt = 2;
2038                     selem = 1;
2039                     break;
2040                 default:
2041                     isValid = false;
2042                     return;
2043             }
2044             if (rpt == 0 || selem == 0)
2045                 isValid = false;
2046             return;
2047         }
2048
2049         void InstructionDecoder_aarch64::OPRRt() {
2050             int encoding = field<0, 4>(insn);
2051             entryID op = insn_in_progress->getOperation().operationID;
2052
2053             if (IS_INSN_BRANCHING(insn)) {
2054                 if (encoding == 31)
2055                     insn_in_progress->appendOperand(makeRegisterExpression(is64Bit ? aarch64::xzr : aarch64::wzr), true,
2056                                                     false);
2057                 else
2058                     insn_in_progress->appendOperand(
2059                             makeRegisterExpression(makeAarch64RegID(is64Bit ? aarch64::x0 : aarch64::w0, encoding)),
2060                             true, false);
2061             }
2062             else if (op == aarch64_op_prfm_imm || op == aarch64_op_prfm_lit || op == aarch64_op_prfm_reg) {
2063                 Expression::Ptr prfop;
2064                 Result arg = Result(u32, unsign_extend32(5, encoding));
2065                 
2066                 if((encoding & 0x1E) == 0x6 || (encoding & 0x1E) == 0xE || (encoding & 0x1E) == 0x16 || (encoding & 0x18) == 0x18)
2067                     prfop = Immediate::makeImmediate(arg);
2068                 else
2069                     prfop = ArmPrfmTypeImmediate::makeArmPrfmTypeImmediate(arg);
2070
2071                 insn_in_progress->appendOperand(prfop, true, false);
2072             }
2073         }
2074
2075         void InstructionDecoder_aarch64::OPRRtL() {
2076             int encoding = field<0, 4>(insn);
2077
2078             if (IS_INSN_LDST_SIMD_MULT(insn) || IS_INSN_LDST_SIMD_MULT_POST(insn)) {
2079                 unsigned int rpt, selem;
2080                 getSIMD_MULT_RptSelem(rpt, selem);
2081                 MachRegister reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
2082                 for (int it_rpt = rpt * selem - 1; it_rpt >= 0; it_rpt--) {
2083                     insn_in_progress->appendOperand(
2084                             makeRegisterExpression(makeAarch64RegID(reg, (encoding + it_rpt) % 32)), false, true);
2085                 }
2086             }
2087             else if (IS_INSN_LDST_SIMD_SING(insn) || IS_INSN_LDST_SIMD_SING_POST(insn)) {
2088                 unsigned int selem = getSIMD_SING_selem();
2089
2090                 MachRegister reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
2091
2092                 for (int it_selem = selem - 1; it_selem >= 0; it_selem--) {
2093                     insn_in_progress->appendOperand(
2094                             makeRegisterExpression(makeAarch64RegID(reg, (encoding + it_selem) % 32)), false, true);
2095                 }
2096             }
2097             else
2098                 insn_in_progress->appendOperand(makeRtExpr(), false, true);
2099         }
2100
2101         void InstructionDecoder_aarch64::OPRRtS() {
2102             int encoding = field<0, 4>(insn);
2103
2104             if (IS_INSN_LDST_SIMD_MULT(insn) || IS_INSN_LDST_SIMD_MULT_POST(insn)) {
2105                 unsigned int rpt, selem;
2106                 getSIMD_MULT_RptSelem(rpt, selem);
2107
2108                 MachRegister reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
2109
2110                 for (int it_rpt = rpt * selem - 1; it_rpt >= 0; it_rpt--) {
2111                     insn_in_progress->appendOperand(
2112                             makeRegisterExpression(makeAarch64RegID(reg, (encoding + it_rpt) % 32)), true, false);
2113                 }
2114             }
2115             else if (IS_INSN_LDST_SIMD_SING(insn) || IS_INSN_LDST_SIMD_SING_POST(insn)) {
2116                 unsigned int selem = getSIMD_SING_selem();
2117
2118                 MachRegister reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
2119
2120                 for (int it_selem = selem - 1; it_selem >= 0; it_selem--) {
2121                     insn_in_progress->appendOperand(
2122                             makeRegisterExpression(makeAarch64RegID(reg, (encoding + it_selem) % 32)), true, false);
2123                 }
2124             }
2125             else
2126                 insn_in_progress->appendOperand(makeRtExpr(), true, false);
2127         }
2128
2129         Expression::Ptr InstructionDecoder_aarch64::makeRt2Expr() {
2130             MachRegister baseReg;
2131             int encoding = field<10, 14>(insn);
2132
2133             if (isFPInsn) {
2134                 baseReg = makeAarch64RegID(isSinglePrec() ? aarch64::s0 : aarch64::d0, encoding);
2135             }
2136             else if (isSIMDInsn) {
2137                 baseReg = getLoadStoreSimdRegister(encoding);
2138             }
2139             else {
2140                 baseReg = is64Bit ? ((encoding == 31) ? aarch64::xzr : aarch64::x0) : ((encoding == 31) ? aarch64::wzr
2141                                                                                                    : aarch64::w0);
2142                 if (encoding != 31)
2143                     baseReg = makeAarch64RegID(baseReg, encoding);
2144             }
2145
2146             return makeRegisterExpression(baseReg);
2147         }
2148
2149         void InstructionDecoder_aarch64::OPRRt2() {
2150             assert(0);
2151         }
2152
2153         void InstructionDecoder_aarch64::OPRRt2L() {
2154             insn_in_progress->appendOperand(makeRt2Expr(), false, true);
2155         }
2156
2157         void InstructionDecoder_aarch64::OPRRt2S() {
2158             insn_in_progress->appendOperand(makeRt2Expr(), true, false);
2159         }
2160
2161         template<unsigned int endBit, unsigned int startBit>
2162         void InstructionDecoder_aarch64::OPRcond() {
2163             int condVal = field<startBit, endBit>(insn);
2164             if (IS_INSN_B_COND(insn)) {
2165                 insn_in_progress->getOperation().mnemonic += ".";
2166                 insn_in_progress->getOperation().mnemonic += condStringMap[condVal];
2167             }
2168             else {
2169                 if(IS_INSN_COND_SELECT(insn))
2170                     fix_condinsn_alias_and_cond(condVal);
2171                 else
2172                     oprRotateAmt++;
2173
2174                 Expression::Ptr cond = ArmConditionImmediate::makeArmConditionImmediate(Result(u8, condVal));
2175                 insn_in_progress->appendOperand(cond, true, false);
2176             }
2177
2178             isPstateRead = true;
2179         }
2180
2181         void InstructionDecoder_aarch64::OPRnzcv() {
2182             if(!isFPInsn && field<4, 4>(insn) == 1) {
2183                 isValid = false;
2184             } else {
2185                 unsigned int nzcvVal = field<0, 3>(insn);
2186                 Expression::Ptr nzcv = Immediate::makeImmediate(Result(u8, nzcvVal));
2187                 insn_in_progress->appendOperand(nzcv, true, false);
2188
2189                 isPstateWritten = true;
2190                 oprRotateAmt++;
2191             }
2192         }
2193
2194         void InstructionDecoder_aarch64::OPRop1() {
2195             op1Field = field<16, 18>(insn);
2196         }
2197
2198         void InstructionDecoder_aarch64::OPRop2() {
2199             op2Field = field<5, 7>(insn);
2200         }
2201
2202         void InstructionDecoder_aarch64::OPRCRm() {
2203             crmField = field<8, 11>(insn);
2204         }
2205
2206         void InstructionDecoder_aarch64::OPRCRn() {
2207         }
2208
2209         template<unsigned int endBit, unsigned int startBit>
2210         void InstructionDecoder_aarch64::OPRS() {
2211             sField = field<startBit, endBit>(insn);
2212         }
2213
2214         void InstructionDecoder_aarch64::OPRscale() {
2215             int scaleVal = 64 - field<10, 15>(insn);
2216
2217             Expression::Ptr scale = Immediate::makeImmediate(Result(u32, unsign_extend32(6, scaleVal)));
2218             insn_in_progress->appendOperand(scale, true, false);
2219         }
2220
2221         Expression::Ptr InstructionDecoder_aarch64::makeRaExpr() {
2222             int encoding = field<10, 14>(insn);
2223             MachRegister reg;
2224
2225             if (isFPInsn) {
2226                 reg = makeAarch64RegID(isSinglePrec() ? aarch64::s0 : aarch64::d0, encoding);
2227             }
2228             else {
2229                 reg = is64Bit ? ((encoding == 31) ? aarch64::sp : aarch64::x0) : ((encoding == 31) ? aarch64::wsp
2230                                                                                                    : aarch64::w0);
2231                 if (encoding != 31)
2232                     reg = makeAarch64RegID(reg, encoding);
2233             }
2234
2235             return makeRegisterExpression(reg);
2236
2237         }
2238
2239         void InstructionDecoder_aarch64::OPRRa() {
2240             insn_in_progress->appendOperand(makeRaExpr(), true, false);
2241
2242             oprRotateAmt++;
2243         }
2244
2245         void InstructionDecoder_aarch64::OPRo0() {
2246
2247         }
2248
2249         void InstructionDecoder_aarch64::OPRb5() {
2250             OPRsf();
2251             hasb5 = true;
2252         }
2253
2254         void InstructionDecoder_aarch64::OPRb40() {
2255
2256         }
2257
2258         Expression::Ptr InstructionDecoder_aarch64::makeb40Expr() {
2259             int b40Val = field<19, 23>(insn);
2260             int bitpos = ((is64Bit ? 1 : 0) << 5) | b40Val;
2261
2262             return Immediate::makeImmediate(Result(u32, unsign_extend32(6, bitpos)));
2263         }
2264
2265         template<unsigned int endBit, unsigned int startBit>
2266         void InstructionDecoder_aarch64::OPRsz() {
2267             _szField = field<startBit, endBit>(insn);
2268         }
2269
2270         bool InstructionDecoder_aarch64::isSinglePrec() {
2271             if (isFPInsn && !isSIMDInsn) {
2272                 if (_typeField == -1) {
2273                     //TODO if the type field is not set, do sth else
2274                     OPRtype<23, 22>();
2275                 }
2276                 return _typeField == 0 ? true : false;
2277             } else if (isSIMDInsn) {
2278                 isValid = false; //not implemeted yet
2279             }
2280             return false;
2281         }
2282
2283         Expression::Ptr InstructionDecoder_aarch64::makeRsExpr() {
2284             MachRegister baseReg = isFPInsn ?
2285                                    (isSinglePrec() ? aarch64::s0 : aarch64::d0) :
2286                                    (is64Bit ? aarch64::x0 : aarch64::w0);
2287
2288             if (IS_INSN_LDST(insn)) {
2289                 baseReg = aarch64::w0;
2290             }
2291             return makeRegisterExpression(makeAarch64RegID(baseReg, field<16, 20>(insn)));
2292         }
2293
2294         void InstructionDecoder_aarch64::OPRRs() {
2295             insn_in_progress->appendOperand(makeRsExpr(), false, true);
2296         }
2297
2298         void InstructionDecoder_aarch64::makeBranchTarget(bool branchIsCall, bool bIsConditional, int immVal,
2299                                                           int immLen) {
2300             Expression::Ptr lhs = makePCExpr();
2301
2302             int64_t offset = sign_extend64(immLen + 2, immVal * 4);
2303             Expression::Ptr rhs = Immediate::makeImmediate(Result(s64, offset));
2304
2305             insn_in_progress->addSuccessor(makeAddExpression(lhs, rhs, s64), branchIsCall, false, bIsConditional,
2306                                            false);
2307             if (branchIsCall) {
2308                 insn_in_progress->addSuccessor(makeFallThroughExpr(), false, false, false, true);
2309             }
2310
2311         }
2312
2313         Expression::Ptr InstructionDecoder_aarch64::makeFallThroughExpr() {
2314             return makeAddExpression(makePCExpr(), Immediate::makeImmediate(Result(u64, unsign_extend64(3, 4))), u64);
2315         }
2316
2317         template<typename T, Result_Type rT>
2318         Expression::Ptr InstructionDecoder_aarch64::fpExpand(int val) {
2319             int N, E, F;
2320             T frac, expandedImm, sign, exp;
2321
2322             N = (rT == s32) ? 32 : 64;
2323             E = (N == 32) ? 8 : 11;
2324             F = N - E - 1;
2325
2326             sign = (val & 0x80) >> 7;
2327
2328             int val6 = ((~val) & 0x40) >> 6, val6mask = (1 << (E - 3)) - 1;
2329             exp = (val6 << (E - 1)) | ((val6 ? val6mask : 0) << 2) | ((val & 0x30) >> 4);
2330
2331             frac = (val & 0xF) << (F - 4);
2332
2333             expandedImm = (sign << (E + F)) | (exp << F) | frac;
2334
2335             return Immediate::makeImmediate(Result(rT, expandedImm));
2336         }
2337
2338         template<typename T>
2339         Expression::Ptr InstructionDecoder_aarch64::makeLogicalImm(int immr, int imms, int immsLen, Result_Type rT) {
2340             int len = highest_set_bit((nField << immsLen) | (~imms & ((1 << immsLen) - 1))) - 1;
2341             int finalsize = (rT == u32 ? 32 : 64);
2342
2343             if (len < 1 || ((1 << len) > finalsize)) {
2344                 isValid = false;
2345                 return Immediate::makeImmediate(Result(u32, 0));
2346             }
2347             int levels = (1 << len) - 1;
2348
2349             int S = imms & levels;
2350             if (S == levels) {
2351                 isValid = false;
2352                 return Immediate::makeImmediate(Result(u32, 0));
2353             }
2354             int R = immr & levels;
2355
2356             int esize = 1 << len;
2357             T welem = (((T) 1) << (S + 1)) - 1;
2358
2359             T wmaskarg = welem;
2360             if (R != 0) {
2361                 T low = welem & (((T) 1 << R) - 1), high = welem & ((((T) 1 << (esize - R)) - 1) << R);
2362                 wmaskarg = (low << (esize - R)) | (high >> R);
2363             }
2364
2365             int idx;
2366             T wmask = wmaskarg;
2367
2368             for (idx = 1; idx < finalsize / esize; idx++) {
2369                 wmask |= (wmaskarg << (esize * idx));
2370             }
2371
2372             return Immediate::makeImmediate(Result(rT, wmask));
2373         }
2374
2375         bool InstructionDecoder_aarch64::fix_bitfieldinsn_alias(int immr, int imms) {
2376             entryID modifiedID = insn_in_progress->getOperation().operationID;
2377             bool do_further_processing = true;
2378
2379             switch (field<27, 30>(insn)) {
2380                 case 0x6:
2381                     modifiedID = (imms < immr) ? aarch64_op_bfi_bfm : aarch64_op_bfxil_bfm;
2382                     break;
2383                 case 0x2:
2384                     if (immr == 0 && (imms == 7 || imms == 15 || imms == 31)) {
2385                         do_further_processing = false;
2386                         switch (imms) {
2387                             case 7:
2388                                 modifiedID = aarch64_op_sxtb_sbfm;
2389                                 break;
2390                             case 15:
2391                                 modifiedID = aarch64_op_sxth_sbfm;
2392                                 break;
2393                             case 31:
2394                                 modifiedID = aarch64_op_sxtw_sbfm;
2395                                 break;
2396                         }
2397                     }
2398                     else
2399                         modifiedID = (imms < immr) ? aarch64_op_sbfiz_sbfm : aarch64_op_sbfx_sbfm;
2400                     break;
2401                 case 0xA:
2402                     if (immr == 0 && (imms == 7 || imms == 15)) {
2403                         do_further_processing = false;
2404                         switch (imms) {
2405                             case 7:
2406                                 modifiedID = aarch64_op_uxtb_ubfm;
2407                                 break;
2408                             case 15:
2409                                 modifiedID = aarch64_op_uxth_ubfm;
2410                                 break;
2411                         }
2412                     }
2413                     else if((imms != 31 || imms != 63) && (imms + 1) == immr)
2414                         modifiedID = aarch64_op_lsl_ubfm;
2415                     else if((imms & 0x1F) == 0x1F)
2416                         modifiedID = aarch64_op_lsr_ubfm;
2417                     else
2418                         modifiedID = (imms < immr) ? aarch64_op_ubfiz_ubfm : aarch64_op_ubfx_ubfm;
2419                     break;
2420                 default:
2421                     isValid = false;
2422             }
2423
2424             insn_in_progress->getOperation().operationID = modifiedID;
2425             insn_in_progress->getOperation().mnemonic = bitfieldInsnAliasMap[modifiedID];
2426
2427             return do_further_processing;
2428         }
2429
2430         void InstructionDecoder_aarch64::fix_condinsn_alias_and_cond(int &cond) {
2431             entryID modifiedID = insn_in_progress->getOperation().operationID;
2432             if (modifiedID == aarch64_op_csel)
2433                 return;
2434
2435             int Rm = field<16, 20>(insn), Rn = field<5, 9>(insn);
2436
2437             if (Rm == Rn && (cond & 0xE) != 0xE && modifiedID == aarch64_op_csneg) {
2438                 modifiedID = aarch64_op_cneg_csneg;
2439                 skipRm = true;
2440             } else if (Rm != 31 && Rn != 31 && (cond & 0xE) != 0xE && Rm == Rn) {
2441                 switch (modifiedID) {
2442                     case aarch64_op_csinc:
2443                         modifiedID = aarch64_op_cinc_csinc;
2444                         break;
2445                     case aarch64_op_csinv:
2446                         modifiedID = aarch64_op_cinv_csinv;
2447                         break;
2448                     default:
2449                         isValid = false;
2450                 }
2451
2452                 skipRm = true;
2453             } else if (Rm == 31 && Rn == 31 && (cond & 0xE) != 0xE) {
2454                 switch (modifiedID) {
2455                     case aarch64_op_csinc:
2456                         modifiedID = aarch64_op_cset_csinc;
2457                         break;
2458                     case aarch64_op_csinv:
2459                         modifiedID = aarch64_op_csetm_csinv;
2460                         break;
2461                     default:
2462                         isValid = false;
2463                 }
2464
2465                 skipRn = skipRm = true;
2466             }
2467
2468             insn_in_progress->getOperation().operationID = modifiedID;
2469             insn_in_progress->getOperation().mnemonic = condInsnAliasMap[modifiedID];
2470             if(skipRm)
2471                 cond = ((cond % 2) == 0) ? (cond + 1) : (cond - 1);
2472         }
2473
2474         template<unsigned int endBit, unsigned int startBit>
2475         void InstructionDecoder_aarch64::OPRimm() {
2476             int immVal = field<startBit, endBit>(insn);
2477             unsigned int immLen = endBit - startBit + 1;
2478
2479             if (IS_INSN_LDST(insn)) {
2480                 if (IS_INSN_LD_LITERAL(insn)) {
2481                     Expression::Ptr literal = makeMemRefIndexLiteral();
2482                     insn_in_progress->appendOperand(literal, true, false);
2483                 }
2484                 else if (IS_INSN_LDST_POST(insn)) {
2485                     Expression::Ptr offset = makeMemRefIndex_offset9();
2486                     insn_in_progress->appendOperand(offset, true, false);
2487                 }
2488                 else if (IS_INSN_LDST_PAIR_POST(insn)) {
2489                     Expression::Ptr offset = makeMemRefPair_offset7();
2490                     insn_in_progress->appendOperand(offset, true, false);
2491                 }
2492
2493                 return;
2494             }
2495
2496             if (hasHw) {
2497                 processHwFieldInsn(immLen, immVal);
2498             }
2499             else if (hasN)        //logical (immediate), bitfield, extract
2500             {
2501                 if (IS_FIELD_IMMR(startBit, endBit)) {
2502                     immr = immVal;
2503                     immrLen = immLen;
2504                 }
2505                 else if (IS_FIELD_IMMS(startBit, endBit)) {
2506                     Expression::Ptr imm;
2507                     bool isLsrLsl = false;
2508
2509                     if (IS_INSN_LOGICAL_IMM(insn)) {
2510                         if (is64Bit)
2511                             imm = makeLogicalImm<uint64_t>(immr, immVal, immLen, u64);
2512                         else
2513                             imm = makeLogicalImm<uint32_t>(immr, immVal, immLen, u32);
2514                         
2515                         insn_in_progress->appendOperand(imm, true, false);
2516                     }
2517                     else {
2518                         entryID curID;
2519
2520                         if (IS_INSN_BITFIELD(insn)) {
2521                             if (!fix_bitfieldinsn_alias(immr, immVal))
2522                                 return;
2523
2524                             curID = insn_in_progress->getOperation().operationID;
2525                             if(curID == aarch64_op_lsl_ubfm || curID == aarch64_op_lsr_ubfm)
2526                                 isLsrLsl = true;
2527                             
2528                             if (curID != aarch64_op_lsr_ubfm && immVal < immr) {
2529                                 int divisor = is64Bit ? 64 : 32, factor = 0;
2530                                 while ((divisor * factor) < immr)
2531                                     factor += 1;
2532                                 immr = (divisor * factor) - immr;
2533                                 immrLen += 1;
2534
2535                                 immVal += 1;
2536                             }
2537                             else
2538                                 immVal = immVal + 1 - immr;
2539
2540                             immLen += 1;
2541                         }
2542
2543                         if(!isLsrLsl) {
2544                             imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));
2545                             insn_in_progress->appendOperand(imm, true, false);
2546                             oprRotateAmt++;
2547                         }
2548                     }
2549
2550                     if (IS_INSN_BITFIELD(insn)) {
2551                         imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immrLen, immr)));
2552                         insn_in_progress->appendOperand(imm, true, false);
2553                         if(!isLsrLsl)
2554                             oprRotateAmt--;
2555                     }
2556                 }
2557                 else
2558                     isValid = false;
2559             }
2560             else if (hasShift) {
2561                 if (IS_INSN_ADDSUB_SHIFT(insn) || IS_INSN_LOGICAL_SHIFT(insn))    //add-sub shifted | logical shifted
2562                 {
2563                     processShiftFieldShiftedInsn(immLen, immVal);
2564                 }
2565                 else if (IS_INSN_ADDSUB_IMM(insn))        //add-sub (immediate)
2566                 {
2567                     processShiftFieldImmInsn(immLen, immVal);
2568                 }
2569                 else
2570                     isValid = false;
2571             }
2572             else if (hasOption) {
2573                 if (IS_INSN_ADDSUB_EXT(insn))                                        //add-sub extended
2574                 {
2575                     Expression::Ptr expr = makeOptionExpression(immLen, immVal);
2576
2577                     insn_in_progress->appendOperand(expr, true, false);
2578                 }
2579                 else {
2580                     isValid = false;
2581                 }
2582             }
2583             else if (IS_INSN_BRANCHING(insn) && !IS_INSN_B_UNCOND_REG(
2584                     insn)) {        //unconditional branch (immediate), test and branch, compare and branch, conditional branch
2585                 bool bIsConditional = false;
2586                 if (!(IS_INSN_B_UNCOND(insn)))
2587                     bIsConditional = true;
2588
2589                 bool branchIsCall = bIsConditional ? false : (field<31, 31>(insn) == 1);
2590
2591                 insn_in_progress->appendOperand(makePCExpr(), false, true);
2592                 makeBranchTarget(branchIsCall, bIsConditional, immVal, immLen);
2593
2594                 if (hasb5)
2595                     insn_in_progress->appendOperand(makeb40Expr(), true, false);
2596
2597                 if (bIsConditional)
2598                     insn_in_progress->addSuccessor(makeFallThroughExpr(), false, false, true, true);
2599             }
2600             else if (IS_INSN_PCREL_ADDR(insn))                                    //pc-relative addressing
2601             {
2602                 if (IS_FIELD_IMMLO(startBit, endBit)) {
2603                     immlo = immVal;
2604                     immloLen = endBit - startBit + 1;
2605                 }
2606                 else if (IS_FIELD_IMMHI(startBit, endBit)) {
2607                     int page = field<31, 31>(insn);
2608                     int64_t offset = (immVal << immloLen) | immlo;
2609                     offset = offset << (page * 12);
2610                     int size = immloLen + immLen + (page * 12);
2611
2612                     insn_in_progress->appendOperand(makePCExpr(), true, false);
2613                     Expression::Ptr imm = Immediate::makeImmediate(Result(s64, (offset << (64 - size)) >> (64 - size)));
2614
2615                     insn_in_progress->appendOperand(imm, true, false);
2616                 }
2617                 else
2618                     isValid = false;
2619             }
2620             else if (isFPInsn) {
2621                 if (isSinglePrec())
2622                     insn_in_progress->appendOperand(fpExpand<int32_t, s32>(immVal), true, false);
2623                 else
2624                     insn_in_progress->appendOperand(fpExpand<int64_t, s64>(immVal), true, false);
2625             }
2626             else if (IS_INSN_EXCEPTION(insn)) {
2627                 Expression::Ptr imm = Immediate::makeImmediate(Result(u16, immVal));
2628                 insn_in_progress->appendOperand(imm, true, false);
2629                 isPstateRead = true;
2630             }
2631             else if (isSIMDInsn) {
2632                 if (IS_INSN_SIMD_EXTR(insn)) {
2633                     if (_Q == 0) {
2634                         if ((immVal & 0x8) == 0) {
2635                             Expression::Ptr imm = Immediate::makeImmediate(
2636                                     Result(u32, unsign_extend32(immLen - 1, immVal & 0x7)));
2637                             insn_in_progress->appendOperand(imm, true, false);
2638                         }
2639                         else
2640                             isValid = false;
2641                     }
2642                     else {
2643                         Expression::Ptr imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));\
2644             insn_in_progress->appendOperand(imm, true, false);
2645                     }
2646                 }
2647                 else if (IS_INSN_SIMD_SHIFT_IMM(insn) || IS_INSN_SCALAR_SHIFT_IMM(insn)) {
2648                     //immh
2649                     if (startBit == 19 && endBit == 22) {
2650                         immlo = immVal;
2651                         immloLen = endBit - startBit + 1;
2652                     }
2653                         //immb
2654                     else if (startBit == 16 && endBit == 18) {
2655                         int opcode = field<11, 15>(insn);
2656                         int shift, isRightShift = 1, elemWidth = (immlo << immLen) | immVal;
2657                         entryID insnID = insn_in_progress->getOperation().operationID;
2658                         bool isScalar = field<28, 28>(insn) ? true : false;
2659
2660                         //check if shift is left; if it is, the immediate has to be processed in a different manner.
2661                         //unfortunately, determining whether the instruction will do a left or right shift cannot be determined in any way other than checking the instruction's opcode
2662                         if (insnID == aarch64_op_shl_advsimd || insnID == aarch64_op_sqshl_advsimd_imm ||
2663                             insnID == aarch64_op_sshll_advsimd ||
2664                             insnID == aarch64_op_sli_advsimd || insnID == aarch64_op_sqshlu_advsimd ||
2665                             insnID == aarch64_op_uqshl_advsimd_imm || insnID == aarch64_op_ushll_advsimd)
2666                             isRightShift = -1;
2667
2668                         switch (highest_set_bit(immlo)) {
2669                             case 0x1:
2670                                 (!isScalar || (opcode & 0x1C) == 0x0C || (opcode & 0x1C) == 0x10)
2671                                 ? (shift = isRightShift * (16 - elemWidth) + (isRightShift > 0 ? 0 : 8))
2672                                 : (isValid = false);
2673                                 break;
2674                             case 0x2:
2675                                 (!isScalar || (opcode & 0x1C) == 0x0C || (opcode & 0x1C) == 0x10)
2676                                 ? (shift = isRightShift * (32 - elemWidth) + (isRightShift > 0 ? 0 : 16))
2677                                 : (isValid = false);
2678                                 break;
2679                             case 0x3:
2680                                 (!isScalar || opcode > 0x0A) ? (shift = isRightShift * (64 - elemWidth) +
2681                                                                         (isRightShift > 0 ? 0 : 32))
2682                                                              : (isValid = false);
2683                                 break;
2684                             case 0x4:
2685                                 shift = isRightShift * (128 - elemWidth) + (isRightShift > 0 ? 0 : 64);
2686                                 break;
2687                             default:
2688                                 isValid = false;
2689                         }
2690
2691                         if (isValid) {
2692                             Expression::Ptr imm = Immediate::makeImmediate(
2693                                     Result(u32, unsign_extend32(immloLen + immLen, shift)));
2694                             insn_in_progress->appendOperand(imm, true, false);
2695                         }
2696                     }
2697                     else
2698                         isValid = false;
2699                 }
2700             }
2701             else                                                            //conditional compare (immediate)
2702             {
2703                 Result_Type rT = is64Bit ? u64 : u32;
2704
2705                 Expression::Ptr imm = Immediate::makeImmediate(
2706                         Result(rT, rT == u32 ? unsign_extend32(immLen, immVal) : unsign_extend64(immLen, immVal)));
2707                 insn_in_progress->appendOperand(imm, true, false);
2708             }
2709         }
2710
2711         void InstructionDecoder_aarch64::reorderOperands() {
2712             if (oprRotateAmt) {
2713                 std::vector<Operand> curOperands;
2714                 insn_in_progress->getOperands(curOperands);
2715
2716                 if (curOperands.empty())
2717                     assert(!"empty operand list found while re-ordering operands");
2718
2719                 std::swap(curOperands[1], curOperands[3]);
2720
2721                 while (oprRotateAmt--)
2722                     std::rotate(curOperands.begin(), curOperands.begin() + 1, curOperands.begin() + 3);
2723
2724                 insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2725             }
2726             else if (IS_INSN_LDST_POST(insn) || IS_INSN_LDST_PAIR_POST(insn)) {
2727                 std::vector<Operand> curOperands;
2728                 insn_in_progress->getOperands(curOperands);
2729                 std::iter_swap(curOperands.begin(), curOperands.end() - 1);
2730                 insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2731             }
2732             else if (IS_INSN_LDST_PAIR(insn)) {
2733                 std::vector<Operand> curOperands;
2734                 insn_in_progress->getOperands(curOperands);
2735                 assert(curOperands.size() == 4 || curOperands.size() == 3);
2736                 if (curOperands.size() == 3) {
2737                     curOperands.insert(curOperands.begin(), curOperands.back());
2738                     curOperands.pop_back();
2739                 } else if (curOperands.size() == 4) {
2740                     std::iter_swap(curOperands.begin(), curOperands.end() - 1);
2741                 }
2742                 insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2743             }
2744             else if (IS_INSN_LDST_EX_PAIR(insn)) {
2745                 std::vector<Operand> curOperands;
2746                 insn_in_progress->getOperands(curOperands);
2747                 if (curOperands.size() == 3) {
2748                     curOperands.insert(curOperands.begin(), curOperands.back());
2749                     curOperands.pop_back();
2750                 }
2751                 else if (curOperands.size() == 4) {
2752                     curOperands.insert(curOperands.begin() + 1, curOperands.back());
2753                     curOperands.pop_back();
2754                 }
2755                 insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2756             }
2757             else if (IS_INSN_ST_EX(insn)) {
2758                 std::vector<Operand> curOperands;
2759                 insn_in_progress->getOperands(curOperands);
2760                 if (curOperands.size() == 3) {
2761                     curOperands.insert(curOperands.begin() + 1, curOperands.back());
2762                     curOperands.pop_back();
2763                     insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2764                 }
2765                 else
2766                     insn_in_progress->m_Operands.reverse();
2767             }
2768             else
2769                 insn_in_progress->m_Operands.reverse();
2770         }
2771
2772         void InstructionDecoder_aarch64::processAlphabetImm() {
2773             if (op == 1 && cmode == 0xE) {
2774                 uint64_t imm = 0;
2775
2776                 for (int imm_index = 0; imm_index < 8; imm_index++)
2777                     imm |= (simdAlphabetImm & (1 << imm_index)) ? (0xFF << (imm_index * 8)) : 0;
2778
2779                 insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u64, imm)), true, false);
2780             }
2781             else if (cmode == 0xF) {
2782                 //fmov (vector, immediate)
2783                 //TODO: check with Bill if this is fine
2784                 insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, simdAlphabetImm)), true, false);
2785             }
2786             else {
2787                 int shiftAmt = 0;
2788
2789                 //16-bit shifted immediate
2790                 if ((cmode & 0xC) == 0x8)
2791                     shiftAmt = ((cmode & 0x2) >> 1) * 8;
2792                     //32-bit shifted immediate
2793                 else if ((cmode & 0x8) == 0x0)
2794                     shiftAmt = ((cmode & 0x6) >> 1) * 8;
2795                     //32-bit shifting ones
2796                 else if ((cmode & 0xE) == 0xC)
2797                     shiftAmt = ((cmode & 0x0) + 1) * 8;
2798
2799                 Expression::Ptr lhs = Immediate::makeImmediate(Result(u32, unsign_extend32(8, simdAlphabetImm)));
2800                 Expression::Ptr rhs = Immediate::makeImmediate(Result(u32, unsign_extend32(5, shiftAmt)));
2801                 Expression::Ptr imm = makeLeftShiftExpression(lhs, rhs, u64);
2802
2803                 insn_in_progress->appendOperand(imm, true, false);
2804             }
2805         }
2806
2807         using namespace boost::assign;
2808
2809 #include "aarch64_opcode_tables.C"
2810
2811         void InstructionDecoder_aarch64::doDelayedDecode(const Instruction *insn_to_complete) {
2812             InstructionDecoder::buffer b(insn_to_complete->ptr(), insn_to_complete->size());
2813             //insn_to_complete->m_Operands.reserve(4);
2814             decode(b);
2815             decodeOperands(insn_to_complete);
2816
2817         }
2818
2819         bool InstructionDecoder_aarch64::decodeOperands(const Instruction *insn_to_complete) {
2820             int insn_table_index = findInsnTableIndex(0);
2821             aarch64_insn_entry *insn_table_entry = &aarch64_insn_entry::main_insn_table[insn_table_index];
2822
2823             insn = insn_to_complete->m_RawInsn.small_insn;
2824             insn_in_progress = const_cast<Instruction *>(insn_to_complete);
2825
2826             if (IS_INSN_LDST_REG(insn) ||
2827                 IS_INSN_ADDSUB_EXT(insn) ||
2828                 IS_INSN_ADDSUB_SHIFT(insn) ||
2829                 IS_INSN_LOGICAL_SHIFT(insn))
2830                 skipRm = true;
2831
2832             for (operandSpec::const_iterator fn = insn_table_entry->operands.begin();
2833                  fn != insn_table_entry->operands.end(); fn++) {
2834                 std::mem_fun(*fn)(this);
2835             }
2836
2837             if (insn_table_index == 0)
2838                 isValid = false;
2839
2840             if (!isValid) {
2841                 insn_in_progress->getOperation().mnemonic = INVALID_ENTRY.mnemonic;
2842                 insn_in_progress->getOperation().operationID = INVALID_ENTRY.op;
2843                 insn_in_progress->m_Operands.clear();
2844                 insn_in_progress->m_Successors.clear();
2845             } else {
2846                 reorderOperands();
2847
2848                 if (IS_INSN_SYSTEM(insn)) {
2849                     processSystemInsn();
2850                 }
2851
2852                 if (IS_INSN_SIMD_MOD_IMM(insn)) {
2853                     processAlphabetImm();
2854                 }
2855
2856                 if (IS_INSN_LDST_SIMD_MULT_POST(insn) || IS_INSN_LDST_SIMD_SING_POST(insn))
2857                     insn_in_progress->appendOperand(makeRnExpr(), false, true);
2858                 else if (insn_in_progress->getOperation().operationID == aarch64_op_cmeq_advsimd_zero &&
2859                          field<29, 29>(insn) == 0)
2860                     insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u32, 0)), true, false);
2861
2862                 if (isPstateWritten || isPstateRead)
2863                     insn_in_progress->appendOperand(makePstateExpr(), isPstateRead, isPstateWritten);
2864             }
2865
2866             return true;
2867         }
2868
2869
2870         int InstructionDecoder_aarch64::findInsnTableIndex(unsigned int decoder_table_index) {
2871             aarch64_mask_entry *cur_entry = &aarch64_mask_entry::main_decoder_table[decoder_table_index];
2872             unsigned int cur_mask = cur_entry->mask;
2873
2874             if (cur_mask == 0) {
2875                 int insn_table_index = cur_entry->insnTableIndex;
2876                 if (insn_table_index == -1)
2877                     assert(!"no instruction table entry found for current instruction");
2878                 else
2879                     return insn_table_index;
2880             }
2881
2882             unsigned int insn_iter_index = 0, map_key_index = 0, branch_map_key = 0;
2883             branchMap cur_branches = cur_entry->nodeBranches;
2884
2885             while (insn_iter_index < AARCH64_INSN_LENGTH) {