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