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