Fixes to correctly handle SIMD load/store single structure post-indexed category
[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<14,15>(insn);
1396     unsigned int S = field<12, 12>(insn);
1397     unsigned int size = field<10, 11>(insn);
1398
1399     if(opcode == 0x0)
1400     {
1401         return 8;
1402     }
1403     else if(opcode == 0x1 && (size & 0x1)==0x0)
1404     {
1405         return 16;
1406     }
1407     else if(opcode == 0x2 && size == 0x0)
1408     {
1409         return 32;
1410     }
1411     else if(opcode == 0x2 && S == 0 && size == 0x1)
1412     {
1413         return 64;
1414     }
1415     else if(opcode == 0x3 && S == 0)
1416     {
1417         return 8<<size;
1418     }
1419     else
1420         isValid = false;
1421     
1422     return 0;
1423 }
1424
1425 Expression::Ptr InstructionDecoder_aarch64::makeMemRefSIMD_MULT(){
1426     Result_Type rt;
1427     getMemRefSIMD_MULT_RT(rt);
1428     return makeDereferenceExpression(makeRnExpr(), rt);
1429 }
1430
1431 Expression::Ptr InstructionDecoder_aarch64::makeMemRefSIMD_SING(){
1432     Result_Type rt;
1433     getMemRefSIMD_SING_RT(rt);
1434     return makeDereferenceExpression(makeRnExpr(), rt);
1435 }
1436
1437 void InstructionDecoder_aarch64::getMemRefExPair_RT(Result_Type &rt){
1438     int size = field<30, 30>(insn);
1439     switch(size){
1440         case 0:
1441             rt = u64;
1442             break;
1443         case 1:
1444             rt = dbl128;
1445             break;
1446         default:
1447             isValid = false;
1448             break;
1449     }
1450     return;
1451 }
1452
1453 Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair(){
1454     Result_Type rt;
1455     getMemRefExPair_RT(rt);
1456     return makeDereferenceExpression(makeRnExpr(), rt);
1457 }
1458
1459 /*
1460 Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair16B(){
1461     return makeDereferenceExpression(makeRnExpr(), dbl128);
1462 }
1463 */
1464
1465 /*
1466 Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair2(){
1467     unsigned int immLen = 4, immVal = 8;
1468     Expression::Ptr offset = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));
1469     return makeDereferenceExpression(makeAddExpression(makeRnExpr(), offset, u64) , u64);
1470 }
1471 */
1472
1473 Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_Rm(){
1474     unsigned int option = field<13, 15>(insn);
1475     if((option&2) != 2)
1476         isValid = false;
1477     MachRegister baseReg = ((option & 0x3)==0x2) ? aarch64::w0 : aarch64::x0;
1478     unsigned int encoding = field<16, 20>(insn);
1479
1480         if( encoding == 31 )//zero register
1481                 return makeRegisterExpression(makeAarch64RegID(aarch64::zr, 0));
1482     else
1483         return makeRegisterExpression(makeAarch64RegID(baseReg, encoding));
1484 }
1485
1486 Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_amount(){
1487     unsigned int S =  field<12, 12>(insn);
1488     unsigned int amountVal = is64Bit?(S==0?0:2):(S==0?0:3);
1489     unsigned int amountLen = 2;
1490
1491     return Immediate::makeImmediate(Result(u32, unsign_extend32(amountLen, amountVal)) ) ;
1492 }
1493
1494 Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_ext(){
1495
1496     int immLen = 2;
1497     int immVal = 0; //for amount
1498
1499     int S = field<12,12>(insn);
1500     int size = field<30,31>(insn);
1501
1502     if( size == 2 ){ //32bit
1503         immVal = S==0?0:(S==1?2:-1);
1504         if( immVal==-1 )
1505             isValid = false;
1506     }else if( size == 3 ){ //64bit
1507         immVal = S==0?0:(S==1?3:-1);
1508         if( immVal==-1)
1509             isValid = false;
1510     }
1511     Expression::Ptr ext = makeOptionExpression(immLen, immVal);
1512
1513     return ext; /*extended ptr*/
1514 }
1515
1516 /**********************
1517 // ld/st reg memReg AST:
1518 //    memRef
1519 //      |
1520 //     ADD
1521 //    /    \
1522 //  [Rn]   EXT
1523 //        /   \
1524 //      [Rm] [amount]
1525 **********************/
1526 Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg(){
1527
1528     Expression::Ptr ext = makeMemRefReg_ext();
1529     Expression::Ptr xn = makeRnExpr();
1530     Expression::Ptr add = makeAddExpression(xn, ext, u64);
1531
1532     Result_Type rt;
1533     getMemRefIndex_RT(rt);
1534     return makeDereferenceExpression(add,rt);
1535 }
1536
1537 void InstructionDecoder_aarch64::LIndex()
1538 {
1539     // never be called
1540     if( IS_INSN_LD_LITERAL(insn)){
1541         insn_in_progress->appendOperand(makeMemRefIndexLiteral(), true, false);
1542         return;
1543     }
1544
1545     // ******************
1546     // load register offset
1547     // ******************
1548     else if( IS_INSN_LDST_REG(insn)){
1549         insn_in_progress->appendOperand(makeMemRefReg(), true, false);
1550         return;
1551     }
1552
1553     // ******************
1554     // load unsigned imm
1555     // ******************
1556     else if( IS_INSN_LDST_UIMM(insn)){
1557         insn_in_progress->appendOperand(makeMemRefIndexUImm(), true, false);
1558         return;
1559     }
1560
1561     // ******************
1562     // load pre, unscaled and unprivlidged
1563     // ******************
1564     else if( IS_INSN_LDST_PRE(insn)
1565         || IS_INSN_LDST_UNPRIV(insn)
1566         || IS_INSN_LDST_UNSCALED(insn) ){
1567         insn_in_progress->appendOperand(makeMemRefIndexPre(), true, false);
1568         return;
1569     }
1570
1571     else if( IS_INSN_LDST_POST(insn) ){
1572         insn_in_progress->appendOperand(makeMemRefIndexPost(), true, false);
1573         return;
1574     }
1575
1576     // ****************************
1577     // load PAIR pre, post, offset
1578     // ****************************
1579     else if( IS_INSN_LDST_PAIR_PRE(insn)
1580         || IS_INSN_LDST_PAIR_NOALLOC(insn) ){
1581         insn_in_progress->appendOperand( makeMemRefPairPre(), true, false);
1582         return;
1583     }
1584
1585     else if( IS_INSN_LDST_PAIR_POST(insn)
1586         || IS_INSN_LDST_PAIR_OFFSET(insn) ){
1587         insn_in_progress->appendOperand( makeMemRefPairPost(), true, false);
1588         return;
1589     }
1590
1591     // ****************************
1592     // load exclusive instructions
1593     // ****************************
1594     else if( IS_INSN_LDST_EX(insn) ){
1595         if( !IS_INSN_LDST_EX_PAIR(insn) ){ // Rt2 field == 31, non-pair op
1596             insn_in_progress->appendOperand( makeMemRefEx(), true, false);
1597         } else { // pair
1598             insn_in_progress->appendOperand( makeMemRefExPair(), true, false);
1599         }
1600         return;
1601     }
1602
1603     // ****************************
1604     // load SIMD multiple structures &
1605     // load SIMD multiple structures post increment
1606     // ****************************
1607     else if( IS_INSN_LDST_SIMD_MULT(insn)
1608             || IS_INSN_LDST_SIMD_MULT_POST(insn) ){
1609         insn_in_progress->appendOperand( makeMemRefSIMD_MULT(), true, false);
1610         return;
1611     }
1612     // ****************************
1613     // load SIMD single structure &
1614     // load SIMD single structure post increment
1615     // ****************************
1616     else if( IS_INSN_LDST_SIMD_SING(insn)
1617             || IS_INSN_LDST_SIMD_SING_POST(insn) ){
1618         insn_in_progress->appendOperand( makeMemRefSIMD_SING(), true, false);
1619         return;
1620     }
1621
1622     assert(0); //un-handled case
1623
1624 }
1625
1626 void InstructionDecoder_aarch64::STIndex()
1627 {
1628     if( IS_INSN_LD_LITERAL(insn))
1629         assert(0); // only load literal, no store literal
1630
1631     // ******************
1632     // ld/st register offset
1633     // ******************
1634     else if( IS_INSN_LDST_REG(insn)){
1635         insn_in_progress->appendOperand( makeMemRefReg(), false, true);
1636         return;
1637     }
1638
1639     else if( IS_INSN_LDST_UIMM(insn)){
1640         insn_in_progress->appendOperand( makeMemRefIndexUImm(), false, true);
1641         return;
1642     }
1643
1644     // ******************
1645     // ld/st pre and post, unscaled and unprivilidged
1646     // ******************
1647     else if( IS_INSN_LDST_PRE(insn)
1648         || IS_INSN_LDST_UNPRIV(insn)
1649         || IS_INSN_LDST_UNSCALED(insn) ){
1650         insn_in_progress->appendOperand( makeMemRefIndexPre(), false, true);
1651         return;
1652     }
1653
1654     else if( IS_INSN_LDST_POST(insn) ){
1655         insn_in_progress->appendOperand( makeMemRefIndexPost(), false, true);
1656         return;
1657     }
1658
1659     // ****************************
1660     // ld/st PAIR pre, post, offset
1661     // ****************************
1662     else if( IS_INSN_LDST_PAIR_PRE(insn)
1663         || IS_INSN_LDST_PAIR_NOALLOC(insn) ){
1664         insn_in_progress->appendOperand( makeMemRefPairPre(), false, true);
1665         return;
1666     }
1667     else if( IS_INSN_LDST_PAIR_POST(insn)
1668         || IS_INSN_LDST_PAIR_OFFSET(insn)) {
1669         insn_in_progress->appendOperand( makeMemRefPairPost(), false, true);
1670         return;
1671     }
1672
1673     // ****************************
1674     // ld/st exclusive instructions
1675     // ****************************
1676     else if( IS_INSN_LDST_EX(insn) ){
1677         if( !IS_INSN_LDST_EX_PAIR(insn) ){ // Rt2 field == 31, non-pair op
1678             insn_in_progress->appendOperand( makeMemRefEx(), false, true);
1679         } else { // pair
1680             insn_in_progress->appendOperand( makeMemRefExPair(), false, true);
1681         }
1682         return;
1683     }
1684
1685     // ****************************
1686     // store SIMD multiple structures &
1687     // store SIMD multiple structures post increment
1688     // ****************************
1689     else if( IS_INSN_LDST_SIMD_MULT(insn)
1690             ||IS_INSN_LDST_SIMD_MULT_POST(insn) ){
1691         insn_in_progress->appendOperand( makeMemRefSIMD_MULT(), false, true);
1692         return;
1693     }
1694     else if( IS_INSN_LDST_SIMD_SING(insn)
1695             ||IS_INSN_LDST_SIMD_SING_POST(insn) ){
1696         insn_in_progress->appendOperand( makeMemRefSIMD_SING(), false, true);
1697         return;
1698     }
1699
1700     assert(0); //un-handled case
1701
1702 }
1703
1704 // This function is for non-writeback
1705 void InstructionDecoder_aarch64::OPRRn()
1706 {
1707         if(IS_INSN_B_UNCOND_REG(insn))                                                                          //unconditional branch (register)
1708         {
1709                 int branchType = field<21, 22>(insn);
1710
1711                 insn_in_progress->appendOperand(makePCExpr(), false, true);
1712                 insn_in_progress->addSuccessor(makeRnExpr(), field<21, 21>(insn) == 1, true, false, false);
1713
1714                 if(branchType == 0x1)
1715                 {
1716                         insn_in_progress->addSuccessor(makeFallThroughExpr(), false, false, false, true);
1717                 }
1718         }
1719         else
1720                 insn_in_progress->appendOperand(makeRnExpr(), true, false);
1721 }
1722
1723 void InstructionDecoder_aarch64::OPRRnL()
1724 {
1725     LIndex();
1726 }
1727
1728 void InstructionDecoder_aarch64::OPRRnS()
1729 {
1730     STIndex();
1731 }
1732
1733 void InstructionDecoder_aarch64::OPRRnU()
1734 {
1735     assert(0);
1736     /* this functions is useless
1737         insn_in_progress->appendOperand(makeRnExpr(), true, true);
1738     */
1739 }
1740
1741 void InstructionDecoder_aarch64::OPRRnLU()
1742 {
1743     if( IS_INSN_LDST_PRE(insn) ){
1744         LIndex();
1745         return;
1746     }
1747
1748     if( IS_INSN_LDST_POST(insn) ){
1749         LIndex();
1750         return;
1751     }
1752
1753     if( IS_INSN_LDST_PAIR_PRE(insn) ){
1754         LIndex();
1755         return;
1756     }
1757
1758     if( IS_INSN_LDST_PAIR_POST(insn) ){
1759         LIndex();
1760         return;
1761     }
1762
1763 }
1764
1765 void InstructionDecoder_aarch64::OPRRnSU()
1766 {
1767     if( IS_INSN_LDST_PRE(insn) ){
1768         STIndex();
1769         return;
1770     }
1771
1772     if( IS_INSN_LDST_POST(insn) ){
1773         STIndex();
1774         return;
1775     }
1776
1777     if( IS_INSN_LDST_PAIR_PRE(insn) ){
1778         STIndex();
1779         return;
1780     }
1781
1782     if( IS_INSN_LDST_PAIR_POST(insn) ){
1783         STIndex();
1784         return;
1785     }
1786 }
1787
1788 unsigned int InstructionDecoder_aarch64::get_SIMD_MULT_POST_imm(){
1789     unsigned int rpt = 0, selem = 0;
1790     getSIMD_MULT_RptSelem(rpt, selem);
1791     unsigned int numReg = rpt*selem;
1792     return _Q == 0x1?numReg<<4:numReg<<3;
1793 }
1794
1795 unsigned int InstructionDecoder_aarch64::get_SIMD_SING_POST_imm()
1796 {
1797     return (getMemRefSIMD_SING_T()>>3)*getSIMD_SING_selem();
1798 }
1799
1800 Expression::Ptr InstructionDecoder_aarch64::makeRmExpr()
1801 {
1802     int encoding  = field<16, 20>(insn);
1803     MachRegister reg;
1804
1805     if(isSIMDInsn)
1806     {
1807         if(IS_INSN_LDST_SIMD_MULT_POST(insn))
1808         {
1809             if(encoding == 31)
1810             {
1811                 unsigned int immVal = get_SIMD_MULT_POST_imm();
1812                 unsigned int immLen = 8;
1813                 
1814                 return Immediate::makeImmediate( Result(u32, unsign_extend32(immLen, immVal)) );
1815             }
1816             else
1817                 reg = aarch64::x0;
1818         }
1819         else if(IS_INSN_LDST_SIMD_SING_POST(insn))
1820         {
1821             if(encoding == 31)
1822             {
1823                 unsigned int immVal = get_SIMD_SING_POST_imm();
1824                 unsigned int immLen = 8;
1825
1826                 return Immediate::makeImmediate( Result(u32, unsign_extend32(immLen, immVal) ) );
1827             }
1828             else
1829                 reg = aarch64::x0;
1830         }
1831         else if(IS_INSN_SIMD_VEC_INDEX(insn) || IS_INSN_SCALAR_INDEX(insn))
1832         {
1833             reg = field<11, 11>(insn)==0x1?aarch64::q0:aarch64::d0;
1834
1835                         if(size == 0x0 || size == 0x3)
1836                                 isValid = false;
1837                         else if(size == 0x1)
1838                                 encoding = encoding & 0xF;
1839         }
1840         else if(IS_INSN_SCALAR_3DIFF(insn))
1841         {
1842             switch(size)
1843             {
1844                 case 0x1:reg = aarch64::h0;
1845                          break;
1846                 case 0x2:reg = aarch64::s0;
1847                          break;
1848                 default:isValid = false;
1849             }
1850         }
1851         else if(IS_INSN_SIMD_3DIFF(insn))
1852         {
1853             entryID op = insn_in_progress->getOperation().operationID;
1854
1855             if(op == aarch64_op_addhn_advsimd || op == aarch64_op_subhn_advsimd ||
1856                op == aarch64_op_raddhn_advsimd || op == aarch64_op_rsubhn_advsimd)
1857                 reg = aarch64::q0;
1858             else
1859                 reg = _Q == 0x1?aarch64::hq0:aarch64::d0;
1860         }
1861                 else if(IS_INSN_SCALAR_3SAME(insn))
1862                 {
1863                         if(size != -1)
1864                         {
1865                                 switch(size)
1866                                 {
1867                                         case 0x0:reg = aarch64::b0;
1868                                                          break;
1869                                         case 0x1:reg = aarch64::h0;
1870                                                          break;
1871                                         case 0x2:reg = aarch64::s0;
1872                                                          break;
1873                                         case 0x3:reg = aarch64::d0;
1874                                                          break;
1875                                         default:isValid = false;
1876                                 }
1877                         }
1878                         else if(_szField != -1)
1879                         {
1880                                 switch(_szField)
1881                                 {
1882                                         case 0x0:reg = aarch64::s0;
1883                                                          break;
1884                                         case 0x1:reg = aarch64::d0;
1885                                                          break;
1886                                         default:isValid = false;
1887                                 }
1888                         }
1889                         else
1890                                 isValid = false;
1891                 }
1892         else
1893             reg = _Q == 0x1?aarch64::q0:aarch64::d0;
1894         
1895         reg = makeAarch64RegID(reg, encoding);
1896     
1897         return makeRegisterExpression(reg);
1898     }
1899     else if(isFPInsn)
1900     {
1901         reg = isSinglePrec()?aarch64::s0:aarch64::d0;
1902         reg = makeAarch64RegID(reg, encoding);
1903     }
1904     else
1905     {
1906         reg = is64Bit?((encoding == 31)?aarch64::zr:aarch64::x0):((encoding == 31)?aarch64::wzr:aarch64::w0);
1907         if(encoding != 31)
1908             reg = makeAarch64RegID(reg, encoding);
1909     }
1910
1911     return makeRegisterExpression(reg);
1912 }
1913
1914 void InstructionDecoder_aarch64::OPRRm()
1915 {
1916         if(IS_INSN_LDST_REG(insn) ||
1917            IS_INSN_ADDSUB_EXT(insn) ||
1918            IS_INSN_ADDSUB_SHIFT(insn) ||
1919            IS_INSN_LOGICAL_SHIFT(insn))
1920                 return;
1921
1922         if(IS_INSN_FP_COMPARE(insn) && field<3, 3>(insn) == 1)
1923                 insn_in_progress->appendOperand(Immediate::makeImmediate(Result(isSinglePrec()?sp_float:dp_float, 0.0)), true, false);
1924         else
1925                 insn_in_progress->appendOperand(makeRmExpr(), true, false);
1926 }
1927
1928 void InstructionDecoder_aarch64::OPRsf()
1929 {
1930         if(field<31, 31>(insn) == 0)
1931                 is64Bit = false;
1932 }
1933
1934 template<unsigned int endBit, unsigned int startBit>
1935 void InstructionDecoder_aarch64::OPRoption()
1936 {
1937         hasOption = true;
1938         optionField = field<startBit, endBit>(insn);
1939 }
1940
1941 void InstructionDecoder_aarch64::OPRshift()
1942 {
1943         hasShift = true;
1944         shiftField = field<22, 23>(insn);
1945 }
1946
1947 void InstructionDecoder_aarch64::OPRhw()
1948 {
1949         hasHw = true;
1950         hwField = field<21, 22>(insn);
1951 }
1952
1953 template<unsigned int endBit, unsigned int startBit>
1954 void InstructionDecoder_aarch64::OPRN()
1955 {
1956         hasN = true;
1957         nField = field<startBit, endBit>(insn);
1958         nLen = endBit - startBit + 1;
1959 }
1960
1961 // the call of this function should be generated by decoder gen for ld/st class
1962 // except for ld/st{s, h, w} subclass
1963 void InstructionDecoder_aarch64::setRegWidth(){
1964     //is64Bit is by default set to TRUE
1965     unsigned int opc = 0x3 & field<22, 23>(insn);
1966     unsigned int opc0 = opc & 0x1;
1967     unsigned int opc1 = (opc & 0x2)>>1;
1968     unsigned int sz  = 0x3 & field<30, 31>(insn);
1969
1970     if(IS_INSN_LDST(insn)){
1971         if(   IS_INSN_LDST_UIMM(insn)   || IS_INSN_LDST_UNSCALED(insn)
1972                 || IS_INSN_LDST_UNPRIV(insn) || IS_INSN_LDST_POST(insn)
1973                 || IS_INSN_LDST_PRE(insn)    || IS_INSN_LDST_REG(insn)){
1974                 if(opc1 == 0){
1975                     if(field<30, 31>(insn) != 3)
1976                         is64Bit = false;
1977                     return;
1978                 }else{
1979                     if( sz == 3){
1980                         if( opc0 == 1)
1981                             isValid = false;
1982                     }
1983                     else{
1984                         if(sz == 2 && opc0 == 1)
1985                             isValid = false;
1986                         if(opc0 == 1)
1987                             is64Bit = false;        
1988                     }
1989                     return;
1990                 }
1991         }
1992         else if(IS_INSN_LDST_EX(insn)){
1993             switch(sz){
1994                 case 2:
1995                 case 0:
1996                 case 1:
1997                     is64Bit = false;
1998                     break;
1999                 case 3:
2000                 default:
2001                     return;
2002             }
2003         }
2004         else if(IS_INSN_LDST_PAIR(insn)){
2005             switch(sz){
2006                 case 0:
2007                     is64Bit = false;
2008                     break;
2009                 case 1:
2010                 case 2:
2011                 case 3:
2012                 default:
2013                     return;
2014             }
2015         }
2016         else if(IS_INSN_LD_LITERAL(insn)){
2017             switch(sz){
2018                 case 0:
2019                     is64Bit = false;
2020                 case 1:
2021                 case 2:
2022                 case 3:
2023                 default:
2024                     return;
2025             }
2026         }
2027         else{
2028             isValid = false;
2029         }
2030     }else{
2031         isValid = false;
2032     }
2033     return;
2034 }
2035
2036 Expression::Ptr InstructionDecoder_aarch64::makeRtExpr()
2037 {
2038         int encoding  = field<0, 4>(insn);
2039         MachRegister reg;
2040
2041         if(isFPInsn)
2042         {
2043                 reg = makeAarch64RegID(isSinglePrec()?aarch64::s0:aarch64::d0, encoding);
2044         }
2045         else
2046         {
2047                 reg = is64Bit?((encoding == 31)?aarch64::zr:aarch64::x0):((encoding == 31)?aarch64::wzr:aarch64::w0);
2048                 if(encoding != 31)
2049                         reg = makeAarch64RegID(reg, encoding);
2050         }
2051
2052         return makeRegisterExpression(reg);
2053 }
2054
2055 void InstructionDecoder_aarch64::getSIMD_MULT_RptSelem(unsigned int &rpt, unsigned int &selem){
2056     unsigned opcode = field<12, 15>(insn);
2057     switch(opcode){
2058         case 0x0:
2059             rpt = 1; selem = 4;
2060             break;
2061         case 0x2:
2062             rpt = 4; selem = 1;
2063             break;
2064         case 0x4:
2065             rpt = 1; selem = 3;
2066             break;
2067         case 0x6:
2068             rpt = 3; selem = 1;
2069             break;
2070         case 0x7:
2071             rpt = 1; selem = 1;
2072             break;
2073         case 0x8:
2074             rpt = 1; selem = 2;
2075             break;
2076         case 0xa:
2077             rpt = 2; selem = 1;
2078             break;
2079         default:
2080             isValid = false;
2081             return;
2082     }
2083     if(rpt==0 || selem==0)
2084         isValid = false;
2085     return;
2086 }
2087
2088 void InstructionDecoder_aarch64::OPRRt()
2089 {
2090         int encoding = field<0, 4>(insn);
2091         if(IS_INSN_BRANCHING(insn))
2092         {
2093                 if(encoding == 31)
2094                         insn_in_progress->appendOperand(makeRegisterExpression(is64Bit?aarch64::zr:aarch64::wzr), true, false);
2095                 else
2096                         insn_in_progress->appendOperand(makeRegisterExpression(makeAarch64RegID(is64Bit?aarch64::x0:aarch64::w0, encoding)), true, false);
2097         }
2098 }
2099
2100 void InstructionDecoder_aarch64::OPRRtL()
2101 {
2102     int encoding = field<0, 4>(insn);
2103
2104     if(IS_INSN_LDST_SIMD_MULT(insn) || IS_INSN_LDST_SIMD_MULT_POST(insn))
2105     {
2106         unsigned int rpt, selem;
2107         getSIMD_MULT_RptSelem(rpt, selem);
2108         MachRegister reg = _Q == 0x1?aarch64::q0:aarch64::d0;
2109         for(int it_rpt = rpt*selem - 1; it_rpt >= 0; it_rpt--){
2110                         insn_in_progress->appendOperand(makeRegisterExpression(makeAarch64RegID(reg, (encoding + it_rpt)%32 )), false, true);
2111         }
2112     }
2113     else if(IS_INSN_LDST_SIMD_SING(insn) || IS_INSN_LDST_SIMD_SING_POST(insn))
2114     {
2115         unsigned int selem =  getSIMD_SING_selem();
2116
2117         MachRegister reg = _Q == 0x1?aarch64::q0:aarch64::d0;
2118
2119         for(int it_selem = selem - 1; it_selem >= 0; it_selem--)
2120         {
2121                         insn_in_progress->appendOperand(makeRegisterExpression(makeAarch64RegID(reg, (encoding + it_selem)%32 )), false, true);
2122         }
2123     }
2124     else
2125             insn_in_progress->appendOperand(makeRtExpr(), false, true);
2126 }
2127
2128 void InstructionDecoder_aarch64::OPRRtS()
2129 {
2130     int encoding = field<0, 4>(insn);
2131
2132     if( IS_INSN_LDST_SIMD_MULT(insn) || IS_INSN_LDST_SIMD_MULT_POST(insn) ){
2133         unsigned int rpt, selem;
2134         getSIMD_MULT_RptSelem(rpt, selem);
2135         
2136         MachRegister reg = _Q == 0x1?aarch64::q0:aarch64::d0;
2137
2138         for(int it_rpt = rpt*selem-1; it_rpt >= 0; it_rpt--){
2139                         insn_in_progress->appendOperand(makeRegisterExpression(makeAarch64RegID(reg, (encoding + it_rpt)%32 )), true, false);
2140         }
2141     }
2142     else if(IS_INSN_LDST_SIMD_SING(insn) || IS_INSN_LDST_SIMD_SING_POST(insn))
2143     {
2144         unsigned int selem =  getSIMD_SING_selem();
2145
2146         MachRegister reg = _Q == 0x1?aarch64::q0:aarch64::d0;
2147
2148         for(int it_selem = selem - 1; it_selem >= 0; it_selem--){
2149                         insn_in_progress->appendOperand(makeRegisterExpression(makeAarch64RegID(reg, (encoding + it_selem)%32 )), true, false);
2150         }
2151     }
2152     else
2153             insn_in_progress->appendOperand(makeRtExpr(), true, false);
2154 }
2155
2156 Expression::Ptr InstructionDecoder_aarch64::makeRt2Expr()
2157 {
2158         MachRegister baseReg = isFPInsn?
2159         (isSinglePrec()?aarch64::s0:aarch64::d0):
2160         (is64Bit?aarch64::x0 : aarch64::w0);
2161
2162         return makeRegisterExpression(makeAarch64RegID(baseReg, field<10, 14>(insn)));
2163 }
2164
2165 void InstructionDecoder_aarch64::OPRRt2()
2166 {
2167     assert(0);
2168 }
2169
2170 void InstructionDecoder_aarch64::OPRRt2L()
2171 {
2172         insn_in_progress->appendOperand(makeRt2Expr(), false, true);
2173 }
2174
2175 void InstructionDecoder_aarch64::OPRRt2S()
2176 {
2177         insn_in_progress->appendOperand(makeRt2Expr(), true, false);
2178 }
2179
2180 template<unsigned int endBit, unsigned int startBit>
2181 void InstructionDecoder_aarch64::OPRcond()
2182 {
2183         unsigned char condVal = static_cast<unsigned char>(field<startBit, endBit>(insn));
2184         if(IS_INSN_B_COND(insn))
2185         {
2186                 insn_in_progress->getOperation().mnemonic += ".";
2187                 insn_in_progress->getOperation().mnemonic += condStringMap[condVal];
2188         }
2189         else
2190         {
2191                 Expression::Ptr cond = Immediate::makeImmediate(Result(u8, condVal));
2192                 insn_in_progress->appendOperand(cond, true, false);
2193                 oprRotateAmt++;
2194         }
2195
2196         isPstateRead = true;
2197 }
2198
2199 void InstructionDecoder_aarch64::OPRnzcv()
2200 {
2201         unsigned int nzcvVal = field<0, 3>(insn)<<28;
2202         Expression::Ptr nzcv = Immediate::makeImmediate(Result(u32, nzcvVal));
2203         insn_in_progress->appendOperand(nzcv, true, false);
2204
2205         isPstateWritten = true;
2206         oprRotateAmt++;
2207 }
2208
2209 void InstructionDecoder_aarch64::OPRop1()
2210 {
2211         op1Field = field<16, 18>(insn);
2212 }
2213
2214 void InstructionDecoder_aarch64::OPRop2()
2215 {
2216         op2Field = field<5, 7>(insn);
2217 }
2218
2219 void InstructionDecoder_aarch64::OPRCRm()
2220 {
2221         crmField = field<8 ,11>(insn);
2222 }
2223
2224 void InstructionDecoder_aarch64::OPRCRn()
2225 {
2226 }
2227
2228 template<unsigned int endBit, unsigned int startBit>
2229 void InstructionDecoder_aarch64::OPRS()
2230 {
2231         sField = field<startBit, endBit>(insn);
2232 }
2233
2234 void InstructionDecoder_aarch64::OPRscale()
2235 {
2236         int scaleVal = 64 - field<10, 15>(insn);
2237
2238         Expression::Ptr scale = Immediate::makeImmediate(Result(u32, unsign_extend32(6, scaleVal)));
2239         insn_in_progress->appendOperand(scale, true, false);
2240 }
2241
2242 Expression::Ptr InstructionDecoder_aarch64::makeRaExpr()
2243 {
2244         int encoding  = field<10, 14>(insn);
2245         MachRegister reg;
2246
2247         if(isFPInsn)
2248         {
2249                 reg = makeAarch64RegID(isSinglePrec()?aarch64::s0:aarch64::d0, encoding);
2250         }
2251         else
2252         {
2253                 reg = is64Bit?((encoding == 31)?aarch64::sp:aarch64::x0):((encoding == 31)?aarch64::wsp:aarch64::w0);
2254                 if(encoding != 31)
2255                         reg = makeAarch64RegID(reg, encoding);
2256         }
2257
2258         return makeRegisterExpression(reg);
2259
2260 }
2261
2262 void InstructionDecoder_aarch64::OPRRa()
2263 {
2264         insn_in_progress->appendOperand(makeRaExpr(), true, false);
2265
2266         oprRotateAmt++;
2267 }
2268
2269 void InstructionDecoder_aarch64::OPRo0()
2270 {
2271
2272 }
2273
2274 void InstructionDecoder_aarch64::OPRb5()
2275 {
2276         OPRsf();
2277         hasb5 = true;
2278 }
2279
2280 void InstructionDecoder_aarch64::OPRb40()
2281 {
2282
2283 }
2284
2285 Expression::Ptr InstructionDecoder_aarch64::makeb40Expr()
2286 {
2287         int b40Val = field<19, 23>(insn);
2288         int bitpos = ((is64Bit?1:0)<<5) | b40Val;
2289
2290         return Immediate::makeImmediate(Result(u32, unsign_extend32(6, bitpos)));
2291 }
2292
2293 template<unsigned int endBit, unsigned int startBit>
2294 void InstructionDecoder_aarch64::OPRsz()
2295 {
2296     _szField = field<startBit, endBit>(insn);
2297 }
2298
2299 bool InstructionDecoder_aarch64::isSinglePrec() {
2300     if( isFPInsn && !isSIMDInsn ){
2301         if(_typeField == -1){
2302             //TODO if the type field is not set, do sth else
2303             OPRtype<23, 22>();
2304         }
2305         return _typeField==0?true:false;
2306     }else if( isSIMDInsn ){
2307         isValid = false; //not implemeted yet
2308     }
2309     return false;
2310 }
2311
2312 Expression::Ptr InstructionDecoder_aarch64::makeRsExpr()
2313 {
2314         MachRegister baseReg = isFPInsn?
2315         (isSinglePrec()?aarch64::s0:aarch64::d0):
2316         (is64Bit?aarch64::x0:aarch64::w0);
2317
2318     if(IS_INSN_LDST(insn)){
2319         baseReg = aarch64::w0;
2320     }
2321         return makeRegisterExpression(makeAarch64RegID(baseReg, field<16, 20>(insn)));
2322 }
2323
2324 void InstructionDecoder_aarch64::OPRRs()
2325 {
2326         insn_in_progress->appendOperand(makeRsExpr(), false, true);
2327 }
2328
2329 void InstructionDecoder_aarch64::makeBranchTarget(bool branchIsCall, bool bIsConditional, int immVal, int immLen)
2330 {
2331         Expression::Ptr lhs = makePCExpr();
2332
2333         int offset = sign_extend64(immLen + 2, immVal*4);
2334         Expression::Ptr rhs = Immediate::makeImmediate(Result(s64, offset));
2335
2336         insn_in_progress->addSuccessor(makeAddExpression(lhs, rhs, s64), branchIsCall, false, bIsConditional, false);
2337         if(branchIsCall)
2338         {
2339                 insn_in_progress->addSuccessor(makeFallThroughExpr(), false, false, false, true);
2340         }
2341
2342 }
2343
2344 Expression::Ptr InstructionDecoder_aarch64::makeFallThroughExpr()
2345 {
2346         return makeAddExpression(makePCExpr(), Immediate::makeImmediate(Result(u64, unsign_extend64(3, 4))), u64);
2347 }
2348
2349 template<typename T, Result_Type rT>
2350 Expression::Ptr InstructionDecoder_aarch64::fpExpand(int val)
2351 {
2352         int N, E, F;
2353         T frac, expandedImm, sign, exp;
2354
2355         N = (rT == s32)?32:64;
2356         E = (N == 32)?8:11;
2357         F = N - E - 1;
2358
2359         sign = (val & 0x80) >> 7;
2360
2361         int val6 = ((~val) & 0x40) >> 6, val6mask = (1 << (E - 3)) - 1;
2362         exp = (val6 << (E - 1)) | ((val6?val6mask:0) << 2) | ((val & 0x30) >> 4);
2363
2364         frac = (val & 0xF) << (F - 4);
2365
2366         expandedImm = (sign << (E + F)) | (exp << F) | frac;
2367
2368         return Immediate::makeImmediate(Result(rT, expandedImm));
2369 }
2370
2371 template<unsigned int endBit, unsigned int startBit>
2372 void InstructionDecoder_aarch64::OPRimm()
2373 {
2374         int immVal = field<startBit, endBit>(insn);
2375         unsigned int immLen = endBit - startBit + 1;
2376
2377         if(IS_INSN_LDST(insn))
2378         {
2379             if(IS_INSN_LD_LITERAL(insn))
2380             {
2381                 Expression::Ptr literal = makeMemRefIndexLiteral();
2382                 insn_in_progress->appendOperand(literal, true, false);
2383             }
2384             else if(IS_INSN_LDST_POST(insn))
2385             {
2386                 Expression::Ptr offset = makeMemRefIndex_offset9();
2387                 insn_in_progress->appendOperand(offset, true, false);
2388             }
2389             else if(IS_INSN_LDST_PAIR_POST(insn)
2390                 || IS_INSN_LDST_PAIR_OFFSET(insn) )
2391             {
2392                 Expression::Ptr offset = makeMemRefPair_offset7();
2393                 insn_in_progress->appendOperand(offset, true, false);
2394             }
2395         
2396             return;
2397         }
2398
2399         if(hasHw)
2400         {
2401                 processHwFieldInsn(immLen, immVal);
2402         }
2403         else if(hasN)           //logical (immediate), bitfield, extract
2404         {
2405                 if(IS_FIELD_IMMR(startBit, endBit))
2406                 {
2407                         immr = immVal;
2408                         immrLen = immLen;
2409                 }
2410                 else if(IS_FIELD_IMMS(startBit, endBit))
2411                 {
2412                         Expression::Ptr imm;
2413
2414                         if(IS_INSN_LOGICAL_IMM(insn))
2415                         {
2416                                 immVal |= (immr << immLen);
2417                                 immVal |= (nField << (immLen + immrLen));
2418
2419                                 immLen += nLen + immrLen;
2420
2421                                 Result_Type rT = is64Bit?u64:u32;
2422                                 imm = Immediate::makeImmediate(Result(rT, rT==u32?unsign_extend32(immLen, immVal):unsign_extend64(immLen, immVal)));
2423                         }
2424                         else
2425                         {
2426                                 imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));
2427                                 oprRotateAmt++;
2428                         }
2429
2430                         insn_in_progress->appendOperand(imm, true, false);
2431                         if(IS_INSN_BITFIELD(insn))
2432                         {
2433                                 imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immrLen, immr)));
2434                                 insn_in_progress->appendOperand(imm, true, false);
2435                                 oprRotateAmt--;
2436                         }
2437                 }
2438                 else
2439                     isValid = false;
2440         }
2441         else if(hasShift)
2442         {
2443                 if(IS_INSN_ADDSUB_SHIFT(insn) || IS_INSN_LOGICAL_SHIFT(insn))   //add-sub shifted | logical shifted
2444                 {
2445                         processShiftFieldShiftedInsn(immLen, immVal);
2446                 }
2447                 else if(IS_INSN_ADDSUB_IMM(insn))               //add-sub (immediate)
2448                 {
2449                         processShiftFieldImmInsn(immLen, immVal);
2450                 }
2451                 else
2452                         isValid = false;
2453         }
2454         else if(hasOption)
2455         {
2456                 if(IS_INSN_ADDSUB_EXT(insn))                                                                            //add-sub extended
2457                 {
2458                     Expression::Ptr expr = makeOptionExpression(immLen, immVal);
2459
2460                     insn_in_progress->appendOperand(expr, true, false);
2461                 }
2462                 else
2463                 {
2464                         isValid = false;
2465                 }
2466         }
2467         else if(IS_INSN_BRANCHING(insn) && !IS_INSN_B_UNCOND_REG(insn))
2468         {               //unconditional branch (immediate), test and branch, compare and branch, conditional branch
2469                 bool bIsConditional = false;
2470                 if(!(IS_INSN_B_UNCOND(insn)))
2471                         bIsConditional = true;
2472
2473                 bool branchIsCall = bIsConditional?false:(field<31, 31>(insn) == 1);
2474
2475                 insn_in_progress->appendOperand(makePCExpr(), false, true);
2476                 makeBranchTarget(branchIsCall, bIsConditional, immVal, immLen);
2477
2478                 if(hasb5)
2479                         insn_in_progress->appendOperand(makeb40Expr(), true, false);
2480
2481                 if(bIsConditional)
2482                         insn_in_progress->addSuccessor(makeFallThroughExpr(), false, false, true, true);
2483         }
2484         else if(IS_INSN_PCREL_ADDR(insn))                                                                       //pc-relative addressing
2485         {
2486                 if(IS_FIELD_IMMLO(startBit, endBit))
2487                 {
2488                         immlo = immVal;
2489                         immloLen = endBit - startBit + 1;
2490                 }
2491                 else if(IS_FIELD_IMMHI(startBit, endBit))
2492                 {
2493                         int page = field<31, 31>(insn);
2494                         int offset = (immVal<<immloLen) | immlo;
2495
2496                         insn_in_progress->appendOperand(makePCExpr(), true, false);
2497                         Expression::Ptr imm = Immediate::makeImmediate(Result(s64, sign_extend64(immloLen + immLen + page*12, offset<<(page*12))));
2498
2499                         insn_in_progress->appendOperand(imm, true, false);
2500                 }
2501                 else
2502                         isValid = false;
2503         }
2504         else if(isFPInsn)
2505         {
2506                 if(isSinglePrec())
2507                         insn_in_progress->appendOperand(fpExpand<int32_t, s32>(immVal), true, false);
2508                 else
2509                         insn_in_progress->appendOperand(fpExpand<int64_t, s64>(immVal), true, false);
2510         }
2511         else if(IS_INSN_EXCEPTION(insn))
2512         {
2513                 Expression::Ptr imm = Immediate::makeImmediate(Result(u16, immVal));
2514                 insn_in_progress->appendOperand(imm, true, false);
2515                 isPstateRead = true;
2516         }
2517         else if(isSIMDInsn)
2518         {
2519             if(IS_INSN_SIMD_EXTR(insn))
2520             {
2521                 if(_Q == 0)
2522                 {
2523                     if((immVal & 0x8) == 0)
2524                     {
2525                         Expression::Ptr imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen - 1, immVal & 0x7)));
2526                         insn_in_progress->appendOperand(imm, true, false);
2527                     }
2528                     else
2529                         isValid = false;
2530                 }
2531                 else
2532                 {
2533                     Expression::Ptr imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));\
2534                     insn_in_progress->appendOperand(imm, true, false);
2535                 }
2536             }
2537             else if(IS_INSN_SIMD_SHIFT_IMM(insn) || IS_INSN_SCALAR_SHIFT_IMM(insn))
2538             {
2539                 //immh
2540                 if(startBit == 19 && endBit == 22)
2541                 {
2542                     immlo = immVal;
2543                     immloLen = endBit - startBit + 1;
2544                 }
2545                 //immb
2546                 else if(startBit == 16 && endBit == 18)
2547                 {
2548                         int opcode = field<11, 15>(insn);
2549                     int shift, isRightShift = 1, elemWidth = (immlo << immLen) | immVal;
2550                     entryID insnID = insn_in_progress->getOperation().operationID;
2551                     
2552                     //check if shift is left; if it is, the immediate has to be processed in a different manner.
2553                     //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
2554                     if(insnID == aarch64_op_shl_advsimd || insnID == aarch64_op_sqshl_advsimd_imm || insnID == aarch64_op_sshll_advsimd ||
2555                        insnID == aarch64_op_sli_advsimd || insnID == aarch64_op_sqshlu_advsimd || insnID == aarch64_op_uqshl_advsimd_imm || insnID == aarch64_op_ushll_advsimd)
2556                         isRightShift = -1;      
2557
2558                     switch(highest_set_bit(immlo))
2559                     {
2560                         case 0x1:((opcode & 0x1C) == 0x0C || (opcode & 0x1C) == 0x10)?(shift = isRightShift*(16 - elemWidth) + (isRightShift>0?0:8)):(isValid = false);
2561                                  break;
2562                         case 0x2:((opcode & 0x1C) == 0x0C || (opcode & 0x1C) == 0x10)?(shift = isRightShift*(32 - elemWidth) + (isRightShift>0?0:16)):(isValid = false);
2563                                  break;
2564                         case 0x3:(opcode > 0x0A)?(shift = isRightShift*(64 - elemWidth) + (isRightShift>0?0:32)):(isValid = false);
2565                                  break;
2566                         case 0x4:shift = isRightShift*(128 - elemWidth) + (isRightShift>0?0:64);
2567                                  break;
2568                         default:isValid = false;
2569                     }
2570
2571                     if(isValid)
2572                     {
2573                         Expression::Ptr imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immloLen + immLen, shift)));
2574                         insn_in_progress->appendOperand(imm, true, false);
2575                     }
2576                 }
2577                 else
2578                     isValid = false;
2579             }
2580         }
2581         else                                                            //conditional compare (immediate)
2582         {
2583                 Result_Type rT = is64Bit?u64:u32;
2584
2585                 Expression::Ptr imm = Immediate::makeImmediate(Result(rT, rT==u32?unsign_extend32(immLen, immVal):unsign_extend64(immLen, immVal)));
2586                 insn_in_progress->appendOperand(imm, true, false);
2587         }
2588 }
2589
2590         void InstructionDecoder_aarch64::reorderOperands()
2591         {
2592             if(oprRotateAmt)
2593             {
2594                         std::vector<Operand> curOperands;
2595                         insn_in_progress->getOperands(curOperands);
2596
2597                         if(curOperands.empty())
2598                                 assert(!"empty operand list found while re-ordering operands");
2599
2600                         std::swap(curOperands[1], curOperands[3]);
2601
2602                         while(oprRotateAmt--)
2603                                 std::rotate(curOperands.begin(), curOperands.begin()+1, curOperands.begin()+3);
2604
2605                         insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2606             }
2607         else if( IS_INSN_LDST_POST(insn) || IS_INSN_LDST_PAIR_POST(insn) ){
2608                 std::vector<Operand> curOperands;
2609                 insn_in_progress->getOperands(curOperands);
2610             std::iter_swap( curOperands.begin(), curOperands.end()-1 );
2611                     insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2612         }
2613         else if( IS_INSN_LDST_PAIR(insn) ){
2614                     std::vector<Operand> curOperands;
2615                     insn_in_progress->getOperands(curOperands);
2616             assert(curOperands.size() == 4 || curOperands.size() == 3);
2617             if(curOperands.size() == 3){
2618                 curOperands.insert(curOperands.begin(), curOperands.back());
2619                 curOperands.pop_back();
2620             }else if(curOperands.size() == 4){
2621                 std::iter_swap( curOperands.begin(), curOperands.end()-1 );
2622             }
2623                     insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2624         }
2625         else if( IS_INSN_LDST_EX_PAIR(insn) ){
2626                     std::vector<Operand> curOperands;
2627                     insn_in_progress->getOperands(curOperands);
2628             if(curOperands.size() == 3) {
2629                 curOperands.insert(curOperands.begin(), curOperands.back());
2630                 curOperands.pop_back();
2631             }
2632             else if( curOperands.size() == 4) {
2633                 curOperands.insert(curOperands.begin()+1, curOperands.back());
2634                 curOperands.pop_back();
2635             }
2636                     insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2637         }
2638         else if( IS_INSN_ST_EX(insn) ){
2639                     std::vector<Operand> curOperands;
2640                     insn_in_progress->getOperands(curOperands);
2641             if(curOperands.size() == 3){
2642                 curOperands.insert(curOperands.begin()+1, curOperands.back());
2643                 curOperands.pop_back();
2644                         insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2645             }
2646             else
2647                         insn_in_progress->m_Operands.reverse();
2648         }
2649             else
2650                     insn_in_progress->m_Operands.reverse();
2651         }
2652
2653 void InstructionDecoder_aarch64::processAlphabetImm()
2654 {
2655    if(op == 1 && cmode == 0xE)
2656    {
2657         uint64_t imm = 0;
2658
2659         for(int imm_index = 0; imm_index < 8; imm_index++)
2660                 imm |= (simdAlphabetImm & (1 << imm_index))?(0xFF << (imm_index * 8)):0;
2661
2662         insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u64, imm)), true, false);
2663    }
2664    else if(cmode == 0xF)
2665    {
2666        //fmov (vector, immediate)
2667        //TODO: check with Bill if this is fine
2668       insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, simdAlphabetImm)), true, false); 
2669    }
2670    else
2671    {
2672         int shiftAmt = 0;
2673
2674         //16-bit shifted immediate
2675         if((cmode & 0xC) == 0x8)
2676             shiftAmt = ((cmode & 0x2) >> 1) * 8;
2677         //32-bit shifted immediate
2678         else if((cmode & 0x8) == 0x0)
2679             shiftAmt = ((cmode & 0x6) >> 1) * 8;
2680         //32-bit shifting ones
2681         else if((cmode & 0xE) == 0xC)
2682             shiftAmt = ((cmode & 0x0) + 1) * 8;
2683         
2684         Expression::Ptr lhs = Immediate::makeImmediate(Result(u32, unsign_extend32(8, simdAlphabetImm)));
2685         Expression::Ptr rhs = Immediate::makeImmediate(Result(u32, unsign_extend32(5, shiftAmt)));
2686         Expression::Ptr imm = makeLeftShiftExpression(lhs, rhs, u64);
2687
2688         insn_in_progress->appendOperand(imm, true, false);
2689    } 
2690 }
2691
2692 using namespace boost::assign;
2693
2694 #include "aarch64_opcode_tables.C"
2695
2696         void InstructionDecoder_aarch64::doDelayedDecode(const Instruction *insn_to_complete)
2697     {
2698                 int insn_table_index = findInsnTableIndex(0);
2699                 aarch64_insn_entry *insn_table_entry = &aarch64_insn_entry::main_insn_table[insn_table_index];
2700
2701                 insn = insn_to_complete->m_RawInsn.small_insn;
2702                 insn_in_progress = const_cast<Instruction*>(insn_to_complete);
2703         for(operandSpec::const_iterator fn = insn_table_entry->operands.begin(); fn != insn_table_entry->operands.end(); fn++)
2704         {
2705                         std::mem_fun(*fn)(this);
2706                 }
2707
2708                 if(insn_table_index == 0)
2709                     isValid = false;
2710
2711                 if(!isValid)
2712                 {
2713                         insn_in_progress->getOperation().mnemonic = INVALID_ENTRY.mnemonic;
2714                         insn_in_progress->getOperation().operationID = INVALID_ENTRY.op;
2715                         insn_in_progress->m_Operands.clear();
2716                         insn_in_progress->m_Successors.clear();
2717                 }
2718                 else
2719                 {
2720                     reorderOperands();
2721
2722                     if(IS_INSN_SYSTEM(insn))
2723                     {
2724                         processSystemInsn();
2725                     }
2726
2727                     if(IS_INSN_SIMD_MOD_IMM(insn))
2728                     {
2729                         processAlphabetImm();
2730                     }
2731
2732                     if(IS_INSN_LDST_SIMD_MULT_POST(insn) || IS_INSN_LDST_SIMD_SING_POST(insn))
2733                         insn_in_progress->appendOperand(makeRnExpr(), false, true);
2734
2735                     if(isPstateWritten || isPstateRead)
2736                         insn_in_progress->appendOperand(makePstateExpr(), isPstateRead, isPstateWritten);
2737                 }
2738
2739     }
2740         int InstructionDecoder_aarch64::findInsnTableIndex(unsigned int decoder_table_index)
2741         {
2742                 aarch64_mask_entry *cur_entry = &aarch64_mask_entry::main_decoder_table[decoder_table_index];
2743                 unsigned int cur_mask = cur_entry->mask;
2744
2745                 if(cur_mask == 0)
2746                 {
2747                         /*if(cur_entry->insnTableIndices.size() == 1)
2748                                 return cur_entry->insnTableIndices[0];
2749
2750                         int insn_table_index = -1;
2751                         for(std::vector<int>::iterator itr = cur_entry->insnTableIndices.begin(); itr != cur_entry->insnTableIndices.end(); itr++)
2752                         {
2753                                 aarch64_insn_entry *nextEntry = &aarch64_insn_entry::main_insn_table[*itr];
2754                                 if((insn & nextEntry->_maskBits) == nextEntry->_encodingBits)
2755                                 {
2756                                         insn_table_index = *itr;
2757                                         break;
2758                                 }
2759                         }*/
2760
2761                         int insn_table_index = cur_entry->insnTableIndex;
2762                         if(insn_table_index == -1)
2763                                 assert(!"no instruction table entry found for current instruction");
2764                         else
2765                                 return insn_table_index;
2766                 }
2767
2768                 unsigned int insn_iter_index = 0, map_key_index = 0, branch_map_key = 0;
2769                 branchMap cur_branches = cur_entry->nodeBranches;
2770
2771                 while(insn_iter_index < AARCH64_INSN_LENGTH)
2772                 {
2773                         if(((cur_mask>>insn_iter_index) & 1) == 1)
2774                         {
2775                                 branch_map_key = branch_map_key | (((insn>>insn_iter_index) & 1)<<map_key_index);
2776                                 map_key_index++;
2777                         }
2778                         insn_iter_index++;
2779                 }
2780
2781                 if(cur_branches.count(branch_map_key) <= 0)
2782                     return 0;
2783                 //      branch_map_key = 0;
2784
2785                 return findInsnTableIndex(cur_branches[branch_map_key]);
2786         }
2787
2788         void InstructionDecoder_aarch64::setFlags()
2789         {
2790                 isPstateWritten = true;
2791         }
2792
2793     void InstructionDecoder_aarch64::mainDecode()
2794     {
2795                 int insn_table_index = findInsnTableIndex(0);
2796                 aarch64_insn_entry *insn_table_entry = &aarch64_insn_entry::main_insn_table[insn_table_index];
2797
2798         insn_in_progress = makeInstruction(insn_table_entry->op, insn_table_entry->mnemonic, 4, reinterpret_cast<unsigned char*>(&insn));
2799         //insn_printf("ARM: %s\n", insn_table_entry->mnemonic);
2800
2801         if(IS_INSN_BRANCHING(insn))
2802         {
2803             // decode control-flow operands immediately; we're all but guaranteed to need them
2804             doDelayedDecode(insn_in_progress);
2805         }
2806
2807         //insn_in_progress->arch_decoded_from = m_Arch;
2808         insn_in_progress->arch_decoded_from = Arch_aarch64;
2809         return;
2810     }
2811   };
2812 };
2813
2814
2815