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