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