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