EncoderMD.cpp 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "Backend.h"
  6. #include "ARM64Encoder.h"
  7. #include "ARM64NeonEncoder.h"
  8. #include "Language/JavascriptFunctionArgIndex.h"
  9. static const uint32 Opdope[] =
  10. {
  11. #define MACRO(name, jnLayout, attrib, byte2, form, opbyte, dope, ...) dope,
  12. #include "MdOpCodes.h"
  13. #undef MACRO
  14. };
  15. DWORD
  16. EncoderMD::BranchOffset_26(int64 x)
  17. {
  18. Assert(IS_CONST_INT26(x >> 1));
  19. Assert((x & 0x3) == 0);
  20. x = x >> 2;
  21. return (DWORD) x;
  22. }
  23. ///----------------------------------------------------------------------------
  24. ///
  25. /// EncoderMD::Init
  26. ///
  27. ///----------------------------------------------------------------------------
  28. void
  29. EncoderMD::Init(Encoder *encoder)
  30. {
  31. m_encoder = encoder;
  32. m_relocList = nullptr;
  33. }
  34. ///----------------------------------------------------------------------------
  35. ///
  36. /// EncoderMD::GetRegEncode
  37. ///
  38. /// Get the encoding of a given register.
  39. ///
  40. ///----------------------------------------------------------------------------
  41. const BYTE
  42. EncoderMD::GetRegEncode(IR::RegOpnd *regOpnd)
  43. {
  44. return GetRegEncode(regOpnd->GetReg());
  45. }
  46. const BYTE
  47. EncoderMD::GetRegEncode(RegNum reg)
  48. {
  49. return RegEncode[reg];
  50. }
  51. const BYTE
  52. EncoderMD::GetFloatRegEncode(IR::RegOpnd *regOpnd)
  53. {
  54. BYTE regEncode = GetRegEncode(regOpnd->GetReg());
  55. AssertMsg(regEncode <= LAST_FLOAT_REG_ENCODE, "Impossible to allocate higher registers on VFP");
  56. return regEncode;
  57. }
  58. ///----------------------------------------------------------------------------
  59. ///
  60. /// EncoderMD::GetOpdope
  61. ///
  62. /// Get the dope vector of a particular instr. The dope vector describes
  63. /// certain properties of an instr.
  64. ///
  65. ///----------------------------------------------------------------------------
  66. uint32
  67. EncoderMD::GetOpdope(IR::Instr *instr)
  68. {
  69. return GetOpdope(instr->m_opcode);
  70. }
  71. uint32
  72. EncoderMD::GetOpdope(Js::OpCode op)
  73. {
  74. return Opdope[op - (Js::OpCode::MDStart+1)];
  75. }
  76. //
  77. // EncoderMD::CanonicalizeInstr :
  78. // Put the instruction in its final form for encoding. This may involve
  79. // expanding a pseudo-op such as LEA or changing an opcode to indicate the
  80. // op bits the encoder should use.
  81. //
  82. // Return the size of the final instruction's encoding.
  83. //
  84. bool EncoderMD::CanonicalizeInstr(IR::Instr* instr)
  85. {
  86. if (!instr->IsLowered())
  87. {
  88. return false;
  89. }
  90. if (instr->m_opcode == Js::OpCode::LEA)
  91. {
  92. this->CanonicalizeLea(instr);
  93. }
  94. return true;
  95. }
  96. void EncoderMD::CanonicalizeLea(IR::Instr * instr)
  97. {
  98. int32 offset;
  99. IR::Opnd* src1 = instr->UnlinkSrc1();
  100. if (src1->IsSymOpnd())
  101. {
  102. RegNum baseReg;
  103. // We may as well turn this LEA into the equivalent ADD instruction and let the common ADD
  104. // logic handle it.
  105. IR::SymOpnd *symOpnd = src1->AsSymOpnd();
  106. this->BaseAndOffsetFromSym(symOpnd, &baseReg, &offset, this->m_func);
  107. symOpnd->Free(this->m_func);
  108. instr->SetSrc1(IR::RegOpnd::New(nullptr, baseReg, TyMachReg, this->m_func));
  109. Assert(IS_CONST_00000FFF(offset) || IS_CONST_00FFF000(offset));
  110. instr->SetSrc2(IR::IntConstOpnd::New(offset, TyMachReg, this->m_func));
  111. }
  112. else
  113. {
  114. IR::IndirOpnd *indirOpnd = src1->AsIndirOpnd();
  115. IR::RegOpnd *baseOpnd = indirOpnd->GetBaseOpnd();
  116. IR::RegOpnd *indexOpnd = indirOpnd->GetIndexOpnd();
  117. offset = indirOpnd->GetOffset();
  118. Assert(offset == 0 || indexOpnd == nullptr);
  119. instr->SetSrc1(baseOpnd);
  120. if (indexOpnd)
  121. {
  122. AssertMsg(indirOpnd->GetScale() == 0, "NYI Needs shifted register support for ADD");
  123. instr->SetSrc2(indexOpnd);
  124. }
  125. else
  126. {
  127. // We want to emit a legal instruction
  128. Assert(IS_CONST_00000FFF(offset) || IS_CONST_00FFF000(offset));
  129. instr->SetSrc2(IR::IntConstOpnd::New(offset, TyMachReg, this->m_func));
  130. }
  131. indirOpnd->Free(this->m_func);
  132. }
  133. instr->m_opcode = Js::OpCode::ADD;
  134. Assert(instr->GetSrc1()->GetSize() == instr->GetSrc2()->GetSize());
  135. }
  136. bool
  137. EncoderMD::DecodeMemoryOpnd(IR::Opnd* opnd, ARM64_REGISTER &baseRegResult, ARM64_REGISTER &indexRegResult, BYTE &indexScale, int32 &offset)
  138. {
  139. RegNum baseReg;
  140. if (opnd->IsSymOpnd())
  141. {
  142. IR::SymOpnd *symOpnd = opnd->AsSymOpnd();
  143. this->BaseAndOffsetFromSym(symOpnd, &baseReg, &offset, this->m_func);
  144. baseRegResult = this->GetRegEncode(baseReg);
  145. return false;
  146. }
  147. else
  148. {
  149. IR::IndirOpnd *indirOpnd = opnd->AsIndirOpnd();
  150. IR::RegOpnd *baseOpnd = indirOpnd->GetBaseOpnd();
  151. IR::RegOpnd *indexOpnd = indirOpnd->GetIndexOpnd();
  152. offset = indirOpnd->GetOffset();
  153. Assert(offset == 0 || indexOpnd == nullptr);
  154. baseRegResult = this->GetRegEncode(baseOpnd);
  155. if (indexOpnd)
  156. {
  157. indexRegResult = this->GetRegEncode(indexOpnd);
  158. indexScale = indirOpnd->GetScale();
  159. return true;
  160. }
  161. else
  162. {
  163. return false;
  164. }
  165. }
  166. }
  167. template<typename _RegFunc64>
  168. int EncoderMD::EmitOp1Register64(Arm64CodeEmitter &Emitter, IR::Instr* instr, _RegFunc64 reg64)
  169. {
  170. IR::Opnd* src1 = instr->GetSrc1();
  171. Assert(src1->IsRegOpnd());
  172. Assert(src1->GetSize() == 8);
  173. return reg64(Emitter, this->GetRegEncode(src1->AsRegOpnd()));
  174. }
  175. template<typename _RegFunc32, typename _RegFunc64>
  176. int EncoderMD::EmitOp2Register(Arm64CodeEmitter &Emitter, IR::Instr* instr, _RegFunc32 reg32, _RegFunc64 reg64)
  177. {
  178. IR::Opnd* dst = instr->GetDst();
  179. IR::Opnd* src1 = instr->GetSrc1();
  180. Assert(dst->IsRegOpnd());
  181. Assert(src1->IsRegOpnd());
  182. int size = dst->GetSize();
  183. Assert(size == 4 || size == 8);
  184. Assert(size == src1->GetSize());
  185. if (size == 8)
  186. {
  187. return reg64(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src1->AsRegOpnd()));
  188. }
  189. else
  190. {
  191. return reg32(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src1->AsRegOpnd()));
  192. }
  193. }
  194. template<typename _RegFunc32, typename _RegFunc64>
  195. int EncoderMD::EmitOp3Register(Arm64CodeEmitter &Emitter, IR::Instr* instr, _RegFunc32 reg32, _RegFunc64 reg64)
  196. {
  197. IR::Opnd* dst = instr->GetDst();
  198. IR::Opnd* src1 = instr->GetSrc1();
  199. IR::Opnd* src2 = instr->GetSrc2();
  200. Assert(dst->IsRegOpnd());
  201. Assert(src1->IsRegOpnd());
  202. Assert(src2->IsRegOpnd());
  203. int size = dst->GetSize();
  204. Assert(size == 4 || size == 8);
  205. Assert(size == src1->GetSize());
  206. Assert(size == src2->GetSize());
  207. if (size == 8)
  208. {
  209. return reg64(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src1->AsRegOpnd()), this->GetRegEncode(src2->AsRegOpnd()));
  210. }
  211. else
  212. {
  213. return reg32(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src1->AsRegOpnd()), this->GetRegEncode(src2->AsRegOpnd()));
  214. }
  215. }
  216. template<typename _RegFunc32, typename _RegFunc64>
  217. int EncoderMD::EmitOp3RegisterShifted(Arm64CodeEmitter &Emitter, IR::Instr* instr, SHIFT_EXTEND_TYPE shiftType, int shiftAmount, _RegFunc32 reg32, _RegFunc64 reg64)
  218. {
  219. IR::Opnd* dst = instr->GetDst();
  220. IR::Opnd* src1 = instr->GetSrc1();
  221. IR::Opnd* src2 = instr->GetSrc2();
  222. Assert(dst->IsRegOpnd());
  223. Assert(src1->IsRegOpnd());
  224. Assert(src2->IsRegOpnd());
  225. int size = dst->GetSize();
  226. Assert(size == 4 || size == 8);
  227. Assert(size == src1->GetSize());
  228. Assert(size == src2->GetSize());
  229. if (size == 8)
  230. {
  231. return reg64(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src1->AsRegOpnd()), Arm64RegisterParam(this->GetRegEncode(src2->AsRegOpnd()), shiftType, shiftAmount & 63));
  232. }
  233. else
  234. {
  235. return reg32(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src1->AsRegOpnd()), Arm64RegisterParam(this->GetRegEncode(src2->AsRegOpnd()), shiftType, shiftAmount & 31));
  236. }
  237. }
  238. template<typename _ImmFunc32, typename _ImmFunc64>
  239. int EncoderMD::EmitOp3Immediate(Arm64CodeEmitter &Emitter, IR::Instr* instr, _ImmFunc32 imm32, _ImmFunc64 imm64)
  240. {
  241. IR::Opnd* dst = instr->GetDst();
  242. IR::Opnd* src1 = instr->GetSrc1();
  243. IR::Opnd* src2 = instr->GetSrc2();
  244. Assert(dst->IsRegOpnd());
  245. Assert(src1->IsRegOpnd());
  246. Assert(src2->IsImmediateOpnd());
  247. int size = dst->GetSize();
  248. Assert(size == 4 || size == 8);
  249. Assert(size == src1->GetSize());
  250. int64 immediate = src2->GetImmediateValue(instr->m_func);
  251. if (size == 8)
  252. {
  253. return imm64(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src1->AsRegOpnd()), ULONG64(immediate));
  254. }
  255. else
  256. {
  257. return imm32(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src1->AsRegOpnd()), ULONG(immediate));
  258. }
  259. }
  260. template<typename _RegFunc32, typename _RegFunc64, typename _ImmFunc32, typename _ImmFunc64>
  261. int EncoderMD::EmitOp3RegisterOrImmediate(Arm64CodeEmitter &Emitter, IR::Instr* instr, _RegFunc32 reg32, _RegFunc64 reg64, _ImmFunc32 imm32, _ImmFunc64 imm64)
  262. {
  263. if (instr->GetSrc2()->IsImmediateOpnd())
  264. {
  265. return this->EmitOp3Immediate(Emitter, instr, imm32, imm64);
  266. }
  267. else if (instr->GetSrc2()->IsRegOpnd())
  268. {
  269. return this->EmitOp3Register(Emitter, instr, reg32, reg64);
  270. }
  271. else
  272. {
  273. AssertMsg(false, "EmitOp3RegisterOrImmediate failed to encode");
  274. return 0;
  275. }
  276. }
  277. template<typename _RegFunc32, typename _RegFunc64, typename _ImmFunc32, typename _ImmFunc64>
  278. int EncoderMD::EmitOp3RegisterOrImmediateExtendSPReg(Arm64CodeEmitter &Emitter, IR::Instr* instr, _RegFunc32 reg32, _RegFunc64 reg64, _ImmFunc32 imm32, _ImmFunc64 imm64)
  279. {
  280. // if we have two regopnds as sources, then we need to be careful
  281. if (instr->GetSrc1()->IsRegOpnd() && instr->GetSrc2()->IsRegOpnd())
  282. {
  283. IR::RegOpnd* src1 = instr->GetSrc1()->AsRegOpnd();
  284. IR::RegOpnd* src2 = instr->GetSrc2()->AsRegOpnd();
  285. IR::RegOpnd* dst = instr->GetDst()->AsRegOpnd();
  286. AssertMsg(!(src1->GetReg() == RegSP && src2->GetReg() == RegSP), "Tried to encode an add or sub that used RegSP as both sources - tighten legalization restrictions!");
  287. // We need to swap the parameters if
  288. // 1. src2 is RegSP
  289. // 2. src1 is RegZR and dst is RegSP
  290. // This is because the valid instruction forms are
  291. // add Rd, Rs, Rw_SFT
  292. // add Rd|SP, Rs|SP, Rw_EXT
  293. // and the encoding for SP is the same as the encoding for ZR
  294. if (src2->GetReg() == RegSP || (src1->GetReg() == RegZR && dst->GetReg() == RegSP))
  295. {
  296. // We can only really do this for addition, so we failfast if it's a sub
  297. AssertOrFailFastMsg(instr->m_opcode != Js::OpCode::SUB && instr->m_opcode != Js::OpCode::SUBS, "Tried to encode a SUB/SUBS with RegSP as the second operand or as the dest with RegZR in first operand - tighten legalization restrictions!");
  298. // We need to swap the arguments
  299. instr->UnlinkSrc1();
  300. instr->UnlinkSrc2();
  301. instr->SetSrc1(src2);
  302. instr->SetSrc2(src1);
  303. IR::RegOpnd* temp = src1;
  304. src1 = src2;
  305. src2 = temp;
  306. }
  307. // The extended form of the instruction takes RegSP for dst and src1 and RegZR for src2
  308. if (src1->GetReg() == RegSP || instr->GetDst()->AsRegOpnd()->GetReg() == RegSP)
  309. {
  310. // EXTEND_UXTX effectively means LSL here, just that LSL is a shift, not an extend, operation
  311. // Regardless, we do it by 0, so it should just be directly using the register
  312. return this->EmitOp3RegisterShifted(Emitter, instr, EXTEND_UXTX, 0, reg32, reg64);
  313. }
  314. }
  315. return EmitOp3RegisterOrImmediate(Emitter, instr, reg32, reg64, imm32, imm64);
  316. }
  317. int EncoderMD::EmitPrefetch(Arm64CodeEmitter &Emitter, IR::Instr* instr, IR::Opnd* memOpnd)
  318. {
  319. Assert(memOpnd->IsIndirOpnd() || memOpnd->IsSymOpnd());
  320. ARM64_REGISTER indexReg;
  321. ARM64_REGISTER baseReg;
  322. BYTE indexScale;
  323. int32 offset;
  324. if (DecodeMemoryOpnd(memOpnd, baseReg, indexReg, indexScale, offset))
  325. {
  326. return EmitPrfmRegister(Emitter, baseReg, Arm64RegisterParam(indexReg, SHIFT_LSL, indexScale));
  327. }
  328. else
  329. {
  330. return EmitPrfmOffset(Emitter, baseReg, offset);
  331. }
  332. }
  333. template<typename _RegFunc8, typename _RegFunc16, typename _RegFunc32, typename _RegFunc64, typename _OffFunc8, typename _OffFunc16, typename _OffFunc32, typename _OffFunc64>
  334. int EncoderMD::EmitLoadStore(Arm64CodeEmitter &Emitter, IR::Instr* instr, IR::Opnd* memOpnd, IR::Opnd* srcDstOpnd, _RegFunc8 reg8, _RegFunc16 reg16, _RegFunc32 reg32, _RegFunc64 reg64, _OffFunc8 off8, _OffFunc16 off16, _OffFunc32 off32, _OffFunc64 off64)
  335. {
  336. Assert(srcDstOpnd->IsRegOpnd());
  337. Assert(memOpnd->IsIndirOpnd() || memOpnd->IsSymOpnd());
  338. int size = memOpnd->GetSize();
  339. Assert(size == 1 || size == 2 || size == 4 || size == 8);
  340. ARM64_REGISTER indexReg;
  341. ARM64_REGISTER baseReg;
  342. BYTE indexScale;
  343. int32 offset;
  344. if (DecodeMemoryOpnd(memOpnd, baseReg, indexReg, indexScale, offset))
  345. {
  346. if (size == 8)
  347. {
  348. return reg64(Emitter, this->GetRegEncode(srcDstOpnd->AsRegOpnd()), baseReg, Arm64RegisterParam(indexReg, SHIFT_LSL, indexScale));
  349. }
  350. else if (size == 4)
  351. {
  352. return reg32(Emitter, this->GetRegEncode(srcDstOpnd->AsRegOpnd()), baseReg, Arm64RegisterParam(indexReg, SHIFT_LSL, indexScale));
  353. }
  354. else if (size == 2)
  355. {
  356. return reg16(Emitter, this->GetRegEncode(srcDstOpnd->AsRegOpnd()), baseReg, Arm64RegisterParam(indexReg, SHIFT_LSL, indexScale));
  357. }
  358. else
  359. {
  360. return reg8(Emitter, this->GetRegEncode(srcDstOpnd->AsRegOpnd()), baseReg, Arm64RegisterParam(indexReg, SHIFT_LSL, indexScale));
  361. }
  362. }
  363. else
  364. {
  365. if (size == 8)
  366. {
  367. return off64(Emitter, this->GetRegEncode(srcDstOpnd->AsRegOpnd()), baseReg, offset);
  368. }
  369. else if (size == 4)
  370. {
  371. return off32(Emitter, this->GetRegEncode(srcDstOpnd->AsRegOpnd()), baseReg, offset);
  372. }
  373. else if (size == 2)
  374. {
  375. return off16(Emitter, this->GetRegEncode(srcDstOpnd->AsRegOpnd()), baseReg, offset);
  376. }
  377. else
  378. {
  379. return off8(Emitter, this->GetRegEncode(srcDstOpnd->AsRegOpnd()), baseReg, offset);
  380. }
  381. }
  382. }
  383. template<typename _OffFunc32, typename _OffFunc64>
  384. int EncoderMD::EmitLoadStorePair(Arm64CodeEmitter &Emitter, IR::Instr* instr, IR::Opnd* memOpnd, IR::Opnd* srcDst1Opnd, IR::Opnd* srcDst2Opnd, _OffFunc32 off32, _OffFunc64 off64)
  385. {
  386. Assert(memOpnd->IsIndirOpnd() || memOpnd->IsSymOpnd());
  387. int size = memOpnd->GetSize();
  388. Assert(size == 4 || size == 8);
  389. ARM64_REGISTER indexReg;
  390. ARM64_REGISTER baseReg;
  391. BYTE indexScale;
  392. int32 offset;
  393. if (DecodeMemoryOpnd(memOpnd, baseReg, indexReg, indexScale, offset))
  394. {
  395. // Should never get here
  396. AssertMsg(false, "EmitLoadStorePair failed to encode");
  397. return 0;
  398. }
  399. else
  400. {
  401. if (size == 8)
  402. {
  403. return off64(Emitter, this->GetRegEncode(srcDst1Opnd->AsRegOpnd()), this->GetRegEncode(srcDst2Opnd->AsRegOpnd()), baseReg, offset);
  404. }
  405. else
  406. {
  407. return off32(Emitter, this->GetRegEncode(srcDst1Opnd->AsRegOpnd()), this->GetRegEncode(srcDst2Opnd->AsRegOpnd()), baseReg, offset);
  408. }
  409. }
  410. }
  411. template<typename _Emitter>
  412. int EncoderMD::EmitUnconditionalBranch(Arm64CodeEmitter &Emitter, IR::Instr* instr, _Emitter emitter)
  413. {
  414. ArmBranchLinker Linker;
  415. EncodeReloc::New(&m_relocList, RelocTypeBranch26, m_pc, instr->AsBranchInstr()->GetTarget(), m_encoder->m_tempAlloc);
  416. Linker.SetTarget(Emitter);
  417. return emitter(Emitter, Linker);
  418. }
  419. int EncoderMD::EmitConditionalBranch(Arm64CodeEmitter &Emitter, IR::Instr* instr, int condition)
  420. {
  421. ArmBranchLinker Linker;
  422. EncodeReloc::New(&m_relocList, RelocTypeBranch19, m_pc, instr->AsBranchInstr()->GetTarget(), m_encoder->m_tempAlloc);
  423. Linker.SetTarget(Emitter);
  424. return EmitBranch(Emitter, Linker, condition);
  425. }
  426. template<typename _Emitter, typename _Emitter64>
  427. int EncoderMD::EmitCompareAndBranch(Arm64CodeEmitter &Emitter, IR::Instr* instr, _Emitter emitter, _Emitter64 emitter64)
  428. {
  429. IR::Opnd* src1 = instr->GetSrc1();
  430. Assert(src1->IsRegOpnd());
  431. int size = src1->GetSize();
  432. Assert(size == 4 || size == 8);
  433. ArmBranchLinker Linker;
  434. EncodeReloc::New(&m_relocList, RelocTypeBranch19, m_pc, instr->AsBranchInstr()->GetTarget(), m_encoder->m_tempAlloc);
  435. Linker.SetTarget(Emitter);
  436. if (size == 8)
  437. {
  438. return emitter64(Emitter, this->GetRegEncode(src1->AsRegOpnd()), Linker);
  439. }
  440. else
  441. {
  442. return emitter(Emitter, this->GetRegEncode(src1->AsRegOpnd()), Linker);
  443. }
  444. }
  445. template<typename _Emitter>
  446. int EncoderMD::EmitTestAndBranch(Arm64CodeEmitter &Emitter, IR::Instr* instr, _Emitter emitter)
  447. {
  448. IR::Opnd* src1 = instr->GetSrc1();
  449. IR::Opnd* src2 = instr->GetSrc2();
  450. Assert(src1->IsRegOpnd());
  451. Assert(src2->IsImmediateOpnd());
  452. ArmBranchLinker Linker;
  453. EncodeReloc::New(&m_relocList, RelocTypeBranch14, m_pc, instr->AsBranchInstr()->GetTarget(), m_encoder->m_tempAlloc);
  454. Linker.SetTarget(Emitter);
  455. int64 immediate = src2->GetImmediateValue(instr->m_func);
  456. Assert(immediate >= 0 && immediate < 64);
  457. return emitter(Emitter, this->GetRegEncode(src1->AsRegOpnd()), ULONG(immediate), Linker);
  458. }
  459. template<typename _Emitter, typename _Emitter64>
  460. int EncoderMD::EmitMovConstant(Arm64CodeEmitter &Emitter, IR::Instr *instr, _Emitter emitter, _Emitter64 emitter64)
  461. {
  462. IR::Opnd* dst = instr->GetDst();
  463. IR::Opnd* src1 = instr->GetSrc1();
  464. IR::Opnd* src2 = instr->GetSrc2();
  465. Assert(dst->IsRegOpnd());
  466. Assert(src1->IsImmediateOpnd() || src1->IsLabelOpnd());
  467. Assert(src2->IsIntConstOpnd());
  468. int size = dst->GetSize();
  469. Assert(size == 4 || size == 8);
  470. uint32 shift = src2->AsIntConstOpnd()->AsUint32();
  471. Assert(shift < 32 || size == 8);
  472. Assert(shift == 0 || shift == 16 || (size == 8 && (shift == 32 || shift == 48)));
  473. IntConstType immediate = 0;
  474. if (src1->IsImmediateOpnd())
  475. {
  476. immediate = src1->GetImmediateValue(instr->m_func);
  477. }
  478. else
  479. {
  480. Assert(src1->IsLabelOpnd());
  481. IR::LabelInstr* labelInstr = src1->AsLabelOpnd()->GetLabel();
  482. if (labelInstr->m_isDataLabel)
  483. {
  484. // If the label is a data label, we don't know the label address yet so handle it as a reloc.
  485. EncodeReloc::New(&m_relocList, RelocTypeLabelImmed, m_pc, labelInstr, m_encoder->m_tempAlloc);
  486. immediate = 0;
  487. }
  488. else
  489. {
  490. // Here the LabelOpnd's offset is a post-lower immediate value; we need
  491. // to mask in just the part indicated by our own shift amount, and send
  492. // that along as our immediate load value.
  493. uintptr_t fullvalue = labelInstr->GetOffset();
  494. immediate = (fullvalue >> shift) & 0xffff;
  495. }
  496. }
  497. Assert((immediate & 0xFFFF) == immediate);
  498. if (size == 8)
  499. {
  500. return emitter64(Emitter, this->GetRegEncode(dst->AsRegOpnd()), ULONG(immediate), shift);
  501. }
  502. else
  503. {
  504. return emitter(Emitter, this->GetRegEncode(dst->AsRegOpnd()), ULONG(immediate), shift);
  505. }
  506. }
  507. template<typename _Emitter, typename _Emitter64>
  508. int EncoderMD::EmitBitfield(Arm64CodeEmitter &Emitter, IR::Instr *instr, _Emitter emitter, _Emitter64 emitter64)
  509. {
  510. IR::Opnd* dst = instr->GetDst();
  511. IR::Opnd* src1 = instr->GetSrc1();
  512. IR::Opnd* src2 = instr->GetSrc2();
  513. Assert(dst->IsRegOpnd());
  514. Assert(src1->IsRegOpnd());
  515. Assert(src2->IsImmediateOpnd());
  516. int size = dst->GetSize();
  517. Assert(size == 4 || size == 8);
  518. Assert(size == src1->GetSize());
  519. IntConstType immediate = src2->GetImmediateValue(instr->m_func);
  520. int start = immediate & 0x3f;
  521. int length = (immediate >> 16) & 0x3f;
  522. Assert(start >= 0 && start < 8 * size);
  523. Assert(length >= 0 && length < 8 * size);
  524. if (size == 8)
  525. {
  526. return emitter64(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src1->AsRegOpnd()), start, length);
  527. }
  528. else
  529. {
  530. return emitter(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src1->AsRegOpnd()), start, length);
  531. }
  532. }
  533. template<typename _Emitter, typename _Emitter64>
  534. int EncoderMD::EmitConditionalSelect(Arm64CodeEmitter &Emitter, IR::Instr *instr, int condition, _Emitter emitter, _Emitter64 emitter64)
  535. {
  536. IR::Opnd* dst = instr->GetDst();
  537. IR::Opnd* src1 = instr->GetSrc1();
  538. IR::Opnd* src2 = instr->GetSrc2();
  539. Assert(dst->IsRegOpnd());
  540. Assert(src1->IsRegOpnd());
  541. Assert(src2->IsRegOpnd());
  542. int size = dst->GetSize();
  543. Assert(size == 4 || size == 8);
  544. Assert(size == src1->GetSize());
  545. Assert(size == src2->GetSize());
  546. if (size == 8)
  547. {
  548. return emitter64(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src1->AsRegOpnd()), this->GetRegEncode(src2->AsRegOpnd()), condition);
  549. }
  550. else
  551. {
  552. return emitter(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src1->AsRegOpnd()), this->GetRegEncode(src2->AsRegOpnd()), condition);
  553. }
  554. }
  555. template<typename _Emitter>
  556. int EncoderMD::EmitOp2FpRegister(Arm64CodeEmitter &Emitter, IR::Instr *instr, _Emitter emitter)
  557. {
  558. return EmitOp2FpRegister(Emitter, instr->GetDst(), instr->GetSrc1(), emitter);
  559. }
  560. template<typename _Emitter>
  561. int EncoderMD::EmitOp2FpRegister(Arm64CodeEmitter &Emitter, IR::Opnd* opnd1, IR::Opnd* opnd2, _Emitter emitter)
  562. {
  563. Assert(opnd1->IsRegOpnd());
  564. Assert(opnd2->IsRegOpnd());
  565. int size = opnd1->GetSize();
  566. Assert(size == 4 || size == 8);
  567. Assert(size == opnd2->GetSize());
  568. NEON_SIZE neonSize = (size == 8) ? SIZE_1D : SIZE_1S;
  569. return emitter(Emitter, this->GetFloatRegEncode(opnd1->AsRegOpnd()), this->GetFloatRegEncode(opnd2->AsRegOpnd()), neonSize);
  570. }
  571. template<typename _Emitter>
  572. int EncoderMD::EmitOp3FpRegister(Arm64CodeEmitter &Emitter, IR::Instr *instr, _Emitter emitter)
  573. {
  574. IR::Opnd* dst = instr->GetDst();
  575. IR::Opnd* src1 = instr->GetSrc1();
  576. IR::Opnd* src2 = instr->GetSrc2();
  577. Assert(dst->IsRegOpnd());
  578. Assert(src1->IsRegOpnd());
  579. Assert(src2->IsRegOpnd());
  580. int size = dst->GetSize();
  581. Assert(size == 4 || size == 8);
  582. Assert(size == src1->GetSize());
  583. Assert(size == src2->GetSize());
  584. NEON_SIZE neonSize = (size == 8) ? SIZE_1D : SIZE_1S;
  585. return emitter(Emitter, this->GetFloatRegEncode(dst->AsRegOpnd()), this->GetFloatRegEncode(src1->AsRegOpnd()), this->GetFloatRegEncode(src2->AsRegOpnd()), neonSize);
  586. }
  587. template<typename _LoadStoreFunc>
  588. int EncoderMD::EmitLoadStoreFp(Arm64CodeEmitter &Emitter, IR::Instr* instr, IR::Opnd* memOpnd, IR::Opnd* srcDstOpnd, _LoadStoreFunc loadStore)
  589. {
  590. Assert(srcDstOpnd->IsRegOpnd());
  591. Assert(memOpnd->IsIndirOpnd() || memOpnd->IsSymOpnd());
  592. int size = memOpnd->GetSize();
  593. Assert(size == 4 || size == 8);
  594. ARM64_REGISTER indexReg;
  595. ARM64_REGISTER baseReg;
  596. BYTE indexScale;
  597. int32 offset;
  598. if (DecodeMemoryOpnd(memOpnd, baseReg, indexReg, indexScale, offset))
  599. {
  600. // Should never get here
  601. AssertMsg(false, "EmitLoadStoreFp failed to encode");
  602. return 0;
  603. }
  604. else
  605. {
  606. return loadStore(Emitter, this->GetFloatRegEncode(srcDstOpnd->AsRegOpnd()), (size == 8) ? SIZE_1D : SIZE_1S, baseReg, offset);
  607. }
  608. }
  609. template<typename _LoadStoreFunc>
  610. int EncoderMD::EmitLoadStoreFpPair(Arm64CodeEmitter &Emitter, IR::Instr* instr, IR::Opnd* memOpnd, IR::Opnd* srcDst1Opnd, IR::Opnd* srcDst2Opnd, _LoadStoreFunc loadStore)
  611. {
  612. Assert(memOpnd->IsIndirOpnd() || memOpnd->IsSymOpnd());
  613. int size = memOpnd->GetSize();
  614. Assert(size == 4 || size == 8);
  615. ARM64_REGISTER indexReg;
  616. ARM64_REGISTER baseReg;
  617. BYTE indexScale;
  618. int32 offset;
  619. if (DecodeMemoryOpnd(memOpnd, baseReg, indexReg, indexScale, offset))
  620. {
  621. // Should never get here
  622. AssertMsg(false, "EmitLoadStoreFpPair failed to encode");
  623. return 0;
  624. }
  625. else
  626. {
  627. return loadStore(Emitter, this->GetFloatRegEncode(srcDst1Opnd->AsRegOpnd()), this->GetFloatRegEncode(srcDst2Opnd->AsRegOpnd()), (size == 8) ? SIZE_1D : SIZE_1S, baseReg, offset);
  628. }
  629. }
  630. template<typename _Int32Func, typename _Uint32Func, typename _Int64Func, typename _Uint64Func>
  631. int EncoderMD::EmitConvertToInt(Arm64CodeEmitter &Emitter, IR::Instr* instr, _Int32Func toInt32, _Uint32Func toUint32, _Int64Func toInt64, _Uint64Func toUint64)
  632. {
  633. IR::Opnd* dst = instr->GetDst();
  634. IR::Opnd* src1 = instr->GetSrc1();
  635. Assert(dst->IsRegOpnd());
  636. Assert(!dst->IsFloat());
  637. Assert(src1->IsRegOpnd());
  638. Assert(src1->IsFloat());
  639. DebugOnly(int size = dst->GetSize());
  640. Assert(size == 4 || size == 8);
  641. int srcSize = src1->GetSize();
  642. Assert(srcSize == 4 || srcSize == 8);
  643. if (dst->GetType() == TyInt32)
  644. {
  645. return toInt32(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetFloatRegEncode(src1->AsRegOpnd()), (srcSize == 8) ? SIZE_1D : SIZE_1S);
  646. }
  647. else if (dst->GetType() == TyUint32)
  648. {
  649. return toUint32(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetFloatRegEncode(src1->AsRegOpnd()), (srcSize == 8) ? SIZE_1D : SIZE_1S);
  650. }
  651. else if (dst->GetType() == TyInt64)
  652. {
  653. return toInt64(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetFloatRegEncode(src1->AsRegOpnd()), (srcSize == 8) ? SIZE_1D : SIZE_1S);
  654. }
  655. else if (dst->GetType() == TyUint64)
  656. {
  657. return toUint64(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetFloatRegEncode(src1->AsRegOpnd()), (srcSize == 8) ? SIZE_1D : SIZE_1S);
  658. }
  659. // Shouldn't get here
  660. AssertMsg(false, "EmitConvertToInt failed to encode");
  661. return 0;
  662. }
  663. template<typename _Emitter>
  664. int EncoderMD::EmitConditionalSelectFp(Arm64CodeEmitter &Emitter, IR::Instr *instr, int condition, _Emitter emitter)
  665. {
  666. IR::Opnd* dst = instr->GetDst();
  667. IR::Opnd* src1 = instr->GetSrc1();
  668. IR::Opnd* src2 = instr->GetSrc2();
  669. Assert(dst->IsRegOpnd());
  670. Assert(src1->IsRegOpnd());
  671. Assert(src2->IsRegOpnd());
  672. int size = dst->GetSize();
  673. Assert(size == 4 || size == 8);
  674. Assert(size == src1->GetSize());
  675. Assert(size == src2->GetSize());
  676. return emitter(Emitter, this->GetFloatRegEncode(dst->AsRegOpnd()), this->GetFloatRegEncode(src1->AsRegOpnd()), this->GetRegEncode(src2->AsRegOpnd()), condition, (size == 8) ? SIZE_1D : SIZE_1S);
  677. }
  678. //---------------------------------------------------------------------------
  679. //
  680. // GenerateEncoding()
  681. //
  682. // generates the encoding for the specified tuple/form by applying the
  683. // associated encoding steps
  684. //
  685. //---------------------------------------------------------------------------
  686. ULONG
  687. EncoderMD::GenerateEncoding(IR::Instr* instr, BYTE *pc)
  688. {
  689. Arm64LocalCodeEmitter<1> Emitter;
  690. IR::Opnd* dst = 0;
  691. IR::Opnd* src1 = 0;
  692. IR::Opnd* src2 = 0;
  693. int bytes = 0;
  694. int size;
  695. switch (instr->m_opcode)
  696. {
  697. case Js::OpCode::ADD:
  698. bytes = this->EmitOp3RegisterOrImmediateExtendSPReg(Emitter, instr, EmitAddRegister, EmitAddRegister64, EmitAddImmediate, EmitAddImmediate64);
  699. break;
  700. case Js::OpCode::ADDS:
  701. // ADDS and SUBS have no valid encoding where dst == RegSP
  702. Assert(instr->GetDst()->AsRegOpnd()->GetReg() != RegSP);
  703. bytes = this->EmitOp3RegisterOrImmediateExtendSPReg(Emitter, instr, EmitAddsRegister, EmitAddsRegister64, EmitAddsImmediate, EmitAddsImmediate64);
  704. break;
  705. case Js::OpCode::ADR:
  706. dst = instr->GetDst();
  707. src1 = instr->GetSrc1();
  708. Assert(dst->IsRegOpnd());
  709. Assert(src1->IsLabelOpnd());
  710. Assert(dst->GetSize() == 8);
  711. Assert(!src1->AsLabelOpnd()->GetLabel()->isInlineeEntryInstr);
  712. EncodeReloc::New(&m_relocList, RelocTypeLabelAdr, m_pc, src1->AsLabelOpnd()->GetLabel(), m_encoder->m_tempAlloc);
  713. bytes = EmitAdr(Emitter, this->GetRegEncode(dst->AsRegOpnd()), 0);
  714. break;
  715. case Js::OpCode::AND:
  716. bytes = this->EmitOp3RegisterOrImmediate(Emitter, instr, EmitAndRegister, EmitAndRegister64, EmitAndImmediate, EmitAndImmediate64);
  717. break;
  718. case Js::OpCode::ANDS:
  719. bytes = this->EmitOp3RegisterOrImmediate(Emitter, instr, EmitAndsRegister, EmitAndsRegister64, EmitAndsImmediate, EmitAndsImmediate64);
  720. break;
  721. case Js::OpCode::ASR:
  722. bytes = this->EmitOp3RegisterOrImmediate(Emitter, instr, EmitAsrRegister, EmitAsrRegister64, EmitAsrImmediate, EmitAsrImmediate64);
  723. break;
  724. case Js::OpCode::B:
  725. bytes = this->EmitConditionalBranch(Emitter, instr, COND_AL);
  726. break;
  727. case Js::OpCode::BFI:
  728. bytes = this->EmitBitfield(Emitter, instr, EmitBfi, EmitBfi64);
  729. break;
  730. case Js::OpCode::BFXIL:
  731. bytes = this->EmitBitfield(Emitter, instr, EmitBfxil, EmitBfxil64);
  732. break;
  733. // ARM64_WORKITEM: Legalizer needs to convert BIC with immediate to AND with inverted immediate
  734. case Js::OpCode::BIC:
  735. bytes = this->EmitOp3Register(Emitter, instr, EmitBicRegister, EmitBicRegister64);
  736. break;
  737. case Js::OpCode::BL:
  738. bytes = this->EmitUnconditionalBranch(Emitter, instr, EmitBl);
  739. break;
  740. case Js::OpCode::BR:
  741. bytes = this->EmitOp1Register64(Emitter, instr, EmitBr);
  742. break;
  743. case Js::OpCode::BLR:
  744. bytes = this->EmitOp1Register64(Emitter, instr, EmitBlr);
  745. break;
  746. case Js::OpCode::BEQ:
  747. bytes = this->EmitConditionalBranch(Emitter, instr, COND_EQ);
  748. break;
  749. case Js::OpCode::BNE:
  750. bytes = this->EmitConditionalBranch(Emitter, instr, COND_NE);
  751. break;
  752. case Js::OpCode::BLT:
  753. bytes = this->EmitConditionalBranch(Emitter, instr, COND_LT);
  754. break;
  755. case Js::OpCode::BLE:
  756. bytes = this->EmitConditionalBranch(Emitter, instr, COND_LE);
  757. break;
  758. case Js::OpCode::BGT:
  759. bytes = this->EmitConditionalBranch(Emitter, instr, COND_GT);
  760. break;
  761. case Js::OpCode::BGE:
  762. bytes = this->EmitConditionalBranch(Emitter, instr, COND_GE);
  763. break;
  764. case Js::OpCode::BCS:
  765. bytes = this->EmitConditionalBranch(Emitter, instr, COND_CS);
  766. break;
  767. case Js::OpCode::BCC:
  768. bytes = this->EmitConditionalBranch(Emitter, instr, COND_CC);
  769. break;
  770. case Js::OpCode::BHI:
  771. bytes = this->EmitConditionalBranch(Emitter, instr, COND_HI);
  772. break;
  773. case Js::OpCode::BLS:
  774. bytes = this->EmitConditionalBranch(Emitter, instr, COND_LS);
  775. break;
  776. case Js::OpCode::BMI:
  777. bytes = this->EmitConditionalBranch(Emitter, instr, COND_MI);
  778. break;
  779. case Js::OpCode::BPL:
  780. bytes = this->EmitConditionalBranch(Emitter, instr, COND_PL);
  781. break;
  782. case Js::OpCode::BVS:
  783. bytes = this->EmitConditionalBranch(Emitter, instr, COND_VS);
  784. break;
  785. case Js::OpCode::BVC:
  786. bytes = this->EmitConditionalBranch(Emitter, instr, COND_VC);
  787. break;
  788. case Js::OpCode::CBZ:
  789. bytes = this->EmitCompareAndBranch(Emitter, instr, EmitCbz, EmitCbz64);
  790. break;
  791. case Js::OpCode::CBNZ:
  792. bytes = this->EmitCompareAndBranch(Emitter, instr, EmitCbnz, EmitCbnz64);
  793. break;
  794. case Js::OpCode::CLZ:
  795. bytes = this->EmitOp2Register(Emitter, instr, EmitClz, EmitClz64);
  796. break;
  797. // Legalizer should convert this to SUBS before getting here
  798. case Js::OpCode::CMP:
  799. Assert(false);
  800. break;
  801. // Legalizer should convert this to ADDS before getting here
  802. case Js::OpCode::CMN:
  803. Assert(false);
  804. break;
  805. case Js::OpCode::CSELEQ:
  806. bytes = this->EmitConditionalSelect(Emitter, instr, COND_EQ, EmitCsel, EmitCsel64);
  807. break;
  808. case Js::OpCode::CSELNE:
  809. bytes = this->EmitConditionalSelect(Emitter, instr, COND_NE, EmitCsel, EmitCsel64);
  810. break;
  811. case Js::OpCode::CSELLT:
  812. bytes = this->EmitConditionalSelect(Emitter, instr, COND_LT, EmitCsel, EmitCsel64);
  813. break;
  814. case Js::OpCode::CSNEGPL:
  815. bytes = this->EmitConditionalSelect(Emitter, instr, COND_PL, EmitCsneg, EmitCsneg64);
  816. break;
  817. case Js::OpCode::CMP_SXTW:
  818. src1 = instr->GetSrc1();
  819. src2 = instr->GetSrc2();
  820. Assert(instr->GetDst() == nullptr);
  821. Assert(src1->IsRegOpnd());
  822. Assert(src2->IsRegOpnd());
  823. size = src1->GetSize();
  824. Assert(size == 8);
  825. Assert(size == src2->GetSize());
  826. bytes = EmitSubsRegister64(Emitter, ARMREG_ZR, this->GetRegEncode(src1->AsRegOpnd()), Arm64RegisterParam(this->GetRegEncode(src2->AsRegOpnd()), EXTEND_SXTW, 0));
  827. break;
  828. case Js::OpCode::DEBUGBREAK:
  829. bytes = EmitDebugBreak(Emitter);
  830. break;
  831. case Js::OpCode::EOR:
  832. bytes = this->EmitOp3RegisterOrImmediate(Emitter, instr, EmitEorRegister, EmitEorRegister64, EmitEorImmediate, EmitEorImmediate64);
  833. break;
  834. case Js::OpCode::EOR_ASR31:
  835. bytes = this->EmitOp3RegisterShifted(Emitter, instr, SHIFT_ASR, 63, EmitEorRegister, EmitEorRegister64);
  836. break;
  837. // Legalizer should convert these into MOVZ/MOVN/MOVK
  838. case Js::OpCode::LDIMM:
  839. Assert(false);
  840. break;
  841. case Js::OpCode::LDR:
  842. Assert(instr->GetDst()->GetSize() <= instr->GetSrc1()->GetSize() || instr->GetSrc1()->IsUnsigned());
  843. bytes = this->EmitLoadStore(Emitter, instr, instr->GetSrc1(), instr->GetDst(), EmitLdrbRegister, EmitLdrhRegister, EmitLdrRegister, EmitLdrRegister64, EmitLdrbOffset, EmitLdrhOffset, EmitLdrOffset, EmitLdrOffset64);
  844. break;
  845. case Js::OpCode::LDRS:
  846. Assert(instr->GetDst()->GetSize() <= instr->GetSrc1()->GetSize() || instr->GetSrc1()->IsSigned());
  847. bytes = this->EmitLoadStore(Emitter, instr, instr->GetSrc1(), instr->GetDst(), EmitLdrsbRegister, EmitLdrshRegister, EmitLdrswRegister64, EmitLdrRegister64, EmitLdrsbOffset, EmitLdrshOffset, EmitLdrswOffset64, EmitLdrOffset64);
  848. break;
  849. // Note: src2 is really the second destination register, due to limitations of IR::Instr
  850. case Js::OpCode::LDP:
  851. bytes = this->EmitLoadStorePair(Emitter, instr, instr->GetSrc1(), instr->GetDst(), instr->GetSrc2(), EmitLdpOffset, EmitLdpOffset64);
  852. break;
  853. // Note: src2 is really the second destination register, due to limitations of IR::Instr
  854. case Js::OpCode::LDP_POST:
  855. bytes = this->EmitLoadStorePair(Emitter, instr, instr->GetSrc1(), instr->GetDst(), instr->GetSrc2(), EmitLdpOffsetPostIndex, EmitLdpOffsetPostIndex64);
  856. break;
  857. // Legalizer should convert this to MOV/ADD before getting here
  858. case Js::OpCode::LEA:
  859. Assert(false);
  860. break;
  861. case Js::OpCode::LSL:
  862. bytes = this->EmitOp3RegisterOrImmediate(Emitter, instr, EmitLslRegister, EmitLslRegister64, EmitLslImmediate, EmitLslImmediate64);
  863. break;
  864. case Js::OpCode::LSR:
  865. bytes = this->EmitOp3RegisterOrImmediate(Emitter, instr, EmitLsrRegister, EmitLsrRegister64, EmitLsrImmediate, EmitLsrImmediate64);
  866. break;
  867. case Js::OpCode::MOV_TRUNC:
  868. Assert(instr->GetDst()->GetSize() == 4);
  869. Assert(instr->GetSrc1()->GetSize() == 4);
  870. // fall through.
  871. case Js::OpCode::MOV:
  872. bytes = this->EmitOp2Register(Emitter, instr, EmitMovRegister, EmitMovRegister64);
  873. break;
  874. case Js::OpCode::MOVK:
  875. bytes = this->EmitMovConstant(Emitter, instr, EmitMovk, EmitMovk64);
  876. break;
  877. case Js::OpCode::MOVN:
  878. bytes = this->EmitMovConstant(Emitter, instr, EmitMovn, EmitMovn64);
  879. break;
  880. case Js::OpCode::MOVZ:
  881. bytes = this->EmitMovConstant(Emitter, instr, EmitMovz, EmitMovz64);
  882. break;
  883. case Js::OpCode::MRS_FPCR:
  884. dst = instr->GetDst();
  885. Assert(dst->IsRegOpnd());
  886. Assert(dst->GetSize() == 4);
  887. bytes = EmitMrs(Emitter, this->GetRegEncode(dst->AsRegOpnd()), ARM64_FPCR);
  888. break;
  889. case Js::OpCode::MRS_FPSR:
  890. dst = instr->GetDst();
  891. Assert(dst->IsRegOpnd());
  892. Assert(dst->GetSize() == 4);
  893. bytes = EmitMrs(Emitter, this->GetRegEncode(dst->AsRegOpnd()), ARM64_FPSR);
  894. break;
  895. case Js::OpCode::MSR_FPCR:
  896. src1 = instr->GetSrc1();
  897. Assert(src1->IsRegOpnd());
  898. Assert(src1->GetSize() == 4);
  899. bytes = EmitMsr(Emitter, this->GetRegEncode(src1->AsRegOpnd()), ARM64_FPCR);
  900. break;
  901. case Js::OpCode::MSR_FPSR:
  902. src1 = instr->GetSrc1();
  903. Assert(src1->IsRegOpnd());
  904. Assert(src1->GetSize() == 4);
  905. bytes = EmitMsr(Emitter, this->GetRegEncode(src1->AsRegOpnd()), ARM64_FPSR);
  906. break;
  907. case Js::OpCode::MUL:
  908. bytes = this->EmitOp3Register(Emitter, instr, EmitMul, EmitMul64);
  909. break;
  910. case Js::OpCode::MVN:
  911. bytes = this->EmitOp2Register(Emitter, instr, EmitMvnRegister, EmitMvnRegister64);
  912. break;
  913. // SMULL dst, src1, src2. src1 and src2 are 32-bit. dst is 64-bit.
  914. case Js::OpCode::SMULL:
  915. dst = instr->GetDst();
  916. src1 = instr->GetSrc1();
  917. src2 = instr->GetSrc2();
  918. Assert(dst->IsRegOpnd());
  919. Assert(src1->IsRegOpnd());
  920. Assert(src2->IsRegOpnd());
  921. Assert(dst->GetSize() == 8);
  922. Assert(src1->GetSize() == 4);
  923. Assert(src2->GetSize() == 4);
  924. bytes = EmitSmull(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src1->AsRegOpnd()), this->GetRegEncode(src2->AsRegOpnd()));
  925. break;
  926. // SMADDL (SMLAL from ARM32) dst, dst, src1, src2. src1 and src2 are 32-bit. dst is 64-bit.
  927. case Js::OpCode::SMADDL:
  928. dst = instr->GetDst();
  929. src1 = instr->GetSrc1();
  930. src2 = instr->GetSrc2();
  931. Assert(dst->IsRegOpnd());
  932. Assert(src1->IsRegOpnd());
  933. Assert(src2->IsRegOpnd());
  934. bytes = EmitSmaddl(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src1->AsRegOpnd()), this->GetRegEncode(src2->AsRegOpnd()));
  935. break;
  936. // MSUB (MLS from ARM32) dst, src1, src2: Multiply and Subtract. We use 3 registers: dst = src1 - src2 * dst
  937. case Js::OpCode::MSUB:
  938. dst = instr->GetDst();
  939. src1 = instr->GetSrc1();
  940. src2 = instr->GetSrc2();
  941. Assert(dst->IsRegOpnd());
  942. Assert(src1->IsRegOpnd());
  943. Assert(src2->IsRegOpnd());
  944. bytes = EmitMsub(Emitter, this->GetRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src2->AsRegOpnd()), this->GetRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src1->AsRegOpnd()));
  945. break;
  946. case Js::OpCode::NOP:
  947. bytes = EmitNop(Emitter);
  948. break;
  949. case Js::OpCode::ORR:
  950. bytes = this->EmitOp3RegisterOrImmediate(Emitter, instr, EmitOrrRegister, EmitOrrRegister64, EmitOrrImmediate, EmitOrrImmediate64);
  951. break;
  952. case Js::OpCode::PLD:
  953. bytes = this->EmitPrefetch(Emitter, instr, instr->GetSrc1());
  954. break;
  955. case Js::OpCode::RET:
  956. bytes = this->EmitOp1Register64(Emitter, instr, EmitRet);
  957. break;
  958. // Legalizer should convert this to SDIV/MSUB before getting here
  959. case Js::OpCode::REM:
  960. Assert(false);
  961. break;
  962. case Js::OpCode::SBFX:
  963. bytes = this->EmitBitfield(Emitter, instr, EmitSbfx, EmitSbfx64);
  964. break;
  965. case Js::OpCode::SDIV:
  966. bytes = this->EmitOp3Register(Emitter, instr, EmitSdiv, EmitSdiv64);
  967. break;
  968. case Js::OpCode::STR:
  969. bytes = this->EmitLoadStore(Emitter, instr, instr->GetDst(), instr->GetSrc1(), EmitStrbRegister, EmitStrhRegister, EmitStrRegister, EmitStrRegister64, EmitStrbOffset, EmitStrhOffset, EmitStrOffset, EmitStrOffset64);
  970. break;
  971. case Js::OpCode::STP:
  972. bytes = this->EmitLoadStorePair(Emitter, instr, instr->GetDst(), instr->GetSrc1(), instr->GetSrc2(), EmitStpOffset, EmitStpOffset64);
  973. break;
  974. case Js::OpCode::STP_PRE:
  975. bytes = this->EmitLoadStorePair(Emitter, instr, instr->GetDst(), instr->GetSrc1(), instr->GetSrc2(), EmitStpOffsetPreIndex, EmitStpOffsetPreIndex64);
  976. break;
  977. case Js::OpCode::SUB:
  978. bytes = this->EmitOp3RegisterOrImmediateExtendSPReg(Emitter, instr, EmitSubRegister, EmitSubRegister64, EmitSubImmediate, EmitSubImmediate64);
  979. break;
  980. case Js::OpCode::SUBS:
  981. // ADDS and SUBS have no valid encoding where dst == RegSP
  982. Assert(instr->GetDst()->AsRegOpnd()->GetReg() != RegSP);
  983. bytes = this->EmitOp3RegisterOrImmediateExtendSPReg(Emitter, instr, EmitSubsRegister, EmitSubsRegister64, EmitSubsImmediate, EmitSubsImmediate64);
  984. break;
  985. case Js::OpCode::SUB_LSL4:
  986. bytes = this->EmitOp3RegisterShifted(Emitter, instr, EXTEND_UXTX, 4, EmitSubRegister, EmitSubRegister64);
  987. break;
  988. case Js::OpCode::TBZ:
  989. bytes = this->EmitTestAndBranch(Emitter, instr, EmitTbz);
  990. break;
  991. case Js::OpCode::TBNZ:
  992. bytes = this->EmitTestAndBranch(Emitter, instr, EmitTbnz);
  993. break;
  994. // Legalizer should convert this to ANDS before getting here
  995. case Js::OpCode::TST:
  996. Assert(false);
  997. break;
  998. case Js::OpCode::UBFX:
  999. bytes = this->EmitBitfield(Emitter, instr, EmitUbfx, EmitUbfx64);
  1000. break;
  1001. case Js::OpCode::FABS:
  1002. bytes = this->EmitOp2FpRegister(Emitter, instr, EmitNeonFabs);
  1003. break;
  1004. case Js::OpCode::FADD:
  1005. bytes = this->EmitOp3FpRegister(Emitter, instr, EmitNeonFadd);
  1006. break;
  1007. case Js::OpCode::FCMP:
  1008. bytes = this->EmitOp2FpRegister(Emitter, instr->GetSrc1(), instr->GetSrc2(), EmitNeonFcmp);
  1009. break;
  1010. case Js::OpCode::FCSELEQ:
  1011. bytes = this->EmitConditionalSelectFp(Emitter, instr, COND_EQ, EmitNeonFcsel);
  1012. break;
  1013. case Js::OpCode::FCSELNE:
  1014. bytes = this->EmitConditionalSelectFp(Emitter, instr, COND_NE, EmitNeonFcsel);
  1015. break;
  1016. case Js::OpCode::FCVT:
  1017. dst = instr->GetDst();
  1018. src1 = instr->GetSrc1();
  1019. Assert(dst->IsRegOpnd());
  1020. Assert(src1->IsRegOpnd());
  1021. Assert(dst->IsFloat());
  1022. size = dst->GetSize();
  1023. Assert(size == 4 || size == 8);
  1024. if (src1->IsFloat())
  1025. {
  1026. bytes = EmitNeonFcvt(Emitter, this->GetFloatRegEncode(dst->AsRegOpnd()), (size == 8) ? SIZE_1D : SIZE_1S, this->GetFloatRegEncode(src1->AsRegOpnd()), (src1->GetSize() == 8) ? SIZE_1D : SIZE_1S);
  1027. }
  1028. else if (src1->GetType() == TyInt32)
  1029. {
  1030. bytes = EmitNeonScvtf(Emitter, this->GetFloatRegEncode(dst->AsRegOpnd()), Arm64SimpleRegisterParam(this->GetRegEncode(src1->AsRegOpnd())), (size == 8) ? SIZE_1D : SIZE_1S);
  1031. }
  1032. else if (src1->GetType() == TyUint32)
  1033. {
  1034. bytes = EmitNeonUcvtf(Emitter, this->GetFloatRegEncode(dst->AsRegOpnd()), Arm64SimpleRegisterParam(this->GetRegEncode(src1->AsRegOpnd())), (size == 8) ? SIZE_1D : SIZE_1S);
  1035. }
  1036. else if (src1->GetType() == TyInt64)
  1037. {
  1038. bytes = EmitNeonScvtf64(Emitter, this->GetFloatRegEncode(dst->AsRegOpnd()), Arm64SimpleRegisterParam(this->GetRegEncode(src1->AsRegOpnd())), (size == 8) ? SIZE_1D : SIZE_1S);
  1039. }
  1040. else if (src1->GetType() == TyUint64)
  1041. {
  1042. bytes = EmitNeonUcvtf64(Emitter, this->GetFloatRegEncode(dst->AsRegOpnd()), Arm64SimpleRegisterParam(this->GetRegEncode(src1->AsRegOpnd())), (size == 8) ? SIZE_1D : SIZE_1S);
  1043. }
  1044. break;
  1045. case Js::OpCode::FCVTM:
  1046. bytes = this->EmitConvertToInt(Emitter, instr, EmitNeonFcvtmsGen, EmitNeonFcvtmuGen, EmitNeonFcvtmsGen64, EmitNeonFcvtmuGen64);
  1047. break;
  1048. case Js::OpCode::FCVTN:
  1049. bytes = this->EmitConvertToInt(Emitter, instr, EmitNeonFcvtnsGen, EmitNeonFcvtnuGen, EmitNeonFcvtnsGen64, EmitNeonFcvtnuGen64);
  1050. break;
  1051. case Js::OpCode::FCVTP:
  1052. bytes = this->EmitConvertToInt(Emitter, instr, EmitNeonFcvtpsGen, EmitNeonFcvtpuGen, EmitNeonFcvtpsGen64, EmitNeonFcvtpuGen64);
  1053. break;
  1054. case Js::OpCode::FCVTZ:
  1055. bytes = this->EmitConvertToInt(Emitter, instr, EmitNeonFcvtzsGen, EmitNeonFcvtzuGen, EmitNeonFcvtzsGen64, EmitNeonFcvtzuGen64);
  1056. break;
  1057. case Js::OpCode::FDIV:
  1058. bytes = this->EmitOp3FpRegister(Emitter, instr, EmitNeonFdiv);
  1059. break;
  1060. case Js::OpCode::FLDR:
  1061. bytes = this->EmitLoadStoreFp(Emitter, instr, instr->GetSrc1(), instr->GetDst(), EmitNeonLdrOffset);
  1062. break;
  1063. // Note: src2 is really the second destination register, due to limitations of IR::Instr
  1064. case Js::OpCode::FLDP:
  1065. bytes = this->EmitLoadStoreFpPair(Emitter, instr, instr->GetSrc1(), instr->GetDst(), instr->GetSrc2(), EmitNeonLdpOffset);
  1066. break;
  1067. case Js::OpCode::FMIN:
  1068. bytes = this->EmitOp3FpRegister(Emitter, instr, EmitNeonFmin);
  1069. break;
  1070. case Js::OpCode::FMAX:
  1071. bytes = this->EmitOp3FpRegister(Emitter, instr, EmitNeonFmax);
  1072. break;
  1073. case Js::OpCode::FMOV:
  1074. bytes = this->EmitOp2FpRegister(Emitter, instr, EmitNeonFmov);
  1075. break;
  1076. case Js::OpCode::FMOV_GEN:
  1077. dst = instr->GetDst();
  1078. src1 = instr->GetSrc1();
  1079. Assert(dst->IsRegOpnd());
  1080. Assert(src1->IsRegOpnd());
  1081. size = dst->GetSize();
  1082. Assert(size == 4 || size == 8);
  1083. Assert(size == src1->GetSize());
  1084. Assert(dst->IsFloat() != src1->IsFloat());
  1085. if (dst->IsFloat())
  1086. {
  1087. bytes = EmitNeonIns(Emitter, this->GetFloatRegEncode(dst->AsRegOpnd()), 0, this->GetRegEncode(src1->AsRegOpnd()), (size == 8) ? SIZE_1D : SIZE_1S);
  1088. }
  1089. else
  1090. {
  1091. if (size == 8)
  1092. {
  1093. bytes = EmitNeonUmov64(Emitter, this->GetFloatRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src1->AsRegOpnd()), 0, (size == 8) ? SIZE_1D : SIZE_1S);
  1094. }
  1095. else
  1096. {
  1097. bytes = EmitNeonUmov(Emitter, this->GetFloatRegEncode(dst->AsRegOpnd()), this->GetRegEncode(src1->AsRegOpnd()), 0, (size == 8) ? SIZE_1D : SIZE_1S);
  1098. }
  1099. }
  1100. break;
  1101. case Js::OpCode::FMUL:
  1102. bytes = this->EmitOp3FpRegister(Emitter, instr, EmitNeonFmul);
  1103. break;
  1104. case Js::OpCode::FNEG:
  1105. bytes = this->EmitOp2FpRegister(Emitter, instr, EmitNeonFneg);
  1106. break;
  1107. case Js::OpCode::FRINTM:
  1108. bytes = this->EmitOp2FpRegister(Emitter, instr, EmitNeonFrintm);
  1109. break;
  1110. case Js::OpCode::FRINTP:
  1111. bytes = this->EmitOp2FpRegister(Emitter, instr, EmitNeonFrintp);
  1112. break;
  1113. case Js::OpCode::FSUB:
  1114. bytes = this->EmitOp3FpRegister(Emitter, instr, EmitNeonFsub);
  1115. break;
  1116. case Js::OpCode::FSQRT:
  1117. bytes = this->EmitOp2FpRegister(Emitter, instr, EmitNeonFsqrt);
  1118. break;
  1119. case Js::OpCode::FSTR:
  1120. bytes = this->EmitLoadStoreFp(Emitter, instr, instr->GetDst(), instr->GetSrc1(), EmitNeonStrOffset);
  1121. break;
  1122. case Js::OpCode::FSTP:
  1123. bytes = this->EmitLoadStoreFpPair(Emitter, instr, instr->GetDst(), instr->GetSrc1(), instr->GetSrc2(), EmitNeonStpOffset);
  1124. break;
  1125. // Opcode not yet implemented
  1126. default:
  1127. #if DBG_DUMP
  1128. instr->Dump();
  1129. Output::Flush();
  1130. #endif
  1131. AssertMsg(UNREACHED, "Unsupported Instruction Form");
  1132. break;
  1133. }
  1134. Assert(bytes != 0);
  1135. return Emitter.Opcode();
  1136. }
  1137. #ifdef INSERT_NOPS
  1138. ptrdiff_t insertNops(BYTE *pc, DWORD outInstr, uint count, uint size)
  1139. {
  1140. //Insert count nops in the beginning
  1141. for(int i = 0; i < count;i++)
  1142. {
  1143. *(DWORD *)(pc + i * sizeof(DWORD)) = 0x8000F3AF;
  1144. }
  1145. if (size == sizeof(ENCODE_16))
  1146. {
  1147. *(ENCODE_16 *)(pc + count * sizeof(DWORD)) = (ENCODE_16)(outInstr & 0x0000ffff);
  1148. *(ENCODE_16 *)(pc + sizeof(ENCODE_16) + count * sizeof(DWORD)) = (ENCODE_16)(0xBF00);
  1149. }
  1150. else
  1151. {
  1152. Assert(size == sizeof(DWORD));
  1153. *(DWORD *)(pc + count * sizeof(DWORD)) = outInstr;
  1154. }
  1155. //Insert count nops at the end;
  1156. for(int i = count + 1; i < (2 *count + 1); i++)
  1157. {
  1158. *(DWORD *)(pc + i * sizeof(DWORD)) = 0x8000F3AF;
  1159. }
  1160. return MachInt*(2*count + 1);
  1161. }
  1162. #endif //INSERT_NOPS
  1163. ///----------------------------------------------------------------------------
  1164. ///
  1165. /// EncoderMD::Encode
  1166. ///
  1167. /// Emit the ARM encoding for the given instruction in the passed in
  1168. /// buffer ptr.
  1169. ///
  1170. ///----------------------------------------------------------------------------
  1171. ptrdiff_t
  1172. EncoderMD::Encode(IR::Instr *instr, BYTE *pc, BYTE* beginCodeAddress)
  1173. {
  1174. m_pc = pc;
  1175. DWORD outInstr;
  1176. // Instructions must be lowered, we don't handle non-MD opcodes here.
  1177. Assert(instr != nullptr);
  1178. if (instr->IsLowered() == false)
  1179. {
  1180. if (instr->IsLabelInstr())
  1181. {
  1182. if (instr->isInlineeEntryInstr)
  1183. {
  1184. size_t inlineeOffset = m_pc - m_encoder->m_encodeBuffer;
  1185. size_t argCount = instr->AsLabelInstr()->GetOffset();
  1186. Assert(inlineeOffset == (inlineeOffset & 0x0FFFFFFF));
  1187. intptr_t inlineeCallInfo = 0;
  1188. const bool encodeResult = Js::InlineeCallInfo::Encode(inlineeCallInfo, argCount, inlineeOffset);
  1189. Assert(encodeResult);
  1190. //We are re-using offset to save the inlineeCallInfo which will be patched in ApplyRelocs
  1191. //This is a cleaner way to patch MOVW\MOVT pair with the right inlineeCallInfo
  1192. instr->AsLabelInstr()->ResetOffset((uintptr_t)inlineeCallInfo);
  1193. }
  1194. else
  1195. {
  1196. instr->AsLabelInstr()->SetPC(m_pc);
  1197. m_func->m_unwindInfo.SetLabelOffset(instr->AsLabelInstr()->m_id, DWORD(m_pc - m_encoder->m_encodeBuffer));
  1198. }
  1199. }
  1200. #if DBG_DUMP
  1201. if (instr->IsEntryInstr() && Js::Configuration::Global.flags.DebugBreak.Contains(m_func->GetFunctionNumber()))
  1202. {
  1203. IR::Instr *int3 = IR::Instr::New(Js::OpCode::DEBUGBREAK, m_func);
  1204. return this->Encode(int3, m_pc);
  1205. }
  1206. #endif
  1207. return 0;
  1208. }
  1209. this->CanonicalizeInstr(instr);
  1210. outInstr = GenerateEncoding(instr, m_pc);
  1211. if (outInstr == 0)
  1212. {
  1213. return 0;
  1214. }
  1215. // TODO: Check if VFP/Neon instructions in Thumb-2 mode we need to swap the instruction halfwords
  1216. #ifdef INSERT_NOPS
  1217. return insertNops(m_pc, outInstr, CountNops, sizeof(DWORD));
  1218. #else
  1219. *(DWORD *)m_pc = outInstr ;
  1220. return MachInt;
  1221. #endif
  1222. }
  1223. bool
  1224. EncoderMD::EncodeLogicalConst(IntConstType constant, DWORD * result, int size = 4)
  1225. {
  1226. *result = FindArm64LogicalImmediateEncoding(constant, size);
  1227. return (*result != ARM64_LOGICAL_IMMEDIATE_NO_ENCODING);
  1228. }
  1229. bool
  1230. EncoderMD::CanEncodeLogicalConst(IntConstType constant, int size)
  1231. {
  1232. DWORD encode;
  1233. return EncodeLogicalConst(constant, &encode, size);
  1234. }
  1235. ///----------------------------------------------------------------------------
  1236. ///
  1237. /// EncodeReloc::New
  1238. ///
  1239. ///----------------------------------------------------------------------------
  1240. void
  1241. EncodeReloc::New(EncodeReloc **pHead, RelocType relocType, BYTE *offset, IR::Instr *relocInstr, ArenaAllocator *alloc)
  1242. {
  1243. EncodeReloc *newReloc = AnewStruct(alloc, EncodeReloc);
  1244. newReloc->m_relocType = relocType;
  1245. newReloc->m_consumerOffset = offset;
  1246. newReloc->m_next = *pHead;
  1247. newReloc->m_relocInstr = relocInstr;
  1248. *pHead = newReloc;
  1249. }
  1250. void
  1251. EncoderMD::BaseAndOffsetFromSym(IR::SymOpnd *symOpnd, RegNum *pBaseReg, int32 *pOffset, Func * func)
  1252. {
  1253. StackSym *stackSym = symOpnd->m_sym->AsStackSym();
  1254. RegNum baseReg = func->GetLocalsPointer();
  1255. int32 offset = stackSym->m_offset + symOpnd->m_offset;
  1256. if (baseReg == RegSP)
  1257. {
  1258. // SP points to the base of the argument area. Non-reg SP points directly to the locals.
  1259. offset += (func->m_argSlotsForFunctionsCalled * MachRegInt);
  1260. }
  1261. if (func->HasInlinee())
  1262. {
  1263. Assert(func->HasInlinee());
  1264. if ((!stackSym->IsArgSlotSym() || stackSym->m_isOrphanedArg) && !stackSym->IsParamSlotSym())
  1265. {
  1266. offset += func->GetInlineeArgumentStackSize();
  1267. }
  1268. }
  1269. if (stackSym->IsParamSlotSym())
  1270. {
  1271. offset += func->m_localStackHeight + func->m_ArgumentsOffset;
  1272. if (!EncoderMD::CanEncodeLoadStoreOffset(offset))
  1273. {
  1274. // Use the frame pointer. No need to hoist an offset for a param.
  1275. baseReg = FRAME_REG;
  1276. offset = stackSym->m_offset + symOpnd->m_offset - (Js::JavascriptFunctionArgIndex_Frame * MachRegInt);
  1277. Assert(EncoderMD::CanEncodeLoadStoreOffset(offset));
  1278. }
  1279. }
  1280. #ifdef DBG
  1281. else
  1282. {
  1283. // Locals are offset by the size of the area allocated for stack args.
  1284. Assert(offset >= 0);
  1285. Assert(baseReg != RegSP || (uint)offset >= (func->m_argSlotsForFunctionsCalled * MachRegInt));
  1286. if (func->HasInlinee())
  1287. {
  1288. // TODO (megupta): BaseReg will be a pre-reserved non SP register when we start supporting try
  1289. Assert(baseReg == RegSP || baseReg == ALT_LOCALS_PTR);
  1290. if (stackSym->IsArgSlotSym() && !stackSym->m_isOrphanedArg)
  1291. {
  1292. Assert(stackSym->m_isInlinedArgSlot);
  1293. //Assert((uint)offset <= ((func->m_argSlotsForFunctionsCalled + func->GetMaxInlineeArgOutCount()) * MachRegInt));
  1294. }
  1295. else
  1296. {
  1297. AssertMsg(stackSym->IsAllocated(), "StackSym offset should be set");
  1298. //Assert((uint)offset > ((func->m_argSlotsForFunctionsCalled + func->GetMaxInlineeArgOutCount()) * MachRegInt));
  1299. //Assert(offset > (func->HasTry() ? (int32)func->GetMaxInlineeArgOutSize() : (int32)(func->m_argSlotsForFunctionsCalled * MachRegInt + func->GetMaxInlineeArgOutSize())));
  1300. }
  1301. }
  1302. // TODO: restore the following assert (very useful) once we have a way to tell whether prolog/epilog
  1303. // gen is complete.
  1304. //Assert(offset < func->m_localStackHeight);
  1305. }
  1306. #endif
  1307. *pBaseReg = baseReg;
  1308. *pOffset = offset;
  1309. }
  1310. ///----------------------------------------------------------------------------
  1311. ///
  1312. /// EncoderMD::ApplyRelocs
  1313. /// We apply relocations to the temporary buffer using the target buffer's address
  1314. /// before we copy the contents of the temporary buffer to the target buffer.
  1315. ///----------------------------------------------------------------------------
  1316. void
  1317. EncoderMD::ApplyRelocs(size_t codeBufferAddress, size_t codeSize, uint* bufferCRC, BOOL isBrShorteningSucceeded, bool isFinalBufferValidation)
  1318. {
  1319. for (EncodeReloc *reloc = m_relocList; reloc; reloc = reloc->m_next)
  1320. {
  1321. PULONG relocAddress = PULONG(reloc->m_consumerOffset);
  1322. PULONG targetAddress = PULONG(reloc->m_relocInstr->AsLabelInstr()->GetPC());
  1323. ULONG_PTR immediate;
  1324. switch (reloc->m_relocType)
  1325. {
  1326. case RelocTypeBranch14:
  1327. case RelocTypeBranch19:
  1328. case RelocTypeBranch26:
  1329. ArmBranchLinker::LinkRaw(relocAddress, targetAddress);
  1330. break;
  1331. case RelocTypeLabelAdr:
  1332. Assert(!reloc->m_relocInstr->isInlineeEntryInstr);
  1333. immediate = ULONG_PTR(targetAddress) - ULONG_PTR(relocAddress);
  1334. Assert(IS_CONST_INT21(immediate));
  1335. *relocAddress = (*relocAddress & ~(3 << 29)) | ULONG((immediate & 3) << 29);
  1336. *relocAddress = (*relocAddress & ~(0x7ffff << 5)) | ULONG(((immediate >> 2) & 0x7ffff) << 5);
  1337. break;
  1338. case RelocTypeLabelImmed:
  1339. {
  1340. // read the shift from the encoded instruction.
  1341. uint32 shift = ((*relocAddress & (0x3 << 21)) >> 21) * 16;
  1342. uintptr_t fullvalue = ULONG_PTR(targetAddress) - ULONG_PTR(m_encoder->m_encodeBuffer) + ULONG_PTR(codeBufferAddress);
  1343. immediate = (fullvalue >> shift) & 0xffff;
  1344. // replace the immediate value in the encoded instruction.
  1345. *relocAddress = (*relocAddress & ~(0xffff << 5)) | ULONG((immediate & 0xffff) << 5);
  1346. break;
  1347. }
  1348. case RelocTypeLabel:
  1349. *(ULONG_PTR*)relocAddress = ULONG_PTR(targetAddress) - ULONG_PTR(m_encoder->m_encodeBuffer) + ULONG_PTR(codeBufferAddress);
  1350. break;
  1351. default:
  1352. // unexpected/unimplemented type
  1353. Assert(UNREACHED);
  1354. }
  1355. }
  1356. }
  1357. void
  1358. EncoderMD::EncodeInlineeCallInfo(IR::Instr *instr, uint32 codeOffset)
  1359. {
  1360. DebugOnly(IR::LabelInstr* inlineeStart = instr->AsLabelInstr());
  1361. Assert((inlineeStart->GetOffset() & 0x0F) == inlineeStart->GetOffset());
  1362. return;
  1363. }
  1364. bool EncoderMD::TryConstFold(IR::Instr *instr, IR::RegOpnd *regOpnd)
  1365. {
  1366. Assert(regOpnd->m_sym->IsConst());
  1367. if (instr->m_opcode == Js::OpCode::MOV)
  1368. {
  1369. if (instr->GetSrc1() != regOpnd)
  1370. {
  1371. return false;
  1372. }
  1373. if (!instr->GetDst()->IsRegOpnd())
  1374. {
  1375. return false;
  1376. }
  1377. IR::Opnd* constOpnd = regOpnd->m_sym->GetConstOpnd();
  1378. if (constOpnd->GetSize() > regOpnd->GetSize())
  1379. {
  1380. return false;
  1381. }
  1382. instr->ReplaceSrc(regOpnd, constOpnd);
  1383. LegalizeMD::LegalizeInstr(instr);
  1384. return true;
  1385. }
  1386. else
  1387. {
  1388. return false;
  1389. }
  1390. }
  1391. bool EncoderMD::TryFold(IR::Instr *instr, IR::RegOpnd *regOpnd)
  1392. {
  1393. if (LowererMD::IsAssign(instr))
  1394. {
  1395. if (!instr->GetDst()->IsRegOpnd() || regOpnd != instr->GetSrc1())
  1396. {
  1397. return false;
  1398. }
  1399. IR::SymOpnd *symOpnd = IR::SymOpnd::New(regOpnd->m_sym, regOpnd->GetType(), instr->m_func);
  1400. instr->ReplaceSrc(regOpnd, symOpnd);
  1401. LegalizeMD::LegalizeInstr(instr);
  1402. return true;
  1403. }
  1404. else
  1405. {
  1406. return false;
  1407. }
  1408. }
  1409. void EncoderMD::AddLabelReloc(BYTE* relocAddress)
  1410. {
  1411. Assert(relocAddress != nullptr);
  1412. EncodeReloc::New(&m_relocList, RelocTypeLabel, relocAddress, *(IR::Instr**)relocAddress, m_encoder->m_tempAlloc);
  1413. }