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 __unused const char* shift_codes[] =
155 {
156 "LSL", "LSR", "ASR", "ROR"
157 };
158 static __unused 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 OK;
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 __unused 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