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