Changed order of start and end bit names in oeprand templates and added updated ARM64...
[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
45     struct aarch64_insn_entry
46     {
47         aarch64_insn_entry(entryID o, const char* m, operandSpec ops):
48         op(o), mnemonic(m), operands(ops)
49         {
50         }
51
52         aarch64_insn_entry():
53         op(aarch64_op_INVALID), mnemonic("INVALID")
54         {
55             // TODO: why 5?
56             // TODO: Is this needed here?
57             operands.reserve(5);
58         }
59
60         aarch64_insn_entry(const aarch64_insn_entry& o) :
61         op(o.op), mnemonic(o.mnemonic), operands(o.operands)
62         {
63         }
64
65         const aarch64_insn_entry& operator=(const aarch64_insn_entry& rhs)
66         {
67             operands.reserve(rhs.operands.size());
68             op = rhs.op;
69             mnemonic = rhs.mnemonic;
70             operands = rhs.operands;
71
72             return *this;
73         }
74
75         entryID op;
76         const char* mnemonic;
77         operandSpec operands;
78
79         static void buildInsnTable();
80         static bool built_insn_table;
81
82         static aarch64_insn_table main_insn_table;
83     };
84
85     struct aarch64_mask_entry
86     {
87                 aarch64_mask_entry(unsigned int m, branchMap bm, int tabIndex):
88                 mask(m), nodeBranches(bm), insnTableIndex(tabIndex)
89                 {
90                 }
91
92                 aarch64_mask_entry():
93                 mask(0), nodeBranches(branchMap()), insnTableIndex(-1)
94                 {
95                 }
96
97                 aarch64_mask_entry(const aarch64_mask_entry& e):
98                 mask(e.mask), nodeBranches(e.nodeBranches), insnTableIndex(e.insnTableIndex)
99                 {
100                 }
101
102                 const aarch64_mask_entry& operator=(const aarch64_mask_entry& rhs)
103                 {
104                         mask = rhs.mask;
105                         nodeBranches = rhs.nodeBranches;
106                         insnTableIndex = rhs.insnTableIndex;
107
108                         return *this;
109                 }
110
111                 unsigned int mask;
112                 branchMap nodeBranches;
113                 int insnTableIndex;
114
115                 static void buildDecoderTable();
116                 static bool built_decoder_table;
117                 static aarch64_decoder_table main_decoder_table;
118         };
119
120     InstructionDecoder_aarch64::InstructionDecoder_aarch64(Architecture a)
121       : InstructionDecoderImpl(a), isPstateRead(false), isPstateWritten(false), isFPInsn(false),isSIMDInsn(false),
122             is64Bit(true), isValid(true), insn(0), insn_in_progress(NULL), isSystemInsn(false),
123         hasHw(false), hasShift(false), hasOption(false), hasN(false),
124         immr(0), immrLen(0), sField(0), nField(0), nLen(0),
125         immlo(0), immloLen(0), _szField(-1)
126     {
127         aarch64_insn_entry::buildInsnTable();
128         aarch64_mask_entry::buildDecoderTable();
129
130         invalid_insn = makeInstruction(aarch64_op_INVALID, "INVALID", 4, reinterpret_cast<unsigned char*>(&insn));
131     }
132
133     InstructionDecoder_aarch64::~InstructionDecoder_aarch64()
134     {
135     }
136
137     void InstructionDecoder_aarch64::decodeOpcode(InstructionDecoder::buffer& b)
138     {
139       b.start += 4;
140     }
141
142     using namespace std;
143     Instruction::Ptr InstructionDecoder_aarch64::decode(InstructionDecoder::buffer& b)
144     {
145         insn_printf("### decoding\n");
146
147         if(b.start > b.end)
148             return Instruction::Ptr();
149            
150                 isPstateRead = isPstateWritten = false;
151         isFPInsn = false;
152         isSIMDInsn = false;
153         isValid = true;
154         is64Bit = true;
155
156         hasHw = false;
157         hwField = 0;
158
159         hasShift = false;
160         shiftField = 0;
161
162         hasOption = false;
163         optionField = 0;
164
165         hasN = false;
166         sField = nField = nLen = 0;
167         immr = immrLen = 0;
168
169         isSystemInsn = false;
170         op0Field = op1Field = op2Field = crnField = crmField = 0;
171
172         immlo = immloLen = 0;
173
174         _szField = -1;
175
176         insn = b.start[0] << 24 | b.start[1] << 16 |
177         b.start[2] << 8 | b.start[3];
178         
179 #if defined(DEBUG_RAW_INSN)
180         cout.width(0);
181         cout << "0x";
182         cout.width(8);
183         cout.fill('0');
184         cout << hex << insn << "\t";
185 #endif
186
187                 mainDecode();
188         b.start += 4;
189
190         return make_shared(insn_in_progress);
191     }
192
193     /* replace this function with a more generic function, which is setRegWidth
194     void InstructionDecoder_aarch64::set32Mode()
195     {
196         // NOTE: is64Bit is set by default.
197                 is64Bit = false;
198     }
199     */
200
201     void InstructionDecoder_aarch64::setFPMode()
202     {
203         // NOTE: if it is fp, only isFP is set.
204                 isFPInsn = true;
205     }
206
207     //TODO: consistency issue
208     void InstructionDecoder_aarch64::setSIMDMode()
209     {
210         // NOTE: if it is SIMD insn, both isFP and isSIMD are set.
211                 isFPInsn = true;
212                 isSIMDInsn = true;
213     }
214
215         template<unsigned int endBit, unsigned int startBit>
216     void InstructionDecoder_aarch64::OPRtype(){
217         _typeField = field<startBit, endBit>(insn);
218     }
219
220     bool InstructionDecoder_aarch64::decodeOperands(const Instruction *)
221     {
222                 return false;
223     }
224
225         void InstructionDecoder_aarch64::processHwFieldInsn(int len, int val)
226         {
227                 Result_Type rT = is64Bit?u64:u32;
228
229                 unsigned int shiftAmount = hwField*16;
230
231                 Expression::Ptr lhs = Immediate::makeImmediate(Result(rT, rT==u32?unsign_extend32(len, val):unsign_extend64(len, val)));
232                 Expression::Ptr rhs = Immediate::makeImmediate(Result(u32, unsign_extend32(6, shiftAmount)));
233
234                 insn_in_progress->appendOperand(makeLeftShiftExpression(lhs, rhs, rT), true, false);
235         }
236
237         void InstructionDecoder_aarch64::processShiftFieldShiftedInsn(int len, int val)
238         {
239                 Result_Type rT;
240                 Expression::Ptr lhs, rhs;
241
242                 rT = is64Bit?u64:u32;
243
244             lhs = makeRmExpr();
245             rhs = Immediate::makeImmediate(Result(u32, unsign_extend32(len, val)));
246
247                 switch(shiftField)                                                                                      //add-sub (shifted) and logical (shifted)
248                 {
249                         case 0:insn_in_progress->appendOperand(makeLeftShiftExpression(lhs, rhs, rT), true, false);
250                                    break;
251                         case 1:insn_in_progress->appendOperand(makeRightLogicalShiftExpression(lhs, rhs, rT), true, false);
252                                    break;
253                         case 2:insn_in_progress->appendOperand(makeRightArithmeticShiftExpression(lhs, rhs, rT), true, false);
254                                    break;
255                         case 3:if(IS_INSN_LOGICAL_SHIFT(insn))                                  //logical (shifted) -- not applicable to add-sub (shifted)
256                                                 insn_in_progress->appendOperand(makeRightRotateExpression(lhs, rhs, rT), true, false);
257                                    else
258                                                 isValid = false;
259                                    break;
260                 }
261         }
262
263         void InstructionDecoder_aarch64::processShiftFieldImmInsn(int len, int val)
264         {
265                 if(shiftField == 0 || shiftField == 1)                                          //add-sub (immediate)
266                 {
267                         Result_Type rT = is64Bit?u64:u32;
268
269                         unsigned int shiftAmount = shiftField * 12;
270
271                         Expression::Ptr lhs = Immediate::makeImmediate(Result(rT, rT==u32?unsign_extend32(len, val):unsign_extend64(len, val)));
272                         Expression::Ptr rhs = Immediate::makeImmediate(Result(u32, unsign_extend32(4, shiftAmount)));
273
274                         insn_in_progress->appendOperand(makeLeftShiftExpression(lhs, rhs, rT), true, false);
275                 }
276                 else
277                 {
278                         isValid = false;
279                 }
280
281         }
282
283         Expression::Ptr InstructionDecoder_aarch64::makeOptionExpression(int len, int val)
284         {
285                 MachRegister baseReg = isFPInsn?
286             (isSinglePrec()?aarch64::d0:aarch64::q0):
287             (is64Bit?aarch64::x0:aarch64::w0);
288
289                 int encoding = field<16, 20>(insn);
290                 if(!isFPInsn && field<16, 20>(insn) == 31)
291                         baseReg = aarch64::zr;
292                 else
293                         baseReg = MachRegister(baseReg.val() + encoding);
294
295                 switch(optionField)
296                 {
297                         case 0:return makeRegisterExpression(baseReg, u8);
298                         case 1:return makeRegisterExpression(baseReg, u16);
299                         case 2:if(!is64Bit && (field<0, 4>(insn) == 31 || field<5, 9>(insn) == 31) && val != 0)
300                                            return makeLeftShiftExpression(makeRegisterExpression(baseReg), Immediate::makeImmediate(Result(u32, unsign_extend32(len, val))), u32);
301                                    else
302                                            return makeRegisterExpression(baseReg, u32);
303                         case 3:if(is64Bit && (field<0, 4>(insn) == 31 || field<5, 9>(insn) == 31) && val != 0)
304                                            return makeLeftShiftExpression(makeRegisterExpression(baseReg), Immediate::makeImmediate(Result(u32, unsign_extend32(len, val))), u64);
305                                    else
306                                            return makeRegisterExpression(baseReg, u64);
307                         case 4:return makeRegisterExpression(baseReg, s8);
308                         case 5:return makeRegisterExpression(baseReg, s16);
309                         case 6:return makeRegisterExpression(baseReg, s32);
310                         case 7:return makeRegisterExpression(baseReg, s64);
311                         default: assert(!"invalid option field value");
312                 }
313         }
314
315         void InstructionDecoder_aarch64::processOptionFieldLSRegOffsetInsn()
316         {
317                 if(optionField == 0x3)                  //option = LSL
318                 {
319                         int sizeVal = field<30, 31>(insn), extend;
320
321                         if(field<23, 23>(insn) == 1)
322                                 sizeVal = 4;
323
324                         extend = sField * sizeVal;
325                         int extendSize = 31;
326                         while(((extend << (31 - extendSize)) & 0x80000000) == 0)
327                                 extendSize--;
328
329                         //above values need to be used in a dereference expression
330                 }
331                 else
332                 {
333                         //sign-extend
334                         switch(optionField)
335                         {
336                                 case 0x2://UXTW
337                                                  break;
338                                 case 0x6://SXTW
339                                                  break;
340                                 case 0x7://SXTX
341                                                  break;
342                                 default:isValid = false;
343                                                 break;
344                         }
345                 }
346         }
347
348         void InstructionDecoder_aarch64::processSystemInsn()
349         {
350                 if(op0Field == 0)
351                 {
352                         if(crnField == 3)                       //clrex, dendBit, dmb, iendBit
353                         {
354                                 Expression::Ptr CRm = Immediate::makeImmediate(Result(u32, unsign_extend32(4, crmField)));
355
356                                 insn_in_progress->appendOperand(CRm, true, false);
357                         }
358                         else if(crnField == 2)
359                         {
360                                 int immVal = (crmField << 3)|(op2Field & 7);            //hint
361
362                                 Expression::Ptr imm = Immediate::makeImmediate(Result(u32, unsign_extend32(7, immVal)));
363
364                                 insn_in_progress->appendOperand(imm, true, false);
365                         }
366                         else if(crnField == 4)
367                         {
368                                 //msr immediate
369                                 //affects pstate
370                         }
371                         else
372                         {
373                                 isValid = false;
374                         }
375                 }
376                 else                  //sys, sysl, mrs, msr register
377                 {
378                         /*int immVal = op2 | (crm << 3) | (crn << 7) | (op1 << 11);
379                         immVal = (op0 >= 2)?(immVal << 1)|(op0 & 1):immVal;
380
381                         int immValLen = 14 + (op0 & 2);
382
383                         Expression::Ptr imm = Immediate::makeImmediate(Result(u32, unsign_extend32<immValLen>(immVal)));
384
385                         insn_in_progress->appendOperand(imm, true, false);*/
386                         assert(!"not implemented");
387
388                 }
389         }
390
391     Result_Type InstructionDecoder_aarch64::makeSizeType(unsigned int)
392     {
393         assert(0); //not implemented
394         return u32;
395     }
396
397     // ****************
398     // decoding opcodes
399     // ****************
400
401 #define fn(x) (&InstructionDecoder_aarch64::x)
402 #define COMMA   ,
403
404 MachRegister InstructionDecoder_aarch64::makeAarch64RegID(MachRegister base, unsigned int encoding)
405 {
406     return MachRegister(base.val() + encoding);
407 }
408
409 Expression::Ptr InstructionDecoder_aarch64::makeRdExpr()
410 {
411         MachRegister baseReg = (isFPInsn && !IS_INSN_FP_CONV_INT(insn))?
412         (isSinglePrec()?aarch64::d0:aarch64::q0):
413         (is64Bit?aarch64::x0:aarch64::w0);
414
415     int encoding = field<0, 4>(insn);
416         if(encoding == 31)
417                 return makeRegisterExpression(makeAarch64RegID(is64Bit?aarch64::sp:aarch64::wsp, 0));
418         else
419                 return makeRegisterExpression(makeAarch64RegID(baseReg, encoding));
420 }
421
422
423 void InstructionDecoder_aarch64::OPRRd()
424 {
425     insn_in_progress->appendOperand(makeRdExpr(), false, true);
426 }
427
428 Expression::Ptr InstructionDecoder_aarch64::makeRnExpr()
429 {
430         MachRegister baseReg = (isFPInsn && !IS_INSN_FP_CONV_FIX(insn))?
431         (isSinglePrec()?aarch64::d0:aarch64::q0):
432         (is64Bit?aarch64::x0:aarch64::w0);
433
434         int encoding = field<5, 9>(insn);
435         if(encoding == 31)
436                 return makeRegisterExpression(makeAarch64RegID(is64Bit?aarch64::sp:aarch64::wsp, 0));
437         else
438                 return makeRegisterExpression(makeAarch64RegID(baseReg, encoding));
439 }
440
441 Expression::Ptr InstructionDecoder_aarch64::makePCExpr()
442 {
443         MachRegister baseReg = aarch64::pc;
444
445         return makeRegisterExpression(makeAarch64RegID(baseReg, 0));
446 }
447
448 Expression::Ptr InstructionDecoder_aarch64::makePstateExpr()
449 {
450         MachRegister baseReg = aarch64::pstate;
451
452         return makeRegisterExpression(makeAarch64RegID(baseReg, 0));
453 }
454
455
456 void InstructionDecoder_aarch64::getMemRefIndexLiteral_OffsetLen(int &immVal, int &immLen){
457     immVal = field<5, 23>(insn);
458     immVal = immVal << 2; //immVal:00
459     immLen = (23 - 5 + 1) + 2;
460     return;
461 }
462
463 void InstructionDecoder_aarch64::getMemRefIndexLiteral_RT(Result_Type &rt){
464     int size = field<30, 31>(insn);
465     switch(size){
466         case 0x0:
467             rt = u32;
468             break;
469         case 0x1:
470             rt = u64;
471             break;
472         case 0x2:
473             rt = s32;
474             break;
475         case 0x3:
476         default:
477             assert(0);
478             break;
479     }
480     return;
481 }
482
483 // ****************************************
484 // load/store literal
485 // eg: load Xt, <literal>
486 // => offset = signextend(<literal>:00, 64)
487 // load from [PC + offset] to Xt
488 // ****************************************
489 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexLiteral()
490 {
491     int immVal, immLen;
492     getMemRefIndexLiteral_OffsetLen(immVal, immLen);
493
494     Expression::Ptr label = Immediate::makeImmediate(Result(s64, sign_extend64(immLen, immVal)));
495
496     Result_Type rt;
497     getMemRefIndexLiteral_RT(rt);
498
499     return makeDereferenceExpression(makeAddExpression(makePCExpr(), label, u64), rt);
500 }
501
502 // TODO potential bug: do we need to distinguish signed and unsigned here?
503 // this funciton is to get the mem ref size
504 // shared by ld/st uimm, post, pre, reg
505 void InstructionDecoder_aarch64::getMemRefIndex_RT(Result_Type &rt){
506     unsigned int opc1 = field<23, 23>(insn);
507     unsigned int size = field<30, 31>(insn);
508
509     if(opc1 == 1){
510         switch(size){
511             case 0:
512                 rt = s8;
513                 break;
514             case 1:
515                 rt = s16;
516                 break;
517             case 2:
518                 rt = s32;
519                 break;
520             case 3:
521                 rt = s64;
522                 break;
523             default:
524                 assert(0);
525                 //should only be 2 or 3
526                 break;
527         }
528     }else{
529         switch(size){
530             case 0:
531                 rt = u8;
532                 break;
533             case 1:
534                 rt = u16;
535                 break;
536             case 2:
537                 rt = u32;
538                 break;
539             case 3:
540                 rt = u64;
541                 break;
542             default:
543                 assert(0);
544                 //should only be 2 or 3
545                 break;
546         }
547     }
548
549     return;
550 }
551
552 void InstructionDecoder_aarch64::getMemRefPair_RT(Result_Type &rt){
553     unsigned int isSigned = field<30,30>(insn);
554     unsigned int size = field<31, 31>(insn);
555
556     // double the width
557     switch(isSigned){
558         case 0:
559             switch(size){
560                 case 0:
561                     //rt = u32;
562                     rt = u64;
563                     break;
564                 case 1:
565                     //rt = u64;
566                     rt = dbl128;
567                     break;
568                 default:
569                     assert(0);
570             }
571             break;
572         case 1:
573             switch(size){
574                 case 0:
575                     //rt = s32;
576                     rt = s64;
577                     break;
578                 case 1:
579                 default:
580                     assert(0);
581             }
582             break;
583         default:
584             assert(0);
585             break;
586     }
587
588     return;
589 }
590
591 void InstructionDecoder_aarch64::getMemRefIndex_SizeSizelen(unsigned int &size, unsigned int &sizeLen){
592     size = field<30, 31>(insn);
593     sizeLen = 31-30+1;
594     return;
595 }
596
597 void InstructionDecoder_aarch64::getMemRefIndexPrePost_ImmImmlen(unsigned int &immVal, unsigned int &immLen){
598     immVal = field<12, 20>(insn);
599     immLen = 20 - 12 + 1;
600     return;
601 }
602
603 void InstructionDecoder_aarch64::getMemRefPair_ImmImmlen(unsigned int &immVal, unsigned int &immLen){
604     immVal = field<15, 21>(insn);
605     immLen = 21-15 + 1;
606     return;
607 }
608
609 // ****************************************
610 // load/store unsigned imm
611 // eg: load Xt, [Xn, #imm]
612 // => offset = unsignextend( imm , 64)
613 // load from [PC + offset] to Xt
614 // ****************************************
615 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexUImm()
616 {
617     if( !IS_INSN_LDST_UIMM(insn) ) assert(0);
618
619     unsigned int immVal = field<10, 21>(insn);
620     unsigned int immLen = 21-10+1;
621
622     Expression::Ptr imm = Immediate::makeImmediate(Result(u64, unsign_extend64(immLen, immVal)));
623
624     unsigned int size, sizeLen;
625     getMemRefIndex_SizeSizelen(size, sizeLen);
626
627     Expression::Ptr scaleForUImm = Immediate::makeImmediate(Result(u32, unsign_extend32(sizeLen, 1<<size)));
628
629     Expression::Ptr offset = makeMultiplyExpression(imm, scaleForUImm, u64);
630
631     Result_Type rt;
632     getMemRefIndex_RT(rt);
633
634     return makeDereferenceExpression(makeAddExpression(makeRnExpr(), offset, u64), rt);
635 }
636
637 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndex_offset9(){
638     unsigned int immVal = 0, immLen = 0;
639     getMemRefIndexPrePost_ImmImmlen(immVal, immLen);
640     return Immediate::makeImmediate(Result(u64, sign_extend64(immLen, immVal)));
641 }
642
643 // scale = 2 + opc<1>
644 // scale = 1<<scale
645 // LSL(sign_ex(imm7 , 64), scale)
646 Expression::Ptr InstructionDecoder_aarch64::makeMemRefPair_offset7(){
647     unsigned int scaleVal = field<31, 31>(insn);
648     unsigned int scaleLen = 1;
649     scaleVal += 2;
650
651     Expression::Ptr scale = Immediate::makeImmediate(Result(u32, unsign_extend32(scaleLen, 1<<scaleVal)));
652
653     unsigned int immVal = 0, immLen = 0;
654     getMemRefPair_ImmImmlen(immVal, immLen);
655
656     Expression::Ptr imm7 = Immediate::makeImmediate(Result(u64, sign_extend64(immLen, immVal)));
657
658     return makeMultiplyExpression(imm7, scale, s64);
659 }
660
661 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndex_addOffset9(){
662     Expression::Ptr offset = makeMemRefIndex_offset9();
663     return makeAddExpression(makeRnExpr(), offset, u64);
664 }
665
666 Expression::Ptr InstructionDecoder_aarch64::makeMemRefPair_addOffset7(){
667     Expression::Ptr offset = makeMemRefPair_offset7();
668     return makeAddExpression(makeRnExpr(), offset, u64);
669 }
670
671 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexPre(){
672     Result_Type rt;
673     getMemRefIndex_RT(rt);
674     return makeDereferenceExpression(makeMemRefIndex_addOffset9(), rt);
675 }
676
677 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexPost(){
678     Result_Type rt;
679     getMemRefIndex_RT(rt);
680     return makeDereferenceExpression(makeRnExpr(), rt);
681 }
682
683 Expression::Ptr InstructionDecoder_aarch64::makeMemRefPairPre(){
684     Result_Type rt;
685     getMemRefPair_RT(rt);
686     return makeDereferenceExpression(makeMemRefPair_addOffset7(), rt);
687 }
688
689 /*
690 Expression::Ptr InstructionDecoder_aarch64::makeMemRefPairPre2(){
691     // datasize = 64/32 /8;
692     unsigned int opc1 = field<31, 31>(insn);
693     unsigned int sizeVal = 1<<(2+opc1); //4 or 8 bytes
694
695     Expression::Ptr dataSize = Immediate::makeImmediate(Result(u32, unsign_extend32( 32, sizeVal ) ) );
696     Expression::Ptr pair2 = makeAddExpression( makeMemRefPair_addOffset7(), dataSize, u64);
697
698     Result_Type rt;
699     getMemRefPair_RT(rt);
700     return makeDereferenceExpression(pair2, rt);
701 }
702 */
703
704 Expression::Ptr InstructionDecoder_aarch64::makeMemRefPairPost(){
705     Result_Type rt;
706     getMemRefPair_RT(rt);
707     return makeDereferenceExpression(makeRnExpr(), rt);
708 }
709
710 /*
711 Expression::Ptr InstructionDecoder_aarch64::makeMemRefPairPost2(){
712     // datasize = 64/32 /8;
713     unsigned int opc1 = field<31, 31>(insn);
714     unsigned int sizeVal = 1<<(2+opc1); //4 or 8 bytes
715
716     Expression::Ptr dataSize = Immediate::makeImmediate(Result(u32, unsign_extend32( 32, sizeVal ) ) );
717     Expression::Ptr pair2 = makeAddExpression( makeRnExpr(), dataSize, u64);
718
719     Result_Type rt;
720     getMemRefPair_RT(rt);
721     return makeDereferenceExpression(pair2, rt);
722 }
723 */
724
725 void InstructionDecoder_aarch64::getMemRefEx_RT(Result_Type &rt){
726     unsigned int sz = field<30, 31>(insn);
727     switch(sz){
728         case 0x00: //B
729             rt = u8;
730             break;
731         case 0x01: //H
732             rt = u16;
733             break;
734         case 0x10: //32b
735             rt = u32;
736             break;
737         case 0x11: //64b
738             rt = u64;
739             break;
740         default:
741             assert(0);// shouldn't reach here;
742     }
743     return;
744 }
745
746 Expression::Ptr InstructionDecoder_aarch64::makeMemRefEx(){
747     Result_Type rt;
748     getMemRefEx_RT(rt);
749     return makeDereferenceExpression(makeRnExpr(), rt);
750 }
751
752 void InstructionDecoder_aarch64::getMemRefExPair_RT(Result_Type &rt){
753     int size = field<30, 30>(insn);
754     switch(size){
755         case 0:
756             rt = u64;
757             break;
758         case 1:
759             rt = dbl128;
760             break;
761         default:
762             assert(!"should not reach here");
763             break;
764     }
765     return;
766 }
767
768 Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair(){
769     Result_Type rt;
770     getMemRefExPair_RT(rt);
771     return makeDereferenceExpression(makeRnExpr(), rt);
772 }
773
774 /*
775 Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair16B(){
776     return makeDereferenceExpression(makeRnExpr(), dbl128);
777 }
778 */
779
780 /*
781 Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair2(){
782     unsigned int immLen = 4, immVal = 8;
783     Expression::Ptr offset = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));
784     return makeDereferenceExpression(makeAddExpression(makeRnExpr(), offset, u64) , u64);
785 }
786 */
787
788 Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_Rm(){
789     unsigned int option = field<13, 15>(insn);
790     if((option&2) != 2) assert(0);
791     MachRegister baseReg = ((option & 0x3)==0x2) ? aarch64::w0 : aarch64::x0;
792     unsigned int encoding = field<16, 20>(insn);
793
794         if( encoding == 31 )//zero register
795                 return makeRegisterExpression(makeAarch64RegID(aarch64::zr, 0));
796     else
797         return makeRegisterExpression(makeAarch64RegID(baseReg, encoding));
798 }
799
800 Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_amount(){
801     unsigned int S =  field<12, 12>(insn);
802     unsigned int amountVal = is64Bit?(S==0?0:2):(S==0?0:3);
803     unsigned int amountLen = 2;
804
805     return Immediate::makeImmediate(Result(u32, unsign_extend32(amountLen, amountVal)) ) ;
806 }
807
808 Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_ext(){
809     //Expression::Ptr rm = makeMemRefReg_Rm();
810     //Expression::Ptr amount = makeMemRefReg_amount();
811
812     int immLen = 2;
813     int immVal = 0; //for amount
814
815     int S = field<12,12>(insn);
816     int size = field<30,31>(insn);
817
818     if( size == 2 ){ //32bit
819         immVal = S==0?0:(S==1?2:-1);
820         if( immVal==-1 ) assert(0);
821     }else if( size == 3 ){ //64bit
822         immVal = S==0?0:(S==1?3:-1);
823         if( immVal==-1) assert(0);
824     }else{
825         assert(0); //unregconized val
826     }
827
828     Expression::Ptr ext = makeOptionExpression(immLen, immVal);
829     return ext; /*extended ptr*/
830 }
831
832 /**********************
833 // ld/st reg memReg AST:
834 //    memRef
835 //      |
836 //     ADD
837 //    /    \
838 //  [Rn]   EXT
839 //        /   \
840 //      [Rm] [amount]
841 **********************/
842 Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg(){
843
844     Expression::Ptr ext = makeMemRefReg_ext();
845     Expression::Ptr xn = makeRnExpr();
846     Expression::Ptr add = makeAddExpression(xn, ext, u64);
847
848     Result_Type rt;
849     getMemRefIndex_RT(rt);
850     return makeDereferenceExpression(add,rt);
851 }
852
853 void InstructionDecoder_aarch64::LIndex()
854 {
855     if( IS_INSN_LD_LITERAL(insn)){
856         insn_in_progress->appendOperand(makeMemRefIndexLiteral(), true, false);
857         return;
858     }
859
860     // ******************
861     // ld/st register offset
862     // ******************
863     else if( IS_INSN_LDST_REG(insn)){
864         insn_in_progress->appendOperand(makeMemRefReg(), true, false);
865         return;
866     }
867
868     // ******************
869     // ld/st unsigned imm
870     // ******************
871     else if( IS_INSN_LDST_UIMM(insn)){
872         insn_in_progress->appendOperand(makeMemRefIndexUImm(), true, false);
873         return;
874     }
875
876     // ******************
877     // ld/st pre and post, unscaled and unprivlidged
878     // ******************
879     else if( IS_INSN_LDST_PRE(insn)
880         || IS_INSN_LDST_UNPRIV(insn)
881         || IS_INSN_LDST_UNSCALED(insn) ){
882         insn_in_progress->appendOperand(makeMemRefIndexPre(), true, false);
883         return;
884     }
885
886     else if( IS_INSN_LDST_POST(insn) ){
887         insn_in_progress->appendOperand(makeMemRefIndexPost(), true, false);
888         return;
889     }
890
891     // ****************************
892     // ld/st PAIR pre, post, offset
893     // ****************************
894     else if( IS_INSN_LDST_PAIR_PRE(insn) ){
895         insn_in_progress->appendOperand(makeMemRefPairPre(), true, false);
896         return;
897     }
898
899     else if( IS_INSN_LDST_PAIR_POST(insn)
900         || IS_INSN_LDST_PAIR_OFFSET(insn)
901         || IS_INSN_LDST_PAIR_NOALLOC(insn) ){
902         insn_in_progress->appendOperand(makeMemRefPairPost(), true, false);
903         return;
904     }
905
906     // ****************************
907     // ld/st exclusive instructions
908     // ****************************
909     else if( IS_INSN_LDST_EX(insn) ){
910         if( !IS_INSN_LDST_EX_PAIR(insn) ){ // Rt2 field == 31, non-pair op
911             insn_in_progress->appendOperand( makeMemRefEx(), true, false);
912         } else { // pair
913             insn_in_progress->appendOperand( makeMemRefExPair(), true, false);
914         }
915         return;
916     }
917
918     assert(0); //un-handled case
919
920 }
921
922 void InstructionDecoder_aarch64::STIndex()
923 {
924     if( IS_INSN_LD_LITERAL(insn))
925         assert(0); // only load literal, no store literal
926
927     // ******************
928     // ld/st register offset
929     // ******************
930     else if( IS_INSN_LDST_REG(insn)){
931         insn_in_progress->appendOperand(makeMemRefReg(), false, true);
932         return;
933     }
934
935     else if( IS_INSN_LDST_UIMM(insn)){
936         insn_in_progress->appendOperand(makeMemRefIndexUImm(), false, true);
937         return;
938     }
939
940     // ******************
941     // ld/st pre and post, unscaled and unprivilidged
942     // ******************
943     else if( IS_INSN_LDST_PRE(insn)
944         || IS_INSN_LDST_UNPRIV(insn)
945         || IS_INSN_LDST_UNSCALED(insn) ){
946         insn_in_progress->appendOperand(makeMemRefIndexPre(), false, true);
947         return;
948     }
949
950     else if( IS_INSN_LDST_POST(insn) ){
951         insn_in_progress->appendOperand(makeMemRefIndexPost(), false, true);
952         return;
953     }
954
955     // ****************************
956     // ld/st PAIR pre, post, offset
957     // ****************************
958     else if( IS_INSN_LDST_PAIR_PRE(insn) ){
959         insn_in_progress->appendOperand(makeMemRefPairPre(), false, true);
960         return;
961     }
962
963     else if( IS_INSN_LDST_PAIR_POST(insn)
964         || IS_INSN_LDST_PAIR_OFFSET(insn)
965         || IS_INSN_LDST_PAIR_NOALLOC(insn) ){
966         insn_in_progress->appendOperand(makeMemRefPairPost(), false, true);
967         return;
968     }
969
970     // ****************************
971     // ld/st exclusive instructions
972     // ****************************
973     else if( IS_INSN_LDST_EX(insn) ){
974         if( !IS_INSN_LDST_EX_PAIR(insn) ){ // Rt2 field == 31, non-pair op
975             insn_in_progress->appendOperand( makeMemRefEx(), false, true);
976         } else { // pair
977             insn_in_progress->appendOperand( makeMemRefExPair(), false, true);
978         }
979         return;
980     }
981
982     assert(0); //un-handled case
983
984 }
985
986 // This function is for non-writeback
987 void InstructionDecoder_aarch64::OPRRn()
988 {
989         if(IS_INSN_B_UNCOND_REG(insn))                                                                          //unconditional branch (register)
990         {
991                 int branchType = field<21, 22>(insn);
992                 bool branchIsCall = false;
993
994                 if(branchType == 0x1)
995                 {
996                         branchIsCall = true;
997                         makeLinkForBranch();
998                 }
999
1000                 insn_in_progress->appendOperand(makePCExpr(), false, true);
1001                 insn_in_progress->addSuccessor(makeRnExpr(), branchIsCall, false, false, false);
1002         }
1003         else
1004                 insn_in_progress->appendOperand(makeRnExpr(), true, false);
1005 }
1006
1007 void InstructionDecoder_aarch64::OPRRnL()
1008 {
1009         insn_in_progress->appendOperand(makeRnExpr(), true, false);
1010     LIndex();
1011 }
1012
1013 void InstructionDecoder_aarch64::OPRRnS()
1014 {
1015         insn_in_progress->appendOperand(makeRnExpr(), true, false);
1016     STIndex();
1017 }
1018
1019 void InstructionDecoder_aarch64::OPRRnU()
1020 {
1021     assert(0);
1022     /* this functions is useless
1023         insn_in_progress->appendOperand(makeRnExpr(), true, true);
1024     */
1025 }
1026
1027 void InstructionDecoder_aarch64::OPRRnLU()
1028 {
1029     if( IS_INSN_LDST_PRE(insn) ){
1030             insn_in_progress->appendOperand(makeRnExpr(), true, true);
1031         LIndex();
1032         return;
1033     }
1034
1035     if( IS_INSN_LDST_POST(insn) ){
1036         LIndex();
1037             insn_in_progress->appendOperand(makeRnExpr(), true, true);
1038         return;
1039     }
1040
1041     if( IS_INSN_LDST_PAIR_PRE(insn) ){
1042             insn_in_progress->appendOperand(makeRnExpr(), true, true);
1043         LIndex();
1044         return;
1045     }
1046
1047     if( IS_INSN_LDST_PAIR_POST(insn) ){
1048         LIndex();
1049             insn_in_progress->appendOperand(makeRnExpr(), true, true);
1050         return;
1051     }
1052
1053 }
1054
1055 void InstructionDecoder_aarch64::OPRRnSU()
1056 {
1057     if( IS_INSN_LDST_PRE(insn) ){
1058             insn_in_progress->appendOperand(makeRnExpr(), true, true);
1059         STIndex();
1060         return;
1061     }
1062
1063     if( IS_INSN_LDST_POST(insn) ){
1064         STIndex();
1065             insn_in_progress->appendOperand(makeRnExpr(), true, true);
1066         return;
1067     }
1068
1069     if( IS_INSN_LDST_PAIR_PRE(insn) ){
1070             insn_in_progress->appendOperand(makeRnExpr(), true, true);
1071         STIndex();
1072         return;
1073     }
1074
1075     if( IS_INSN_LDST_PAIR_POST(insn) ){
1076         STIndex();
1077             insn_in_progress->appendOperand(makeRnExpr(), true, true);
1078         return;
1079     }
1080 }
1081
1082 Expression::Ptr InstructionDecoder_aarch64::makeRmExpr()
1083 {
1084         MachRegister baseReg = isFPInsn?
1085         (isSinglePrec()?aarch64::d0:aarch64::q0):
1086         (is64Bit?aarch64::x0:aarch64::w0);
1087
1088         int encoding = field<16, 20>(insn);
1089         if(!isFPInsn && field<16, 20>(insn) == 31)                                                      //zero register applicable only for non-floating point instructions
1090                 return makeRegisterExpression(makeAarch64RegID(aarch64::zr, 0));
1091         else
1092                 return makeRegisterExpression(makeAarch64RegID(baseReg, encoding));
1093 }
1094
1095 void InstructionDecoder_aarch64::OPRRm()
1096 {
1097         if(IS_INSN_LDST_REG(insn) ||
1098            IS_INSN_ADDSUB_EXT(insn) ||
1099            IS_INSN_ADDSUB_SHIFT(insn) ||
1100            IS_INSN_LOGICAL_SHIFT(insn))
1101                 return;
1102
1103         insn_in_progress->appendOperand(makeRmExpr(), true, false);
1104 }
1105
1106 void InstructionDecoder_aarch64::OPRsf()
1107 {
1108         if(field<31, 31>(insn) == 0)
1109                 is64Bit = false;
1110 }
1111
1112 template<unsigned int endBit, unsigned int startBit>
1113 void InstructionDecoder_aarch64::OPRoption()
1114 {
1115         hasOption = true;
1116         optionField = field<startBit, endBit>(insn);
1117 }
1118
1119 void InstructionDecoder_aarch64::OPRshift()
1120 {
1121         hasShift = true;
1122         shiftField = field<22, 23>(insn);
1123 }
1124
1125 void InstructionDecoder_aarch64::OPRhw()
1126 {
1127         hasHw = true;
1128         hwField = field<21, 22>(insn);
1129 }
1130
1131 template<unsigned int endBit, unsigned int startBit>
1132 void InstructionDecoder_aarch64::OPRN()
1133 {
1134         nField = field<startBit, endBit>(insn);
1135         nLen = endBit - startBit + 1;
1136 }
1137
1138 // the call of this function should be generated by decoder gen for ld/st class
1139 // except for ld/st{s, h, w} subclass
1140 void InstructionDecoder_aarch64::setRegWidth(){
1141     //is64Bit is by default set to TRUE
1142     unsigned int opc = 0x3 & field<22, 23>(insn);
1143     unsigned int opc0 = opc & 0x1;
1144     unsigned int opc1 = (opc & 0x2)>>1;
1145     unsigned int sz  = 0x3 & field<30, 31>(insn);
1146
1147     if(IS_INSN_LDST(insn)){
1148         if(   IS_INSN_LDST_UIMM(insn)   || IS_INSN_LDST_UNSCALED(insn)
1149                 || IS_INSN_LDST_UNPRIV(insn) || IS_INSN_LDST_POST(insn)
1150                 || IS_INSN_LDST_PRE(insn)    || IS_INSN_LDST_REG(insn)){
1151                 if(opc1 == 0){
1152                     if(field<30, 31>(insn) != 3)
1153                         is64Bit = false;
1154                     return;
1155                 }else{
1156                     if( sz == 3){
1157                         if( opc0 == 1) assert(!"unallocated insn");
1158                     }
1159                     else{
1160                         if(sz == 2 && opc0 == 1) assert(!"unallocated insn");
1161                         if(opc0 == 1)
1162                             is64Bit = false;
1163                     }
1164                     return;
1165                 }
1166         }
1167         else if(IS_INSN_LDST_EX(insn)){
1168             switch(sz){
1169                 case 2:
1170                     is64Bit = false;
1171                     break;
1172                 case 0:
1173                 case 1:
1174                 case 3:
1175                 default:
1176                     return;
1177             }
1178         }
1179         else if(IS_INSN_LDST_PAIR(insn)){
1180             switch(sz){
1181                 case 0:
1182                     is64Bit = false;
1183                     break;
1184                 case 1:
1185                 case 2:
1186                 case 3:
1187                 default:
1188                     return;
1189             }
1190         }
1191         else if(IS_INSN_LD_LITERAL(insn)){
1192             switch(sz){
1193                 case 0:
1194                     is64Bit = false;
1195                 case 1:
1196                 case 2:
1197                 case 3:
1198                 default:
1199                     return;
1200             }
1201         }
1202         else{
1203             assert(!"not implemented for SIMD");
1204         }
1205     }else{
1206         assert(0);
1207     }
1208     return;
1209 }
1210
1211 Expression::Ptr InstructionDecoder_aarch64::makeRtExpr()
1212 {
1213         MachRegister baseReg = isFPInsn?
1214         (isSinglePrec()?aarch64::d0:aarch64::q0):
1215         (is64Bit ? aarch64::x0 : aarch64::w0);
1216
1217         return makeRegisterExpression(makeAarch64RegID(baseReg, field<0, 4>(insn)));
1218 }
1219
1220 void InstructionDecoder_aarch64::OPRRt()
1221 {
1222         //sys, sysl, msr reg, mrs
1223         //others
1224 }
1225
1226 void InstructionDecoder_aarch64::OPRRtL()
1227 {
1228         insn_in_progress->appendOperand(makeRtExpr(), false, true);
1229 }
1230
1231 void InstructionDecoder_aarch64::OPRRtS()
1232 {
1233         insn_in_progress->appendOperand(makeRtExpr(), true, false);
1234 }
1235
1236 Expression::Ptr InstructionDecoder_aarch64::makeRt2Expr()
1237 {
1238         MachRegister baseReg = isFPInsn?
1239         (isSinglePrec()?aarch64::d0:aarch64::q0):
1240         (is64Bit?aarch64::x0 : aarch64::w0);
1241
1242         return makeRegisterExpression(makeAarch64RegID(baseReg, field<10, 14>(insn)));
1243 }
1244
1245 void InstructionDecoder_aarch64::OPRRt2()
1246 {
1247     assert(0);
1248 }
1249
1250 void InstructionDecoder_aarch64::OPRRt2L()
1251 {
1252         insn_in_progress->appendOperand(makeRt2Expr(), false, true);
1253 }
1254
1255 void InstructionDecoder_aarch64::OPRRt2S()
1256 {
1257         insn_in_progress->appendOperand(makeRt2Expr(), true, false);
1258 }
1259
1260 template<unsigned int endBit, unsigned int startBit>
1261 void InstructionDecoder_aarch64::OPRcond()
1262 {
1263         unsigned char condVal = static_cast<unsigned char>(field<startBit, endBit>(insn));
1264         Expression::Ptr cond = Immediate::makeImmediate(Result(u8, condVal));
1265         insn_in_progress->appendOperand(cond, true, false);
1266
1267         isPstateRead = true;
1268 }
1269
1270 void InstructionDecoder_aarch64::OPRnzcv()
1271 {
1272         uint64_t nzcvVal = (static_cast<uint64_t>(field<0, 3>(insn)))<<60;
1273         Expression::Ptr nzcv = Immediate::makeImmediate(Result(u64, nzcvVal));
1274         insn_in_progress->appendOperand(nzcv, true, false);
1275
1276         isPstateWritten = true;
1277 }
1278
1279 void InstructionDecoder_aarch64::OPRop1()
1280 {
1281         op1Field = field<16, 18>(insn);
1282 }
1283
1284 void InstructionDecoder_aarch64::OPRop2()
1285 {
1286         op2Field = field<5, 7>(insn);
1287 }
1288
1289 void InstructionDecoder_aarch64::OPRCRm()
1290 {
1291         isSystemInsn = true;
1292         crmField = field<8 ,11>(insn);
1293 }
1294
1295 void InstructionDecoder_aarch64::OPRCRn()
1296 {
1297         crnField = field<12, 15>(insn);
1298 }
1299
1300 template<unsigned int endBit, unsigned int startBit>
1301 void InstructionDecoder_aarch64::OPRS()
1302 {
1303         sField = field<startBit, endBit>(insn);
1304 }
1305
1306 void InstructionDecoder_aarch64::OPRscale()
1307 {
1308         int scaleVal = 64 - field<10, 15>(insn);
1309
1310         Expression::Ptr scale = Immediate::makeImmediate(Result(u32, unsign_extend32(6, scaleVal)));
1311         insn_in_progress->appendOperand(scale, true, false);
1312 }
1313
1314 Expression::Ptr InstructionDecoder_aarch64::makeRaExpr()
1315 {
1316         MachRegister baseReg = isFPInsn?
1317         (isSinglePrec()?aarch64::d0:aarch64::q0):
1318         (is64Bit?aarch64::x0:aarch64::w0);
1319
1320         return makeRegisterExpression(makeAarch64RegID(baseReg, field<10, 14>(insn)));
1321 }
1322
1323 void InstructionDecoder_aarch64::OPRRa()
1324 {
1325         insn_in_progress->appendOperand(makeRaExpr(), true, false);
1326 }
1327
1328 void InstructionDecoder_aarch64::OPRo0()
1329 {
1330         op0Field = field<19, 20>(insn);
1331 }
1332
1333 void InstructionDecoder_aarch64::OPRb5()
1334 {
1335         OPRsf();
1336 }
1337
1338 void InstructionDecoder_aarch64::OPRb40()
1339 {
1340         int b40Val = field<19, 23>(insn);
1341         int bitpos = ((is64Bit?1:0)<<5) | b40Val;
1342
1343         insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u32, unsign_extend32(6, bitpos))), true, false);
1344 }
1345
1346 template<unsigned int endBit, unsigned int startBit>
1347 void InstructionDecoder_aarch64::OPRsz()
1348 {
1349     _szField = field<startBit, endBit>(insn);
1350 }
1351
1352 bool InstructionDecoder_aarch64::isSinglePrec() {
1353     if( isFPInsn && !isSIMDInsn ){
1354         if(_typeField!=-1){
1355             return _typeField==0?true:false;
1356         }else{
1357             //TODO if the type field is not set, do sth else
1358             assert(0);
1359         }
1360     }else if( isSIMDInsn ){
1361         assert(0); //not implemeted yet
1362     }
1363     return false;
1364 }
1365
1366 Expression::Ptr InstructionDecoder_aarch64::makeRsExpr()
1367 {
1368         MachRegister baseReg = isFPInsn?
1369         (isSinglePrec()?aarch64::d0:aarch64::q0):
1370         (is64Bit?aarch64::x0:aarch64::w0);
1371
1372         return makeRegisterExpression(makeAarch64RegID(baseReg, field<16, 20>(insn)));
1373 }
1374
1375 void InstructionDecoder_aarch64::OPRRs()
1376 {
1377         insn_in_progress->appendOperand(makeRsExpr(), false, true);
1378 }
1379
1380 void InstructionDecoder_aarch64::makeLinkForBranch()
1381 {
1382         insn_in_progress->appendOperand(makeRegisterExpression(makeAarch64RegID(aarch64::x30, 0)), false, true);
1383 }
1384
1385 void InstructionDecoder_aarch64::makeBranchTarget(bool branchIsCall, bool bIsConditional, int immVal, int immLen)
1386 {
1387         Expression::Ptr lhs = makePCExpr();
1388
1389         int offset = sign_extend64(immLen + 2, immVal*4);
1390         Expression::Ptr rhs = Immediate::makeImmediate(Result(s64, offset));
1391
1392         if(branchIsCall)
1393         {
1394                 makeLinkForBranch();
1395         }
1396
1397         insn_in_progress->addSuccessor(makeAddExpression(lhs, rhs, s64), branchIsCall, false, bIsConditional, false);
1398 }
1399
1400 Expression::Ptr InstructionDecoder_aarch64::makeFallThroughExpr()
1401 {
1402         return makeAddExpression(makePCExpr(), Immediate::makeImmediate(Result(u64, unsign_extend64(3, 4))), u64);
1403 }
1404
1405 template<typename T, Result_Type rT>
1406 Expression::Ptr InstructionDecoder_aarch64::fpExpand(int val)
1407 {
1408         int N, E, F, sign, exp;
1409         T frac, expandedImm;
1410         
1411         N = (rT == s32)?32:64;
1412         E = (N == 32)?8:11;
1413         F = N - E - 1;
1414         
1415         sign = (val & 0x80) >> 7;
1416         
1417         int val6 = ((~val) & 0x40) >> 6, val6mask = (1 << (E - 3)) - 1;
1418         exp = (val6 << (E - 1)) | ((val6?val6mask:0) << 2) | ((val & 0x30) >> 4);
1419         
1420         frac = (val & 0xF) << (F - 4);
1421         
1422         expandedImm = (sign << (E + F)) | (exp << F) | frac;
1423                 
1424         return Immediate::makeImmediate(Result(rT, expandedImm));
1425 }
1426
1427 template<unsigned int endBit, unsigned int startBit>
1428 void InstructionDecoder_aarch64::OPRimm()
1429 {
1430         int immVal = field<startBit, endBit>(insn);
1431         unsigned int immLen = endBit - startBit + 1;
1432
1433         if(hasHw)
1434         {
1435                 if(IS_INSN_MOVEWIDE_IMM(insn))          //movewide (immediate)
1436                 {
1437                         processHwFieldInsn(immLen, immVal);
1438                 }
1439                 else
1440                 {
1441                         isValid = false;
1442                 }
1443         }
1444         else if(hasN)           //logical (immediate), bitfield, extract
1445         {
1446                 if(IS_FIELD_IMMR(startBit, endBit))
1447                 {
1448                         immr = immVal;
1449                         immrLen = immLen;
1450
1451                         if(IS_INSN_BITFIELD(insn))
1452                         {
1453                                 Expression::Ptr imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immrLen, immr)));
1454                                 insn_in_progress->appendOperand(imm, true, false);
1455                         }
1456                 }
1457                 else if(IS_FIELD_IMMS(startBit, endBit))
1458                 {
1459                         Expression::Ptr imm;
1460
1461                         if(IS_INSN_LOGICAL_IMM(insn))
1462                         {
1463                                 immVal |= (immr << immLen);
1464                                 immVal |= (nField << (immLen + immrLen));
1465
1466                                 immLen += nLen + immrLen;
1467
1468                                 Result_Type rT = is64Bit?u64:u32;
1469                                 imm = Immediate::makeImmediate(Result(rT, rT==u32?unsign_extend32(immLen, immVal):unsign_extend64(immLen, immVal)));
1470                         }
1471                         else
1472                                 imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));
1473
1474                         insn_in_progress->appendOperand(imm, true, false);
1475                 }
1476         }
1477         else if(hasShift)
1478         {
1479                 if(IS_INSN_ADDSUB_SHIFT(insn) || IS_INSN_LOGICAL_SHIFT(insn))   //add-sub shifted | logical shifted
1480                 {
1481                         processShiftFieldShiftedInsn(immLen, immVal);
1482                 }
1483                 else if(IS_INSN_ADDSUB_IMM(insn))               //add-sub (immediate)
1484                 {
1485                         processShiftFieldImmInsn(immLen, immVal);
1486                 }
1487                 else
1488                 {
1489                         isValid = false;
1490                 }
1491         }
1492         else if(hasOption)
1493         {
1494                 if(IS_INSN_ADDSUB_EXT(insn))                                                                            //add-sub extended
1495                 {
1496                     Expression::Ptr expr = makeOptionExpression(immLen, immVal);
1497
1498                     insn_in_progress->appendOperand(expr, true, false);
1499                 }
1500                 else
1501                 {
1502                         isValid = false;
1503                 }
1504         }
1505         else if(IS_INSN_BRANCHING(insn) && !IS_INSN_B_UNCOND_REG(insn))
1506         {               //unconditional branch (immediate), test and branch, compare and branch, conditional branch
1507                 bool bIsConditional = false;
1508                 if(!(IS_INSN_B_UNCOND(insn)))
1509                         bIsConditional = true;
1510
1511                 bool branchIsCall = bIsConditional?false:(field<31, 31>(insn) == 1);
1512
1513                 insn_in_progress->appendOperand(makePCExpr(), false, true);
1514                 makeBranchTarget(branchIsCall, bIsConditional, immVal, immLen);
1515
1516                 if(bIsConditional)
1517                         insn_in_progress->addSuccessor(makeFallThroughExpr(), false, false, false, true);
1518         }
1519         else if(IS_INSN_PCREL_ADDR(insn))                                                                       //pc-relative addressing
1520         {
1521                 if(IS_FIELD_IMMLO(startBit, endBit))
1522                 {
1523                         immlo = immVal;
1524                         immloLen = endBit - startBit + 1;
1525                 }
1526                 else if(IS_FIELD_IMMHI(startBit, endBit))
1527                 {
1528                         bool page = (field<31, 31>(insn) == 1);
1529                         int offset = (immVal<<immloLen) | immlo;
1530
1531                         Expression::Ptr imm;
1532
1533                         insn_in_progress->appendOperand(makePCExpr(), true, false);
1534                         if(page)
1535                                 imm = makeLeftShiftExpression(Immediate::makeImmediate(Result(s64, sign_extend64(immloLen + immLen, offset))),
1536                                                                                           Immediate::makeImmediate(Result(u32, unsign_extend32(4, 12))), s64);
1537                         else
1538                                 imm = Immediate::makeImmediate(Result(s64, sign_extend64(immloLen + immLen, offset)));
1539
1540                         insn_in_progress->appendOperand(imm, true, false);
1541                 }
1542                 else
1543                         isValid = false;
1544         }
1545         else
1546         {
1547                 if(IS_INSN_FP_IMM(insn))
1548                 {
1549                         if(isSinglePrec())
1550                                 insn_in_progress->appendOperand(fpExpand<uint32_t, s32>(immVal), true, false);
1551                         else
1552                                 insn_in_progress->appendOperand(fpExpand<uint64_t, s64>(immVal), true, false);
1553                 }
1554                 else                                                            //exception, conditional compare (immediate)
1555                 {
1556                         Result_Type rT = is64Bit?u64:u32;
1557
1558                         Expression::Ptr imm = Immediate::makeImmediate(Result(rT, rT==u32?unsign_extend32(immLen, immVal):unsign_extend64(immLen, immVal)));
1559                         insn_in_progress->appendOperand(imm, true, false);
1560                 }
1561         }
1562 }
1563
1564
1565 using namespace boost::assign;
1566
1567 #include "aarch64_opcode_tables.C"
1568
1569         void InstructionDecoder_aarch64::doDelayedDecode(const Instruction *insn_to_complete)
1570     {
1571                 int insn_table_index = findInsnTableIndex(0);
1572                 aarch64_insn_entry *insn_table_entry = &aarch64_insn_entry::main_insn_table[insn_table_index];
1573
1574                 insn = insn_to_complete->m_RawInsn.small_insn;
1575                 insn_in_progress = const_cast<Instruction*>(insn_to_complete);
1576
1577                 //only a small subset of instructions modify nzcv and the following are the ones for whom it cannot be detected from any operand that they do modify pstate
1578                 //it thus needs to be read from the manual..yay
1579                 if(((IS_INSN_ADDSUB_EXT(insn) || IS_INSN_ADDSUB_SHIFT(insn) || IS_INSN_ADDSUB_IMM(insn) || IS_INSN_ADDSUB_CARRY(insn))
1580                          && field<29, 29>(insn) == 0x1) ||
1581                    ((IS_INSN_LOGICAL_SHIFT(insn) || IS_INSN_LOGICAL_IMM(insn))
1582                          && field<29, 30>(insn) == 0x3) ||
1583                    (IS_INSN_FP_COMPARE(insn))
1584             )
1585                    isPstateWritten = true;
1586
1587
1588         for(operandSpec::const_iterator fn = insn_table_entry->operands.begin(); fn != insn_table_entry->operands.end(); fn++)
1589         {
1590                         std::mem_fun(*fn)(this);
1591                 }
1592
1593                 if(isPstateWritten || isPstateRead)
1594                         insn_in_progress->appendOperand(makePstateExpr(), isPstateRead, isPstateWritten);
1595
1596                 if(isSystemInsn)
1597                 {
1598                         processSystemInsn();
1599                 }
1600
1601                 if(!isValid)
1602                 {
1603                         insn_in_progress = invalid_insn;
1604                 }
1605     }
1606
1607         int InstructionDecoder_aarch64::findInsnTableIndex(unsigned int decoder_table_index)
1608         {
1609                 aarch64_mask_entry *cur_entry = &aarch64_mask_entry::main_decoder_table[decoder_table_index];
1610                 unsigned int cur_mask = cur_entry->mask;
1611
1612                 if(cur_mask == 0)
1613                         return cur_entry->insnTableIndex;
1614
1615                 unsigned int insn_iter_index = 0, map_key_index = 0, branch_map_key = 0;
1616                 branchMap cur_branches = cur_entry->nodeBranches;
1617
1618                 while(insn_iter_index <= AARCH64_INSN_LENGTH)
1619                 {
1620                         if(((cur_mask>>insn_iter_index) & 1) == 1)
1621                         {
1622                                 branch_map_key = branch_map_key | (((insn>>insn_iter_index) & 1)<<map_key_index);
1623                                 map_key_index++;
1624                         }
1625                         insn_iter_index++;
1626                 }
1627
1628                 if(cur_branches.count(branch_map_key) <= 0)
1629                         branch_map_key = 0;
1630
1631                 return findInsnTableIndex(cur_branches[branch_map_key]);
1632         }
1633
1634     void InstructionDecoder_aarch64::mainDecode()
1635     {
1636                 int insn_table_index = findInsnTableIndex(0);
1637
1638                 aarch64_insn_entry *insn_table_entry = &aarch64_insn_entry::main_insn_table[insn_table_index];
1639
1640         insn_in_progress = makeInstruction(insn_table_entry->op, insn_table_entry->mnemonic, 4, reinterpret_cast<unsigned char*>(&insn));
1641         insn_printf("ARM: %s\n", insn_table_entry->mnemonic);
1642
1643         if(IS_INSN_BRANCHING(insn))
1644         {
1645             // decode control-flow operands immediately; we're all but guaranteed to need them
1646             doDelayedDecode(insn_in_progress);
1647         }
1648
1649         //insn_in_progress->arch_decoded_from = m_Arch;
1650         insn_in_progress->arch_decoded_from = Arch_aarch64;
1651         return;
1652     }
1653   };
1654 };
1655
1656
1657