updated decoder-aarch64 for LDST SIMD
[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         /*
101                 aarch64_mask_entry(unsigned int m, branchMap bm, int tabIndex):
102                 mask(m), nodeBranches(bm), insnTableIndex(tabIndex)
103                 {
104                 }
105         */
106
107                 aarch64_mask_entry(unsigned int m, branchMap bm, std::vector<int> tabIndices):
108                 mask(m), nodeBranches(bm), insnTableIndices(tabIndices)
109                 {
110                 }
111
112                 aarch64_mask_entry():
113                 mask(0), nodeBranches(branchMap()), insnTableIndices(std::vector<int>())
114                 {
115                 }
116
117                 aarch64_mask_entry(const aarch64_mask_entry& e):
118                 mask(e.mask), nodeBranches(e.nodeBranches), insnTableIndices(e.insnTableIndices)
119                 {
120                 }
121
122                 const aarch64_mask_entry& operator=(const aarch64_mask_entry& rhs)
123                 {
124                         mask = rhs.mask;
125                         nodeBranches = rhs.nodeBranches;
126                         insnTableIndices = rhs.insnTableIndices;
127
128                         return *this;
129                 }
130
131                 unsigned int mask;
132                 branchMap nodeBranches;
133         std::vector<int> insnTableIndices;
134
135                 static void buildDecoderTable();
136                 static bool built_decoder_table;
137                 static aarch64_decoder_table main_decoder_table;
138         };
139
140     InstructionDecoder_aarch64::InstructionDecoder_aarch64(Architecture a)
141       : InstructionDecoderImpl(a), isPstateRead(false), isPstateWritten(false), isFPInsn(false),isSIMDInsn(false),
142             is64Bit(true), isValid(true), insn(0), insn_in_progress(NULL),
143         hasHw(false), hasShift(false), hasOption(false), hasN(false),
144         immr(0), immrLen(0), sField(0), nField(0), nLen(0),
145         immlo(0), immloLen(0), _szField(-1)
146     {
147         aarch64_insn_entry::buildInsnTable();
148         aarch64_mask_entry::buildDecoderTable();
149         InstructionDecoder_aarch64::buildSysRegMap();
150
151         std::string condArray[16] = {"eq","ne","cs","cc","mi","pl","vs","vc","hi","ls","ge","lt","gt","le","al","nv"};
152         InstructionDecoder_aarch64::condStringMap.assign(&condArray[0], &condArray[0] + 16);
153     }
154
155     InstructionDecoder_aarch64::~InstructionDecoder_aarch64()
156     {
157     }
158
159     void InstructionDecoder_aarch64::decodeOpcode(InstructionDecoder::buffer& b)
160     {
161       b.start += 4;
162     }
163
164     using namespace std;
165     Instruction::Ptr InstructionDecoder_aarch64::decode(InstructionDecoder::buffer& b)
166     {
167         if(b.start > b.end)
168             return Instruction::Ptr();
169
170                 isPstateRead = isPstateWritten = false;
171         isFPInsn = false;
172         isSIMDInsn = false;
173         isValid = true;
174         is64Bit = true;
175
176         hasHw = false;
177         hwField = 0;
178
179         hasShift = false;
180         shiftField = 0;
181
182         hasOption = false;
183         optionField = 0;
184
185         hasN = false;
186         sField = nField = nLen = 0;
187         immr = immrLen = 0;
188
189         op1Field = op2Field = crmField = 0;
190
191         immlo = immloLen = 0;
192
193         _szField = -1;
194
195                 oprRotateAmt = 0;
196                 hasb5 = false;
197
198         insn = b.start[0] << 24 | b.start[1] << 16 |
199         b.start[2] << 8 | b.start[3];
200
201 #if defined(DEBUG_RAW_INSN)
202         cout.width(0);
203         cout << "0x";
204         cout.width(8);
205         cout.fill('0');
206         cout << hex << insn << "\t";
207 #endif
208
209                 mainDecode();
210         b.start += 4;
211
212         return make_shared(insn_in_progress);
213     }
214
215     /* replace this function with a more generic function, which is setRegWidth
216     void InstructionDecoder_aarch64::set32Mode()
217     {
218         // NOTE: is64Bit is set by default.
219                 is64Bit = false;
220     }
221     */
222     void InstructionDecoder_aarch64::NOTHING(){
223     }
224
225     void InstructionDecoder_aarch64::setFPMode()
226     {
227         // NOTE: if it is fp, only isFP is set.
228                 isFPInsn = true;
229     }
230
231      //TODO: consistency issue
232      void InstructionDecoder_aarch64::setSIMDMode()
233     {
234         // NOTE: if it is SIMD insn, both isFP and isSIMD are set.
235                 isFPInsn = true;
236                 isSIMDInsn = true;
237     }
238
239         template<unsigned int endBit, unsigned int startBit>
240     void InstructionDecoder_aarch64::OPRtype(){
241         _typeField = field<startBit, endBit>(insn);
242     }
243
244     bool InstructionDecoder_aarch64::decodeOperands(const Instruction *)
245     {
246                 return false;
247     }
248
249         void InstructionDecoder_aarch64::processHwFieldInsn(int len, int val)
250         {
251                 Result_Type rT = is64Bit?u64:u32;
252
253                 unsigned int shiftAmount = hwField*16;
254
255                 Expression::Ptr lhs = Immediate::makeImmediate(Result(rT, rT==u32?unsign_extend32(len, val):unsign_extend64(len, val)));
256                 Expression::Ptr rhs = Immediate::makeImmediate(Result(u32, unsign_extend32(6, shiftAmount)));
257
258                 insn_in_progress->appendOperand(makeLeftShiftExpression(lhs, rhs, rT), true, false);
259         }
260
261         void InstructionDecoder_aarch64::processShiftFieldShiftedInsn(int len, int val)
262         {
263                 Result_Type rT;
264                 Expression::Ptr lhs, rhs;
265
266                 rT = is64Bit?u64:u32;
267
268             lhs = makeRmExpr();
269             rhs = Immediate::makeImmediate(Result(u32, unsign_extend32(len, val)));
270
271                 switch(shiftField)                                                                                      //add-sub (shifted) and logical (shifted)
272                 {
273                         case 0:insn_in_progress->appendOperand(makeLeftShiftExpression(lhs, rhs, rT), true, false);
274                                    break;
275                         case 1:insn_in_progress->appendOperand(makeRightLogicalShiftExpression(lhs, rhs, rT), true, false);
276                                    break;
277                         case 2:insn_in_progress->appendOperand(makeRightArithmeticShiftExpression(lhs, rhs, rT), true, false);
278                                    break;
279                         case 3:if(IS_INSN_LOGICAL_SHIFT(insn))                                  //logical (shifted) -- not applicable to add-sub (shifted)
280                                                 insn_in_progress->appendOperand(makeRightRotateExpression(lhs, rhs, rT), true, false);
281                                    else
282                                                 isValid = false;
283                                    break;
284                 }
285         }
286
287         void InstructionDecoder_aarch64::processShiftFieldImmInsn(int len, int val)
288         {
289                 if(shiftField == 0 || shiftField == 1)                                          //add-sub (immediate)
290                 {
291                         Result_Type rT = is64Bit?u64:u32;
292
293                         unsigned int shiftAmount = shiftField * 12;
294
295                         Expression::Ptr lhs = Immediate::makeImmediate(Result(rT, rT==u32?unsign_extend32(len, val):unsign_extend64(len, val)));
296                         Expression::Ptr rhs = Immediate::makeImmediate(Result(u32, unsign_extend32(4, shiftAmount)));
297
298                         insn_in_progress->appendOperand(makeLeftShiftExpression(lhs, rhs, rT), true, false);
299                 }
300                 else
301                 {
302                         isValid = false;
303                 }
304
305         }
306
307         Expression::Ptr InstructionDecoder_aarch64::makeOptionExpression(int len, int val)
308         {
309                 MachRegister reg;
310                 int encoding = field<16, 20>(insn);
311
312                 reg = ((optionField & 0x3) == 0x3)?((encoding == 31)?aarch64::zr:aarch64::x0):((encoding == 31)?aarch64::wzr:aarch64::w0);
313                 if(encoding != 31)
314                         reg = makeAarch64RegID(reg, encoding);
315
316                 Expression::Ptr lhs;
317
318                 switch(optionField)
319                 {
320                         case 0:lhs = makeRegisterExpression(reg, u8);
321                                         break;
322                         case 1:lhs = makeRegisterExpression(reg, u16);
323                                         break;
324                         case 2:lhs = makeRegisterExpression(reg, u32);
325                                         break;
326                         case 3:lhs = makeRegisterExpression(reg, u64);
327                                         break;
328                         case 4:lhs = makeRegisterExpression(reg, s8);
329                                         break;
330                         case 5:lhs = makeRegisterExpression(reg, s16);
331                                         break;
332                         case 6:lhs = makeRegisterExpression(reg, s32);
333                                         break;
334                         case 7:lhs = makeRegisterExpression(reg, s64);
335                                         break;
336                         default: assert(!"invalid option field value");
337                 }
338
339                 Result_Type rT = is64Bit?(optionField<4?u64:s64):(optionField<4?u32:s32);
340
341                 return makeLeftShiftExpression(lhs, Immediate::makeImmediate(Result(u32, unsign_extend32(len, val))), rT);
342         }
343
344         void InstructionDecoder_aarch64::processOptionFieldLSRegOffsetInsn()
345         {
346                 if(optionField == 0x3)                  //option = LSL
347                 {
348                         int sizeVal = field<30, 31>(insn), extend;
349
350                         if(field<23, 23>(insn) == 1)
351                                 sizeVal = 4;
352
353                         extend = sField * sizeVal;
354                         int extendSize = 31;
355                         while(extendSize >= 0  && ((extend << (31 - extendSize)) & 0x80000000) == 0)
356                                 extendSize--;
357
358                         //above values need to be used in a dereference expression
359                 }
360                 else
361                 {
362                         //sign-extend
363                         switch(optionField)
364                         {
365                                 case 0x2://UXTW
366                                                  break;
367                                 case 0x6://SXTW
368                                                  break;
369                                 case 0x7://SXTX
370                                                  break;
371                                 default:isValid = false;
372                                                 break;
373                         }
374                 }
375         }
376
377         void InstructionDecoder_aarch64::processSystemInsn()
378         {
379                 int op0Field = field<19, 20>(insn), crnField = field<12, 15>(insn);
380
381                 if(op0Field == 0)
382                 {
383                         if(crnField == 3)                       //clrex, dendBit, dmb, iendBit
384                         {
385                                 Expression::Ptr CRm = Immediate::makeImmediate(Result(u8, unsign_extend32(4, crmField)));
386
387                                 insn_in_progress->appendOperand(CRm, true, false);
388                         }
389                         else if(crnField == 2)                    //hint
390                         {
391                                 int immVal = (crmField << 3)|(op2Field & 7);
392
393                                 Expression::Ptr imm = Immediate::makeImmediate(Result(u8, unsign_extend32(7, immVal)));
394
395                                 insn_in_progress->appendOperand(imm, true, false);
396                         }
397                         else if(crnField == 4)                          //msr (immediate)
398                         {
399                                 int pstatefield = (op1Field << 3) | (op2Field & 7);
400                                 insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, unsign_extend32(6, pstatefield))), true, false);
401
402                                 insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, unsign_extend32(4, crmField))), true, false);
403
404                                 isPstateWritten = true;
405                         }
406                         else
407                         {
408                                 isValid = false;
409                         }
410                 }
411                 else if(op0Field == 1)                  //sys, sysl
412                 {
413                         insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, unsign_extend32(3, op1Field))), true, false);
414                         insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, unsign_extend32(4, crnField))), true, false);
415                         insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, unsign_extend32(4, crmField))), true, false);
416                         insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, unsign_extend32(3, op2Field))), true, false);
417
418                         bool isRtRead = (field<21, 21>(insn) == 0);
419                         insn_in_progress->appendOperand(makeRtExpr(), isRtRead, !isRtRead);
420                 }
421                 else                   //mrs (register), msr
422                 {
423                         bool isRtRead = (field<21, 21>(insn) == 0);
424
425                         unsigned int systemRegEncoding = (op0Field << 14) | (op1Field << 11) | (crnField << 7) | (crmField << 3) | op2Field;
426                         if(InstructionDecoder_aarch64::sysRegMap.count(systemRegEncoding) <= 0)
427                                 assert(!"tried to access system register not accessible in EL0");
428
429                         insn_in_progress->appendOperand(makeRegisterExpression(InstructionDecoder_aarch64::sysRegMap[systemRegEncoding]), !isRtRead, isRtRead);
430                         insn_in_progress->appendOperand(makeRtExpr(), isRtRead, !isRtRead);
431                         if(!isRtRead)
432                             insn_in_progress->m_Operands.reverse();
433                 }
434         }
435
436     Result_Type InstructionDecoder_aarch64::makeSizeType(unsigned int)
437     {
438         assert(0); //not implemented
439         return u32;
440     }
441
442     // ****************
443     // decoding opcodes
444     // ****************
445
446 #define fn(x) (&InstructionDecoder_aarch64::x)
447 #define COMMA   ,
448
449 MachRegister InstructionDecoder_aarch64::makeAarch64RegID(MachRegister base, unsigned int encoding)
450 {
451     return MachRegister(base.val() + encoding);
452 }
453
454 Expression::Ptr InstructionDecoder_aarch64::makeRdExpr()
455 {
456     int encoding  = field<0, 4>(insn);
457         MachRegister reg;
458
459     if( isSIMDInsn ){
460         reg = aarch64::q0;
461         reg = makeAarch64RegID(reg, encoding);
462     } else
463         if(isFPInsn && !((IS_INSN_FP_CONV_FIX(insn) || (IS_INSN_FP_CONV_INT(insn))) && !IS_SOURCE_GP(insn)))
464         {
465
466                 if(IS_INSN_FP_DATAPROC_ONESRC(insn))
467                 {
468                         int opc = field<15, 16>(insn);
469                         switch(opc)
470                         {
471                                 case 0: reg = aarch64::s0;
472                                                 break;
473                                 case 1: reg = aarch64::d0;
474                                                 break;
475                                 case 3: reg = aarch64::h0;
476                                                 break;
477                                 default: assert(!"invalid destination register size");
478                         }
479                 }
480                 else
481                         reg = isSinglePrec()?aarch64::s0:aarch64::d0;
482
483                 reg = makeAarch64RegID(reg, encoding);
484         }
485         else
486         {
487                 reg = is64Bit?((encoding == 31)?aarch64::sp:aarch64::x0):((encoding == 31)?aarch64::wsp:aarch64::w0);
488                 if(encoding != 31)
489                         reg = makeAarch64RegID(reg, encoding);
490         }
491
492         return makeRegisterExpression(reg);
493 }
494
495 void InstructionDecoder_aarch64::OPRRd()
496 {
497     insn_in_progress->appendOperand(makeRdExpr(), false, true);
498 }
499
500 Expression::Ptr InstructionDecoder_aarch64::makeRnExpr()
501 {
502     int encoding  = field<5, 9>(insn);
503         MachRegister reg;
504
505     if( isSIMDInsn && !IS_INSN_LDST(insn) ){
506         reg = aarch64::q0;
507         reg = makeAarch64RegID(reg, encoding);
508     } else
509         if(isFPInsn && !((IS_INSN_FP_CONV_FIX(insn) || (IS_INSN_FP_CONV_INT(insn))) && IS_SOURCE_GP(insn)))
510         {
511                 switch(_typeField)
512                 {
513                     case 0: reg = aarch64::s0;
514                         break;
515                     case 1: reg = aarch64::d0;
516                                 break;
517                     case 3: reg = aarch64::h0;
518                                 break;
519                     default: assert(!"invalid source register size");
520                 }
521                 reg = makeAarch64RegID(reg, encoding);
522         }
523     else if(IS_INSN_LDST(insn)){
524         reg = encoding == 31?aarch64::sp:aarch64::x0;
525                 if(encoding != 31)
526                         reg = makeAarch64RegID(reg, encoding);
527     }
528         else
529         {
530                 reg = is64Bit?((encoding == 31)?aarch64::sp:aarch64::x0):((encoding == 31)?aarch64::wsp:aarch64::w0);
531                 if(encoding != 31)
532                         reg = makeAarch64RegID(reg, encoding);
533         }
534
535         return makeRegisterExpression(reg);
536 }
537
538 Expression::Ptr InstructionDecoder_aarch64::makePCExpr()
539 {
540         MachRegister baseReg = aarch64::pc;
541
542         return makeRegisterExpression(makeAarch64RegID(baseReg, 0));
543 }
544
545 Expression::Ptr InstructionDecoder_aarch64::makePstateExpr()
546 {
547         MachRegister baseReg = aarch64::pstate;
548
549         return makeRegisterExpression(makeAarch64RegID(baseReg, 0));
550 }
551
552
553 void InstructionDecoder_aarch64::getMemRefIndexLiteral_OffsetLen(int &immVal, int &immLen){
554     immVal = field<5, 23>(insn);
555     immVal = immVal << 2; //immVal:00
556     immLen = (23 - 5 + 1) + 2;
557     return;
558 }
559
560 void InstructionDecoder_aarch64::getMemRefIndexLiteral_RT(Result_Type &rt){
561     int size = field<30, 31>(insn);
562     switch(size){
563         case 0x0:
564             rt = u32;
565             break;
566         case 0x1:
567             rt = u64;
568             break;
569         case 0x2:
570             rt = s32;
571             break;
572         case 0x3:
573         default:
574             assert(0);
575             break;
576     }
577     return;
578 }
579
580 // ****************************************
581 // load/store literal
582 // eg: load Xt, <literal>
583 // => offset = signextend(<literal>:00, 64)
584 // load from [PC + offset] to Xt
585 // ****************************************
586 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexLiteral()
587 {
588     int immVal, immLen;
589     getMemRefIndexLiteral_OffsetLen(immVal, immLen);
590
591     Expression::Ptr label = Immediate::makeImmediate(Result(s32, sign_extend32(immLen, immVal)));
592
593     Result_Type rt;
594     getMemRefIndexLiteral_RT(rt);
595
596     return makeDereferenceExpression(makeAddExpression(label, makePCExpr(), u64), rt);
597 }
598
599 // TODO potential bug: do we need to distinguish signed and unsigned here?
600 // this funciton is to get the mem ref size
601 // shared by ld/st uimm, post, pre, reg
602 void InstructionDecoder_aarch64::getMemRefIndex_RT(Result_Type &rt){
603     unsigned int opc1 = field<23, 23>(insn);
604     unsigned int size = field<30, 31>(insn);
605
606     if(opc1 == 1){
607         switch(size){
608             case 0:
609                 rt = s8;
610                 break;
611             case 1:
612                 rt = s16;
613                 break;
614             case 2:
615                 rt = s32;
616                 break;
617             case 3:
618                 rt = s64;
619                 break;
620             default:
621                 assert(0);
622                 //should only be 2 or 3
623                 break;
624         }
625     }else{
626         switch(size){
627             case 0:
628                 rt = u8;
629                 break;
630             case 1:
631                 rt = u16;
632                 break;
633             case 2:
634                 rt = u32;
635                 break;
636             case 3:
637                 rt = u64;
638                 break;
639             default:
640                 assert(0);
641                 //should only be 2 or 3
642                 break;
643         }
644     }
645
646     return;
647 }
648
649 void InstructionDecoder_aarch64::getMemRefPair_RT(Result_Type &rt){
650     unsigned int isSigned = field<30,30>(insn);
651     unsigned int size = field<31, 31>(insn);
652
653     // double the width
654     switch(isSigned){
655         case 0:
656             switch(size){
657                 case 0:
658                     //rt = u32;
659                     rt = u64;
660                     break;
661                 case 1:
662                     //rt = u64;
663                     rt = dbl128;
664                     break;
665                 default:
666                     assert(0);
667             }
668             break;
669         case 1:
670             switch(size){
671                 case 0:
672                     //rt = s32;
673                     rt = s64;
674                     break;
675                 case 1:
676                 default:
677                     assert(0);
678             }
679             break;
680         default:
681             assert(0);
682             break;
683     }
684
685     return;
686 }
687
688 void InstructionDecoder_aarch64::getMemRefIndex_SizeSizelen(unsigned int &size, unsigned int &sizeLen){
689     size = field<30, 31>(insn);
690     sizeLen = 31-30+1;
691     return;
692 }
693
694 void InstructionDecoder_aarch64::getMemRefIndexPrePost_ImmImmlen(unsigned int &immVal, unsigned int &immLen){
695     immVal = field<12, 20>(insn);
696     immLen = 20 - 12 + 1;
697     return;
698 }
699
700 void InstructionDecoder_aarch64::getMemRefPair_ImmImmlen(unsigned int &immVal, unsigned int &immLen){
701     immVal = field<15, 21>(insn);
702     immLen = 21-15 + 1;
703     return;
704 }
705
706 // ****************************************
707 // load/store unsigned imm
708 // eg: load Xt, [Xn, #imm]
709 // => offset = unsignextend( imm , 64)
710 // load from [PC + offset] to Xt
711 // ****************************************
712 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexUImm()
713 {
714     assert( IS_INSN_LDST_UIMM(insn) );
715
716     int immVal = field<10, 21>(insn);
717     int immLen = 21 - 10 + 1;
718
719     unsigned int size = 0, sizeLen = 0;
720     getMemRefIndex_SizeSizelen(size, sizeLen);
721
722     Expression::Ptr offset = Immediate::makeImmediate( Result(u64, unsign_extend64( immLen+size, immVal<<size) ) );
723
724     /*
725     Expression::Ptr scaleForUImm = Immediate::makeImmediate(Result(u32, unsign_extend32(sizeLen + size, 1<<size)));
726     Expression::Ptr offset = makeMultiplyExpression(imm, scaleForUImm, u64);
727     */
728
729     Result_Type rt;
730     getMemRefIndex_RT(rt);
731     return makeDereferenceExpression( makeAddExpression(makeRnExpr(), offset, u64), rt);
732 }
733
734 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndex_offset9(){
735     unsigned int immVal = 0, immLen = 0;
736     getMemRefIndexPrePost_ImmImmlen(immVal, immLen);
737     return Immediate::makeImmediate(Result(u32, sign_extend32(immLen, immVal)));
738 }
739
740 // scale = 2 + opc<1>
741 // scale = 1<<scale
742 // LSL(sign_ex(imm7 , 64), scale)
743 Expression::Ptr InstructionDecoder_aarch64::makeMemRefPair_offset7(){
744     /*
745     unsigned int scaleVal = field<31, 31>(insn);
746     unsigned int scaleLen = 8;
747     scaleVal += 2;
748     Expression::Ptr scale = Immediate::makeImmediate(Result(u32, unsign_extend32(scaleLen, 1<<scaleVal)));
749     */
750
751     unsigned int immVal = 0, immLen = 0;
752     getMemRefPair_ImmImmlen(immVal, immLen);
753
754     immVal = is64Bit?immVal<<3:immVal<<2;
755     Expression::Ptr imm7 = Immediate::makeImmediate(Result(u64, sign_extend64(immLen, immVal)));
756
757     //return makeMultiplyExpression(imm7, scale, s64);
758     return imm7;
759 }
760
761 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndex_addOffset9(){
762     Expression::Ptr offset = makeMemRefIndex_offset9();
763     return makeAddExpression(makeRnExpr(), offset, u64);
764 }
765
766 Expression::Ptr InstructionDecoder_aarch64::makeMemRefPair_addOffset7(){
767     Expression::Ptr offset = makeMemRefPair_offset7();
768     return makeAddExpression(makeRnExpr(), offset, u64);
769 }
770
771 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexPre(){
772     Result_Type rt;
773     getMemRefIndex_RT(rt);
774     return makeDereferenceExpression(makeMemRefIndex_addOffset9(), rt);
775 }
776
777 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexPost(){
778     Result_Type rt;
779     getMemRefIndex_RT(rt);
780     return makeDereferenceExpression(makeRnExpr(), rt);
781 }
782
783 Expression::Ptr InstructionDecoder_aarch64::makeMemRefPairPre(){
784     Result_Type rt;
785     getMemRefPair_RT(rt);
786     return makeDereferenceExpression(makeMemRefPair_addOffset7(), rt);
787 }
788
789 /*
790 Expression::Ptr InstructionDecoder_aarch64::makeMemRefPairPre2(){
791     // datasize = 64/32 /8;
792     unsigned int opc1 = field<31, 31>(insn);
793     unsigned int sizeVal = 1<<(2+opc1); //4 or 8 bytes
794
795     Expression::Ptr dataSize = Immediate::makeImmediate(Result(u32, unsign_extend32( 32, sizeVal ) ) );
796     Expression::Ptr pair2 = makeAddExpression( makeMemRefPair_addOffset7(), dataSize, u64);
797
798     Result_Type rt;
799     getMemRefPair_RT(rt);
800     return makeDereferenceExpression(pair2, rt);
801 }
802 */
803
804 Expression::Ptr InstructionDecoder_aarch64::makeMemRefPairPost(){
805     Result_Type rt;
806     getMemRefPair_RT(rt);
807     return makeDereferenceExpression(makeRnExpr(), rt);
808 }
809
810 /*
811 Expression::Ptr InstructionDecoder_aarch64::makeMemRefPairPost2(){
812     // datasize = 64/32 /8;
813     unsigned int opc1 = field<31, 31>(insn);
814     unsigned int sizeVal = 1<<(2+opc1); //4 or 8 bytes
815
816     Expression::Ptr dataSize = Immediate::makeImmediate(Result(u32, unsign_extend32( 32, sizeVal ) ) );
817     Expression::Ptr pair2 = makeAddExpression( makeRnExpr(), dataSize, u64);
818
819     Result_Type rt;
820     getMemRefPair_RT(rt);
821     return makeDereferenceExpression(pair2, rt);
822 }
823 */
824
825 void InstructionDecoder_aarch64::getMemRefEx_RT(Result_Type &rt){
826     unsigned int sz = field<30, 31>(insn);
827     switch(sz){
828         case 0x00: //B
829             rt = u8;
830             break;
831         case 0x01: //H
832             rt = u16;
833             break;
834         case 0x02: //32b
835             rt = u32;
836             break;
837         case 0x03: //64b
838             rt = u64;
839             break;
840         default:
841             rt = u64;
842     }
843     return;
844 }
845
846 Expression::Ptr InstructionDecoder_aarch64::makeMemRefEx(){
847     Result_Type rt;
848     getMemRefEx_RT(rt);
849     return makeDereferenceExpression(makeRnExpr(), rt);
850 }
851
852 void InstructionDecoder_aarch64::OPRQ(){
853     _Q = field<30, 30>(insn);
854 }
855
856 void InstructionDecoder_aarch64::OPRL(){
857     _L = field<30, 30>(insn);
858 }
859
860 void InstructionDecoder_aarch64::getMemRefSIMD_MULT_RT(Result_Type &rt){
861     //TODO
862     rt = dbl128;
863 }
864
865 Expression::Ptr InstructionDecoder_aarch64::makeMemRefSIMD_MULT(){
866     Result_Type rt;
867     getMemRefSIMD_MULT_RT(rt);
868     return makeDereferenceExpression(makeRnExpr(), rt);
869 }
870
871 void InstructionDecoder_aarch64::getMemRefExPair_RT(Result_Type &rt){
872     int size = field<30, 30>(insn);
873     switch(size){
874         case 0:
875             rt = u64;
876             break;
877         case 1:
878             rt = dbl128;
879             break;
880         default:
881             assert(!"should not reach here");
882             break;
883     }
884     return;
885 }
886
887 Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair(){
888     Result_Type rt;
889     getMemRefExPair_RT(rt);
890     return makeDereferenceExpression(makeRnExpr(), rt);
891 }
892
893 /*
894 Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair16B(){
895     return makeDereferenceExpression(makeRnExpr(), dbl128);
896 }
897 */
898
899 /*
900 Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair2(){
901     unsigned int immLen = 4, immVal = 8;
902     Expression::Ptr offset = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));
903     return makeDereferenceExpression(makeAddExpression(makeRnExpr(), offset, u64) , u64);
904 }
905 */
906
907 Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_Rm(){
908     unsigned int option = field<13, 15>(insn);
909     if((option&2) != 2) assert(0);
910     MachRegister baseReg = ((option & 0x3)==0x2) ? aarch64::w0 : aarch64::x0;
911     unsigned int encoding = field<16, 20>(insn);
912
913         if( encoding == 31 )//zero register
914                 return makeRegisterExpression(makeAarch64RegID(aarch64::zr, 0));
915     else
916         return makeRegisterExpression(makeAarch64RegID(baseReg, encoding));
917 }
918
919 Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_amount(){
920     unsigned int S =  field<12, 12>(insn);
921     unsigned int amountVal = is64Bit?(S==0?0:2):(S==0?0:3);
922     unsigned int amountLen = 2;
923
924     return Immediate::makeImmediate(Result(u32, unsign_extend32(amountLen, amountVal)) ) ;
925 }
926
927 Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_ext(){
928     //TODO
929     /*
930         int sizeVal = field<30, 31>(insn), extend;
931
932         if(field<23, 23>(insn) == 1)
933                 sizeVal = 4;
934
935         extend = sField * sizeVal;
936         int extendSize = 31;
937         while(extendSize >= 0 && ((extend << (31 - extendSize)) & 0x80000000) == 0)
938                 extendSize--;
939     Expression::Ptr ext = makeOptionExpression(extendSize, sizeVal);
940         */
941
942     int immLen = 2;
943     int immVal = 0; //for amount
944
945     int S = field<12,12>(insn);
946     int size = field<30,31>(insn);
947
948     if( size == 2 ){ //32bit
949         immVal = S==0?0:(S==1?2:-1);
950         if( immVal==-1 ) assert(0);
951     }else if( size == 3 ){ //64bit
952         immVal = S==0?0:(S==1?3:-1);
953         if( immVal==-1) assert(0);
954     }
955     Expression::Ptr ext = makeOptionExpression(immLen, immVal);
956
957     return ext; /*extended ptr*/
958 }
959
960 /**********************
961 // ld/st reg memReg AST:
962 //    memRef
963 //      |
964 //     ADD
965 //    /    \
966 //  [Rn]   EXT
967 //        /   \
968 //      [Rm] [amount]
969 **********************/
970 Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg(){
971
972     Expression::Ptr ext = makeMemRefReg_ext();
973     Expression::Ptr xn = makeRnExpr();
974     Expression::Ptr add = makeAddExpression(xn, ext, u64);
975
976     Result_Type rt;
977     getMemRefIndex_RT(rt);
978     return makeDereferenceExpression(add,rt);
979 }
980
981 void InstructionDecoder_aarch64::LIndex()
982 {
983     // never be called
984     if( IS_INSN_LD_LITERAL(insn)){
985         insn_in_progress->appendOperand(makeMemRefIndexLiteral(), true, false);
986         return;
987     }
988
989     // ******************
990     // ld register offset
991     // ******************
992     else if( IS_INSN_LDST_REG(insn)){
993         insn_in_progress->appendOperand(makeMemRefReg(), true, false);
994         return;
995     }
996
997     // ******************
998     // ld unsigned imm
999     // ******************
1000     else if( IS_INSN_LDST_UIMM(insn)){
1001         insn_in_progress->appendOperand(makeMemRefIndexUImm(), true, false);
1002         return;
1003     }
1004
1005     // ******************
1006     // ld pre and post, unscaled and unprivlidged
1007     // ******************
1008     else if( IS_INSN_LDST_PRE(insn)
1009         || IS_INSN_LDST_UNPRIV(insn)
1010         || IS_INSN_LDST_UNSCALED(insn) ){
1011         insn_in_progress->appendOperand(makeMemRefIndexPre(), true, false);
1012         return;
1013     }
1014
1015     else if( IS_INSN_LDST_POST(insn) ){
1016         insn_in_progress->appendOperand(makeMemRefIndexPost(), true, false);
1017         return;
1018     }
1019
1020     // ****************************
1021     // ld PAIR pre, post, offset
1022     // ****************************
1023     else if( IS_INSN_LDST_PAIR_PRE(insn)
1024         || IS_INSN_LDST_PAIR_NOALLOC(insn) ){
1025         insn_in_progress->appendOperand(makeMemRefPairPre(), true, false);
1026         return;
1027     }
1028
1029     else if( IS_INSN_LDST_PAIR_POST(insn)
1030         || IS_INSN_LDST_PAIR_OFFSET(insn) ){
1031         insn_in_progress->appendOperand(makeMemRefPairPost(), true, false);
1032         return;
1033     }
1034
1035
1036     // ****************************
1037     // ld exclusive instructions
1038     // ****************************
1039     else if( IS_INSN_LDST_EX(insn) ){
1040         if( !IS_INSN_LDST_EX_PAIR(insn) ){ // Rt2 field == 31, non-pair op
1041             insn_in_progress->appendOperand( makeMemRefEx(), true, false);
1042         } else { // pair
1043             insn_in_progress->appendOperand( makeMemRefExPair(), true, false);
1044         }
1045         return;
1046     }
1047
1048     else if( IS_INSN_LDST_SIMD_MULT(insn) ){
1049
1050     }
1051     else if( IS_INSN_LDST_SIMD_MULT_POST(insn) ){
1052         assert(0);
1053     }
1054     else if( IS_INSN_LDST_SIMD_SING(insn) ){
1055         assert(0);
1056     }
1057     else if( IS_INSN_LDST_SIMD_SING_POST(insn) ){
1058         assert(0);
1059     }
1060
1061     assert(0); //un-handled case
1062
1063 }
1064
1065 void InstructionDecoder_aarch64::STIndex()
1066 {
1067     if( IS_INSN_LD_LITERAL(insn))
1068         assert(0); // only load literal, no store literal
1069
1070     // ******************
1071     // ld/st register offset
1072     // ******************
1073     else if( IS_INSN_LDST_REG(insn)){
1074         insn_in_progress->appendOperand(makeMemRefReg(), false, true);
1075         return;
1076     }
1077
1078     else if( IS_INSN_LDST_UIMM(insn)){
1079         insn_in_progress->appendOperand(makeMemRefIndexUImm(), false, true);
1080         return;
1081     }
1082
1083     // ******************
1084     // ld/st pre and post, unscaled and unprivilidged
1085     // ******************
1086     else if( IS_INSN_LDST_PRE(insn)
1087         || IS_INSN_LDST_UNPRIV(insn)
1088         || IS_INSN_LDST_UNSCALED(insn) ){
1089         insn_in_progress->appendOperand(makeMemRefIndexPre(), false, true);
1090         return;
1091     }
1092
1093     else if( IS_INSN_LDST_POST(insn) ){
1094         insn_in_progress->appendOperand(makeMemRefIndexPost(), false, true);
1095         return;
1096     }
1097
1098     // ****************************
1099     // ld/st PAIR pre, post, offset
1100     // ****************************
1101     else if( IS_INSN_LDST_PAIR_PRE(insn)
1102         || IS_INSN_LDST_PAIR_NOALLOC(insn) ){
1103         insn_in_progress->appendOperand(makeMemRefPairPre(), false, true);
1104         return;
1105     }
1106
1107     else if( IS_INSN_LDST_PAIR_POST(insn)
1108         || IS_INSN_LDST_PAIR_OFFSET(insn)) {
1109         insn_in_progress->appendOperand(makeMemRefPairPost(), false, true);
1110         return;
1111     }
1112
1113
1114     // ****************************
1115     // ld/st exclusive instructions
1116     // ****************************
1117     else if( IS_INSN_LDST_EX(insn) ){
1118         if( !IS_INSN_LDST_EX_PAIR(insn) ){ // Rt2 field == 31, non-pair op
1119             insn_in_progress->appendOperand( makeMemRefEx(), false, true);
1120         } else { // pair
1121             insn_in_progress->appendOperand( makeMemRefExPair(), false, true);
1122         }
1123         return;
1124     }
1125
1126     assert(0); //un-handled case
1127
1128 }
1129
1130 // This function is for non-writeback
1131 void InstructionDecoder_aarch64::OPRRn()
1132 {
1133         if(IS_INSN_B_UNCOND_REG(insn))                                                                          //unconditional branch (register)
1134         {
1135                 int branchType = field<21, 22>(insn);
1136
1137                 insn_in_progress->appendOperand(makePCExpr(), false, true);
1138                 insn_in_progress->addSuccessor(makeRnExpr(), field<21, 21>(insn) == 1, true, false, false);
1139
1140                 if(branchType == 0x1)
1141                 {
1142                         insn_in_progress->addSuccessor(makeFallThroughExpr(), false, false, false, true);
1143                 }
1144         }
1145         else
1146                 insn_in_progress->appendOperand(makeRnExpr(), true, false);
1147 }
1148
1149 void InstructionDecoder_aarch64::OPRRnL()
1150 {
1151     LIndex();
1152 }
1153
1154 void InstructionDecoder_aarch64::OPRRnS()
1155 {
1156     STIndex();
1157 }
1158
1159 void InstructionDecoder_aarch64::OPRRnU()
1160 {
1161     assert(0);
1162     /* this functions is useless
1163         insn_in_progress->appendOperand(makeRnExpr(), true, true);
1164     */
1165 }
1166
1167 void InstructionDecoder_aarch64::OPRRnLU()
1168 {
1169     if( IS_INSN_LDST_PRE(insn) ){
1170         LIndex();
1171         return;
1172     }
1173
1174     if( IS_INSN_LDST_POST(insn) ){
1175         LIndex();
1176         return;
1177     }
1178
1179     if( IS_INSN_LDST_PAIR_PRE(insn) ){
1180         LIndex();
1181         return;
1182     }
1183
1184     if( IS_INSN_LDST_PAIR_POST(insn) ){
1185         LIndex();
1186         return;
1187     }
1188
1189 }
1190
1191 void InstructionDecoder_aarch64::OPRRnSU()
1192 {
1193     if( IS_INSN_LDST_PRE(insn) ){
1194         STIndex();
1195         return;
1196     }
1197
1198     if( IS_INSN_LDST_POST(insn) ){
1199         STIndex();
1200         return;
1201     }
1202
1203     if( IS_INSN_LDST_PAIR_PRE(insn) ){
1204         STIndex();
1205         return;
1206     }
1207
1208     if( IS_INSN_LDST_PAIR_POST(insn) ){
1209         STIndex();
1210         return;
1211     }
1212 }
1213
1214 Expression::Ptr InstructionDecoder_aarch64::makeRmExpr()
1215 {
1216     int encoding  = field<16, 20>(insn);
1217         MachRegister reg;
1218
1219     if( isSIMDInsn ){
1220         reg = aarch64::q0;
1221         reg = makeAarch64RegID(reg, encoding);
1222     } else
1223         if(isFPInsn)
1224         {
1225                 reg = isSinglePrec()?aarch64::s0:aarch64::d0;
1226                 reg = makeAarch64RegID(reg, encoding);
1227         }
1228         else
1229         {
1230                 reg = is64Bit?((encoding == 31)?aarch64::zr:aarch64::x0):((encoding == 31)?aarch64::wzr:aarch64::w0);
1231                 if(encoding != 31)
1232                         reg = makeAarch64RegID(reg, encoding);
1233         }
1234
1235         return makeRegisterExpression(reg);
1236 }
1237
1238 void InstructionDecoder_aarch64::OPRRm()
1239 {
1240         if(IS_INSN_LDST_REG(insn) ||
1241            IS_INSN_ADDSUB_EXT(insn) ||
1242            IS_INSN_ADDSUB_SHIFT(insn) ||
1243            IS_INSN_LOGICAL_SHIFT(insn))
1244                 return;
1245
1246         if(IS_INSN_FP_COMPARE(insn) && field<3, 3>(insn) == 1)
1247                 insn_in_progress->appendOperand(Immediate::makeImmediate(Result(isSinglePrec()?sp_float:dp_float, 0.0)), true, false);
1248         else
1249                 insn_in_progress->appendOperand(makeRmExpr(), true, false);
1250 }
1251
1252 void InstructionDecoder_aarch64::OPRsf()
1253 {
1254         if(field<31, 31>(insn) == 0)
1255                 is64Bit = false;
1256 }
1257
1258 template<unsigned int endBit, unsigned int startBit>
1259 void InstructionDecoder_aarch64::OPRoption()
1260 {
1261         hasOption = true;
1262         optionField = field<startBit, endBit>(insn);
1263 }
1264
1265 void InstructionDecoder_aarch64::OPRshift()
1266 {
1267         hasShift = true;
1268         shiftField = field<22, 23>(insn);
1269 }
1270
1271 void InstructionDecoder_aarch64::OPRhw()
1272 {
1273         hasHw = true;
1274         hwField = field<21, 22>(insn);
1275 }
1276
1277 template<unsigned int endBit, unsigned int startBit>
1278 void InstructionDecoder_aarch64::OPRN()
1279 {
1280         hasN = true;
1281         nField = field<startBit, endBit>(insn);
1282         nLen = endBit - startBit + 1;
1283 }
1284
1285 // the call of this function should be generated by decoder gen for ld/st class
1286 // except for ld/st{s, h, w} subclass
1287 void InstructionDecoder_aarch64::setRegWidth(){
1288     //is64Bit is by default set to TRUE
1289     unsigned int opc = 0x3 & field<22, 23>(insn);
1290     unsigned int opc0 = opc & 0x1;
1291     unsigned int opc1 = (opc & 0x2)>>1;
1292     unsigned int sz  = 0x3 & field<30, 31>(insn);
1293
1294     if(IS_INSN_LDST(insn)){
1295         if(   IS_INSN_LDST_UIMM(insn)   || IS_INSN_LDST_UNSCALED(insn)
1296                 || IS_INSN_LDST_UNPRIV(insn) || IS_INSN_LDST_POST(insn)
1297                 || IS_INSN_LDST_PRE(insn)    || IS_INSN_LDST_REG(insn)){
1298                 if(opc1 == 0){
1299                     if(field<30, 31>(insn) != 3)
1300                         is64Bit = false;
1301                     return;
1302                 }else{
1303                     if( sz == 3){
1304                         if( opc0 == 1) assert(!"unallocated insn");
1305                     }
1306                     else{
1307                         if(sz == 2 && opc0 == 1) assert(!"unallocated insn");
1308                         if(opc0 == 1)
1309                             is64Bit = false;
1310                     }
1311                     return;
1312                 }
1313         }
1314         else if(IS_INSN_LDST_EX(insn)){
1315             switch(sz){
1316                 case 2:
1317                 case 0:
1318                 case 1:
1319                     is64Bit = false;
1320                     break;
1321                 case 3:
1322                 default:
1323                     return;
1324             }
1325         }
1326         else if(IS_INSN_LDST_PAIR(insn)){
1327             switch(sz){
1328                 case 0:
1329                     is64Bit = false;
1330                     break;
1331                 case 1:
1332                 case 2:
1333                 case 3:
1334                 default:
1335                     return;
1336             }
1337         }
1338         else if(IS_INSN_LD_LITERAL(insn)){
1339             switch(sz){
1340                 case 0:
1341                     is64Bit = false;
1342                 case 1:
1343                 case 2:
1344                 case 3:
1345                 default:
1346                     return;
1347             }
1348         }
1349         else{
1350             assert(!"not implemented for SIMD");
1351         }
1352     }else{
1353         assert(0);
1354     }
1355     return;
1356 }
1357
1358 Expression::Ptr InstructionDecoder_aarch64::makeRtExpr()
1359 {
1360         int encoding  = field<0, 4>(insn);
1361         MachRegister reg;
1362
1363         if(isFPInsn)
1364         {
1365                 reg = makeAarch64RegID(isSinglePrec()?aarch64::s0:aarch64::d0, encoding);
1366         }
1367         else
1368         {
1369                 reg = is64Bit?((encoding == 31)?aarch64::zr:aarch64::x0):((encoding == 31)?aarch64::wzr:aarch64::w0);
1370                 if(encoding != 31)
1371                         reg = makeAarch64RegID(reg, encoding);
1372         }
1373
1374         return makeRegisterExpression(reg);
1375 }
1376
1377 void InstructionDecoder_aarch64::get_rptselem(unsigned int &rpt, unsigned int &selem){
1378     unsigned opcode = field<12, 15>(insn);
1379     switch(opcode){
1380         case 0x0:
1381             rpt = 1; selem = 4;
1382             break;
1383         case 0x2:
1384             rpt = 4; selem = 1;
1385             break;
1386         case 0x4:
1387             rpt = 1; selem = 3;
1388             break;
1389         case 0x6:
1390             rpt = 3; selem = 1;
1391             break;
1392         case 0x7:
1393             rpt = 1; selem = 1;
1394             break;
1395         case 0x8:
1396             rpt = 1; selem = 2;
1397             break;
1398         case 0xa:
1399             rpt = 2; selem = 1;
1400             break;
1401         default:
1402             assert(!"unallocated encoding");
1403             return;
1404     }
1405     assert(rpt!=0 && selem!=0);
1406     return;
1407 }
1408
1409 void InstructionDecoder_aarch64::OPRRt()
1410 {
1411         int encoding = field<0, 4>(insn);
1412         if(IS_INSN_BRANCHING(insn))
1413         {
1414                 if(encoding == 31)
1415                         insn_in_progress->appendOperand(makeRegisterExpression(is64Bit?aarch64::zr:aarch64::wzr), true, false);
1416                 else
1417                         insn_in_progress->appendOperand(makeRegisterExpression(makeAarch64RegID(is64Bit?aarch64::x0:aarch64::w0, encoding)), true, false);
1418         }
1419 }
1420
1421 void InstructionDecoder_aarch64::OPRRtL()
1422 {
1423         int encoding = field<0, 4>(insn);
1424     if( IS_INSN_LDST_SIMD_MULT(insn) ){
1425         unsigned int rpt, selem;
1426         get_rptselem(rpt, selem);
1427         for(unsigned int it_rpt = 0; it_rpt < rpt; it_rpt++){
1428                         insn_in_progress->appendOperand(makeRegisterExpression(makeAarch64RegID(aarch64::q0, encoding + it_rpt)), false, true);
1429         }
1430     }
1431     else
1432             insn_in_progress->appendOperand(makeRtExpr(), false, true);
1433 }
1434
1435 void InstructionDecoder_aarch64::OPRRtS()
1436 {
1437         int encoding = field<0, 4>(insn);
1438     if( IS_INSN_LDST_SIMD_MULT(insn) ){
1439         unsigned int rpt, selem;
1440         get_rptselem(rpt, selem);
1441         for(unsigned int it_rpt = 0; it_rpt < rpt; it_rpt++){
1442                         insn_in_progress->appendOperand(makeRegisterExpression(makeAarch64RegID(aarch64::q0, encoding + it_rpt)), true, false);
1443         }
1444     }
1445     else
1446             insn_in_progress->appendOperand(makeRtExpr(), true, false);
1447 }
1448
1449 Expression::Ptr InstructionDecoder_aarch64::makeRt2Expr()
1450 {
1451         MachRegister baseReg = isFPInsn?
1452         (isSinglePrec()?aarch64::s0:aarch64::d0):
1453         (is64Bit?aarch64::x0 : aarch64::w0);
1454
1455         return makeRegisterExpression(makeAarch64RegID(baseReg, field<10, 14>(insn)));
1456 }
1457
1458 void InstructionDecoder_aarch64::OPRRt2()
1459 {
1460     assert(0);
1461 }
1462
1463 void InstructionDecoder_aarch64::OPRRt2L()
1464 {
1465         insn_in_progress->appendOperand(makeRt2Expr(), false, true);
1466 }
1467
1468 void InstructionDecoder_aarch64::OPRRt2S()
1469 {
1470         insn_in_progress->appendOperand(makeRt2Expr(), true, false);
1471 }
1472
1473 template<unsigned int endBit, unsigned int startBit>
1474 void InstructionDecoder_aarch64::OPRcond()
1475 {
1476         unsigned char condVal = static_cast<unsigned char>(field<startBit, endBit>(insn));
1477         if(IS_INSN_B_COND(insn))
1478         {
1479                 insn_in_progress->getOperation().mnemonic += ".";
1480                 insn_in_progress->getOperation().mnemonic += condStringMap[condVal];
1481         }
1482         else
1483         {
1484                 Expression::Ptr cond = Immediate::makeImmediate(Result(u8, condVal));
1485                 insn_in_progress->appendOperand(cond, true, false);
1486                 oprRotateAmt++;
1487         }
1488
1489         isPstateRead = true;
1490 }
1491
1492 void InstructionDecoder_aarch64::OPRnzcv()
1493 {
1494         unsigned int nzcvVal = field<0, 3>(insn)<<28;
1495         Expression::Ptr nzcv = Immediate::makeImmediate(Result(u32, nzcvVal));
1496         insn_in_progress->appendOperand(nzcv, true, false);
1497
1498         isPstateWritten = true;
1499         oprRotateAmt++;
1500 }
1501
1502 void InstructionDecoder_aarch64::OPRop1()
1503 {
1504         op1Field = field<16, 18>(insn);
1505 }
1506
1507 void InstructionDecoder_aarch64::OPRop2()
1508 {
1509         op2Field = field<5, 7>(insn);
1510 }
1511
1512 void InstructionDecoder_aarch64::OPRCRm()
1513 {
1514         crmField = field<8 ,11>(insn);
1515 }
1516
1517 void InstructionDecoder_aarch64::OPRCRn()
1518 {
1519 }
1520
1521 template<unsigned int endBit, unsigned int startBit>
1522 void InstructionDecoder_aarch64::OPRS()
1523 {
1524         sField = field<startBit, endBit>(insn);
1525 }
1526
1527 void InstructionDecoder_aarch64::OPRscale()
1528 {
1529         int scaleVal = 64 - field<10, 15>(insn);
1530
1531         Expression::Ptr scale = Immediate::makeImmediate(Result(u32, unsign_extend32(6, scaleVal)));
1532         insn_in_progress->appendOperand(scale, true, false);
1533 }
1534
1535 Expression::Ptr InstructionDecoder_aarch64::makeRaExpr()
1536 {
1537         int encoding  = field<10, 14>(insn);
1538         MachRegister reg;
1539
1540         if(isFPInsn)
1541         {
1542                 reg = makeAarch64RegID(isSinglePrec()?aarch64::s0:aarch64::d0, encoding);
1543         }
1544         else
1545         {
1546                 reg = is64Bit?((encoding == 31)?aarch64::sp:aarch64::x0):((encoding == 31)?aarch64::wsp:aarch64::w0);
1547                 if(encoding != 31)
1548                         reg = makeAarch64RegID(reg, encoding);
1549         }
1550
1551         return makeRegisterExpression(reg);
1552
1553 }
1554
1555 void InstructionDecoder_aarch64::OPRRa()
1556 {
1557         insn_in_progress->appendOperand(makeRaExpr(), true, false);
1558
1559         oprRotateAmt++;
1560 }
1561
1562 void InstructionDecoder_aarch64::OPRo0()
1563 {
1564
1565 }
1566
1567 void InstructionDecoder_aarch64::OPRb5()
1568 {
1569         OPRsf();
1570         hasb5 = true;
1571 }
1572
1573 void InstructionDecoder_aarch64::OPRb40()
1574 {
1575
1576 }
1577
1578 Expression::Ptr InstructionDecoder_aarch64::makeb40Expr()
1579 {
1580         int b40Val = field<19, 23>(insn);
1581         int bitpos = ((is64Bit?1:0)<<5) | b40Val;
1582
1583         return Immediate::makeImmediate(Result(u32, unsign_extend32(6, bitpos)));
1584 }
1585
1586 template<unsigned int endBit, unsigned int startBit>
1587 void InstructionDecoder_aarch64::OPRsz()
1588 {
1589     _szField = field<startBit, endBit>(insn);
1590 }
1591
1592 bool InstructionDecoder_aarch64::isSinglePrec() {
1593     if( isFPInsn && !isSIMDInsn ){
1594         if(_typeField == -1){
1595             //TODO if the type field is not set, do sth else
1596             OPRtype<23, 22>();
1597         }
1598         return _typeField==0?true:false;
1599     }else if( isSIMDInsn ){
1600         assert(0); //not implemeted yet
1601     }
1602     return false;
1603 }
1604
1605 Expression::Ptr InstructionDecoder_aarch64::makeRsExpr()
1606 {
1607         MachRegister baseReg = isFPInsn?
1608         (isSinglePrec()?aarch64::s0:aarch64::d0):
1609         (is64Bit?aarch64::x0:aarch64::w0);
1610
1611     if(IS_INSN_LDST(insn)){
1612         baseReg = aarch64::w0;
1613     }
1614         return makeRegisterExpression(makeAarch64RegID(baseReg, field<16, 20>(insn)));
1615 }
1616
1617 void InstructionDecoder_aarch64::OPRRs()
1618 {
1619         insn_in_progress->appendOperand(makeRsExpr(), false, true);
1620 }
1621
1622 void InstructionDecoder_aarch64::makeBranchTarget(bool branchIsCall, bool bIsConditional, int immVal, int immLen)
1623 {
1624         Expression::Ptr lhs = makePCExpr();
1625
1626         int offset = sign_extend64(immLen + 2, immVal*4);
1627         Expression::Ptr rhs = Immediate::makeImmediate(Result(s64, offset));
1628
1629         insn_in_progress->addSuccessor(makeAddExpression(lhs, rhs, s64), branchIsCall, false, bIsConditional, false);
1630         if(branchIsCall)
1631         {
1632                 insn_in_progress->addSuccessor(makeFallThroughExpr(), false, false, false, true);
1633         }
1634
1635 }
1636
1637 Expression::Ptr InstructionDecoder_aarch64::makeFallThroughExpr()
1638 {
1639         return makeAddExpression(makePCExpr(), Immediate::makeImmediate(Result(u64, unsign_extend64(3, 4))), u64);
1640 }
1641
1642 template<typename T, Result_Type rT>
1643 Expression::Ptr InstructionDecoder_aarch64::fpExpand(int val)
1644 {
1645         int N, E, F;
1646         T frac, expandedImm, sign, exp;
1647
1648         N = (rT == s32)?32:64;
1649         E = (N == 32)?8:11;
1650         F = N - E - 1;
1651
1652         sign = (val & 0x80) >> 7;
1653
1654         int val6 = ((~val) & 0x40) >> 6, val6mask = (1 << (E - 3)) - 1;
1655         exp = (val6 << (E - 1)) | ((val6?val6mask:0) << 2) | ((val & 0x30) >> 4);
1656
1657         frac = (val & 0xF) << (F - 4);
1658
1659         expandedImm = (sign << (E + F)) | (exp << F) | frac;
1660
1661         return Immediate::makeImmediate(Result(rT, expandedImm));
1662 }
1663
1664 template<unsigned int endBit, unsigned int startBit>
1665 void InstructionDecoder_aarch64::OPRimm()
1666 {
1667         int immVal = field<startBit, endBit>(insn);
1668         unsigned int immLen = endBit - startBit + 1;
1669
1670         if(IS_INSN_LDST(insn)){
1671         if(IS_INSN_LD_LITERAL(insn) ){
1672                         Expression::Ptr literal = makeMemRefIndexLiteral();
1673                         insn_in_progress->appendOperand(literal, true, false);
1674         }
1675         else if(IS_INSN_LDST_POST(insn)){
1676                         Expression::Ptr offset = makeMemRefIndex_offset9();
1677                         insn_in_progress->appendOperand(offset, true, false);
1678         }
1679         else if(IS_INSN_LDST_PAIR_POST(insn)
1680                 || IS_INSN_LDST_PAIR_OFFSET(insn) ){
1681                         Expression::Ptr offset = makeMemRefPair_offset7();
1682                         insn_in_progress->appendOperand(offset, true, false);
1683         }
1684                 return;
1685     }
1686
1687         if(hasHw)
1688         {
1689                 processHwFieldInsn(immLen, immVal);
1690         }
1691         else if(hasN)           //logical (immediate), bitfield, extract
1692         {
1693                 if(IS_FIELD_IMMR(startBit, endBit))
1694                 {
1695                         immr = immVal;
1696                         immrLen = immLen;
1697                 }
1698                 else if(IS_FIELD_IMMS(startBit, endBit))
1699                 {
1700                         Expression::Ptr imm;
1701
1702                         if(IS_INSN_LOGICAL_IMM(insn))
1703                         {
1704                                 immVal |= (immr << immLen);
1705                                 immVal |= (nField << (immLen + immrLen));
1706
1707                                 immLen += nLen + immrLen;
1708
1709                                 Result_Type rT = is64Bit?u64:u32;
1710                                 imm = Immediate::makeImmediate(Result(rT, rT==u32?unsign_extend32(immLen, immVal):unsign_extend64(immLen, immVal)));
1711                         }
1712                         else
1713                         {
1714                                 imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));
1715                                 oprRotateAmt++;
1716                         }
1717
1718                         insn_in_progress->appendOperand(imm, true, false);
1719                         if(IS_INSN_BITFIELD(insn))
1720                         {
1721                                 imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immrLen, immr)));
1722                                 insn_in_progress->appendOperand(imm, true, false);
1723                                 oprRotateAmt--;
1724                         }
1725                 }
1726                 else
1727                     isValid = false;
1728         }
1729         else if(hasShift)
1730         {
1731                 if(IS_INSN_ADDSUB_SHIFT(insn) || IS_INSN_LOGICAL_SHIFT(insn))   //add-sub shifted | logical shifted
1732                 {
1733                         processShiftFieldShiftedInsn(immLen, immVal);
1734                 }
1735                 else if(IS_INSN_ADDSUB_IMM(insn))               //add-sub (immediate)
1736                 {
1737                         processShiftFieldImmInsn(immLen, immVal);
1738                 }
1739                 else
1740                         isValid = false;
1741         }
1742         else if(hasOption)
1743         {
1744                 if(IS_INSN_ADDSUB_EXT(insn))                                                                            //add-sub extended
1745                 {
1746                     Expression::Ptr expr = makeOptionExpression(immLen, immVal);
1747
1748                     insn_in_progress->appendOperand(expr, true, false);
1749                 }
1750                 else
1751                 {
1752                         isValid = false;
1753                 }
1754         }
1755         else if(IS_INSN_BRANCHING(insn) && !IS_INSN_B_UNCOND_REG(insn))
1756         {               //unconditional branch (immediate), test and branch, compare and branch, conditional branch
1757                 bool bIsConditional = false;
1758                 if(!(IS_INSN_B_UNCOND(insn)))
1759                         bIsConditional = true;
1760
1761                 bool branchIsCall = bIsConditional?false:(field<31, 31>(insn) == 1);
1762
1763                 insn_in_progress->appendOperand(makePCExpr(), false, true);
1764                 makeBranchTarget(branchIsCall, bIsConditional, immVal, immLen);
1765
1766                 if(hasb5)
1767                         insn_in_progress->appendOperand(makeb40Expr(), true, false);
1768
1769                 if(bIsConditional)
1770                         insn_in_progress->addSuccessor(makeFallThroughExpr(), false, false, true, true);
1771         }
1772         else if(IS_INSN_PCREL_ADDR(insn))                                                                       //pc-relative addressing
1773         {
1774                 if(IS_FIELD_IMMLO(startBit, endBit))
1775                 {
1776                         immlo = immVal;
1777                         immloLen = endBit - startBit + 1;
1778                 }
1779                 else if(IS_FIELD_IMMHI(startBit, endBit))
1780                 {
1781                         int page = field<31, 31>(insn);
1782                         int offset = (immVal<<immloLen) | immlo;
1783
1784                         insn_in_progress->appendOperand(makePCExpr(), true, false);
1785                         Expression::Ptr imm = Immediate::makeImmediate(Result(s64, sign_extend64(immloLen + immLen + page*12, offset<<(page*12))));
1786
1787                         insn_in_progress->appendOperand(imm, true, false);
1788                 }
1789                 else
1790                         isValid = false;
1791         }
1792         else if(isFPInsn)
1793         {
1794                 if(isSinglePrec())
1795                         insn_in_progress->appendOperand(fpExpand<int32_t, s32>(immVal), true, false);
1796                 else
1797                         insn_in_progress->appendOperand(fpExpand<int64_t, s64>(immVal), true, false);
1798         }
1799         else if(IS_INSN_EXCEPTION(insn))
1800         {
1801                 Expression::Ptr imm = Immediate::makeImmediate(Result(u16, immVal));
1802                 insn_in_progress->appendOperand(imm, true, false);
1803                 isPstateRead = true;
1804         }
1805         else                                                            //conditional compare (immediate)
1806         {
1807                 Result_Type rT = is64Bit?u64:u32;
1808
1809                 Expression::Ptr imm = Immediate::makeImmediate(Result(rT, rT==u32?unsign_extend32(immLen, immVal):unsign_extend64(immLen, immVal)));
1810                 insn_in_progress->appendOperand(imm, true, false);
1811         }
1812 }
1813
1814         void InstructionDecoder_aarch64::reorderOperands()
1815         {
1816             if(oprRotateAmt)
1817             {
1818                         std::vector<Operand> curOperands;
1819                         insn_in_progress->getOperands(curOperands);
1820
1821                         if(curOperands.empty())
1822                                 assert(!"empty operand list found while re-ordering operands");
1823
1824                         std::swap(curOperands[1], curOperands[3]);
1825
1826                         while(oprRotateAmt--)
1827                                 std::rotate(curOperands.begin(), curOperands.begin()+1, curOperands.begin()+3);
1828
1829                         insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
1830             }
1831         else if( IS_INSN_LDST_POST(insn) || IS_INSN_LDST_PAIR_POST(insn) ){
1832                 std::vector<Operand> curOperands;
1833                 insn_in_progress->getOperands(curOperands);
1834             std::iter_swap( curOperands.begin(), curOperands.end()-1 );
1835                     insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
1836         }
1837         else if( IS_INSN_LDST_PAIR(insn) ){
1838                     std::vector<Operand> curOperands;
1839                     insn_in_progress->getOperands(curOperands);
1840             assert(curOperands.size() == 4 || curOperands.size() == 3);
1841             if(curOperands.size() == 3){
1842                 curOperands.insert(curOperands.begin(), curOperands.back());
1843                 curOperands.pop_back();
1844             }else if(curOperands.size() == 4){
1845                 std::iter_swap( curOperands.begin(), curOperands.end()-1 );
1846             }
1847                     insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
1848         }
1849         else if( IS_INSN_LDST_EX_PAIR(insn) ){
1850                     std::vector<Operand> curOperands;
1851                     insn_in_progress->getOperands(curOperands);
1852             if(curOperands.size() == 3) {
1853                 curOperands.insert(curOperands.begin(), curOperands.back());
1854                 curOperands.pop_back();
1855             }
1856             else if( curOperands.size() == 4) {
1857                 curOperands.insert(curOperands.begin()+1, curOperands.back());
1858                 curOperands.pop_back();
1859             }
1860                     insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
1861         }
1862         else if( IS_INSN_ST_EX(insn) ){
1863                     std::vector<Operand> curOperands;
1864                     insn_in_progress->getOperands(curOperands);
1865             if(curOperands.size() == 3){
1866                 curOperands.insert(curOperands.begin()+1, curOperands.back());
1867                 curOperands.pop_back();
1868                         insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
1869             }
1870             else
1871                         insn_in_progress->m_Operands.reverse();
1872         }
1873             else
1874                     insn_in_progress->m_Operands.reverse();
1875         }
1876
1877
1878 using namespace boost::assign;
1879
1880 #include "aarch64_opcode_tables.C"
1881
1882         void InstructionDecoder_aarch64::doDelayedDecode(const Instruction *insn_to_complete)
1883     {
1884                 int insn_table_index = findInsnTableIndex(0);
1885                 aarch64_insn_entry *insn_table_entry = &aarch64_insn_entry::main_insn_table[insn_table_index];
1886
1887                 insn = insn_to_complete->m_RawInsn.small_insn;
1888                 insn_in_progress = const_cast<Instruction*>(insn_to_complete);
1889
1890         for(operandSpec::const_iterator fn = insn_table_entry->operands.begin(); fn != insn_table_entry->operands.end(); fn++)
1891         {
1892                         std::mem_fun(*fn)(this);
1893                 }
1894
1895                 reorderOperands();
1896
1897                 if(IS_INSN_SYSTEM(insn))
1898                 {
1899                         processSystemInsn();
1900                 }
1901
1902                 if(isPstateWritten || isPstateRead)
1903                         insn_in_progress->appendOperand(makePstateExpr(), isPstateRead, isPstateWritten);
1904
1905                 if(!isValid)
1906                 {
1907                         insn_in_progress->getOperation().mnemonic = INVALID_ENTRY.mnemonic;
1908                         insn_in_progress->getOperation().operationID = INVALID_ENTRY.op;
1909                         insn_in_progress->m_Operands.clear();
1910                         insn_in_progress->m_Successors.clear();
1911                 }
1912     }
1913         int InstructionDecoder_aarch64::findInsnTableIndex(unsigned int decoder_table_index)
1914         {
1915                 aarch64_mask_entry *cur_entry = &aarch64_mask_entry::main_decoder_table[decoder_table_index];
1916                 unsigned int cur_mask = cur_entry->mask;
1917
1918                 if(cur_mask == 0)
1919                 {
1920                         if(cur_entry->insnTableIndices.size() == 1)
1921                                 return cur_entry->insnTableIndices[0];
1922
1923                         int insn_table_index = -1;
1924                         for(std::vector<int>::iterator itr = cur_entry->insnTableIndices.begin(); itr != cur_entry->insnTableIndices.end(); itr++)
1925                         {
1926                                 aarch64_insn_entry *nextEntry = &aarch64_insn_entry::main_insn_table[*itr];
1927                                 if((insn & nextEntry->_maskBits) == nextEntry->_encodingBits)
1928                                 {
1929                                         insn_table_index = *itr;
1930                                         break;
1931                                 }
1932                         }
1933
1934                         if(insn_table_index == -1)
1935                                 assert(!"no instruction table entry found for current instruction");
1936                         else
1937                                 return insn_table_index;
1938                 }
1939
1940                 unsigned int insn_iter_index = 0, map_key_index = 0, branch_map_key = 0;
1941                 branchMap cur_branches = cur_entry->nodeBranches;
1942
1943                 while(insn_iter_index < AARCH64_INSN_LENGTH)
1944                 {
1945                         if(((cur_mask>>insn_iter_index) & 1) == 1)
1946                         {
1947                                 branch_map_key = branch_map_key | (((insn>>insn_iter_index) & 1)<<map_key_index);
1948                                 map_key_index++;
1949                         }
1950                         insn_iter_index++;
1951                 }
1952
1953                 if(cur_branches.count(branch_map_key) <= 0)
1954                         branch_map_key = 0;
1955
1956                 return findInsnTableIndex(cur_branches[branch_map_key]);
1957         }
1958
1959         void InstructionDecoder_aarch64::setFlags()
1960         {
1961                 isPstateWritten = true;
1962         }
1963
1964     void InstructionDecoder_aarch64::mainDecode()
1965     {
1966                 int insn_table_index = findInsnTableIndex(0);
1967                 aarch64_insn_entry *insn_table_entry = &aarch64_insn_entry::main_insn_table[insn_table_index];
1968
1969         insn_in_progress = makeInstruction(insn_table_entry->op, insn_table_entry->mnemonic, 4, reinterpret_cast<unsigned char*>(&insn));
1970         //insn_printf("ARM: %s\n", insn_table_entry->mnemonic);
1971
1972         if(IS_INSN_BRANCHING(insn))
1973         {
1974             // decode control-flow operands immediately; we're all but guaranteed to need them
1975             doDelayedDecode(insn_in_progress);
1976         }
1977
1978         //insn_in_progress->arch_decoded_from = m_Arch;
1979         insn_in_progress->arch_decoded_from = Arch_aarch64;
1980         return;
1981     }
1982   };
1983 };
1984
1985
1986