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