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_get_heap_const_table: {
353 EmitGetHeapConstTable(emitter, insn);
354 return;
355 }
356 case MOP_heap_const: {
357 EmitHeapConstant(emitter, insn);
358 return;
359 }
360 case MOP_lazy_tail: {
361 /* No need to emit this pseudo instruction. */
362 return;
363 }
364 case MOP_lazy_ldr_static: {
365 EmitLazyLoadStatic(emitter, insn);
366 return;
367 }
368 case MOP_arrayclass_cache_ldr: {
369 EmitArrayClassCacheLoad(emitter, insn);
370 return;
371 }
372 case MOP_get_and_addI:
373 case MOP_get_and_addL: {
374 EmitGetAndAddInt(emitter, insn);
375 return;
376 }
377 case MOP_get_and_setI:
378 case MOP_get_and_setL: {
379 EmitGetAndSetInt(emitter, insn);
380 return;
381 }
382 case MOP_compare_and_swapI:
383 case MOP_compare_and_swapL: {
384 EmitCompareAndSwapInt(emitter, insn);
385 return;
386 }
387 case MOP_string_indexof: {
388 EmitStringIndexOf(emitter, insn);
389 return;
390 }
391 case MOP_pseudo_none:
392 case MOP_pseduo_tls_release: {
393 return;
394 }
395 case MOP_tls_desc_call: {
396 EmitCTlsDescCall(emitter, insn);
397 return;
398 }
399 case MOP_tls_desc_rel: {
400 EmitCTlsDescRel(emitter, insn);
401 return;
402 }
403 case MOP_sync_lock_test_setI:
404 case MOP_sync_lock_test_setL: {
405 EmitSyncLockTestSet(emitter, insn);
406 return;
407 }
408 case MOP_pure_call: {
409 EmitPureCall(emitter, insn);
410 return;
411 }
412 default:
413 break;
414 }
415
416 std::string format(md->format);
417 (void)emitter.Emit("\t").Emit(md->name).Emit("\t");
418 size_t opndSize = insn.GetOperandSize();
419 std::vector<int32> seq(opndSize, -1);
420 std::vector<std::string> prefix(opndSize); /* used for print prefix like "*" in icall *rax */
421 uint32 index = 0;
422 uint32 commaNum = 0;
423 for (uint32 i = 0; i < format.length(); ++i) {
424 char c = format[i];
425 if (c >= '0' && c <= '5') {
426 seq[index++] = c - '0';
427 ++commaNum;
428 } else if (c != ',') {
429 prefix[index].push_back(c);
430 }
431 }
432
433 bool isRefField =
434 (opndSize == 0) ? false : CheckInsnRefField(insn, static_cast<size_t>(static_cast<uint32>(seq[0])));
435 uint32 compositeOpnds = 0;
436 for (uint32 i = 0; i < commaNum; ++i) {
437 if (seq[i] == -1) {
438 continue;
439 }
440 if (prefix[i].length() > 0) {
441 (void)emitter.Emit(prefix[i]);
442 }
443 if (emitter.NeedToDealWithHugeSo() && (mOp == MOP_xbl || mOp == MOP_tail_call_opt_xbl)) {
444 auto *nameOpnd = static_cast<FuncNameOperand *>(&insn.GetOperand(kInsnFirstOpnd));
445 emitter.InsertHugeSoTarget(nameOpnd->GetName());
446 (void)emitter.Emit(nameOpnd->GetName() + emitter.HugeSoPostFix());
447 break;
448 }
449 A64OpndEmitVisitor visitor(emitter, md->opndMD[static_cast<uint32>(seq[i])]);
450
451 insn.GetOperand(static_cast<uint32>(seq[i])).Accept(visitor);
452 if (compositeOpnds == 1) {
453 (void)emitter.Emit("}");
454 }
455 if (compositeOpnds > 0) {
456 --compositeOpnds;
457 }
458 /* reset opnd0 ref-field flag, so following instruction has correct register */
459 if (isRefField && (i == 0)) {
460 static_cast<RegOperand *>(&insn.GetOperand(static_cast<uint32>(seq[0])))->SetRefField(false);
461 }
462 /* Temporary comment the label:.Label.debug.callee */
463 if (i != (commaNum - 1)) {
464 (void)emitter.Emit(", ");
465 }
466 const uint32 commaNumForEmitLazy = 2;
467 if (!CGOptions::IsLazyBinding() || GetCG()->IsLibcore() || (mOp != MOP_wldr && mOp != MOP_xldr) ||
468 commaNum != commaNumForEmitLazy || i != 1 ||
469 !insn.GetOperand(static_cast<uint32>(seq[1])).IsMemoryAccessOperand()) {
470 continue;
471 }
472 /*
473 * Only check the last operand of ldr in lo12 mode.
474 * Check the second operand, if it's [AArch64MemOperand::kAddrModeLo12Li]
475 */
476 auto *memOpnd = static_cast<MemOperand *>(&insn.GetOperand(static_cast<uint32>(seq[1])));
477 if (memOpnd == nullptr || memOpnd->GetAddrMode() != MemOperand::kAddrModeLo12Li) {
478 continue;
479 }
480 const MIRSymbol *sym = memOpnd->GetSymbol();
481 if (sym->IsMuidFuncDefTab() || sym->IsMuidFuncUndefTab() || sym->IsMuidDataDefTab() ||
482 sym->IsMuidDataUndefTab()) {
483 (void)emitter.Emit("\n");
484 EmitLazyBindingRoutine(emitter, insn);
485 }
486 }
487 if (GetCG()->GenerateVerboseCG() || (GetCG()->GenerateVerboseAsm() && insn.IsComment())) {
488 const char *comment = insn.GetComment().c_str();
489 if (comment != nullptr && strlen(comment) > 0) {
490 (void)emitter.Emit("\t\t// ").Emit(comment);
491 }
492 }
493
494 (void)emitter.Emit("\n");
495 #endif
496 }
497
498 #ifdef ARK_LITECG_DEBUG
AsmStringOutputRegNum(bool isInt,uint32 regno,uint32 intBase,uint32 fpBase,std::string & strToEmit)499 static void AsmStringOutputRegNum(bool isInt, uint32 regno, uint32 intBase, uint32 fpBase, std::string &strToEmit)
500 {
501 regno_t newRegno;
502 if (isInt) {
503 CHECK_FATAL(regno >= intBase, "value overflow");
504 newRegno = regno - intBase;
505 } else {
506 newRegno = regno - fpBase;
507 }
508 if (newRegno > (kDecimalMax - 1)) {
509 uint32 tenth = newRegno / kDecimalMax;
510 strToEmit += '0' + static_cast<char>(tenth);
511 newRegno -= (kDecimalMax * tenth);
512 }
513 strToEmit += newRegno + '0';
514 }
515 #endif
516
EmitInlineAsm(Emitter & emitter,const Insn & insn) const517 void AArch64AsmEmitter::EmitInlineAsm(Emitter &emitter, const Insn &insn) const
518 {
519 #ifdef ARK_LITECG_DEBUG
520 (void)emitter.Emit("\t//Inline asm begin\n\t");
521 auto &list1 = static_cast<ListOperand &>(insn.GetOperand(kAsmOutputListOpnd));
522 std::vector<RegOperand *> outOpnds;
523 for (auto *regOpnd : list1.GetOperands()) {
524 outOpnds.push_back(regOpnd);
525 }
526 auto &list2 = static_cast<ListOperand &>(insn.GetOperand(kAsmInputListOpnd));
527 std::vector<RegOperand *> inOpnds;
528 for (auto *regOpnd : list2.GetOperands()) {
529 inOpnds.push_back(regOpnd);
530 }
531 auto &list6 = static_cast<ListConstraintOperand &>(insn.GetOperand(kAsmOutputRegPrefixOpnd));
532 auto &list7 = static_cast<ListConstraintOperand &>(insn.GetOperand(kAsmInputRegPrefixOpnd));
533 MapleString asmStr = static_cast<StringOperand &>(insn.GetOperand(kAsmStringOpnd)).GetComment();
534 std::string stringToEmit;
535 auto IsMemAccess = [](char c) -> bool { return c == '['; };
536 auto EmitRegister = [&](const char *p, bool isInt, uint32 regNO, bool unDefRegSize) -> void {
537 if (IsMemAccess(p[0])) {
538 stringToEmit += "[x";
539 AsmStringOutputRegNum(isInt, regNO, R0, V0, stringToEmit);
540 stringToEmit += "]";
541 } else {
542 DEBUG_ASSERT((p[0] == 'w' || p[0] == 'x' || p[0] == 's' || p[0] == 'd' || p[0] == 'v'),
543 "Asm invalid register type");
544 if ((p[0] == 'w' || p[0] == 'x') && unDefRegSize) {
545 stringToEmit += 'x';
546 } else {
547 stringToEmit += p[0];
548 }
549 if (!unDefRegSize) {
550 isInt = (p[0] == 'w' || p[0] == 'x');
551 }
552 AsmStringOutputRegNum(isInt, regNO, R0, V0, stringToEmit);
553 }
554 };
555 for (size_t i = 0; i < asmStr.length(); ++i) {
556 switch (asmStr[i]) {
557 case '$': {
558 char c = asmStr[++i];
559 if ((c >= '0') && (c <= '9')) {
560 auto val = static_cast<uint32>(c - '0');
561 if (asmStr[i + 1] >= '0' && asmStr[i + 1] <= '9') {
562 val = val * kDecimalMax + static_cast<uint32>(asmStr[++i] - '0');
563 }
564 if (val < outOpnds.size()) {
565 const char *prefix = list6.stringList[val]->GetComment().c_str();
566 RegOperand *opnd = outOpnds[val];
567 EmitRegister(prefix, opnd->IsOfIntClass(), opnd->GetRegisterNumber(), true);
568 } else {
569 val -= static_cast<uint32>(outOpnds.size());
570 CHECK_FATAL(val < inOpnds.size(), "Inline asm : invalid register constraint number");
571 RegOperand *opnd = inOpnds[val];
572 /* input is a immediate */
573 const char *prefix = list7.stringList[val]->GetComment().c_str();
574 if (prefix[0] == 'i') {
575 stringToEmit += '#';
576 for (size_t k = 1; k < list7.stringList[val]->GetComment().length(); ++k) {
577 stringToEmit += prefix[k];
578 }
579 } else {
580 EmitRegister(prefix, opnd->IsOfIntClass(), opnd->GetRegisterNumber(), true);
581 }
582 }
583 } else if (c == '{') {
584 c = asmStr[++i];
585 CHECK_FATAL(((c >= '0') && (c <= '9')), "Inline asm : invalid register constraint number");
586 auto val = static_cast<uint32>(c - '0');
587 if (asmStr[i + 1] >= '0' && asmStr[i + 1] <= '9') {
588 val = val * kDecimalMax + static_cast<uint32>(asmStr[++i] - '0');
589 }
590 regno_t regno;
591 bool isAddr = false;
592 if (val < outOpnds.size()) {
593 RegOperand *opnd = outOpnds[val];
594 regno = opnd->GetRegisterNumber();
595 isAddr = IsMemAccess(list6.stringList[val]->GetComment().c_str()[0]);
596 } else {
597 val -= static_cast<uint32>(outOpnds.size());
598 CHECK_FATAL(val < inOpnds.size(), "Inline asm : invalid register constraint number");
599 RegOperand *opnd = inOpnds[val];
600 regno = opnd->GetRegisterNumber();
601 DEBUG_ASSERT(list7.stringList[val]->GetComment().c_str() != nullptr,
602 "list7 GetComment.c_str should not be nullptr");
603 isAddr = IsMemAccess(list7.stringList[val]->GetComment().c_str()[0]);
604 }
605 c = asmStr[++i];
606 CHECK_FATAL(c == ':', "Parsing error in inline asm string during emit");
607 c = asmStr[++i];
608 std::string prefix(1, c);
609 if (c == 'a' || isAddr) {
610 prefix = "[x";
611 }
612 EmitRegister(prefix.c_str(), true, regno, false);
613 c = asmStr[++i];
614 CHECK_FATAL(c == '}', "Parsing error in inline asm string during emit");
615 }
616 break;
617 }
618 case '\n': {
619 stringToEmit += "\n\t";
620 break;
621 }
622 default:
623 stringToEmit += asmStr[i];
624 }
625 }
626 (void)emitter.Emit(stringToEmit);
627 (void)emitter.Emit("\n\t//Inline asm end\n");
628 #endif
629 }
630
EmitClinitTail(Emitter & emitter,const Insn & insn) const631 void AArch64AsmEmitter::EmitClinitTail(Emitter &emitter, const Insn &insn) const
632 {
633 #ifdef ARK_LITECG_DEBUG
634 /*
635 * ldr x17, [xs, #112]
636 * ldr wzr, [x17]
637 */
638 const InsnDesc *md = &AArch64CG::kMd[MOP_clinit_tail];
639
640 Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
641
642 const OpndDesc *prop0 = md->opndMD[0];
643 A64OpndEmitVisitor visitor(emitter, prop0);
644
645 /* emit "ldr x17,[xs,#112]" */
646 (void)emitter.Emit("\t").Emit("ldr").Emit("\tx17, [");
647 opnd0->Accept(visitor);
648 (void)emitter.Emit(", #");
649 (void)emitter.Emit(static_cast<uint32>(ClassMetadata::OffsetOfInitState()));
650 (void)emitter.Emit("]");
651 (void)emitter.Emit("\n");
652
653 /* emit "ldr xzr, [x17]" */
654 (void)emitter.Emit("\t").Emit("ldr\txzr, [x17]\n");
655 #endif
656 }
657
EmitLazyLoad(Emitter & emitter,const Insn & insn) const658 void AArch64AsmEmitter::EmitLazyLoad(Emitter &emitter, const Insn &insn) const
659 {
660 #ifdef ARK_LITECG_DEBUG
661 /*
662 * ldr wd, [xs] # xd and xs should be differenct register
663 * ldr wd, [xd]
664 */
665 const InsnDesc *md = &AArch64CG::kMd[MOP_lazy_ldr];
666
667 Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
668 Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
669 const OpndDesc *prop0 = md->opndMD[0];
670 const OpndDesc *prop1 = md->opndMD[1];
671 A64OpndEmitVisitor visitor(emitter, prop0);
672 A64OpndEmitVisitor visitor1(emitter, prop1);
673
674 /* emit "ldr wd, [xs]" */
675 (void)emitter.Emit("\t").Emit("ldr\t");
676 #ifdef USE_32BIT_REF
677 opnd0->Accept(visitor);
678 #else
679 opnd0->Accept(visitor1);
680 #endif
681 (void)emitter.Emit(", [");
682 opnd1->Accept(visitor1);
683 (void)emitter.Emit("]\t// lazy load.\n");
684
685 /* emit "ldr wd, [xd]" */
686 (void)emitter.Emit("\t").Emit("ldr\t");
687 opnd0->Accept(visitor);
688 (void)emitter.Emit(", [");
689 opnd1->Accept(visitor1);
690 (void)emitter.Emit("]\t// lazy load.\n");
691 #endif
692 }
693
EmitCounter(Emitter & emitter,const Insn & insn) const694 void AArch64AsmEmitter::EmitCounter(Emitter &emitter, const Insn &insn) const
695 {
696 #ifdef ARK_LITECG_DEBUG
697 /*
698 * adrp x1, __profile_bb_table$$GetBoolean_bytecode+4
699 * ldr w17, [x1, #:lo12:__profile_bb_table$$GetBoolean_bytecode+4]
700 * add w17, w17, #1
701 * str w17, [x1, #:lo12:__profile_bb_table$$GetBoolean_bytecode+4]
702 */
703 const InsnDesc *md = &AArch64CG::kMd[MOP_counter];
704
705 Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
706 Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
707 const OpndDesc *prop0 = md->opndMD[kInsnFirstOpnd];
708 A64OpndEmitVisitor visitor(emitter, prop0);
709 StImmOperand *stImmOpnd = static_cast<StImmOperand *>(opnd1);
710 CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitCounter");
711 /* emit adrp */
712 (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
713 opnd0->Accept(visitor);
714 (void)emitter.Emit(",");
715 (void)emitter.Emit(stImmOpnd->GetName());
716 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
717 (void)emitter.Emit("\n");
718 /* emit ldr */
719 (void)emitter.Emit("\t").Emit("ldr").Emit("\tw17, [");
720 opnd0->Accept(visitor);
721 (void)emitter.Emit(",");
722 (void)emitter.Emit("#");
723 (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
724 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
725 (void)emitter.Emit("]");
726 (void)emitter.Emit("\n");
727 /* emit add */
728 (void)emitter.Emit("\t").Emit("add").Emit("\tw17, w17, #1");
729 (void)emitter.Emit("\n");
730 /* emit str */
731 (void)emitter.Emit("\t").Emit("str").Emit("\tw17, [");
732 opnd0->Accept(visitor);
733 (void)emitter.Emit(",");
734 (void)emitter.Emit("#");
735 (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
736 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
737 (void)emitter.Emit("]");
738 (void)emitter.Emit("\n");
739 #endif
740 }
741
EmitAdrpLabel(Emitter & emitter,const Insn & insn) const742 void AArch64AsmEmitter::EmitAdrpLabel(Emitter &emitter, const Insn &insn) const
743 {
744 #ifdef ARK_LITECG_DEBUG
745 /* adrp xd, label
746 * add xd, xd, #lo12:label
747 */
748 const InsnDesc *md = &AArch64CG::kMd[MOP_adrp_label];
749
750 Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
751 Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
752 const OpndDesc *prop0 = md->opndMD[0];
753 A64OpndEmitVisitor visitor(emitter, prop0);
754 auto lidx = static_cast<ImmOperand *>(opnd1)->GetValue();
755
756 /* adrp xd, label */
757 (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
758 opnd0->Accept(visitor);
759 (void)emitter.Emit(", ");
760 CHECK_NULL_FATAL(Globals::GetInstance()->GetBECommon()->GetMIRModule().CurFunction());
761 char *idx = strdup(std::to_string(
762 Globals::GetInstance()->GetBECommon()->GetMIRModule().CurFunction()->GetPuidx()).c_str());
763 CHECK_FATAL(idx != nullptr, "strdup failed");
764 (void)emitter.Emit(".L.").Emit(idx).Emit("__").Emit(lidx).Emit("\n");
765
766 /* add xd, xd, #lo12:label */
767 (void)emitter.Emit("\tadd\t");
768 opnd0->Accept(visitor);
769 (void)emitter.Emit(", ");
770 opnd0->Accept(visitor);
771 (void)emitter.Emit(", ");
772 (void)emitter.Emit(":lo12:").Emit(".L.").Emit(idx).Emit("__").Emit(lidx).Emit("\n");
773 (void)emitter.Emit("\n");
774 free(idx);
775 idx = nullptr;
776 #endif
777 }
778
EmitHeapConstant(Emitter & emitter,const Insn & insn) const779 void AArch64AsmEmitter::EmitHeapConstant(Emitter &emitter, const Insn &insn) const
780 {
781 #ifdef ARK_LITECG_DEBUG
782 /* ldr reg1, [reg0, offset]
783 */
784 const InsnDesc *md = &AArch64CG::kMd[MOP_heap_const];
785
786 Operand &opnd0 = insn.GetOperand(kInsnFirstOpnd);
787 Operand &opnd1 = insn.GetOperand(kInsnSecondOpnd);
788 Operand &opnd2 = insn.GetOperand(kInsnThirdOpnd);
789 const OpndDesc *prop0 = md->opndMD[0];
790 A64OpndEmitVisitor visitor(emitter, prop0);
791 (void)emitter.Emit("\t").Emit("ldr").Emit("\t");
792 opnd0.Accept(visitor);
793 (void)emitter.Emit(", [");
794 opnd1.Accept(visitor);
795 (void)emitter.Emit(",#");
796 int64_t slotIndex = static_cast<ImmOperand&>(opnd2).GetValue();
797 (void)emitter.Emit(slotIndex * k8ByteSize).Emit("] // __heap_constant(");
798 opnd2.Accept(visitor);
799 (void)emitter.Emit(")\n");
800 #endif
801 }
802
EmitGetHeapConstTable(Emitter & emitter,const Insn & insn) const803 void AArch64AsmEmitter::EmitGetHeapConstTable(Emitter &emitter, const Insn &insn) const
804 {
805 #ifdef ARK_LITECG_DEBUG
806 /* ldr reg0, [reg1, offset1]
807 * ldr reg0, [reg0, offset2]
808 */
809 const InsnDesc *md = &AArch64CG::kMd[MOP_get_heap_const_table];
810
811 Operand &opnd0 = insn.GetOperand(kInsnFirstOpnd);
812 Operand &opnd1 = insn.GetOperand(kInsnSecondOpnd);
813 Operand &opnd2 = insn.GetOperand(kInsnThirdOpnd);
814 Operand &opnd3 = insn.GetOperand(kInsnFourthOpnd);
815 const OpndDesc *prop0 = md->opndMD[0];
816 A64OpndEmitVisitor visitor(emitter, prop0);
817 (void)emitter.Emit("\t").Emit("ldr").Emit("\t");
818 opnd0.Accept(visitor);
819 (void)emitter.Emit(", [");
820 opnd1.Accept(visitor);
821 (void)emitter.Emit(",");
822 opnd2.Accept(visitor);
823 (void)emitter.Emit("]\n");
824
825 (void)emitter.Emit("\t").Emit("ldr").Emit("\t");
826 opnd0.Accept(visitor);
827 (void)emitter.Emit(", [");
828 opnd0.Accept(visitor);
829 (void)emitter.Emit(",");
830 opnd3.Accept(visitor);
831 (void)emitter.Emit("] // __ get_heap_constant_table\n");
832 #endif
833 }
834
EmitAdrpLdr(Emitter & emitter,const Insn & insn) const835 void AArch64AsmEmitter::EmitAdrpLdr(Emitter &emitter, const Insn &insn) const
836 {
837 #ifdef ARK_LITECG_DEBUG
838 const InsnDesc *md = &AArch64CG::kMd[MOP_adrp_ldr];
839 Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
840 Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
841 const OpndDesc *prop0 = md->opndMD[0];
842 A64OpndEmitVisitor visitor(emitter, prop0);
843 auto *stImmOpnd = static_cast<StImmOperand *>(opnd1);
844 CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitAdrpLdr");
845
846 (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
847 opnd0->Accept(visitor);
848 (void)emitter.Emit(", ");
849 (void)emitter.Emit(stImmOpnd->GetName());
850 if (stImmOpnd->GetOffset() != 0) {
851 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
852 }
853 (void)emitter.Emit("\n");
854
855 (void)emitter.Emit("\tldr\t");
856 static_cast<RegOperand *>(opnd0)->SetRefField(true);
857 opnd0->Accept(visitor);
858 static_cast<RegOperand *>(opnd0)->SetRefField(false);
859 (void)emitter.Emit(", ");
860 (void)emitter.Emit("[");
861 opnd0->Accept(visitor);
862 (void)emitter.Emit(",");
863 (void)emitter.Emit("#");
864 (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
865 if (stImmOpnd->GetOffset() != 0) {
866 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
867 }
868 (void)emitter.Emit("]\n");
869 #endif
870 }
871
EmitLazyLoadStatic(Emitter & emitter,const Insn & insn) const872 void AArch64AsmEmitter::EmitLazyLoadStatic(Emitter &emitter, const Insn &insn) const
873 {
874 #ifdef ARK_LITECG_DEBUG
875 /* adrp xd, :got:__staticDecoupleValueOffset$$xxx+offset
876 * ldr wd, [xd, #:got_lo12:__staticDecoupleValueOffset$$xxx+offset]
877 * ldr wzr, [xd]
878 */
879 const InsnDesc *md = &AArch64CG::kMd[MOP_lazy_ldr_static];
880
881 Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
882 Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
883 const OpndDesc *prop0 = md->GetOpndDes(0);
884 A64OpndEmitVisitor visitor(emitter, prop0);
885 auto *stImmOpnd = static_cast<StImmOperand *>(opnd1);
886 CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitLazyLoadStatic");
887
888 /* emit "adrp xd, :got:__staticDecoupleValueOffset$$xxx+offset" */
889 (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
890 opnd0->Accept(visitor);
891 (void)emitter.Emit(", ");
892 (void)emitter.Emit(stImmOpnd->GetName());
893 if (stImmOpnd->GetOffset() != 0) {
894 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
895 }
896 (void)emitter.Emit("\t// lazy load static.\n");
897
898 /* emit "ldr wd, [xd, #:got_lo12:__staticDecoupleValueOffset$$xxx+offset]" */
899 (void)emitter.Emit("\tldr\t");
900 static_cast<RegOperand *>(opnd0)->SetRefField(true);
901 #ifdef USE_32BIT_REF
902 const OpndDesc prop2(prop0->GetOperandType(), prop0->GetRegProp(), prop0->GetSize() / 2);
903 opnd0->Emit(emitter, &prop2); /* ldr wd, ... for terminal system */
904 #else
905 opnd0->Accept(visitor); /* ldr xd, ... for qemu */
906 #endif /* USE_32BIT_REF */
907 static_cast<RegOperand *>(opnd0)->SetRefField(false);
908 (void)emitter.Emit(", ");
909 (void)emitter.Emit("[");
910 opnd0->Accept(visitor);
911 (void)emitter.Emit(",");
912 (void)emitter.Emit("#");
913 (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
914 if (stImmOpnd->GetOffset() != 0) {
915 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
916 }
917 (void)emitter.Emit("]\t// lazy load static.\n");
918
919 /* emit "ldr wzr, [xd]" */
920 (void)emitter.Emit("\t").Emit("ldr\twzr, [");
921 opnd0->Accept(visitor);
922 (void)emitter.Emit("]\t// lazy load static.\n");
923 #endif
924 }
925
EmitArrayClassCacheLoad(Emitter & emitter,const Insn & insn) const926 void AArch64AsmEmitter::EmitArrayClassCacheLoad(Emitter &emitter, const Insn &insn) const
927 {
928 #ifdef ARK_LITECG_DEBUG
929 /* adrp xd, :got:__arrayClassCacheTable$$xxx+offset
930 * ldr wd, [xd, #:got_lo12:__arrayClassCacheTable$$xxx+offset]
931 * ldr wzr, [xd]
932 */
933 const InsnDesc *md = &AArch64CG::kMd[MOP_arrayclass_cache_ldr];
934 Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
935 Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
936 const OpndDesc *prop0 = md->GetOpndDes(kInsnFirstOpnd);
937 A64OpndEmitVisitor visitor(emitter, prop0);
938 auto *stImmOpnd = static_cast<StImmOperand *>(opnd1);
939 CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitLazyLoadStatic");
940
941 /* emit "adrp xd, :got:__arrayClassCacheTable$$xxx+offset" */
942 (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
943 opnd0->Accept(visitor);
944 (void)emitter.Emit(", ");
945 (void)emitter.Emit(stImmOpnd->GetName());
946 if (stImmOpnd->GetOffset() != 0) {
947 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
948 }
949 (void)emitter.Emit("\t// load array class.\n");
950
951 /* emit "ldr wd, [xd, #:got_lo12:__arrayClassCacheTable$$xxx+offset]" */
952 (void)emitter.Emit("\tldr\t");
953 static_cast<RegOperand *>(opnd0)->SetRefField(true);
954 #ifdef USE_32BIT_REF
955 const OpndDesc prop2(prop0->GetOperandType(), prop0->GetRegProp(), prop0->GetSize() / 2);
956 A64OpndEmitVisitor visitor2(emitter, prop2);
957 opnd0->Accept(visitor2); /* ldr wd, ... for terminal system */
958 #else
959 opnd0->Accept(visitor); /* ldr xd, ... for qemu */
960 #endif /* USE_32BIT_REF */
961 static_cast<RegOperand *>(opnd0)->SetRefField(false);
962 (void)emitter.Emit(", ");
963 (void)emitter.Emit("[");
964 opnd0->Accept(visitor);
965 (void)emitter.Emit(",");
966 (void)emitter.Emit("#");
967 (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
968 if (stImmOpnd->GetOffset() != 0) {
969 (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
970 }
971 (void)emitter.Emit("]\t// load array class.\n");
972
973 /* emit "ldr wzr, [xd]" */
974 (void)emitter.Emit("\t").Emit("ldr\twzr, [");
975 opnd0->Accept(visitor);
976 (void)emitter.Emit("]\t// check resolve array class.\n");
977 #endif
978 }
979
980 /*
981 * intrinsic_get_add_int w0, xt, wt, ws, x1, x2, w3, label
982 * add xt, x1, x2
983 * label:
984 * ldaxr w0, [xt]
985 * add wt, w0, w3
986 * stlxr ws, wt, [xt]
987 * cbnz ws, label
988 */
EmitGetAndAddInt(Emitter & emitter,const Insn & insn) const989 void AArch64AsmEmitter::EmitGetAndAddInt(Emitter &emitter, const Insn &insn) const
990 {
991 #ifdef ARK_LITECG_DEBUG
992 DEBUG_ASSERT(insn.GetOperandSize() > kInsnEighthOpnd, "ensure the oprands number");
993 (void)emitter.Emit("\t//\tstart of Unsafe.getAndAddInt.\n");
994 Operand *tempOpnd0 = &insn.GetOperand(kInsnSecondOpnd);
995 Operand *tempOpnd1 = &insn.GetOperand(kInsnThirdOpnd);
996 Operand *tempOpnd2 = &insn.GetOperand(kInsnFourthOpnd);
997 Operand *objOpnd = &insn.GetOperand(kInsnFifthOpnd);
998 Operand *offsetOpnd = &insn.GetOperand(kInsnSixthOpnd);
999 Operand *deltaOpnd = &insn.GetOperand(kInsnSeventhOpnd);
1000 Operand *labelOpnd = &insn.GetOperand(kInsnEighthOpnd);
1001 A64OpndEmitVisitor visitor(emitter, nullptr);
1002 /* emit add. */
1003 (void)emitter.Emit("\t").Emit("add").Emit("\t");
1004 tempOpnd0->Accept(visitor);
1005 (void)emitter.Emit(", ");
1006 objOpnd->Accept(visitor);
1007 (void)emitter.Emit(", ");
1008 offsetOpnd->Accept(visitor);
1009 (void)emitter.Emit("\n");
1010 /* emit label. */
1011 labelOpnd->Accept(visitor);
1012 (void)emitter.Emit(":\n");
1013 Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1014 const MOperator mOp = insn.GetMachineOpcode();
1015 const InsnDesc *md = &AArch64CG::kMd[mOp];
1016 const OpndDesc *retProp = md->opndMD[kInsnFirstOpnd];
1017 A64OpndEmitVisitor retVisitor(emitter, retProp);
1018 /* emit ldaxr */
1019 (void)emitter.Emit("\t").Emit("ldaxr").Emit("\t");
1020 retVal->Accept(retVisitor);
1021 (void)emitter.Emit(", [");
1022 tempOpnd0->Accept(visitor);
1023 (void)emitter.Emit("]\n");
1024 /* emit add. */
1025 (void)emitter.Emit("\t").Emit("add").Emit("\t");
1026 tempOpnd1->Accept(retVisitor);
1027 (void)emitter.Emit(", ");
1028 retVal->Accept(retVisitor);
1029 (void)emitter.Emit(", ");
1030 deltaOpnd->Accept(retVisitor);
1031 (void)emitter.Emit("\n");
1032 /* emit stlxr. */
1033 (void)emitter.Emit("\t").Emit("stlxr").Emit("\t");
1034 tempOpnd2->Accept(visitor);
1035 (void)emitter.Emit(", ");
1036 tempOpnd1->Accept(retVisitor);
1037 (void)emitter.Emit(", [");
1038 tempOpnd0->Accept(visitor);
1039 (void)emitter.Emit("]\n");
1040 /* emit cbnz. */
1041 (void)emitter.Emit("\t").Emit("cbnz").Emit("\t");
1042 tempOpnd2->Accept(visitor);
1043 (void)emitter.Emit(", ");
1044 labelOpnd->Accept(visitor);
1045 (void)emitter.Emit("\n");
1046 (void)emitter.Emit("\t//\tend of Unsafe.getAndAddInt.\n");
1047 #endif
1048 }
1049
1050 /*
1051 * intrinsic_get_set_int w0, xt, ws, x1, x2, w3, label
1052 * add xt, x1, x2
1053 * label:
1054 * ldaxr w0, [xt]
1055 * stlxr ws, w3, [xt]
1056 * cbnz ws, label
1057 */
EmitGetAndSetInt(Emitter & emitter,const Insn & insn) const1058 void AArch64AsmEmitter::EmitGetAndSetInt(Emitter &emitter, const Insn &insn) const
1059 {
1060 #ifdef ARK_LITECG_DEBUG
1061 /* MOP_get_and_setI and MOP_get_and_setL have 7 operands */
1062 DEBUG_ASSERT(insn.GetOperandSize() > kInsnSeventhOpnd, "ensure the operands number");
1063 Operand *tempOpnd0 = &insn.GetOperand(kInsnSecondOpnd);
1064 Operand *tempOpnd1 = &insn.GetOperand(kInsnThirdOpnd);
1065 Operand *objOpnd = &insn.GetOperand(kInsnFourthOpnd);
1066 Operand *offsetOpnd = &insn.GetOperand(kInsnFifthOpnd);
1067 A64OpndEmitVisitor visitor(emitter, nullptr);
1068 /* add x1, x1, x2 */
1069 (void)emitter.Emit("\tadd\t");
1070 tempOpnd0->Accept(visitor);
1071 (void)emitter.Emit(", ");
1072 objOpnd->Accept(visitor);
1073 (void)emitter.Emit(", ");
1074 offsetOpnd->Accept(visitor);
1075 (void)emitter.Emit("\n");
1076 Operand *labelOpnd = &insn.GetOperand(kInsnSeventhOpnd);
1077 /* label: */
1078 labelOpnd->Accept(visitor);
1079 (void)emitter.Emit(":\n");
1080 Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1081 /* ldaxr w0, [xt] */
1082 (void)emitter.Emit("\tldaxr\t");
1083 retVal->Accept(visitor);
1084 (void)emitter.Emit(", [");
1085 tempOpnd0->Accept(visitor);
1086 (void)emitter.Emit("]\n");
1087 Operand *newValueOpnd = &insn.GetOperand(kInsnSixthOpnd);
1088 /* stlxr ws, w3, [xt] */
1089 (void)emitter.Emit("\tstlxr\t");
1090 tempOpnd1->Accept(visitor);
1091 (void)emitter.Emit(", ");
1092 newValueOpnd->Accept(visitor);
1093 (void)emitter.Emit(", [");
1094 tempOpnd0->Accept(visitor);
1095 (void)emitter.Emit("]\n");
1096 /* cbnz w2, label */
1097 (void)emitter.Emit("\tcbnz\t");
1098 tempOpnd1->Accept(visitor);
1099 (void)emitter.Emit(", ");
1100 labelOpnd->Accept(visitor);
1101 (void)emitter.Emit("\n");
1102 #endif
1103 }
1104
1105 /*
1106 * intrinsic_string_indexof w0, x1, w2, x3, w4, x5, x6, x7, x8, x9, w10,
1107 * Label.FIRST_LOOP, Label.STR2_NEXT, Label.STR1_LOOP,
1108 * Label.STR1_NEXT, Label.LAST_WORD, Label.NOMATCH, Label.RET
1109 * cmp w4, w2
1110 * b.gt .Label.NOMATCH
1111 * sub w2, w2, w4
1112 * sub w4, w4, #8
1113 * mov w10, w2
1114 * uxtw x4, w4
1115 * uxtw x2, w2
1116 * add x3, x3, x4
1117 * add x1, x1, x2
1118 * neg x4, x4
1119 * neg x2, x2
1120 * ldr x5, [x3,x4]
1121 * .Label.FIRST_LOOP:
1122 * ldr x7, [x1,x2]
1123 * cmp x5, x7
1124 * b.eq .Label.STR1_LOOP
1125 * .Label.STR2_NEXT:
1126 * adds x2, x2, #1
1127 * b.le .Label.FIRST_LOOP
1128 * b .Label.NOMATCH
1129 * .Label.STR1_LOOP:
1130 * adds x8, x4, #8
1131 * add x9, x2, #8
1132 * b.ge .Label.LAST_WORD
1133 * .Label.STR1_NEXT:
1134 * ldr x6, [x3,x8]
1135 * ldr x7, [x1,x9]
1136 * cmp x6, x7
1137 * b.ne .Label.STR2_NEXT
1138 * adds x8, x8, #8
1139 * add x9, x9, #8
1140 * b.lt .Label.STR1_NEXT
1141 * .Label.LAST_WORD:
1142 * ldr x6, [x3]
1143 * sub x9, x1, x4
1144 * ldr x7, [x9,x2]
1145 * cmp x6, x7
1146 * b.ne .Label.STR2_NEXT
1147 * add w0, w10, w2
1148 * b .Label.RET
1149 * .Label.NOMATCH:
1150 * mov w0, #-1
1151 * .Label.RET:
1152 */
EmitStringIndexOf(Emitter & emitter,const Insn & insn) const1153 void AArch64AsmEmitter::EmitStringIndexOf(Emitter &emitter, const Insn &insn) const
1154 {
1155 #ifdef ARK_LITECG_DEBUG
1156 /* MOP_string_indexof has 18 operands */
1157 DEBUG_ASSERT(insn.GetOperandSize() == 18, "ensure the operands number");
1158 Operand *patternLengthOpnd = &insn.GetOperand(kInsnFifthOpnd);
1159 Operand *srcLengthOpnd = &insn.GetOperand(kInsnThirdOpnd);
1160 const std::string patternLengthReg =
1161 AArch64CG::intRegNames[AArch64CG::kR64List][static_cast<RegOperand *>(patternLengthOpnd)->GetRegisterNumber()];
1162 const std::string srcLengthReg =
1163 AArch64CG::intRegNames[AArch64CG::kR64List][static_cast<RegOperand *>(srcLengthOpnd)->GetRegisterNumber()];
1164 A64OpndEmitVisitor visitor(emitter, nullptr);
1165 /* cmp w4, w2 */
1166 (void)emitter.Emit("\tcmp\t");
1167 patternLengthOpnd->Accept(visitor);
1168 (void)emitter.Emit(", ");
1169 srcLengthOpnd->Accept(visitor);
1170 (void)emitter.Emit("\n");
1171 /* the 16th operand of MOP_string_indexof is Label.NOMATCH */
1172 Operand *labelNoMatch = &insn.GetOperand(16);
1173 /* b.gt Label.NOMATCH */
1174 (void)emitter.Emit("\tb.gt\t");
1175 labelNoMatch->Accept(visitor);
1176 (void)emitter.Emit("\n");
1177 /* sub w2, w2, w4 */
1178 (void)emitter.Emit("\tsub\t");
1179 srcLengthOpnd->Accept(visitor);
1180 (void)emitter.Emit(", ");
1181 srcLengthOpnd->Accept(visitor);
1182 (void)emitter.Emit(", ");
1183 patternLengthOpnd->Accept(visitor);
1184 (void)emitter.Emit("\n");
1185 /* sub w4, w4, #8 */
1186 (void)emitter.Emit("\tsub\t");
1187 patternLengthOpnd->Accept(visitor);
1188 (void)emitter.Emit(", ");
1189 patternLengthOpnd->Accept(visitor);
1190 (void)emitter.Emit(", #8\n");
1191 /* the 10th operand of MOP_string_indexof is w10 */
1192 Operand *resultTmp = &insn.GetOperand(10);
1193 /* mov w10, w2 */
1194 (void)emitter.Emit("\tmov\t");
1195 resultTmp->Accept(visitor);
1196 (void)emitter.Emit(", ");
1197 srcLengthOpnd->Accept(visitor);
1198 (void)emitter.Emit("\n");
1199 /* uxtw x4, w4 */
1200 (void)emitter.Emit("\tuxtw\t").Emit(patternLengthReg);
1201 (void)emitter.Emit(", ");
1202 patternLengthOpnd->Accept(visitor);
1203 (void)emitter.Emit("\n");
1204 /* uxtw x2, w2 */
1205 (void)emitter.Emit("\tuxtw\t").Emit(srcLengthReg);
1206 (void)emitter.Emit(", ");
1207 srcLengthOpnd->Accept(visitor);
1208 (void)emitter.Emit("\n");
1209 Operand *patternStringBaseOpnd = &insn.GetOperand(kInsnFourthOpnd);
1210 /* add x3, x3, x4 */
1211 (void)emitter.Emit("\tadd\t");
1212 patternStringBaseOpnd->Accept(visitor);
1213 (void)emitter.Emit(", ");
1214 patternStringBaseOpnd->Accept(visitor);
1215 (void)emitter.Emit(", ").Emit(patternLengthReg);
1216 (void)emitter.Emit("\n");
1217 Operand *srcStringBaseOpnd = &insn.GetOperand(kInsnSecondOpnd);
1218 /* add x1, x1, x2 */
1219 (void)emitter.Emit("\tadd\t");
1220 srcStringBaseOpnd->Accept(visitor);
1221 (void)emitter.Emit(", ");
1222 srcStringBaseOpnd->Accept(visitor);
1223 (void)emitter.Emit(", ").Emit(srcLengthReg);
1224 (void)emitter.Emit("\n");
1225 /* neg x4, x4 */
1226 (void)emitter.Emit("\tneg\t").Emit(patternLengthReg);
1227 (void)emitter.Emit(", ").Emit(patternLengthReg);
1228 (void)emitter.Emit("\n");
1229 /* neg x2, x2 */
1230 (void)emitter.Emit("\tneg\t").Emit(srcLengthReg);
1231 (void)emitter.Emit(", ").Emit(srcLengthReg);
1232 (void)emitter.Emit("\n");
1233 Operand *first = &insn.GetOperand(kInsnSixthOpnd);
1234 /* ldr x5, [x3,x4] */
1235 (void)emitter.Emit("\tldr\t");
1236 first->Accept(visitor);
1237 (void)emitter.Emit(", [");
1238 patternStringBaseOpnd->Accept(visitor);
1239 (void)emitter.Emit(",").Emit(patternLengthReg);
1240 (void)emitter.Emit("]\n");
1241 /* the 11th operand of MOP_string_indexof is Label.FIRST_LOOP */
1242 Operand *labelFirstLoop = &insn.GetOperand(11);
1243 /* .Label.FIRST_LOOP: */
1244 labelFirstLoop->Accept(visitor);
1245 (void)emitter.Emit(":\n");
1246 /* the 7th operand of MOP_string_indexof is x7 */
1247 Operand *ch2 = &insn.GetOperand(7);
1248 /* ldr x7, [x1,x2] */
1249 (void)emitter.Emit("\tldr\t");
1250 ch2->Accept(visitor);
1251 (void)emitter.Emit(", [");
1252 srcStringBaseOpnd->Accept(visitor);
1253 (void)emitter.Emit(",").Emit(srcLengthReg);
1254 (void)emitter.Emit("]\n");
1255 /* cmp x5, x7 */
1256 (void)emitter.Emit("\tcmp\t");
1257 first->Accept(visitor);
1258 (void)emitter.Emit(", ");
1259 ch2->Accept(visitor);
1260 (void)emitter.Emit("\n");
1261 /* the 13th operand of MOP_string_indexof is Label.STR1_LOOP */
1262 Operand *labelStr1Loop = &insn.GetOperand(13);
1263 /* b.eq .Label.STR1_LOOP */
1264 (void)emitter.Emit("\tb.eq\t");
1265 labelStr1Loop->Accept(visitor);
1266 (void)emitter.Emit("\n");
1267 /* the 12th operand of MOP_string_indexof is Label.STR2_NEXT */
1268 Operand *labelStr2Next = &insn.GetOperand(12);
1269 /* .Label.STR2_NEXT: */
1270 labelStr2Next->Accept(visitor);
1271 (void)emitter.Emit(":\n");
1272 /* adds x2, x2, #1 */
1273 (void)emitter.Emit("\tadds\t").Emit(srcLengthReg);
1274 (void)emitter.Emit(", ").Emit(srcLengthReg);
1275 (void)emitter.Emit(", #1\n");
1276 /* b.le .Label.FIRST_LOOP */
1277 (void)emitter.Emit("\tb.le\t");
1278 labelFirstLoop->Accept(visitor);
1279 (void)emitter.Emit("\n");
1280 /* b .Label.NOMATCH */
1281 (void)emitter.Emit("\tb\t");
1282 labelNoMatch->Accept(visitor);
1283 (void)emitter.Emit("\n");
1284 /* .Label.STR1_LOOP: */
1285 labelStr1Loop->Accept(visitor);
1286 (void)emitter.Emit(":\n");
1287 /* the 8th operand of MOP_string_indexof is x8 */
1288 Operand *tmp1 = &insn.GetOperand(kInsnEighthOpnd);
1289 /* adds x8, x4, #8 */
1290 (void)emitter.Emit("\tadds\t");
1291 tmp1->Accept(visitor);
1292 (void)emitter.Emit(", ").Emit(patternLengthReg);
1293 (void)emitter.Emit(", #8\n");
1294 /* the 9th operand of MOP_string_indexof is x9 */
1295 Operand *tmp2 = &insn.GetOperand(9);
1296 /* add x9, x2, #8 */
1297 (void)emitter.Emit("\tadd\t");
1298 tmp2->Accept(visitor);
1299 (void)emitter.Emit(", ").Emit(srcLengthReg);
1300 (void)emitter.Emit(", #8\n");
1301 /* the 15th operand of MOP_string_indexof is Label.LAST_WORD */
1302 Operand *labelLastWord = &insn.GetOperand(15);
1303 /* b.ge .Label.LAST_WORD */
1304 (void)emitter.Emit("\tb.ge\t");
1305 labelLastWord->Accept(visitor);
1306 (void)emitter.Emit("\n");
1307 /* the 14th operand of MOP_string_indexof is Label.STR1_NEXT */
1308 Operand *labelStr1Next = &insn.GetOperand(14);
1309 /* .Label.STR1_NEXT: */
1310 labelStr1Next->Accept(visitor);
1311 (void)emitter.Emit(":\n");
1312 /* the 6th operand of MOP_string_indexof is x6 */
1313 Operand *ch1 = &insn.GetOperand(6);
1314 /* ldr x6, [x3,x8] */
1315 (void)emitter.Emit("\tldr\t");
1316 ch1->Accept(visitor);
1317 (void)emitter.Emit(", [");
1318 patternStringBaseOpnd->Accept(visitor);
1319 (void)emitter.Emit(",");
1320 tmp1->Accept(visitor);
1321 (void)emitter.Emit("]\n");
1322 /* ldr x7, [x1,x9] */
1323 (void)emitter.Emit("\tldr\t");
1324 ch2->Accept(visitor);
1325 (void)emitter.Emit(", [");
1326 srcStringBaseOpnd->Accept(visitor);
1327 (void)emitter.Emit(",");
1328 tmp2->Accept(visitor);
1329 (void)emitter.Emit("]\n");
1330 /* cmp x6, x7 */
1331 (void)emitter.Emit("\tcmp\t");
1332 ch1->Accept(visitor);
1333 (void)emitter.Emit(", ");
1334 ch2->Accept(visitor);
1335 (void)emitter.Emit("\n");
1336 /* b.ne .Label.STR2_NEXT */
1337 (void)emitter.Emit("\tb.ne\t");
1338 labelStr2Next->Accept(visitor);
1339 (void)emitter.Emit("\n");
1340 /* adds x8, x8, #8 */
1341 (void)emitter.Emit("\tadds\t");
1342 tmp1->Accept(visitor);
1343 (void)emitter.Emit(", ");
1344 tmp1->Accept(visitor);
1345 (void)emitter.Emit(", #8\n");
1346 /* add x9, x9, #8 */
1347 (void)emitter.Emit("\tadd\t");
1348 tmp2->Accept(visitor);
1349 (void)emitter.Emit(", ");
1350 tmp2->Accept(visitor);
1351 (void)emitter.Emit(", #8\n");
1352 /* b.lt .Label.STR1_NEXT */
1353 (void)emitter.Emit("\tb.lt\t");
1354 labelStr1Next->Accept(visitor);
1355 (void)emitter.Emit("\n");
1356 /* .Label.LAST_WORD: */
1357 labelLastWord->Accept(visitor);
1358 (void)emitter.Emit(":\n");
1359 /* ldr x6, [x3] */
1360 (void)emitter.Emit("\tldr\t");
1361 ch1->Accept(visitor);
1362 (void)emitter.Emit(", [");
1363 patternStringBaseOpnd->Accept(visitor);
1364 (void)emitter.Emit("]\n");
1365 /* sub x9, x1, x4 */
1366 (void)emitter.Emit("\tsub\t");
1367 tmp2->Accept(visitor);
1368 (void)emitter.Emit(", ");
1369 srcStringBaseOpnd->Accept(visitor);
1370 (void)emitter.Emit(", ").Emit(patternLengthReg);
1371 (void)emitter.Emit("\n");
1372 /* ldr x7, [x9,x2] */
1373 (void)emitter.Emit("\tldr\t");
1374 ch2->Accept(visitor);
1375 (void)emitter.Emit(", [");
1376 tmp2->Accept(visitor);
1377 (void)emitter.Emit(", ").Emit(srcLengthReg);
1378 (void)emitter.Emit("]\n");
1379 /* cmp x6, x7 */
1380 (void)emitter.Emit("\tcmp\t");
1381 ch1->Accept(visitor);
1382 (void)emitter.Emit(", ");
1383 ch2->Accept(visitor);
1384 (void)emitter.Emit("\n");
1385 /* b.ne .Label.STR2_NEXT */
1386 (void)emitter.Emit("\tb.ne\t");
1387 labelStr2Next->Accept(visitor);
1388 (void)emitter.Emit("\n");
1389 Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1390 /* add w0, w10, w2 */
1391 (void)emitter.Emit("\tadd\t");
1392 retVal->Accept(visitor);
1393 (void)emitter.Emit(", ");
1394 resultTmp->Accept(visitor);
1395 (void)emitter.Emit(", ");
1396 srcLengthOpnd->Accept(visitor);
1397 (void)emitter.Emit("\n");
1398 /* the 17th operand of MOP_string_indexof Label.ret */
1399 Operand *labelRet = &insn.GetOperand(17);
1400 /* b .Label.ret */
1401 (void)emitter.Emit("\tb\t");
1402 labelRet->Accept(visitor);
1403 (void)emitter.Emit("\n");
1404 /* .Label.NOMATCH: */
1405 labelNoMatch->Accept(visitor);
1406 (void)emitter.Emit(":\n");
1407 /* mov w0, #-1 */
1408 (void)emitter.Emit("\tmov\t");
1409 retVal->Accept(visitor);
1410 (void)emitter.Emit(", #-1\n");
1411 /* .Label.ret: */
1412 labelRet->Accept(visitor);
1413 (void)emitter.Emit(":\n");
1414 #endif
1415 }
1416
1417 /*
1418 * intrinsic_compare_swap_int x0, xt, xs, x1, x2, w3, w4, lable1, label2
1419 * add xt, x1, x2
1420 * label1:
1421 * ldaxr ws, [xt]
1422 * cmp ws, w3
1423 * b.ne label2
1424 * stlxr ws, w4, [xt]
1425 * cbnz ws, label1
1426 * label2:
1427 * cset x0, eq
1428 */
EmitCompareAndSwapInt(Emitter & emitter,const Insn & insn) const1429 void AArch64AsmEmitter::EmitCompareAndSwapInt(Emitter &emitter, const Insn &insn) const
1430 {
1431 #ifdef ARK_LITECG_DEBUG
1432 /* MOP_compare_and_swapI and MOP_compare_and_swapL have 8 operands */
1433 DEBUG_ASSERT(insn.GetOperandSize() > kInsnEighthOpnd, "ensure the operands number");
1434 const MOperator mOp = insn.GetMachineOpcode();
1435 const InsnDesc *md = &AArch64CG::kMd[mOp];
1436 Operand *temp0 = &insn.GetOperand(kInsnSecondOpnd);
1437 Operand *temp1 = &insn.GetOperand(kInsnThirdOpnd);
1438 Operand *obj = &insn.GetOperand(kInsnFourthOpnd);
1439 Operand *offset = &insn.GetOperand(kInsnFifthOpnd);
1440 A64OpndEmitVisitor visitor(emitter, nullptr);
1441 /* add xt, x1, x2 */
1442 (void)emitter.Emit("\tadd\t");
1443 temp0->Accept(visitor);
1444 (void)emitter.Emit(", ");
1445 obj->Accept(visitor);
1446 (void)emitter.Emit(", ");
1447 offset->Accept(visitor);
1448 (void)emitter.Emit("\n");
1449 Operand *label1 = &insn.GetOperand(kInsnEighthOpnd);
1450 /* label1: */
1451 label1->Accept(visitor);
1452 (void)emitter.Emit(":\n");
1453 /* ldaxr ws, [xt] */
1454 (void)emitter.Emit("\tldaxr\t");
1455 temp1->Accept(visitor);
1456 (void)emitter.Emit(", [");
1457 temp0->Accept(visitor);
1458 (void)emitter.Emit("]\n");
1459 Operand *expectedValue = &insn.GetOperand(kInsnSixthOpnd);
1460 const OpndDesc *expectedValueProp = md->opndMD[kInsnSixthOpnd];
1461 /* cmp ws, w3 */
1462 (void)emitter.Emit("\tcmp\t");
1463 temp1->Accept(visitor);
1464 (void)emitter.Emit(", ");
1465 A64OpndEmitVisitor visitorExpect(emitter, expectedValueProp);
1466 expectedValue->Accept(visitorExpect);
1467 (void)emitter.Emit("\n");
1468 constexpr uint32 kInsnNinethOpnd = 8;
1469 Operand *label2 = &insn.GetOperand(kInsnNinethOpnd);
1470 /* b.ne label2 */
1471 (void)emitter.Emit("\tbne\t");
1472 label2->Accept(visitor);
1473 (void)emitter.Emit("\n");
1474 Operand *newValue = &insn.GetOperand(kInsnSeventhOpnd);
1475 /* stlxr ws, w4, [xt] */
1476 (void)emitter.Emit("\tstlxr\t");
1477 (void)emitter.Emit(
1478 AArch64CG::intRegNames[AArch64CG::kR32List][static_cast<RegOperand *>(temp1)->GetRegisterNumber()]);
1479 (void)emitter.Emit(", ");
1480 newValue->Accept(visitor);
1481 (void)emitter.Emit(", [");
1482 temp0->Accept(visitor);
1483 (void)emitter.Emit("]\n");
1484 /* cbnz ws, label1 */
1485 (void)emitter.Emit("\tcbnz\t");
1486 (void)emitter.Emit(
1487 AArch64CG::intRegNames[AArch64CG::kR32List][static_cast<RegOperand *>(temp1)->GetRegisterNumber()]);
1488 (void)emitter.Emit(", ");
1489 label1->Accept(visitor);
1490 (void)emitter.Emit("\n");
1491 /* label2: */
1492 label2->Accept(visitor);
1493 (void)emitter.Emit(":\n");
1494 Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1495 /* cset x0, eq */
1496 (void)emitter.Emit("\tcset\t");
1497 retVal->Accept(visitor);
1498 (void)emitter.Emit(", EQ\n");
1499 #endif
1500 }
1501
EmitCTlsDescRel(Emitter & emitter,const Insn & insn) const1502 void AArch64AsmEmitter::EmitCTlsDescRel(Emitter &emitter, const Insn &insn) const
1503 {
1504 #ifdef ARK_LITECG_DEBUG
1505 const InsnDesc *md = &AArch64CG::kMd[MOP_tls_desc_rel];
1506 Operand *result = &insn.GetOperand(kInsnFirstOpnd);
1507 Operand *src = &insn.GetOperand(kInsnSecondOpnd);
1508 Operand *symbol = &insn.GetOperand(kInsnThirdOpnd);
1509 auto stImmOpnd = static_cast<StImmOperand *>(symbol);
1510 A64OpndEmitVisitor resultVisitor(emitter, md->opndMD[0]);
1511 A64OpndEmitVisitor srcVisitor(emitter, md->opndMD[1]);
1512 (void)emitter.Emit("\t").Emit("add").Emit("\t");
1513 result->Accept(resultVisitor);
1514 (void)emitter.Emit(", ");
1515 src->Accept(srcVisitor);
1516 (void)emitter.Emit(", #:tprel_hi12:").Emit(stImmOpnd->GetName()).Emit(", lsl #12\n");
1517 (void)emitter.Emit("\t").Emit("add").Emit("\t");
1518 result->Accept(resultVisitor);
1519 (void)emitter.Emit(", ");
1520 result->Accept(resultVisitor);
1521 (void)emitter.Emit(", #:tprel_lo12_nc:").Emit(stImmOpnd->GetName()).Emit("\n");
1522 #endif
1523 }
1524
EmitCTlsDescCall(Emitter & emitter,const Insn & insn) const1525 void AArch64AsmEmitter::EmitCTlsDescCall(Emitter &emitter, const Insn &insn) const
1526 {
1527 #ifdef ARK_LITECG_DEBUG
1528 const InsnDesc *md = &AArch64CG::kMd[MOP_tls_desc_call];
1529 Operand *func = &insn.GetOperand(kInsnFirstOpnd);
1530 Operand *symbol = &insn.GetOperand(kInsnThirdOpnd);
1531 const OpndDesc *prop = md->opndMD[0];
1532 auto *stImmOpnd = static_cast<StImmOperand *>(symbol);
1533 const std::string &symName = stImmOpnd->GetName();
1534 A64OpndEmitVisitor funcVisitor(emitter, prop);
1535 /* adrp x0, :tlsdesc:symbol */
1536 (void)emitter.Emit("\t").Emit("adrp\tx0, :tlsdesc:").Emit(symName).Emit("\n");
1537 /* ldr x1, [x0, #tlsdesc_lo12:symbol] */
1538 (void)emitter.Emit("\t").Emit("ldr").Emit("\t");
1539 func->Accept(funcVisitor);
1540 (void)emitter.Emit(", [x0, #:tlsdesc_lo12:").Emit(symName).Emit("]\n");
1541 /* add x0 ,#tlsdesc_lo12:symbol */
1542 (void)emitter.Emit("\t").Emit("add\tx0, x0, :tlsdesc_lo12:").Emit(symName).Emit("\n");
1543 /* .tlsdesccall <symbolName> */
1544 (void)emitter.Emit("\t").Emit(".tlsdesccall").Emit("\t").Emit(symName).Emit("\n");
1545 /* blr xd */
1546 (void)emitter.Emit("\t").Emit("blr").Emit("\t");
1547 func->Accept(funcVisitor);
1548 (void)emitter.Emit("\n");
1549 #endif
1550 }
1551
EmitSyncLockTestSet(Emitter & emitter,const Insn & insn) const1552 void AArch64AsmEmitter::EmitSyncLockTestSet(Emitter &emitter, const Insn &insn) const
1553 {
1554 #ifdef ARK_LITECG_DEBUG
1555 const InsnDesc *md = &AArch64CG::kMd[insn.GetMachineOpcode()];
1556 auto *result = &insn.GetOperand(kInsnFirstOpnd);
1557 auto *temp = &insn.GetOperand(kInsnSecondOpnd);
1558 auto *addr = &insn.GetOperand(kInsnThirdOpnd);
1559 auto *value = &insn.GetOperand(kInsnFourthOpnd);
1560 auto *label = &insn.GetOperand(kInsnFifthOpnd);
1561 A64OpndEmitVisitor resultVisitor(emitter, md->opndMD[kInsnFirstOpnd]);
1562 A64OpndEmitVisitor tempVisitor(emitter, md->opndMD[kInsnSecondOpnd]);
1563 A64OpndEmitVisitor addrVisitor(emitter, md->opndMD[kInsnThirdOpnd]);
1564 A64OpndEmitVisitor valueVisitor(emitter, md->opndMD[kInsnFourthOpnd]);
1565 A64OpndEmitVisitor labelVisitor(emitter, md->opndMD[kInsnFifthOpnd]);
1566 /* label: */
1567 label->Accept(labelVisitor);
1568 (void)emitter.Emit(":\n");
1569 /* ldxr x0, [x2] */
1570 (void)emitter.Emit("\t").Emit("ldxr").Emit("\t");
1571 result->Accept(resultVisitor);
1572 (void)emitter.Emit(", [");
1573 addr->Accept(addrVisitor);
1574 (void)emitter.Emit("]\n");
1575 /* stxr w1, x3, [x2] */
1576 (void)emitter.Emit("\t").Emit("stxr").Emit("\t");
1577 temp->Accept(tempVisitor);
1578 (void)emitter.Emit(", ");
1579 value->Accept(valueVisitor);
1580 (void)emitter.Emit(", [");
1581 addr->Accept(addrVisitor);
1582 (void)emitter.Emit("]\n");
1583 /* cbnz w1, label */
1584 (void)emitter.Emit("\t").Emit("cbnz").Emit("\t");
1585 temp->Accept(tempVisitor);
1586 (void)emitter.Emit(", ");
1587 label->Accept(labelVisitor);
1588 (void)emitter.Emit("\n");
1589 /* dmb ish */
1590 (void)emitter.Emit("\t").Emit("dmb").Emit("\t").Emit("ish").Emit("\n");
1591 #endif
1592 }
1593
EmitPureCall(Emitter & emitter,const Insn & insn) const1594 void AArch64AsmEmitter::EmitPureCall(Emitter &emitter, const Insn &insn) const
1595 {
1596 #ifdef ARK_LITECG_DEBUG
1597 const InsnDesc *md = &AArch64CG::kMd[insn.GetMachineOpcode()];
1598 auto *callee = &insn.GetOperand(kInsnFirstOpnd);
1599 A64OpndEmitVisitor calleeVisitor(emitter, md->opndMD[kInsnFirstOpnd]);
1600 (void)emitter.Emit("\t").Emit("blr").Emit("\t");
1601 callee->Accept(calleeVisitor);
1602 (void)emitter.Emit("\n");
1603 #endif
1604 }
1605
EmitCheckThrowPendingException(Emitter & emitter,Insn & insn) const1606 void AArch64AsmEmitter::EmitCheckThrowPendingException(Emitter &emitter, Insn &insn) const
1607 {
1608 #ifdef ARK_LITECG_DEBUG
1609 /*
1610 * mrs x16, TPIDR_EL0
1611 * ldr x16, [x16, #64]
1612 * ldr x16, [x16, #8]
1613 * cbz x16, .lnoexception
1614 * bl MCC_ThrowPendingException
1615 * .lnoexception:
1616 */
1617 (void)emitter.Emit("\t").Emit("mrs").Emit("\tx16, TPIDR_EL0");
1618 (void)emitter.Emit("\n");
1619 (void)emitter.Emit("\t").Emit("ldr").Emit("\tx16, [x16, #64]");
1620 (void)emitter.Emit("\n");
1621 (void)emitter.Emit("\t").Emit("ldr").Emit("\tx16, [x16, #8]");
1622 (void)emitter.Emit("\n");
1623 (void)emitter.Emit("\t").Emit("cbz").Emit("\tx16, .lnoeh.").Emit(maplebe::CG::GetCurCGFunc()->GetName());
1624 (void)emitter.Emit("\n");
1625 (void)emitter.Emit("\t").Emit("bl").Emit("\tMCC_ThrowPendingException");
1626 (void)emitter.Emit("\n");
1627 (void)emitter.Emit(".lnoeh.").Emit(maplebe::CG::GetCurCGFunc()->GetName()).Emit(":");
1628 (void)emitter.Emit("\n");
1629 #endif
1630 }
1631
EmitLazyBindingRoutine(Emitter & emitter,const Insn & insn) const1632 void AArch64AsmEmitter::EmitLazyBindingRoutine(Emitter &emitter, const Insn &insn) const
1633 {
1634 #ifdef ARK_LITECG_DEBUG
1635 /* ldr xzr, [xs] */
1636 const InsnDesc *md = &AArch64CG::kMd[MOP_adrp_ldr];
1637
1638 Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
1639 const OpndDesc *prop0 = md->opndMD[0];
1640 A64OpndEmitVisitor visitor(emitter, prop0);
1641
1642 /* emit "ldr xzr,[xs]" */
1643 #ifdef USE_32BIT_REF
1644 (void)emitter.Emit("\t").Emit("ldr").Emit("\twzr, [");
1645 #else
1646 (void)emitter.Emit("\t").Emit("ldr").Emit("\txzr, [");
1647 #endif /* USE_32BIT_REF */
1648 opnd0->Accept(visitor);
1649 (void)emitter.Emit("]");
1650 (void)emitter.Emit("\t// Lazy binding\n");
1651 #endif
1652 }
1653
1654 #ifdef ARK_LITECG_DEBUG
1655 struct CfiDescr {
1656 const std::string name;
1657 uint32 opndCount;
1658 /* create 3 OperandType array to store cfi instruction's operand type */
1659 std::array<Operand::OperandType, 3> opndTypes;
1660 };
1661
1662 static CfiDescr cfiDescrTable[cfi::kOpCfiLast + 1] = {
1663 #define CFI_DEFINE(k, sub, n, o0, o1, o2) {".cfi_" #k, n, {Operand::kOpd##o0, Operand::kOpd##o1, Operand::kOpd##o2}},
1664 #define ARM_DIRECTIVES_DEFINE(k, sub, n, o0, o1, o2) \
1665 {"." #k, n, {Operand::kOpd##o0, Operand::kOpd##o1, Operand::kOpd##o2}},
1666 #include "cfi.def"
1667 #undef CFI_DEFINE
1668 #undef ARM_DIRECTIVES_DEFINE
1669 {".cfi_undef", 0, {Operand::kOpdUndef, Operand::kOpdUndef, Operand::kOpdUndef}}};
1670 #endif
1671
EmitAArch64CfiInsn(Emitter & emitter,const Insn & insn) const1672 void AArch64AsmEmitter::EmitAArch64CfiInsn(Emitter &emitter, const Insn &insn) const
1673 {
1674 #ifdef ARK_LITECG_DEBUG
1675 MOperator mOp = insn.GetMachineOpcode();
1676 CHECK_FATAL(mOp <= cfi::kOpCfiLast, "check overflow");
1677 CfiDescr &cfiDescr = cfiDescrTable[mOp];
1678 (void)emitter.Emit("\t").Emit(cfiDescr.name);
1679 for (uint32 i = 0; i < cfiDescr.opndCount; ++i) {
1680 (void)emitter.Emit(" ");
1681 Operand &curOperand = insn.GetOperand(i);
1682 cfi::CFIOpndEmitVisitor cfiOpndEmitVisitor(emitter);
1683 curOperand.Accept(cfiOpndEmitVisitor);
1684 if (i < (cfiDescr.opndCount - 1)) {
1685 (void)emitter.Emit(",");
1686 }
1687 }
1688 (void)emitter.Emit("\n");
1689 #endif
1690 }
1691
CheckInsnRefField(const Insn & insn,size_t opndIndex) const1692 bool AArch64AsmEmitter::CheckInsnRefField(const Insn &insn, size_t opndIndex) const
1693 {
1694 #ifdef ARK_LITECG_DEBUG
1695 if (insn.IsAccessRefField() && insn.AccessMem()) {
1696 Operand &opnd0 = insn.GetOperand(opndIndex);
1697 if (opnd0.IsRegister()) {
1698 static_cast<RegOperand &>(opnd0).SetRefField(true);
1699 return true;
1700 }
1701 }
1702 #endif
1703 return false;
1704 }
1705 } /* namespace maplebe */
1706