1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "aarch64_emitter.h"
17 #include "metadata_layout.h"
18 #include "aarch64_obj_emitter.h"
19
20 namespace {
21 using namespace maple;
22 } // namespace
23
24 namespace maplebe {
25 using namespace maple;
26
EmitBBHeaderLabel(FuncEmitInfo & funcEmitInfo,const std::string & name,LabelIdx labIdx)27 void AArch64AsmEmitter::EmitBBHeaderLabel(FuncEmitInfo &funcEmitInfo, const std::string &name, LabelIdx labIdx)
28 {
29 #ifdef ARK_LITECG_DEBUG
30 (void)name;
31 CGFunc &cgFunc = funcEmitInfo.GetCGFunc();
32 AArch64CGFunc &aarchCGFunc = static_cast<AArch64CGFunc &>(cgFunc);
33 CG *currCG = cgFunc.GetCG();
34 LabelOperand &label = aarchCGFunc.GetOrCreateLabelOperand(labIdx);
35 /* if label order is default value -1, set new order */
36 if (label.GetLabelOrder() == 0xFFFFFFFF) {
37 label.SetLabelOrder(currCG->GetLabelOrderCnt());
38 currCG->IncreaseLabelOrderCnt();
39 }
40 CHECK_NULL_FATAL(currCG->GetMIRModule()->CurFunction());
41 PUIdx pIdx = currCG->GetMIRModule()->CurFunction()->GetPuidx();
42 char *puIdx = strdup(std::to_string(pIdx).c_str());
43 CHECK_FATAL(puIdx != nullptr, "strdup failed");
44 currCG->template Emit<CG::EmitterType::AsmEmitter>([&cgFunc, currCG, puIdx, labIdx, label](Emitter* emitter) {
45 const std::string &labelName = cgFunc.GetFunction().GetLabelTab()->GetName(labIdx);
46 if (currCG->GenerateVerboseCG()) {
47 (void)emitter->Emit(".L.")
48 .Emit(puIdx)
49 .Emit("__")
50 .Emit(labIdx)
51 .Emit(":\t//label order ")
52 .Emit(label.GetLabelOrder());
53 if (!labelName.empty() && labelName.at(0) != '@') {
54 /* If label name has @ as its first char, it is not from MIR */
55 (void)emitter->Emit(", MIR: @").Emit(labelName).Emit("\n");
56 } else {
57 (void)emitter->Emit("\n");
58 }
59 } else {
60 (void)emitter->Emit(".L.").Emit(puIdx).Emit("__").Emit(labIdx).Emit(":\n");
61 }
62 });
63 free(puIdx);
64 puIdx = nullptr;
65 #endif
66 }
67
RecordRegInfo(FuncEmitInfo & funcEmitInfo) const68 void AArch64AsmEmitter::RecordRegInfo(FuncEmitInfo &funcEmitInfo) const
69 {
70 #ifdef ARK_LITECG_DEBUG
71 if (!CGOptions::DoIPARA()) {
72 return;
73 }
74 CGFunc &cgFunc = funcEmitInfo.GetCGFunc();
75 AArch64CGFunc &aarchCGFunc = static_cast<AArch64CGFunc &>(cgFunc);
76
77 std::set<regno_t> referedRegs;
78 MIRFunction &mirFunc = cgFunc.GetFunction();
79 FOR_ALL_BB_REV(bb, &aarchCGFunc)
80 {
81 FOR_BB_INSNS_REV(insn, bb)
82 {
83 if (!insn->IsMachineInstruction()) {
84 continue;
85 }
86 if (insn->IsCall() || insn->IsTailCall()) {
87 auto *targetOpnd = insn->GetCallTargetOperand();
88 bool safeCheck = false;
89 CHECK_FATAL(targetOpnd != nullptr,
90 "target is null in AArch64Emitter::IsCallToFunctionThatNeverReturns");
91 if (targetOpnd->IsFuncNameOpnd()) {
92 FuncNameOperand *target = static_cast<FuncNameOperand *>(targetOpnd);
93 const MIRSymbol *funcSt = target->GetFunctionSymbol();
94 DEBUG_ASSERT(funcSt->GetSKind() == maple::kStFunc, "funcst must be a function name symbol");
95 MIRFunction *func = funcSt->GetFunction();
96 if (func != nullptr && func->IsReferedRegsValid()) {
97 safeCheck = true;
98 for (auto preg : func->GetReferedRegs()) {
99 referedRegs.insert(preg);
100 }
101 }
102 }
103 if (!safeCheck) {
104 mirFunc.SetReferedRegsValid(false);
105 return;
106 }
107 }
108 if (referedRegs.size() == kMaxRegNum) {
109 break;
110 }
111 uint32 opndNum = insn->GetOperandSize();
112 const InsnDesc *md = &AArch64CG::kMd[insn->GetMachineOpcode()];
113 for (uint32 i = 0; i < opndNum; ++i) {
114 if (insn->GetMachineOpcode() == MOP_asm) {
115 if (i == kAsmOutputListOpnd || i == kAsmClobberListOpnd) {
116 for (auto opnd : static_cast<ListOperand &>(insn->GetOperand(i)).GetOperands()) {
117 if (opnd->IsRegister()) {
118 referedRegs.insert(static_cast<RegOperand *>(opnd)->GetRegisterNumber());
119 }
120 }
121 }
122 continue;
123 }
124 Operand &opnd = insn->GetOperand(i);
125 if (opnd.IsList()) {
126 /* all use, skip it */
127 } else if (opnd.IsMemoryAccessOperand()) {
128 auto &memOpnd = static_cast<MemOperand &>(opnd);
129 RegOperand *base = memOpnd.GetBaseRegister();
130 if (!memOpnd.IsIntactIndexed()) {
131 referedRegs.insert(base->GetRegisterNumber());
132 }
133 } else if (opnd.IsRegister()) {
134 RegType regType = static_cast<RegOperand &>(opnd).GetRegisterType();
135 if (regType == kRegTyCc || regType == kRegTyVary) {
136 continue;
137 }
138 bool isDef = md->GetOpndDes(i)->IsRegDef();
139 if (isDef) {
140 referedRegs.insert(static_cast<RegOperand &>(opnd).GetRegisterNumber());
141 }
142 }
143 }
144 }
145 }
146 mirFunc.SetReferedRegsValid(true);
147 #ifdef DEBUG
148 for (auto reg : referedRegs) {
149 if (reg > kMaxRegNum) {
150 DEBUG_ASSERT(0, "unexpected preg");
151 }
152 }
153 #endif
154 mirFunc.CopyReferedRegs(referedRegs);
155 #endif
156 }
157
Run(FuncEmitInfo & funcEmitInfo)158 void AArch64AsmEmitter::Run(FuncEmitInfo &funcEmitInfo)
159 {
160 #ifdef ARK_LITECG_DEBUG
161 CGFunc &cgFunc = funcEmitInfo.GetCGFunc();
162 AArch64CGFunc &aarchCGFunc = static_cast<AArch64CGFunc &>(cgFunc);
163 CG *currCG = cgFunc.GetCG();
164 /* emit header of this function */
165 currCG->template Emit<CG::EmitterType::AsmEmitter>(
166 [this, &cgFunc, &aarchCGFunc, currCG, &funcEmitInfo](Emitter *emitter) {
167 // insert for __cxx_global_var_init
168 if (cgFunc.GetName() == "__cxx_global_var_init") {
169 (void)emitter->Emit("\t.section\t.init_array,\"aw\"\n");
170 (void)emitter->Emit("\t.quad\t").Emit(cgFunc.GetName()).Emit("\n");
171 }
172 if (cgFunc.GetFunction().GetAttr(FUNCATTR_initialization)) {
173 (void)emitter->Emit("\t.section\t.init_array,\"aw\"\n");
174 (void)emitter->Emit("\t.quad\t").Emit(cgFunc.GetName()).Emit("\n");
175 }
176 if (cgFunc.GetFunction().GetAttr(FUNCATTR_termination)) {
177 (void)emitter->Emit("\t.section\t.fini_array,\"aw\"\n");
178 (void)emitter->Emit("\t.quad\t").Emit(cgFunc.GetName()).Emit("\n");
179 }
180 (void)emitter->Emit("\n");
181 if (cgFunc.GetFunction().GetAttr(FUNCATTR_section)) {
182 const std::string §ionName = cgFunc.GetFunction().GetAttrs().GetPrefixSectionName();
183 (void)emitter->Emit("\t.section " + sectionName).Emit(",\"ax\",@progbits\n");
184 } else if (cgFunc.GetFunction().GetAttr(FUNCATTR_constructor_priority)) {
185 (void)emitter->Emit("\t.section\t.text.startup").Emit(",\"ax\",@progbits\n");
186 } else {
187 (void)emitter->Emit("\t.text\n");
188 }
189 if (CGOptions::GetFuncAlignPow() != 0) {
190 (void)emitter->Emit("\t.align ").Emit(CGOptions::GetFuncAlignPow()).Emit("\n");
191 }
192 MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(cgFunc.GetFunction().GetStIdx().Idx());
193 const std::string &funcName = std::string(cgFunc.GetShortFuncName().c_str());
194
195 CHECK_NULL_FATAL(funcSt);
196 std::string funcStName = funcSt->GetName();
197 if (funcSt->GetFunction()->GetAttr(FUNCATTR_weak)) {
198 (void)emitter->Emit("\t.weak\t" + funcStName + "\n");
199 (void)emitter->Emit("\t.hidden\t" + funcStName + "\n");
200 } else if (funcSt->GetFunction()->GetAttr(FUNCATTR_local)) {
201 (void)emitter->Emit("\t.local\t" + funcStName + "\n");
202 } else if (funcSt->GetFunction() && funcSt->GetFunction()->IsStatic()) {
203 // nothing
204 } else {
205 /* should refer to function attribute */
206 (void)emitter->Emit("\t.globl\t").Emit(funcSt->GetName()).Emit("\n");
207 (void)emitter->Emit("\t.hidden\t").Emit(funcSt->GetName()).Emit("\n");
208 }
209 (void)emitter->Emit("\t.type\t" + funcStName + ", %function\n");
210 (void)emitter->Emit(funcStName + ":\n");
211
212 /* if the last insn is call, then insert nop */
213 bool found = false;
214 FOR_ALL_BB_REV(bb, &aarchCGFunc)
215 {
216 FOR_BB_INSNS_REV(insn, bb)
217 {
218 if (insn->IsMachineInstruction()) {
219 if (insn->IsCall()) {
220 Insn &newInsn = aarchCGFunc.GetInsnBuilder()->BuildInsn<AArch64CG>(MOP_nop);
221 bb->InsertInsnAfter(*insn, newInsn);
222 }
223 found = true;
224 break;
225 }
226 }
227 if (found) {
228 break;
229 }
230 }
231
232 RecordRegInfo(funcEmitInfo);
233
234 /* emit instructions */
235 FOR_ALL_BB(bb, &aarchCGFunc)
236 {
237 if (bb->IsUnreachable()) {
238 continue;
239 }
240 if (currCG->GenerateVerboseCG()) {
241 (void)emitter->Emit("# freq:").Emit(bb->GetFrequency()).Emit("\n");
242 }
243 /* emit bb headers */
244 if (bb->GetLabIdx() != MIRLabelTable::GetDummyLabel()) {
245 EmitBBHeaderLabel(funcEmitInfo, funcName, bb->GetLabIdx());
246 }
247
248 FOR_BB_INSNS(insn, bb)
249 {
250 auto dbgComment = insn->GetDebugComment();
251 if (currDebugComment != dbgComment) {
252 currDebugComment = dbgComment;
253 if (dbgComment != nullptr) {
254 emitter->Emit("\t// ");
255 emitter->Emit(dbgComment->c_str());
256 emitter->Emit("\n ");
257 } else {
258 emitter->Emit("\t// \n");
259 }
260 }
261 if (insn->IsCfiInsn()) {
262 EmitAArch64CfiInsn(*emitter, *insn);
263 } else {
264 EmitAArch64Insn(*emitter, *insn);
265 }
266 }
267 }
268 (void)emitter->Emit("\t.size\t" + funcStName + ", .-").Emit(funcStName + "\n");
269
270 auto constructorAttr = funcSt->GetFunction()->GetAttrs().GetConstructorPriority();
271 if (constructorAttr != -1) {
272 (void)emitter->Emit("\t.section\t.init_array." + std::to_string(constructorAttr) + ",\"aw\"\n");
273 (void)emitter->Emit("\t.align 3\n");
274 (void)emitter->Emit("\t.xword\t" + funcStName + "\n");
275 }
276
277 EmitFunctionSymbolTable(funcEmitInfo);
278
279 for (auto &it : cgFunc.GetEmitStVec()) {
280 /* emit switch table only here */
281 MIRSymbol *st = it.second;
282 DEBUG_ASSERT(st->IsReadOnly(), "NYI");
283 (void)emitter->Emit("\n");
284 (void)emitter->Emit("\t.align 3\n");
285 (void)emitter->Emit(st->GetName() + ":\n");
286 MIRAggConst *arrayConst = safe_cast<MIRAggConst>(st->GetKonst());
287 CHECK_NULL_FATAL(cgFunc.GetMirModule().CurFunction());
288 PUIdx pIdx = cgFunc.GetMirModule().CurFunction()->GetPuidx();
289 char *idx = strdup(std::to_string(pIdx).c_str());
290 CHECK_FATAL(arrayConst != nullptr, "null ptr check");
291 for (size_t i = 0; i < arrayConst->GetConstVec().size(); i++) {
292 MIRLblConst *lblConst = safe_cast<MIRLblConst>(arrayConst->GetConstVecItem(i));
293 CHECK_FATAL(lblConst != nullptr, "null ptr check");
294 CHECK_FATAL(idx != nullptr, "strdup failed");
295 (void)emitter->Emit("\t.quad\t.L.").Emit(idx).Emit("__").Emit(lblConst->GetValue());
296 (void)emitter->Emit(" - " + st->GetName() + "\n");
297 }
298 free(idx);
299 idx = nullptr;
300 }
301
302 for (const auto &mpPair : cgFunc.GetLabelAndValueMap()) {
303 LabelOperand &labelOpnd = aarchCGFunc.GetOrCreateLabelOperand(mpPair.first);
304 A64OpndEmitVisitor visitor(*emitter, nullptr);
305 labelOpnd.Accept(visitor);
306 (void)emitter->Emit(":\n");
307 (void)emitter->Emit("\t.quad ").Emit(static_cast<int64>(mpPair.second)).Emit("\n");
308 }
309 });
310 #endif
311 }
312
EmitAArch64Insn(maplebe::Emitter & emitter,Insn & insn) const313 void AArch64AsmEmitter::EmitAArch64Insn(maplebe::Emitter &emitter, Insn &insn) const
314 {
315 #ifdef ARK_LITECG_DEBUG
316 MOperator mOp = insn.GetMachineOpcode();
317 emitter.SetCurrentMOP(mOp);
318 const InsnDesc *md = insn.GetDesc();
319
320 if (!GetCG()->GenerateVerboseAsm() && !GetCG()->GenerateVerboseCG() && insn.IsComment()) {
321 return;
322 }
323
324 switch (mOp) {
325 case MOP_adrp_ldr: {
326 EmitAdrpLdr(emitter, insn);
327 if (CGOptions::IsLazyBinding() && !GetCG()->IsLibcore()) {
328 EmitLazyBindingRoutine(emitter, insn);
329 }
330 return;
331 }
332 case MOP_counter: {
333 EmitCounter(emitter, insn);
334 return;
335 }
336 case MOP_asm: {
337 EmitInlineAsm(emitter, insn);
338 return;
339 }
340 case MOP_clinit_tail: {
341 EmitClinitTail(emitter, insn);
342 return;
343 }
344 case MOP_lazy_ldr: {
345 EmitLazyLoad(emitter, insn);
346 return;
347 }
348 case MOP_adrp_label: {
349 EmitAdrpLabel(emitter, insn);
350 return;
351 }
352 case MOP_lazy_tail: {
353 /* No need to emit this pseudo instruction. */
354 return;
355 }
356 case MOP_lazy_ldr_static: {
357 EmitLazyLoadStatic(emitter, insn);
358 return;
359 }
360 case MOP_arrayclass_cache_ldr: {
361 EmitArrayClassCacheLoad(emitter, insn);
362 return;
363 }
364 case MOP_get_and_addI:
365 case MOP_get_and_addL: {
366 EmitGetAndAddInt(emitter, insn);
367 return;
368 }
369 case MOP_get_and_setI:
370 case MOP_get_and_setL: {
371 EmitGetAndSetInt(emitter, insn);
372 return;
373 }
374 case MOP_compare_and_swapI:
375 case MOP_compare_and_swapL: {
376 EmitCompareAndSwapInt(emitter, insn);
377 return;
378 }
379 case MOP_string_indexof: {
380 EmitStringIndexOf(emitter, insn);
381 return;
382 }
383 case MOP_pseudo_none:
384 case MOP_pseduo_tls_release: {
385 return;
386 }
387 case MOP_tls_desc_call: {
388 EmitCTlsDescCall(emitter, insn);
389 return;
390 }
391 case MOP_tls_desc_rel: {
392 EmitCTlsDescRel(emitter, insn);
393 return;
394 }
395 case MOP_sync_lock_test_setI:
396 case MOP_sync_lock_test_setL: {
397 EmitSyncLockTestSet(emitter, insn);
398 return;
399 }
400 case MOP_pure_call: {
401 EmitPureCall(emitter, insn);
402 return;
403 }
404 default:
405 break;
406 }
407
408 std::string format(md->format);
409 (void)emitter.Emit("\t").Emit(md->name).Emit("\t");
410 size_t opndSize = insn.GetOperandSize();
411 std::vector<int32> seq(opndSize, -1);
412 std::vector<std::string> prefix(opndSize); /* used for print prefix like "*" in icall *rax */
413 uint32 index = 0;
414 uint32 commaNum = 0;
415 for (uint32 i = 0; i < format.length(); ++i) {
416 char c = format[i];
417 if (c >= '0' && c <= '5') {
418 seq[index++] = c - '0';
419 ++commaNum;
420 } else if (c != ',') {
421 prefix[index].push_back(c);
422 }
423 }
424
425 bool isRefField =
426 (opndSize == 0) ? false : CheckInsnRefField(insn, static_cast<size_t>(static_cast<uint32>(seq[0])));
427 uint32 compositeOpnds = 0;
428 for (uint32 i = 0; i < commaNum; ++i) {
429 if (seq[i] == -1) {
430 continue;
431 }
432 if (prefix[i].length() > 0) {
433 (void)emitter.Emit(prefix[i]);
434 }
435 if (emitter.NeedToDealWithHugeSo() && (mOp == MOP_xbl || mOp == MOP_tail_call_opt_xbl)) {
436 auto *nameOpnd = static_cast<FuncNameOperand *>(&insn.GetOperand(kInsnFirstOpnd));
437 emitter.InsertHugeSoTarget(nameOpnd->GetName());
438 (void)emitter.Emit(nameOpnd->GetName() + emitter.HugeSoPostFix());
439 break;
440 }
441 A64OpndEmitVisitor visitor(emitter, md->opndMD[static_cast<uint32>(seq[i])]);
442
443 insn.GetOperand(static_cast<uint32>(seq[i])).Accept(visitor);
444 if (compositeOpnds == 1) {
445 (void)emitter.Emit("}");
446 }
447 if (compositeOpnds > 0) {
448 --compositeOpnds;
449 }
450 /* reset opnd0 ref-field flag, so following instruction has correct register */
451 if (isRefField && (i == 0)) {
452 static_cast<RegOperand *>(&insn.GetOperand(static_cast<uint32>(seq[0])))->SetRefField(false);
453 }
454 /* Temporary comment the label:.Label.debug.callee */
455 if (i != (commaNum - 1)) {
456 (void)emitter.Emit(", ");
457 }
458 const uint32 commaNumForEmitLazy = 2;
459 if (!CGOptions::IsLazyBinding() || GetCG()->IsLibcore() || (mOp != MOP_wldr && mOp != MOP_xldr) ||
460 commaNum != commaNumForEmitLazy || i != 1 ||
461 !insn.GetOperand(static_cast<uint32>(seq[1])).IsMemoryAccessOperand()) {
462 continue;
463 }
464 /*
465 * Only check the last operand of ldr in lo12 mode.
466 * Check the second operand, if it's [AArch64MemOperand::kAddrModeLo12Li]
467 */
468 auto *memOpnd = static_cast<MemOperand *>(&insn.GetOperand(static_cast<uint32>(seq[1])));
469 if (memOpnd == nullptr || memOpnd->GetAddrMode() != MemOperand::kAddrModeLo12Li) {
470 continue;
471 }
472 const MIRSymbol *sym = memOpnd->GetSymbol();
473 if (sym->IsMuidFuncDefTab() || sym->IsMuidFuncUndefTab() || sym->IsMuidDataDefTab() ||
474 sym->IsMuidDataUndefTab()) {
475 (void)emitter.Emit("\n");
476 EmitLazyBindingRoutine(emitter, insn);
477 }
478 }
479 if (GetCG()->GenerateVerboseCG() || (GetCG()->GenerateVerboseAsm() && insn.IsComment())) {
480 const char *comment = insn.GetComment().c_str();
481 if (comment != nullptr && strlen(comment) > 0) {
482 (void)emitter.Emit("\t\t// ").Emit(comment);
483 }
484 }
485
486 (void)emitter.Emit("\n");
487 #endif
488 }
489
490 #ifdef ARK_LITECG_DEBUG
AsmStringOutputRegNum(bool isInt,uint32 regno,uint32 intBase,uint32 fpBase,std::string & strToEmit)491 static void AsmStringOutputRegNum(bool isInt, uint32 regno, uint32 intBase, uint32 fpBase, std::string &strToEmit)
492 {
493 regno_t newRegno;
494 if (isInt) {
495 CHECK_FATAL(regno >= intBase, "value overflow");
496 newRegno = regno - intBase;
497 } else {
498 newRegno = regno - fpBase;
499 }
500 if (newRegno > (kDecimalMax - 1)) {
501 uint32 tenth = newRegno / kDecimalMax;
502 strToEmit += '0' + static_cast<char>(tenth);
503 newRegno -= (kDecimalMax * tenth);
504 }
505 strToEmit += newRegno + '0';
506 }
507 #endif
508
EmitInlineAsm(Emitter & emitter,const Insn & insn) const509 void AArch64AsmEmitter::EmitInlineAsm(Emitter &emitter, const Insn &insn) const
510 {
511 #ifdef ARK_LITECG_DEBUG
512 (void)emitter.Emit("\t//Inline asm begin\n\t");
513 auto &list1 = static_cast<ListOperand &>(insn.GetOperand(kAsmOutputListOpnd));
514 std::vector<RegOperand *> outOpnds;
515 for (auto *regOpnd : list1.GetOperands()) {
516 outOpnds.push_back(regOpnd);
517 }
518 auto &list2 = static_cast<ListOperand &>(insn.GetOperand(kAsmInputListOpnd));
519 std::vector<RegOperand *> inOpnds;
520 for (auto *regOpnd : list2.GetOperands()) {
521 inOpnds.push_back(regOpnd);
522 }
523 auto &list6 = static_cast<ListConstraintOperand &>(insn.GetOperand(kAsmOutputRegPrefixOpnd));
524 auto &list7 = static_cast<ListConstraintOperand &>(insn.GetOperand(kAsmInputRegPrefixOpnd));
525 MapleString asmStr = static_cast<StringOperand &>(insn.GetOperand(kAsmStringOpnd)).GetComment();
526 std::string stringToEmit;
527 auto IsMemAccess = [](char c) -> bool { return c == '['; };
528 auto EmitRegister = [&](const char *p, bool isInt, uint32 regNO, bool unDefRegSize) -> void {
529 if (IsMemAccess(p[0])) {
530 stringToEmit += "[x";
531 AsmStringOutputRegNum(isInt, regNO, R0, V0, stringToEmit);
532 stringToEmit += "]";
533 } else {
534 DEBUG_ASSERT((p[0] == 'w' || p[0] == 'x' || p[0] == 's' || p[0] == 'd' || p[0] == 'v'),
535 "Asm invalid register type");
536 if ((p[0] == 'w' || p[0] == 'x') && unDefRegSize) {
537 stringToEmit += 'x';
538 } else {
539 stringToEmit += p[0];
540 }
541 if (!unDefRegSize) {
542 isInt = (p[0] == 'w' || p[0] == 'x');
543 }
544 AsmStringOutputRegNum(isInt, regNO, R0, V0, stringToEmit);
545 }
546 };
547 for (size_t i = 0; i < asmStr.length(); ++i) {
548 switch (asmStr[i]) {
549 case '$': {
550 char c = asmStr[++i];
551 if ((c >= '0') && (c <= '9')) {
552 auto val = static_cast<uint32>(c - '0');
553 if (asmStr[i + 1] >= '0' && asmStr[i + 1] <= '9') {
554 val = val * kDecimalMax + static_cast<uint32>(asmStr[++i] - '0');
555 }
556 if (val < outOpnds.size()) {
557 const char *prefix = list6.stringList[val]->GetComment().c_str();
558 RegOperand *opnd = outOpnds[val];
559 EmitRegister(prefix, opnd->IsOfIntClass(), opnd->GetRegisterNumber(), true);
560 } else {
561 val -= static_cast<uint32>(outOpnds.size());
562 CHECK_FATAL(val < inOpnds.size(), "Inline asm : invalid register constraint number");
563 RegOperand *opnd = inOpnds[val];
564 /* input is a immediate */
565 const char *prefix = list7.stringList[val]->GetComment().c_str();
566 if (prefix[0] == 'i') {
567 stringToEmit += '#';
568 for (size_t k = 1; k < list7.stringList[val]->GetComment().length(); ++k) {
569 stringToEmit += prefix[k];
570 }
571 } else {
572 EmitRegister(prefix, opnd->IsOfIntClass(), opnd->GetRegisterNumber(), true);
573 }
574 }
575 } else if (c == '{') {
576 c = asmStr[++i];
577 CHECK_FATAL(((c >= '0') && (c <= '9')), "Inline asm : invalid register constraint number");
578 auto val = static_cast<uint32>(c - '0');
579 if (asmStr[i + 1] >= '0' && asmStr[i + 1] <= '9') {
580 val = val * kDecimalMax + static_cast<uint32>(asmStr[++i] - '0');
581 }
582 regno_t regno;
583 bool isAddr = false;
584 if (val < outOpnds.size()) {
585 RegOperand *opnd = outOpnds[val];
586 regno = opnd->GetRegisterNumber();
587 isAddr = IsMemAccess(list6.stringList[val]->GetComment().c_str()[0]);
588 } else {
589 val -= static_cast<uint32>(outOpnds.size());
590 CHECK_FATAL(val < inOpnds.size(), "Inline asm : invalid register constraint number");
591 RegOperand *opnd = inOpnds[val];
592 regno = opnd->GetRegisterNumber();
593 DEBUG_ASSERT(list7.stringList[val]->GetComment().c_str() != nullptr,
594 "list7 GetComment.c_str should not be nullptr");
595 isAddr = IsMemAccess(list7.stringList[val]->GetComment().c_str()[0]);
596 }
597 c = asmStr[++i];
598 CHECK_FATAL(c == ':', "Parsing error in inline asm string during emit");
599 c = asmStr[++i];
600 std::string prefix(1, c);
601 if (c == 'a' || isAddr) {
602 prefix = "[x";
603 }
604 EmitRegister(prefix.c_str(), true, regno, false);
605 c = asmStr[++i];
606 CHECK_FATAL(c == '}', "Parsing error in inline asm string during emit");
607 }
608 break;
609 }
610 case '\n': {
611 stringToEmit += "\n\t";
612 break;
613 }
614 default:
615 stringToEmit += asmStr[i];
616 }
617 }
618 (void)emitter.Emit(stringToEmit);
619 (void)emitter.Emit("\n\t//Inline asm end\n");
620 #endif
621 }
622
EmitClinitTail(Emitter & emitter,const Insn & insn) const623 void AArch64AsmEmitter::EmitClinitTail(Emitter &emitter, const Insn &insn) const
624 {
625 #ifdef ARK_LITECG_DEBUG
626 /*
627 * ldr x17, [xs, #112]
628 * ldr wzr, [x17]
629 */
630 const InsnDesc *md = &AArch64CG::kMd[MOP_clinit_tail];
631
632 Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
633
634 const OpndDesc *prop0 = md->opndMD[0];
635 A64OpndEmitVisitor visitor(emitter, prop0);
636
637 /* emit "ldr x17,[xs,#112]" */
638 (void)emitter.Emit("\t").Emit("ldr").Emit("\tx17, [");
639 opnd0->Accept(visitor);
640 (void)emitter.Emit(", #");
641 (void)emitter.Emit(static_cast<uint32>(ClassMetadata::OffsetOfInitState()));
642 (void)emitter.Emit("]");
643 (void)emitter.Emit("\n");
644
645 /* emit "ldr xzr, [x17]" */
646 (void)emitter.Emit("\t").Emit("ldr\txzr, [x17]\n");
647 #endif
648 }
649
EmitLazyLoad(Emitter & emitter,const Insn & insn) const650 void AArch64AsmEmitter::EmitLazyLoad(Emitter &emitter, const Insn &insn) const
651 {
652 #ifdef ARK_LITECG_DEBUG
653 /*
654 * ldr wd, [xs] # xd and xs should be differenct register
655 * ldr wd, [xd]
656 */
657 const InsnDesc *md = &AArch64CG::kMd[MOP_lazy_ldr];
658
659 Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
660 Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
661 const OpndDesc *prop0 = md->opndMD[0];
662 const OpndDesc *prop1 = md->opndMD[1];
663 A64OpndEmitVisitor visitor(emitter, prop0);
664 A64OpndEmitVisitor visitor1(emitter, prop1);
665
666 /* emit "ldr wd, [xs]" */
667 (void)emitter.Emit("\t").Emit("ldr\t");
668 #ifdef USE_32BIT_REF
669 opnd0->Accept(visitor);
670 #else
671 opnd0->Accept(visitor1);
672 #endif
673 (void)emitter.Emit(", [");
674 opnd1->Accept(visitor1);
675 (void)emitter.Emit("]\t// lazy load.\n");
676
677 /* emit "ldr wd, [xd]" */
678 (void)emitter.Emit("\t").Emit("ldr\t");
679 opnd0->Accept(visitor);
680 (void)emitter.Emit(", [");
681 opnd1->Accept(visitor1);
682 (void)emitter.Emit("]\t// lazy load.\n");
683 #endif
684 }
685
EmitCounter(Emitter & emitter,const Insn & insn) const686 void AArch64AsmEmitter::EmitCounter(Emitter &emitter, const Insn &insn) const
687 {
688 #ifdef ARK_LITECG_DEBUG
689 /*
690 * adrp x1, __profile_bb_table$$GetBoolean_bytecode+4
691 * ldr w17, [x1, #:lo12:__profile_bb_table$$GetBoolean_bytecode+4]
692 * add w17, w17, #1
693 * str w17, [x1, #:lo12:__profile_bb_table$$GetBoolean_bytecode+4]
694 */
695 const InsnDesc *md = &AArch64CG::kMd[MOP_counter];
696
697 Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
698 Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
699 const OpndDesc *prop0 = md->opndMD[kInsnFirstOpnd];
700 A64OpndEmitVisitor visitor(emitter, prop0);
701 StImmOperand *stImmOpnd = static_cast<StImmOperand *>(opnd1);
702 CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitCounter");
703 /* emit adrp */
704 (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
705 opnd0->Accept(visitor);
706 (void)emitter.Emit(",");
707 (void)emitter.Emit(stImmOpnd->GetName());
708 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
709 (void)emitter.Emit("\n");
710 /* emit ldr */
711 (void)emitter.Emit("\t").Emit("ldr").Emit("\tw17, [");
712 opnd0->Accept(visitor);
713 (void)emitter.Emit(",");
714 (void)emitter.Emit("#");
715 (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
716 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
717 (void)emitter.Emit("]");
718 (void)emitter.Emit("\n");
719 /* emit add */
720 (void)emitter.Emit("\t").Emit("add").Emit("\tw17, w17, #1");
721 (void)emitter.Emit("\n");
722 /* emit str */
723 (void)emitter.Emit("\t").Emit("str").Emit("\tw17, [");
724 opnd0->Accept(visitor);
725 (void)emitter.Emit(",");
726 (void)emitter.Emit("#");
727 (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
728 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
729 (void)emitter.Emit("]");
730 (void)emitter.Emit("\n");
731 #endif
732 }
733
EmitAdrpLabel(Emitter & emitter,const Insn & insn) const734 void AArch64AsmEmitter::EmitAdrpLabel(Emitter &emitter, const Insn &insn) const
735 {
736 #ifdef ARK_LITECG_DEBUG
737 /* adrp xd, label
738 * add xd, xd, #lo12:label
739 */
740 const InsnDesc *md = &AArch64CG::kMd[MOP_adrp_label];
741
742 Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
743 Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
744 const OpndDesc *prop0 = md->opndMD[0];
745 A64OpndEmitVisitor visitor(emitter, prop0);
746 auto lidx = static_cast<ImmOperand *>(opnd1)->GetValue();
747
748 /* adrp xd, label */
749 (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
750 opnd0->Accept(visitor);
751 (void)emitter.Emit(", ");
752 char *idx;
753 CHECK_NULL_FATAL(Globals::GetInstance()->GetBECommon()->GetMIRModule().CurFunction());
754 idx =
755 strdup(std::to_string(Globals::GetInstance()->GetBECommon()->GetMIRModule().CurFunction()->GetPuidx()).c_str());
756 CHECK_FATAL(idx != nullptr, "strdup failed");
757 (void)emitter.Emit(".L.").Emit(idx).Emit("__").Emit(lidx).Emit("\n");
758
759 /* add xd, xd, #lo12:label */
760 (void)emitter.Emit("\tadd\t");
761 opnd0->Accept(visitor);
762 (void)emitter.Emit(", ");
763 opnd0->Accept(visitor);
764 (void)emitter.Emit(", ");
765 (void)emitter.Emit(":lo12:").Emit(".L.").Emit(idx).Emit("__").Emit(lidx).Emit("\n");
766 (void)emitter.Emit("\n");
767 free(idx);
768 idx = nullptr;
769 #endif
770 }
771
EmitAdrpLdr(Emitter & emitter,const Insn & insn) const772 void AArch64AsmEmitter::EmitAdrpLdr(Emitter &emitter, const Insn &insn) const
773 {
774 #ifdef ARK_LITECG_DEBUG
775 const InsnDesc *md = &AArch64CG::kMd[MOP_adrp_ldr];
776 Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
777 Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
778 const OpndDesc *prop0 = md->opndMD[0];
779 A64OpndEmitVisitor visitor(emitter, prop0);
780 auto *stImmOpnd = static_cast<StImmOperand *>(opnd1);
781 CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitAdrpLdr");
782
783 (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
784 opnd0->Accept(visitor);
785 (void)emitter.Emit(", ");
786 (void)emitter.Emit(stImmOpnd->GetName());
787 if (stImmOpnd->GetOffset() != 0) {
788 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
789 }
790 (void)emitter.Emit("\n");
791
792 (void)emitter.Emit("\tldr\t");
793 static_cast<RegOperand *>(opnd0)->SetRefField(true);
794 opnd0->Accept(visitor);
795 static_cast<RegOperand *>(opnd0)->SetRefField(false);
796 (void)emitter.Emit(", ");
797 (void)emitter.Emit("[");
798 opnd0->Accept(visitor);
799 (void)emitter.Emit(",");
800 (void)emitter.Emit("#");
801 (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
802 if (stImmOpnd->GetOffset() != 0) {
803 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
804 }
805 (void)emitter.Emit("]\n");
806 #endif
807 }
808
EmitLazyLoadStatic(Emitter & emitter,const Insn & insn) const809 void AArch64AsmEmitter::EmitLazyLoadStatic(Emitter &emitter, const Insn &insn) const
810 {
811 #ifdef ARK_LITECG_DEBUG
812 /* adrp xd, :got:__staticDecoupleValueOffset$$xxx+offset
813 * ldr wd, [xd, #:got_lo12:__staticDecoupleValueOffset$$xxx+offset]
814 * ldr wzr, [xd]
815 */
816 const InsnDesc *md = &AArch64CG::kMd[MOP_lazy_ldr_static];
817
818 Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
819 Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
820 const OpndDesc *prop0 = md->GetOpndDes(0);
821 A64OpndEmitVisitor visitor(emitter, prop0);
822 auto *stImmOpnd = static_cast<StImmOperand *>(opnd1);
823 CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitLazyLoadStatic");
824
825 /* emit "adrp xd, :got:__staticDecoupleValueOffset$$xxx+offset" */
826 (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
827 opnd0->Accept(visitor);
828 (void)emitter.Emit(", ");
829 (void)emitter.Emit(stImmOpnd->GetName());
830 if (stImmOpnd->GetOffset() != 0) {
831 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
832 }
833 (void)emitter.Emit("\t// lazy load static.\n");
834
835 /* emit "ldr wd, [xd, #:got_lo12:__staticDecoupleValueOffset$$xxx+offset]" */
836 (void)emitter.Emit("\tldr\t");
837 static_cast<RegOperand *>(opnd0)->SetRefField(true);
838 #ifdef USE_32BIT_REF
839 const OpndDesc prop2(prop0->GetOperandType(), prop0->GetRegProp(), prop0->GetSize() / 2);
840 opnd0->Emit(emitter, &prop2); /* ldr wd, ... for terminal system */
841 #else
842 opnd0->Accept(visitor); /* ldr xd, ... for qemu */
843 #endif /* USE_32BIT_REF */
844 static_cast<RegOperand *>(opnd0)->SetRefField(false);
845 (void)emitter.Emit(", ");
846 (void)emitter.Emit("[");
847 opnd0->Accept(visitor);
848 (void)emitter.Emit(",");
849 (void)emitter.Emit("#");
850 (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
851 if (stImmOpnd->GetOffset() != 0) {
852 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
853 }
854 (void)emitter.Emit("]\t// lazy load static.\n");
855
856 /* emit "ldr wzr, [xd]" */
857 (void)emitter.Emit("\t").Emit("ldr\twzr, [");
858 opnd0->Accept(visitor);
859 (void)emitter.Emit("]\t// lazy load static.\n");
860 #endif
861 }
862
EmitArrayClassCacheLoad(Emitter & emitter,const Insn & insn) const863 void AArch64AsmEmitter::EmitArrayClassCacheLoad(Emitter &emitter, const Insn &insn) const
864 {
865 #ifdef ARK_LITECG_DEBUG
866 /* adrp xd, :got:__arrayClassCacheTable$$xxx+offset
867 * ldr wd, [xd, #:got_lo12:__arrayClassCacheTable$$xxx+offset]
868 * ldr wzr, [xd]
869 */
870 const InsnDesc *md = &AArch64CG::kMd[MOP_arrayclass_cache_ldr];
871 Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
872 Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
873 const OpndDesc *prop0 = md->GetOpndDes(kInsnFirstOpnd);
874 A64OpndEmitVisitor visitor(emitter, prop0);
875 auto *stImmOpnd = static_cast<StImmOperand *>(opnd1);
876 CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitLazyLoadStatic");
877
878 /* emit "adrp xd, :got:__arrayClassCacheTable$$xxx+offset" */
879 (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
880 opnd0->Accept(visitor);
881 (void)emitter.Emit(", ");
882 (void)emitter.Emit(stImmOpnd->GetName());
883 if (stImmOpnd->GetOffset() != 0) {
884 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
885 }
886 (void)emitter.Emit("\t// load array class.\n");
887
888 /* emit "ldr wd, [xd, #:got_lo12:__arrayClassCacheTable$$xxx+offset]" */
889 (void)emitter.Emit("\tldr\t");
890 static_cast<RegOperand *>(opnd0)->SetRefField(true);
891 #ifdef USE_32BIT_REF
892 const OpndDesc prop2(prop0->GetOperandType(), prop0->GetRegProp(), prop0->GetSize() / 2);
893 A64OpndEmitVisitor visitor2(emitter, prop2);
894 opnd0->Accept(visitor2); /* ldr wd, ... for terminal system */
895 #else
896 opnd0->Accept(visitor); /* ldr xd, ... for qemu */
897 #endif /* USE_32BIT_REF */
898 static_cast<RegOperand *>(opnd0)->SetRefField(false);
899 (void)emitter.Emit(", ");
900 (void)emitter.Emit("[");
901 opnd0->Accept(visitor);
902 (void)emitter.Emit(",");
903 (void)emitter.Emit("#");
904 (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
905 if (stImmOpnd->GetOffset() != 0) {
906 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
907 }
908 (void)emitter.Emit("]\t// load array class.\n");
909
910 /* emit "ldr wzr, [xd]" */
911 (void)emitter.Emit("\t").Emit("ldr\twzr, [");
912 opnd0->Accept(visitor);
913 (void)emitter.Emit("]\t// check resolve array class.\n");
914 #endif
915 }
916
917 /*
918 * intrinsic_get_add_int w0, xt, wt, ws, x1, x2, w3, label
919 * add xt, x1, x2
920 * label:
921 * ldaxr w0, [xt]
922 * add wt, w0, w3
923 * stlxr ws, wt, [xt]
924 * cbnz ws, label
925 */
EmitGetAndAddInt(Emitter & emitter,const Insn & insn) const926 void AArch64AsmEmitter::EmitGetAndAddInt(Emitter &emitter, const Insn &insn) const
927 {
928 #ifdef ARK_LITECG_DEBUG
929 DEBUG_ASSERT(insn.GetOperandSize() > kInsnEighthOpnd, "ensure the oprands number");
930 (void)emitter.Emit("\t//\tstart of Unsafe.getAndAddInt.\n");
931 Operand *tempOpnd0 = &insn.GetOperand(kInsnSecondOpnd);
932 Operand *tempOpnd1 = &insn.GetOperand(kInsnThirdOpnd);
933 Operand *tempOpnd2 = &insn.GetOperand(kInsnFourthOpnd);
934 Operand *objOpnd = &insn.GetOperand(kInsnFifthOpnd);
935 Operand *offsetOpnd = &insn.GetOperand(kInsnSixthOpnd);
936 Operand *deltaOpnd = &insn.GetOperand(kInsnSeventhOpnd);
937 Operand *labelOpnd = &insn.GetOperand(kInsnEighthOpnd);
938 A64OpndEmitVisitor visitor(emitter, nullptr);
939 /* emit add. */
940 (void)emitter.Emit("\t").Emit("add").Emit("\t");
941 tempOpnd0->Accept(visitor);
942 (void)emitter.Emit(", ");
943 objOpnd->Accept(visitor);
944 (void)emitter.Emit(", ");
945 offsetOpnd->Accept(visitor);
946 (void)emitter.Emit("\n");
947 /* emit label. */
948 labelOpnd->Accept(visitor);
949 (void)emitter.Emit(":\n");
950 Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
951 const MOperator mOp = insn.GetMachineOpcode();
952 const InsnDesc *md = &AArch64CG::kMd[mOp];
953 const OpndDesc *retProp = md->opndMD[kInsnFirstOpnd];
954 A64OpndEmitVisitor retVisitor(emitter, retProp);
955 /* emit ldaxr */
956 (void)emitter.Emit("\t").Emit("ldaxr").Emit("\t");
957 retVal->Accept(retVisitor);
958 (void)emitter.Emit(", [");
959 tempOpnd0->Accept(visitor);
960 (void)emitter.Emit("]\n");
961 /* emit add. */
962 (void)emitter.Emit("\t").Emit("add").Emit("\t");
963 tempOpnd1->Accept(retVisitor);
964 (void)emitter.Emit(", ");
965 retVal->Accept(retVisitor);
966 (void)emitter.Emit(", ");
967 deltaOpnd->Accept(retVisitor);
968 (void)emitter.Emit("\n");
969 /* emit stlxr. */
970 (void)emitter.Emit("\t").Emit("stlxr").Emit("\t");
971 tempOpnd2->Accept(visitor);
972 (void)emitter.Emit(", ");
973 tempOpnd1->Accept(retVisitor);
974 (void)emitter.Emit(", [");
975 tempOpnd0->Accept(visitor);
976 (void)emitter.Emit("]\n");
977 /* emit cbnz. */
978 (void)emitter.Emit("\t").Emit("cbnz").Emit("\t");
979 tempOpnd2->Accept(visitor);
980 (void)emitter.Emit(", ");
981 labelOpnd->Accept(visitor);
982 (void)emitter.Emit("\n");
983 (void)emitter.Emit("\t//\tend of Unsafe.getAndAddInt.\n");
984 #endif
985 }
986
987 /*
988 * intrinsic_get_set_int w0, xt, ws, x1, x2, w3, label
989 * add xt, x1, x2
990 * label:
991 * ldaxr w0, [xt]
992 * stlxr ws, w3, [xt]
993 * cbnz ws, label
994 */
EmitGetAndSetInt(Emitter & emitter,const Insn & insn) const995 void AArch64AsmEmitter::EmitGetAndSetInt(Emitter &emitter, const Insn &insn) const
996 {
997 #ifdef ARK_LITECG_DEBUG
998 /* MOP_get_and_setI and MOP_get_and_setL have 7 operands */
999 DEBUG_ASSERT(insn.GetOperandSize() > kInsnSeventhOpnd, "ensure the operands number");
1000 Operand *tempOpnd0 = &insn.GetOperand(kInsnSecondOpnd);
1001 Operand *tempOpnd1 = &insn.GetOperand(kInsnThirdOpnd);
1002 Operand *objOpnd = &insn.GetOperand(kInsnFourthOpnd);
1003 Operand *offsetOpnd = &insn.GetOperand(kInsnFifthOpnd);
1004 A64OpndEmitVisitor visitor(emitter, nullptr);
1005 /* add x1, x1, x2 */
1006 (void)emitter.Emit("\tadd\t");
1007 tempOpnd0->Accept(visitor);
1008 (void)emitter.Emit(", ");
1009 objOpnd->Accept(visitor);
1010 (void)emitter.Emit(", ");
1011 offsetOpnd->Accept(visitor);
1012 (void)emitter.Emit("\n");
1013 Operand *labelOpnd = &insn.GetOperand(kInsnSeventhOpnd);
1014 /* label: */
1015 labelOpnd->Accept(visitor);
1016 (void)emitter.Emit(":\n");
1017 Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1018 /* ldaxr w0, [xt] */
1019 (void)emitter.Emit("\tldaxr\t");
1020 retVal->Accept(visitor);
1021 (void)emitter.Emit(", [");
1022 tempOpnd0->Accept(visitor);
1023 (void)emitter.Emit("]\n");
1024 Operand *newValueOpnd = &insn.GetOperand(kInsnSixthOpnd);
1025 /* stlxr ws, w3, [xt] */
1026 (void)emitter.Emit("\tstlxr\t");
1027 tempOpnd1->Accept(visitor);
1028 (void)emitter.Emit(", ");
1029 newValueOpnd->Accept(visitor);
1030 (void)emitter.Emit(", [");
1031 tempOpnd0->Accept(visitor);
1032 (void)emitter.Emit("]\n");
1033 /* cbnz w2, label */
1034 (void)emitter.Emit("\tcbnz\t");
1035 tempOpnd1->Accept(visitor);
1036 (void)emitter.Emit(", ");
1037 labelOpnd->Accept(visitor);
1038 (void)emitter.Emit("\n");
1039 #endif
1040 }
1041
1042 /*
1043 * intrinsic_string_indexof w0, x1, w2, x3, w4, x5, x6, x7, x8, x9, w10,
1044 * Label.FIRST_LOOP, Label.STR2_NEXT, Label.STR1_LOOP,
1045 * Label.STR1_NEXT, Label.LAST_WORD, Label.NOMATCH, Label.RET
1046 * cmp w4, w2
1047 * b.gt .Label.NOMATCH
1048 * sub w2, w2, w4
1049 * sub w4, w4, #8
1050 * mov w10, w2
1051 * uxtw x4, w4
1052 * uxtw x2, w2
1053 * add x3, x3, x4
1054 * add x1, x1, x2
1055 * neg x4, x4
1056 * neg x2, x2
1057 * ldr x5, [x3,x4]
1058 * .Label.FIRST_LOOP:
1059 * ldr x7, [x1,x2]
1060 * cmp x5, x7
1061 * b.eq .Label.STR1_LOOP
1062 * .Label.STR2_NEXT:
1063 * adds x2, x2, #1
1064 * b.le .Label.FIRST_LOOP
1065 * b .Label.NOMATCH
1066 * .Label.STR1_LOOP:
1067 * adds x8, x4, #8
1068 * add x9, x2, #8
1069 * b.ge .Label.LAST_WORD
1070 * .Label.STR1_NEXT:
1071 * ldr x6, [x3,x8]
1072 * ldr x7, [x1,x9]
1073 * cmp x6, x7
1074 * b.ne .Label.STR2_NEXT
1075 * adds x8, x8, #8
1076 * add x9, x9, #8
1077 * b.lt .Label.STR1_NEXT
1078 * .Label.LAST_WORD:
1079 * ldr x6, [x3]
1080 * sub x9, x1, x4
1081 * ldr x7, [x9,x2]
1082 * cmp x6, x7
1083 * b.ne .Label.STR2_NEXT
1084 * add w0, w10, w2
1085 * b .Label.RET
1086 * .Label.NOMATCH:
1087 * mov w0, #-1
1088 * .Label.RET:
1089 */
EmitStringIndexOf(Emitter & emitter,const Insn & insn) const1090 void AArch64AsmEmitter::EmitStringIndexOf(Emitter &emitter, const Insn &insn) const
1091 {
1092 #ifdef ARK_LITECG_DEBUG
1093 /* MOP_string_indexof has 18 operands */
1094 DEBUG_ASSERT(insn.GetOperandSize() == 18, "ensure the operands number");
1095 Operand *patternLengthOpnd = &insn.GetOperand(kInsnFifthOpnd);
1096 Operand *srcLengthOpnd = &insn.GetOperand(kInsnThirdOpnd);
1097 const std::string patternLengthReg =
1098 AArch64CG::intRegNames[AArch64CG::kR64List][static_cast<RegOperand *>(patternLengthOpnd)->GetRegisterNumber()];
1099 const std::string srcLengthReg =
1100 AArch64CG::intRegNames[AArch64CG::kR64List][static_cast<RegOperand *>(srcLengthOpnd)->GetRegisterNumber()];
1101 A64OpndEmitVisitor visitor(emitter, nullptr);
1102 /* cmp w4, w2 */
1103 (void)emitter.Emit("\tcmp\t");
1104 patternLengthOpnd->Accept(visitor);
1105 (void)emitter.Emit(", ");
1106 srcLengthOpnd->Accept(visitor);
1107 (void)emitter.Emit("\n");
1108 /* the 16th operand of MOP_string_indexof is Label.NOMATCH */
1109 Operand *labelNoMatch = &insn.GetOperand(16);
1110 /* b.gt Label.NOMATCH */
1111 (void)emitter.Emit("\tb.gt\t");
1112 labelNoMatch->Accept(visitor);
1113 (void)emitter.Emit("\n");
1114 /* sub w2, w2, w4 */
1115 (void)emitter.Emit("\tsub\t");
1116 srcLengthOpnd->Accept(visitor);
1117 (void)emitter.Emit(", ");
1118 srcLengthOpnd->Accept(visitor);
1119 (void)emitter.Emit(", ");
1120 patternLengthOpnd->Accept(visitor);
1121 (void)emitter.Emit("\n");
1122 /* sub w4, w4, #8 */
1123 (void)emitter.Emit("\tsub\t");
1124 patternLengthOpnd->Accept(visitor);
1125 (void)emitter.Emit(", ");
1126 patternLengthOpnd->Accept(visitor);
1127 (void)emitter.Emit(", #8\n");
1128 /* the 10th operand of MOP_string_indexof is w10 */
1129 Operand *resultTmp = &insn.GetOperand(10);
1130 /* mov w10, w2 */
1131 (void)emitter.Emit("\tmov\t");
1132 resultTmp->Accept(visitor);
1133 (void)emitter.Emit(", ");
1134 srcLengthOpnd->Accept(visitor);
1135 (void)emitter.Emit("\n");
1136 /* uxtw x4, w4 */
1137 (void)emitter.Emit("\tuxtw\t").Emit(patternLengthReg);
1138 (void)emitter.Emit(", ");
1139 patternLengthOpnd->Accept(visitor);
1140 (void)emitter.Emit("\n");
1141 /* uxtw x2, w2 */
1142 (void)emitter.Emit("\tuxtw\t").Emit(srcLengthReg);
1143 (void)emitter.Emit(", ");
1144 srcLengthOpnd->Accept(visitor);
1145 (void)emitter.Emit("\n");
1146 Operand *patternStringBaseOpnd = &insn.GetOperand(kInsnFourthOpnd);
1147 /* add x3, x3, x4 */
1148 (void)emitter.Emit("\tadd\t");
1149 patternStringBaseOpnd->Accept(visitor);
1150 (void)emitter.Emit(", ");
1151 patternStringBaseOpnd->Accept(visitor);
1152 (void)emitter.Emit(", ").Emit(patternLengthReg);
1153 (void)emitter.Emit("\n");
1154 Operand *srcStringBaseOpnd = &insn.GetOperand(kInsnSecondOpnd);
1155 /* add x1, x1, x2 */
1156 (void)emitter.Emit("\tadd\t");
1157 srcStringBaseOpnd->Accept(visitor);
1158 (void)emitter.Emit(", ");
1159 srcStringBaseOpnd->Accept(visitor);
1160 (void)emitter.Emit(", ").Emit(srcLengthReg);
1161 (void)emitter.Emit("\n");
1162 /* neg x4, x4 */
1163 (void)emitter.Emit("\tneg\t").Emit(patternLengthReg);
1164 (void)emitter.Emit(", ").Emit(patternLengthReg);
1165 (void)emitter.Emit("\n");
1166 /* neg x2, x2 */
1167 (void)emitter.Emit("\tneg\t").Emit(srcLengthReg);
1168 (void)emitter.Emit(", ").Emit(srcLengthReg);
1169 (void)emitter.Emit("\n");
1170 Operand *first = &insn.GetOperand(kInsnSixthOpnd);
1171 /* ldr x5, [x3,x4] */
1172 (void)emitter.Emit("\tldr\t");
1173 first->Accept(visitor);
1174 (void)emitter.Emit(", [");
1175 patternStringBaseOpnd->Accept(visitor);
1176 (void)emitter.Emit(",").Emit(patternLengthReg);
1177 (void)emitter.Emit("]\n");
1178 /* the 11th operand of MOP_string_indexof is Label.FIRST_LOOP */
1179 Operand *labelFirstLoop = &insn.GetOperand(11);
1180 /* .Label.FIRST_LOOP: */
1181 labelFirstLoop->Accept(visitor);
1182 (void)emitter.Emit(":\n");
1183 /* the 7th operand of MOP_string_indexof is x7 */
1184 Operand *ch2 = &insn.GetOperand(7);
1185 /* ldr x7, [x1,x2] */
1186 (void)emitter.Emit("\tldr\t");
1187 ch2->Accept(visitor);
1188 (void)emitter.Emit(", [");
1189 srcStringBaseOpnd->Accept(visitor);
1190 (void)emitter.Emit(",").Emit(srcLengthReg);
1191 (void)emitter.Emit("]\n");
1192 /* cmp x5, x7 */
1193 (void)emitter.Emit("\tcmp\t");
1194 first->Accept(visitor);
1195 (void)emitter.Emit(", ");
1196 ch2->Accept(visitor);
1197 (void)emitter.Emit("\n");
1198 /* the 13th operand of MOP_string_indexof is Label.STR1_LOOP */
1199 Operand *labelStr1Loop = &insn.GetOperand(13);
1200 /* b.eq .Label.STR1_LOOP */
1201 (void)emitter.Emit("\tb.eq\t");
1202 labelStr1Loop->Accept(visitor);
1203 (void)emitter.Emit("\n");
1204 /* the 12th operand of MOP_string_indexof is Label.STR2_NEXT */
1205 Operand *labelStr2Next = &insn.GetOperand(12);
1206 /* .Label.STR2_NEXT: */
1207 labelStr2Next->Accept(visitor);
1208 (void)emitter.Emit(":\n");
1209 /* adds x2, x2, #1 */
1210 (void)emitter.Emit("\tadds\t").Emit(srcLengthReg);
1211 (void)emitter.Emit(", ").Emit(srcLengthReg);
1212 (void)emitter.Emit(", #1\n");
1213 /* b.le .Label.FIRST_LOOP */
1214 (void)emitter.Emit("\tb.le\t");
1215 labelFirstLoop->Accept(visitor);
1216 (void)emitter.Emit("\n");
1217 /* b .Label.NOMATCH */
1218 (void)emitter.Emit("\tb\t");
1219 labelNoMatch->Accept(visitor);
1220 (void)emitter.Emit("\n");
1221 /* .Label.STR1_LOOP: */
1222 labelStr1Loop->Accept(visitor);
1223 (void)emitter.Emit(":\n");
1224 /* the 8th operand of MOP_string_indexof is x8 */
1225 Operand *tmp1 = &insn.GetOperand(kInsnEighthOpnd);
1226 /* adds x8, x4, #8 */
1227 (void)emitter.Emit("\tadds\t");
1228 tmp1->Accept(visitor);
1229 (void)emitter.Emit(", ").Emit(patternLengthReg);
1230 (void)emitter.Emit(", #8\n");
1231 /* the 9th operand of MOP_string_indexof is x9 */
1232 Operand *tmp2 = &insn.GetOperand(9);
1233 /* add x9, x2, #8 */
1234 (void)emitter.Emit("\tadd\t");
1235 tmp2->Accept(visitor);
1236 (void)emitter.Emit(", ").Emit(srcLengthReg);
1237 (void)emitter.Emit(", #8\n");
1238 /* the 15th operand of MOP_string_indexof is Label.LAST_WORD */
1239 Operand *labelLastWord = &insn.GetOperand(15);
1240 /* b.ge .Label.LAST_WORD */
1241 (void)emitter.Emit("\tb.ge\t");
1242 labelLastWord->Accept(visitor);
1243 (void)emitter.Emit("\n");
1244 /* the 14th operand of MOP_string_indexof is Label.STR1_NEXT */
1245 Operand *labelStr1Next = &insn.GetOperand(14);
1246 /* .Label.STR1_NEXT: */
1247 labelStr1Next->Accept(visitor);
1248 (void)emitter.Emit(":\n");
1249 /* the 6th operand of MOP_string_indexof is x6 */
1250 Operand *ch1 = &insn.GetOperand(6);
1251 /* ldr x6, [x3,x8] */
1252 (void)emitter.Emit("\tldr\t");
1253 ch1->Accept(visitor);
1254 (void)emitter.Emit(", [");
1255 patternStringBaseOpnd->Accept(visitor);
1256 (void)emitter.Emit(",");
1257 tmp1->Accept(visitor);
1258 (void)emitter.Emit("]\n");
1259 /* ldr x7, [x1,x9] */
1260 (void)emitter.Emit("\tldr\t");
1261 ch2->Accept(visitor);
1262 (void)emitter.Emit(", [");
1263 srcStringBaseOpnd->Accept(visitor);
1264 (void)emitter.Emit(",");
1265 tmp2->Accept(visitor);
1266 (void)emitter.Emit("]\n");
1267 /* cmp x6, x7 */
1268 (void)emitter.Emit("\tcmp\t");
1269 ch1->Accept(visitor);
1270 (void)emitter.Emit(", ");
1271 ch2->Accept(visitor);
1272 (void)emitter.Emit("\n");
1273 /* b.ne .Label.STR2_NEXT */
1274 (void)emitter.Emit("\tb.ne\t");
1275 labelStr2Next->Accept(visitor);
1276 (void)emitter.Emit("\n");
1277 /* adds x8, x8, #8 */
1278 (void)emitter.Emit("\tadds\t");
1279 tmp1->Accept(visitor);
1280 (void)emitter.Emit(", ");
1281 tmp1->Accept(visitor);
1282 (void)emitter.Emit(", #8\n");
1283 /* add x9, x9, #8 */
1284 (void)emitter.Emit("\tadd\t");
1285 tmp2->Accept(visitor);
1286 (void)emitter.Emit(", ");
1287 tmp2->Accept(visitor);
1288 (void)emitter.Emit(", #8\n");
1289 /* b.lt .Label.STR1_NEXT */
1290 (void)emitter.Emit("\tb.lt\t");
1291 labelStr1Next->Accept(visitor);
1292 (void)emitter.Emit("\n");
1293 /* .Label.LAST_WORD: */
1294 labelLastWord->Accept(visitor);
1295 (void)emitter.Emit(":\n");
1296 /* ldr x6, [x3] */
1297 (void)emitter.Emit("\tldr\t");
1298 ch1->Accept(visitor);
1299 (void)emitter.Emit(", [");
1300 patternStringBaseOpnd->Accept(visitor);
1301 (void)emitter.Emit("]\n");
1302 /* sub x9, x1, x4 */
1303 (void)emitter.Emit("\tsub\t");
1304 tmp2->Accept(visitor);
1305 (void)emitter.Emit(", ");
1306 srcStringBaseOpnd->Accept(visitor);
1307 (void)emitter.Emit(", ").Emit(patternLengthReg);
1308 (void)emitter.Emit("\n");
1309 /* ldr x7, [x9,x2] */
1310 (void)emitter.Emit("\tldr\t");
1311 ch2->Accept(visitor);
1312 (void)emitter.Emit(", [");
1313 tmp2->Accept(visitor);
1314 (void)emitter.Emit(", ").Emit(srcLengthReg);
1315 (void)emitter.Emit("]\n");
1316 /* cmp x6, x7 */
1317 (void)emitter.Emit("\tcmp\t");
1318 ch1->Accept(visitor);
1319 (void)emitter.Emit(", ");
1320 ch2->Accept(visitor);
1321 (void)emitter.Emit("\n");
1322 /* b.ne .Label.STR2_NEXT */
1323 (void)emitter.Emit("\tb.ne\t");
1324 labelStr2Next->Accept(visitor);
1325 (void)emitter.Emit("\n");
1326 Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1327 /* add w0, w10, w2 */
1328 (void)emitter.Emit("\tadd\t");
1329 retVal->Accept(visitor);
1330 (void)emitter.Emit(", ");
1331 resultTmp->Accept(visitor);
1332 (void)emitter.Emit(", ");
1333 srcLengthOpnd->Accept(visitor);
1334 (void)emitter.Emit("\n");
1335 /* the 17th operand of MOP_string_indexof Label.ret */
1336 Operand *labelRet = &insn.GetOperand(17);
1337 /* b .Label.ret */
1338 (void)emitter.Emit("\tb\t");
1339 labelRet->Accept(visitor);
1340 (void)emitter.Emit("\n");
1341 /* .Label.NOMATCH: */
1342 labelNoMatch->Accept(visitor);
1343 (void)emitter.Emit(":\n");
1344 /* mov w0, #-1 */
1345 (void)emitter.Emit("\tmov\t");
1346 retVal->Accept(visitor);
1347 (void)emitter.Emit(", #-1\n");
1348 /* .Label.ret: */
1349 labelRet->Accept(visitor);
1350 (void)emitter.Emit(":\n");
1351 #endif
1352 }
1353
1354 /*
1355 * intrinsic_compare_swap_int x0, xt, xs, x1, x2, w3, w4, lable1, label2
1356 * add xt, x1, x2
1357 * label1:
1358 * ldaxr ws, [xt]
1359 * cmp ws, w3
1360 * b.ne label2
1361 * stlxr ws, w4, [xt]
1362 * cbnz ws, label1
1363 * label2:
1364 * cset x0, eq
1365 */
EmitCompareAndSwapInt(Emitter & emitter,const Insn & insn) const1366 void AArch64AsmEmitter::EmitCompareAndSwapInt(Emitter &emitter, const Insn &insn) const
1367 {
1368 #ifdef ARK_LITECG_DEBUG
1369 /* MOP_compare_and_swapI and MOP_compare_and_swapL have 8 operands */
1370 DEBUG_ASSERT(insn.GetOperandSize() > kInsnEighthOpnd, "ensure the operands number");
1371 const MOperator mOp = insn.GetMachineOpcode();
1372 const InsnDesc *md = &AArch64CG::kMd[mOp];
1373 Operand *temp0 = &insn.GetOperand(kInsnSecondOpnd);
1374 Operand *temp1 = &insn.GetOperand(kInsnThirdOpnd);
1375 Operand *obj = &insn.GetOperand(kInsnFourthOpnd);
1376 Operand *offset = &insn.GetOperand(kInsnFifthOpnd);
1377 A64OpndEmitVisitor visitor(emitter, nullptr);
1378 /* add xt, x1, x2 */
1379 (void)emitter.Emit("\tadd\t");
1380 temp0->Accept(visitor);
1381 (void)emitter.Emit(", ");
1382 obj->Accept(visitor);
1383 (void)emitter.Emit(", ");
1384 offset->Accept(visitor);
1385 (void)emitter.Emit("\n");
1386 Operand *label1 = &insn.GetOperand(kInsnEighthOpnd);
1387 /* label1: */
1388 label1->Accept(visitor);
1389 (void)emitter.Emit(":\n");
1390 /* ldaxr ws, [xt] */
1391 (void)emitter.Emit("\tldaxr\t");
1392 temp1->Accept(visitor);
1393 (void)emitter.Emit(", [");
1394 temp0->Accept(visitor);
1395 (void)emitter.Emit("]\n");
1396 Operand *expectedValue = &insn.GetOperand(kInsnSixthOpnd);
1397 const OpndDesc *expectedValueProp = md->opndMD[kInsnSixthOpnd];
1398 /* cmp ws, w3 */
1399 (void)emitter.Emit("\tcmp\t");
1400 temp1->Accept(visitor);
1401 (void)emitter.Emit(", ");
1402 A64OpndEmitVisitor visitorExpect(emitter, expectedValueProp);
1403 expectedValue->Accept(visitorExpect);
1404 (void)emitter.Emit("\n");
1405 constexpr uint32 kInsnNinethOpnd = 8;
1406 Operand *label2 = &insn.GetOperand(kInsnNinethOpnd);
1407 /* b.ne label2 */
1408 (void)emitter.Emit("\tbne\t");
1409 label2->Accept(visitor);
1410 (void)emitter.Emit("\n");
1411 Operand *newValue = &insn.GetOperand(kInsnSeventhOpnd);
1412 /* stlxr ws, w4, [xt] */
1413 (void)emitter.Emit("\tstlxr\t");
1414 (void)emitter.Emit(
1415 AArch64CG::intRegNames[AArch64CG::kR32List][static_cast<RegOperand *>(temp1)->GetRegisterNumber()]);
1416 (void)emitter.Emit(", ");
1417 newValue->Accept(visitor);
1418 (void)emitter.Emit(", [");
1419 temp0->Accept(visitor);
1420 (void)emitter.Emit("]\n");
1421 /* cbnz ws, label1 */
1422 (void)emitter.Emit("\tcbnz\t");
1423 (void)emitter.Emit(
1424 AArch64CG::intRegNames[AArch64CG::kR32List][static_cast<RegOperand *>(temp1)->GetRegisterNumber()]);
1425 (void)emitter.Emit(", ");
1426 label1->Accept(visitor);
1427 (void)emitter.Emit("\n");
1428 /* label2: */
1429 label2->Accept(visitor);
1430 (void)emitter.Emit(":\n");
1431 Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1432 /* cset x0, eq */
1433 (void)emitter.Emit("\tcset\t");
1434 retVal->Accept(visitor);
1435 (void)emitter.Emit(", EQ\n");
1436 #endif
1437 }
1438
EmitCTlsDescRel(Emitter & emitter,const Insn & insn) const1439 void AArch64AsmEmitter::EmitCTlsDescRel(Emitter &emitter, const Insn &insn) const
1440 {
1441 #ifdef ARK_LITECG_DEBUG
1442 const InsnDesc *md = &AArch64CG::kMd[MOP_tls_desc_rel];
1443 Operand *result = &insn.GetOperand(kInsnFirstOpnd);
1444 Operand *src = &insn.GetOperand(kInsnSecondOpnd);
1445 Operand *symbol = &insn.GetOperand(kInsnThirdOpnd);
1446 auto stImmOpnd = static_cast<StImmOperand *>(symbol);
1447 A64OpndEmitVisitor resultVisitor(emitter, md->opndMD[0]);
1448 A64OpndEmitVisitor srcVisitor(emitter, md->opndMD[1]);
1449 (void)emitter.Emit("\t").Emit("add").Emit("\t");
1450 result->Accept(resultVisitor);
1451 (void)emitter.Emit(", ");
1452 src->Accept(srcVisitor);
1453 (void)emitter.Emit(", #:tprel_hi12:").Emit(stImmOpnd->GetName()).Emit(", lsl #12\n");
1454 (void)emitter.Emit("\t").Emit("add").Emit("\t");
1455 result->Accept(resultVisitor);
1456 (void)emitter.Emit(", ");
1457 result->Accept(resultVisitor);
1458 (void)emitter.Emit(", #:tprel_lo12_nc:").Emit(stImmOpnd->GetName()).Emit("\n");
1459 #endif
1460 }
1461
EmitCTlsDescCall(Emitter & emitter,const Insn & insn) const1462 void AArch64AsmEmitter::EmitCTlsDescCall(Emitter &emitter, const Insn &insn) const
1463 {
1464 #ifdef ARK_LITECG_DEBUG
1465 const InsnDesc *md = &AArch64CG::kMd[MOP_tls_desc_call];
1466 Operand *func = &insn.GetOperand(kInsnFirstOpnd);
1467 Operand *symbol = &insn.GetOperand(kInsnThirdOpnd);
1468 const OpndDesc *prop = md->opndMD[0];
1469 auto *stImmOpnd = static_cast<StImmOperand *>(symbol);
1470 const std::string &symName = stImmOpnd->GetName();
1471 A64OpndEmitVisitor funcVisitor(emitter, prop);
1472 /* adrp x0, :tlsdesc:symbol */
1473 (void)emitter.Emit("\t").Emit("adrp\tx0, :tlsdesc:").Emit(symName).Emit("\n");
1474 /* ldr x1, [x0, #tlsdesc_lo12:symbol] */
1475 (void)emitter.Emit("\t").Emit("ldr").Emit("\t");
1476 func->Accept(funcVisitor);
1477 (void)emitter.Emit(", [x0, #:tlsdesc_lo12:").Emit(symName).Emit("]\n");
1478 /* add x0 ,#tlsdesc_lo12:symbol */
1479 (void)emitter.Emit("\t").Emit("add\tx0, x0, :tlsdesc_lo12:").Emit(symName).Emit("\n");
1480 /* .tlsdesccall <symbolName> */
1481 (void)emitter.Emit("\t").Emit(".tlsdesccall").Emit("\t").Emit(symName).Emit("\n");
1482 /* blr xd */
1483 (void)emitter.Emit("\t").Emit("blr").Emit("\t");
1484 func->Accept(funcVisitor);
1485 (void)emitter.Emit("\n");
1486 #endif
1487 }
1488
EmitSyncLockTestSet(Emitter & emitter,const Insn & insn) const1489 void AArch64AsmEmitter::EmitSyncLockTestSet(Emitter &emitter, const Insn &insn) const
1490 {
1491 #ifdef ARK_LITECG_DEBUG
1492 const InsnDesc *md = &AArch64CG::kMd[insn.GetMachineOpcode()];
1493 auto *result = &insn.GetOperand(kInsnFirstOpnd);
1494 auto *temp = &insn.GetOperand(kInsnSecondOpnd);
1495 auto *addr = &insn.GetOperand(kInsnThirdOpnd);
1496 auto *value = &insn.GetOperand(kInsnFourthOpnd);
1497 auto *label = &insn.GetOperand(kInsnFifthOpnd);
1498 A64OpndEmitVisitor resultVisitor(emitter, md->opndMD[kInsnFirstOpnd]);
1499 A64OpndEmitVisitor tempVisitor(emitter, md->opndMD[kInsnSecondOpnd]);
1500 A64OpndEmitVisitor addrVisitor(emitter, md->opndMD[kInsnThirdOpnd]);
1501 A64OpndEmitVisitor valueVisitor(emitter, md->opndMD[kInsnFourthOpnd]);
1502 A64OpndEmitVisitor labelVisitor(emitter, md->opndMD[kInsnFifthOpnd]);
1503 /* label: */
1504 label->Accept(labelVisitor);
1505 (void)emitter.Emit(":\n");
1506 /* ldxr x0, [x2] */
1507 (void)emitter.Emit("\t").Emit("ldxr").Emit("\t");
1508 result->Accept(resultVisitor);
1509 (void)emitter.Emit(", [");
1510 addr->Accept(addrVisitor);
1511 (void)emitter.Emit("]\n");
1512 /* stxr w1, x3, [x2] */
1513 (void)emitter.Emit("\t").Emit("stxr").Emit("\t");
1514 temp->Accept(tempVisitor);
1515 (void)emitter.Emit(", ");
1516 value->Accept(valueVisitor);
1517 (void)emitter.Emit(", [");
1518 addr->Accept(addrVisitor);
1519 (void)emitter.Emit("]\n");
1520 /* cbnz w1, label */
1521 (void)emitter.Emit("\t").Emit("cbnz").Emit("\t");
1522 temp->Accept(tempVisitor);
1523 (void)emitter.Emit(", ");
1524 label->Accept(labelVisitor);
1525 (void)emitter.Emit("\n");
1526 /* dmb ish */
1527 (void)emitter.Emit("\t").Emit("dmb").Emit("\t").Emit("ish").Emit("\n");
1528 #endif
1529 }
1530
EmitPureCall(Emitter & emitter,const Insn & insn) const1531 void AArch64AsmEmitter::EmitPureCall(Emitter &emitter, const Insn &insn) const
1532 {
1533 #ifdef ARK_LITECG_DEBUG
1534 const InsnDesc *md = &AArch64CG::kMd[insn.GetMachineOpcode()];
1535 auto *callee = &insn.GetOperand(kInsnFirstOpnd);
1536 A64OpndEmitVisitor calleeVisitor(emitter, md->opndMD[kInsnFirstOpnd]);
1537 (void)emitter.Emit("\t").Emit("blr").Emit("\t");
1538 callee->Accept(calleeVisitor);
1539 (void)emitter.Emit("\n");
1540 #endif
1541 }
1542
EmitCheckThrowPendingException(Emitter & emitter,Insn & insn) const1543 void AArch64AsmEmitter::EmitCheckThrowPendingException(Emitter &emitter, Insn &insn) const
1544 {
1545 #ifdef ARK_LITECG_DEBUG
1546 /*
1547 * mrs x16, TPIDR_EL0
1548 * ldr x16, [x16, #64]
1549 * ldr x16, [x16, #8]
1550 * cbz x16, .lnoexception
1551 * bl MCC_ThrowPendingException
1552 * .lnoexception:
1553 */
1554 (void)emitter.Emit("\t").Emit("mrs").Emit("\tx16, TPIDR_EL0");
1555 (void)emitter.Emit("\n");
1556 (void)emitter.Emit("\t").Emit("ldr").Emit("\tx16, [x16, #64]");
1557 (void)emitter.Emit("\n");
1558 (void)emitter.Emit("\t").Emit("ldr").Emit("\tx16, [x16, #8]");
1559 (void)emitter.Emit("\n");
1560 (void)emitter.Emit("\t").Emit("cbz").Emit("\tx16, .lnoeh.").Emit(maplebe::CG::GetCurCGFunc()->GetName());
1561 (void)emitter.Emit("\n");
1562 (void)emitter.Emit("\t").Emit("bl").Emit("\tMCC_ThrowPendingException");
1563 (void)emitter.Emit("\n");
1564 (void)emitter.Emit(".lnoeh.").Emit(maplebe::CG::GetCurCGFunc()->GetName()).Emit(":");
1565 (void)emitter.Emit("\n");
1566 #endif
1567 }
1568
EmitLazyBindingRoutine(Emitter & emitter,const Insn & insn) const1569 void AArch64AsmEmitter::EmitLazyBindingRoutine(Emitter &emitter, const Insn &insn) const
1570 {
1571 #ifdef ARK_LITECG_DEBUG
1572 /* ldr xzr, [xs] */
1573 const InsnDesc *md = &AArch64CG::kMd[MOP_adrp_ldr];
1574
1575 Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
1576 const OpndDesc *prop0 = md->opndMD[0];
1577 A64OpndEmitVisitor visitor(emitter, prop0);
1578
1579 /* emit "ldr xzr,[xs]" */
1580 #ifdef USE_32BIT_REF
1581 (void)emitter.Emit("\t").Emit("ldr").Emit("\twzr, [");
1582 #else
1583 (void)emitter.Emit("\t").Emit("ldr").Emit("\txzr, [");
1584 #endif /* USE_32BIT_REF */
1585 opnd0->Accept(visitor);
1586 (void)emitter.Emit("]");
1587 (void)emitter.Emit("\t// Lazy binding\n");
1588 #endif
1589 }
1590
1591 #ifdef ARK_LITECG_DEBUG
1592 struct CfiDescr {
1593 const std::string name;
1594 uint32 opndCount;
1595 /* create 3 OperandType array to store cfi instruction's operand type */
1596 std::array<Operand::OperandType, 3> opndTypes;
1597 };
1598
1599 static CfiDescr cfiDescrTable[cfi::kOpCfiLast + 1] = {
1600 #define CFI_DEFINE(k, sub, n, o0, o1, o2) {".cfi_" #k, n, {Operand::kOpd##o0, Operand::kOpd##o1, Operand::kOpd##o2}},
1601 #define ARM_DIRECTIVES_DEFINE(k, sub, n, o0, o1, o2) \
1602 {"." #k, n, {Operand::kOpd##o0, Operand::kOpd##o1, Operand::kOpd##o2}},
1603 #include "cfi.def"
1604 #undef CFI_DEFINE
1605 #undef ARM_DIRECTIVES_DEFINE
1606 {".cfi_undef", 0, {Operand::kOpdUndef, Operand::kOpdUndef, Operand::kOpdUndef}}};
1607 #endif
1608
EmitAArch64CfiInsn(Emitter & emitter,const Insn & insn) const1609 void AArch64AsmEmitter::EmitAArch64CfiInsn(Emitter &emitter, const Insn &insn) const
1610 {
1611 #ifdef ARK_LITECG_DEBUG
1612 MOperator mOp = insn.GetMachineOpcode();
1613 CHECK_FATAL(mOp <= cfi::kOpCfiLast, "check overflow");
1614 CfiDescr &cfiDescr = cfiDescrTable[mOp];
1615 (void)emitter.Emit("\t").Emit(cfiDescr.name);
1616 for (uint32 i = 0; i < cfiDescr.opndCount; ++i) {
1617 (void)emitter.Emit(" ");
1618 Operand &curOperand = insn.GetOperand(i);
1619 cfi::CFIOpndEmitVisitor cfiOpndEmitVisitor(emitter);
1620 curOperand.Accept(cfiOpndEmitVisitor);
1621 if (i < (cfiDescr.opndCount - 1)) {
1622 (void)emitter.Emit(",");
1623 }
1624 }
1625 (void)emitter.Emit("\n");
1626 #endif
1627 }
1628
CheckInsnRefField(const Insn & insn,size_t opndIndex) const1629 bool AArch64AsmEmitter::CheckInsnRefField(const Insn &insn, size_t opndIndex) const
1630 {
1631 #ifdef ARK_LITECG_DEBUG
1632 if (insn.IsAccessRefField() && insn.AccessMem()) {
1633 Operand &opnd0 = insn.GetOperand(opndIndex);
1634 if (opnd0.IsRegister()) {
1635 static_cast<RegOperand &>(opnd0).SetRefField(true);
1636 return true;
1637 }
1638 }
1639 #endif
1640 return false;
1641 }
1642 } /* namespace maplebe */
1643