blob: 0e4f7df9a2ffea47c3eec73c4abb15f70bbb1033 [file] [log] [blame]
Ashok Bhat658f89d2013-02-28 18:32:03 +00001/*
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 "ArmToAarch64Assembler"
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/Aarch64Assembler.h"
40#include "codeflinger/CodeCache.h"
41#include "codeflinger/Aarch64Disassembler.h"
42
43
44/*
45** --------------------------------------------
46** Support for Aarch64 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 AArch64 instructions.
53**
54** ----------------------
55** ArmToAarch64Assembler
56** ----------------------
57**
58** - Subclassed from ArmAssemblerInterface
59**
60** - Translates each ArmAssemblerInterface call to generate
61** one or more Aarch64 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 Aarch64 instructions. These functions also log the instruction
69** to LOG, if AARCH64_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 aarch64_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 Aarch64
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** ArmToAarch64Assembler unit test bench
93** --------------------------------------------
94**
95** - Tests ArmToAarch64Assembler 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** Aarch64 disassembler
109** ----------------------
110** - This disassembler disassembles only those machine codes which can be
111** generated by ArmToAarch64Assembler. 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** - ArmToAarch64Assembler maps these functions to appropriate 64 bit
126** functions.
127**
128** ----------------------
129** GGLAssembler changes
130** ----------------------
131** - Since ArmToAarch64Assembler can generate 4 Aarch64 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 AARCH64_ASM_DEBUG 0
144
145#if AARCH64_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
153namespace android {
154
155static const char* shift_codes[] =
156{
157 "LSL", "LSR", "ASR", "ROR"
158};
159static 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
166ArmToAarch64Assembler::ArmToAarch64Assembler(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
178ArmToAarch64Assembler::ArmToAarch64Assembler(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
190ArmToAarch64Assembler::~ArmToAarch64Assembler()
191{
192}
193
194uint32_t* ArmToAarch64Assembler::pc() const
195{
196 return mPC;
197}
198
199uint32_t* ArmToAarch64Assembler::base() const
200{
201 return mBase;
202}
203
204void ArmToAarch64Assembler::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 AARCH64_ASM_DEBUG
215 ALOGI("RESET\n");
216#endif
217}
218
219int ArmToAarch64Assembler::getCodegenArch()
220{
221 return CODEGEN_ARCH_AARCH64;
222}
223
224// ----------------------------------------------------------------------------
225
226void ArmToAarch64Assembler::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 ::aarch64_disassemble(*i, instr);
250 printf("%s\n", instr);
251 }
252 i++;
253 }
254}
255
256void ArmToAarch64Assembler::comment(const char* string)
257{
258 mComments.add(mPC, string);
259 LOG_INSTR("//%s\n", string);
260}
261
262void ArmToAarch64Assembler::label(const char* theLabel)
263{
264 mLabels.add(theLabel, mPC);
265 mLabelsInverseMapping.add(mPC, theLabel);
266 LOG_LABEL("%s:\n", theLabel);
267}
268
269void ArmToAarch64Assembler::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
276void ArmToAarch64Assembler::BL(int cc, const char* label)
277{
278 NOT_IMPLEMENTED(); //Not Required
279}
280
281// ----------------------------------------------------------------------------
282//Prolog/Epilog & Generate...
283// ----------------------------------------------------------------------------
284
285void ArmToAarch64Assembler::prolog()
286{
287 // write prolog code
288 mPrologPC = mPC;
289 *mPC++ = A64_MOVZ_X(mZeroReg,0,0);
290}
291
292void ArmToAarch64Assembler::epilog(uint32_t touched)
293{
294 // write epilog code
295 static const int XLR = 30;
296 *mPC++ = A64_RET(XLR);
297}
298
299int ArmToAarch64Assembler::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
332uint32_t* ArmToAarch64Assembler::pcForLabel(const char* label)
333{
334 return mLabels.valueFor(label);
335}
336
337// ----------------------------------------------------------------------------
338// Data Processing...
339// ----------------------------------------------------------------------------
340void ArmToAarch64Assembler::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
408void ArmToAarch64Assembler::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
463void ArmToAarch64Assembler::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
498void ArmToAarch64Assembler::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// ----------------------------------------------------------------------------
519void ArmToAarch64Assembler::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}
527void ArmToAarch64Assembler::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}
533void ArmToAarch64Assembler::UMULL(int cc, int s,
534 int RdLo, int RdHi, int Rm, int Rs)
535{
536 NOT_IMPLEMENTED(); //Not required
537}
538void ArmToAarch64Assembler::UMUAL(int cc, int s,
539 int RdLo, int RdHi, int Rm, int Rs)
540{
541 NOT_IMPLEMENTED(); //Not required
542}
543void ArmToAarch64Assembler::SMULL(int cc, int s,
544 int RdLo, int RdHi, int Rm, int Rs)
545{
546 NOT_IMPLEMENTED(); //Not required
547}
548void ArmToAarch64Assembler::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// ----------------------------------------------------------------------------
557void ArmToAarch64Assembler::B(int cc, uint32_t* pc){
558 NOT_IMPLEMENTED(); //Not required
559}
560
561void ArmToAarch64Assembler::BL(int cc, uint32_t* pc){
562 NOT_IMPLEMENTED(); //Not required
563}
564
565void ArmToAarch64Assembler::BX(int cc, int Rn){
566 NOT_IMPLEMENTED(); //Not required
567}
568
569// ----------------------------------------------------------------------------
570// data transfer...
571// ----------------------------------------------------------------------------
572enum dataTransferOp
573{
574 opLDR,opLDRB,opLDRH,opSTR,opSTRB,opSTRH
575};
576
577void ArmToAarch64Assembler::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}
634void ArmToAarch64Assembler::ADDR_LDR(int cc, int Rd, int Rn, uint32_t op_type)
635{
636 return dataTransfer(opLDR, cc, Rd, Rn, op_type, 64);
637}
638void ArmToAarch64Assembler::ADDR_STR(int cc, int Rd, int Rn, uint32_t op_type)
639{
640 return dataTransfer(opSTR, cc, Rd, Rn, op_type, 64);
641}
642void ArmToAarch64Assembler::LDR(int cc, int Rd, int Rn, uint32_t op_type)
643{
644 return dataTransfer(opLDR, cc, Rd, Rn, op_type);
645}
646void ArmToAarch64Assembler::LDRB(int cc, int Rd, int Rn, uint32_t op_type)
647{
648 return dataTransfer(opLDRB, cc, Rd, Rn, op_type);
649}
650void ArmToAarch64Assembler::STR(int cc, int Rd, int Rn, uint32_t op_type)
651{
652 return dataTransfer(opSTR, cc, Rd, Rn, op_type);
653}
654
655void ArmToAarch64Assembler::STRB(int cc, int Rd, int Rn, uint32_t op_type)
656{
657 return dataTransfer(opSTRB, cc, Rd, Rn, op_type);
658}
659
660void ArmToAarch64Assembler::LDRH(int cc, int Rd, int Rn, uint32_t op_type)
661{
662 return dataTransfer(opLDRH, cc, Rd, Rn, op_type);
663}
664void ArmToAarch64Assembler::LDRSB(int cc, int Rd, int Rn, uint32_t offset)
665{
666 NOT_IMPLEMENTED(); //Not required
667}
668void ArmToAarch64Assembler::LDRSH(int cc, int Rd, int Rn, uint32_t offset)
669{
670 NOT_IMPLEMENTED(); //Not required
671}
672
673void ArmToAarch64Assembler::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// ----------------------------------------------------------------------------
681void ArmToAarch64Assembler::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
702void ArmToAarch64Assembler::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// ----------------------------------------------------------------------------
726void ArmToAarch64Assembler::SWP(int cc, int Rn, int Rd, int Rm)
727{
728 NOT_IMPLEMENTED(); //Not required
729}
730void ArmToAarch64Assembler::SWPB(int cc, int Rn, int Rd, int Rm)
731{
732 NOT_IMPLEMENTED(); //Not required
733}
734void ArmToAarch64Assembler::SWI(int cc, uint32_t comment)
735{
736 NOT_IMPLEMENTED(); //Not required
737}
738
739// ----------------------------------------------------------------------------
740// DSP instructions...
741// ----------------------------------------------------------------------------
742void ArmToAarch64Assembler::PLD(int Rn, uint32_t offset) {
743 NOT_IMPLEMENTED(); //Not required
744}
745
746void ArmToAarch64Assembler::CLZ(int cc, int Rd, int Rm)
747{
748 NOT_IMPLEMENTED(); //Not required
749}
750
751void ArmToAarch64Assembler::QADD(int cc, int Rd, int Rm, int Rn)
752{
753 NOT_IMPLEMENTED(); //Not required
754}
755
756void ArmToAarch64Assembler::QDADD(int cc, int Rd, int Rm, int Rn)
757{
758 NOT_IMPLEMENTED(); //Not required
759}
760
761void ArmToAarch64Assembler::QSUB(int cc, int Rd, int Rm, int Rn)
762{
763 NOT_IMPLEMENTED(); //Not required
764}
765
766void ArmToAarch64Assembler::QDSUB(int cc, int Rd, int Rm, int Rn)
767{
768 NOT_IMPLEMENTED(); //Not required
769}
770
771// ----------------------------------------------------------------------------
772// 16 x 16 multiplication
773// ----------------------------------------------------------------------------
774void ArmToAarch64Assembler::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// ----------------------------------------------------------------------------
794void ArmToAarch64Assembler::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// ----------------------------------------------------------------------------
810void ArmToAarch64Assembler::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
820void ArmToAarch64Assembler::SMLAL(int cc, int xy,
821 int RdHi, int RdLo, int Rs, int Rm)
822{
823 NOT_IMPLEMENTED(); //Not required
824 return;
825}
826
827void ArmToAarch64Assembler::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// ----------------------------------------------------------------------------
837void ArmToAarch64Assembler::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// ----------------------------------------------------------------------------
852void ArmToAarch64Assembler::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// ----------------------------------------------------------------------------
860int ArmToAarch64Assembler::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
869bool ArmToAarch64Assembler::isValidImmediate(uint32_t immediate)
870{
871 uint32_t rot, imm;
872 return buildImmediate(immediate, rot, imm) == 0;
873}
874
875uint32_t ArmToAarch64Assembler::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
885uint32_t ArmToAarch64Assembler::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
893uint32_t ArmToAarch64Assembler::reg_rrx(int Rm)
894{
895 NOT_IMPLEMENTED();
896 return OPERAND_UNSUPPORTED;
897}
898
899uint32_t ArmToAarch64Assembler::reg_reg(int Rm, int type, int Rs)
900{
901 NOT_IMPLEMENTED(); //Not required
902 return OPERAND_UNSUPPORTED;
903}
904// ----------------------------------------------------------------------------
905// Addressing modes...
906// ----------------------------------------------------------------------------
907uint32_t ArmToAarch64Assembler::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
916uint32_t ArmToAarch64Assembler::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
925uint32_t ArmToAarch64Assembler::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
940uint32_t ArmToAarch64Assembler::reg_scale_post(int Rm, int type, uint32_t shift)
941{
942 NOT_IMPLEMENTED(); //Not required
943 return OPERAND_UNSUPPORTED;
944}
945
946uint32_t ArmToAarch64Assembler::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
955uint32_t ArmToAarch64Assembler::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
964uint32_t ArmToAarch64Assembler::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
978uint32_t ArmToAarch64Assembler::reg_post(int Rm)
979{
980 NOT_IMPLEMENTED(); //Not required
981 return OPERAND_UNSUPPORTED;
982}
983
984// ----------------------------------------------------------------------------
985// A64 instructions
986// ----------------------------------------------------------------------------
987
988static const char * dataTransferOpName[] =
989{
990 "LDR","LDRB","LDRH","STR","STRB","STRH"
991};
992
993static 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};
1002uint32_t ArmToAarch64Assembler::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
1020uint32_t ArmToAarch64Assembler::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
1032uint32_t ArmToAarch64Assembler::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}
1045uint32_t ArmToAarch64Assembler::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
1056uint32_t ArmToAarch64Assembler::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
1067uint32_t ArmToAarch64Assembler::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}
1073uint32_t ArmToAarch64Assembler::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}
1082uint32_t ArmToAarch64Assembler::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
1089uint32_t ArmToAarch64Assembler::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
1096uint32_t ArmToAarch64Assembler::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
1106uint32_t ArmToAarch64Assembler::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
1127uint32_t ArmToAarch64Assembler::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
1137uint32_t ArmToAarch64Assembler::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
1147uint32_t ArmToAarch64Assembler::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
1157uint32_t ArmToAarch64Assembler::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
1164uint32_t ArmToAarch64Assembler::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
1171uint32_t ArmToAarch64Assembler::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
1177uint32_t ArmToAarch64Assembler::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
1184uint32_t ArmToAarch64Assembler::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
1191uint32_t ArmToAarch64Assembler::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
1198uint32_t ArmToAarch64Assembler::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
1205uint32_t ArmToAarch64Assembler::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
1212uint32_t ArmToAarch64Assembler::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}
1219uint32_t ArmToAarch64Assembler::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}
1226uint32_t ArmToAarch64Assembler::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}
1234uint32_t ArmToAarch64Assembler::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