14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/compiler/assembler/aarch64/assembler_aarch64.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include <ostream>
194514f5e3Sopenharmony_ci#include <sstream>
204514f5e3Sopenharmony_ci
214514f5e3Sopenharmony_ci#include "ecmascript/ecma_vm.h"
224514f5e3Sopenharmony_ci#include "ecmascript/mem/dyn_chunk.h"
234514f5e3Sopenharmony_ci#include "ecmascript/tests/test_helper.h"
244514f5e3Sopenharmony_ci
254514f5e3Sopenharmony_ci#include "llvm-c/Analysis.h"
264514f5e3Sopenharmony_ci#include "llvm-c/Core.h"
274514f5e3Sopenharmony_ci#include "llvm-c/Disassembler.h"
284514f5e3Sopenharmony_ci#include "llvm-c/ExecutionEngine.h"
294514f5e3Sopenharmony_ci#include "llvm-c/Target.h"
304514f5e3Sopenharmony_ci
314514f5e3Sopenharmony_cinamespace panda::test {
324514f5e3Sopenharmony_ciusing namespace panda::ecmascript;
334514f5e3Sopenharmony_ciusing namespace panda::ecmascript::aarch64;
344514f5e3Sopenharmony_ciclass AssemblerAarch64Test : public testing::Test {
354514f5e3Sopenharmony_cipublic:
364514f5e3Sopenharmony_ci    static void SetUpTestCase()
374514f5e3Sopenharmony_ci    {
384514f5e3Sopenharmony_ci        GTEST_LOG_(INFO) << "SetUpTestCase";
394514f5e3Sopenharmony_ci    }
404514f5e3Sopenharmony_ci
414514f5e3Sopenharmony_ci    static void TearDownTestCase()
424514f5e3Sopenharmony_ci    {
434514f5e3Sopenharmony_ci        GTEST_LOG_(INFO) << "TearDownCase";
444514f5e3Sopenharmony_ci    }
454514f5e3Sopenharmony_ci
464514f5e3Sopenharmony_ci    void SetUp() override
474514f5e3Sopenharmony_ci    {
484514f5e3Sopenharmony_ci        InitializeLLVM(TARGET_AARCH64);
494514f5e3Sopenharmony_ci        TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
504514f5e3Sopenharmony_ci        chunk_ = thread->GetEcmaVM()->GetChunk();
514514f5e3Sopenharmony_ci    }
524514f5e3Sopenharmony_ci
534514f5e3Sopenharmony_ci    void TearDown() override
544514f5e3Sopenharmony_ci    {
554514f5e3Sopenharmony_ci        TestHelper::DestroyEcmaVMWithScope(instance, scope);
564514f5e3Sopenharmony_ci    }
574514f5e3Sopenharmony_ci
584514f5e3Sopenharmony_ci    static const char *SymbolLookupCallback([[maybe_unused]] void *disInfo, [[maybe_unused]] uint64_t referenceValue,
594514f5e3Sopenharmony_ci                                            uint64_t *referenceType, [[maybe_unused]] uint64_t referencePC,
604514f5e3Sopenharmony_ci                                            [[maybe_unused]] const char **referenceName)
614514f5e3Sopenharmony_ci    {
624514f5e3Sopenharmony_ci        *referenceType = LLVMDisassembler_ReferenceType_InOut_None;
634514f5e3Sopenharmony_ci        return nullptr;
644514f5e3Sopenharmony_ci    }
654514f5e3Sopenharmony_ci
664514f5e3Sopenharmony_ci    void InitializeLLVM(std::string triple)
674514f5e3Sopenharmony_ci    {
684514f5e3Sopenharmony_ci        if (triple.compare(TARGET_X64) == 0) {
694514f5e3Sopenharmony_ci            LLVMInitializeX86TargetInfo();
704514f5e3Sopenharmony_ci            LLVMInitializeX86TargetMC();
714514f5e3Sopenharmony_ci            LLVMInitializeX86Disassembler();
724514f5e3Sopenharmony_ci            /* this method must be called, ohterwise "Target does not support MC emission" */
734514f5e3Sopenharmony_ci            LLVMInitializeX86AsmPrinter();
744514f5e3Sopenharmony_ci            LLVMInitializeX86AsmParser();
754514f5e3Sopenharmony_ci            LLVMInitializeX86Target();
764514f5e3Sopenharmony_ci        } else if (triple.compare(TARGET_AARCH64) == 0) {
774514f5e3Sopenharmony_ci            LLVMInitializeAArch64TargetInfo();
784514f5e3Sopenharmony_ci            LLVMInitializeAArch64TargetMC();
794514f5e3Sopenharmony_ci            LLVMInitializeAArch64Disassembler();
804514f5e3Sopenharmony_ci            LLVMInitializeAArch64AsmPrinter();
814514f5e3Sopenharmony_ci            LLVMInitializeAArch64AsmParser();
824514f5e3Sopenharmony_ci            LLVMInitializeAArch64Target();
834514f5e3Sopenharmony_ci        } else {
844514f5e3Sopenharmony_ci            LOG_ECMA(FATAL) << "this branch is unreachable";
854514f5e3Sopenharmony_ci            UNREACHABLE();
864514f5e3Sopenharmony_ci        }
874514f5e3Sopenharmony_ci    }
884514f5e3Sopenharmony_ci
894514f5e3Sopenharmony_ci    void DisassembleChunk(const char *triple, Assembler *assemlber, std::ostream &os)
904514f5e3Sopenharmony_ci    {
914514f5e3Sopenharmony_ci        LLVMDisasmContextRef dcr = LLVMCreateDisasm(triple, nullptr, 0, nullptr, SymbolLookupCallback);
924514f5e3Sopenharmony_ci        uint8_t *byteSp = assemlber->GetBegin();
934514f5e3Sopenharmony_ci        size_t numBytes = assemlber->GetCurrentPosition();
944514f5e3Sopenharmony_ci        unsigned pc = 0;
954514f5e3Sopenharmony_ci        const char outStringSize = 100;
964514f5e3Sopenharmony_ci        char outString[outStringSize];
974514f5e3Sopenharmony_ci        while (numBytes > 0) {
984514f5e3Sopenharmony_ci            size_t InstSize = LLVMDisasmInstruction(dcr, byteSp, numBytes, pc, outString, outStringSize);
994514f5e3Sopenharmony_ci            if (InstSize == 0) {
1004514f5e3Sopenharmony_ci                // 8 : 8 means width of the pc offset and instruction code
1014514f5e3Sopenharmony_ci                os << std::setw(8) << std::setfill('0') << std::hex << pc << ":" << std::setw(8)
1024514f5e3Sopenharmony_ci                   << *reinterpret_cast<uint32_t *>(byteSp) << "maybe constant" << std::endl;
1034514f5e3Sopenharmony_ci                pc += 4; // 4 pc length
1044514f5e3Sopenharmony_ci                byteSp += 4; // 4 sp offset
1054514f5e3Sopenharmony_ci                numBytes -= 4; // 4 num bytes
1064514f5e3Sopenharmony_ci            }
1074514f5e3Sopenharmony_ci            // 8 : 8 means width of the pc offset and instruction code
1084514f5e3Sopenharmony_ci            os << std::setw(8) << std::setfill('0') << std::hex << pc << ":" << std::setw(8)
1094514f5e3Sopenharmony_ci               << *reinterpret_cast<uint32_t *>(byteSp) << " " << outString << std::endl;
1104514f5e3Sopenharmony_ci            pc += InstSize;
1114514f5e3Sopenharmony_ci            byteSp += InstSize;
1124514f5e3Sopenharmony_ci            numBytes -= InstSize;
1134514f5e3Sopenharmony_ci        }
1144514f5e3Sopenharmony_ci        LLVMDisasmDispose(dcr);
1154514f5e3Sopenharmony_ci    }
1164514f5e3Sopenharmony_ci    EcmaVM *instance {nullptr};
1174514f5e3Sopenharmony_ci    JSThread *thread {nullptr};
1184514f5e3Sopenharmony_ci    EcmaHandleScope *scope {nullptr};
1194514f5e3Sopenharmony_ci    Chunk *chunk_ {nullptr};
1204514f5e3Sopenharmony_ci};
1214514f5e3Sopenharmony_ci
1224514f5e3Sopenharmony_ci#define __ masm.
1234514f5e3Sopenharmony_ciHWTEST_F_L0(AssemblerAarch64Test, Mov)
1244514f5e3Sopenharmony_ci{
1254514f5e3Sopenharmony_ci    std::string expectResult("00000000:d28acf01 \tmov\tx1, #22136\n"
1264514f5e3Sopenharmony_ci                             "00000004:f2a24681 \tmovk\tx1, #4660, lsl #16\n"
1274514f5e3Sopenharmony_ci                             "00000008:f2ffffe1 \tmovk\tx1, #65535, lsl #48\n"
1284514f5e3Sopenharmony_ci                             "0000000c:d2801de2 \tmov\tx2, #239\n"
1294514f5e3Sopenharmony_ci                             "00000010:f2b579a2 \tmovk\tx2, #43981, lsl #16\n"
1304514f5e3Sopenharmony_ci                             "00000014:f2cacf02 \tmovk\tx2, #22136, lsl #32\n"
1314514f5e3Sopenharmony_ci                             "00000018:f2e24682 \tmovk\tx2, #4660, lsl #48\n"
1324514f5e3Sopenharmony_ci                             "0000001c:b2683be3 \tmov\tx3, #549739036672\n"
1334514f5e3Sopenharmony_ci                             "00000020:f2824683 \tmovk\tx3, #4660\n"
1344514f5e3Sopenharmony_ci                             "00000024:32083fe4 \tmov\tw4, #-16776961\n");
1354514f5e3Sopenharmony_ci    AssemblerAarch64 masm(chunk_);
1364514f5e3Sopenharmony_ci    __ Mov(Register(X1),  Immediate(0xffff000012345678));
1374514f5e3Sopenharmony_ci    __ Mov(Register(X2),  Immediate(0x12345678abcd00ef));
1384514f5e3Sopenharmony_ci    __ Mov(Register(X3),  Immediate(0x7fff001234));
1394514f5e3Sopenharmony_ci    __ Mov(Register(X4).W(),  Immediate(0xff0000ff));
1404514f5e3Sopenharmony_ci    std::ostringstream oss;
1414514f5e3Sopenharmony_ci    DisassembleChunk(TARGET_AARCH64, &masm, oss);
1424514f5e3Sopenharmony_ci    ASSERT_EQ(oss.str(), expectResult);
1434514f5e3Sopenharmony_ci}
1444514f5e3Sopenharmony_ci
1454514f5e3Sopenharmony_ciHWTEST_F_L0(AssemblerAarch64Test, MovReg)
1464514f5e3Sopenharmony_ci{
1474514f5e3Sopenharmony_ci    std::string expectResult("00000000:aa0203e1 \tmov\tx1, x2\n"
1484514f5e3Sopenharmony_ci                             "00000004:910003e2 \tmov\tx2, sp\n"
1494514f5e3Sopenharmony_ci                             "00000008:2a0203e1 \tmov\tw1, w2\n");
1504514f5e3Sopenharmony_ci    AssemblerAarch64 masm(chunk_);
1514514f5e3Sopenharmony_ci    __ Mov(Register(X1),  Register(X2));
1524514f5e3Sopenharmony_ci    __ Mov(Register(X2),  Register(SP));
1534514f5e3Sopenharmony_ci    __ Mov(Register(X1, W),  Register(X2, W));
1544514f5e3Sopenharmony_ci    std::ostringstream oss;
1554514f5e3Sopenharmony_ci    DisassembleChunk(TARGET_AARCH64, &masm, oss);
1564514f5e3Sopenharmony_ci    ASSERT_EQ(oss.str(), expectResult);
1574514f5e3Sopenharmony_ci}
1584514f5e3Sopenharmony_ci
1594514f5e3Sopenharmony_ciHWTEST_F_L0(AssemblerAarch64Test, LdpStp)
1604514f5e3Sopenharmony_ci{
1614514f5e3Sopenharmony_ci    std::string expectResult("00000000:a8808be1 \tstp\tx1, x2, [sp], #8\n"
1624514f5e3Sopenharmony_ci                             "00000004:a9c08be1 \tldp\tx1, x2, [sp, #8]!\n"
1634514f5e3Sopenharmony_ci                             "00000008:a94093e3 \tldp\tx3, x4, [sp, #8]\n"
1644514f5e3Sopenharmony_ci                             "0000000c:294113e3 \tldp\tw3, w4, [sp, #8]\n");
1654514f5e3Sopenharmony_ci
1664514f5e3Sopenharmony_ci    AssemblerAarch64 masm(chunk_);
1674514f5e3Sopenharmony_ci    __ Stp(Register(X1),  Register(X2), MemoryOperand(Register(SP), 8, POSTINDEX));
1684514f5e3Sopenharmony_ci    __ Ldp(Register(X1),  Register(X2), MemoryOperand(Register(SP), 8, PREINDEX));
1694514f5e3Sopenharmony_ci    __ Ldp(Register(X3),  Register(X4), MemoryOperand(Register(SP), 8, OFFSET));
1704514f5e3Sopenharmony_ci    __ Ldp(Register(X3).W(),  Register(X4).W(), MemoryOperand(Register(SP), 8, OFFSET));
1714514f5e3Sopenharmony_ci    std::ostringstream oss;
1724514f5e3Sopenharmony_ci    DisassembleChunk(TARGET_AARCH64, &masm, oss);
1734514f5e3Sopenharmony_ci    ASSERT_EQ(oss.str(), expectResult);
1744514f5e3Sopenharmony_ci}
1754514f5e3Sopenharmony_ci
1764514f5e3Sopenharmony_ciHWTEST_F_L0(AssemblerAarch64Test, LdrStr)
1774514f5e3Sopenharmony_ci{
1784514f5e3Sopenharmony_ci    std::string expectResult("00000000:f80087e1 \tstr\tx1, [sp], #8\n"
1794514f5e3Sopenharmony_ci                             "00000004:f81f87e1 \tstr\tx1, [sp], #-8\n"
1804514f5e3Sopenharmony_ci                             "00000008:f8408fe1 \tldr\tx1, [sp, #8]!\n"
1814514f5e3Sopenharmony_ci                             "0000000c:f94007e3 \tldr\tx3, [sp, #8]\n"
1824514f5e3Sopenharmony_ci                             "00000010:b9400be3 \tldr\tw3, [sp, #8]\n"
1834514f5e3Sopenharmony_ci                             "00000014:38408fe1 \tldrb\tw1, [sp, #8]!\n"
1844514f5e3Sopenharmony_ci                             "00000018:394023e1 \tldrb\tw1, [sp, #8]\n"
1854514f5e3Sopenharmony_ci                             "0000001c:78408fe1 \tldrh\tw1, [sp, #8]!\n"
1864514f5e3Sopenharmony_ci                             "00000020:794013e1 \tldrh\tw1, [sp, #8]\n"
1874514f5e3Sopenharmony_ci                             "00000024:f85f83e1 \tldur\tx1, [sp, #-8]\n"
1884514f5e3Sopenharmony_ci                             "00000028:f81f83e3 \tstur\tx3, [sp, #-8]\n");
1894514f5e3Sopenharmony_ci
1904514f5e3Sopenharmony_ci    AssemblerAarch64 masm(chunk_);
1914514f5e3Sopenharmony_ci    __ Str(Register(X1), MemoryOperand(Register(SP), 8, POSTINDEX));
1924514f5e3Sopenharmony_ci    __ Str(Register(X1), MemoryOperand(Register(SP), -8, POSTINDEX));
1934514f5e3Sopenharmony_ci    __ Ldr(Register(X1), MemoryOperand(Register(SP), 8, PREINDEX));
1944514f5e3Sopenharmony_ci    __ Ldr(Register(X3), MemoryOperand(Register(SP), 8, OFFSET));
1954514f5e3Sopenharmony_ci    __ Ldr(Register(X3).W(), MemoryOperand(Register(SP), 8, OFFSET));
1964514f5e3Sopenharmony_ci    __ Ldrb(Register(X1).W(), MemoryOperand(Register(SP), 8, PREINDEX));
1974514f5e3Sopenharmony_ci    __ Ldrb(Register(X1).W(), MemoryOperand(Register(SP), 8, OFFSET));
1984514f5e3Sopenharmony_ci    __ Ldrh(Register(X1).W(), MemoryOperand(Register(SP), 8, PREINDEX));
1994514f5e3Sopenharmony_ci    __ Ldrh(Register(X1).W(), MemoryOperand(Register(SP), 8, OFFSET));
2004514f5e3Sopenharmony_ci    __ Ldur(Register(X1), MemoryOperand(Register(SP), -8, OFFSET));
2014514f5e3Sopenharmony_ci    __ Stur(Register(X3), MemoryOperand(Register(SP), -8, OFFSET));
2024514f5e3Sopenharmony_ci    std::ostringstream oss;
2034514f5e3Sopenharmony_ci    DisassembleChunk(TARGET_AARCH64, &masm, oss);
2044514f5e3Sopenharmony_ci    ASSERT_EQ(oss.str(), expectResult);
2054514f5e3Sopenharmony_ci}
2064514f5e3Sopenharmony_ci
2074514f5e3Sopenharmony_ciHWTEST_F_L0(AssemblerAarch64Test, AddSub)
2084514f5e3Sopenharmony_ci{
2094514f5e3Sopenharmony_ci    std::string expectResult("00000000:910023ff \tadd\tsp, sp, #8\n"
2104514f5e3Sopenharmony_ci                             "00000004:d10023ff \tsub\tsp, sp, #8\n"
2114514f5e3Sopenharmony_ci                             "00000008:8b020021 \tadd\tx1, x1, x2\n"
2124514f5e3Sopenharmony_ci                             "0000000c:8b030c41 \tadd\tx1, x2, x3, lsl #3\n"
2134514f5e3Sopenharmony_ci                             "00000010:8b234c41 \tadd\tx1, x2, w3, uxtw #3\n"
2144514f5e3Sopenharmony_ci                             "00000014:8b224fff \tadd\tsp, sp, w2, uxtw #3\n");
2154514f5e3Sopenharmony_ci    AssemblerAarch64 masm(chunk_);
2164514f5e3Sopenharmony_ci    __ Add(Register(SP), Register(SP), Immediate(8));
2174514f5e3Sopenharmony_ci    __ Add(Register(SP), Register(SP), Immediate(-8));
2184514f5e3Sopenharmony_ci    __ Add(Register(X1), Register(X1), Operand(Register(X2)));
2194514f5e3Sopenharmony_ci    __ Add(Register(X1), Register(X2), Operand(Register(X3), LSL, 3));
2204514f5e3Sopenharmony_ci    __ Add(Register(X1), Register(X2), Operand(Register(X3), UXTW, 3));
2214514f5e3Sopenharmony_ci    __ Add(Register(SP), Register(SP), Operand(Register(X2), UXTW, 3));
2224514f5e3Sopenharmony_ci
2234514f5e3Sopenharmony_ci    std::ostringstream oss;
2244514f5e3Sopenharmony_ci    DisassembleChunk(TARGET_AARCH64, &masm, oss);
2254514f5e3Sopenharmony_ci    ASSERT_EQ(oss.str(), expectResult);
2264514f5e3Sopenharmony_ci}
2274514f5e3Sopenharmony_ci
2284514f5e3Sopenharmony_ciHWTEST_F_L0(AssemblerAarch64Test, CMP)
2294514f5e3Sopenharmony_ci{
2304514f5e3Sopenharmony_ci    std::string expectResult("00000000:eb02003f \tcmp\tx1, x2\n"
2314514f5e3Sopenharmony_ci                             "00000004:f100203f \tcmp\tx1, #8\n");
2324514f5e3Sopenharmony_ci    AssemblerAarch64 masm(chunk_);
2334514f5e3Sopenharmony_ci    __ Cmp(Register(X1), Register(X2));
2344514f5e3Sopenharmony_ci    __ Cmp(Register(X1), Immediate(8));
2354514f5e3Sopenharmony_ci
2364514f5e3Sopenharmony_ci    std::ostringstream oss;
2374514f5e3Sopenharmony_ci    DisassembleChunk(TARGET_AARCH64, &masm, oss);
2384514f5e3Sopenharmony_ci    ASSERT_EQ(oss.str(), expectResult);
2394514f5e3Sopenharmony_ci}
2404514f5e3Sopenharmony_ci
2414514f5e3Sopenharmony_ciHWTEST_F_L0(AssemblerAarch64Test, Branch)
2424514f5e3Sopenharmony_ci{
2434514f5e3Sopenharmony_ci    std::string expectResult("00000000:eb02003f \tcmp\tx1, x2\n"
2444514f5e3Sopenharmony_ci                             "00000004:54000080 \tb.eq\t0x14\n"
2454514f5e3Sopenharmony_ci                             "00000008:f100203f \tcmp\tx1, #8\n"
2464514f5e3Sopenharmony_ci                             "0000000c:5400004c \tb.gt\t0x14\n"
2474514f5e3Sopenharmony_ci                             "00000010:14000002 \tb\t0x18\n"
2484514f5e3Sopenharmony_ci                             "00000014:d2800140 \tmov\tx0, #10\n"
2494514f5e3Sopenharmony_ci                             "00000018:b27f03e0 \torr\tx0, xzr, #0x2\n");
2504514f5e3Sopenharmony_ci    AssemblerAarch64 masm(chunk_);
2514514f5e3Sopenharmony_ci    Label label1;
2524514f5e3Sopenharmony_ci    Label label2;
2534514f5e3Sopenharmony_ci    __ Cmp(Register(X1), Register(X2));
2544514f5e3Sopenharmony_ci    __ B(Condition::EQ, &label1);
2554514f5e3Sopenharmony_ci    __ Cmp(Register(X1), Immediate(8));
2564514f5e3Sopenharmony_ci    __ B(Condition::GT, &label1);
2574514f5e3Sopenharmony_ci    __ B(&label2);
2584514f5e3Sopenharmony_ci    __ Bind(&label1);
2594514f5e3Sopenharmony_ci    {
2604514f5e3Sopenharmony_ci        __ Mov(Register(X0), Immediate(0xa));
2614514f5e3Sopenharmony_ci    }
2624514f5e3Sopenharmony_ci    __ Bind(&label2);
2634514f5e3Sopenharmony_ci    {
2644514f5e3Sopenharmony_ci        __ Mov(Register(X0), Immediate(0x2));
2654514f5e3Sopenharmony_ci    }
2664514f5e3Sopenharmony_ci
2674514f5e3Sopenharmony_ci    std::ostringstream oss;
2684514f5e3Sopenharmony_ci    DisassembleChunk(TARGET_AARCH64, &masm, oss);
2694514f5e3Sopenharmony_ci    ASSERT_EQ(oss.str(), expectResult);
2704514f5e3Sopenharmony_ci}
2714514f5e3Sopenharmony_ci
2724514f5e3Sopenharmony_ciHWTEST_F_L0(AssemblerAarch64Test, Loop)
2734514f5e3Sopenharmony_ci{
2744514f5e3Sopenharmony_ci    std::string expectResult("00000000:7100005f \tcmp\tw2, #0\n"
2754514f5e3Sopenharmony_ci                             "00000004:540000e0 \tb.eq\t0x20\n"
2764514f5e3Sopenharmony_ci                             "00000008:51000442 \tsub\tw2, w2, #1\n"
2774514f5e3Sopenharmony_ci                             "0000000c:8b224c84 \tadd\tx4, x4, w2, uxtw #3\n"
2784514f5e3Sopenharmony_ci                             "00000010:f85f8485 \tldr\tx5, [x4], #-8\n"
2794514f5e3Sopenharmony_ci                             "00000014:f81f8fe5 \tstr\tx5, [sp, #-8]!\n"
2804514f5e3Sopenharmony_ci                             "00000018:51000442 \tsub\tw2, w2, #1\n"
2814514f5e3Sopenharmony_ci                             "0000001c:54ffffa5 \tb.pl\t0x10\n"
2824514f5e3Sopenharmony_ci                             "00000020:d2800140 \tmov\tx0, #10\n");
2834514f5e3Sopenharmony_ci    AssemblerAarch64 masm(chunk_);
2844514f5e3Sopenharmony_ci    Label label1;
2854514f5e3Sopenharmony_ci    Label labelLoop;
2864514f5e3Sopenharmony_ci    Register count(X2, W);
2874514f5e3Sopenharmony_ci    Register base(X4);
2884514f5e3Sopenharmony_ci    Register temp(X5);
2894514f5e3Sopenharmony_ci    __ Cmp(count, Immediate(0));
2904514f5e3Sopenharmony_ci    __ B(Condition::EQ, &label1);
2914514f5e3Sopenharmony_ci    __ Add(count, count, Immediate(-1));
2924514f5e3Sopenharmony_ci    __ Add(base, base, Operand(count, UXTW, 3));
2934514f5e3Sopenharmony_ci    __ Bind(&labelLoop);
2944514f5e3Sopenharmony_ci    {
2954514f5e3Sopenharmony_ci        __ Ldr(temp, MemoryOperand(base, -8, POSTINDEX));
2964514f5e3Sopenharmony_ci        __ Str(temp, MemoryOperand(Register(SP), -8, PREINDEX));
2974514f5e3Sopenharmony_ci        __ Add(count, count, Immediate(-1));
2984514f5e3Sopenharmony_ci        __ B(Condition::PL, &labelLoop);
2994514f5e3Sopenharmony_ci    }
3004514f5e3Sopenharmony_ci    __ Bind(&label1);
3014514f5e3Sopenharmony_ci    {
3024514f5e3Sopenharmony_ci        __ Mov(Register(X0), Immediate(0xa));
3034514f5e3Sopenharmony_ci    }
3044514f5e3Sopenharmony_ci    std::ostringstream oss;
3054514f5e3Sopenharmony_ci    DisassembleChunk(TARGET_AARCH64, &masm, oss);
3064514f5e3Sopenharmony_ci    ASSERT_EQ(oss.str(), expectResult);
3074514f5e3Sopenharmony_ci}
3084514f5e3Sopenharmony_ci
3094514f5e3Sopenharmony_ciHWTEST_F_L0(AssemblerAarch64Test, TbzAndCbz)
3104514f5e3Sopenharmony_ci{
3114514f5e3Sopenharmony_ci    std::string expectResult("00000000:36780001 \ttbz\tw1, #15, 0x0\n"
3124514f5e3Sopenharmony_ci                             "00000004:b60000c2 \ttbz\tx2, #32, 0x1c\n"
3134514f5e3Sopenharmony_ci                             "00000008:372800c2 \ttbnz\tw2, #5, 0x20\n"
3144514f5e3Sopenharmony_ci                             "0000000c:34000063 \tcbz\tw3, 0x18\n"
3154514f5e3Sopenharmony_ci                             "00000010:b5000064 \tcbnz\tx4, 0x1c\n"
3164514f5e3Sopenharmony_ci                             "00000014:b4000065 \tcbz\tx5, 0x20\n"
3174514f5e3Sopenharmony_ci                             "00000018:b24003e0 \torr\tx0, xzr, #0x1\n"
3184514f5e3Sopenharmony_ci                             "0000001c:b27f03e0 \torr\tx0, xzr, #0x2\n"
3194514f5e3Sopenharmony_ci                             "00000020:b24007e0 \torr\tx0, xzr, #0x3\n");
3204514f5e3Sopenharmony_ci    AssemblerAarch64 masm(chunk_);
3214514f5e3Sopenharmony_ci    Label label1;
3224514f5e3Sopenharmony_ci    Label label2;
3234514f5e3Sopenharmony_ci    Label label3;
3244514f5e3Sopenharmony_ci    __ Tbz(Register(X1), 15, &label1);
3254514f5e3Sopenharmony_ci    __ Tbz(Register(X2), 32,  &label2);
3264514f5e3Sopenharmony_ci    __ Tbnz(Register(X2), 5,  &label3);
3274514f5e3Sopenharmony_ci    __ Cbz(Register(X3).W(), &label1);
3284514f5e3Sopenharmony_ci    __ Cbnz(Register(X4), &label2);
3294514f5e3Sopenharmony_ci    __ Cbz(Register(X5), &label3);
3304514f5e3Sopenharmony_ci    __ Bind(&label1);
3314514f5e3Sopenharmony_ci    {
3324514f5e3Sopenharmony_ci        __ Mov(Register(X0), Immediate(0x1));
3334514f5e3Sopenharmony_ci    }
3344514f5e3Sopenharmony_ci    __ Bind(&label2);
3354514f5e3Sopenharmony_ci    {
3364514f5e3Sopenharmony_ci        __ Mov(Register(X0), Immediate(0x2));
3374514f5e3Sopenharmony_ci    }
3384514f5e3Sopenharmony_ci    __ Bind(&label3);
3394514f5e3Sopenharmony_ci    {
3404514f5e3Sopenharmony_ci        __ Mov(Register(X0), Immediate(0x3));
3414514f5e3Sopenharmony_ci    }
3424514f5e3Sopenharmony_ci    std::ostringstream oss;
3434514f5e3Sopenharmony_ci    DisassembleChunk(TARGET_AARCH64, &masm, oss);
3444514f5e3Sopenharmony_ci    ASSERT_EQ(oss.str(), expectResult);
3454514f5e3Sopenharmony_ci}
3464514f5e3Sopenharmony_ci
3474514f5e3Sopenharmony_ciHWTEST_F_L0(AssemblerAarch64Test, Call)
3484514f5e3Sopenharmony_ci{
3494514f5e3Sopenharmony_ci    std::string expectResult("00000000:b24003e0 \torr\tx0, xzr, #0x1\n"
3504514f5e3Sopenharmony_ci                             "00000004:b27f03e1 \torr\tx1, xzr, #0x2\n"
3514514f5e3Sopenharmony_ci                             "00000008:b24007e2 \torr\tx2, xzr, #0x3\n"
3524514f5e3Sopenharmony_ci                             "0000000c:97fffffd \tbl\t0x0\n"
3534514f5e3Sopenharmony_ci                             "00000010:d63f0040 \tblr\tx2\n");
3544514f5e3Sopenharmony_ci    AssemblerAarch64 masm(chunk_);
3554514f5e3Sopenharmony_ci    Label label1;
3564514f5e3Sopenharmony_ci    __ Bind(&label1);
3574514f5e3Sopenharmony_ci    {
3584514f5e3Sopenharmony_ci        __ Mov(Register(X0), Immediate(0x1));
3594514f5e3Sopenharmony_ci        __ Mov(Register(X1), Immediate(0x2));
3604514f5e3Sopenharmony_ci        __ Mov(Register(X2), Immediate(0x3));
3614514f5e3Sopenharmony_ci        __ Bl(&label1);
3624514f5e3Sopenharmony_ci        __ Blr(Register(X2));
3634514f5e3Sopenharmony_ci    }
3644514f5e3Sopenharmony_ci    std::ostringstream oss;
3654514f5e3Sopenharmony_ci    DisassembleChunk(TARGET_AARCH64, &masm, oss);
3664514f5e3Sopenharmony_ci    ASSERT_EQ(oss.str(), expectResult);
3674514f5e3Sopenharmony_ci}
3684514f5e3Sopenharmony_ci
3694514f5e3Sopenharmony_ciHWTEST_F_L0(AssemblerAarch64Test, RetAndBrk)
3704514f5e3Sopenharmony_ci{
3714514f5e3Sopenharmony_ci    std::string expectResult("00000000:d65f03c0 \tret\n"
3724514f5e3Sopenharmony_ci                             "00000004:d65f0280 \tret\tx20\n"
3734514f5e3Sopenharmony_ci                             "00000008:d4200000 \tbrk\t#0\n");
3744514f5e3Sopenharmony_ci    AssemblerAarch64 masm(chunk_);
3754514f5e3Sopenharmony_ci    __ Ret();
3764514f5e3Sopenharmony_ci    __ Ret(Register(X20));
3774514f5e3Sopenharmony_ci    __ Brk(Immediate(0));
3784514f5e3Sopenharmony_ci
3794514f5e3Sopenharmony_ci    std::ostringstream oss;
3804514f5e3Sopenharmony_ci    DisassembleChunk(TARGET_AARCH64, &masm, oss);
3814514f5e3Sopenharmony_ci    ASSERT_EQ(oss.str(), expectResult);
3824514f5e3Sopenharmony_ci}
3834514f5e3Sopenharmony_ci#undef __
3844514f5e3Sopenharmony_ci}
385