1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *  * Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #define LOG_TAG "ArmToArm64Assembler"
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include <cutils/log.h>
36 #include <cutils/properties.h>
37 #include <private/pixelflinger/ggl_context.h>
38 
39 #include "codeflinger/Arm64Assembler.h"
40 #include "codeflinger/CodeCache.h"
41 #include "codeflinger/Arm64Disassembler.h"
42 
43 
44 /*
45 ** --------------------------------------------
46 ** Support for Arm64 in GGLAssembler JIT
47 ** --------------------------------------------
48 **
49 ** Approach
50 ** - GGLAssembler and associated files are largely un-changed.
51 ** - A translator class maps ArmAssemblerInterface calls to
52 **   generate Arm64 instructions.
53 **
54 ** ----------------------
55 ** ArmToArm64Assembler
56 ** ----------------------
57 **
58 ** - Subclassed from ArmAssemblerInterface
59 **
60 ** - Translates each ArmAssemblerInterface call to generate
61 **   one or more Arm64 instructions  as necessary.
62 **
63 ** - Does not implement ArmAssemblerInterface portions unused by GGLAssembler
64 **   It calls NOT_IMPLEMENTED() for such cases, which in turn logs
65 **    a fatal message.
66 **
67 ** - Uses A64_.. series of functions to generate instruction machine code
68 **   for Arm64 instructions. These functions also log the instruction
69 **   to LOG, if ARM64_ASM_DEBUG define is set to 1
70 **
71 ** - Dumps machine code and eqvt assembly if "debug.pf.disasm" option is set
72 **   It uses arm64_disassemble to perform disassembly
73 **
74 ** - Uses register 13 (SP in ARM), 15 (PC in ARM), 16, 17 for storing
75 **   intermediate results. GGLAssembler does not use SP and PC as these
76 **   registers are marked as reserved. The temporary registers are not
77 **   saved/restored on stack as these are caller-saved registers in Arm64
78 **
79 ** - Uses CSEL instruction to support conditional execution. The result is
80 **   stored in a temporary register and then copied to the target register
81 **   if the condition is true.
82 **
83 ** - In the case of conditional data transfer instructions, conditional
84 **   branch is used to skip over instruction, if the condition is false
85 **
86 ** - Wherever possible, immediate values are transferred to temporary
87 **   register prior to processing. This simplifies overall implementation
88 **   as instructions requiring immediate values are converted to
89 **   move immediate instructions followed by register-register instruction.
90 **
91 ** --------------------------------------------
92 ** ArmToArm64Assembler unit test bench
93 ** --------------------------------------------
94 **
95 ** - Tests ArmToArm64Assembler interface for all the possible
96 **   ways in which GGLAssembler uses ArmAssemblerInterface interface.
97 **
98 ** - Uses test jacket (written in assembly) to set the registers,
99 **   condition flags prior to calling generated instruction. It also
100 **   copies registers and flags at the end of execution. Caller then
101 **   checks if generated code performed correct operation based on
102 **   output registers and flags.
103 **
104 ** - Broadly contains three type of tests, (i) data operation tests
105 **   (ii) data transfer tests and (iii) LDM/STM tests.
106 **
107 ** ----------------------
108 ** Arm64 disassembler
109 ** ----------------------
110 ** - This disassembler disassembles only those machine codes which can be
111 **   generated by ArmToArm64Assembler. It has a unit testbench which
112 **   tests all the instructions supported by the disassembler.
113 **
114 ** ------------------------------------------------------------------
115 ** ARMAssembler/ARMAssemblerInterface/ARMAssemblerProxy changes
116 ** ------------------------------------------------------------------
117 **
118 ** - In existing code, addresses were being handled as 32 bit values at
119 **   certain places.
120 **
121 ** - Added a new set of functions for address load/store/manipulation.
122 **   These are ADDR_LDR, ADDR_STR, ADDR_ADD, ADDR_SUB and they map to
123 **   default 32 bit implementations in ARMAssemblerInterface.
124 **
125 ** - ArmToArm64Assembler maps these functions to appropriate 64 bit
126 **   functions.
127 **
128 ** ----------------------
129 ** GGLAssembler changes
130 ** ----------------------
131 ** - Since ArmToArm64Assembler can generate 4 Arm64 instructions for
132 **   each call in worst case, the memory required is set to 4 times
133 **   ARM memory
134 **
135 ** - Address load/store/manipulation were changed to use new functions
136 **   added in the ARMAssemblerInterface.
137 **
138 */
139 
140 
141 #define NOT_IMPLEMENTED()  LOG_FATAL("Arm instruction %s not yet implemented\n", __func__)
142 
143 #define ARM64_ASM_DEBUG 0
144 
145 #if ARM64_ASM_DEBUG
146     #define LOG_INSTR(...) ALOGD("\t" __VA_ARGS__)
147     #define LOG_LABEL(...) ALOGD(__VA_ARGS__)
148 #else
149     #define LOG_INSTR(...) ((void)0)
150     #define LOG_LABEL(...) ((void)0)
151 #endif
152 
153 namespace android {
154 
155 static const char* shift_codes[] =
156 {
157     "LSL", "LSR", "ASR", "ROR"
158 };
159 static const char *cc_codes[] =
160 {
161     "EQ", "NE", "CS", "CC", "MI",
162     "PL", "VS", "VC", "HI", "LS",
163     "GE", "LT", "GT", "LE", "AL", "NV"
164 };
165 
ArmToArm64Assembler(const sp<Assembly> & assembly)166 ArmToArm64Assembler::ArmToArm64Assembler(const sp<Assembly>& assembly)
167     :   ARMAssemblerInterface(),
168         mAssembly(assembly)
169 {
170     mBase = mPC = (uint32_t *)assembly->base();
171     mDuration = ggl_system_time();
172     mZeroReg = 13;
173     mTmpReg1 = 15;
174     mTmpReg2 = 16;
175     mTmpReg3 = 17;
176 }
177 
ArmToArm64Assembler(void * base)178 ArmToArm64Assembler::ArmToArm64Assembler(void *base)
179     :   ARMAssemblerInterface(), mAssembly(NULL)
180 {
181     mBase = mPC = (uint32_t *)base;
182     mDuration = ggl_system_time();
183     // Regs 13, 15, 16, 17 are used as temporary registers
184     mZeroReg = 13;
185     mTmpReg1 = 15;
186     mTmpReg2 = 16;
187     mTmpReg3 = 17;
188 }
189 
~ArmToArm64Assembler()190 ArmToArm64Assembler::~ArmToArm64Assembler()
191 {
192 }
193 
pc() const194 uint32_t* ArmToArm64Assembler::pc() const
195 {
196     return mPC;
197 }
198 
base() const199 uint32_t* ArmToArm64Assembler::base() const
200 {
201     return mBase;
202 }
203 
reset()204 void ArmToArm64Assembler::reset()
205 {
206     if(mAssembly == NULL)
207         mPC = mBase;
208     else
209         mBase = mPC = (uint32_t *)mAssembly->base();
210     mBranchTargets.clear();
211     mLabels.clear();
212     mLabelsInverseMapping.clear();
213     mComments.clear();
214 #if ARM64_ASM_DEBUG
215     ALOGI("RESET\n");
216 #endif
217 }
218 
getCodegenArch()219 int ArmToArm64Assembler::getCodegenArch()
220 {
221     return CODEGEN_ARCH_ARM64;
222 }
223 
224 // ----------------------------------------------------------------------------
225 
disassemble(const char * name)226 void ArmToArm64Assembler::disassemble(const char* name)
227 {
228     if(name)
229     {
230         printf("%s:\n", name);
231     }
232     size_t count = pc()-base();
233     uint32_t* i = base();
234     while (count--)
235     {
236         ssize_t label = mLabelsInverseMapping.indexOfKey(i);
237         if (label >= 0)
238         {
239             printf("%s:\n", mLabelsInverseMapping.valueAt(label));
240         }
241         ssize_t comment = mComments.indexOfKey(i);
242         if (comment >= 0)
243         {
244             printf("; %s\n", mComments.valueAt(comment));
245         }
246         printf("%p:    %08x    ", i, uint32_t(i[0]));
247         {
248             char instr[256];
249             ::arm64_disassemble(*i, instr);
250             printf("%s\n", instr);
251         }
252         i++;
253     }
254 }
255 
comment(const char * string)256 void ArmToArm64Assembler::comment(const char* string)
257 {
258     mComments.add(mPC, string);
259     LOG_INSTR("//%s\n", string);
260 }
261 
label(const char * theLabel)262 void ArmToArm64Assembler::label(const char* theLabel)
263 {
264     mLabels.add(theLabel, mPC);
265     mLabelsInverseMapping.add(mPC, theLabel);
266     LOG_LABEL("%s:\n", theLabel);
267 }
268 
B(int cc,const char * label)269 void ArmToArm64Assembler::B(int cc, const char* label)
270 {
271     mBranchTargets.add(branch_target_t(label, mPC));
272     LOG_INSTR("B%s %s\n", cc_codes[cc], label );
273     *mPC++ = (0x54 << 24) | cc;
274 }
275 
BL(int,const char *)276 void ArmToArm64Assembler::BL(int /*cc*/, const char* /*label*/)
277 {
278     NOT_IMPLEMENTED(); //Not Required
279 }
280 
281 // ----------------------------------------------------------------------------
282 //Prolog/Epilog & Generate...
283 // ----------------------------------------------------------------------------
284 
prolog()285 void ArmToArm64Assembler::prolog()
286 {
287     // write prolog code
288     mPrologPC = mPC;
289     *mPC++ = A64_MOVZ_X(mZeroReg,0,0);
290 }
291 
epilog(uint32_t)292 void ArmToArm64Assembler::epilog(uint32_t /*touched*/)
293 {
294     // write epilog code
295     static const int XLR = 30;
296     *mPC++ = A64_RET(XLR);
297 }
298 
generate(const char * name)299 int ArmToArm64Assembler::generate(const char* name)
300 {
301     // fixup all the branches
302     size_t count = mBranchTargets.size();
303     while (count--)
304     {
305         const branch_target_t& bt = mBranchTargets[count];
306         uint32_t* target_pc = mLabels.valueFor(bt.label);
307         LOG_ALWAYS_FATAL_IF(!target_pc,
308                 "error resolving branch targets, target_pc is null");
309         int32_t offset = int32_t(target_pc - bt.pc);
310         *bt.pc |= (offset & 0x7FFFF) << 5;
311     }
312 
313     if(mAssembly != NULL)
314         mAssembly->resize( int(pc()-base())*4 );
315 
316     // the instruction cache is flushed by CodeCache
317     const int64_t duration = ggl_system_time() - mDuration;
318     const char * const format = "generated %s (%d ins) at [%p:%p] in %ld ns\n";
319     ALOGI(format, name, int(pc()-base()), base(), pc(), duration);
320 
321 
322     char value[PROPERTY_VALUE_MAX];
323     property_get("debug.pf.disasm", value, "0");
324     if (atoi(value) != 0)
325     {
326         printf(format, name, int(pc()-base()), base(), pc(), duration);
327         disassemble(name);
328     }
329     return NO_ERROR;
330 }
331 
pcForLabel(const char * label)332 uint32_t* ArmToArm64Assembler::pcForLabel(const char* label)
333 {
334     return mLabels.valueFor(label);
335 }
336 
337 // ----------------------------------------------------------------------------
338 // Data Processing...
339 // ----------------------------------------------------------------------------
dataProcessingCommon(int opcode,int s,int Rd,int Rn,uint32_t Op2)340 void ArmToArm64Assembler::dataProcessingCommon(int opcode,
341         int s, int Rd, int Rn, uint32_t Op2)
342 {
343     if(opcode != opSUB && s == 1)
344     {
345         NOT_IMPLEMENTED(); //Not required
346         return;
347     }
348 
349     if(opcode != opSUB && opcode != opADD && opcode != opAND &&
350        opcode != opORR && opcode != opMVN)
351     {
352         NOT_IMPLEMENTED(); //Not required
353         return;
354     }
355 
356     if(Op2 == OPERAND_REG_IMM && mAddrMode.reg_imm_shift > 31)
357         {
358         NOT_IMPLEMENTED();
359         return;
360     }
361 
362     //Store immediate in temporary register and convert
363     //immediate operation into register operation
364     if(Op2 == OPERAND_IMM)
365     {
366         int imm = mAddrMode.immediate;
367         *mPC++ = A64_MOVZ_W(mTmpReg2, imm & 0x0000FFFF, 0);
368         *mPC++ = A64_MOVK_W(mTmpReg2, (imm >> 16) & 0x0000FFFF, 16);
369         Op2 = mTmpReg2;
370     }
371 
372 
373     {
374         uint32_t shift;
375         uint32_t amount;
376         uint32_t Rm;
377 
378         if(Op2 == OPERAND_REG_IMM)
379         {
380             shift   = mAddrMode.reg_imm_type;
381             amount  = mAddrMode.reg_imm_shift;
382             Rm      = mAddrMode.reg_imm_Rm;
383         }
384         else if(Op2 < OPERAND_REG)
385         {
386             shift   = 0;
387             amount  = 0;
388             Rm      = Op2;
389         }
390         else
391         {
392             NOT_IMPLEMENTED(); //Not required
393             return;
394         }
395 
396         switch(opcode)
397         {
398             case opADD: *mPC++ = A64_ADD_W(Rd, Rn, Rm, shift, amount); break;
399             case opAND: *mPC++ = A64_AND_W(Rd, Rn, Rm, shift, amount); break;
400             case opORR: *mPC++ = A64_ORR_W(Rd, Rn, Rm, shift, amount); break;
401             case opMVN: *mPC++ = A64_ORN_W(Rd, Rn, Rm, shift, amount); break;
402             case opSUB: *mPC++ = A64_SUB_W(Rd, Rn, Rm, shift, amount, s);break;
403         };
404 
405     }
406 }
407 
dataProcessing(int opcode,int cc,int s,int Rd,int Rn,uint32_t Op2)408 void ArmToArm64Assembler::dataProcessing(int opcode, int cc,
409         int s, int Rd, int Rn, uint32_t Op2)
410 {
411     uint32_t Wd;
412 
413     if(cc != AL)
414         Wd = mTmpReg1;
415     else
416         Wd = Rd;
417 
418     if(opcode == opADD || opcode == opAND || opcode == opORR ||opcode == opSUB)
419     {
420         dataProcessingCommon(opcode, s, Wd, Rn, Op2);
421     }
422     else if(opcode == opCMP)
423     {
424         dataProcessingCommon(opSUB, 1, mTmpReg3, Rn, Op2);
425     }
426     else if(opcode == opRSB)
427     {
428         dataProcessingCommon(opSUB, s, Wd, Rn, Op2);
429         dataProcessingCommon(opSUB, s, Wd, mZeroReg, Wd);
430     }
431     else if(opcode == opMOV)
432     {
433         dataProcessingCommon(opORR, 0, Wd, mZeroReg, Op2);
434         if(s == 1)
435         {
436             dataProcessingCommon(opSUB, 1, mTmpReg3, Wd, mZeroReg);
437         }
438     }
439     else if(opcode == opMVN)
440     {
441         dataProcessingCommon(opMVN, s, Wd, mZeroReg, Op2);
442     }
443     else if(opcode == opBIC)
444     {
445         dataProcessingCommon(opMVN, s, mTmpReg3, mZeroReg, Op2);
446         dataProcessingCommon(opAND, s, Wd, Rn, mTmpReg3);
447     }
448     else
449     {
450         NOT_IMPLEMENTED();
451         return;
452     }
453 
454     if(cc != AL)
455     {
456         *mPC++ = A64_CSEL_W(Rd, mTmpReg1, Rd, cc);
457     }
458 }
459 // ----------------------------------------------------------------------------
460 // Address Processing...
461 // ----------------------------------------------------------------------------
462 
ADDR_ADD(int cc,int s,int Rd,int Rn,uint32_t Op2)463 void ArmToArm64Assembler::ADDR_ADD(int cc,
464         int s, int Rd, int Rn, uint32_t Op2)
465 {
466     if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required
467     if(s  != 0) { NOT_IMPLEMENTED(); return;} //Not required
468 
469 
470     if(Op2 == OPERAND_REG_IMM && mAddrMode.reg_imm_type == LSL)
471     {
472         int Rm = mAddrMode.reg_imm_Rm;
473         int amount = mAddrMode.reg_imm_shift;
474         *mPC++ = A64_ADD_X_Wm_SXTW(Rd, Rn, Rm, amount);
475     }
476     else if(Op2 < OPERAND_REG)
477     {
478         int Rm = Op2;
479         int amount = 0;
480         *mPC++ = A64_ADD_X_Wm_SXTW(Rd, Rn, Rm, amount);
481     }
482     else if(Op2 == OPERAND_IMM)
483     {
484         int imm = mAddrMode.immediate;
485         *mPC++ = A64_MOVZ_W(mTmpReg1, imm & 0x0000FFFF, 0);
486         *mPC++ = A64_MOVK_W(mTmpReg1, (imm >> 16) & 0x0000FFFF, 16);
487 
488         int Rm = mTmpReg1;
489         int amount = 0;
490         *mPC++ = A64_ADD_X_Wm_SXTW(Rd, Rn, Rm, amount);
491     }
492     else
493     {
494         NOT_IMPLEMENTED(); //Not required
495     }
496 }
497 
ADDR_SUB(int cc,int s,int Rd,int Rn,uint32_t Op2)498 void ArmToArm64Assembler::ADDR_SUB(int cc,
499         int s, int Rd, int Rn, uint32_t Op2)
500 {
501     if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required
502     if(s  != 0) { NOT_IMPLEMENTED(); return;} //Not required
503 
504     if(Op2 == OPERAND_REG_IMM && mAddrMode.reg_imm_type == LSR)
505     {
506         *mPC++ = A64_ADD_W(mTmpReg1, mZeroReg, mAddrMode.reg_imm_Rm,
507                            LSR, mAddrMode.reg_imm_shift);
508         *mPC++ = A64_SUB_X_Wm_SXTW(Rd, Rn, mTmpReg1, 0);
509     }
510     else
511     {
512         NOT_IMPLEMENTED(); //Not required
513     }
514 }
515 
516 // ----------------------------------------------------------------------------
517 // multiply...
518 // ----------------------------------------------------------------------------
MLA(int cc,int s,int Rd,int Rm,int Rs,int Rn)519 void ArmToArm64Assembler::MLA(int cc, int s,int Rd, int Rm, int Rs, int Rn)
520 {
521     if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required
522 
523     *mPC++ = A64_MADD_W(Rd, Rm, Rs, Rn);
524     if(s == 1)
525         dataProcessingCommon(opSUB, 1, mTmpReg1, Rd, mZeroReg);
526 }
MUL(int cc,int s,int Rd,int Rm,int Rs)527 void ArmToArm64Assembler::MUL(int cc, int s, int Rd, int Rm, int Rs)
528 {
529     if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required
530     if(s  != 0) { NOT_IMPLEMENTED(); return;} //Not required
531     *mPC++ = A64_MADD_W(Rd, Rm, Rs, mZeroReg);
532 }
UMULL(int,int,int,int,int,int)533 void ArmToArm64Assembler::UMULL(int /*cc*/, int /*s*/,
534         int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/)
535 {
536     NOT_IMPLEMENTED(); //Not required
537 }
UMUAL(int,int,int,int,int,int)538 void ArmToArm64Assembler::UMUAL(int /*cc*/, int /*s*/,
539         int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/)
540 {
541     NOT_IMPLEMENTED(); //Not required
542 }
SMULL(int,int,int,int,int,int)543 void ArmToArm64Assembler::SMULL(int /*cc*/, int /*s*/,
544         int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/)
545 {
546     NOT_IMPLEMENTED(); //Not required
547 }
SMUAL(int,int,int,int,int,int)548 void ArmToArm64Assembler::SMUAL(int /*cc*/, int /*s*/,
549         int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/)
550 {
551     NOT_IMPLEMENTED(); //Not required
552 }
553 
554 // ----------------------------------------------------------------------------
555 // branches relative to PC...
556 // ----------------------------------------------------------------------------
B(int,uint32_t *)557 void ArmToArm64Assembler::B(int /*cc*/, uint32_t* /*pc*/){
558     NOT_IMPLEMENTED(); //Not required
559 }
560 
BL(int,uint32_t *)561 void ArmToArm64Assembler::BL(int /*cc*/, uint32_t* /*pc*/){
562     NOT_IMPLEMENTED(); //Not required
563 }
564 
BX(int,int)565 void ArmToArm64Assembler::BX(int /*cc*/, int /*Rn*/){
566     NOT_IMPLEMENTED(); //Not required
567 }
568 
569 // ----------------------------------------------------------------------------
570 // data transfer...
571 // ----------------------------------------------------------------------------
572 enum dataTransferOp
573 {
574     opLDR,opLDRB,opLDRH,opSTR,opSTRB,opSTRH
575 };
576 
dataTransfer(int op,int cc,int Rd,int Rn,uint32_t op_type,uint32_t size)577 void ArmToArm64Assembler::dataTransfer(int op, int cc,
578                             int Rd, int Rn, uint32_t op_type, uint32_t size)
579 {
580     const int XSP = 31;
581     if(Rn == SP)
582         Rn = XSP;
583 
584     if(op_type == OPERAND_IMM)
585     {
586         int addrReg;
587         int imm = mAddrMode.immediate;
588         if(imm >= 0 && imm < (1<<12))
589             *mPC++ = A64_ADD_IMM_X(mTmpReg1, mZeroReg, imm, 0);
590         else if(imm < 0 && -imm < (1<<12))
591             *mPC++ = A64_SUB_IMM_X(mTmpReg1, mZeroReg, -imm, 0);
592         else
593         {
594             NOT_IMPLEMENTED();
595             return;
596         }
597 
598         addrReg = Rn;
599         if(mAddrMode.preindex == true || mAddrMode.postindex == true)
600         {
601             *mPC++ = A64_ADD_X(mTmpReg2, addrReg, mTmpReg1);
602             if(mAddrMode.preindex == true)
603                 addrReg = mTmpReg2;
604         }
605 
606         if(cc != AL)
607             *mPC++ = A64_B_COND(cc^1, 8);
608 
609         *mPC++ = A64_LDRSTR_Wm_SXTW_0(op, size, Rd, addrReg, mZeroReg);
610 
611         if(mAddrMode.writeback == true)
612             *mPC++ = A64_CSEL_X(Rn, mTmpReg2, Rn, cc);
613     }
614     else if(op_type == OPERAND_REG_OFFSET)
615     {
616         if(cc != AL)
617             *mPC++ = A64_B_COND(cc^1, 8);
618         *mPC++ = A64_LDRSTR_Wm_SXTW_0(op, size, Rd, Rn, mAddrMode.reg_offset);
619 
620     }
621     else if(op_type > OPERAND_UNSUPPORTED)
622     {
623         if(cc != AL)
624             *mPC++ = A64_B_COND(cc^1, 8);
625         *mPC++ = A64_LDRSTR_Wm_SXTW_0(op, size, Rd, Rn, mZeroReg);
626     }
627     else
628     {
629         NOT_IMPLEMENTED(); // Not required
630     }
631     return;
632 
633 }
ADDR_LDR(int cc,int Rd,int Rn,uint32_t op_type)634 void ArmToArm64Assembler::ADDR_LDR(int cc, int Rd, int Rn, uint32_t op_type)
635 {
636     return dataTransfer(opLDR, cc, Rd, Rn, op_type, 64);
637 }
ADDR_STR(int cc,int Rd,int Rn,uint32_t op_type)638 void ArmToArm64Assembler::ADDR_STR(int cc, int Rd, int Rn, uint32_t op_type)
639 {
640     return dataTransfer(opSTR, cc, Rd, Rn, op_type, 64);
641 }
LDR(int cc,int Rd,int Rn,uint32_t op_type)642 void ArmToArm64Assembler::LDR(int cc, int Rd, int Rn, uint32_t op_type)
643 {
644     return dataTransfer(opLDR, cc, Rd, Rn, op_type);
645 }
LDRB(int cc,int Rd,int Rn,uint32_t op_type)646 void ArmToArm64Assembler::LDRB(int cc, int Rd, int Rn, uint32_t op_type)
647 {
648     return dataTransfer(opLDRB, cc, Rd, Rn, op_type);
649 }
STR(int cc,int Rd,int Rn,uint32_t op_type)650 void ArmToArm64Assembler::STR(int cc, int Rd, int Rn, uint32_t op_type)
651 {
652     return dataTransfer(opSTR, cc, Rd, Rn, op_type);
653 }
654 
STRB(int cc,int Rd,int Rn,uint32_t op_type)655 void ArmToArm64Assembler::STRB(int cc, int Rd, int Rn, uint32_t op_type)
656 {
657     return dataTransfer(opSTRB, cc, Rd, Rn, op_type);
658 }
659 
LDRH(int cc,int Rd,int Rn,uint32_t op_type)660 void ArmToArm64Assembler::LDRH(int cc, int Rd, int Rn, uint32_t op_type)
661 {
662     return dataTransfer(opLDRH, cc, Rd, Rn, op_type);
663 }
LDRSB(int,int,int,uint32_t)664 void ArmToArm64Assembler::LDRSB(int /*cc*/, int /*Rd*/, int /*Rn*/, uint32_t /*offset*/)
665 {
666     NOT_IMPLEMENTED(); //Not required
667 }
LDRSH(int,int,int,uint32_t)668 void ArmToArm64Assembler::LDRSH(int /*cc*/, int /*Rd*/, int /*Rn*/, uint32_t /*offset*/)
669 {
670     NOT_IMPLEMENTED(); //Not required
671 }
672 
STRH(int cc,int Rd,int Rn,uint32_t op_type)673 void ArmToArm64Assembler::STRH(int cc, int Rd, int Rn, uint32_t op_type)
674 {
675     return dataTransfer(opSTRH, cc, Rd, Rn, op_type);
676 }
677 
678 // ----------------------------------------------------------------------------
679 // block data transfer...
680 // ----------------------------------------------------------------------------
LDM(int cc,int dir,int Rn,int W,uint32_t reg_list)681 void ArmToArm64Assembler::LDM(int cc, int dir,
682         int Rn, int W, uint32_t reg_list)
683 {
684     const int XSP = 31;
685     if(cc != AL || dir != IA || W == 0 || Rn != SP)
686     {
687         NOT_IMPLEMENTED();
688         return;
689     }
690 
691     for(int i = 0; i < 32; ++i)
692     {
693         if((reg_list & (1 << i)))
694         {
695             int reg = i;
696             int size = 16;
697             *mPC++ = A64_LDR_IMM_PostIndex(reg, XSP, size);
698         }
699     }
700 }
701 
STM(int cc,int dir,int Rn,int W,uint32_t reg_list)702 void ArmToArm64Assembler::STM(int cc, int dir,
703         int Rn, int W, uint32_t reg_list)
704 {
705     const int XSP = 31;
706     if(cc != AL || dir != DB || W == 0 || Rn != SP)
707     {
708         NOT_IMPLEMENTED();
709         return;
710     }
711 
712     for(int i = 31; i >= 0; --i)
713     {
714         if((reg_list & (1 << i)))
715         {
716             int size = -16;
717             int reg  = i;
718             *mPC++ = A64_STR_IMM_PreIndex(reg, XSP, size);
719         }
720     }
721 }
722 
723 // ----------------------------------------------------------------------------
724 // special...
725 // ----------------------------------------------------------------------------
SWP(int,int,int,int)726 void ArmToArm64Assembler::SWP(int /*cc*/, int /*Rn*/, int /*Rd*/, int /*Rm*/)
727 {
728     NOT_IMPLEMENTED(); //Not required
729 }
SWPB(int,int,int,int)730 void ArmToArm64Assembler::SWPB(int /*cc*/, int /*Rn*/, int /*Rd*/, int /*Rm*/)
731 {
732     NOT_IMPLEMENTED(); //Not required
733 }
SWI(int,uint32_t)734 void ArmToArm64Assembler::SWI(int /*cc*/, uint32_t /*comment*/)
735 {
736     NOT_IMPLEMENTED(); //Not required
737 }
738 
739 // ----------------------------------------------------------------------------
740 // DSP instructions...
741 // ----------------------------------------------------------------------------
PLD(int,uint32_t)742 void ArmToArm64Assembler::PLD(int /*Rn*/, uint32_t /*offset*/) {
743     NOT_IMPLEMENTED(); //Not required
744 }
745 
CLZ(int,int,int)746 void ArmToArm64Assembler::CLZ(int /*cc*/, int /*Rd*/, int /*Rm*/)
747 {
748     NOT_IMPLEMENTED(); //Not required
749 }
750 
QADD(int,int,int,int)751 void ArmToArm64Assembler::QADD(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/)
752 {
753     NOT_IMPLEMENTED(); //Not required
754 }
755 
QDADD(int,int,int,int)756 void ArmToArm64Assembler::QDADD(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/)
757 {
758     NOT_IMPLEMENTED(); //Not required
759 }
760 
QSUB(int,int,int,int)761 void ArmToArm64Assembler::QSUB(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/)
762 {
763     NOT_IMPLEMENTED(); //Not required
764 }
765 
QDSUB(int,int,int,int)766 void ArmToArm64Assembler::QDSUB(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/)
767 {
768     NOT_IMPLEMENTED(); //Not required
769 }
770 
771 // ----------------------------------------------------------------------------
772 // 16 x 16 multiplication
773 // ----------------------------------------------------------------------------
SMUL(int cc,int xy,int Rd,int Rm,int Rs)774 void ArmToArm64Assembler::SMUL(int cc, int xy,
775                 int Rd, int Rm, int Rs)
776 {
777     if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required
778 
779     if (xy & xyTB)
780         *mPC++ = A64_SBFM_W(mTmpReg1, Rm, 16, 31);
781     else
782         *mPC++ = A64_SBFM_W(mTmpReg1, Rm, 0, 15);
783 
784     if (xy & xyBT)
785         *mPC++ = A64_SBFM_W(mTmpReg2, Rs, 16, 31);
786     else
787         *mPC++ = A64_SBFM_W(mTmpReg2, Rs, 0, 15);
788 
789     *mPC++ = A64_MADD_W(Rd,mTmpReg1,mTmpReg2, mZeroReg);
790 }
791 // ----------------------------------------------------------------------------
792 // 32 x 16 multiplication
793 // ----------------------------------------------------------------------------
SMULW(int cc,int y,int Rd,int Rm,int Rs)794 void ArmToArm64Assembler::SMULW(int cc, int y, int Rd, int Rm, int Rs)
795 {
796     if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required
797 
798     if (y & yT)
799         *mPC++ = A64_SBFM_W(mTmpReg1, Rs, 16, 31);
800     else
801         *mPC++ = A64_SBFM_W(mTmpReg1, Rs, 0, 15);
802 
803     *mPC++ = A64_SBFM_W(mTmpReg2, Rm, 0, 31);
804     *mPC++ = A64_SMADDL(mTmpReg3,mTmpReg1,mTmpReg2, mZeroReg);
805     *mPC++ = A64_UBFM_X(Rd,mTmpReg3, 16, 47);
806 }
807 // ----------------------------------------------------------------------------
808 // 16 x 16 multiplication and accumulate
809 // ----------------------------------------------------------------------------
SMLA(int cc,int xy,int Rd,int Rm,int Rs,int Rn)810 void ArmToArm64Assembler::SMLA(int cc, int xy, int Rd, int Rm, int Rs, int Rn)
811 {
812     if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required
813     if(xy != xyBB) { NOT_IMPLEMENTED(); return;} //Not required
814 
815     *mPC++ = A64_SBFM_W(mTmpReg1, Rm, 0, 15);
816     *mPC++ = A64_SBFM_W(mTmpReg2, Rs, 0, 15);
817     *mPC++ = A64_MADD_W(Rd, mTmpReg1, mTmpReg2, Rn);
818 }
819 
SMLAL(int,int,int,int,int,int)820 void ArmToArm64Assembler::SMLAL(int /*cc*/, int /*xy*/,
821                 int /*RdHi*/, int /*RdLo*/, int /*Rs*/, int /*Rm*/)
822 {
823     NOT_IMPLEMENTED(); //Not required
824     return;
825 }
826 
SMLAW(int,int,int,int,int,int)827 void ArmToArm64Assembler::SMLAW(int /*cc*/, int /*y*/,
828                 int /*Rd*/, int /*Rm*/, int /*Rs*/, int /*Rn*/)
829 {
830     NOT_IMPLEMENTED(); //Not required
831     return;
832 }
833 
834 // ----------------------------------------------------------------------------
835 // Byte/half word extract and extend
836 // ----------------------------------------------------------------------------
UXTB16(int cc,int Rd,int Rm,int rotate)837 void ArmToArm64Assembler::UXTB16(int cc, int Rd, int Rm, int rotate)
838 {
839     if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required
840 
841     *mPC++ = A64_EXTR_W(mTmpReg1, Rm, Rm, rotate * 8);
842 
843     uint32_t imm = 0x00FF00FF;
844     *mPC++ = A64_MOVZ_W(mTmpReg2, imm & 0xFFFF, 0);
845     *mPC++ = A64_MOVK_W(mTmpReg2, (imm >> 16) & 0x0000FFFF, 16);
846     *mPC++ = A64_AND_W(Rd,mTmpReg1, mTmpReg2);
847 }
848 
849 // ----------------------------------------------------------------------------
850 // Bit manipulation
851 // ----------------------------------------------------------------------------
UBFX(int cc,int Rd,int Rn,int lsb,int width)852 void ArmToArm64Assembler::UBFX(int cc, int Rd, int Rn, int lsb, int width)
853 {
854     if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required
855     *mPC++ = A64_UBFM_W(Rd, Rn, lsb, lsb + width - 1);
856 }
857 // ----------------------------------------------------------------------------
858 // Shifters...
859 // ----------------------------------------------------------------------------
buildImmediate(uint32_t immediate,uint32_t & rot,uint32_t & imm)860 int ArmToArm64Assembler::buildImmediate(
861         uint32_t immediate, uint32_t& rot, uint32_t& imm)
862 {
863     rot = 0;
864     imm = immediate;
865     return 0; // Always true
866 }
867 
868 
isValidImmediate(uint32_t immediate)869 bool ArmToArm64Assembler::isValidImmediate(uint32_t immediate)
870 {
871     uint32_t rot, imm;
872     return buildImmediate(immediate, rot, imm) == 0;
873 }
874 
imm(uint32_t immediate)875 uint32_t ArmToArm64Assembler::imm(uint32_t immediate)
876 {
877     mAddrMode.immediate = immediate;
878     mAddrMode.writeback = false;
879     mAddrMode.preindex  = false;
880     mAddrMode.postindex = false;
881     return OPERAND_IMM;
882 
883 }
884 
reg_imm(int Rm,int type,uint32_t shift)885 uint32_t ArmToArm64Assembler::reg_imm(int Rm, int type, uint32_t shift)
886 {
887     mAddrMode.reg_imm_Rm = Rm;
888     mAddrMode.reg_imm_type = type;
889     mAddrMode.reg_imm_shift = shift;
890     return OPERAND_REG_IMM;
891 }
892 
reg_rrx(int)893 uint32_t ArmToArm64Assembler::reg_rrx(int /*Rm*/)
894 {
895     NOT_IMPLEMENTED();
896     return OPERAND_UNSUPPORTED;
897 }
898 
reg_reg(int,int,int)899 uint32_t ArmToArm64Assembler::reg_reg(int /*Rm*/, int /*type*/, int /*Rs*/)
900 {
901     NOT_IMPLEMENTED(); //Not required
902     return OPERAND_UNSUPPORTED;
903 }
904 // ----------------------------------------------------------------------------
905 // Addressing modes...
906 // ----------------------------------------------------------------------------
immed12_pre(int32_t immed12,int W)907 uint32_t ArmToArm64Assembler::immed12_pre(int32_t immed12, int W)
908 {
909     mAddrMode.immediate = immed12;
910     mAddrMode.writeback = W;
911     mAddrMode.preindex  = true;
912     mAddrMode.postindex = false;
913     return OPERAND_IMM;
914 }
915 
immed12_post(int32_t immed12)916 uint32_t ArmToArm64Assembler::immed12_post(int32_t immed12)
917 {
918     mAddrMode.immediate = immed12;
919     mAddrMode.writeback = true;
920     mAddrMode.preindex  = false;
921     mAddrMode.postindex = true;
922     return OPERAND_IMM;
923 }
924 
reg_scale_pre(int Rm,int type,uint32_t shift,int W)925 uint32_t ArmToArm64Assembler::reg_scale_pre(int Rm, int type,
926         uint32_t shift, int W)
927 {
928     if(type != 0 || shift != 0 || W != 0)
929     {
930         NOT_IMPLEMENTED(); //Not required
931         return OPERAND_UNSUPPORTED;
932     }
933     else
934     {
935         mAddrMode.reg_offset = Rm;
936         return OPERAND_REG_OFFSET;
937     }
938 }
939 
reg_scale_post(int,int,uint32_t)940 uint32_t ArmToArm64Assembler::reg_scale_post(int /*Rm*/, int /*type*/, uint32_t /*shift*/)
941 {
942     NOT_IMPLEMENTED(); //Not required
943     return OPERAND_UNSUPPORTED;
944 }
945 
immed8_pre(int32_t immed8,int W)946 uint32_t ArmToArm64Assembler::immed8_pre(int32_t immed8, int W)
947 {
948     mAddrMode.immediate = immed8;
949     mAddrMode.writeback = W;
950     mAddrMode.preindex  = true;
951     mAddrMode.postindex = false;
952     return OPERAND_IMM;
953 }
954 
immed8_post(int32_t immed8)955 uint32_t ArmToArm64Assembler::immed8_post(int32_t immed8)
956 {
957     mAddrMode.immediate = immed8;
958     mAddrMode.writeback = true;
959     mAddrMode.preindex  = false;
960     mAddrMode.postindex = true;
961     return OPERAND_IMM;
962 }
963 
reg_pre(int Rm,int W)964 uint32_t ArmToArm64Assembler::reg_pre(int Rm, int W)
965 {
966     if(W != 0)
967     {
968         NOT_IMPLEMENTED(); //Not required
969         return OPERAND_UNSUPPORTED;
970     }
971     else
972     {
973         mAddrMode.reg_offset = Rm;
974         return OPERAND_REG_OFFSET;
975     }
976 }
977 
reg_post(int)978 uint32_t ArmToArm64Assembler::reg_post(int /*Rm*/)
979 {
980     NOT_IMPLEMENTED(); //Not required
981     return OPERAND_UNSUPPORTED;
982 }
983 
984 // ----------------------------------------------------------------------------
985 // A64 instructions
986 // ----------------------------------------------------------------------------
987 
988 static const char * dataTransferOpName[] =
989 {
990     "LDR","LDRB","LDRH","STR","STRB","STRH"
991 };
992 
993 static const uint32_t dataTransferOpCode [] =
994 {
995     ((0xB8u << 24) | (0x3 << 21) | (0x6 << 13) | (0x0 << 12) |(0x1 << 11)),
996     ((0x38u << 24) | (0x3 << 21) | (0x6 << 13) | (0x1 << 12) |(0x1 << 11)),
997     ((0x78u << 24) | (0x3 << 21) | (0x6 << 13) | (0x0 << 12) |(0x1 << 11)),
998     ((0xB8u << 24) | (0x1 << 21) | (0x6 << 13) | (0x0 << 12) |(0x1 << 11)),
999     ((0x38u << 24) | (0x1 << 21) | (0x6 << 13) | (0x1 << 12) |(0x1 << 11)),
1000     ((0x78u << 24) | (0x1 << 21) | (0x6 << 13) | (0x0 << 12) |(0x1 << 11))
1001 };
A64_LDRSTR_Wm_SXTW_0(uint32_t op,uint32_t size,uint32_t Rt,uint32_t Rn,uint32_t Rm)1002 uint32_t ArmToArm64Assembler::A64_LDRSTR_Wm_SXTW_0(uint32_t op,
1003                             uint32_t size, uint32_t Rt,
1004                             uint32_t Rn, uint32_t Rm)
1005 {
1006     if(size == 32)
1007     {
1008         LOG_INSTR("%s W%d, [X%d, W%d, SXTW #0]\n",
1009                    dataTransferOpName[op], Rt, Rn, Rm);
1010         return(dataTransferOpCode[op] | (Rm << 16) | (Rn << 5) | Rt);
1011     }
1012     else
1013     {
1014         LOG_INSTR("%s X%d, [X%d, W%d, SXTW #0]\n",
1015                   dataTransferOpName[op], Rt, Rn, Rm);
1016         return(dataTransferOpCode[op] | (0x1<<30) | (Rm<<16) | (Rn<<5)|Rt);
1017     }
1018 }
1019 
A64_STR_IMM_PreIndex(uint32_t Rt,uint32_t Rn,int32_t simm)1020 uint32_t ArmToArm64Assembler::A64_STR_IMM_PreIndex(uint32_t Rt,
1021                             uint32_t Rn, int32_t simm)
1022 {
1023     if(Rn == 31)
1024         LOG_INSTR("STR W%d, [SP, #%d]!\n", Rt, simm);
1025     else
1026         LOG_INSTR("STR W%d, [X%d, #%d]!\n", Rt, Rn, simm);
1027 
1028     uint32_t imm9 = (unsigned)(simm) & 0x01FF;
1029     return (0xB8 << 24) | (imm9 << 12) | (0x3 << 10) | (Rn << 5) | Rt;
1030 }
1031 
A64_LDR_IMM_PostIndex(uint32_t Rt,uint32_t Rn,int32_t simm)1032 uint32_t ArmToArm64Assembler::A64_LDR_IMM_PostIndex(uint32_t Rt,
1033                             uint32_t Rn, int32_t simm)
1034 {
1035     if(Rn == 31)
1036         LOG_INSTR("LDR W%d, [SP], #%d\n",Rt,simm);
1037     else
1038         LOG_INSTR("LDR W%d, [X%d], #%d\n",Rt, Rn, simm);
1039 
1040     uint32_t imm9 = (unsigned)(simm) & 0x01FF;
1041     return (0xB8 << 24) | (0x1 << 22) |
1042              (imm9 << 12) | (0x1 << 10) | (Rn << 5) | Rt;
1043 
1044 }
A64_ADD_X_Wm_SXTW(uint32_t Rd,uint32_t Rn,uint32_t Rm,uint32_t amount)1045 uint32_t ArmToArm64Assembler::A64_ADD_X_Wm_SXTW(uint32_t Rd,
1046                                uint32_t Rn,
1047                                uint32_t Rm,
1048                                uint32_t amount)
1049 {
1050     LOG_INSTR("ADD X%d, X%d, W%d, SXTW #%d\n", Rd, Rn, Rm, amount);
1051     return ((0x8B << 24) | (0x1 << 21) |(Rm << 16) |
1052               (0x6 << 13) | (amount << 10) | (Rn << 5) | Rd);
1053 
1054 }
1055 
A64_SUB_X_Wm_SXTW(uint32_t Rd,uint32_t Rn,uint32_t Rm,uint32_t amount)1056 uint32_t ArmToArm64Assembler::A64_SUB_X_Wm_SXTW(uint32_t Rd,
1057                                uint32_t Rn,
1058                                uint32_t Rm,
1059                                uint32_t amount)
1060 {
1061     LOG_INSTR("SUB X%d, X%d, W%d, SXTW #%d\n", Rd, Rn, Rm, amount);
1062     return ((0xCB << 24) | (0x1 << 21) |(Rm << 16) |
1063             (0x6 << 13) | (amount << 10) | (Rn << 5) | Rd);
1064 
1065 }
1066 
A64_B_COND(uint32_t cc,uint32_t offset)1067 uint32_t ArmToArm64Assembler::A64_B_COND(uint32_t cc, uint32_t offset)
1068 {
1069     LOG_INSTR("B.%s #.+%d\n", cc_codes[cc], offset);
1070     return (0x54 << 24) | ((offset/4) << 5) | (cc);
1071 
1072 }
A64_ADD_X(uint32_t Rd,uint32_t Rn,uint32_t Rm,uint32_t shift,uint32_t amount)1073 uint32_t ArmToArm64Assembler::A64_ADD_X(uint32_t Rd, uint32_t Rn,
1074                                           uint32_t Rm, uint32_t shift,
1075                                           uint32_t amount)
1076 {
1077     LOG_INSTR("ADD X%d, X%d, X%d, %s #%d\n",
1078                Rd, Rn, Rm, shift_codes[shift], amount);
1079     return ((0x8B << 24) | (shift << 22) | ( Rm << 16) |
1080             (amount << 10) |(Rn << 5) | Rd);
1081 }
A64_ADD_IMM_X(uint32_t Rd,uint32_t Rn,uint32_t imm,uint32_t shift)1082 uint32_t ArmToArm64Assembler::A64_ADD_IMM_X(uint32_t Rd, uint32_t Rn,
1083                                           uint32_t imm, uint32_t shift)
1084 {
1085     LOG_INSTR("ADD X%d, X%d, #%d, LSL #%d\n", Rd, Rn, imm, shift);
1086     return (0x91 << 24) | ((shift/12) << 22) | (imm << 10) | (Rn << 5) | Rd;
1087 }
1088 
A64_SUB_IMM_X(uint32_t Rd,uint32_t Rn,uint32_t imm,uint32_t shift)1089 uint32_t ArmToArm64Assembler::A64_SUB_IMM_X(uint32_t Rd, uint32_t Rn,
1090                                           uint32_t imm, uint32_t shift)
1091 {
1092     LOG_INSTR("SUB X%d, X%d, #%d, LSL #%d\n", Rd, Rn, imm, shift);
1093     return (0xD1 << 24) | ((shift/12) << 22) | (imm << 10) | (Rn << 5) | Rd;
1094 }
1095 
A64_ADD_W(uint32_t Rd,uint32_t Rn,uint32_t Rm,uint32_t shift,uint32_t amount)1096 uint32_t ArmToArm64Assembler::A64_ADD_W(uint32_t Rd, uint32_t Rn,
1097                                           uint32_t Rm, uint32_t shift,
1098                                           uint32_t amount)
1099 {
1100     LOG_INSTR("ADD W%d, W%d, W%d, %s #%d\n",
1101                Rd, Rn, Rm, shift_codes[shift], amount);
1102     return ((0x0B << 24) | (shift << 22) | ( Rm << 16) |
1103             (amount << 10) |(Rn << 5) | Rd);
1104 }
1105 
A64_SUB_W(uint32_t Rd,uint32_t Rn,uint32_t Rm,uint32_t shift,uint32_t amount,uint32_t setflag)1106 uint32_t ArmToArm64Assembler::A64_SUB_W(uint32_t Rd, uint32_t Rn,
1107                                           uint32_t Rm, uint32_t shift,
1108                                           uint32_t amount,
1109                                           uint32_t setflag)
1110 {
1111     if(setflag == 0)
1112     {
1113         LOG_INSTR("SUB W%d, W%d, W%d, %s #%d\n",
1114                Rd, Rn, Rm, shift_codes[shift], amount);
1115         return ((0x4B << 24) | (shift << 22) | ( Rm << 16) |
1116                 (amount << 10) |(Rn << 5) | Rd);
1117     }
1118     else
1119     {
1120         LOG_INSTR("SUBS W%d, W%d, W%d, %s #%d\n",
1121                    Rd, Rn, Rm, shift_codes[shift], amount);
1122         return ((0x6B << 24) | (shift << 22) | ( Rm << 16) |
1123                 (amount << 10) |(Rn << 5) | Rd);
1124     }
1125 }
1126 
A64_AND_W(uint32_t Rd,uint32_t Rn,uint32_t Rm,uint32_t shift,uint32_t amount)1127 uint32_t ArmToArm64Assembler::A64_AND_W(uint32_t Rd, uint32_t Rn,
1128                                           uint32_t Rm, uint32_t shift,
1129                                           uint32_t amount)
1130 {
1131     LOG_INSTR("AND W%d, W%d, W%d, %s #%d\n",
1132                Rd, Rn, Rm, shift_codes[shift], amount);
1133     return ((0x0A << 24) | (shift << 22) | ( Rm << 16) |
1134             (amount << 10) |(Rn << 5) | Rd);
1135 }
1136 
A64_ORR_W(uint32_t Rd,uint32_t Rn,uint32_t Rm,uint32_t shift,uint32_t amount)1137 uint32_t ArmToArm64Assembler::A64_ORR_W(uint32_t Rd, uint32_t Rn,
1138                                           uint32_t Rm, uint32_t shift,
1139                                           uint32_t amount)
1140 {
1141     LOG_INSTR("ORR W%d, W%d, W%d, %s #%d\n",
1142                Rd, Rn, Rm, shift_codes[shift], amount);
1143     return ((0x2A << 24) | (shift << 22) | ( Rm << 16) |
1144             (amount << 10) |(Rn << 5) | Rd);
1145 }
1146 
A64_ORN_W(uint32_t Rd,uint32_t Rn,uint32_t Rm,uint32_t shift,uint32_t amount)1147 uint32_t ArmToArm64Assembler::A64_ORN_W(uint32_t Rd, uint32_t Rn,
1148                                           uint32_t Rm, uint32_t shift,
1149                                           uint32_t amount)
1150 {
1151     LOG_INSTR("ORN W%d, W%d, W%d, %s #%d\n",
1152                Rd, Rn, Rm, shift_codes[shift], amount);
1153     return ((0x2A << 24) | (shift << 22) | (0x1 << 21) | ( Rm << 16) |
1154             (amount << 10) |(Rn << 5) | Rd);
1155 }
1156 
A64_CSEL_X(uint32_t Rd,uint32_t Rn,uint32_t Rm,uint32_t cond)1157 uint32_t ArmToArm64Assembler::A64_CSEL_X(uint32_t Rd, uint32_t Rn,
1158                                            uint32_t Rm, uint32_t cond)
1159 {
1160     LOG_INSTR("CSEL X%d, X%d, X%d, %s\n", Rd, Rn, Rm, cc_codes[cond]);
1161     return ((0x9A << 24)|(0x1 << 23)|(Rm << 16) |(cond << 12)| (Rn << 5) | Rd);
1162 }
1163 
A64_CSEL_W(uint32_t Rd,uint32_t Rn,uint32_t Rm,uint32_t cond)1164 uint32_t ArmToArm64Assembler::A64_CSEL_W(uint32_t Rd, uint32_t Rn,
1165                                            uint32_t Rm, uint32_t cond)
1166 {
1167     LOG_INSTR("CSEL W%d, W%d, W%d, %s\n", Rd, Rn, Rm, cc_codes[cond]);
1168     return ((0x1A << 24)|(0x1 << 23)|(Rm << 16) |(cond << 12)| (Rn << 5) | Rd);
1169 }
1170 
A64_RET(uint32_t Rn)1171 uint32_t ArmToArm64Assembler::A64_RET(uint32_t Rn)
1172 {
1173     LOG_INSTR("RET X%d\n", Rn);
1174     return ((0xD6 << 24) | (0x1 << 22) | (0x1F << 16) | (Rn << 5));
1175 }
1176 
A64_MOVZ_X(uint32_t Rd,uint32_t imm,uint32_t shift)1177 uint32_t ArmToArm64Assembler::A64_MOVZ_X(uint32_t Rd, uint32_t imm,
1178                                          uint32_t shift)
1179 {
1180     LOG_INSTR("MOVZ X%d, #0x%x, LSL #%d\n", Rd, imm, shift);
1181     return(0xD2 << 24) | (0x1 << 23) | ((shift/16) << 21) |  (imm << 5) | Rd;
1182 }
1183 
A64_MOVK_W(uint32_t Rd,uint32_t imm,uint32_t shift)1184 uint32_t ArmToArm64Assembler::A64_MOVK_W(uint32_t Rd, uint32_t imm,
1185                                          uint32_t shift)
1186 {
1187     LOG_INSTR("MOVK W%d, #0x%x, LSL #%d\n", Rd, imm, shift);
1188     return (0x72 << 24) | (0x1 << 23) | ((shift/16) << 21) | (imm << 5) | Rd;
1189 }
1190 
A64_MOVZ_W(uint32_t Rd,uint32_t imm,uint32_t shift)1191 uint32_t ArmToArm64Assembler::A64_MOVZ_W(uint32_t Rd, uint32_t imm,
1192                                          uint32_t shift)
1193 {
1194     LOG_INSTR("MOVZ W%d, #0x%x, LSL #%d\n", Rd, imm, shift);
1195     return(0x52 << 24) | (0x1 << 23) | ((shift/16) << 21) |  (imm << 5) | Rd;
1196 }
1197 
A64_SMADDL(uint32_t Rd,uint32_t Rn,uint32_t Rm,uint32_t Ra)1198 uint32_t ArmToArm64Assembler::A64_SMADDL(uint32_t Rd, uint32_t Rn,
1199                                            uint32_t Rm, uint32_t Ra)
1200 {
1201     LOG_INSTR("SMADDL X%d, W%d, W%d, X%d\n",Rd, Rn, Rm, Ra);
1202     return ((0x9B << 24) | (0x1 << 21) | (Rm << 16)|(Ra << 10)|(Rn << 5) | Rd);
1203 }
1204 
A64_MADD_W(uint32_t Rd,uint32_t Rn,uint32_t Rm,uint32_t Ra)1205 uint32_t ArmToArm64Assembler::A64_MADD_W(uint32_t Rd, uint32_t Rn,
1206                                            uint32_t Rm, uint32_t Ra)
1207 {
1208     LOG_INSTR("MADD W%d, W%d, W%d, W%d\n",Rd, Rn, Rm, Ra);
1209     return ((0x1B << 24) | (Rm << 16) | (Ra << 10) |(Rn << 5) | Rd);
1210 }
1211 
A64_SBFM_W(uint32_t Rd,uint32_t Rn,uint32_t immr,uint32_t imms)1212 uint32_t ArmToArm64Assembler::A64_SBFM_W(uint32_t Rd, uint32_t Rn,
1213                                            uint32_t immr, uint32_t imms)
1214 {
1215     LOG_INSTR("SBFM W%d, W%d, #%d, #%d\n", Rd, Rn, immr, imms);
1216     return ((0x13 << 24) | (immr << 16) | (imms << 10) | (Rn << 5) | Rd);
1217 
1218 }
A64_UBFM_W(uint32_t Rd,uint32_t Rn,uint32_t immr,uint32_t imms)1219 uint32_t ArmToArm64Assembler::A64_UBFM_W(uint32_t Rd, uint32_t Rn,
1220                                            uint32_t immr, uint32_t imms)
1221 {
1222     LOG_INSTR("UBFM W%d, W%d, #%d, #%d\n", Rd, Rn, immr, imms);
1223     return ((0x53 << 24) | (immr << 16) | (imms << 10) | (Rn << 5) | Rd);
1224 
1225 }
A64_UBFM_X(uint32_t Rd,uint32_t Rn,uint32_t immr,uint32_t imms)1226 uint32_t ArmToArm64Assembler::A64_UBFM_X(uint32_t Rd, uint32_t Rn,
1227                                            uint32_t immr, uint32_t imms)
1228 {
1229     LOG_INSTR("UBFM X%d, X%d, #%d, #%d\n", Rd, Rn, immr, imms);
1230     return ((0xD3 << 24) | (0x1 << 22) |
1231             (immr << 16) | (imms << 10) | (Rn << 5) | Rd);
1232 
1233 }
A64_EXTR_W(uint32_t Rd,uint32_t Rn,uint32_t Rm,uint32_t lsb)1234 uint32_t ArmToArm64Assembler::A64_EXTR_W(uint32_t Rd, uint32_t Rn,
1235                                            uint32_t Rm, uint32_t lsb)
1236 {
1237     LOG_INSTR("EXTR W%d, W%d, W%d, #%d\n", Rd, Rn, Rm, lsb);
1238     return (0x13 << 24)|(0x1 << 23) | (Rm << 16) | (lsb << 10)|(Rn << 5) | Rd;
1239 }
1240 
1241 }; // namespace android
1242 
1243