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