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