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