Fixes to correctly handle stack pointer in the destination register field
[dyninst.git] / instructionAPI / src / InstructionDecoder-aarch64.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  *
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  *
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  *
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  *
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  *
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 #include "InstructionDecoder-aarch64.h"
32 #include <boost/assign/list_of.hpp>
33 #include "../../common/src/singleton_object_pool.h"
34
35 namespace Dyninst
36 {
37   namespace InstructionAPI
38   {
39     typedef void (InstructionDecoder_aarch64::*operandFactory)();
40     typedef std::vector<operandFactory> operandSpec;
41     typedef std::vector<aarch64_insn_entry> aarch64_insn_table;
42     typedef std::map<unsigned int, aarch64_mask_entry> aarch64_decoder_table;
43     typedef std::map<unsigned int, unsigned int> branchMap;
44     typedef uint32_t Bits_t;
45
46     std::vector<std::string> InstructionDecoder_aarch64::condStringMap;
47     std::map<unsigned int, MachRegister> InstructionDecoder_aarch64::sysRegMap;
48
49     struct aarch64_insn_entry
50     {
51         aarch64_insn_entry(entryID o, const char* m, operandSpec ops):
52         op(o), mnemonic(m), operands(ops)
53         {
54         }
55
56         aarch64_insn_entry(entryID o, const char* m, operandSpec ops, Bits_t enb, Bits_t mb):
57         op(o), mnemonic(m), operands(ops),_encodingBits(enb), _maskBits(mb)
58         {
59         }
60
61         aarch64_insn_entry():
62         op(aarch64_op_INVALID), mnemonic("INVALID")
63         {
64             operands.reserve(5);
65         }
66
67         aarch64_insn_entry(const aarch64_insn_entry& o) :
68         op(o.op), mnemonic(o.mnemonic), operands(o.operands),
69         _encodingBits(o._encodingBits),_maskBits(o._maskBits)
70         {
71         }
72
73         const aarch64_insn_entry& operator=(const aarch64_insn_entry& rhs)
74         {
75             operands.reserve(rhs.operands.size());
76             op = rhs.op;
77             mnemonic = rhs.mnemonic;
78             operands = rhs.operands;
79             _encodingBits = rhs._encodingBits;
80             _maskBits = rhs._maskBits;
81
82             return *this;
83         }
84
85         entryID op;
86         const char* mnemonic;
87         operandSpec operands;
88
89         Bits_t _encodingBits;
90         Bits_t _maskBits;
91
92         static void buildInsnTable();
93         static bool built_insn_table;
94
95         static aarch64_insn_table main_insn_table;
96     };
97
98     struct aarch64_mask_entry
99     {
100                 aarch64_mask_entry(unsigned int m, branchMap bm, int tabIndex):
101                 mask(m), nodeBranches(bm), insnTableIndices(std::vector<int>()), insnTableIndex(tabIndex)
102                 {
103                 }
104
105                 aarch64_mask_entry(unsigned int m, branchMap bm, std::vector<int> tabIndices):
106                 mask(m), nodeBranches(bm), insnTableIndices(tabIndices), insnTableIndex(0)
107                 {
108                 }
109
110                 aarch64_mask_entry():
111                 mask(0), nodeBranches(branchMap()), insnTableIndices(std::vector<int>()), insnTableIndex(0)
112                 {
113                 }
114
115                 aarch64_mask_entry(const aarch64_mask_entry& e):
116                 mask(e.mask), nodeBranches(e.nodeBranches), insnTableIndices(e.insnTableIndices), insnTableIndex(e.insnTableIndex)
117                 {
118                 }
119
120                 const aarch64_mask_entry& operator=(const aarch64_mask_entry& rhs)
121                 {
122                         mask = rhs.mask;
123                         nodeBranches = rhs.nodeBranches;
124                         insnTableIndices = rhs.insnTableIndices;
125             insnTableIndex = rhs.insnTableIndex;
126
127                         return *this;
128                 }
129
130                 unsigned int mask;
131                 branchMap nodeBranches;
132         std::vector<int> insnTableIndices;
133         int insnTableIndex;
134
135                 static void buildDecoderTable();
136                 static bool built_decoder_table;
137                 static bool isAliasWeakSolution;
138                 static aarch64_decoder_table main_decoder_table;
139         };
140
141     InstructionDecoder_aarch64::InstructionDecoder_aarch64(Architecture a)
142       : InstructionDecoderImpl(a), isPstateRead(false), isPstateWritten(false), isFPInsn(false),isSIMDInsn(false),
143         is64Bit(true), isValid(true), insn(0), insn_in_progress(NULL),
144         hasHw(false), hasShift(false), hasOption(false), hasN(false),
145         immr(0), immrLen(0), sField(0), nField(0), nLen(0),
146         immlo(0), immloLen(0), _szField(-1), size(-1),
147         cmode(0), op(0), simdAlphabetImm(0), _Q(1)
148     {
149         aarch64_insn_entry::buildInsnTable();
150         aarch64_mask_entry::buildDecoderTable();
151         InstructionDecoder_aarch64::buildSysRegMap();
152
153         std::string condArray[16] = {"eq","ne","cs","cc","mi","pl","vs","vc","hi","ls","ge","lt","gt","le","al","nv"};
154         InstructionDecoder_aarch64::condStringMap.assign(&condArray[0], &condArray[0] + 16);
155     }
156
157     InstructionDecoder_aarch64::~InstructionDecoder_aarch64()
158     {
159     }
160
161     void InstructionDecoder_aarch64::decodeOpcode(InstructionDecoder::buffer& b)
162     {
163       b.start += 4;
164     }
165
166     using namespace std;
167     Instruction::Ptr InstructionDecoder_aarch64::decode(InstructionDecoder::buffer& b)
168     {
169         if(b.start > b.end)
170             return Instruction::Ptr();
171
172                 isPstateRead = isPstateWritten = false;
173         isFPInsn = false;
174         isSIMDInsn = false;
175         isValid = true;
176         is64Bit = true;
177
178         hasHw = false;
179         hwField = 0;
180
181         hasShift = false;
182         shiftField = 0;
183
184         hasOption = false;
185         optionField = 0;
186
187         hasN = false;
188         sField = nField = nLen = 0;
189         immr = immrLen = 0;
190
191         op1Field = op2Field = crmField = 0;
192
193         immlo = immloLen = 0;
194
195         _szField = size = -1;
196         _Q = 1;
197
198                 cmode = op = simdAlphabetImm = 0;
199
200                 oprRotateAmt = 0;
201                 hasb5 = false;
202
203         insn = b.start[3] << 24 | b.start[2] << 16 |
204         b.start[1] << 8 | b.start[0];
205
206 #if defined(DEBUG_RAW_INSN)
207         cout.width(0);
208         cout << "0x";
209         cout.width(8);
210         cout.fill('0');
211         cout << hex << insn << "\t";
212 #endif
213
214                 mainDecode();
215         b.start += 4;
216
217         return make_shared(insn_in_progress);
218     }
219
220     /* replace this function with a more generic function, which is setRegWidth
221     void InstructionDecoder_aarch64::set32Mode()
222     {
223         // NOTE: is64Bit is set by default.
224                 is64Bit = false;
225     }
226     */
227     void InstructionDecoder_aarch64::NOTHING(){
228     }
229
230     void InstructionDecoder_aarch64::setFPMode()
231     {
232         // NOTE: if it is fp, only isFP is set.
233                 isFPInsn = true;
234     }
235
236      //TODO: consistency issue
237      void InstructionDecoder_aarch64::setSIMDMode()
238     {
239         // NOTE: if it is SIMD insn, both isFP and isSIMD are set.
240                 //isFPInsn = true;
241                 isSIMDInsn = true;
242     }
243
244         template<unsigned int endBit, unsigned int startBit>
245     void InstructionDecoder_aarch64::OPRtype()
246         {
247         _typeField = field<startBit, endBit>(insn);
248     }
249
250     bool InstructionDecoder_aarch64::decodeOperands(const Instruction *)
251     {
252                 return false;
253     }
254
255         void InstructionDecoder_aarch64::processHwFieldInsn(int len, int val)
256         {
257                 Result_Type rT = is64Bit?u64:u32;
258
259                 unsigned int shiftAmount = hwField*16;
260
261                 Expression::Ptr lhs = Immediate::makeImmediate(Result(rT, rT==u32?unsign_extend32(len, val):unsign_extend64(len, val)));
262                 Expression::Ptr rhs = Immediate::makeImmediate(Result(u32, unsign_extend32(6, shiftAmount)));
263
264                 insn_in_progress->appendOperand(makeLeftShiftExpression(lhs, rhs, rT), true, false);
265         }
266
267         void InstructionDecoder_aarch64::processShiftFieldShiftedInsn(int len, int val)
268         {
269                 Result_Type rT;
270                 Expression::Ptr lhs, rhs;
271
272                 rT = is64Bit?u64:u32;
273
274             lhs = makeRmExpr();
275             rhs = Immediate::makeImmediate(Result(u32, unsign_extend32(len, val)));
276
277                 switch(shiftField)                                                                                      //add-sub (shifted) and logical (shifted)
278                 {
279                         case 0:insn_in_progress->appendOperand(makeLeftShiftExpression(lhs, rhs, rT), true, false);
280                                    break;
281                         case 1:insn_in_progress->appendOperand(makeRightLogicalShiftExpression(lhs, rhs, rT), true, false);
282                                    break;
283                         case 2:insn_in_progress->appendOperand(makeRightArithmeticShiftExpression(lhs, rhs, rT), true, false);
284                                    break;
285                         case 3:if(IS_INSN_LOGICAL_SHIFT(insn))                                  //logical (shifted) -- not applicable to add-sub (shifted)
286                                                 insn_in_progress->appendOperand(makeRightRotateExpression(lhs, rhs, rT), true, false);
287                                    else
288                                                 isValid = false;
289                                    break;
290                 }
291         }
292
293         void InstructionDecoder_aarch64::processShiftFieldImmInsn(int len, int val)
294         {
295                 if(shiftField == 0 || shiftField == 1)                                          //add-sub (immediate)
296                 {
297                         Result_Type rT = is64Bit?u64:u32;
298
299                         unsigned int shiftAmount = shiftField * 12;
300
301                         Expression::Ptr lhs = Immediate::makeImmediate(Result(rT, rT==u32?unsign_extend32(len, val):unsign_extend64(len, val)));
302                         Expression::Ptr rhs = Immediate::makeImmediate(Result(u32, unsign_extend32(4, shiftAmount)));
303
304                         insn_in_progress->appendOperand(makeLeftShiftExpression(lhs, rhs, rT), true, false);
305                 }
306                 else
307                 {
308                         isValid = false;
309                 }
310
311         }
312
313         Expression::Ptr InstructionDecoder_aarch64::makeOptionExpression(int len, int val)
314         {
315                 MachRegister reg;
316                 int encoding = field<16, 20>(insn);
317
318                 reg = ((optionField & 0x3) == 0x3)?((encoding == 31)?aarch64::zr:aarch64::x0):((encoding == 31)?aarch64::wzr:aarch64::w0);
319                 if(encoding != 31)
320                         reg = makeAarch64RegID(reg, encoding);
321
322                 Expression::Ptr lhs;
323
324                 switch(optionField)
325                 {
326                         case 0:lhs = makeRegisterExpression(reg, u8);
327                                         break;
328                         case 1:lhs = makeRegisterExpression(reg, u16);
329                                         break;
330                         case 2:lhs = makeRegisterExpression(reg, u32);
331                                         break;
332                         case 3:lhs = makeRegisterExpression(reg, u64);
333                                         break;
334                         case 4:lhs = makeRegisterExpression(reg, s8);
335                                         break;
336                         case 5:lhs = makeRegisterExpression(reg, s16);
337                                         break;
338                         case 6:lhs = makeRegisterExpression(reg, s32);
339                                         break;
340                         case 7:lhs = makeRegisterExpression(reg, s64);
341                                         break;
342                         default: isValid = false;   //invalid option field
343                 }
344
345                 Result_Type rT = is64Bit?(optionField<4?u64:s64):(optionField<4?u32:s32);
346
347                 return makeLeftShiftExpression(lhs, Immediate::makeImmediate(Result(u32, unsign_extend32(len, val))), rT);
348         }
349
350         void InstructionDecoder_aarch64::processOptionFieldLSRegOffsetInsn()
351         {
352                 if(optionField == 0x3)                  //option = LSL
353                 {
354                         int sizeVal = field<30, 31>(insn), extend;
355
356                         if(field<23, 23>(insn) == 1)
357                                 sizeVal = 4;
358
359                         extend = sField * sizeVal;
360                         int extendSize = 31;
361                         while(extendSize >= 0  && ((extend << (31 - extendSize)) & 0x80000000) == 0)
362                                 extendSize--;
363
364                         //above values need to be used in a dereference expression
365                 }
366                 else
367                 {
368                         //sign-extend
369                         switch(optionField)
370                         {
371                                 case 0x2://UXTW
372                                                  break;
373                                 case 0x6://SXTW
374                                                  break;
375                                 case 0x7://SXTX
376                                                  break;
377                                 default:isValid = false;
378                                                 break;
379                         }
380                 }
381         }
382
383         void InstructionDecoder_aarch64::processSystemInsn()
384         {
385                 int op0Field = field<19, 20>(insn), crnField = field<12, 15>(insn);
386
387                 if(op0Field == 0)
388                 {
389                         if(crnField == 3)                       //clrex, dendBit, dmb, iendBit
390                         {
391                                 Expression::Ptr CRm = Immediate::makeImmediate(Result(u8, unsign_extend32(4, crmField)));
392
393                                 insn_in_progress->appendOperand(CRm, true, false);
394                         }
395                         else if(crnField == 2)                    //hint
396                         {
397                                 int immVal = (crmField << 3)|(op2Field & 7);
398
399                                 Expression::Ptr imm = Immediate::makeImmediate(Result(u8, unsign_extend32(7, immVal)));
400
401                                 insn_in_progress->appendOperand(imm, true, false);
402                         }
403                         else if(crnField == 4)                          //msr (immediate)
404                         {
405                                 int pstatefield = (op1Field << 3) | (op2Field & 7);
406                                 insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, unsign_extend32(6, pstatefield))), true, false);
407
408                                 insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, unsign_extend32(4, crmField))), true, false);
409
410                                 isPstateWritten = true;
411                         }
412                         else
413                         {
414                                 isValid = false;
415                         }
416                 }
417                 else if(op0Field == 1)                  //sys, sysl
418                 {
419                         insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, unsign_extend32(3, op1Field))), true, false);
420                         insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, unsign_extend32(4, crnField))), true, false);
421                         insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, unsign_extend32(4, crmField))), true, false);
422                         insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, unsign_extend32(3, op2Field))), true, false);
423
424                         bool isRtRead = (field<21, 21>(insn) == 0);
425                         insn_in_progress->appendOperand(makeRtExpr(), isRtRead, !isRtRead);
426                 }
427                 else                   //mrs (register), msr
428                 {
429                         bool isRtRead = (field<21, 21>(insn) == 0);
430
431                         unsigned int systemRegEncoding = (op0Field << 14) | (op1Field << 11) | (crnField << 7) | (crmField << 3) | op2Field;
432                         if(InstructionDecoder_aarch64::sysRegMap.count(systemRegEncoding) <= 0)
433                                 assert(!"tried to access system register not accessible in EL0");
434
435                         MachRegister reg;
436                         if((op0Field & 0x3) == 0x3 && (crnField & 0x3) == 0x3 && (crnField & 0x8) == 0x8)
437                                 reg = aarch64::IMPLEMENTATION_DEFINED_SYSREG;
438                         else
439                                 reg = InstructionDecoder_aarch64::sysRegMap[systemRegEncoding];
440                         insn_in_progress->appendOperand(makeRegisterExpression(reg), !isRtRead, isRtRead);
441                         insn_in_progress->appendOperand(makeRtExpr(), isRtRead, !isRtRead);
442                         if(!isRtRead)
443                             insn_in_progress->m_Operands.reverse();
444                 }
445         }
446
447     Result_Type InstructionDecoder_aarch64::makeSizeType(unsigned int)
448     {
449         assert(0); //not implemented
450         return u32;
451     }
452
453     // ****************
454     // decoding opcodes
455     // ****************
456
457 #define fn(x) (&InstructionDecoder_aarch64::x)
458 #define COMMA   ,
459
460 MachRegister InstructionDecoder_aarch64::makeAarch64RegID(MachRegister base, unsigned int encoding)
461 {
462     return MachRegister(base.val() + encoding);
463 }
464
465 template<unsigned int endBit, unsigned int startBit>
466 void InstructionDecoder_aarch64::OPRsize()
467 {
468     size = field<startBit, endBit>(insn);
469 }
470
471 Expression::Ptr InstructionDecoder_aarch64::makeRdExpr()
472 {
473     int encoding  = field<0, 4>(insn);
474         MachRegister reg;
475
476     if(isSIMDInsn)
477     {
478         if(IS_INSN_SIMD_ACROSS(insn))
479         {
480                 //fmaxnmv, fmaxv, fminnmv, fminv
481                         if(field<14, 14>(insn) == 0x1)
482                         {
483                                 if(_szField == 0x0)
484                                         reg = aarch64::s0;
485                                 else
486                                         isValid = false;
487                         }
488                         else
489                         {
490                                 int opcode = field<12 ,16>(insn);
491
492                                 //saddlv and uaddlv with opcode field 0x03 use different sets of registers
493                                 switch(size)
494                                 {
495                                         case 0x0:reg = (opcode == 0x03)?aarch64::h0:aarch64::b0;
496                                                          break;
497                                         case 0x1:reg = (opcode == 0x03)?aarch64::s0:aarch64::h0;
498                                                          break;
499                                         case 0x2:reg = (opcode == 0x03)?aarch64::d0:aarch64::s0;
500                                                          break;
501                                         default:isValid = false;
502                                 }
503                 }
504         }
505         else if(IS_INSN_SIMD_COPY(insn))
506         {
507             unsigned int op = field<29, 29>(insn);
508             unsigned int imm4 = field<11, 14>(insn);
509         
510             if(op == 0x1)
511                 reg = aarch64::q0;
512             else
513                 {
514                 switch(imm4)
515                 {
516                     case 0x5:
517                     case 0x7:
518                         reg = _Q == 0x1?aarch64::x0:aarch64::w0;
519                         break;
520                     default:
521                         reg = _Q == 0x1?aarch64::q0:aarch64::d0;
522                         break;
523                 }
524             }
525         }
526                 else if(IS_INSN_SCALAR_COPY(insn) || IS_INSN_SCALAR_SHIFT_IMM(insn))
527                 {
528                         int switchbit;
529
530                         if(IS_INSN_SCALAR_COPY(insn))
531                                 switchbit = lowest_set_bit(field<16, 20>(insn));
532                         else
533                                 switchbit = highest_set_bit(field<19, 22>(insn));
534
535                         switch(switchbit)
536                         {
537                                 case 0x1:reg = aarch64::b0;
538                                          break;
539                                 case 0x2:reg = aarch64::h0;
540                                          break;
541                                 case 0x3:reg = aarch64::s0;
542                                          break;
543                                 case 0x4:reg = aarch64::d0;
544                                          break;
545                                 default:isValid = false;
546                         }
547                 }
548                 else if(IS_INSN_SCALAR_3DIFF(insn))
549                 {
550                         switch(size)
551                         {
552                                 case 0x1:reg = aarch64::s0;
553                                          break;
554                                 case 0x2:reg = aarch64::d0;
555                                          break;
556                                 default:isValid = false;
557                         }
558                 }
559                 else if(IS_INSN_SCALAR_INDEX(insn))
560                 {
561                         int opcode = field<12, 15>(insn);
562
563                         //sqdmlal, sqdmlsl, sqdmull
564                         if((opcode & 0x3) == 0x3)
565                         {
566                                 switch(size)
567                                 {
568                                         case 0x1:reg = aarch64::s0;
569                                                  break;
570                                         case 0x2:reg = aarch64::d0;
571                                                  break;
572                                         default:isValid = false;
573                                 }
574                         }
575                         //sqdmulh, sqrdmulh
576                         else if((opcode & 0xC) == 0xC)
577                         {
578                                 switch(size)
579                                 {
580                                         case 0x1:reg = aarch64::h0;
581                                                  break;
582                                         case 0x2:reg = aarch64::s0;
583                                                  break;
584                                         default:isValid = false;
585                                 }
586                         }
587                         //fmla, fmls, fmul, fmulx
588                         else if((opcode & 0x3) == 0x1)
589                         {
590                                 switch(_szField)
591                                 {
592                                         case 0x0:reg = aarch64::s0;
593                                                  break;
594                                         case 0x1:reg = aarch64::d0;
595                                                  break;
596                                         default:isValid = false;
597                                 }
598                         }
599                         else
600                                 isValid = false;
601                 }
602                 else if(IS_INSN_SCALAR_2REG_MISC(insn) || IS_INSN_SCALAR_3SAME(insn))
603                 {
604                         //some instructions in this set rely on sz for choosing the register and some on size
605                         //only one of them is set for an instruction, however
606                         if(_szField == -1)
607                         {
608                                 switch(size)
609                                 {
610                                         case 0x0:reg = aarch64::b0;
611                                                  break;
612                                         case 0x1:reg = aarch64::h0;
613                                                  break;
614                                         case 0x2:reg = aarch64::s0;
615                                                  break;
616                                         case 0x3:reg = aarch64::d0;
617                                                  break;
618                                         default:isValid = false;
619                                 }
620                         }
621                         else
622                                 {
623                                 switch(_szField)
624                                 {
625                                         case 0x0:reg = aarch64::s0;
626                                                  break;
627                                         case 0x1:
628                                                 {
629                                                         entryID op = insn_in_progress->getOperation().operationID;
630                                                         reg = (op == aarch64_op_fcvtxn_advsimd)?aarch64::s0:aarch64::d0;
631                                                 }
632                                                 break;
633                                         default:isValid = false;
634                                 }
635                         }
636                 }
637                 else if(IS_INSN_SCALAR_PAIR(insn))
638                 {
639                         if(size != -1)
640                         {
641                                 if(size == 0x3)
642                                         reg = aarch64::d0;
643                                 else
644                                         isValid = false;
645                         }
646                         else if(_szField != -1)
647                         {
648                                 switch(_szField)
649                                 {
650                                         case 0x0:reg = aarch64::s0;
651                                                  break;
652                                         case 0x1:reg = aarch64::d0;
653                                                  break;
654                                 }
655                         }
656                         else
657                                 isValid = false;
658                 }
659                 else if(IS_INSN_SIMD_MOD_IMM(insn) && _Q == 0 && op == 1 && cmode == 0xE)
660                 {
661                         reg = aarch64::d0;
662                 }
663                 else if(IS_INSN_SIMD_VEC_INDEX(insn))
664                 {
665                         if(field<13, 13>(insn) == 0x1)
666                                 reg = aarch64::q0;
667                         else
668                                 reg = _Q == 0x1?aarch64::q0:aarch64::d0;
669                 }
670                 else if(IS_INSN_SIMD_3DIFF(insn))
671                 {
672                         entryID op = insn_in_progress->getOperation().operationID;
673
674                         if(op == aarch64_op_addhn_advsimd || op == aarch64_op_subhn_advsimd ||
675                            op == aarch64_op_raddhn_advsimd || op == aarch64_op_rsubhn_advsimd)
676                                 reg = _Q == 0x1?aarch64::hq0:aarch64::d0;
677                         else
678                                 reg = aarch64::q0;
679                 }
680         // 3SAME, 2REG_MISC, EXTRACT
681         else 
682             reg = _Q == 0x1?aarch64::q0:aarch64::d0;
683
684         reg = makeAarch64RegID(reg, encoding);
685     } 
686     else if(isFPInsn && !((IS_INSN_FP_CONV_FIX(insn) || (IS_INSN_FP_CONV_INT(insn))) && !IS_SOURCE_GP(insn)))
687     {
688                 if(IS_INSN_FP_DATAPROC_ONESRC(insn))
689                 {
690                         int opc = field<15, 16>(insn);
691                         switch(opc)
692                         {
693                                 case 0: reg = aarch64::s0;
694                                         break;
695                                 case 1: reg = aarch64::d0;
696                                         break;
697                                 case 3: reg = aarch64::h0;
698                                         break;
699                                 default: isValid = false;
700                         }
701                 }
702                 else
703                         reg = isSinglePrec()?aarch64::s0:aarch64::d0;
704
705                         reg = makeAarch64RegID(reg, encoding);
706         }
707         else
708         {
709             if(encoding == 31)
710                 ((IS_INSN_ADDSUB_IMM(insn) || IS_INSN_ADDSUB_EXT(insn) || IS_INSN_LOGICAL_IMM(insn)) && !isPstateWritten)?(reg = is64Bit?aarch64::sp:aarch64::wsp):(isValid = false);
711             else
712                 reg = is64Bit?aarch64::x0:aarch64::w0;
713
714             if(isValid && encoding != 31)
715                 reg = makeAarch64RegID(reg, encoding);
716         }
717
718         return makeRegisterExpression(reg);
719 }
720
721 void InstructionDecoder_aarch64::OPRRd()
722 {
723     Expression::Ptr reg = makeRdExpr();
724         int cmode = field<12, 15>(insn);
725
726         bool isRdRead = false;
727         if(((IS_INSN_SIMD_VEC_INDEX(insn) || IS_INSN_SCALAR_INDEX(insn)) && !(cmode & 0x8)) ||
728            (IS_INSN_SIMD_MOD_IMM(insn) &&
729                            (((cmode & 0x8) && !(cmode & 0x4) && (cmode & 0x1)) ||
730                                 (!(cmode & 0x8) && (cmode & 0x1)))))
731                 isRdRead = true;
732     //for SIMD/Scalar vector indexed set, some instructions read Rd and some don't. This can be determined from the highest bit of the opcode field (bit 15)
733     insn_in_progress->appendOperand(reg, isRdRead, true);
734 }
735
736 void InstructionDecoder_aarch64::OPRcmode()
737 {
738     cmode = field<12, 15>(insn);
739 }
740
741 void InstructionDecoder_aarch64::OPRop()
742 {
743     op = field<29, 29>(insn);
744 }
745
746 void InstructionDecoder_aarch64::OPRa()
747 {
748     simdAlphabetImm |= (simdAlphabetImm & 0x7F) | (field<18, 18>(insn)<<7);
749 }
750
751 void InstructionDecoder_aarch64::OPRb()
752 {
753     simdAlphabetImm |= (simdAlphabetImm & 0xBF) | (field<17, 17>(insn)<<6);
754 }
755
756 void InstructionDecoder_aarch64::OPRc()
757 {
758     simdAlphabetImm |= (simdAlphabetImm & 0xDF) | (field<16, 16>(insn)<<5);
759 }
760
761 void InstructionDecoder_aarch64::OPRd()
762 {
763     simdAlphabetImm |= (simdAlphabetImm & 0xEF) | (field<9, 9>(insn)<<4);
764 }
765
766 void InstructionDecoder_aarch64::OPRe()
767 {
768     simdAlphabetImm |= (simdAlphabetImm & 0xF7) | (field<8, 8>(insn)<<3);
769 }
770
771 void InstructionDecoder_aarch64::OPRf()
772 {
773     simdAlphabetImm |= (simdAlphabetImm & 0xFB) | (field<7, 7>(insn)<<2);
774 }
775
776 void InstructionDecoder_aarch64::OPRg()
777 {
778     simdAlphabetImm |= (simdAlphabetImm & 0xFD) | (field<6, 6>(insn)<<1);
779 }
780
781 void InstructionDecoder_aarch64::OPRh()
782 {
783     simdAlphabetImm |= (simdAlphabetImm & 0xFE) | (field<5, 5>(insn));
784 }
785
786 void InstructionDecoder_aarch64::OPRlen()
787 {
788     //reuse immlo
789     immlo = field<13, 14>(insn);
790 }
791
792 Expression::Ptr InstructionDecoder_aarch64::makeRnExpr()
793 {
794     int encoding  = field<5, 9>(insn);
795         MachRegister reg;
796
797     if(isSIMDInsn && !IS_INSN_LDST(insn))
798     {
799         if(IS_INSN_SIMD_COPY(insn))
800         {
801             unsigned int op = field<29, 29>(insn);
802             unsigned int imm4 = field<11, 14>(insn);
803             unsigned int imm5 = field<16, 20>(insn);
804
805             //ins (element)
806             if(op == 0x1)
807             {
808                 reg = (imm4 & 0x8)?aarch64::q0:aarch64::d0;
809             }
810             else
811             {
812                 switch(imm4)
813                 {
814                                         //dup (element), smov, umov
815                                         case 0x0:
816                                         case 0x5:
817                                         case 0x7:
818                                                 reg = (imm5 & 0x10)?aarch64::q0:aarch64::d0;
819                                                 break;
820                                         //dup (general), ins (general)
821                                         case 0x1:
822                                         case 0x3:
823                                                 if(imm5 & 0x1 || imm5 & 0x2 || imm5 & 0x4)
824                                                 {
825                                                         reg = encoding==31?aarch64::wzr:aarch64::w0;
826                                                 }
827                                                 else
828                                                 {
829                                                         reg = encoding==31?aarch64::zr:aarch64::x0;
830                                                 }
831                                                 break;
832                                         default:isValid = false;
833                                                         break;
834                                 }
835             }
836         }
837                 else if(IS_INSN_SCALAR_COPY(insn))
838                 {
839                         int imm5 = field<16, 20>(insn);
840
841                         reg = (imm5 & 0x10)?aarch64::q0:aarch64::d0;
842                 }
843                 else if(IS_INSN_SCALAR_PAIR(insn))
844                 {
845                         if(size != -1)
846                         {
847                                 if(size == 0x3)
848                                         reg = aarch64::q0;
849                                 else
850                                         isValid = false;
851                         }
852                         else if(_szField != -1)
853                         {
854                                 switch(_szField)
855                                 {
856                                         case 0x0:reg = aarch64::d0;
857                                                  break;
858                                         case 0x1:reg = aarch64::q0;
859                                                  break;
860                                 }
861                         }
862                         else
863                                 isValid = false;
864                 }
865                 else if(IS_INSN_SCALAR_SHIFT_IMM(insn))
866                 {
867                         int switchbit = highest_set_bit(field<19, 22>(insn));
868                         bool isRnVa = false;
869                         int opcode = field<11, 15>(insn);
870
871                         if((opcode & 0x1C) == 0x10)
872                                 isRnVa = true;
873
874                         switch(switchbit)
875                         {
876                                 case 0x1:reg = isRnVa?aarch64::h0:aarch64::b0;
877                                          break;
878                                 case 0x2:reg = isRnVa?aarch64::s0:aarch64::h0;
879                                          break;
880                                 case 0x3:reg = isRnVa?aarch64::d0:aarch64::s0;
881                                          break;
882                                 case 0x4:isRnVa?(isValid = false):(reg = aarch64::d0);
883                                          break;
884                                 default:isValid = false;
885                         }
886                 }
887                 else if(IS_INSN_SCALAR_3DIFF(insn))
888                 {
889                         switch(size)
890                         {
891                                 case 0x1:reg = aarch64::h0;
892                                          break;
893                                 case 0x2:reg = aarch64::s0;
894                                          break;
895                                 default:isValid = false;
896                         }
897                 }
898                 else if(IS_INSN_SCALAR_INDEX(insn))
899                 {
900                         int opcode = field<12, 15>(insn);
901
902                         //sqdmlal, sqdmlsl, sqdmull
903                         //sqdmulh, sqrdmulh
904                         if((opcode & 0xC) == 0xC || (opcode & 0x3) == 0x3)
905                         {
906                                 switch(size)
907                                 {
908                                         case 0x1:reg = aarch64::h0;
909                                                  break;
910                                         case 0x2:reg = aarch64::s0;
911                                                  break;
912                                         default:isValid = false;
913                                 }
914                         }
915                         //fmla, fmls, fmul, fmulx
916                         else if((opcode & 0x3) == 0x1)
917                         {
918                                 switch(_szField)
919                                 {
920                                         case 0x0:reg = aarch64::s0;
921                                                  break;
922                                         case 0x1:reg = aarch64::d0;
923                                                  break;
924                                         default:isValid = false;
925                                 }
926                         }
927                         else
928                                 isValid = false;
929                 }
930                 else if(IS_INSN_SCALAR_2REG_MISC(insn) || IS_INSN_SCALAR_3SAME(insn))
931                 {
932                         //some instructions in this set rely on sz for choosing the register and some on size
933                         //only one of them is set for an instruction, however
934                         bool isRnVa = false;
935                         int opcode = field<12, 16>(insn);
936                         if(!IS_INSN_SCALAR_3SAME(insn) && (opcode & 0x18) == 0x10 && (opcode & 0x1) == 0x0)
937                                 isRnVa = true;
938
939                         if(_szField == -1)
940                         {
941                                 switch(size)
942                                 {
943                                         case 0x0:reg = isRnVa?aarch64::h0:aarch64::b0;
944                                                  break;
945                                         case 0x1:reg = isRnVa?aarch64::s0:aarch64::h0;
946                                                  break;
947                                         case 0x2:reg = isRnVa?aarch64::d0:aarch64::s0;
948                                                  break;
949                                         case 0x3:isRnVa?(isValid = false):(reg = aarch64::d0);
950                                                  break;
951                                         default:isValid = false;
952                                 }
953                         }
954                         else
955                         {
956                                 switch(_szField)
957                                 {
958                                         case 0x0:isRnVa?(isValid = false):(reg = aarch64::s0);
959                                                  break;
960                                         case 0x1:reg = aarch64::d0;
961                                                  break;
962                                         default:isValid = false;
963                                 }
964                         }
965                 }
966         else if(IS_INSN_SIMD_VEC_INDEX(insn))
967         {
968                         //the below two conditions can easily be combined into one, but would be difficult to understand
969                         if(field<13, 13>(insn) == 0x1)
970                                         reg = _Q == 0x1?aarch64::hq0:aarch64::d0;
971                         else
972                         //sqdmulh, mul, sqrdmulh, fmla, fmls, fmul, mla, mls, fmulx
973                                 reg = _Q == 0x1?aarch64::q0:aarch64::d0;
974         }
975                 else if(IS_INSN_SIMD_TAB_LOOKUP(insn))
976                 {
977                         reg = _Q==1?aarch64::q0:aarch64::d0;
978
979                         for(int reg_index = immlo; reg_index > 0; reg_index--)
980                         {
981                                 insn_in_progress->appendOperand(makeRegisterExpression(makeAarch64RegID(reg, (encoding+reg_index)%32)), true, false);
982                         }
983                 }
984                 else if(IS_INSN_SIMD_3DIFF(insn))
985                 {
986                         entryID op = insn_in_progress->getOperation().operationID;
987
988                         if(op == aarch64_op_saddw_advsimd || op == aarch64_op_ssubw_advsimd ||
989                            op == aarch64_op_addhn_advsimd || op == aarch64_op_subhn_advsimd ||
990                            op == aarch64_op_uaddw_advsimd || op == aarch64_op_usubw_advsimd ||
991                            op == aarch64_op_raddhn_advsimd || op == aarch64_op_rsubhn_advsimd)
992                                 reg = aarch64::q0;
993                         else
994                                 reg = _Q == 0x1?aarch64::hq0:aarch64::d0;
995                 }
996         else
997             reg = _Q == 0x1?aarch64::q0:aarch64::d0;
998                 
999                 if(!(reg == aarch64::wzr || reg == aarch64::zr))
1000                         reg = makeAarch64RegID(reg, encoding);
1001     } 
1002     else if(isFPInsn && !((IS_INSN_FP_CONV_FIX(insn) || (IS_INSN_FP_CONV_INT(insn))) && IS_SOURCE_GP(insn)))
1003     {
1004                 switch(_typeField)
1005                 {
1006                         case 0: reg = aarch64::s0;
1007                                 break;
1008                         case 1: reg = aarch64::d0;
1009                                 break;
1010                         case 3: reg = aarch64::h0;
1011                                 break;
1012                         default: isValid = false;
1013                 }
1014
1015                 reg = makeAarch64RegID(reg, encoding);
1016     }
1017     else if(IS_INSN_LDST(insn))
1018     {
1019         reg = encoding == 31?aarch64::sp:aarch64::x0;
1020
1021                 if(encoding != 31)
1022                 reg = makeAarch64RegID(reg, encoding);
1023     }
1024     else
1025     {
1026         if(encoding == 31)
1027             /*((IS_INSN_ADDSUB_IMM(insn) || IS_INSN_ADDSUB_EXT(insn) || IS_INSN_LOGICAL_IMM(insn)) && !isPstateWritten)?*/(reg = is64Bit?aarch64::sp:aarch64::wsp)/*:(isValid = false)*/;
1028         else
1029             reg = is64Bit?aarch64::x0:aarch64::w0;
1030
1031         if(isValid && encoding != 31)
1032                 reg = makeAarch64RegID(reg, encoding);
1033     }
1034
1035     return makeRegisterExpression(reg);
1036 }
1037
1038 Expression::Ptr InstructionDecoder_aarch64::makePCExpr()
1039 {
1040         MachRegister baseReg = aarch64::pc;
1041
1042         return makeRegisterExpression(makeAarch64RegID(baseReg, 0));
1043 }
1044
1045 Expression::Ptr InstructionDecoder_aarch64::makePstateExpr()
1046 {
1047         MachRegister baseReg = aarch64::pstate;
1048
1049         return makeRegisterExpression(makeAarch64RegID(baseReg, 0));
1050 }
1051
1052
1053 void InstructionDecoder_aarch64::getMemRefIndexLiteral_OffsetLen(int &immVal, int &immLen)
1054 {
1055     immVal = field<5, 23>(insn);
1056     immVal = immVal << 2; //immVal:00
1057     immLen = (23 - 5 + 1) + 2;
1058     return;
1059 }
1060
1061 void InstructionDecoder_aarch64::getMemRefIndexLiteral_RT(Result_Type &rt)
1062 {
1063     int size = field<30, 31>(insn);
1064     switch(size)
1065         {
1066                 case 0x0:
1067                         rt = u32;
1068                         break;
1069                 case 0x1:
1070                         rt = u64;
1071                         break;
1072                 case 0x2:
1073                         rt = s32;
1074                         break;
1075                 case 0x3:
1076                         rt = invalid_type;
1077                         break;
1078                 default:
1079                         rt = invalid_type;
1080                         isValid = false;
1081                         break;
1082         }
1083 }
1084
1085 // ****************************************
1086 // load/store literal
1087 // eg: load Xt, <literal>
1088 // => offset = signextend(<literal>:00, 64)
1089 // load from [PC + offset] to Xt
1090 // ****************************************
1091 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexLiteral()
1092 {
1093     int immVal, immLen;
1094     getMemRefIndexLiteral_OffsetLen(immVal, immLen);
1095
1096     Expression::Ptr label = Immediate::makeImmediate(Result(s64, sign_extend64(immLen, immVal)));
1097
1098     Result_Type rt;
1099     getMemRefIndexLiteral_RT(rt);
1100
1101     return makeDereferenceExpression(makeAddExpression(makePCExpr(), label, u64), rt);
1102 }
1103
1104 // TODO potential bug: do we need to distinguish signed and unsigned here?
1105 // this funciton is to get the mem ref size
1106 // shared by ld/st uimm, post, pre, reg
1107 void InstructionDecoder_aarch64::getMemRefIndex_RT(Result_Type &rt)
1108 {
1109     unsigned int opc1 = field<23, 23>(insn);
1110     unsigned int size = field<30, 31>(insn);
1111
1112     if(opc1 == 1)
1113         {
1114         switch(size)
1115                 {
1116             case 0:
1117                 rt = s8;
1118                 break;
1119             case 1:
1120                 rt = s16;
1121                 break;
1122             case 2:
1123                 rt = s32;
1124                 break;
1125             case 3:
1126                 rt = s64;
1127                 break;
1128             default:
1129                 isValid = false;
1130                 //should only be 2 or 3
1131                 break;
1132         }
1133     }
1134         else
1135         {
1136         switch(size)
1137                 {
1138             case 0:
1139                 rt = u8;
1140                 break;
1141             case 1:
1142                 rt = u16;
1143                 break;
1144             case 2:
1145                 rt = u32;
1146                 break;
1147             case 3:
1148                 rt = u64;
1149                 break;
1150             default:
1151                 isValid = false;
1152                 //should only be 2 or 3
1153                 break;
1154         }
1155     }
1156 }
1157
1158 void InstructionDecoder_aarch64::getMemRefPair_RT(Result_Type &rt)
1159 {
1160         unsigned int isSigned = field<30, 30>(insn);
1161         unsigned int size = field<31, 31>(insn);
1162
1163         // double the width
1164         switch (isSigned)
1165         {
1166                 case 0:
1167                         switch (size)
1168                         {
1169                                 case 0:
1170                                         //rt = u32;
1171                                         rt = u64;
1172                                         break;
1173                                 case 1:
1174                                         //rt = u64;
1175                                         rt = dbl128;
1176                                         break;
1177                                 default:
1178                                         isValid = false;
1179                         }
1180                         break;
1181                 case 1:
1182                         switch (size)
1183                         {
1184                                 case 0:
1185                                         //rt = s32;
1186                                         rt = s64;
1187                                         break;
1188                                 case 1:
1189                                 default:
1190                                         isValid = false;
1191                         }
1192                         break;
1193                 default:
1194                         isValid = false;
1195                         break;
1196         }
1197 }
1198
1199 void InstructionDecoder_aarch64::getMemRefIndex_SizeSizelen(unsigned int &size, unsigned int &sizeLen)
1200 {
1201     size = field<30, 31>(insn);
1202     if(size == 0x0 && field<23, 23>(insn) == 0x1)
1203         size = 4;
1204     sizeLen = 31-30+1+(size/4);
1205     return;
1206 }
1207
1208 void InstructionDecoder_aarch64::getMemRefIndexPrePost_ImmImmlen(unsigned int &immVal, unsigned int &immLen)
1209 {
1210     immVal = field<12, 20>(insn);
1211     immLen = 20 - 12 + 1;
1212     return;
1213 }
1214
1215 void InstructionDecoder_aarch64::getMemRefPair_ImmImmlen(unsigned int &immVal, unsigned int &immLen)
1216 {
1217     immVal = field<15, 21>(insn);
1218     immLen = 21-15 + 1;
1219     return;
1220 }
1221
1222 // ****************************************
1223 // load/store unsigned imm
1224 // eg: load Xt, [Xn, #imm]
1225 // => offset = unsignextend( imm , 64)
1226 // load from [PC + offset] to Xt
1227 // ****************************************
1228 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexUImm()
1229 {
1230     assert( IS_INSN_LDST_UIMM(insn) );
1231
1232     int immVal = field<10, 21>(insn);
1233     int immLen = 21 - 10 + 1;
1234
1235     unsigned int size = 0, sizeLen = 0;
1236     getMemRefIndex_SizeSizelen(size, sizeLen);
1237
1238     Expression::Ptr offset = Immediate::makeImmediate( Result(u64, unsign_extend64( immLen+size, immVal<<size) ) );
1239
1240     Result_Type rt;
1241     getMemRefIndex_RT(rt);
1242     return makeDereferenceExpression( makeAddExpression(makeRnExpr(), offset, u64), rt);
1243 }
1244
1245 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndex_offset9()
1246 {
1247     unsigned int immVal = 0, immLen = 0;
1248     getMemRefIndexPrePost_ImmImmlen(immVal, immLen);
1249     return Immediate::makeImmediate(Result(u32, sign_extend32(immLen, immVal)));
1250 }
1251
1252 // scale = 2 + opc<1>
1253 // scale = 1<<scale
1254 // LSL(sign_ex(imm7 , 64), scale)
1255 Expression::Ptr InstructionDecoder_aarch64::makeMemRefPair_offset7()
1256                 {
1257     /*
1258     unsigned int scaleVal = field<31, 31>(insn);
1259     unsigned int scaleLen = 8;
1260     scaleVal += 2;
1261     Expression::Ptr scale = Immediate::makeImmediate(Result(u32, unsign_extend32(scaleLen, 1<<scaleVal)));
1262     */
1263
1264     unsigned int immVal = 0, immLen = 0;
1265     getMemRefPair_ImmImmlen(immVal, immLen);
1266
1267         Expression::Ptr lhs = Immediate::makeImmediate(Result(s64, sign_extend64(immLen, immVal)));
1268         int scale = 2;
1269         if(isSIMDInsn)
1270                 scale += field<30, 31>(insn);
1271         else
1272                 scale += field<31, 31>(insn);
1273         Expression::Ptr rhs = Immediate::makeImmediate(Result(u8, scale));
1274
1275     //return makeMultiplyExpression(imm7, scale, s64);
1276     return makeLeftShiftExpression(lhs, rhs, s64);
1277 }
1278
1279 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndex_addOffset9()
1280 {
1281     Expression::Ptr offset = makeMemRefIndex_offset9();
1282     return makeAddExpression(makeRnExpr(), offset, u64);
1283 }
1284
1285 Expression::Ptr InstructionDecoder_aarch64::makeMemRefPair_addOffset7()
1286 {
1287     Expression::Ptr offset = makeMemRefPair_offset7();
1288     return makeAddExpression(makeRnExpr(), offset, u64);
1289 }
1290
1291 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexPre()
1292 {
1293     Result_Type rt;
1294     getMemRefIndex_RT(rt);
1295     return makeDereferenceExpression(makeMemRefIndex_addOffset9(), rt);
1296 }
1297
1298 Expression::Ptr InstructionDecoder_aarch64::makeMemRefIndexPost()
1299 {
1300     Result_Type rt;
1301     getMemRefIndex_RT(rt);
1302     return makeDereferenceExpression(makeRnExpr(), rt);
1303 }
1304
1305 Expression::Ptr InstructionDecoder_aarch64::makeMemRefPairPre()
1306 {
1307     Result_Type rt;
1308     getMemRefPair_RT(rt);
1309     return makeDereferenceExpression(makeMemRefPair_addOffset7(), rt);
1310 }
1311
1312 Expression::Ptr InstructionDecoder_aarch64::makeMemRefPairPost()
1313 {
1314     Result_Type rt;
1315     getMemRefPair_RT(rt);
1316     return makeDereferenceExpression(makeRnExpr(), rt);
1317 }
1318
1319 void InstructionDecoder_aarch64::getMemRefEx_RT(Result_Type &rt)
1320 {
1321     unsigned int sz = field<30, 31>(insn);
1322     switch(sz)
1323         {
1324         case 0x00: //B
1325             rt = u8;
1326             break;
1327         case 0x01: //H
1328             rt = u16;
1329             break;
1330         case 0x02: //32b
1331             rt = u32;
1332             break;
1333         case 0x03: //64b
1334             rt = u64;
1335             break;
1336         default:
1337             rt = u64;
1338     }
1339 }
1340
1341 Expression::Ptr InstructionDecoder_aarch64::makeMemRefEx()
1342 {
1343     Result_Type rt;
1344     getMemRefEx_RT(rt);
1345     return makeDereferenceExpression(makeRnExpr(), rt);
1346 }
1347
1348 void InstructionDecoder_aarch64::OPRQ()
1349 {
1350     _Q = field<30, 30>(insn);
1351 }
1352
1353 void InstructionDecoder_aarch64::OPRL()
1354 {
1355     _L = field<30, 30>(insn);
1356 }
1357
1358 unsigned int InstructionDecoder_aarch64::getMemRefSIMD_MULT_T()
1359 {
1360     unsigned int Q = field<30, 30>(insn);
1361     return Q?128:64;
1362 }
1363
1364 void InstructionDecoder_aarch64::getMemRefSIMD_MULT_RT(Result_Type &rt)
1365 {
1366     unsigned int tmpSize = getMemRefSIMD_MULT_T();
1367     unsigned int rpt = 0, selem = 0;
1368     getSIMD_MULT_RptSelem(rpt, selem);
1369     tmpSize = tmpSize * rpt * selem;
1370     switch(tmpSize)
1371         {
1372         case 64:
1373             rt = u64;
1374             return;
1375         case 128:
1376             rt = dbl128;
1377             return;
1378         case 192:
1379             rt = m192;
1380             return;
1381         case 256:
1382             rt = m256;
1383             return;
1384         case 384:
1385             rt = m384;
1386             return;
1387         case 512:
1388             rt = m512;
1389             return;
1390         default:
1391             isValid = false;
1392             return;
1393     }
1394 }
1395
1396 unsigned int InstructionDecoder_aarch64::getSIMD_SING_selem()
1397 {
1398     return ( ((field<13, 13>(insn)<<1)&0x2) | (field<21,21>(insn)&0x1) ) + 0x1;
1399 }
1400
1401 void InstructionDecoder_aarch64::getMemRefSIMD_SING_RT(Result_Type &rt)
1402 {
1403     unsigned int tmpSize = getMemRefSIMD_SING_T();
1404     unsigned int selem = getSIMD_SING_selem();
1405     switch(selem*tmpSize)
1406         {
1407         case 8:
1408             rt = u8;
1409             break;
1410         case 16:
1411             rt = u16;
1412             break;
1413         case 24:
1414             rt = u24;
1415             break;
1416         case 32:
1417             rt = u32;
1418             break;
1419         case 48:
1420             rt = u48;
1421             break;
1422         case 64:
1423             rt = u64;
1424             break;
1425         case 96:
1426             rt = m96;
1427             break;
1428         case 128:
1429             rt = dbl128;
1430             break;
1431         case 192:
1432             rt = m192;
1433             break;
1434         case 256:
1435             rt = m256;
1436             break;
1437         default:
1438             isValid = false;
1439             break;
1440     }
1441 }
1442
1443 unsigned int InstructionDecoder_aarch64::getMemRefSIMD_SING_T()
1444 {
1445     unsigned int opcode = field<14,15>(insn);
1446     unsigned int S = field<12, 12>(insn);
1447     unsigned int size = field<10, 11>(insn);
1448
1449     switch(opcode)
1450     {
1451                 case 0x0:return 8;
1452                 case 0x1:if((size & 0x1) == 0x0)
1453                                  return 16;
1454                          else
1455                                  isValid = false;
1456                          break;
1457                 case 0x2:if(size == 0x0)
1458                                  return 32;
1459                          else if(size == 0x1 && S == 0)
1460                                  return 64;
1461                          else
1462                                  isValid = false;
1463                          break;
1464                 case 0x3:return 8<<size;
1465                 default:isValid = false;
1466     }
1467
1468     return 0;
1469 }
1470
1471 Expression::Ptr InstructionDecoder_aarch64::makeMemRefSIMD_MULT()
1472 {
1473     Result_Type rt;
1474     getMemRefSIMD_MULT_RT(rt);
1475     return makeDereferenceExpression(makeRnExpr(), rt);
1476 }
1477
1478 Expression::Ptr InstructionDecoder_aarch64::makeMemRefSIMD_SING()
1479 {
1480     Result_Type rt;
1481     getMemRefSIMD_SING_RT(rt);
1482     return makeDereferenceExpression(makeRnExpr(), rt);
1483 }
1484
1485 void InstructionDecoder_aarch64::getMemRefExPair_RT(Result_Type &rt)
1486 {
1487     int size = field<30, 30>(insn);
1488     switch(size)
1489         {
1490         case 0:
1491             rt = u64;
1492             break;
1493         case 1:
1494             rt = dbl128;
1495             break;
1496         default:
1497             isValid = false;
1498             break;
1499     }
1500 }
1501
1502 Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair()
1503 {
1504     Result_Type rt;
1505     getMemRefExPair_RT(rt);
1506     return makeDereferenceExpression(makeRnExpr(), rt);
1507 }
1508
1509 /*
1510 Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair16B(){
1511     return makeDereferenceExpression(makeRnExpr(), dbl128);
1512 }
1513 */
1514
1515 /*
1516 Expression::Ptr InstructionDecoder_aarch64::makeMemRefExPair2(){
1517     unsigned int immLen = 4, immVal = 8;
1518     Expression::Ptr offset = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));
1519     return makeDereferenceExpression(makeAddExpression(makeRnExpr(), offset, u64) , u64);
1520 }
1521 */
1522
1523 Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_Rm()
1524 {
1525     unsigned int option = field<13, 15>(insn);
1526     if((option&2) != 2)
1527         isValid = false;
1528     MachRegister baseReg = ((option & 0x3)==0x2) ? aarch64::w0 : aarch64::x0;
1529     unsigned int encoding = field<16, 20>(insn);
1530
1531         if( encoding == 31 )//zero register
1532                 return makeRegisterExpression(makeAarch64RegID(aarch64::zr, 0));
1533     else
1534         return makeRegisterExpression(makeAarch64RegID(baseReg, encoding));
1535 }
1536
1537 Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_amount()
1538 {
1539     unsigned int S =  field<12, 12>(insn);
1540     unsigned int amountVal = is64Bit?(S==0?0:2):(S==0?0:3);
1541     unsigned int amountLen = 2;
1542
1543     return Immediate::makeImmediate(Result(u32, unsign_extend32(amountLen, amountVal)) ) ;
1544 }
1545
1546 Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg_ext()
1547 {
1548     int immLen = 2;
1549     int immVal = 0; //for amount
1550
1551     int S = field<12,12>(insn);
1552     int size = field<30,31>(insn);
1553
1554     if( size == 2 )
1555         { //32bit
1556         immVal = S==0?0:(S==1?2:-1);
1557         if( immVal==-1 )
1558                 isValid = false;
1559     }
1560         else if( size == 3 )
1561         { //64bit
1562         immVal = S==0?0:(S==1?3:-1);
1563         if( immVal==-1)
1564                 isValid = false;
1565     }
1566
1567     Expression::Ptr ext = makeOptionExpression(immLen, immVal);
1568
1569     return ext; /*extended ptr*/
1570 }
1571
1572 /**********************
1573 // ld/st reg memReg AST:
1574 //    memRef
1575 //      |
1576 //     ADD
1577 //    /    \
1578 //  [Rn]   EXT
1579 //        /   \
1580 //      [Rm] [amount]
1581 **********************/
1582 Expression::Ptr InstructionDecoder_aarch64::makeMemRefReg()
1583 {
1584     Expression::Ptr ext = makeMemRefReg_ext();
1585     Expression::Ptr xn = makeRnExpr();
1586     Expression::Ptr add = makeAddExpression(xn, ext, u64);
1587
1588     Result_Type rt;
1589     getMemRefIndex_RT(rt);
1590     return makeDereferenceExpression(add,rt);
1591 }
1592
1593 void InstructionDecoder_aarch64::LIndex()
1594 {
1595     // never be called
1596     if( IS_INSN_LD_LITERAL(insn))
1597         {
1598         insn_in_progress->appendOperand(makeMemRefIndexLiteral(), true, false);
1599     }
1600     // ******************
1601     // load register offset
1602     // ******************
1603     else if( IS_INSN_LDST_REG(insn))
1604         {
1605         insn_in_progress->appendOperand(makeMemRefReg(), true, false);
1606     }
1607     // ******************
1608     // load unsigned imm
1609     // ******************
1610     else if( IS_INSN_LDST_UIMM(insn))
1611         {
1612         insn_in_progress->appendOperand(makeMemRefIndexUImm(), true, false);
1613     }
1614     // ******************
1615     // load pre, unscaled and unprivlidged
1616     // ******************
1617     else if( IS_INSN_LDST_PRE(insn)
1618         || IS_INSN_LDST_UNPRIV(insn)
1619         || IS_INSN_LDST_UNSCALED(insn) )
1620         {
1621         insn_in_progress->appendOperand(makeMemRefIndexPre(), true, false);
1622     }
1623     else if( IS_INSN_LDST_POST(insn) )
1624         {
1625         insn_in_progress->appendOperand(makeMemRefIndexPost(), true, false);
1626     }
1627     // ****************************
1628     // load PAIR pre, post, offset
1629     // ****************************
1630     else if( IS_INSN_LDST_PAIR_PRE(insn)
1631         || IS_INSN_LDST_PAIR_NOALLOC(insn) )
1632         {
1633         insn_in_progress->appendOperand( makeMemRefPairPre(), true, false);
1634     }
1635     else if( IS_INSN_LDST_PAIR_POST(insn)
1636         || IS_INSN_LDST_PAIR_OFFSET(insn) )
1637         {
1638         insn_in_progress->appendOperand( makeMemRefPairPost(), true, false);
1639     }
1640     // ****************************
1641     // load exclusive instructions
1642     // ****************************
1643     else if( IS_INSN_LDST_EX(insn) )
1644         {
1645         if( !IS_INSN_LDST_EX_PAIR(insn) )
1646                 { // Rt2 field == 31, non-pair op
1647             insn_in_progress->appendOperand( makeMemRefEx(), true, false);
1648         }
1649                 else
1650                 { // pair
1651             insn_in_progress->appendOperand( makeMemRefExPair(), true, false);
1652         }
1653     }
1654     // ****************************
1655     // load SIMD multiple structures &
1656     // load SIMD multiple structures post increment
1657     // ****************************
1658     else if( IS_INSN_LDST_SIMD_MULT(insn)
1659             || IS_INSN_LDST_SIMD_MULT_POST(insn) )
1660         {
1661         insn_in_progress->appendOperand( makeMemRefSIMD_MULT(), true, false);
1662     }
1663     // ****************************
1664     // load SIMD single structure &
1665     // load SIMD single structure post increment
1666     // ****************************
1667     else if( IS_INSN_LDST_SIMD_SING(insn)
1668             || IS_INSN_LDST_SIMD_SING_POST(insn) )
1669         {
1670         insn_in_progress->appendOperand( makeMemRefSIMD_SING(), true, false);
1671     }
1672         else
1673                 assert(0);
1674 }
1675
1676 void InstructionDecoder_aarch64::STIndex()
1677 {
1678     if( IS_INSN_LD_LITERAL(insn))
1679         assert(0); // only load literal, no store literal
1680     // ******************
1681     // ld/st register offset
1682     // ******************
1683     else if( IS_INSN_LDST_REG(insn))
1684         {
1685         insn_in_progress->appendOperand( makeMemRefReg(), false, true);
1686     }
1687     else if( IS_INSN_LDST_UIMM(insn))
1688         {
1689         insn_in_progress->appendOperand( makeMemRefIndexUImm(), false, true);
1690     }
1691     // ******************
1692     // ld/st pre and post, unscaled and unprivilidged
1693     // ******************
1694     else if( IS_INSN_LDST_PRE(insn)
1695         || IS_INSN_LDST_UNPRIV(insn)
1696         || IS_INSN_LDST_UNSCALED(insn) )
1697         {
1698         insn_in_progress->appendOperand( makeMemRefIndexPre(), false, true);
1699     }
1700     else if( IS_INSN_LDST_POST(insn) )
1701         {
1702         insn_in_progress->appendOperand( makeMemRefIndexPost(), false, true);
1703     }
1704     // ****************************
1705     // ld/st PAIR pre, post, offset
1706     // ****************************
1707     else if( IS_INSN_LDST_PAIR_PRE(insn)
1708         || IS_INSN_LDST_PAIR_NOALLOC(insn) )
1709         {
1710         insn_in_progress->appendOperand( makeMemRefPairPre(), false, true);
1711     }
1712     else if( IS_INSN_LDST_PAIR_POST(insn)
1713         || IS_INSN_LDST_PAIR_OFFSET(insn))
1714         {
1715         insn_in_progress->appendOperand( makeMemRefPairPost(), false, true);
1716     }
1717     // ****************************
1718     // ld/st exclusive instructions
1719     // ****************************
1720     else if( IS_INSN_LDST_EX(insn) )
1721         {
1722         if( !IS_INSN_LDST_EX_PAIR(insn) )
1723                 { // Rt2 field == 31, non-pair op
1724             insn_in_progress->appendOperand( makeMemRefEx(), false, true);
1725         }
1726                 else
1727                 { // pair
1728             insn_in_progress->appendOperand( makeMemRefExPair(), false, true);
1729         }
1730     }
1731     // ****************************
1732     // store SIMD multiple structures &
1733     // store SIMD multiple structures post increment
1734     // ****************************
1735     else if( IS_INSN_LDST_SIMD_MULT(insn)
1736             ||IS_INSN_LDST_SIMD_MULT_POST(insn) )
1737         {
1738         insn_in_progress->appendOperand( makeMemRefSIMD_MULT(), false, true);
1739     }
1740     else if( IS_INSN_LDST_SIMD_SING(insn)
1741             ||IS_INSN_LDST_SIMD_SING_POST(insn) )
1742         {
1743         insn_in_progress->appendOperand( makeMemRefSIMD_SING(), false, true);
1744     }
1745         else
1746         assert(0); //un-handled case
1747
1748 }
1749
1750 // This function is for non-writeback
1751 void InstructionDecoder_aarch64::OPRRn()
1752 {
1753         if(IS_INSN_B_UNCOND_REG(insn))                                                                          //unconditional branch (register)
1754         {
1755                 int branchType = field<21, 22>(insn);
1756
1757                 insn_in_progress->appendOperand(makePCExpr(), false, true);
1758                 insn_in_progress->addSuccessor(makeRnExpr(), field<21, 21>(insn) == 1, true, false, false);
1759
1760                 if(branchType == 0x1)
1761                 {
1762                         insn_in_progress->addSuccessor(makeFallThroughExpr(), false, false, false, true);
1763                 }
1764         }
1765         else
1766                 insn_in_progress->appendOperand(makeRnExpr(), true, false);
1767 }
1768
1769 void InstructionDecoder_aarch64::OPRRnL()
1770 {
1771     LIndex();
1772 }
1773
1774 void InstructionDecoder_aarch64::OPRRnS()
1775 {
1776     STIndex();
1777 }
1778
1779 void InstructionDecoder_aarch64::OPRRnU()
1780 {
1781     assert(0);
1782     /* this functions is useless
1783         insn_in_progress->appendOperand(makeRnExpr(), true, true);
1784     */
1785 }
1786
1787 void InstructionDecoder_aarch64::OPRRnLU()
1788 {
1789         if(IS_INSN_LDST_PRE(insn) || IS_INSN_LDST_POST(insn) || IS_INSN_LDST_PAIR_PRE(insn) || IS_INSN_LDST_PAIR_POST(insn))
1790                 LIndex();
1791 }
1792
1793 void InstructionDecoder_aarch64::OPRRnSU()
1794 {
1795         if(IS_INSN_LDST_PRE(insn) || IS_INSN_LDST_POST(insn) || IS_INSN_LDST_PAIR_PRE(insn) || IS_INSN_LDST_PAIR_POST(insn))
1796                 STIndex();
1797 }
1798
1799 unsigned int InstructionDecoder_aarch64::get_SIMD_MULT_POST_imm(){
1800     unsigned int rpt = 0, selem = 0;
1801     getSIMD_MULT_RptSelem(rpt, selem);
1802     unsigned int numReg = rpt*selem;
1803     return _Q == 0x1?numReg<<4:numReg<<3;
1804 }
1805
1806 unsigned int InstructionDecoder_aarch64::get_SIMD_SING_POST_imm()
1807 {
1808     return (getMemRefSIMD_SING_T()>>3)*getSIMD_SING_selem();
1809 }
1810
1811 Expression::Ptr InstructionDecoder_aarch64::makeRmExpr()
1812 {
1813     int encoding  = field<16, 20>(insn);
1814     MachRegister reg;
1815
1816     if(isSIMDInsn)
1817     {
1818         if(IS_INSN_LDST_SIMD_MULT_POST(insn))
1819         {
1820             if(encoding == 31)
1821             {
1822                 unsigned int immVal = get_SIMD_MULT_POST_imm();
1823                 unsigned int immLen = 8;
1824                 
1825                 return Immediate::makeImmediate( Result(u32, unsign_extend32(immLen, immVal)) );
1826             }
1827             else
1828                 reg = aarch64::x0;
1829         }
1830         else if(IS_INSN_LDST_SIMD_SING_POST(insn))
1831         {
1832             if(encoding == 31)
1833             {
1834                 unsigned int immVal = get_SIMD_SING_POST_imm();
1835                 unsigned int immLen = 8;
1836
1837                 return Immediate::makeImmediate( Result(u32, unsign_extend32(immLen, immVal) ) );
1838             }
1839             else
1840                 reg = aarch64::x0;
1841         }
1842         else if(IS_INSN_SIMD_VEC_INDEX(insn) || IS_INSN_SCALAR_INDEX(insn))
1843         {
1844             reg = field<11, 11>(insn)==0x1?aarch64::q0:aarch64::d0;
1845
1846                         if(size == 0x0 || size == 0x3)
1847                                 isValid = false;
1848                         else if(size == 0x1)
1849                                 encoding = encoding & 0xF;
1850         }
1851         else if(IS_INSN_SCALAR_3DIFF(insn))
1852         {
1853             switch(size)
1854             {
1855                 case 0x1:reg = aarch64::h0;
1856                          break;
1857                 case 0x2:reg = aarch64::s0;
1858                          break;
1859                 default:isValid = false;
1860             }
1861         }
1862         else if(IS_INSN_SIMD_3DIFF(insn))
1863         {
1864             entryID op = insn_in_progress->getOperation().operationID;
1865
1866             if(op == aarch64_op_addhn_advsimd || op == aarch64_op_subhn_advsimd ||
1867                op == aarch64_op_raddhn_advsimd || op == aarch64_op_rsubhn_advsimd)
1868                 reg = aarch64::q0;
1869             else
1870                 reg = _Q == 0x1?aarch64::hq0:aarch64::d0;
1871         }
1872                 else if(IS_INSN_SCALAR_3SAME(insn))
1873                 {
1874                         if(size != -1)
1875                         {
1876                                 switch(size)
1877                                 {
1878                                         case 0x0:reg = aarch64::b0;
1879                                                          break;
1880                                         case 0x1:reg = aarch64::h0;
1881                                                          break;
1882                                         case 0x2:reg = aarch64::s0;
1883                                                          break;
1884                                         case 0x3:reg = aarch64::d0;
1885                                                          break;
1886                                         default:isValid = false;
1887                                 }
1888                         }
1889                         else if(_szField != -1)
1890                         {
1891                                 switch(_szField)
1892                                 {
1893                                         case 0x0:reg = aarch64::s0;
1894                                                          break;
1895                                         case 0x1:reg = aarch64::d0;
1896                                                          break;
1897                                         default:isValid = false;
1898                                 }
1899                         }
1900                         else
1901                                 isValid = false;
1902                 }
1903         else
1904             reg = _Q == 0x1?aarch64::q0:aarch64::d0;
1905         
1906         reg = makeAarch64RegID(reg, encoding);
1907     
1908         return makeRegisterExpression(reg);
1909     }
1910     else if(isFPInsn)
1911     {
1912         reg = isSinglePrec()?aarch64::s0:aarch64::d0;
1913         reg = makeAarch64RegID(reg, encoding);
1914     }
1915     else
1916     {
1917         reg = is64Bit?((encoding == 31)?aarch64::zr:aarch64::x0):((encoding == 31)?aarch64::wzr:aarch64::w0);
1918         if(encoding != 31)
1919             reg = makeAarch64RegID(reg, encoding);
1920     }
1921
1922     return makeRegisterExpression(reg);
1923 }
1924
1925 void InstructionDecoder_aarch64::OPRRm()
1926 {
1927         if(IS_INSN_LDST_REG(insn) ||
1928            IS_INSN_ADDSUB_EXT(insn) ||
1929            IS_INSN_ADDSUB_SHIFT(insn) ||
1930            IS_INSN_LOGICAL_SHIFT(insn))
1931                 return;
1932
1933         if(IS_INSN_FP_COMPARE(insn) && field<3, 3>(insn) == 1)
1934                 insn_in_progress->appendOperand(Immediate::makeImmediate(Result(isSinglePrec()?sp_float:dp_float, 0.0)), true, false);
1935         else
1936                 insn_in_progress->appendOperand(makeRmExpr(), true, false);
1937 }
1938
1939 void InstructionDecoder_aarch64::OPRsf()
1940 {
1941         if(field<31, 31>(insn) == 0)
1942                 is64Bit = false;
1943 }
1944
1945 template<unsigned int endBit, unsigned int startBit>
1946 void InstructionDecoder_aarch64::OPRoption()
1947 {
1948         hasOption = true;
1949         optionField = field<startBit, endBit>(insn);
1950 }
1951
1952 void InstructionDecoder_aarch64::OPRshift()
1953 {
1954         hasShift = true;
1955         shiftField = field<22, 23>(insn);
1956 }
1957
1958 void InstructionDecoder_aarch64::OPRhw()
1959 {
1960         hasHw = true;
1961         hwField = field<21, 22>(insn);
1962 }
1963
1964 template<unsigned int endBit, unsigned int startBit>
1965 void InstructionDecoder_aarch64::OPRN()
1966 {
1967         hasN = true;
1968         nField = field<startBit, endBit>(insn);
1969         nLen = endBit - startBit + 1;
1970 }
1971
1972 // the call of this function should be generated by decoder gen for ld/st class
1973 // except for ld/st{s, h, w} subclass
1974 void InstructionDecoder_aarch64::setRegWidth(){
1975     //is64Bit is by default set to TRUE
1976     unsigned int opc = 0x3 & field<22, 23>(insn);
1977     unsigned int opc0 = opc & 0x1;
1978     unsigned int opc1 = (opc & 0x2)>>1;
1979     unsigned int sz  = 0x3 & field<30, 31>(insn);
1980
1981     if(IS_INSN_LDST(insn)){
1982         if(   IS_INSN_LDST_UIMM(insn)   || IS_INSN_LDST_UNSCALED(insn)
1983                 || IS_INSN_LDST_UNPRIV(insn) || IS_INSN_LDST_POST(insn)
1984                 || IS_INSN_LDST_PRE(insn)    || IS_INSN_LDST_REG(insn)){
1985                 if(opc1 == 0){
1986                     if(field<30, 31>(insn) != 3)
1987                         is64Bit = false;
1988                     return;
1989                 }else{
1990                     if( sz == 3){
1991                         if( opc0 == 1)
1992                             isValid = false;
1993                     }
1994                     else{
1995                         if(sz == 2 && opc0 == 1)
1996                             isValid = false;
1997                         if(opc0 == 1)
1998                             is64Bit = false;        
1999                     }
2000                     return;
2001                 }
2002         }
2003         else if(IS_INSN_LDST_EX(insn)){
2004             switch(sz){
2005                 case 2:
2006                 case 0:
2007                 case 1:
2008                     is64Bit = false;
2009                     break;
2010                 case 3:
2011                 default:
2012                     return;
2013             }
2014         }
2015         else if(IS_INSN_LDST_PAIR(insn)){
2016             switch(sz){
2017                 case 0:
2018                     is64Bit = false;
2019                     break;
2020                 case 1:
2021                 case 2:
2022                 case 3:
2023                 default:
2024                     return;
2025             }
2026         }
2027         else if(IS_INSN_LD_LITERAL(insn)){
2028             switch(sz){
2029                 case 0:
2030                     is64Bit = false;
2031                 case 1:
2032                 case 2:
2033                 case 3:
2034                 default:
2035                     return;
2036             }
2037         }
2038         else{
2039             isValid = false;
2040         }
2041     }else{
2042         isValid = false;
2043     }
2044     return;
2045 }
2046
2047 MachRegister InstructionDecoder_aarch64::getLoadStoreSimdRegister(int encoding)
2048 {
2049     MachRegister reg;
2050
2051     if(size != -1)
2052     {
2053         switch(size)
2054         {
2055             case 0x0:reg = (field<23, 23>(insn) == 0x1)?aarch64::q0:aarch64::b0;
2056                      break;
2057             case 0x1:reg = aarch64::h0;
2058                      break;
2059             case 0x2:reg = aarch64::s0;
2060                      break;
2061             case 0x3:reg = aarch64::d0;
2062                      break;
2063         }           
2064     }
2065     else
2066     {
2067         switch(field<30, 31>(insn))
2068         {
2069             case 0x0:reg = aarch64::s0;
2070                      break;
2071             case 0x1:reg = aarch64::d0;
2072                      break;
2073             case 0x2:reg = aarch64::q0;
2074                      break;
2075             case 0x3:isValid = false;
2076                      break;
2077         }
2078     }
2079
2080     return makeAarch64RegID(reg, encoding);
2081 }
2082
2083 Expression::Ptr InstructionDecoder_aarch64::makeRtExpr()
2084 {
2085         int encoding  = field<0, 4>(insn);
2086         MachRegister reg;
2087
2088         if(isFPInsn)
2089         {
2090             reg = makeAarch64RegID(isSinglePrec()?aarch64::s0:aarch64::d0, encoding);
2091         }
2092         else if(isSIMDInsn)
2093         {
2094             reg = getLoadStoreSimdRegister(encoding);
2095         }
2096         else
2097         {
2098             reg = is64Bit?((encoding == 31)?aarch64::zr:aarch64::x0):((encoding == 31)?aarch64::wzr:aarch64::w0);
2099             if(encoding != 31)
2100                 reg = makeAarch64RegID(reg, encoding);
2101         }
2102
2103         return makeRegisterExpression(reg);
2104 }
2105
2106 void InstructionDecoder_aarch64::getSIMD_MULT_RptSelem(unsigned int &rpt, unsigned int &selem){
2107     unsigned opcode = field<12, 15>(insn);
2108     switch(opcode){
2109         case 0x0:
2110             rpt = 1; selem = 4;
2111             break;
2112         case 0x2:
2113             rpt = 4; selem = 1;
2114             break;
2115         case 0x4:
2116             rpt = 1; selem = 3;
2117             break;
2118         case 0x6:
2119             rpt = 3; selem = 1;
2120             break;
2121         case 0x7:
2122             rpt = 1; selem = 1;
2123             break;
2124         case 0x8:
2125             rpt = 1; selem = 2;
2126             break;
2127         case 0xa:
2128             rpt = 2; selem = 1;
2129             break;
2130         default:
2131             isValid = false;
2132             return;
2133     }
2134     if(rpt==0 || selem==0)
2135         isValid = false;
2136     return;
2137 }
2138
2139 void InstructionDecoder_aarch64::OPRRt()
2140 {
2141         int encoding = field<0, 4>(insn);
2142         entryID op = insn_in_progress->getOperation().operationID;
2143
2144         if(IS_INSN_BRANCHING(insn))
2145         {
2146                 if(encoding == 31)
2147                         insn_in_progress->appendOperand(makeRegisterExpression(is64Bit?aarch64::zr:aarch64::wzr), true, false);
2148                 else
2149                         insn_in_progress->appendOperand(makeRegisterExpression(makeAarch64RegID(is64Bit?aarch64::x0:aarch64::w0, encoding)), true, false);
2150         }
2151         else if(op == aarch64_op_prfm_imm || op == aarch64_op_prfm_lit || op == aarch64_op_prfm_reg)
2152         {
2153             Expression::Ptr prfop = Immediate::makeImmediate(Result(u32, unsign_extend32(5, encoding)));
2154             insn_in_progress->appendOperand(prfop, true, false);
2155         }
2156 }
2157
2158 void InstructionDecoder_aarch64::OPRRtL()
2159 {
2160     int encoding = field<0, 4>(insn);
2161
2162     if(IS_INSN_LDST_SIMD_MULT(insn) || IS_INSN_LDST_SIMD_MULT_POST(insn))
2163     {
2164         unsigned int rpt, selem;
2165         getSIMD_MULT_RptSelem(rpt, selem);
2166         MachRegister reg = _Q == 0x1?aarch64::q0:aarch64::d0;
2167         for(int it_rpt = rpt*selem - 1; it_rpt >= 0; it_rpt--){
2168                         insn_in_progress->appendOperand(makeRegisterExpression(makeAarch64RegID(reg, (encoding + it_rpt)%32 )), false, true);
2169         }
2170     }
2171     else if(IS_INSN_LDST_SIMD_SING(insn) || IS_INSN_LDST_SIMD_SING_POST(insn))
2172     {
2173         unsigned int selem =  getSIMD_SING_selem();
2174
2175         MachRegister reg = _Q == 0x1?aarch64::q0:aarch64::d0;
2176
2177         for(int it_selem = selem - 1; it_selem >= 0; it_selem--)
2178         {
2179                         insn_in_progress->appendOperand(makeRegisterExpression(makeAarch64RegID(reg, (encoding + it_selem)%32 )), false, true);
2180         }
2181     }
2182     else
2183             insn_in_progress->appendOperand(makeRtExpr(), false, true);
2184 }
2185
2186 void InstructionDecoder_aarch64::OPRRtS()
2187 {
2188     int encoding = field<0, 4>(insn);
2189
2190     if( IS_INSN_LDST_SIMD_MULT(insn) || IS_INSN_LDST_SIMD_MULT_POST(insn) ){
2191         unsigned int rpt, selem;
2192         getSIMD_MULT_RptSelem(rpt, selem);
2193         
2194         MachRegister reg = _Q == 0x1?aarch64::q0:aarch64::d0;
2195
2196         for(int it_rpt = rpt*selem-1; it_rpt >= 0; it_rpt--){
2197                         insn_in_progress->appendOperand(makeRegisterExpression(makeAarch64RegID(reg, (encoding + it_rpt)%32 )), true, false);
2198         }
2199     }
2200     else if(IS_INSN_LDST_SIMD_SING(insn) || IS_INSN_LDST_SIMD_SING_POST(insn))
2201     {
2202         unsigned int selem =  getSIMD_SING_selem();
2203
2204         MachRegister reg = _Q == 0x1?aarch64::q0:aarch64::d0;
2205
2206         for(int it_selem = selem - 1; it_selem >= 0; it_selem--){
2207                         insn_in_progress->appendOperand(makeRegisterExpression(makeAarch64RegID(reg, (encoding + it_selem)%32 )), true, false);
2208         }
2209     }
2210     else
2211             insn_in_progress->appendOperand(makeRtExpr(), true, false);
2212 }
2213
2214 Expression::Ptr InstructionDecoder_aarch64::makeRt2Expr()
2215 {
2216     MachRegister baseReg;
2217     int encoding = field<10, 14>(insn);
2218
2219     if(isFPInsn)
2220     {
2221         baseReg = makeAarch64RegID(isSinglePrec()?aarch64::s0:aarch64::d0, encoding);
2222     }
2223     else if(isSIMDInsn)
2224     {
2225         baseReg = getLoadStoreSimdRegister(encoding);
2226     }
2227     else
2228     {
2229         baseReg = makeAarch64RegID(is64Bit?aarch64::x0:aarch64::w0, encoding);
2230     }
2231
2232     return makeRegisterExpression(baseReg);
2233 }
2234
2235 void InstructionDecoder_aarch64::OPRRt2()
2236 {
2237     assert(0);
2238 }
2239
2240 void InstructionDecoder_aarch64::OPRRt2L()
2241 {
2242         insn_in_progress->appendOperand(makeRt2Expr(), false, true);
2243 }
2244
2245 void InstructionDecoder_aarch64::OPRRt2S()
2246 {
2247         insn_in_progress->appendOperand(makeRt2Expr(), true, false);
2248 }
2249
2250 template<unsigned int endBit, unsigned int startBit>
2251 void InstructionDecoder_aarch64::OPRcond()
2252 {
2253         unsigned char condVal = static_cast<unsigned char>(field<startBit, endBit>(insn));
2254         if(IS_INSN_B_COND(insn))
2255         {
2256                 insn_in_progress->getOperation().mnemonic += ".";
2257                 insn_in_progress->getOperation().mnemonic += condStringMap[condVal];
2258         }
2259         else
2260         {
2261                 Expression::Ptr cond = Immediate::makeImmediate(Result(u8, condVal));
2262                 insn_in_progress->appendOperand(cond, true, false);
2263                 oprRotateAmt++;
2264         }
2265
2266         isPstateRead = true;
2267 }
2268
2269 void InstructionDecoder_aarch64::OPRnzcv()
2270 {
2271         unsigned int nzcvVal = field<0, 3>(insn)<<28;
2272         Expression::Ptr nzcv = Immediate::makeImmediate(Result(u32, nzcvVal));
2273         insn_in_progress->appendOperand(nzcv, true, false);
2274
2275         isPstateWritten = true;
2276         oprRotateAmt++;
2277 }
2278
2279 void InstructionDecoder_aarch64::OPRop1()
2280 {
2281         op1Field = field<16, 18>(insn);
2282 }
2283
2284 void InstructionDecoder_aarch64::OPRop2()
2285 {
2286         op2Field = field<5, 7>(insn);
2287 }
2288
2289 void InstructionDecoder_aarch64::OPRCRm()
2290 {
2291         crmField = field<8 ,11>(insn);
2292 }
2293
2294 void InstructionDecoder_aarch64::OPRCRn()
2295 {
2296 }
2297
2298 template<unsigned int endBit, unsigned int startBit>
2299 void InstructionDecoder_aarch64::OPRS()
2300 {
2301         sField = field<startBit, endBit>(insn);
2302 }
2303
2304 void InstructionDecoder_aarch64::OPRscale()
2305 {
2306         int scaleVal = 64 - field<10, 15>(insn);
2307
2308         Expression::Ptr scale = Immediate::makeImmediate(Result(u32, unsign_extend32(6, scaleVal)));
2309         insn_in_progress->appendOperand(scale, true, false);
2310 }
2311
2312 Expression::Ptr InstructionDecoder_aarch64::makeRaExpr()
2313 {
2314         int encoding  = field<10, 14>(insn);
2315         MachRegister reg;
2316
2317         if(isFPInsn)
2318         {
2319                 reg = makeAarch64RegID(isSinglePrec()?aarch64::s0:aarch64::d0, encoding);
2320         }
2321         else
2322         {
2323                 reg = is64Bit?((encoding == 31)?aarch64::sp:aarch64::x0):((encoding == 31)?aarch64::wsp:aarch64::w0);
2324                 if(encoding != 31)
2325                         reg = makeAarch64RegID(reg, encoding);
2326         }
2327
2328         return makeRegisterExpression(reg);
2329
2330 }
2331
2332 void InstructionDecoder_aarch64::OPRRa()
2333 {
2334         insn_in_progress->appendOperand(makeRaExpr(), true, false);
2335
2336         oprRotateAmt++;
2337 }
2338
2339 void InstructionDecoder_aarch64::OPRo0()
2340 {
2341
2342 }
2343
2344 void InstructionDecoder_aarch64::OPRb5()
2345 {
2346         OPRsf();
2347         hasb5 = true;
2348 }
2349
2350 void InstructionDecoder_aarch64::OPRb40()
2351 {
2352
2353 }
2354
2355 Expression::Ptr InstructionDecoder_aarch64::makeb40Expr()
2356 {
2357         int b40Val = field<19, 23>(insn);
2358         int bitpos = ((is64Bit?1:0)<<5) | b40Val;
2359
2360         return Immediate::makeImmediate(Result(u32, unsign_extend32(6, bitpos)));
2361 }
2362
2363 template<unsigned int endBit, unsigned int startBit>
2364 void InstructionDecoder_aarch64::OPRsz()
2365 {
2366     _szField = field<startBit, endBit>(insn);
2367 }
2368
2369 bool InstructionDecoder_aarch64::isSinglePrec() {
2370     if( isFPInsn && !isSIMDInsn ){
2371         if(_typeField == -1){
2372             //TODO if the type field is not set, do sth else
2373             OPRtype<23, 22>();
2374         }
2375         return _typeField==0?true:false;
2376     }else if( isSIMDInsn ){
2377         isValid = false; //not implemeted yet
2378     }
2379     return false;
2380 }
2381
2382 Expression::Ptr InstructionDecoder_aarch64::makeRsExpr()
2383 {
2384         MachRegister baseReg = isFPInsn?
2385         (isSinglePrec()?aarch64::s0:aarch64::d0):
2386         (is64Bit?aarch64::x0:aarch64::w0);
2387
2388     if(IS_INSN_LDST(insn)){
2389         baseReg = aarch64::w0;
2390     }
2391         return makeRegisterExpression(makeAarch64RegID(baseReg, field<16, 20>(insn)));
2392 }
2393
2394 void InstructionDecoder_aarch64::OPRRs()
2395 {
2396         insn_in_progress->appendOperand(makeRsExpr(), false, true);
2397 }
2398
2399 void InstructionDecoder_aarch64::makeBranchTarget(bool branchIsCall, bool bIsConditional, int immVal, int immLen)
2400 {
2401         Expression::Ptr lhs = makePCExpr();
2402
2403         int offset = sign_extend64(immLen + 2, immVal*4);
2404         Expression::Ptr rhs = Immediate::makeImmediate(Result(s64, offset));
2405
2406         insn_in_progress->addSuccessor(makeAddExpression(lhs, rhs, s64), branchIsCall, false, bIsConditional, false);
2407         if(branchIsCall)
2408         {
2409                 insn_in_progress->addSuccessor(makeFallThroughExpr(), false, false, false, true);
2410         }
2411
2412 }
2413
2414 Expression::Ptr InstructionDecoder_aarch64::makeFallThroughExpr()
2415 {
2416         return makeAddExpression(makePCExpr(), Immediate::makeImmediate(Result(u64, unsign_extend64(3, 4))), u64);
2417 }
2418
2419 template<typename T, Result_Type rT>
2420 Expression::Ptr InstructionDecoder_aarch64::fpExpand(int val)
2421 {
2422         int N, E, F;
2423         T frac, expandedImm, sign, exp;
2424
2425         N = (rT == s32)?32:64;
2426         E = (N == 32)?8:11;
2427         F = N - E - 1;
2428
2429         sign = (val & 0x80) >> 7;
2430
2431         int val6 = ((~val) & 0x40) >> 6, val6mask = (1 << (E - 3)) - 1;
2432         exp = (val6 << (E - 1)) | ((val6?val6mask:0) << 2) | ((val & 0x30) >> 4);
2433
2434         frac = (val & 0xF) << (F - 4);
2435
2436         expandedImm = (sign << (E + F)) | (exp << F) | frac;
2437
2438         return Immediate::makeImmediate(Result(rT, expandedImm));
2439 }
2440
2441 template<typename T>
2442 Expression::Ptr InstructionDecoder_aarch64::makeLogicalImm(int immr, int imms, int immsLen, Result_Type rT)
2443 {
2444     int len = highest_set_bit((nField<<immsLen) | (~imms & ((1<<immsLen) - 1))) - 1;
2445     int finalsize = (rT == u32?32:64);
2446
2447     if(len < 1 || ((1<<len) > finalsize))
2448     {
2449             isValid = false;
2450             return Immediate::makeImmediate(Result(u32, 0));
2451     }
2452     int levels = (1<<len) - 1;
2453
2454     int S = imms & levels;
2455     if(S == levels)
2456     {
2457         isValid = false;
2458         return Immediate::makeImmediate(Result(u32, 0));
2459     }
2460     int R = immr & levels;
2461
2462     int esize = 1<<len;
2463     T welem = (((T)1)<<(S+1)) - 1;
2464
2465     T wmaskarg = welem;
2466     if(R != 0)
2467     {
2468             T low = welem & (((T)1<<R) - 1), high = welem & ((((T)1<<(esize - R)) - 1)<<R);
2469             wmaskarg = (low<<(esize - R)) | (high>>R);
2470     }
2471
2472     int idx;
2473     T wmask = wmaskarg;
2474
2475     for(idx = 1; idx < finalsize/esize; idx++)
2476     {
2477         wmask |= (wmaskarg<<(esize*idx));
2478     }
2479
2480     return Immediate::makeImmediate(Result(rT, wmask));
2481 }
2482
2483 template<unsigned int endBit, unsigned int startBit>
2484 void InstructionDecoder_aarch64::OPRimm()
2485 {
2486         int immVal = field<startBit, endBit>(insn);
2487         unsigned int immLen = endBit - startBit + 1;
2488
2489         if(IS_INSN_LDST(insn))
2490         {
2491             if(IS_INSN_LD_LITERAL(insn))
2492             {
2493                 Expression::Ptr literal = makeMemRefIndexLiteral();
2494                 insn_in_progress->appendOperand(literal, true, false);
2495             }
2496             else if(IS_INSN_LDST_POST(insn))
2497             {
2498                 Expression::Ptr offset = makeMemRefIndex_offset9();
2499                 insn_in_progress->appendOperand(offset, true, false);
2500             }
2501             else if(IS_INSN_LDST_PAIR_POST(insn)
2502                 || IS_INSN_LDST_PAIR_OFFSET(insn) )
2503             {
2504                 Expression::Ptr offset = makeMemRefPair_offset7();
2505                 insn_in_progress->appendOperand(offset, true, false);
2506             }
2507         
2508             return;
2509         }
2510
2511         if(hasHw)
2512         {
2513                 processHwFieldInsn(immLen, immVal);
2514         }
2515         else if(hasN)           //logical (immediate), bitfield, extract
2516         {
2517                 if(IS_FIELD_IMMR(startBit, endBit))
2518                 {
2519                         immr = immVal;
2520                         immrLen = immLen;
2521                 }
2522                 else if(IS_FIELD_IMMS(startBit, endBit))
2523                 {
2524                         Expression::Ptr imm;
2525
2526                         if(IS_INSN_LOGICAL_IMM(insn))
2527                         {
2528                                 if(is64Bit)
2529                                     imm = makeLogicalImm<uint64_t>(immr, immVal, immLen, u64);
2530                                 else
2531                                     imm = makeLogicalImm<uint32_t>(immr, immVal, immLen, u32);
2532                         }
2533                         else
2534                         {
2535                                 imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));
2536                                 oprRotateAmt++;
2537                         }
2538
2539                         insn_in_progress->appendOperand(imm, true, false);
2540                         if(IS_INSN_BITFIELD(insn))
2541                         {
2542                                 imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immrLen, immr)));
2543                                 insn_in_progress->appendOperand(imm, true, false);
2544                                 oprRotateAmt--;
2545                         }
2546                 }
2547                 else
2548                     isValid = false;
2549         }
2550         else if(hasShift)
2551         {
2552                 if(IS_INSN_ADDSUB_SHIFT(insn) || IS_INSN_LOGICAL_SHIFT(insn))   //add-sub shifted | logical shifted
2553                 {
2554                         processShiftFieldShiftedInsn(immLen, immVal);
2555                 }
2556                 else if(IS_INSN_ADDSUB_IMM(insn))               //add-sub (immediate)
2557                 {
2558                         processShiftFieldImmInsn(immLen, immVal);
2559                 }
2560                 else
2561                         isValid = false;
2562         }
2563         else if(hasOption)
2564         {
2565                 if(IS_INSN_ADDSUB_EXT(insn))                                                                            //add-sub extended
2566                 {
2567                     Expression::Ptr expr = makeOptionExpression(immLen, immVal);
2568
2569                     insn_in_progress->appendOperand(expr, true, false);
2570                 }
2571                 else
2572                 {
2573                         isValid = false;
2574                 }
2575         }
2576         else if(IS_INSN_BRANCHING(insn) && !IS_INSN_B_UNCOND_REG(insn))
2577         {               //unconditional branch (immediate), test and branch, compare and branch, conditional branch
2578                 bool bIsConditional = false;
2579                 if(!(IS_INSN_B_UNCOND(insn)))
2580                         bIsConditional = true;
2581
2582                 bool branchIsCall = bIsConditional?false:(field<31, 31>(insn) == 1);
2583
2584                 insn_in_progress->appendOperand(makePCExpr(), false, true);
2585                 makeBranchTarget(branchIsCall, bIsConditional, immVal, immLen);
2586
2587                 if(hasb5)
2588                         insn_in_progress->appendOperand(makeb40Expr(), true, false);
2589
2590                 if(bIsConditional)
2591                         insn_in_progress->addSuccessor(makeFallThroughExpr(), false, false, true, true);
2592         }
2593         else if(IS_INSN_PCREL_ADDR(insn))                                                                       //pc-relative addressing
2594         {
2595                 if(IS_FIELD_IMMLO(startBit, endBit))
2596                 {
2597                         immlo = immVal;
2598                         immloLen = endBit - startBit + 1;
2599                 }
2600                 else if(IS_FIELD_IMMHI(startBit, endBit))
2601                 {
2602                         int page = field<31, 31>(insn);
2603                         int64_t offset = (immVal<<immloLen) | immlo;
2604                         offset = offset<<(page*12);
2605                         int size = immloLen + immLen + (page*12);
2606
2607                         insn_in_progress->appendOperand(makePCExpr(), true, false);
2608                         Expression::Ptr imm = Immediate::makeImmediate(Result(s64, (offset << (64 - size)) >> (64 - size)));
2609
2610                         insn_in_progress->appendOperand(imm, true, false);
2611                 }
2612                 else
2613                         isValid = false;
2614         }
2615         else if(isFPInsn)
2616         {
2617                 if(isSinglePrec())
2618                         insn_in_progress->appendOperand(fpExpand<int32_t, s32>(immVal), true, false);
2619                 else
2620                         insn_in_progress->appendOperand(fpExpand<int64_t, s64>(immVal), true, false);
2621         }
2622         else if(IS_INSN_EXCEPTION(insn))
2623         {
2624                 Expression::Ptr imm = Immediate::makeImmediate(Result(u16, immVal));
2625                 insn_in_progress->appendOperand(imm, true, false);
2626                 isPstateRead = true;
2627         }
2628         else if(isSIMDInsn)
2629         {
2630             if(IS_INSN_SIMD_EXTR(insn))
2631             {
2632                 if(_Q == 0)
2633                 {
2634                     if((immVal & 0x8) == 0)
2635                     {
2636                         Expression::Ptr imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen - 1, immVal & 0x7)));
2637                         insn_in_progress->appendOperand(imm, true, false);
2638                     }
2639                     else
2640                         isValid = false;
2641                 }
2642                 else
2643                 {
2644                     Expression::Ptr imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immLen, immVal)));\
2645                     insn_in_progress->appendOperand(imm, true, false);
2646                 }
2647             }
2648             else if(IS_INSN_SIMD_SHIFT_IMM(insn) || IS_INSN_SCALAR_SHIFT_IMM(insn))
2649             {
2650                 //immh
2651                 if(startBit == 19 && endBit == 22)
2652                 {
2653                     immlo = immVal;
2654                     immloLen = endBit - startBit + 1;
2655                 }
2656                 //immb
2657                 else if(startBit == 16 && endBit == 18)
2658                 {
2659                         int opcode = field<11, 15>(insn);
2660                     int shift, isRightShift = 1, elemWidth = (immlo << immLen) | immVal;
2661                     entryID insnID = insn_in_progress->getOperation().operationID;
2662                         bool isScalar = field<28, 28>(insn)?true:false;
2663                     
2664                     //check if shift is left; if it is, the immediate has to be processed in a different manner.
2665                     //unfortunately, determining whether the instruction will do a left or right shift cannot be determined in any way other than checking the instruction's opcode
2666                     if(insnID == aarch64_op_shl_advsimd || insnID == aarch64_op_sqshl_advsimd_imm || insnID == aarch64_op_sshll_advsimd ||
2667                        insnID == aarch64_op_sli_advsimd || insnID == aarch64_op_sqshlu_advsimd || insnID == aarch64_op_uqshl_advsimd_imm || insnID == aarch64_op_ushll_advsimd)
2668                         isRightShift = -1;
2669
2670                     switch(highest_set_bit(immlo))
2671                     {
2672                         case 0x1:(!isScalar || (opcode & 0x1C) == 0x0C || (opcode & 0x1C) == 0x10)?(shift = isRightShift*(16 - elemWidth) + (isRightShift>0?0:8)):(isValid = false);
2673                                  break;
2674                         case 0x2:(!isScalar || (opcode & 0x1C) == 0x0C || (opcode & 0x1C) == 0x10)?(shift = isRightShift*(32 - elemWidth) + (isRightShift>0?0:16)):(isValid = false);
2675                                  break;
2676                         case 0x3:(!isScalar || opcode > 0x0A)?(shift = isRightShift*(64 - elemWidth) + (isRightShift>0?0:32)):(isValid = false);
2677                                  break;
2678                         case 0x4:shift = isRightShift*(128 - elemWidth) + (isRightShift>0?0:64);
2679                                  break;
2680                         default:isValid = false;
2681                     }
2682
2683                     if(isValid)
2684                     {
2685                         Expression::Ptr imm = Immediate::makeImmediate(Result(u32, unsign_extend32(immloLen + immLen, shift)));
2686                         insn_in_progress->appendOperand(imm, true, false);
2687                     }
2688                 }
2689                 else
2690                     isValid = false;
2691             }
2692         }
2693         else                                                            //conditional compare (immediate)
2694         {
2695                 Result_Type rT = is64Bit?u64:u32;
2696
2697                 Expression::Ptr imm = Immediate::makeImmediate(Result(rT, rT==u32?unsign_extend32(immLen, immVal):unsign_extend64(immLen, immVal)));
2698                 insn_in_progress->appendOperand(imm, true, false);
2699         }
2700 }
2701
2702         void InstructionDecoder_aarch64::reorderOperands()
2703         {
2704             if(oprRotateAmt)
2705             {
2706                         std::vector<Operand> curOperands;
2707                         insn_in_progress->getOperands(curOperands);
2708
2709                         if(curOperands.empty())
2710                                 assert(!"empty operand list found while re-ordering operands");
2711
2712                         std::swap(curOperands[1], curOperands[3]);
2713
2714                         while(oprRotateAmt--)
2715                                 std::rotate(curOperands.begin(), curOperands.begin()+1, curOperands.begin()+3);
2716
2717                         insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2718             }
2719         else if( IS_INSN_LDST_POST(insn) || IS_INSN_LDST_PAIR_POST(insn) ){
2720                 std::vector<Operand> curOperands;
2721                 insn_in_progress->getOperands(curOperands);
2722             std::iter_swap( curOperands.begin(), curOperands.end()-1 );
2723                     insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2724         }
2725         else if( IS_INSN_LDST_PAIR(insn) ){
2726                     std::vector<Operand> curOperands;
2727                     insn_in_progress->getOperands(curOperands);
2728             assert(curOperands.size() == 4 || curOperands.size() == 3);
2729             if(curOperands.size() == 3){
2730                 curOperands.insert(curOperands.begin(), curOperands.back());
2731                 curOperands.pop_back();
2732             }else if(curOperands.size() == 4){
2733                 std::iter_swap( curOperands.begin(), curOperands.end()-1 );
2734             }
2735                     insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2736         }
2737         else if( IS_INSN_LDST_EX_PAIR(insn) ){
2738                     std::vector<Operand> curOperands;
2739                     insn_in_progress->getOperands(curOperands);
2740             if(curOperands.size() == 3) {
2741                 curOperands.insert(curOperands.begin(), curOperands.back());
2742                 curOperands.pop_back();
2743             }
2744             else if( curOperands.size() == 4) {
2745                 curOperands.insert(curOperands.begin()+1, curOperands.back());
2746                 curOperands.pop_back();
2747             }
2748                     insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2749         }
2750         else if( IS_INSN_ST_EX(insn) ){
2751                     std::vector<Operand> curOperands;
2752                     insn_in_progress->getOperands(curOperands);
2753             if(curOperands.size() == 3){
2754                 curOperands.insert(curOperands.begin()+1, curOperands.back());
2755                 curOperands.pop_back();
2756                         insn_in_progress->m_Operands.assign(curOperands.begin(), curOperands.end());
2757             }
2758             else
2759                         insn_in_progress->m_Operands.reverse();
2760         }
2761             else
2762                     insn_in_progress->m_Operands.reverse();
2763         }
2764
2765 void InstructionDecoder_aarch64::processAlphabetImm()
2766 {
2767    if(op == 1 && cmode == 0xE)
2768    {
2769         uint64_t imm = 0;
2770
2771         for(int imm_index = 0; imm_index < 8; imm_index++)
2772                 imm |= (simdAlphabetImm & (1 << imm_index))?(0xFF << (imm_index * 8)):0;
2773
2774         insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u64, imm)), true, false);
2775    }
2776    else if(cmode == 0xF)
2777    {
2778        //fmov (vector, immediate)
2779        //TODO: check with Bill if this is fine
2780       insn_in_progress->appendOperand(Immediate::makeImmediate(Result(u8, simdAlphabetImm)), true, false); 
2781    }
2782    else
2783    {
2784         int shiftAmt = 0;
2785
2786         //16-bit shifted immediate
2787         if((cmode & 0xC) == 0x8)
2788             shiftAmt = ((cmode & 0x2) >> 1) * 8;
2789         //32-bit shifted immediate
2790         else if((cmode & 0x8) == 0x0)
2791             shiftAmt = ((cmode & 0x6) >> 1) * 8;
2792         //32-bit shifting ones
2793         else if((cmode & 0xE) == 0xC)
2794             shiftAmt = ((cmode & 0x0) + 1) * 8;
2795         
2796         Expression::Ptr lhs = Immediate::makeImmediate(Result(u32, unsign_extend32(8, simdAlphabetImm)));
2797         Expression::Ptr rhs = Immediate::makeImmediate(Result(u32, unsign_extend32(5, shiftAmt)));
2798         Expression::Ptr imm = makeLeftShiftExpression(lhs, rhs, u64);
2799
2800         insn_in_progress->appendOperand(imm, true, false);
2801    } 
2802 }
2803
2804 using namespace boost::assign;
2805
2806 #include "aarch64_opcode_tables.C"
2807
2808         void InstructionDecoder_aarch64::doDelayedDecode(const Instruction *insn_to_complete)
2809     {
2810                 int insn_table_index = findInsnTableIndex(0);
2811                 aarch64_insn_entry *insn_table_entry = &aarch64_insn_entry::main_insn_table[insn_table_index];
2812
2813                 insn = insn_to_complete->m_RawInsn.small_insn;
2814                 insn_in_progress = const_cast<Instruction*>(insn_to_complete);
2815         for(operandSpec::const_iterator fn = insn_table_entry->operands.begin(); fn != insn_table_entry->operands.end(); fn++)
2816         {
2817                         std::mem_fun(*fn)(this);
2818                 }
2819
2820                 if(insn_table_index == 0)
2821                     isValid = false;
2822
2823                 if(!isValid)
2824                 {
2825                         insn_in_progress->getOperation().mnemonic = INVALID_ENTRY.mnemonic;
2826                         insn_in_progress->getOperation().operationID = INVALID_ENTRY.op;
2827                         insn_in_progress->m_Operands.clear();
2828                         insn_in_progress->m_Successors.clear();
2829                 }
2830                 else
2831                 {
2832                     reorderOperands();
2833
2834                     if(IS_INSN_SYSTEM(insn))
2835                     {
2836                         processSystemInsn();
2837                     }
2838
2839                     if(IS_INSN_SIMD_MOD_IMM(insn))
2840                     {
2841                         processAlphabetImm();
2842                     }
2843
2844                     if(IS_INSN_LDST_SIMD_MULT_POST(insn) || IS_INSN_LDST_SIMD_SING_POST(insn))
2845                         insn_in_progress->appendOperand(makeRnExpr(), false, true);
2846
2847                     if(isPstateWritten || isPstateRead)
2848                         insn_in_progress->appendOperand(makePstateExpr(), isPstateRead, isPstateWritten);
2849                 }
2850
2851     }
2852         int InstructionDecoder_aarch64::findInsnTableIndex(unsigned int decoder_table_index)
2853         {
2854                 aarch64_mask_entry *cur_entry = &aarch64_mask_entry::main_decoder_table[decoder_table_index];
2855                 unsigned int cur_mask = cur_entry->mask;
2856
2857                 if(cur_mask == 0)
2858                 {
2859                         int insn_table_index = cur_entry->insnTableIndex;
2860                         if(insn_table_index == -1)
2861                                 assert(!"no instruction table entry found for current instruction");
2862                         else
2863                                 return insn_table_index;
2864                 }
2865
2866                 unsigned int insn_iter_index = 0, map_key_index = 0, branch_map_key = 0;
2867                 branchMap cur_branches = cur_entry->nodeBranches;
2868
2869                 while(insn_iter_index < AARCH64_INSN_LENGTH)
2870                 {
2871                         if(((cur_mask>>insn_iter_index) & 1) == 1)
2872                         {
2873                                 branch_map_key = branch_map_key | (((insn>>insn_iter_index) & 1)<<map_key_index);
2874                                 map_key_index++;
2875                         }
2876                         insn_iter_index++;
2877                 }
2878
2879                 if(cur_branches.count(branch_map_key) <= 0)
2880                     return 0;
2881                 //      branch_map_key = 0;
2882
2883                 return findInsnTableIndex(cur_branches[branch_map_key]);
2884         }
2885
2886         void InstructionDecoder_aarch64::setFlags()
2887         {
2888                 isPstateWritten = true;
2889         }
2890
2891     void InstructionDecoder_aarch64::mainDecode()
2892     {
2893                 int insn_table_index = findInsnTableIndex(0);
2894                 aarch64_insn_entry *insn_table_entry = &aarch64_insn_entry::main_insn_table[insn_table_index];
2895
2896         insn_in_progress = makeInstruction(insn_table_entry->op, insn_table_entry->mnemonic, 4, reinterpret_cast<unsigned char*>(&insn));
2897
2898         if(IS_INSN_BRANCHING(insn))
2899         {
2900             doDelayedDecode(insn_in_progress);
2901         }
2902
2903         insn_in_progress->arch_decoded_from = Arch_aarch64;
2904         return;
2905     }
2906   };
2907 };
2908
2909
2910