Arm64Assembler.cpp revision 3078b13b98ad8d29dcb2b7e3665c0c92944404a9
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
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
166ArmToArm64Assembler::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
178ArmToArm64Assembler::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
190ArmToArm64Assembler::~ArmToArm64Assembler()
191{
192}
193
194uint32_t* ArmToArm64Assembler::pc() const
195{
196    return mPC;
197}
198
199uint32_t* ArmToArm64Assembler::base() const
200{
201    return mBase;
202}
203
204void 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
219int ArmToArm64Assembler::getCodegenArch()
220{
221    return CODEGEN_ARCH_ARM64;
222}
223
224// ----------------------------------------------------------------------------
225
226void 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
256void ArmToArm64Assembler::comment(const char* string)
257{
258    mComments.add(mPC, string);
259    LOG_INSTR("//%s\n", string);
260}
261
262void ArmToArm64Assembler::label(const char* theLabel)
263{
264    mLabels.add(theLabel, mPC);
265    mLabelsInverseMapping.add(mPC, theLabel);
266    LOG_LABEL("%s:\n", theLabel);
267}
268
269void 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
276void ArmToArm64Assembler::BL(int /*cc*/, const char* /*label*/)
277{
278    NOT_IMPLEMENTED(); //Not Required
279}
280
281// ----------------------------------------------------------------------------
282//Prolog/Epilog & Generate...
283// ----------------------------------------------------------------------------
284
285void ArmToArm64Assembler::prolog()
286{
287    // write prolog code
288    mPrologPC = mPC;
289    *mPC++ = A64_MOVZ_X(mZeroReg,0,0);
290}
291
292void ArmToArm64Assembler::epilog(uint32_t /*touched*/)
293{
294    // write epilog code
295    static const int XLR = 30;
296    *mPC++ = A64_RET(XLR);
297}
298
299int 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
332uint32_t* ArmToArm64Assembler::pcForLabel(const char* label)
333{
334    return mLabels.valueFor(label);
335}
336
337// ----------------------------------------------------------------------------
338// Data Processing...
339// ----------------------------------------------------------------------------
340void 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
408void 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
463void 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
498void 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// ----------------------------------------------------------------------------
519void 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}
527void 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}
533void ArmToArm64Assembler::UMULL(int /*cc*/, int /*s*/,
534        int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/)
535{
536    NOT_IMPLEMENTED(); //Not required
537}
538void ArmToArm64Assembler::UMUAL(int /*cc*/, int /*s*/,
539        int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/)
540{
541    NOT_IMPLEMENTED(); //Not required
542}
543void ArmToArm64Assembler::SMULL(int /*cc*/, int /*s*/,
544        int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/)
545{
546    NOT_IMPLEMENTED(); //Not required
547}
548void 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// ----------------------------------------------------------------------------
557void ArmToArm64Assembler::B(int /*cc*/, uint32_t* /*pc*/){
558    NOT_IMPLEMENTED(); //Not required
559}
560
561void ArmToArm64Assembler::BL(int /*cc*/, uint32_t* /*pc*/){
562    NOT_IMPLEMENTED(); //Not required
563}
564
565void ArmToArm64Assembler::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 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}
634void 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}
638void 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}
642void ArmToArm64Assembler::LDR(int cc, int Rd, int Rn, uint32_t op_type)
643{
644    return dataTransfer(opLDR, cc, Rd, Rn, op_type);
645}
646void ArmToArm64Assembler::LDRB(int cc, int Rd, int Rn, uint32_t op_type)
647{
648    return dataTransfer(opLDRB, cc, Rd, Rn, op_type);
649}
650void ArmToArm64Assembler::STR(int cc, int Rd, int Rn, uint32_t op_type)
651{
652    return dataTransfer(opSTR, cc, Rd, Rn, op_type);
653}
654
655void ArmToArm64Assembler::STRB(int cc, int Rd, int Rn, uint32_t op_type)
656{
657    return dataTransfer(opSTRB, cc, Rd, Rn, op_type);
658}
659
660void ArmToArm64Assembler::LDRH(int cc, int Rd, int Rn, uint32_t op_type)
661{
662    return dataTransfer(opLDRH, cc, Rd, Rn, op_type);
663}
664void ArmToArm64Assembler::LDRSB(int /*cc*/, int /*Rd*/, int /*Rn*/, uint32_t /*offset*/)
665{
666    NOT_IMPLEMENTED(); //Not required
667}
668void ArmToArm64Assembler::LDRSH(int /*cc*/, int /*Rd*/, int /*Rn*/, uint32_t /*offset*/)
669{
670    NOT_IMPLEMENTED(); //Not required
671}
672
673void 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// ----------------------------------------------------------------------------
681void 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
702void 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// ----------------------------------------------------------------------------
726void ArmToArm64Assembler::SWP(int /*cc*/, int /*Rn*/, int /*Rd*/, int /*Rm*/)
727{
728    NOT_IMPLEMENTED(); //Not required
729}
730void ArmToArm64Assembler::SWPB(int /*cc*/, int /*Rn*/, int /*Rd*/, int /*Rm*/)
731{
732    NOT_IMPLEMENTED(); //Not required
733}
734void ArmToArm64Assembler::SWI(int /*cc*/, uint32_t /*comment*/)
735{
736    NOT_IMPLEMENTED(); //Not required
737}
738
739// ----------------------------------------------------------------------------
740// DSP instructions...
741// ----------------------------------------------------------------------------
742void ArmToArm64Assembler::PLD(int /*Rn*/, uint32_t /*offset*/) {
743    NOT_IMPLEMENTED(); //Not required
744}
745
746void ArmToArm64Assembler::CLZ(int /*cc*/, int /*Rd*/, int /*Rm*/)
747{
748    NOT_IMPLEMENTED(); //Not required
749}
750
751void ArmToArm64Assembler::QADD(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/)
752{
753    NOT_IMPLEMENTED(); //Not required
754}
755
756void ArmToArm64Assembler::QDADD(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/)
757{
758    NOT_IMPLEMENTED(); //Not required
759}
760
761void ArmToArm64Assembler::QSUB(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/)
762{
763    NOT_IMPLEMENTED(); //Not required
764}
765
766void 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// ----------------------------------------------------------------------------
774void 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// ----------------------------------------------------------------------------
794void 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// ----------------------------------------------------------------------------
810void 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
820void 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
827void 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// ----------------------------------------------------------------------------
837void 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// ----------------------------------------------------------------------------
852void 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// ----------------------------------------------------------------------------
860int 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
869bool ArmToArm64Assembler::isValidImmediate(uint32_t immediate)
870{
871    uint32_t rot, imm;
872    return buildImmediate(immediate, rot, imm) == 0;
873}
874
875uint32_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
885uint32_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
893uint32_t ArmToArm64Assembler::reg_rrx(int /*Rm*/)
894{
895    NOT_IMPLEMENTED();
896    return OPERAND_UNSUPPORTED;
897}
898
899uint32_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// ----------------------------------------------------------------------------
907uint32_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
916uint32_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
925uint32_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
940uint32_t ArmToArm64Assembler::reg_scale_post(int /*Rm*/, int /*type*/, uint32_t /*shift*/)
941{
942    NOT_IMPLEMENTED(); //Not required
943    return OPERAND_UNSUPPORTED;
944}
945
946uint32_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
955uint32_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
964uint32_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
978uint32_t ArmToArm64Assembler::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 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
1020uint32_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
1032uint32_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}
1045uint32_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
1056uint32_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
1067uint32_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}
1073uint32_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}
1082uint32_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
1089uint32_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
1096uint32_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
1106uint32_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
1127uint32_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
1137uint32_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
1147uint32_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
1157uint32_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
1164uint32_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
1171uint32_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
1177uint32_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
1184uint32_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
1191uint32_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
1198uint32_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
1205uint32_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
1212uint32_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}
1219uint32_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}
1226uint32_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}
1234uint32_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