fix warning
[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::zr : 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
473         Expression::Ptr InstructionDecoder_aarch64::makeRdExpr() {
474             int encoding = field<0, 4>(insn);
475             MachRegister reg;
476
477             if (isSIMDInsn) {
478                 if (IS_INSN_SIMD_ACROSS(insn)) {
479                     //fmaxnmv, fmaxv, fminnmv, fminv
480                     if (field<14, 14>(insn) == 0x1) {
481                         if (_szField == 0x0)
482                             reg = aarch64::s0;
483                         else
484                             isValid = false;
485                     }
486                     else {
487                         int opcode = field<12, 16>(insn);
488
489                         //saddlv and uaddlv with opcode field 0x03 use different sets of registers
490                         switch (size) {
491                             case 0x0:
492                                 reg = (opcode == 0x03) ? aarch64::h0 : aarch64::b0;
493                                 break;
494                             case 0x1:
495                                 reg = (opcode == 0x03) ? aarch64::s0 : aarch64::h0;
496                                 break;
497                             case 0x2:
498                                 reg = (opcode == 0x03) ? aarch64::d0 : aarch64::s0;
499                                 break;
500                             default:
501                                 isValid = false;
502                         }
503                     }
504                 }
505                 else if (IS_INSN_SIMD_COPY(insn)) {
506                     unsigned int op = field<29, 29>(insn);
507                     unsigned int imm4 = field<11, 14>(insn);
508
509                     if (op == 0x1)
510                         reg = aarch64::q0;
511                     else {
512                         switch (imm4) {
513                             case 0x5:
514                             case 0x7:
515                                 reg = _Q == 0x1 ? aarch64::x0 : aarch64::w0;
516                                 break;
517                             default:
518                                 reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
519                                 break;
520                         }
521                     }
522                 }
523                 else if (IS_INSN_SCALAR_COPY(insn) || IS_INSN_SCALAR_SHIFT_IMM(insn)) {
524                     int switchbit;
525
526                     if (IS_INSN_SCALAR_COPY(insn))
527                         switchbit = lowest_set_bit(field<16, 20>(insn));
528                     else
529                         switchbit = highest_set_bit(field<19, 22>(insn));
530
531                     switch (switchbit) {
532                         case 0x1:
533                             reg = aarch64::b0;
534                             break;
535                         case 0x2:
536                             reg = aarch64::h0;
537                             break;
538                         case 0x3:
539                             reg = aarch64::s0;
540                             break;
541                         case 0x4:
542                             reg = aarch64::d0;
543                             break;
544                         default:
545                             isValid = false;
546                     }
547                 }
548                 else if (IS_INSN_SCALAR_3DIFF(insn)) {
549                     switch (size) {
550                         case 0x1:
551                             reg = aarch64::s0;
552                             break;
553                         case 0x2:
554                             reg = aarch64::d0;
555                             break;
556                         default:
557                             isValid = false;
558                     }
559                 }
560                 else if (IS_INSN_SCALAR_INDEX(insn)) {
561                     int opcode = field<12, 15>(insn);
562
563                     //sqdmlal, sqdmlsl, sqdmull
564                     if ((opcode & 0x3) == 0x3) {
565                         switch (size) {
566                             case 0x1:
567                                 reg = aarch64::s0;
568                                 break;
569                             case 0x2:
570                                 reg = aarch64::d0;
571                                 break;
572                             default:
573                                 isValid = false;
574                         }
575                     }
576                         //sqdmulh, sqrdmulh
577                     else if ((opcode & 0xC) == 0xC) {
578                         switch (size) {
579                             case 0x1:
580                                 reg = aarch64::h0;
581                                 break;
582                             case 0x2:
583                                 reg = aarch64::s0;
584                                 break;
585                             default:
586                                 isValid = false;
587                         }
588                     }
589                         //fmla, fmls, fmul, fmulx
590                     else if ((opcode & 0x3) == 0x1) {
591                         switch (_szField) {
592                             case 0x0:
593                                 reg = aarch64::s0;
594                                 break;
595                             case 0x1:
596                                 reg = aarch64::d0;
597                                 break;
598                             default:
599                                 isValid = false;
600                         }
601                     }
602                     else
603                         isValid = false;
604                 }
605                 else if (IS_INSN_SCALAR_2REG_MISC(insn) || IS_INSN_SCALAR_3SAME(insn)) {
606                     //some instructions in this set rely on sz for choosing the register and some on size
607                     //only one of them is set for an instruction, however
608                     if (_szField == -1) {
609                         switch (size) {
610                             case 0x0:
611                                 reg = aarch64::b0;
612                                 break;
613                             case 0x1:
614                                 reg = aarch64::h0;
615                                 break;
616                             case 0x2:
617                                 reg = aarch64::s0;
618                                 break;
619                             case 0x3:
620                                 reg = aarch64::d0;
621                                 break;
622                             default:
623                                 isValid = false;
624                         }
625                     }
626                     else {
627                         switch (_szField) {
628                             case 0x0:
629                                 reg = aarch64::s0;
630                                 break;
631                             case 0x1: {
632                                 entryID op = insn_in_progress->getOperation().operationID;
633                                 reg = (op == aarch64_op_fcvtxn_advsimd) ? aarch64::s0 : aarch64::d0;
634                             }
635                                 break;
636                             default:
637                                 isValid = false;
638                         }
639                     }
640                 }
641                 else if (IS_INSN_SCALAR_PAIR(insn)) {
642                     if (size != -1) {
643                         if (size == 0x3)
644                             reg = aarch64::d0;
645                         else
646                             isValid = false;
647                     }
648                     else if (_szField != -1) {
649                         switch (_szField) {
650                             case 0x0:
651                                 reg = aarch64::s0;
652                                 break;
653                             case 0x1:
654                                 reg = aarch64::d0;
655                                 break;
656                         }
657                     }
658                     else
659                         isValid = false;
660                 }
661                 else if (IS_INSN_SIMD_MOD_IMM(insn) && _Q == 0 && op == 1 && cmode == 0xE) {
662                     reg = aarch64::d0;
663                 }
664                 else if (IS_INSN_SIMD_VEC_INDEX(insn)) {
665                     if (field<13, 13>(insn) == 0x1)
666                         reg = aarch64::q0;
667                     else
668                         reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
669                 }
670                 else if (IS_INSN_SIMD_3DIFF(insn)) {
671                     entryID op = insn_in_progress->getOperation().operationID;
672
673                     if (op == aarch64_op_addhn_advsimd || op == aarch64_op_subhn_advsimd ||
674                         op == aarch64_op_raddhn_advsimd || op == aarch64_op_rsubhn_advsimd)
675                         reg = _Q == 0x1 ? aarch64::hq0 : aarch64::d0;
676                     else
677                         reg = aarch64::q0;
678                 }
679                     // 3SAME, 2REG_MISC, EXTRACT
680                 else
681                     reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
682
683                 reg = makeAarch64RegID(reg, encoding);
684             }
685             else if (isFPInsn && !((IS_INSN_FP_CONV_FIX(insn) || (IS_INSN_FP_CONV_INT(insn))) && !IS_SOURCE_GP(insn))) {
686                 if (IS_INSN_FP_DATAPROC_ONESRC(insn)) {
687                     int opc = field<15, 16>(insn);
688                     switch (opc) {
689                         case 0:
690                             reg = aarch64::s0;
691                             break;
692                         case 1:
693                             reg = aarch64::d0;
694                             break;
695                         case 3:
696                             reg = aarch64::h0;
697                             break;
698                         default:
699                             isValid = false;
700                     }
701                 }
702                 else
703                     reg = isSinglePrec() ? aarch64::s0 : aarch64::d0;
704
705                 reg = makeAarch64RegID(reg, encoding);
706             }
707             else {
708                 if (encoding == 31)
709                     reg = ((IS_INSN_ADDSUB_IMM(insn) || IS_INSN_ADDSUB_EXT(insn) || IS_INSN_LOGICAL_IMM(insn)) &&
710                            !isPstateWritten) ? (is64Bit ? aarch64::sp : aarch64::wsp) : (is64Bit ? aarch64::zr
711                                                                                                  : aarch64::wzr);
712                 else
713                     reg = is64Bit ? aarch64::x0 : aarch64::w0;
714
715                 if (isValid && encoding != 31)
716                     reg = makeAarch64RegID(reg, encoding);
717             }
718
719             return makeRegisterExpression(reg);
720         }
721
722         void InstructionDecoder_aarch64::OPRRd() {
723             Expression::Ptr reg = makeRdExpr();
724             int cmode = field<12, 15>(insn);
725
726             bool isRdRead = false;
727             if (((IS_INSN_SIMD_VEC_INDEX(insn) || IS_INSN_SCALAR_INDEX(insn)) && !(cmode & 0x8)) ||
728                 (IS_INSN_SIMD_MOD_IMM(insn) &&
729                  (((cmode & 0x8) && !(cmode & 0x4) && (cmode & 0x1)) ||
730                   (!(cmode & 0x8) && (cmode & 0x1)))))
731                 isRdRead = true;
732             //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)
733             insn_in_progress->appendOperand(reg, isRdRead, true);
734         }
735
736         void InstructionDecoder_aarch64::OPRcmode() {
737             cmode = field<12, 15>(insn);
738         }
739
740         void InstructionDecoder_aarch64::OPRop() {
741             op = field<29, 29>(insn);
742         }
743
744         void InstructionDecoder_aarch64::OPRa() {
745             simdAlphabetImm |= (simdAlphabetImm & 0x7F) | (field<18, 18>(insn) << 7);
746         }
747
748         void InstructionDecoder_aarch64::OPRb() {
749             simdAlphabetImm |= (simdAlphabetImm & 0xBF) | (field<17, 17>(insn) << 6);
750         }
751
752         void InstructionDecoder_aarch64::OPRc() {
753             simdAlphabetImm |= (simdAlphabetImm & 0xDF) | (field<16, 16>(insn) << 5);
754         }
755
756         void InstructionDecoder_aarch64::OPRd() {
757             simdAlphabetImm |= (simdAlphabetImm & 0xEF) | (field<9, 9>(insn) << 4);
758         }
759
760         void InstructionDecoder_aarch64::OPRe() {
761             simdAlphabetImm |= (simdAlphabetImm & 0xF7) | (field<8, 8>(insn) << 3);
762         }
763
764         void InstructionDecoder_aarch64::OPRf() {
765             simdAlphabetImm |= (simdAlphabetImm & 0xFB) | (field<7, 7>(insn) << 2);
766         }
767
768         void InstructionDecoder_aarch64::OPRg() {
769             simdAlphabetImm |= (simdAlphabetImm & 0xFD) | (field<6, 6>(insn) << 1);
770         }
771
772         void InstructionDecoder_aarch64::OPRh() {
773             simdAlphabetImm |= (simdAlphabetImm & 0xFE) | (field<5, 5>(insn));
774         }
775
776         void InstructionDecoder_aarch64::OPRlen() {
777             //reuse immlo
778             immlo = field<13, 14>(insn);
779         }
780
781         Expression::Ptr InstructionDecoder_aarch64::makeRnExpr() {
782             int encoding = field<5, 9>(insn);
783             MachRegister reg;
784
785             if (isSIMDInsn && !IS_INSN_LDST(insn)) {
786                 if (IS_INSN_SIMD_COPY(insn)) {
787                     unsigned int op = field<29, 29>(insn);
788                     unsigned int imm4 = field<11, 14>(insn);
789                     unsigned int imm5 = field<16, 20>(insn);
790
791                     //ins (element)
792                     if (op == 0x1) {
793                         reg = (imm4 & 0x8) ? aarch64::q0 : aarch64::d0;
794                     }
795                     else {
796                         switch (imm4) {
797                             //dup (element), smov, umov
798                             case 0x0:
799                             case 0x5:
800                             case 0x7:
801                                 reg = (imm5 & 0x10) ? aarch64::q0 : aarch64::d0;
802                                 break;
803                                 //dup (general), ins (general)
804                             case 0x1:
805                             case 0x3:
806                                 if (imm5 & 0x1 || imm5 & 0x2 || imm5 & 0x4) {
807                                     reg = encoding == 31 ? aarch64::wzr : aarch64::w0;
808                                 }
809                                 else {
810                                     reg = encoding == 31 ? aarch64::zr : aarch64::x0;
811                                 }
812                                 break;
813                             default:
814                                 isValid = false;
815                                 break;
816                         }
817                     }
818                 }
819                 else if (IS_INSN_SCALAR_COPY(insn)) {
820                     int imm5 = field<16, 20>(insn);
821
822                     reg = (imm5 & 0x10) ? aarch64::q0 : aarch64::d0;
823                 }
824                 else if (IS_INSN_SCALAR_PAIR(insn)) {
825                     if (size != -1) {
826                         if (size == 0x3)
827                             reg = aarch64::q0;
828                         else
829                             isValid = false;
830                     }
831                     else if (_szField != -1) {
832                         switch (_szField) {
833                             case 0x0:
834                                 reg = aarch64::d0;
835                                 break;
836                             case 0x1:
837                                 reg = aarch64::q0;
838                                 break;
839                         }
840                     }
841                     else
842                         isValid = false;
843                 }
844                 else if (IS_INSN_SCALAR_SHIFT_IMM(insn)) {
845                     int switchbit = highest_set_bit(field<19, 22>(insn));
846                     bool isRnVa = false;
847                     int opcode = field<11, 15>(insn);
848
849                     if ((opcode & 0x1C) == 0x10)
850                         isRnVa = true;
851
852                     switch (switchbit) {
853                         case 0x1:
854                             reg = isRnVa ? aarch64::h0 : aarch64::b0;
855                             break;
856                         case 0x2:
857                             reg = isRnVa ? aarch64::s0 : aarch64::h0;
858                             break;
859                         case 0x3:
860                             reg = isRnVa ? aarch64::d0 : aarch64::s0;
861                             break;
862                         case 0x4:
863                             isRnVa ? (isValid = false) : (reg = aarch64::d0);
864                             break;
865                         default:
866                             isValid = false;
867                     }
868                 }
869                 else if (IS_INSN_SCALAR_3DIFF(insn)) {
870                     switch (size) {
871                         case 0x1:
872                             reg = aarch64::h0;
873                             break;
874                         case 0x2:
875                             reg = aarch64::s0;
876                             break;
877                         default:
878                             isValid = false;
879                     }
880                 }
881                 else if (IS_INSN_SCALAR_INDEX(insn)) {
882                     int opcode = field<12, 15>(insn);
883
884                     //sqdmlal, sqdmlsl, sqdmull
885                     //sqdmulh, sqrdmulh
886                     if ((opcode & 0xC) == 0xC || (opcode & 0x3) == 0x3) {
887                         switch (size) {
888                             case 0x1:
889                                 reg = aarch64::h0;
890                                 break;
891                             case 0x2:
892                                 reg = aarch64::s0;
893                                 break;
894                             default:
895                                 isValid = false;
896                         }
897                     }
898                         //fmla, fmls, fmul, fmulx
899                     else if ((opcode & 0x3) == 0x1) {
900                         switch (_szField) {
901                             case 0x0:
902                                 reg = aarch64::s0;
903                                 break;
904                             case 0x1:
905                                 reg = aarch64::d0;
906                                 break;
907                             default:
908                                 isValid = false;
909                         }
910                     }
911                     else
912                         isValid = false;
913                 }
914                 else if (IS_INSN_SCALAR_2REG_MISC(insn) || IS_INSN_SCALAR_3SAME(insn)) {
915                     //some instructions in this set rely on sz for choosing the register and some on size
916                     //only one of them is set for an instruction, however
917                     bool isRnVa = false;
918                     int opcode = field<12, 16>(insn);
919                     if (!IS_INSN_SCALAR_3SAME(insn) && (opcode & 0x18) == 0x10 && (opcode & 0x1) == 0x0)
920                         isRnVa = true;
921
922                     if (_szField == -1) {
923                         switch (size) {
924                             case 0x0:
925                                 reg = isRnVa ? aarch64::h0 : aarch64::b0;
926                                 break;
927                             case 0x1:
928                                 reg = isRnVa ? aarch64::s0 : aarch64::h0;
929                                 break;
930                             case 0x2:
931                                 reg = isRnVa ? aarch64::d0 : aarch64::s0;
932                                 break;
933                             case 0x3:
934                                 isRnVa ? (isValid = false) : (reg = aarch64::d0);
935                                 break;
936                             default:
937                                 isValid = false;
938                         }
939                     }
940                     else {
941                         switch (_szField) {
942                             case 0x0:
943                                 isRnVa ? (isValid = false) : (reg = aarch64::s0);
944                                 break;
945                             case 0x1:
946                                 reg = aarch64::d0;
947                                 break;
948                             default:
949                                 isValid = false;
950                         }
951                     }
952                 }
953                 else if (IS_INSN_SIMD_VEC_INDEX(insn)) {
954                     //the below two conditions can easily be combined into one, but would be difficult to understand
955                     if (field<13, 13>(insn) == 0x1)
956                         reg = _Q == 0x1 ? aarch64::hq0 : aarch64::d0;
957                     else
958                         //sqdmulh, mul, sqrdmulh, fmla, fmls, fmul, mla, mls, fmulx
959                         reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
960                 }
961                 else if (IS_INSN_SIMD_TAB_LOOKUP(insn)) {
962                     reg = _Q == 1 ? aarch64::q0 : aarch64::d0;
963
964                     for (int reg_index = immlo; reg_index > 0; reg_index--) {
965                         insn_in_progress->appendOperand(
966                                 makeRegisterExpression(makeAarch64RegID(reg, (encoding + reg_index) % 32)), true,
967                                 false);
968                     }
969                 }
970                 else if (IS_INSN_SIMD_3DIFF(insn)) {
971                     entryID op = insn_in_progress->getOperation().operationID;
972
973                     if (op == aarch64_op_saddw_advsimd || op == aarch64_op_ssubw_advsimd ||
974                         op == aarch64_op_addhn_advsimd || op == aarch64_op_subhn_advsimd ||
975                         op == aarch64_op_uaddw_advsimd || op == aarch64_op_usubw_advsimd ||
976                         op == aarch64_op_raddhn_advsimd || op == aarch64_op_rsubhn_advsimd)
977                         reg = aarch64::q0;
978                     else
979                         reg = _Q == 0x1 ? aarch64::hq0 : aarch64::d0;
980                 }
981                 else
982                     reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
983
984                 if (!(reg == aarch64::wzr || reg == aarch64::zr))
985                     reg = makeAarch64RegID(reg, encoding);
986             }
987             else if (isFPInsn && !((IS_INSN_FP_CONV_FIX(insn) || (IS_INSN_FP_CONV_INT(insn))) && IS_SOURCE_GP(insn))) {
988                 switch (_typeField) {
989                     case 0:
990                         reg = aarch64::s0;
991                         break;
992                     case 1:
993                         reg = aarch64::d0;
994                         break;
995                     case 3:
996                         reg = aarch64::h0;
997                         break;
998                     default:
999                         isValid = false;
1000                 }
1001
1002                 reg = makeAarch64RegID(reg, encoding);
1003             }
1004             else if (IS_INSN_LDST(insn)) {
1005                 reg = encoding == 31 ? aarch64::sp : aarch64::x0;
1006
1007                 if (encoding != 31)
1008                     reg = makeAarch64RegID(reg, encoding);
1009             }
1010             else {
1011                 if (encoding == 31)
1012                     reg = (IS_INSN_ADDSUB_IMM(insn) || IS_INSN_ADDSUB_EXT(insn)) ? (is64Bit ? aarch64::sp
1013                                                                                             : aarch64::wsp) : (is64Bit
1014                                                                                                                ? aarch64::zr
1015                                                                                                                : aarch64::wzr);
1016                 else
1017                     reg = is64Bit ? aarch64::x0 : aarch64::w0;
1018
1019                 if (isValid && encoding != 31)
1020                     reg = makeAarch64RegID(reg, encoding);
1021             }
1022
1023             return makeRegisterExpression(reg);
1024         }
1025
1026         Expression::Ptr InstructionDecoder_aarch64::makePCExpr() {
1027             MachRegister baseReg = aarch64::pc;
1028
1029             return makeRegisterExpression(makeAarch64RegID(baseReg, 0));
1030         }
1031
1032         Expression::Ptr InstructionDecoder_aarch64::makePstateExpr() {
1033             MachRegister baseReg = aarch64::pstate;
1034
1035             return makeRegisterExpression(makeAarch64RegID(baseReg, 0));
1036         }
1037
1038
1039         void InstructionDecoder_aarch64::getMemRefIndexLiteral_OffsetLen(int &immVal, int &immLen) {
1040             immVal = field<5, 23>(insn);
1041             immVal = immVal << 2; //immVal:00
1042             immLen = (23 - 5 + 1) + 2;
1043             return;
1044         }
1045
1046         void InstructionDecoder_aarch64::getMemRefIndexLiteral_RT(Result_Type &rt) {
1047             int size = field<30, 31>(insn);
1048             switch (size) {
1049                 case 0x0:
1050                     rt = u32;
1051                     break;
1052                 case 0x1:
1053                     rt = u64;
1054                     break;
1055                 case 0x2:
1056                     rt = s32;
1057                     break;
1058                 case 0x3:
1059                     break;
1060                 default:
1061                     isValid = false;
1062                     break;
1063             }
1064         }
1065
1066 // ****************************************
1067 // load/store literal
1068 // eg: load Xt, <literal>
1069 // => offset = signextend(<literal>:00, 64)
1070 // load from [PC + offset] to Xt
1071 // ****************************************
1072         Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexLiteral() {
1073             int immVal, immLen;
1074             getMemRefIndexLiteral_OffsetLen(immVal, immLen);
1075
1076             Expression::Ptr label = Immediate::makeImmediate(Result(s64, sign_extend64(immLen, immVal)));
1077
1078             Result_Type rt = invalid_type;
1079             getMemRefIndexLiteral_RT(rt);
1080
1081             return makeDereferenceExpression(makeAddExpression(makePCExpr(), label, u64), rt);
1082         }
1083
1084 // TODO potential bug: do we need to distinguish signed and unsigned here?
1085 // this funciton is to get the mem ref size
1086 // shared by ld/st uimm, post, pre, reg
1087         void InstructionDecoder_aarch64::getMemRefIndex_RT(Result_Type &rt) {
1088             unsigned int opc1 = field<23, 23>(insn);
1089             unsigned int size = field<30, 31>(insn);
1090
1091             if (opc1 == 1) {
1092                 switch (size) {
1093                     case 0:
1094                         rt = s8;
1095                         break;
1096                     case 1:
1097                         rt = s16;
1098                         break;
1099                     case 2:
1100                         rt = s32;
1101                         break;
1102                     case 3:
1103                         rt = s64;
1104                         break;
1105                     default:
1106                         isValid = false;
1107                         //should only be 2 or 3
1108                         break;
1109                 }
1110             }
1111             else {
1112                 switch (size) {
1113                     case 0:
1114                         rt = u8;
1115                         break;
1116                     case 1:
1117                         rt = u16;
1118                         break;
1119                     case 2:
1120                         rt = u32;
1121                         break;
1122                     case 3:
1123                         rt = u64;
1124                         break;
1125                     default:
1126                         isValid = false;
1127                         //should only be 2 or 3
1128                         break;
1129                 }
1130             }
1131         }
1132
1133         void InstructionDecoder_aarch64::getMemRefPair_RT(Result_Type &rt) {
1134             unsigned int isSigned = field<30, 30>(insn);
1135             unsigned int size = field<31, 31>(insn);
1136
1137             // double the width
1138             switch (isSigned) {
1139                 case 0:
1140                     switch (size) {
1141                         case 0:
1142                             //rt = u32;
1143                             rt = u64;
1144                             break;
1145                         case 1:
1146                             //rt = u64;
1147                             rt = dbl128;
1148                             break;
1149                         default:
1150                             isValid = false;
1151                     }
1152                     break;
1153                 case 1:
1154                     switch (size) {
1155                         case 0:
1156                             //rt = s32;
1157                             rt = s64;
1158                             break;
1159                         case 1:
1160                         default:
1161                             isValid = false;
1162                     }
1163                     break;
1164                 default:
1165                     isValid = false;
1166                     break;
1167             }
1168         }
1169
1170         void InstructionDecoder_aarch64::getMemRefIndex_SizeSizelen(unsigned int &size, unsigned int &sizeLen) {
1171             size = field<30, 31>(insn);
1172             if (size == 0x0 && field<23, 23>(insn) == 0x1)
1173                 size = 4;
1174             sizeLen = 31 - 30 + 1 + (size / 4);
1175             return;
1176         }
1177
1178         void InstructionDecoder_aarch64::getMemRefIndexPrePost_ImmImmlen(unsigned int &immVal, unsigned int &immLen) {
1179             immVal = field<12, 20>(insn);
1180             immLen = 20 - 12 + 1;
1181             return;
1182         }
1183
1184         void InstructionDecoder_aarch64::getMemRefPair_ImmImmlen(unsigned int &immVal, unsigned int &immLen) {
1185             immVal = field<15, 21>(insn);
1186             immLen = 21 - 15 + 1;
1187             return;
1188         }
1189
1190 // ****************************************
1191 // load/store unsigned imm
1192 // eg: load Xt, [Xn, #imm]
1193 // => offset = unsignextend( imm , 64)
1194 // load from [PC + offset] to Xt
1195 // ****************************************
1196         Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexUImm() {
1197             assert(IS_INSN_LDST_UIMM(insn));
1198
1199             int immVal = field<10, 21>(insn);
1200             int immLen = 21 - 10 + 1;
1201
1202             unsigned int size = 0, sizeLen = 0;
1203             getMemRefIndex_SizeSizelen(size, sizeLen);
1204
1205             Expression::Ptr offset = Immediate::makeImmediate(
1206                     Result(u64, unsign_extend64(immLen + size, immVal << size)));
1207
1208             Result_Type rt;
1209             getMemRefIndex_RT(rt);
1210             return makeDereferenceExpression(makeAddExpression(makeRnExpr(), offset, u64), rt);
1211         }
1212
1213         Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndex_offset9() {
1214             unsigned int immVal = 0, immLen = 0;
1215             getMemRefIndexPrePost_ImmImmlen(immVal, immLen);
1216             return Immediate::makeImmediate(Result(u32, sign_extend32(immLen, immVal)));
1217         }
1218
1219 // scale = 2 + opc<1>
1220 // scale = 1<<scale
1221 // LSL(sign_ex(imm7 , 64), scale)
1222         Expression::Ptr InstructionDecoder_aarch64::makeMemRefPair_offset7() {
1223             /*
1224     unsigned int scaleVal = field<31, 31>(insn);
1225     unsigned int scaleLen = 8;
1226     scaleVal += 2;
1227     Expression::Ptr scale = Immediate::makeImmediate(Result(u32, unsign_extend32(scaleLen, 1<<scaleVal)));
1228     */
1229
1230             unsigned int immVal = 0, immLen = 0;
1231             getMemRefPair_ImmImmlen(immVal, immLen);
1232
1233             Expression::Ptr lhs = Immediate::makeImmediate(Result(s64, sign_extend64(immLen, immVal)));
1234             int scale = 2;
1235             if (isSIMDInsn)
1236                 scale += field<30, 31>(insn);
1237             else
1238                 scale += field<31, 31>(insn);
1239             Expression::Ptr rhs = Immediate::makeImmediate(Result(u8, scale));
1240
1241             //return makeMultiplyExpression(imm7, scale, s64);
1242             return makeLeftShiftExpression(lhs, rhs, s64);
1243         }
1244
1245         Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndex_addOffset9() {
1246             Expression::Ptr offset = makeMemRefIndex_offset9();
1247             return makeAddExpression(makeRnExpr(), offset, u64);
1248         }
1249
1250         Expression::Ptr InstructionDecoder_aarch64::makeMemRefPair_addOffset7() {
1251             Expression::Ptr offset = makeMemRefPair_offset7();
1252             return makeAddExpression(makeRnExpr(), offset, u64);
1253         }
1254
1255         Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexPre() {
1256             Result_Type rt;
1257             getMemRefIndex_RT(rt);
1258             return makeDereferenceExpression(makeMemRefIndex_addOffset9(), rt);
1259         }
1260
1261         Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexPost() {
1262             Result_Type rt;
1263             getMemRefIndex_RT(rt);
1264             return makeDereferenceExpression(makeRnExpr(), rt);
1265         }
1266
1267         Expression::Ptr InstructionDecoder_aarch64::makeMemRefPairPre() {
1268             Result_Type rt;
1269             getMemRefPair_RT(rt);
1270             return makeDereferenceExpression(makeMemRefPair_addOffset7(), rt);
1271         }
1272
1273         Expression::Ptr InstructionDecoder_aarch64::makeMemRefPairPost() {
1274             Result_Type rt;
1275             getMemRefPair_RT(rt);
1276             return makeDereferenceExpression(makeRnExpr(), rt);
1277         }
1278
1279         void InstructionDecoder_aarch64::getMemRefEx_RT(Result_Type &rt) {
1280             unsigned int sz = field<30, 31>(insn);
1281             switch (sz) {
1282                 case 0x00: //B
1283                     rt = u8;
1284                     break;
1285                 case 0x01: //H
1286                     rt = u16;
1287                     break;
1288                 case 0x02: //32b
1289                     rt = u32;
1290                     break;
1291                 case 0x03: //64b
1292                     rt = u64;
1293                     break;
1294                 default:
1295                     rt = u64;
1296             }
1297         }
1298
1299         Expression::Ptr InstructionDecoder_aarch64::makeMemRefEx() {
1300             Result_Type rt;
1301             getMemRefEx_RT(rt);
1302             return makeDereferenceExpression(makeRnExpr(), rt);
1303         }
1304
1305         void InstructionDecoder_aarch64::OPRQ() {
1306             _Q = field<30, 30>(insn);
1307         }
1308
1309         void InstructionDecoder_aarch64::OPRL() {
1310             _L = field<30, 30>(insn);
1311         }
1312
1313         unsigned int InstructionDecoder_aarch64::getMemRefSIMD_MULT_T() {
1314             unsigned int Q = field<30, 30>(insn);
1315             return Q ? 128 : 64;
1316         }
1317
1318         void InstructionDecoder_aarch64::getMemRefSIMD_MULT_RT(Result_Type &rt) {
1319             unsigned int tmpSize = getMemRefSIMD_MULT_T();
1320             unsigned int rpt = 0, selem = 0;
1321             getSIMD_MULT_RptSelem(rpt, selem);
1322             tmpSize = tmpSize * rpt * selem;
1323             switch (tmpSize) {
1324                 case 64:
1325                     rt = u64;
1326                     return;
1327                 case 128:
1328                     rt = dbl128;
1329                     return;
1330                 case 192:
1331                     rt = m192;
1332                     return;
1333                 case 256:
1334                     rt = m256;
1335                     return;
1336                 case 384:
1337                     rt = m384;
1338                     return;
1339                 case 512:
1340                     rt = m512;
1341                     return;
1342                 default:
1343                     isValid = false;
1344                     return;
1345             }
1346         }
1347
1348         unsigned int InstructionDecoder_aarch64::getSIMD_SING_selem() {
1349             return (((field<13, 13>(insn) << 1) & 0x2) | (field<21, 21>(insn) & 0x1)) + 0x1;
1350         }
1351
1352         void InstructionDecoder_aarch64::getMemRefSIMD_SING_RT(Result_Type &rt) {
1353             unsigned int tmpSize = getMemRefSIMD_SING_T();
1354             unsigned int selem = getSIMD_SING_selem();
1355             switch (selem * tmpSize) {
1356                 case 8:
1357                     rt = u8;
1358                     break;
1359                 case 16:
1360                     rt = u16;
1361                     break;
1362                 case 24:
1363                     rt = u24;
1364                     break;
1365                 case 32:
1366                     rt = u32;
1367                     break;
1368                 case 48:
1369                     rt = u48;
1370                     break;
1371                 case 64:
1372                     rt = u64;
1373                     break;
1374                 case 96:
1375                     rt = m96;
1376                     break;
1377                 case 128:
1378                     rt = dbl128;
1379                     break;
1380                 case 192:
1381                     rt = m192;
1382                     break;
1383                 case 256:
1384                     rt = m256;
1385                     break;
1386                 default:
1387                     isValid = false;
1388                     break;
1389             }
1390         }
1391
1392         unsigned int InstructionDecoder_aarch64::getMemRefSIMD_SING_T() {
1393             unsigned int opcode = field<14, 15>(insn);
1394             unsigned int S = field<12, 12>(insn);
1395             unsigned int size = field<10, 11>(insn);
1396
1397             switch (opcode) {
1398                 case 0x0:
1399                     return 8;
1400                 case 0x1:
1401                     if ((size & 0x1) == 0x0)
1402                         return 16;
1403                     else
1404                         isValid = false;
1405                     break;
1406                 case 0x2:
1407                     if (size == 0x0)
1408                         return 32;
1409                     else if (size == 0x1 && S == 0)
1410                         return 64;
1411                     else
1412                         isValid = false;
1413                     break;
1414                 case 0x3:
1415                     return 8 << size;
1416                 default:
1417                     isValid = false;
1418             }
1419
1420             return 0;
1421         }
1422
1423         Expression::Ptr InstructionDecoder_aarch64::makeMemRefSIMD_MULT() {
1424             Result_Type rt;
1425             getMemRefSIMD_MULT_RT(rt);
1426             return makeDereferenceExpression(makeRnExpr(), rt);
1427         }
1428
1429         Expression::Ptr InstructionDecoder_aarch64::makeMemRefSIMD_SING() {
1430             Result_Type rt;
1431             getMemRefSIMD_SING_RT(rt);
1432             return makeDereferenceExpression(makeRnExpr(), rt);
1433         }
1434
1435         void InstructionDecoder_aarch64::getMemRefExPair_RT(Result_Type &rt) {
1436             int size = field<30, 30>(insn);
1437             switch (size) {
1438                 case 0:
1439                     rt = u64;
1440                     break;
1441                 case 1:
1442                     rt = dbl128;
1443                     break;
1444                 default:
1445                     isValid = false;
1446                     break;
1447             }
1448         }
1449
1450         Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair() {
1451             Result_Type rt;
1452             getMemRefExPair_RT(rt);
1453             return makeDereferenceExpression(makeRnExpr(), rt);
1454         }
1455
1456 /*
1457 Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair16B(){
1458     return makeDereferenceExpression(makeRnExpr(), dbl128);
1459 }
1460 */
1461
1462 /*
1463 Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair2(){
1464     unsigned int immLen = 4, immVal = 8;
1465     Expression::Ptr offset = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));
1466     return makeDereferenceExpression(makeAddExpression(makeRnExpr(), offset, u64) , u64);
1467 }
1468 */
1469
1470         Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_Rm() {
1471             unsigned int option = field<13, 15>(insn);
1472             if ((option & 2) != 2)
1473                 isValid = false;
1474             MachRegister baseReg = ((option & 0x3) == 0x2) ? aarch64::w0 : aarch64::x0;
1475             unsigned int encoding = field<16, 20>(insn);
1476
1477             if (encoding == 31)//zero register
1478                 return makeRegisterExpression(makeAarch64RegID(aarch64::zr, 0));
1479             else
1480                 return makeRegisterExpression(makeAarch64RegID(baseReg, encoding));
1481         }
1482
1483         Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_amount() {
1484             unsigned int S = field<12, 12>(insn);
1485             unsigned int amountVal = is64Bit ? (S == 0 ? 0 : 2) : (S == 0 ? 0 : 3);
1486             unsigned int amountLen = 2;
1487
1488             return Immediate::makeImmediate(Result(u32, unsign_extend32(amountLen, amountVal)));
1489         }
1490
1491         Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_ext() {
1492             int immLen = 2;
1493             int immVal = 0; //for amount
1494
1495             int S = field<12, 12>(insn);
1496             int size = field<30, 31>(insn);
1497
1498             if (size == 2) { //32bit
1499                 immVal = S == 0 ? 0 : (S == 1 ? 2 : -1);
1500                 if (immVal == -1)
1501                     isValid = false;
1502             }
1503             else if (size == 3) { //64bit
1504                 immVal = S == 0 ? 0 : (S == 1 ? 3 : -1);
1505                 if (immVal == -1)
1506                     isValid = false;
1507             }
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                 insn_in_progress->appendOperand(makeMemRefPairPre(), true, false);
1568             }
1569             else if (IS_INSN_LDST_PAIR_POST(insn)
1570                      || IS_INSN_LDST_PAIR_OFFSET(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                 insn_in_progress->appendOperand(makeMemRefPairPre(), false, true);
1633             }
1634             else if (IS_INSN_LDST_PAIR_POST(insn)
1635                      || IS_INSN_LDST_PAIR_OFFSET(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::zr : 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
1865         template<unsigned int endBit, unsigned int startBit>
1866         void InstructionDecoder_aarch64::OPRN() {
1867             hasN = true;
1868             nField = field<startBit, endBit>(insn);
1869             nLen = endBit - startBit + 1;
1870         }
1871
1872 // the call of this function should be generated by decoder gen for ld/st class
1873 // except for ld/st{s, h, w} subclass
1874         void InstructionDecoder_aarch64::setRegWidth() {
1875             //is64Bit is by default set to TRUE
1876             unsigned int opc = 0x3 & field<22, 23>(insn);
1877             unsigned int opc0 = opc & 0x1;
1878             unsigned int opc1 = (opc & 0x2) >> 1;
1879             unsigned int sz = 0x3 & field<30, 31>(insn);
1880
1881             if (IS_INSN_LDST(insn)) {
1882                 if (IS_INSN_LDST_UIMM(insn) || IS_INSN_LDST_UNSCALED(insn)
1883                     || IS_INSN_LDST_UNPRIV(insn) || IS_INSN_LDST_POST(insn)
1884                     || IS_INSN_LDST_PRE(insn) || IS_INSN_LDST_REG(insn)) {
1885                     if (opc1 == 0) {
1886                         if (field<30, 31>(insn) != 3)
1887                             is64Bit = false;
1888                         return;
1889                     } else {
1890                         if (sz == 3) {
1891                             if (opc0 == 1)
1892                                 isValid = false;
1893                         }
1894                         else {
1895                             if (sz == 2 && opc0 == 1)
1896                                 isValid = false;
1897                             if (opc0 == 1)
1898                                 is64Bit = false;
1899                         }
1900                         return;
1901                     }
1902                 }
1903                 else if (IS_INSN_LDST_EX(insn)) {
1904                     switch (sz) {
1905                         case 2:
1906                         case 0:
1907                         case 1:
1908                             is64Bit = false;
1909                             break;
1910                         case 3:
1911                         default:
1912                             return;
1913                     }
1914                 }
1915                 else if (IS_INSN_LDST_PAIR(insn)) {
1916                     switch (sz) {
1917                         case 0:
1918                             is64Bit = false;
1919                             break;
1920                         case 1:
1921                         case 2:
1922                         case 3:
1923                         default:
1924                             return;
1925                     }
1926                 }
1927                 else if (IS_INSN_LD_LITERAL(insn)) {
1928                     switch (sz) {
1929                         case 0:
1930                             is64Bit = false;
1931                         case 1:
1932                         case 2:
1933                         case 3:
1934                         default:
1935                             return;
1936                     }
1937                 }
1938                 else {
1939                     isValid = false;
1940                 }
1941             } else {
1942                 isValid = false;
1943             }
1944             return;
1945         }
1946
1947         MachRegister InstructionDecoder_aarch64::getLoadStoreSimdRegister(int encoding) {
1948             MachRegister reg;
1949
1950             if (size != -1) {
1951                 switch (size) {
1952                     case 0x0:
1953                         reg = (field<23, 23>(insn) == 0x1) ? aarch64::q0 : aarch64::b0;
1954                         break;
1955                     case 0x1:
1956                         reg = aarch64::h0;
1957                         break;
1958                     case 0x2:
1959                         reg = aarch64::s0;
1960                         break;
1961                     case 0x3:
1962                         reg = aarch64::d0;
1963                         break;
1964                 }
1965             }
1966             else {
1967                 switch (field<30, 31>(insn)) {
1968                     case 0x0:
1969                         reg = aarch64::s0;
1970                         break;
1971                     case 0x1:
1972                         reg = aarch64::d0;
1973                         break;
1974                     case 0x2:
1975                         reg = aarch64::q0;
1976                         break;
1977                     case 0x3:
1978                         isValid = false;
1979                         break;
1980                 }
1981             }
1982
1983             return makeAarch64RegID(reg, encoding);
1984         }
1985
1986         Expression::Ptr InstructionDecoder_aarch64::makeRtExpr() {
1987             int encoding = field<0, 4>(insn);
1988             MachRegister reg;
1989
1990             if (isFPInsn) {
1991                 reg = makeAarch64RegID(isSinglePrec() ? aarch64::s0 : aarch64::d0, encoding);
1992             }
1993             else if (isSIMDInsn) {
1994                 reg = getLoadStoreSimdRegister(encoding);
1995             }
1996             else {
1997                 reg = is64Bit ? ((encoding == 31) ? aarch64::zr : aarch64::x0) : ((encoding == 31) ? aarch64::wzr
1998                                                                                                    : aarch64::w0);
1999                 if (encoding != 31)
2000                     reg = makeAarch64RegID(reg, encoding);
2001             }
2002
2003             return makeRegisterExpression(reg);
2004         }
2005
2006         void InstructionDecoder_aarch64::getSIMD_MULT_RptSelem(unsigned int &rpt, unsigned int &selem) {
2007             unsigned opcode = field<12, 15>(insn);
2008             switch (opcode) {
2009                 case 0x0:
2010                     rpt = 1;
2011                     selem = 4;
2012                     break;
2013                 case 0x2:
2014                     rpt = 4;
2015                     selem = 1;
2016                     break;
2017                 case 0x4:
2018                     rpt = 1;
2019                     selem = 3;
2020                     break;
2021                 case 0x6:
2022                     rpt = 3;
2023                     selem = 1;
2024                     break;
2025                 case 0x7:
2026                     rpt = 1;
2027                     selem = 1;
2028                     break;
2029                 case 0x8:
2030                     rpt = 1;
2031                     selem = 2;
2032                     break;
2033                 case 0xa:
2034                     rpt = 2;
2035                     selem = 1;
2036                     break;
2037                 default:
2038                     isValid = false;
2039                     return;
2040             }
2041             if (rpt == 0 || selem == 0)
2042                 isValid = false;
2043             return;
2044         }
2045
2046         void InstructionDecoder_aarch64::OPRRt() {
2047             int encoding = field<0, 4>(insn);
2048             entryID op = insn_in_progress->getOperation().operationID;
2049
2050             if (IS_INSN_BRANCHING(insn)) {
2051                 if (encoding == 31)
2052                     insn_in_progress->appendOperand(makeRegisterExpression(is64Bit ? aarch64::zr : aarch64::wzr), true,
2053                                                     false);
2054                 else
2055                     insn_in_progress->appendOperand(
2056                             makeRegisterExpression(makeAarch64RegID(is64Bit ? aarch64::x0 : aarch64::w0, encoding)),
2057                             true, false);
2058             }
2059             else if (op == aarch64_op_prfm_imm || op == aarch64_op_prfm_lit || op == aarch64_op_prfm_reg) {
2060                 Expression::Ptr prfop;
2061                 Result arg = Result(u32, unsign_extend32(5, encoding));
2062                 
2063                 if((encoding & 0x1E) == 0x6 || (encoding & 0x1E) == 0xE || (encoding & 0x1E) == 0x16 || (encoding & 0x18) == 0x18)
2064                     prfop = Immediate::makeImmediate(arg);
2065                 else
2066                     prfop = ArmPrfmTypeImmediate::makeArmPrfmTypeImmediate(arg);
2067
2068                 insn_in_progress->appendOperand(prfop, true, false);
2069             }
2070         }
2071
2072         void InstructionDecoder_aarch64::OPRRtL() {
2073             int encoding = field<0, 4>(insn);
2074
2075             if (IS_INSN_LDST_SIMD_MULT(insn) || IS_INSN_LDST_SIMD_MULT_POST(insn)) {
2076                 unsigned int rpt, selem;
2077                 getSIMD_MULT_RptSelem(rpt, selem);
2078                 MachRegister reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
2079                 for (int it_rpt = rpt * selem - 1; it_rpt >= 0; it_rpt--) {
2080                     insn_in_progress->appendOperand(
2081                             makeRegisterExpression(makeAarch64RegID(reg, (encoding + it_rpt) % 32)), false, true);
2082                 }
2083             }
2084             else if (IS_INSN_LDST_SIMD_SING(insn) || IS_INSN_LDST_SIMD_SING_POST(insn)) {
2085                 unsigned int selem = getSIMD_SING_selem();
2086
2087                 MachRegister reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
2088
2089                 for (int it_selem = selem - 1; it_selem >= 0; it_selem--) {
2090                     insn_in_progress->appendOperand(
2091                             makeRegisterExpression(makeAarch64RegID(reg, (encoding + it_selem) % 32)), false, true);
2092                 }
2093             }
2094             else
2095                 insn_in_progress->appendOperand(makeRtExpr(), false, true);
2096         }
2097
2098         void InstructionDecoder_aarch64::OPRRtS() {
2099             int encoding = field<0, 4>(insn);
2100
2101             if (IS_INSN_LDST_SIMD_MULT(insn) || IS_INSN_LDST_SIMD_MULT_POST(insn)) {
2102                 unsigned int rpt, selem;
2103                 getSIMD_MULT_RptSelem(rpt, selem);
2104
2105                 MachRegister reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
2106
2107                 for (int it_rpt = rpt * selem - 1; it_rpt >= 0; it_rpt--) {
2108                     insn_in_progress->appendOperand(
2109                             makeRegisterExpression(makeAarch64RegID(reg, (encoding + it_rpt) % 32)), true, false);
2110                 }
2111             }
2112             else if (IS_INSN_LDST_SIMD_SING(insn) || IS_INSN_LDST_SIMD_SING_POST(insn)) {
2113                 unsigned int selem = getSIMD_SING_selem();
2114
2115                 MachRegister reg = _Q == 0x1 ? aarch64::q0 : aarch64::d0;
2116
2117                 for (int it_selem = selem - 1; it_selem >= 0; it_selem--) {
2118                     insn_in_progress->appendOperand(
2119                             makeRegisterExpression(makeAarch64RegID(reg, (encoding + it_selem) % 32)), true, false);
2120                 }
2121             }
2122             else
2123                 insn_in_progress->appendOperand(makeRtExpr(), true, false);
2124         }
2125
2126         Expression::Ptr InstructionDecoder_aarch64::makeRt2Expr() {
2127             MachRegister baseReg;
2128             int encoding = field<10, 14>(insn);
2129
2130             if (isFPInsn) {
2131                 baseReg = makeAarch64RegID(isSinglePrec() ? aarch64::s0 : aarch64::d0, encoding);
2132             }
2133             else if (isSIMDInsn) {
2134                 baseReg = getLoadStoreSimdRegister(encoding);
2135             }
2136             else {
2137                 baseReg = makeAarch64RegID(is64Bit ? aarch64::x0 : aarch64::w0, encoding);
2138             }
2139
2140             return makeRegisterExpression(baseReg);
2141         }
2142
2143         void InstructionDecoder_aarch64::OPRRt2() {
2144             assert(0);
2145         }
2146
2147         void InstructionDecoder_aarch64::OPRRt2L() {
2148             insn_in_progress->appendOperand(makeRt2Expr(), false, true);
2149         }
2150
2151         void InstructionDecoder_aarch64::OPRRt2S() {
2152             insn_in_progress->appendOperand(makeRt2Expr(), true, false);
2153         }
2154
2155         template<unsigned int endBit, unsigned int startBit>
2156         void InstructionDecoder_aarch64::OPRcond() {
2157             int condVal = field<startBit, endBit>(insn);
2158             if (IS_INSN_B_COND(insn)) {
2159                 insn_in_progress->getOperation().mnemonic += ".";
2160                 insn_in_progress->getOperation().mnemonic += condStringMap[condVal];
2161             }
2162             else {
2163                 if(IS_INSN_COND_SELECT(insn))
2164                     fix_condinsn_alias_and_cond(condVal);
2165                 else
2166                     oprRotateAmt++;
2167
2168                 Expression::Ptr cond = ArmConditionImmediate::makeArmConditionImmediate(Result(u8, condVal));
2169                 insn_in_progress->appendOperand(cond, true, false);
2170             }
2171
2172             isPstateRead = true;
2173         }
2174
2175         void InstructionDecoder_aarch64::OPRnzcv() {
2176             unsigned int nzcvVal = field<0, 3>(insn) << 28;
2177             Expression::Ptr nzcv = Immediate::makeImmediate(Result(u32, nzcvVal));
2178             insn_in_progress->appendOperand(nzcv, true, false);
2179
2180             isPstateWritten = true;
2181             oprRotateAmt++;
2182         }
2183
2184         void InstructionDecoder_aarch64::OPRop1() {
2185             op1Field = field<16, 18>(insn);
2186         }
2187
2188         void InstructionDecoder_aarch64::OPRop2() {
2189             op2Field = field<5, 7>(insn);
2190         }
2191
2192         void InstructionDecoder_aarch64::OPRCRm() {
2193             crmField = field<8, 11>(insn);
2194         }
2195
2196         void InstructionDecoder_aarch64::OPRCRn() {
2197         }
2198
2199         template<unsigned int endBit, unsigned int startBit>
2200         void InstructionDecoder_aarch64::OPRS() {
2201             sField = field<startBit, endBit>(insn);
2202         }
2203
2204         void InstructionDecoder_aarch64::OPRscale() {
2205             int scaleVal = 64 - field<10, 15>(insn);
2206
2207             Expression::Ptr scale = Immediate::makeImmediate(Result(u32, unsign_extend32(6, scaleVal)));
2208             insn_in_progress->appendOperand(scale, true, false);
2209         }
2210
2211         Expression::Ptr InstructionDecoder_aarch64::makeRaExpr() {
2212             int encoding = field<10, 14>(insn);
2213             MachRegister reg;
2214
2215             if (isFPInsn) {
2216                 reg = makeAarch64RegID(isSinglePrec() ? aarch64::s0 : aarch64::d0, encoding);
2217             }
2218             else {
2219                 reg = is64Bit ? ((encoding == 31) ? aarch64::sp : aarch64::x0) : ((encoding == 31) ? aarch64::wsp
2220                                                                                                    : aarch64::w0);
2221                 if (encoding != 31)
2222                     reg = makeAarch64RegID(reg, encoding);
2223             }
2224
2225             return makeRegisterExpression(reg);
2226
2227         }
2228
2229         void InstructionDecoder_aarch64::OPRRa() {
2230             insn_in_progress->appendOperand(makeRaExpr(), true, false);
2231
2232             oprRotateAmt++;
2233         }
2234
2235         void InstructionDecoder_aarch64::OPRo0() {
2236
2237         }
2238
2239         void InstructionDecoder_aarch64::OPRb5() {
2240             OPRsf();
2241             hasb5 = true;
2242         }
2243
2244         void InstructionDecoder_aarch64::OPRb40() {
2245
2246         }
2247
2248         Expression::Ptr InstructionDecoder_aarch64::makeb40Expr() {
2249             int b40Val = field<19, 23>(insn);
2250             int bitpos = ((is64Bit ? 1 : 0) << 5) | b40Val;
2251
2252             return Immediate::makeImmediate(Result(u32, unsign_extend32(6, bitpos)));
2253         }
2254
2255         template<unsigned int endBit, unsigned int startBit>
2256         void InstructionDecoder_aarch64::OPRsz() {
2257             _szField = field<startBit, endBit>(insn);
2258         }
2259
2260         bool InstructionDecoder_aarch64::isSinglePrec() {
2261             if (isFPInsn && !isSIMDInsn) {
2262                 if (_typeField == -1) {
2263                     //TODO if the type field is not set, do sth else
2264                     OPRtype<23, 22>();
2265                 }
2266                 return _typeField == 0 ? true : false;
2267             } else if (isSIMDInsn) {
2268                 isValid = false; //not implemeted yet
2269             }
2270             return false;
2271         }
2272
2273         Expression::Ptr InstructionDecoder_aarch64::makeRsExpr() {
2274             MachRegister baseReg = isFPInsn ?
2275                                    (isSinglePrec() ? aarch64::s0 : aarch64::d0) :
2276                                    (is64Bit ? aarch64::x0 : aarch64::w0);
2277
2278             if (IS_INSN_LDST(insn)) {
2279                 baseReg = aarch64::w0;
2280             }
2281             return makeRegisterExpression(makeAarch64RegID(baseReg, field<16, 20>(insn)));
2282         }
2283
2284         void InstructionDecoder_aarch64::OPRRs() {
2285             insn_in_progress->appendOperand(makeRsExpr(), false, true);
2286         }
2287
2288         void InstructionDecoder_aarch64::makeBranchTarget(bool branchIsCall, bool bIsConditional, int immVal,
2289                                                           int immLen) {
2290             Expression::Ptr lhs = makePCExpr();
2291
2292             int offset = sign_extend64(immLen + 2, immVal * 4);
2293             Expression::Ptr rhs = Immediate::makeImmediate(Result(s64, offset));
2294
2295             insn_in_progress->addSuccessor(makeAddExpression(lhs, rhs, s64), branchIsCall, false, bIsConditional,
2296                                            false);
2297             if (branchIsCall) {
2298                 insn_in_progress->addSuccessor(makeFallThroughExpr(), false, false, false, true);
2299             }
2300
2301         }
2302
2303         Expression::Ptr InstructionDecoder_aarch64::makeFallThroughExpr() {
2304             return makeAddExpression(makePCExpr(), Immediate::makeImmediate(Result(u64, unsign_extend64(3, 4))), u64);
2305         }
2306
2307         template<typename T, Result_Type rT>
2308         Expression::Ptr InstructionDecoder_aarch64::fpExpand(int val) {
2309             int N, E, F;
2310             T frac, expandedImm, sign, exp;
2311
2312             N = (rT == s32) ? 32 : 64;
2313             E = (N == 32) ? 8 : 11;
2314             F = N - E - 1;
2315
2316             sign = (val & 0x80) >> 7;
2317
2318             int val6 = ((~val) & 0x40) >> 6, val6mask = (1 << (E - 3)) - 1;
2319             exp = (val6 << (E - 1)) | ((val6 ? val6mask : 0) << 2) | ((val & 0x30) >> 4);
2320
2321             frac = (val & 0xF) << (F - 4);
2322
2323             expandedImm = (sign << (E + F)) | (exp << F) | frac;
2324
2325             return Immediate::makeImmediate(Result(rT, expandedImm));
2326         }
2327
2328         template<typename T>
2329         Expression::Ptr InstructionDecoder_aarch64::makeLogicalImm(int immr, int imms, int immsLen, Result_Type rT) {
2330             int len = highest_set_bit((nField << immsLen) | (~imms & ((1 << immsLen) - 1))) - 1;
2331             int finalsize = (rT == u32 ? 32 : 64);
2332
2333             if (len < 1 || ((1 << len) > finalsize)) {
2334                 isValid = false;
2335                 return Immediate::makeImmediate(Result(u32, 0));
2336             }
2337             int levels = (1 << len) - 1;
2338
2339             int S = imms & levels;
2340             if (S == levels) {
2341                 isValid = false;
2342                 return Immediate::makeImmediate(Result(u32, 0));
2343             }
2344             int R = immr & levels;
2345
2346             int esize = 1 << len;
2347             T welem = (((T) 1) << (S + 1)) - 1;
2348
2349             T wmaskarg = welem;
2350             if (R != 0) {
2351                 T low = welem & (((T) 1 << R) - 1), high = welem & ((((T) 1 << (esize - R)) - 1) << R);
2352                 wmaskarg = (low << (esize - R)) | (high >> R);
2353             }
2354
2355             int idx;
2356             T wmask = wmaskarg;
2357
2358             for (idx = 1; idx < finalsize / esize; idx++) {
2359                 wmask |= (wmaskarg << (esize * idx));
2360             }
2361
2362             return Immediate::makeImmediate(Result(rT, wmask));
2363         }
2364
2365         bool InstructionDecoder_aarch64::fix_bitfieldinsn_alias(int immr, int imms) {
2366             entryID modifiedID = insn_in_progress->getOperation().operationID;
2367             bool do_further_processing = true;
2368
2369             switch (field<27, 30>(insn)) {
2370                 case 0x6:
2371                     modifiedID = (imms < immr) ? aarch64_op_bfi_bfm : aarch64_op_bfxil_bfm;
2372                     break;
2373                 case 0x2:
2374                     if (immr == 0 && (imms == 7 || imms == 15 || imms == 31)) {
2375                         do_further_processing = false;
2376                         switch (imms) {
2377                             case 7:
2378                                 modifiedID = aarch64_op_sxtb_sbfm;
2379                                 break;
2380                             case 15:
2381                                 modifiedID = aarch64_op_sxth_sbfm;
2382                                 break;
2383                             case 31:
2384                                 modifiedID = aarch64_op_sxtw_sbfm;
2385                                 break;
2386                         }
2387                     }
2388                     else
2389                         modifiedID = (imms < immr) ? aarch64_op_sbfiz_sbfm : aarch64_op_sbfx_sbfm;
2390                     break;
2391                 case 0xA:
2392                     if (immr == 0 && (imms == 7 || imms == 15)) {
2393                         do_further_processing = false;
2394                         switch (imms) {
2395                             case 7:
2396                                 modifiedID = aarch64_op_uxtb_ubfm;
2397                                 break;
2398                             case 15:
2399                                 modifiedID = aarch64_op_uxth_ubfm;
2400                                 break;
2401                         }
2402                     }
2403                     else if((imms != 31 || imms != 63) && (imms + 1) == immr)
2404                         modifiedID = aarch64_op_lsl_ubfm;
2405                     else if((imms & 0x1F) == 0x1F)
2406                         modifiedID = aarch64_op_lsr_ubfm;
2407                     else
2408                         modifiedID = (imms < immr) ? aarch64_op_ubfiz_ubfm : aarch64_op_ubfx_ubfm;
2409                     break;
2410                 default:
2411                     isValid = false;
2412             }
2413
2414             insn_in_progress->getOperation().operationID = modifiedID;
2415             insn_in_progress->getOperation().mnemonic = bitfieldInsnAliasMap[modifiedID];
2416
2417             return do_further_processing;
2418         }
2419
2420         void InstructionDecoder_aarch64::fix_condinsn_alias_and_cond(int &cond) {
2421             entryID modifiedID = insn_in_progress->getOperation().operationID;
2422             if (modifiedID == aarch64_op_csel)
2423                 return;
2424
2425             int Rm = field<16, 20>(insn), Rn = field<5, 9>(insn);
2426
2427             if (Rm == Rn && (cond & 0xE) != 0xE && modifiedID == aarch64_op_csneg) {
2428                 modifiedID = aarch64_op_cneg_csneg;
2429                 skipRm = true;
2430             } else if (Rm != 31 && Rn != 31 && (cond & 0xE) != 0xE && Rm == Rn) {
2431                 switch (modifiedID) {
2432                     case aarch64_op_csinc:
2433                         modifiedID = aarch64_op_cinc_csinc;
2434                         break;
2435                     case aarch64_op_csinv:
2436                         modifiedID = aarch64_op_cinv_csinv;
2437                         break;
2438                     default:
2439                         isValid = false;
2440                 }
2441
2442                 skipRm = true;
2443             } else if (Rm == 31 && Rn == 31 && (cond & 0xE) != 0xE) {
2444                 switch (modifiedID) {
2445                     case aarch64_op_csinc:
2446                         modifiedID = aarch64_op_cset_csinc;
2447                         break;
2448                     case aarch64_op_csinv:
2449                         modifiedID = aarch64_op_csetm_csinv;
2450                         break;
2451                     default:
2452                         isValid = false;
2453                 }
2454
2455                 skipRn = skipRm = true;
2456             }
2457
2458             insn_in_progress->getOperation().operationID = modifiedID;
2459             insn_in_progress->getOperation().mnemonic = condInsnAliasMap[modifiedID];
2460             if(skipRm)
2461                 cond = ((cond % 2) == 0) ? (cond + 1) : (cond - 1);
2462         }
2463
2464         template<unsigned int endBit, unsigned int startBit>
2465         void InstructionDecoder_aarch64::OPRimm() {
2466             int immVal = field<startBit, endBit>(insn);
2467             unsigned int immLen = endBit - startBit + 1;
2468
2469             if (IS_INSN_LDST(insn)) {
2470                 if (IS_INSN_LD_LITERAL(insn)) {
2471                     Expression::Ptr literal = makeMemRefIndexLiteral();
2472                     insn_in_progress->appendOperand(literal, true, false);
2473                 }
2474                 else if (IS_INSN_LDST_POST(insn)) {
2475                     Expression::Ptr offset = makeMemRefIndex_offset9();
2476                     insn_in_progress->appendOperand(offset, true, false);
2477                 }
2478                 else if (IS_INSN_LDST_PAIR_POST(insn)
2479                          || IS_INSN_LDST_PAIR_OFFSET(insn)) {
2480                     Expression::Ptr offset = makeMemRefPair_offset7();
2481                     insn_in_progress->appendOperand(offset, true, false);
2482                 }
2483
2484                 return;
2485             }
2486
2487             if (hasHw) {
2488                 processHwFieldInsn(immLen, immVal);
2489             }
2490             else if (hasN)        //logical (immediate), bitfield, extract
2491             {
2492                 if (IS_FIELD_IMMR(startBit, endBit)) {
2493                     immr = immVal;
2494                     immrLen = immLen;
2495                 }
2496                 else if (IS_FIELD_IMMS(startBit, endBit)) {
2497                     Expression::Ptr imm;
2498                     bool isLsrLsl = false;
2499
2500                     if (IS_INSN_LOGICAL_IMM(insn)) {
2501                         if (is64Bit)
2502                             imm = makeLogicalImm<uint64_t>(immr, immVal, immLen, u64);
2503                         else
2504                             imm = makeLogicalImm<uint32_t>(immr, immVal, immLen, u32);
2505                         
2506                         insn_in_progress->appendOperand(imm, true, false);
2507                     }
2508                     else {
2509                         entryID curID;
2510
2511                         if (IS_INSN_BITFIELD(insn)) {
2512                             if (!fix_bitfieldinsn_alias(immr, immVal))
2513                                 return;
2514
2515                             curID = insn_in_progress->getOperation().operationID;
2516                             if(curID == aarch64_op_lsl_ubfm || curID == aarch64_op_lsr_ubfm)
2517                                 isLsrLsl = true;
2518                             
2519                             if (curID != aarch64_op_lsr_ubfm && immVal < immr) {
2520                                 int divisor = is64Bit ? 64 : 32, factor = 0;
2521                                 while ((divisor * factor) < immr)
2522                                     factor += 1;
2523                                 immr = (divisor * factor) - immr;
2524                                 immrLen += 1;
2525
2526                                 immVal += 1;
2527                             }
2528                             else
2529                                 immVal = immVal + 1 - immr;
2530
2531                             immLen += 1;
2532                         }
2533
2534                         if(!isLsrLsl) {
2535                             imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));
2536                             insn_in_progress->appendOperand(imm, true, false);
2537                             oprRotateAmt++;
2538                         }
2539                     }
2540
2541                     if (IS_INSN_BITFIELD(insn)) {
2542                         imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immrLen, immr)));
2543                         insn_in_progress->appendOperand(imm, true, false);
2544                         if(!isLsrLsl)
2545                             oprRotateAmt--;
2546                     }
2547                 }
2548                 else
2549                     isValid = false;
2550             }
2551             else if (hasShift) {
2552                 if (IS_INSN_ADDSUB_SHIFT(insn) || IS_INSN_LOGICAL_SHIFT(insn))    //add-sub shifted | logical shifted
2553                 {
2554                     processShiftFieldShiftedInsn(immLen, immVal);
2555                 }
2556                 else if (IS_INSN_ADDSUB_IMM(insn))        //add-sub (immediate)
2557                 {
2558                     processShiftFieldImmInsn(immLen, immVal);
2559                 }
2560                 else
2561                     isValid = false;
2562             }
2563             else if (hasOption) {
2564                 if (IS_INSN_ADDSUB_EXT(insn))                                        //add-sub extended
2565                 {
2566                     Expression::Ptr expr = makeOptionExpression(immLen, immVal);
2567
2568                     insn_in_progress->appendOperand(expr, true, false);
2569                 }
2570                 else {
2571                     isValid = false;
2572                 }
2573             }
2574             else if (IS_INSN_BRANCHING(insn) && !IS_INSN_B_UNCOND_REG(
2575                     insn)) {        //unconditional branch (immediate), test and branch, compare and branch, conditional branch
2576                 bool bIsConditional = false;
2577                 if (!(IS_INSN_B_UNCOND(insn)))
2578                     bIsConditional = true;
2579
2580                 bool branchIsCall = bIsConditional ? false : (field<31, 31>(insn) == 1);
2581
2582                 insn_in_progress->appendOperand(makePCExpr(), false, true);
2583                 makeBranchTarget(branchIsCall, bIsConditional, immVal, immLen);
2584
2585                 if (hasb5)
2586                     insn_in_progress->appendOperand(makeb40Expr(), true, false);
2587
2588                 if (bIsConditional)
2589                     insn_in_progress->addSuccessor(makeFallThroughExpr(), false, false, true, true);
2590             }
2591             else if (IS_INSN_PCREL_ADDR(insn))                                    //pc-relative addressing
2592             {
2593                 if (IS_FIELD_IMMLO(startBit, endBit)) {
2594                     immlo = immVal;
2595                     immloLen = endBit - startBit + 1;
2596                 }
2597                 else if (IS_FIELD_IMMHI(startBit, endBit)) {
2598                     int page = field<31, 31>(insn);
2599                     int64_t offset = (immVal << immloLen) | immlo;
2600                     offset = offset << (page * 12);
2601                     int size = immloLen + immLen + (page * 12);
2602
2603                     insn_in_progress->appendOperand(makePCExpr(), true, false);
2604                     Expression::Ptr imm = Immediate::makeImmediate(Result(s64, (offset << (64 - size)) >> (64 - size)));
2605
2606                     insn_in_progress->appendOperand(imm, true, false);
2607                 }
2608                 else
2609                     isValid = false;
2610             }
2611             else if (isFPInsn) {
2612                 if (isSinglePrec())
2613                     insn_in_progress->appendOperand(fpExpand<int32_t, s32>(immVal), true, false);
2614                 else
2615                     insn_in_progress->appendOperand(fpExpand<int64_t, s64>(immVal), true, false);
2616             }
2617             else if (IS_INSN_EXCEPTION(insn)) {
2618                 Expression::Ptr imm = Immediate::makeImmediate(Result(u16, immVal));
2619                 insn_in_progress->appendOperand(imm, true, false);
2620                 isPstateRead = true;
2621             }
2622             else if (isSIMDInsn) {
2623                 if (IS_INSN_SIMD_EXTR(insn)) {
2624                     if (_Q == 0) {
2625                         if ((immVal & 0x8) == 0) {
2626                             Expression::Ptr imm = Immediate::makeImmediate(
2627                                     Result(u32, unsign_extend32(immLen - 1, immVal & 0x7)));
2628                             insn_in_progress->appendOperand(imm, true, false);
2629                         }
2630                         else
2631                             isValid = false;
2632                     }
2633                     else {
2634                         Expression::Ptr imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));\
2635             insn_in_progress->appendOperand(imm, true, false);
2636                     }
2637                 }
2638                 else if (IS_INSN_SIMD_SHIFT_IMM(insn) || IS_INSN_SCALAR_SHIFT_IMM(insn)) {
2639                     //immh
2640                     if (startBit == 19 && endBit == 22) {
2641                         immlo = immVal;
2642                         immloLen = endBit - startBit + 1;
2643                     }
2644                         //immb
2645                     else if (startBit == 16 && endBit == 18) {
2646                         int opcode = field<11, 15>(insn);
2647                         int shift, isRightShift = 1, elemWidth = (immlo << immLen) | immVal;
2648                         entryID insnID = insn_in_progress->getOperation().operationID;
2649                         bool isScalar = field<28, 28>(insn) ? true : false;
2650
2651                         //check if shift is left; if it is, the immediate has to be processed in a different manner.
2652                         //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
2653                         if (insnID == aarch64_op_shl_advsimd || insnID == aarch64_op_sqshl_advsimd_imm ||
2654                             insnID == aarch64_op_sshll_advsimd ||
2655                             insnID == aarch64_op_sli_advsimd || insnID == aarch64_op_sqshlu_advsimd ||
2656                             insnID == aarch64_op_uqshl_advsimd_imm || insnID == aarch64_op_ushll_advsimd)
2657                             isRightShift = -1;
2658
2659                         switch (highest_set_bit(immlo)) {
2660                             case 0x1:
2661                                 (!isScalar || (opcode & 0x1C) == 0x0C || (opcode & 0x1C) == 0x10)
2662                                 ? (shift = isRightShift * (16 - elemWidth) + (isRightShift > 0 ? 0 : 8))
2663                                 : (isValid = false);
2664                                 break;
2665                             case 0x2:
2666                                 (!isScalar || (opcode & 0x1C) == 0x0C || (opcode & 0x1C) == 0x10)
2667                                 ? (shift = isRightShift * (32 - elemWidth) + (isRightShift > 0 ? 0 : 16))
2668                                 : (isValid = false);
2669                                 break;
2670                             case 0x3:
2671                                 (!isScalar || opcode > 0x0A) ? (shift = isRightShift * (64 - elemWidth) +
2672                                                                         (isRightShift > 0 ? 0 : 32))
2673                                                              : (isValid = false);
2674                                 break;
2675                             case 0x4:
2676                                 shift = isRightShift * (128 - elemWidth) + (isRightShift > 0 ? 0 : 64);
2677                                 break;
2678                             default:
2679                                 isValid = false;
2680                         }
2681
2682                         if (isValid) {
2683                             Expression::Ptr imm = Immediate::makeImmediate(
2684                                     Result(u32, unsign_extend32(immloLen + immLen, shift)));
2685                             insn_in_progress->appendOperand(imm, true, false);
2686                         }
2687                     }
2688                     else
2689                         isValid = false;
2690                 }
2691             }
2692             else                                                            //conditional compare (immediate)
2693             {
2694                 Result_Type rT = is64Bit ? u64 : u32;
2695
2696                 Expression::Ptr imm = Immediate::makeImmediate(
2697                         Result(rT, rT == u32 ? unsign_extend32(immLen, immVal) : unsign_extend64(immLen, immVal)));
2698                 insn_in_progress->appendOperand(imm, true, false);
2699             }
2700         }
2701
2702         void InstructionDecoder_aarch64::reorderOperands() {
2703             if (oprRotateAmt) {
2704                 std::vector<Operand> curOperands;
2705                 insn_in_progress->getOperands(curOperands);
2706
2707                 if (curOperands.empty())
2708                     assert(!"empty operand list found while re-ordering operands");
2709
2710                 std::swap(curOperands[1], curOperands[3]);
2711
2712                 while (oprRotateAmt--)
2713                     std::rotate(curOperands.begin(), curOperands.begin() + 1, curOperands.begin() + 3);
2714
2715                 insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2716             }
2717             else if (IS_INSN_LDST_POST(insn) || IS_INSN_LDST_PAIR_POST(insn)) {
2718                 std::vector<Operand> curOperands;
2719                 insn_in_progress->getOperands(curOperands);
2720                 std::iter_swap(curOperands.begin(), curOperands.end() - 1);
2721                 insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2722             }
2723             else if (IS_INSN_LDST_PAIR(insn)) {
2724                 std::vector<Operand> curOperands;
2725                 insn_in_progress->getOperands(curOperands);
2726                 assert(curOperands.size() == 4 || curOperands.size() == 3);
2727                 if (curOperands.size() == 3) {
2728                     curOperands.insert(curOperands.begin(), curOperands.back());
2729                     curOperands.pop_back();
2730                 } else if (curOperands.size() == 4) {
2731                     std::iter_swap(curOperands.begin(), curOperands.end() - 1);
2732                 }
2733                 insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2734             }
2735             else if (IS_INSN_LDST_EX_PAIR(insn)) {
2736                 std::vector<Operand> curOperands;
2737                 insn_in_progress->getOperands(curOperands);
2738                 if (curOperands.size() == 3) {
2739                     curOperands.insert(curOperands.begin(), curOperands.back());
2740                     curOperands.pop_back();
2741                 }
2742                 else if (curOperands.size() == 4) {
2743                     curOperands.insert(curOperands.begin() + 1, curOperands.back());
2744                     curOperands.pop_back();
2745                 }
2746                 insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2747             }
2748             else if (IS_INSN_ST_EX(insn)) {
2749                 std::vector<Operand> curOperands;
2750                 insn_in_progress->getOperands(curOperands);
2751                 if (curOperands.size() == 3) {
2752                     curOperands.insert(curOperands.begin() + 1, curOperands.back());
2753                     curOperands.pop_back();
2754                     insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2755                 }
2756                 else
2757                     insn_in_progress->m_Operands.reverse();
2758             }
2759             else
2760                 insn_in_progress->m_Operands.reverse();
2761         }
2762
2763         void InstructionDecoder_aarch64::processAlphabetImm() {
2764             if (op == 1 && cmode == 0xE) {
2765                 uint64_t imm = 0;
2766
2767                 for (int imm_index = 0; imm_index < 8; imm_index++)
2768                     imm |= (simdAlphabetImm & (1 << imm_index)) ? (0xFF << (imm_index * 8)) : 0;
2769
2770                 insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u64, imm)), true, false);
2771             }
2772             else if (cmode == 0xF) {
2773                 //fmov (vector, immediate)
2774                 //TODO: check with Bill if this is fine
2775                 insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, simdAlphabetImm)), true, false);
2776             }
2777             else {
2778                 int shiftAmt = 0;
2779
2780                 //16-bit shifted immediate
2781                 if ((cmode & 0xC) == 0x8)
2782                     shiftAmt = ((cmode & 0x2) >> 1) * 8;
2783                     //32-bit shifted immediate
2784                 else if ((cmode & 0x8) == 0x0)
2785                     shiftAmt = ((cmode & 0x6) >> 1) * 8;
2786                     //32-bit shifting ones
2787                 else if ((cmode & 0xE) == 0xC)
2788                     shiftAmt = ((cmode & 0x0) + 1) * 8;
2789
2790                 Expression::Ptr lhs = Immediate::makeImmediate(Result(u32, unsign_extend32(8, simdAlphabetImm)));
2791                 Expression::Ptr rhs = Immediate::makeImmediate(Result(u32, unsign_extend32(5, shiftAmt)));
2792                 Expression::Ptr imm = makeLeftShiftExpression(lhs, rhs, u64);
2793
2794                 insn_in_progress->appendOperand(imm, true, false);
2795             }
2796         }
2797
2798         using namespace boost::assign;
2799
2800 #include "aarch64_opcode_tables.C"
2801
2802         void InstructionDecoder_aarch64::doDelayedDecode(const Instruction *insn_to_complete) {
2803             InstructionDecoder::buffer b(insn_to_complete->ptr(), insn_to_complete->size());
2804             //insn_to_complete->m_Operands.reserve(4);
2805             decode(b);
2806             decodeOperands(insn_to_complete);
2807
2808         }
2809
2810         bool InstructionDecoder_aarch64::decodeOperands(const Instruction * insn_to_complete) {
2811             int insn_table_index = findInsnTableIndex(0);
2812             aarch64_insn_entry *insn_table_entry = &aarch64_insn_entry::main_insn_table[insn_table_index];
2813
2814             insn = insn_to_complete->m_RawInsn.small_insn;
2815             insn_in_progress = const_cast<Instruction *>(insn_to_complete);
2816             
2817             if (IS_INSN_LDST_REG(insn) ||
2818                 IS_INSN_ADDSUB_EXT(insn) ||
2819                 IS_INSN_ADDSUB_SHIFT(insn) ||
2820                 IS_INSN_LOGICAL_SHIFT(insn))
2821                 skipRm = true;
2822             
2823             for (operandSpec::const_iterator fn = insn_table_entry->operands.begin();
2824                  fn != insn_table_entry->operands.end(); fn++) {
2825                 std::mem_fun(*fn)(this);
2826             }
2827
2828             if (insn_table_index == 0)
2829                 isValid = false;
2830
2831             if (!isValid) {
2832                 insn_in_progress->getOperation().mnemonic = INVALID_ENTRY.mnemonic;
2833                 insn_in_progress->getOperation().operationID = INVALID_ENTRY.op;
2834                 insn_in_progress->m_Operands.clear();
2835                 insn_in_progress->m_Successors.clear();
2836             }
2837             else {
2838                 reorderOperands();
2839
2840                 if (IS_INSN_SYSTEM(insn)) {
2841                     processSystemInsn();
2842                 }
2843
2844                 if (IS_INSN_SIMD_MOD_IMM(insn)) {
2845                     processAlphabetImm();
2846                 }
2847
2848                 if (IS_INSN_LDST_SIMD_MULT_POST(insn) || IS_INSN_LDST_SIMD_SING_POST(insn))
2849                     insn_in_progress->appendOperand(makeRnExpr(), false, true);
2850
2851                 if (isPstateWritten || isPstateRead)
2852                     insn_in_progress->appendOperand(makePstateExpr(), isPstateRead, isPstateWritten);
2853             }
2854
2855             return true;
2856         }
2857
2858
2859         int InstructionDecoder_aarch64::findInsnTableIndex(unsigned int decoder_table_index) {
2860             aarch64_mask_entry *cur_entry = &aarch64_mask_entry::main_decoder_table[decoder_table_index];
2861             unsigned int cur_mask = cur_entry->mask;
2862
2863             if (cur_mask == 0) {
2864                 int insn_table_index = cur_entry->insnTableIndex;
2865                 if (insn_table_index == -1)
2866                     assert(!"no instruction table entry found for current instruction");
2867                 else
2868                     return insn_table_index;
2869             }
2870
2871             unsigned int insn_iter_index = 0, map_key_index = 0, branch_map_key = 0;
2872             branchMap cur_branches = cur_entry->nodeBranches;
2873
2874             while (insn_iter_index < AARCH64_INSN_LENGTH) {
2875                 if (((cur_mask >> insn_iter_index) & 1) == 1) {
2876                     branch_map_key = branch_map_key | (((insn >> insn_iter_index) & 1) << map_key_index);
2877                     map_key_index++;
2878                 }
2879                 insn_iter_index++;
2880             }
2881
2882             if (cur_branches.count(branch_map_key) <= 0)
2883                 return 0;
2884             //  branch_map_key = 0;
2885
2886             return findInsnTableIndex(cur_branches[branch_map_key]);
2887         }