EncoderMD.cpp 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850
  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 "X64Encode.h"
  7. static const BYTE OpcodeByte2[]={
  8. #define MACRO(name, jnLayout, attrib, byte2, ...) byte2,
  9. #include "MdOpcodes.h"
  10. #undef MACRO
  11. };
  12. struct FormTemplate{ BYTE form[6]; };
  13. #define f(form) TEMPLATE_FORM_ ## form
  14. static const struct FormTemplate OpcodeFormTemplate[] =
  15. {
  16. #define MACRO(name, jnLayout, attrib, byte2, form, ...) form ,
  17. #include "MdOpcodes.h"
  18. #undef MACRO
  19. };
  20. #undef f
  21. struct OpbyteTemplate { byte opbyte[6]; };
  22. static const struct OpbyteTemplate Opbyte[] =
  23. {
  24. #define MACRO(name, jnLayout, attrib, byte2, form, opbyte, ...) opbyte,
  25. #include "MdOpcodes.h"
  26. #undef MACRO
  27. };
  28. static const uint32 Opdope[] =
  29. {
  30. #define MACRO(name, jnLayout, attrib, byte2, form, opbyte, dope, ...) dope,
  31. #include "MdOpcodes.h"
  32. #undef MACRO
  33. };
  34. static const BYTE OpEncoding[] =
  35. {
  36. #define REGDAT(name, dispName, encoding, ...) encoding ,
  37. #include "RegList.h"
  38. #undef MACRO
  39. };
  40. static const uint32 OpcodeLeadIn[] =
  41. {
  42. #define MACRO(name, jnLayout, attrib, byte2, form, opByte, dope, leadIn, ...) leadIn,
  43. #include "MdOpcodes.h"
  44. #undef MACRO
  45. };
  46. static const enum Forms OpcodeForms[] =
  47. {
  48. #define MACRO(name, jnLayout, attrib, byte2, form, ...) form,
  49. #include "MdOpcodes.h"
  50. #undef MACRO
  51. };
  52. static const BYTE Nop1[] = { 0x90 }; /* nop */
  53. static const BYTE Nop2[] = { 0x66, 0x90 }; /* xchg ax, ax */
  54. static const BYTE Nop3[] = { 0x0F, 0x1F, 0x00 }; /* nop dword ptr [rax] */
  55. static const BYTE Nop4[] = { 0x0F, 0x1F, 0x40, 0x00 }; /* nop dword ptr [rax + 0] */
  56. static const BYTE * const Nop[4] = { Nop1, Nop2, Nop3, Nop4 };
  57. enum CMP_IMM8
  58. {
  59. EQ,
  60. LT,
  61. LE,
  62. UNORD,
  63. NEQ,
  64. NLT,
  65. NLE,
  66. ORD
  67. };
  68. ///----------------------------------------------------------------------------
  69. ///
  70. /// EncoderMD::Init
  71. ///
  72. ///----------------------------------------------------------------------------
  73. void
  74. EncoderMD::Init(Encoder *encoder)
  75. {
  76. m_encoder = encoder;
  77. m_relocList = nullptr;
  78. m_lastLoopLabelPosition = -1;
  79. }
  80. ///----------------------------------------------------------------------------
  81. ///
  82. /// EncoderMD::GetOpcodeByte2
  83. ///
  84. /// Get the second byte encoding of the given instr.
  85. ///
  86. ///----------------------------------------------------------------------------
  87. const BYTE
  88. EncoderMD::GetOpcodeByte2(IR::Instr *instr)
  89. {
  90. return OpcodeByte2[instr->m_opcode - (Js::OpCode::MDStart+1)];
  91. }
  92. ///----------------------------------------------------------------------------
  93. ///
  94. /// EncoderMD::GetInstrForm
  95. ///
  96. /// Get the form list of the given instruction. The form list contains
  97. /// the possible encoding forms of an instruction.
  98. ///
  99. ///----------------------------------------------------------------------------
  100. Forms
  101. EncoderMD::GetInstrForm(IR::Instr *instr)
  102. {
  103. return OpcodeForms[instr->m_opcode - (Js::OpCode::MDStart + 1)];
  104. }
  105. ///----------------------------------------------------------------------------
  106. ///
  107. /// EncoderMD::GetFormTemplate
  108. ///
  109. /// Get the form list of the given instruction. The form list contains
  110. /// the possible encoding forms of an instruction.
  111. ///
  112. ///----------------------------------------------------------------------------
  113. const BYTE *
  114. EncoderMD::GetFormTemplate(IR::Instr *instr)
  115. {
  116. return OpcodeFormTemplate[instr->m_opcode - (Js::OpCode::MDStart + 1)].form;
  117. }
  118. ///----------------------------------------------------------------------------
  119. ///
  120. /// EncoderMD::GetOpbyte
  121. ///
  122. /// Get the first byte opcode of an instr.
  123. ///
  124. ///----------------------------------------------------------------------------
  125. const BYTE *
  126. EncoderMD::GetOpbyte(IR::Instr *instr)
  127. {
  128. return Opbyte[instr->m_opcode - (Js::OpCode::MDStart+1)].opbyte;
  129. }
  130. ///----------------------------------------------------------------------------
  131. ///
  132. /// EncoderMD::GetRegEncode
  133. ///
  134. /// Get the amd64 encoding of a given register.
  135. ///
  136. ///----------------------------------------------------------------------------
  137. const BYTE
  138. EncoderMD::GetRegEncode(IR::RegOpnd *regOpnd)
  139. {
  140. return this->GetRegEncode(regOpnd->GetReg());
  141. }
  142. const BYTE
  143. EncoderMD::GetRegEncode(RegNum reg)
  144. {
  145. AssertMsg(reg != RegNOREG, "should have valid reg in encoder");
  146. //
  147. // Instead of lookup. We can also AND with 0x7.
  148. //
  149. return (BYTE)(OpEncoding[1 + reg - RegRAX]);
  150. }
  151. ///----------------------------------------------------------------------------
  152. ///
  153. /// EncoderMD::GetOpdope
  154. ///
  155. /// Get the dope vector of a particular instr. The dope vector describes
  156. /// certain properties of an instr.
  157. ///
  158. ///----------------------------------------------------------------------------
  159. const uint32
  160. EncoderMD::GetOpdope(IR::Instr *instr)
  161. {
  162. return Opdope[instr->m_opcode - (Js::OpCode::MDStart+1)];
  163. }
  164. ///----------------------------------------------------------------------------
  165. ///
  166. /// EncoderMD::GetLeadIn
  167. ///
  168. /// Get the leadin of a particular instr.
  169. ///
  170. ///----------------------------------------------------------------------------
  171. const uint32
  172. EncoderMD::GetLeadIn(IR::Instr * instr)
  173. {
  174. return OpcodeLeadIn[instr->m_opcode - (Js::OpCode::MDStart+1)];
  175. }
  176. ///----------------------------------------------------------------------------
  177. ///
  178. /// EncoderMD::FitsInByte
  179. ///
  180. /// Can we encode this value into a signed extended byte?
  181. ///
  182. ///----------------------------------------------------------------------------
  183. bool
  184. EncoderMD::FitsInByte(size_t value)
  185. {
  186. return ((size_t)(signed char)(value & 0xFF) == value);
  187. }
  188. ///----------------------------------------------------------------------------
  189. ///
  190. /// EncoderMD::GetMod
  191. ///
  192. /// Get the "MOD" part of a MODRM encoding for a given operand.
  193. ///
  194. ///----------------------------------------------------------------------------
  195. BYTE
  196. EncoderMD::GetMod(IR::IndirOpnd * indirOpnd, int* pDispSize)
  197. {
  198. RegNum reg = indirOpnd->GetBaseOpnd()->GetReg();
  199. return GetMod(indirOpnd->GetOffset(), (reg == RegR13 || reg == RegRBP), pDispSize);
  200. }
  201. BYTE
  202. EncoderMD::GetMod(IR::SymOpnd * symOpnd, int * pDispSize, RegNum& rmReg)
  203. {
  204. StackSym * stackSym = symOpnd->m_sym->AsStackSym();
  205. int32 offset = stackSym->m_offset;
  206. rmReg = RegRBP;
  207. if (stackSym->IsArgSlotSym() && !stackSym->m_isOrphanedArg)
  208. {
  209. if (stackSym->m_isInlinedArgSlot)
  210. {
  211. Assert(offset >= 0);
  212. offset -= this->m_func->m_localStackHeight;
  213. stackSym->m_offset = offset;
  214. stackSym->m_allocated = true;
  215. }
  216. else
  217. {
  218. rmReg = RegRSP;
  219. }
  220. }
  221. else
  222. {
  223. Assert(offset != 0);
  224. }
  225. return GetMod((size_t)offset + (size_t)symOpnd->m_offset, rmReg == RegRBP, pDispSize);
  226. }
  227. BYTE
  228. EncoderMD::GetMod(size_t offset, bool regIsRbpOrR13, int * pDispSize)
  229. {
  230. if (offset == 0 && !regIsRbpOrR13)
  231. {
  232. *(pDispSize) = 0;
  233. return Mod00;
  234. }
  235. else if (this->FitsInByte(offset))
  236. {
  237. *(pDispSize) = 1;
  238. return Mod01;
  239. }
  240. else if(Math::FitsInDWord(offset))
  241. {
  242. *(pDispSize) = 4;
  243. return Mod10;
  244. }
  245. else
  246. {
  247. AssertMsg(0, "Cannot encode offsets more than 32 bits in MODRM");
  248. return 0xff;
  249. }
  250. }
  251. ///----------------------------------------------------------------------------
  252. ///
  253. /// EncoderMD::EmitModRM
  254. ///
  255. /// Emit an effective address using the MODRM byte.
  256. ///
  257. ///----------------------------------------------------------------------------
  258. BYTE
  259. EncoderMD::EmitModRM(IR::Instr * instr, IR::Opnd *opnd, BYTE reg1)
  260. {
  261. int dispSize = -1; // Initialize to suppress C4701 false positive
  262. IR::IndirOpnd *indirOpnd;
  263. IR::RegOpnd *regOpnd;
  264. IR::RegOpnd *baseOpnd;
  265. IR::RegOpnd *indexOpnd;
  266. BYTE reg;
  267. BYTE regBase;
  268. BYTE regIndex;
  269. BYTE baseRegEncode;
  270. BYTE rexEncoding = 0;
  271. AssertMsg( (reg1 & 7) == reg1, "Invalid reg1");
  272. reg1 = (reg1 & 7) << 3; // mask and put in reg field
  273. switch (opnd->GetKind())
  274. {
  275. case IR::OpndKindReg:
  276. regOpnd = opnd->AsRegOpnd();
  277. AssertMsg(regOpnd->GetReg() != RegNOREG, "All regOpnd should have a valid reg set during encoder");
  278. reg = this->GetRegEncode(regOpnd);
  279. this->EmitConst((Mod11 | reg1 | reg), 1);
  280. if(this->IsExtendedRegister(regOpnd->GetReg()))
  281. {
  282. return REXB;
  283. }
  284. else
  285. {
  286. return 0;
  287. }
  288. case IR::OpndKindSym:
  289. AssertMsg(opnd->AsSymOpnd()->m_sym->IsStackSym(), "Should only see stackSym syms in encoder.");
  290. BYTE byte;
  291. RegNum rmReg;
  292. BYTE mod;
  293. mod = this->GetMod(opnd->AsSymOpnd(), &dispSize, rmReg);
  294. baseRegEncode = this->GetRegEncode(rmReg);
  295. byte = (BYTE)(mod | reg1 | baseRegEncode);
  296. *(m_pc++) = byte;
  297. if (rmReg == RegRSP)
  298. {
  299. byte = (BYTE)(((baseRegEncode & 7) << 3) | (baseRegEncode & 7));
  300. *(m_pc++) = byte;
  301. }
  302. else
  303. {
  304. AssertMsg(opnd->AsSymOpnd()->m_sym->AsStackSym()->m_offset, "Expected stackSym offset to be set.");
  305. }
  306. break;
  307. case IR::OpndKindIndir:
  308. indirOpnd = opnd->AsIndirOpnd();
  309. AssertMsg(indirOpnd->GetBaseOpnd() != nullptr, "Expected base to be set in indirOpnd");
  310. baseOpnd = indirOpnd->GetBaseOpnd();
  311. indexOpnd = indirOpnd->GetIndexOpnd();
  312. AssertMsg(!indexOpnd || indexOpnd->GetReg() != RegRSP, "ESP cannot be the index of an indir.");
  313. regBase = this->GetRegEncode(baseOpnd);
  314. if (indexOpnd != nullptr)
  315. {
  316. regIndex = this->GetRegEncode(indexOpnd);
  317. *(m_pc++) = (this->GetMod(indirOpnd, &dispSize) | reg1 | 0x4);
  318. *(m_pc++) = (((indirOpnd->GetScale() & 3) << 6) | ((regIndex & 7) << 3) | (regBase & 7));
  319. rexEncoding |= this->GetRexByte(this->REXX, indexOpnd);
  320. rexEncoding |= this->GetRexByte(this->REXB, baseOpnd);
  321. }
  322. else if (baseOpnd->GetReg() == RegR12 || baseOpnd->GetReg() == RegRSP)
  323. {
  324. //
  325. // Using RSP/R12 as base requires the SIB byte even where there is no index.
  326. //
  327. *(m_pc++) = (this->GetMod(indirOpnd, &dispSize) | reg1 | regBase);
  328. *(m_pc++) = (BYTE)(((regBase & 7) << 3) | (regBase & 7));
  329. rexEncoding |= this->GetRexByte(this->REXB, baseOpnd);
  330. }
  331. else
  332. {
  333. *(m_pc++) = (this->GetMod(indirOpnd, &dispSize) | reg1 | regBase);
  334. rexEncoding |= this->GetRexByte(this->REXB, baseOpnd);
  335. }
  336. break;
  337. case IR::OpndKindMemRef:
  338. *(m_pc++) = (char)(reg1 | 0x4);
  339. *(m_pc++) = 0x25; // SIB displacement
  340. AssertMsg(Math::FitsInDWord((size_t)opnd->AsMemRefOpnd()->GetMemLoc()), "Size overflow");
  341. dispSize = 4;
  342. break;
  343. default:
  344. AssertMsg(UNREACHED, "Unexpected operand kind");
  345. break;
  346. }
  347. AssertMsg(dispSize != -1, "Uninitialized dispSize");
  348. BYTE retval = this->EmitImmed(opnd, dispSize, 0);
  349. AssertMsg(retval == 0, "Not possible.");
  350. return rexEncoding;
  351. }
  352. ///----------------------------------------------------------------------------
  353. ///
  354. /// EncoderMD::EmitConst
  355. ///
  356. /// Emit a constant of the given size.
  357. ///
  358. ///----------------------------------------------------------------------------
  359. void
  360. EncoderMD::EmitConst(size_t val, int size, bool allowImm64 /* = false */)
  361. {
  362. AssertMsg(allowImm64 || size != 8, "Invalid size of immediate. It can only be 8 for certain instructions, MOV being the most popular");
  363. switch (size)
  364. {
  365. case 0:
  366. return;
  367. case 1:
  368. *(uint8*)m_pc = (char)val;
  369. break;
  370. case 2:
  371. *(uint16*)m_pc = (short)val;
  372. break;
  373. case 4:
  374. *(uint32*)m_pc = (uint32)val;
  375. break;
  376. case 8:
  377. *(uint64*)m_pc = (uint64)val;
  378. break;
  379. default:
  380. AssertMsg(UNREACHED, "Unexpected size");
  381. }
  382. m_pc += size;
  383. }
  384. ///----------------------------------------------------------------------------
  385. ///
  386. /// EncoderMD::EmitImmed
  387. ///
  388. /// Emit the immediate value of the given operand. It returns 0x2 for a
  389. /// sbit encoding, 0 otherwise.
  390. ///
  391. ///----------------------------------------------------------------------------
  392. BYTE
  393. EncoderMD::EmitImmed(IR::Opnd * opnd, int opSize, int sbit, bool allow64Immediates)
  394. {
  395. StackSym *stackSym = nullptr;
  396. BYTE retval = 0;
  397. size_t value = 0;
  398. switch (opnd->GetKind())
  399. {
  400. case IR::OpndKindAddr:
  401. value = (size_t)opnd->AsAddrOpnd()->m_address;
  402. goto intConst;
  403. case IR::OpndKindIntConst:
  404. value = opnd->AsIntConstOpnd()->GetValue();
  405. intConst:
  406. if (sbit && opSize > 1 && this->FitsInByte(value))
  407. {
  408. opSize = 1;
  409. retval = 0x2; /* set S bit */
  410. }
  411. break;
  412. case IR::OpndKindSym:
  413. AssertMsg(opnd->AsSymOpnd()->m_sym->IsStackSym(), "Should only see stackSym here");
  414. stackSym = opnd->AsSymOpnd()->m_sym->AsStackSym();
  415. value = stackSym->m_offset + opnd->AsSymOpnd()->m_offset;
  416. break;
  417. case IR::OpndKindHelperCall:
  418. AssertMsg(this->GetOpndSize(opnd) == 8, "HelperCall opnd must be 64 bit");
  419. value = (size_t)IR::GetMethodAddress(m_func->GetThreadContextInfo(), opnd->AsHelperCallOpnd());
  420. break;
  421. case IR::OpndKindIndir:
  422. value = opnd->AsIndirOpnd()->GetOffset();
  423. break;
  424. case IR::OpndKindMemRef:
  425. value = (size_t)opnd->AsMemRefOpnd()->GetMemLoc();
  426. break;
  427. case IR::OpndKindLabel:
  428. value = (size_t)opnd->AsLabelOpnd()->GetLabel();
  429. AppendRelocEntry(RelocTypeLabelUse, (void*) m_pc, nullptr);
  430. break;
  431. default:
  432. AssertMsg(UNREACHED, "Unimplemented...");
  433. }
  434. if (!allow64Immediates && opSize == 8)
  435. {
  436. Assert(Math::FitsInDWord(value));
  437. opSize = 4;
  438. }
  439. this->EmitConst(value, opSize, allow64Immediates);
  440. return retval;
  441. }
  442. int
  443. EncoderMD::GetOpndSize(IR::Opnd * opnd)
  444. {
  445. return TySize[opnd->GetType()];
  446. }
  447. ///----------------------------------------------------------------------------
  448. ///
  449. /// EncoderMD::Encode
  450. ///
  451. /// Emit the x64 encoding for the given instruction in the passed in
  452. /// buffer ptr.
  453. ///
  454. ///----------------------------------------------------------------------------
  455. ptrdiff_t
  456. EncoderMD::Encode(IR::Instr *instr, BYTE *pc, BYTE* beginCodeAddress)
  457. {
  458. BYTE *popcodeByte = nullptr,
  459. *prexByte = nullptr,
  460. *instrStart = nullptr,
  461. *instrRestart = nullptr;
  462. IR::Opnd *dst = instr->GetDst();
  463. IR::Opnd *src1 = instr->GetSrc1();
  464. IR::Opnd *src2 = instr->GetSrc2();
  465. IR::Opnd *opr1 = nullptr;
  466. IR::Opnd *opr2 = nullptr;
  467. int instrSize = -1;
  468. bool skipRexByte = false;
  469. m_pc = pc;
  470. if (instr->IsLowered() == false)
  471. {
  472. if (instr->IsLabelInstr())
  473. {
  474. IR::LabelInstr *labelInstr = instr->AsLabelInstr();
  475. labelInstr->SetPC(m_pc);
  476. if (!labelInstr->IsUnreferenced())
  477. {
  478. int relocEntryPosition = AppendRelocEntry(RelocTypeLabel, labelInstr);
  479. if (!PHASE_OFF(Js::LoopAlignPhase, m_func))
  480. {
  481. // we record position of last loop-top label (leaf loops) for loop alignment
  482. if (labelInstr->m_isLoopTop && labelInstr->GetLoop()->isLeaf)
  483. {
  484. m_relocList->Item(relocEntryPosition).m_type = RelocType::RelocTypeAlignedLabel;
  485. }
  486. }
  487. }
  488. }
  489. #if DBG_DUMP
  490. if (instr->IsEntryInstr() && Js::Configuration::Global.flags.DebugBreak.Contains(m_func->GetFunctionNumber()))
  491. {
  492. IR::Instr *int3 = IR::Instr::New(Js::OpCode::INT, m_func);
  493. int3->SetSrc1(IR::IntConstOpnd::New(3, TyInt32, m_func));
  494. return this->Encode(int3, m_pc);
  495. }
  496. #endif
  497. return 0;
  498. }
  499. const BYTE *form = EncoderMD::GetFormTemplate(instr);
  500. const BYTE *opcodeTemplate = EncoderMD::GetOpbyte(instr);
  501. const uint32 leadIn = EncoderMD::GetLeadIn(instr);
  502. uint32 opdope = EncoderMD::GetOpdope(instr);
  503. //
  504. // Canonicalize operands.
  505. //
  506. if (opdope & DDST)
  507. {
  508. opr1 = dst;
  509. opr2 = src1;
  510. }
  511. else
  512. {
  513. opr1 = src1;
  514. opr2 = src2;
  515. }
  516. if (opr1)
  517. {
  518. instrSize = this->GetOpndSize(opr1);
  519. #if DBG
  520. switch (instr->m_opcode)
  521. {
  522. case Js::OpCode::MOVSXD:
  523. if (8 != this->GetOpndSize(opr1) || 4 != this->GetOpndSize(opr2))
  524. {
  525. AssertMsg(0, "Invalid Operand size ");
  526. }
  527. break;
  528. case Js::OpCode::IMUL2:
  529. // If this is IMUL3 then make sure a 32 bit encoding is possible.
  530. Assert((!opr2) || (!opr2->IsImmediateOpnd()) || (GetOpndSize(opr1) < 8));
  531. break;
  532. case Js::OpCode::SHL:
  533. case Js::OpCode::SHR:
  534. case Js::OpCode::SAR:
  535. //
  536. // TODO_JIT64:
  537. // These should be MachInt instead of Int32. Just ignore for now.
  538. //
  539. //if (instrSize != TySize[TyInt32])
  540. //{
  541. // AssertMsg(0, "Operand size mismatch");
  542. //}
  543. break;
  544. default:
  545. if (opr2)
  546. {
  547. //
  548. // review: this should eventually be enabled. Currently our type system does not
  549. // allow copying from DWORD to QWORD. hence the problem. This is required to read
  550. // JavascriptArray::length which is 4 bytes but the length needs to be operated as
  551. // normal Machine Integer.
  552. //
  553. //
  554. // TODO_JIT64:
  555. // These should be MachInt instead of Int32. Just ignore for now.
  556. //
  557. /*
  558. if (instrSize != this->GetOpndSize(opr2))
  559. {
  560. AssertMsg(0, "Operand size mismatch");
  561. }
  562. */
  563. }
  564. }
  565. #endif
  566. }
  567. instrRestart = instrStart = m_pc;
  568. // put out 16bit override if any
  569. if (instrSize == 2 && (opdope & (DNO16 | DFLT)) == 0)
  570. {
  571. *instrRestart++ = 0x66;
  572. }
  573. //
  574. // Instruction format is REX [0xF] OP_BYTE ...
  575. //
  576. // Emit the leading byte(s) of multibyte instructions.
  577. if (opdope & D66EX)
  578. {
  579. Assert((opdope & (D66EX | D66 | DF2 | DF3 )) == D66EX);
  580. if (opr1->IsFloat64() || opr2->IsFloat64())
  581. {
  582. *instrRestart++ = 0x66;
  583. }
  584. }
  585. else if (opdope & D66)
  586. {
  587. Assert((opdope & (D66 | DF2 | DF3)) == D66);
  588. Assert(leadIn == OLB_0F || leadIn == OLB_0F3A);
  589. *instrRestart++ = 0x66;
  590. }
  591. else if (opdope & DF2)
  592. {
  593. Assert((opdope & (DF2 | DF3)) == DF2);
  594. Assert(leadIn == OLB_0F);
  595. *instrRestart++ = 0xf2;
  596. }
  597. else if (opdope & DF3)
  598. {
  599. Assert(leadIn == OLB_0F);
  600. *instrRestart++ = 0xf3;
  601. }
  602. // REX byte.
  603. prexByte = instrRestart;
  604. // This is a heuristic to determine whether we really need to have the Rex bytes
  605. // This heuristics is always correct for instrSize == 8
  606. // For instrSize < 8, we might use extended registers and we will have to adjust in EmitRexByte
  607. bool reservedRexByte = (instrSize == 8);
  608. if (reservedRexByte)
  609. {
  610. instrRestart++;
  611. }
  612. switch(leadIn)
  613. {
  614. case OLB_NONE:
  615. break;
  616. case OLB_0F:
  617. *instrRestart++ = 0x0f;
  618. break;
  619. case OLB_0F3A:
  620. *instrRestart++ = 0x0f;
  621. *instrRestart++ = 0x3a;
  622. break;
  623. default:
  624. Assert(UNREACHED);
  625. __assume(UNREACHED);
  626. }
  627. // Actual opcode byte.
  628. popcodeByte = instrRestart++;
  629. //
  630. // Try each form 1 by 1, until we find the one appropriate for this instruction
  631. // and its operands.
  632. //
  633. for (;; opcodeTemplate++, form++)
  634. {
  635. m_pc = instrRestart;
  636. AssertMsg(m_pc - instrStart <= MachMaxInstrSize, "MachMaxInstrSize not set correctly");
  637. // Setup default values.
  638. BYTE opcodeByte = *opcodeTemplate;
  639. BYTE rexByte = REXOVERRIDE | REXW;
  640. switch ((*form) & FORM_MASK)
  641. {
  642. //
  643. // This would only be required for mov rax, [64bit memory address].
  644. //
  645. case AX_MEM:
  646. if (!opr2 || !opr2->IsMemRefOpnd())
  647. {
  648. continue;
  649. }
  650. AnalysisAssert(opr1);
  651. if (opr1->IsRegOpnd() && RegRAX == opr1->AsRegOpnd()->GetReg())
  652. {
  653. AssertMsg(opr2, "Operand 2 must be present in AX_MEM mode");
  654. if (TyInt64 == instrSize)
  655. {
  656. this->EmitImmed(opr2, instrSize, 0);
  657. }
  658. else
  659. {
  660. //
  661. // we don't have a 64 bit opnd. Hence we can will have to use
  662. // the normal MODRM/SIB encoding.
  663. //
  664. continue;
  665. }
  666. }
  667. // NYI
  668. case AX_IM:
  669. continue;
  670. // General immediate case. Special cases have already been checked.
  671. case IMM:
  672. if (!opr2->IsImmediateOpnd())
  673. {
  674. continue;
  675. }
  676. rexByte |= this->EmitModRM(instr, opr1, this->GetOpcodeByte2(instr) >> 3);
  677. opcodeByte |= this->EmitImmed(opr2, instrSize, *form & SBIT);
  678. break;
  679. case NO:
  680. {
  681. Assert(instr->m_opcode == Js::OpCode::CQO || instr->m_opcode == Js::OpCode::CDQ);
  682. instrSize = instr->m_opcode == Js::OpCode::CQO ? 8 : 4;
  683. BYTE byte2 = this->GetOpcodeByte2(instr);
  684. if (byte2)
  685. {
  686. *(m_pc)++ = byte2;
  687. }
  688. }
  689. break;
  690. // Short immediate/reg.
  691. case SHIMR:
  692. AnalysisAssert(opr1);
  693. if (!opr1->IsRegOpnd())
  694. {
  695. continue;
  696. }
  697. if (opr2->IsImmediateOpnd())
  698. {
  699. Assert(instr->m_opcode == Js::OpCode::MOV);
  700. if (instrSize == 8 && !instr->isInlineeEntryInstr && Math::FitsInDWord(opr2->GetImmediateValue(instr->m_func)))
  701. {
  702. // Better off using the C7 encoding as it will sign extend
  703. continue;
  704. }
  705. }
  706. else if (!opr2->IsLabelOpnd())
  707. {
  708. continue;
  709. }
  710. opcodeByte |= this->GetRegEncode(opr1->AsRegOpnd());
  711. rexByte |= this->GetRexByte(this->REXB, opr1);
  712. if (instrSize > 1)
  713. {
  714. opcodeByte |= 0x8; /* set the W bit */
  715. }
  716. this->EmitImmed(opr2, instrSize, 0, true); /* S bit known to be 0 */
  717. break;
  718. case AXMODRM:
  719. AssertMsg(opr1->AsRegOpnd()->GetReg() == RegRAX, "Expected src1 of IMUL/IDIV to be RAX");
  720. opr1 = opr2;
  721. opr2 = nullptr;
  722. // FALLTHROUGH
  723. case MODRM:
  724. modrm:
  725. AnalysisAssert(opr1);
  726. if (opr2 == nullptr)
  727. {
  728. BYTE byte2 = (this->GetOpcodeByte2(instr) >> 3);
  729. rexByte |= this->EmitModRM(instr, opr1, byte2);
  730. }
  731. else if (opr1->IsRegOpnd())
  732. {
  733. rexByte |= this->GetRexByte(this->REXR, opr1);
  734. rexByte |= this->EmitModRM(instr, opr2, this->GetRegEncode(opr1->AsRegOpnd()));
  735. if ((*form) & DBIT)
  736. {
  737. opcodeByte |= 0x2; // set D bit
  738. }
  739. }
  740. else
  741. {
  742. AssertMsg(opr2->IsRegOpnd(), "Expected opr2 to be a valid reg");
  743. AssertMsg(instrSize == this->GetOpndSize(opr2), "sf");
  744. AssertMsg(instrSize == this->GetOpndSize(opr1), "Opnd Size mismatch");
  745. rexByte |= this->GetRexByte(this->REXR, opr2);
  746. rexByte |= this->EmitModRM(instr, opr1, this->GetRegEncode(opr2->AsRegOpnd()));
  747. }
  748. break;
  749. // reg in opbyte. Only whole register allowed .
  750. case SH_REG:
  751. AnalysisAssert(opr1);
  752. if (!opr1->IsRegOpnd())
  753. {
  754. continue;
  755. }
  756. opcodeByte |= this->GetRegEncode(opr1->AsRegOpnd());
  757. rexByte |= this->GetRexByte(this->REXB, opr1);
  758. break;
  759. // short form immed. (must be unary)
  760. case SH_IM:
  761. AnalysisAssert(opr1);
  762. if (!opr1->IsIntConstOpnd() && !opr1->IsAddrOpnd())
  763. {
  764. continue;
  765. }
  766. instrSize = this->GetOpndSize(opr1);
  767. opcodeByte |= this->EmitImmed(opr1, instrSize, 1);
  768. break;
  769. case SHFT:
  770. rexByte |= this->EmitModRM(instr, opr1, this->GetOpcodeByte2(instr) >> 3);
  771. if (opr2->IsRegOpnd())
  772. {
  773. AssertMsg(opr2->AsRegOpnd()->GetReg() == RegRCX, "Expected ECX as opr2 of variable shift");
  774. opcodeByte |= *(opcodeTemplate + 1);
  775. }
  776. else
  777. {
  778. IntConstType value;
  779. AssertMsg(opr2->IsIntConstOpnd(), "Expected register or constant as shift amount opnd");
  780. value = opr2->AsIntConstOpnd()->GetValue();
  781. if (value == 1)
  782. {
  783. opcodeByte |= 0x10;
  784. }
  785. else
  786. {
  787. this->EmitConst(value, 1);
  788. }
  789. }
  790. break;
  791. // NYI
  792. case LABREL1:
  793. continue;
  794. // jmp, call with full relative disp.
  795. case LABREL2:
  796. if (opr1 == nullptr)
  797. {
  798. AssertMsg(sizeof(size_t) == sizeof(void*), "Sizes of void* assumed to be 64-bits");
  799. AssertMsg(instr->IsBranchInstr(), "Invalid LABREL2 form");
  800. AppendRelocEntry(RelocTypeBranch, (void*)m_pc, instr->AsBranchInstr()->GetTarget());
  801. this->EmitConst(0 , 4);
  802. }
  803. else if (opr1->IsIntConstOpnd())
  804. {
  805. // pc relative calls are not supported on x64.
  806. AssertMsg(UNREACHED, "Pc relative calls are not supported on x64");
  807. }
  808. else
  809. {
  810. continue;
  811. }
  812. break;
  813. // Special form which doesn't fit any existing patterns.
  814. case SPECIAL:
  815. switch (instr->m_opcode)
  816. {
  817. case Js::OpCode::RET:
  818. {
  819. AssertMsg(opr1->IsIntConstOpnd(), "RET should have intConst as src");
  820. IntConstType value = opr1->AsIntConstOpnd()->GetValue();
  821. if (value==0)
  822. {
  823. opcodeByte |= 0x1; // no imm16 follows
  824. }
  825. else
  826. {
  827. this->EmitConst(value, 2);
  828. }
  829. break;
  830. }
  831. case Js::OpCode::BT:
  832. case Js::OpCode::BTR:
  833. case Js::OpCode::BTS:
  834. /*
  835. * 0F A3 /r BT r/m32, r32
  836. * REX.W 0F A3 /r BT r/m64, r64
  837. * 0F BA /6 ib BT r/m32, imm8
  838. * REX.W 0F BA /6 ib BT r/m64, imm8
  839. * or
  840. * 0F B3 /r BTR r/m32, r32
  841. * REX.W 0F B3 /r BTR r/m64, r64
  842. * 0F BA /6 ib BTR r/m32, imm8
  843. * REX.W 0F BA /6 ib BTR r/m64, imm8
  844. * or
  845. * 0F AB /r BTS r/m32, r32
  846. * REX.W 0F AB /r BTS r/m64, r64
  847. * 0F BA /5 ib BTS r/m32, imm8
  848. * REX.W 0F BA /5 ib BTS r/m64, imm8
  849. */
  850. Assert(instr->m_opcode != Js::OpCode::BT || dst == nullptr);
  851. AssertMsg(instr->m_opcode == Js::OpCode::BT ||
  852. dst && (dst->IsRegOpnd() || dst->IsMemRefOpnd() || dst->IsIndirOpnd()), "Invalid dst type on BTR/BTS instruction.");
  853. if (src2->IsImmediateOpnd())
  854. {
  855. rexByte |= this->GetRexByte(this->REXR, src1);
  856. rexByte |= this->EmitModRM(instr, src1, this->GetOpcodeByte2(instr) >> 3);
  857. Assert(src2->IsIntConstOpnd() && src2->GetType() == TyInt8);
  858. opcodeByte |= EmitImmed(src2, 1, 0);
  859. }
  860. else
  861. {
  862. /* this is special dbit modrm in which opr1 can be a reg*/
  863. Assert(src2->IsRegOpnd());
  864. form++;
  865. opcodeTemplate++;
  866. Assert(((*form) & FORM_MASK) == MODRM);
  867. opcodeByte = *opcodeTemplate;
  868. rexByte |= this->GetRexByte(this->REXR, src2);
  869. rexByte |= this->EmitModRM(instr, src1, this->GetRegEncode(src2->AsRegOpnd()));
  870. }
  871. break;
  872. case Js::OpCode::SHLD:
  873. /*
  874. * 0F A4 SHLD r/m32, r32, imm8
  875. * REX.W 0F A4 SHLD r/m64, r64, imm8
  876. */
  877. AssertMsg(dst && (dst->IsRegOpnd() || dst->IsMemRefOpnd() || dst->IsIndirOpnd()), "Invalid dst type on SHLD instruction.");
  878. AssertMsg(src1 && src1->IsRegOpnd(), "Expected SHLD's second operand to be a register.");
  879. AssertMsg(src2 && src2->IsImmediateOpnd(), "Expected SHLD's third operand to be an immediate.");
  880. rexByte |= this->GetRexByte(this->REXR, opr2);
  881. rexByte |= EmitModRM(instr, opr1, GetRegEncode(opr2->AsRegOpnd()));
  882. opcodeByte |= EmitImmed(src2, 1, 1);
  883. break;
  884. case Js::OpCode::IMUL2:
  885. AssertMsg(opr1->IsRegOpnd() && instrSize != 1, "Illegal IMUL2");
  886. Assert(instrSize < 8);
  887. if (!opr2->IsImmediateOpnd())
  888. {
  889. continue;
  890. }
  891. // turn an 'imul2 reg, immed' into an 'imul3 reg, reg, immed'.
  892. // Reset pointers
  893. prexByte = instrStart;
  894. reservedRexByte = true;
  895. // imul3 uses a one-byte opcode, so no need to set the first byte of the opcode to 0xf
  896. popcodeByte = instrStart + 1;
  897. m_pc = instrStart + 2;
  898. // Set up default values
  899. rexByte = REXOVERRIDE;
  900. opcodeByte = *opcodeTemplate; // hammer prefix
  901. rexByte |= this->GetRexByte(REXR, opr1);
  902. rexByte |= this->EmitModRM(instr, opr1, this->GetRegEncode(opr1->AsRegOpnd()));
  903. // Currently, we only support 32-bit operands (Assert(instrSize < 8) above), so REXW is not set
  904. Assert(!(rexByte & REXW));
  905. opcodeByte |= this->EmitImmed(opr2, instrSize, 1);
  906. break;
  907. case Js::OpCode::INT:
  908. if (opr1->AsIntConstOpnd()->GetValue() != 3)
  909. {
  910. opcodeByte |= 1;
  911. *(m_pc)++ = (char)opr1->AsIntConstOpnd()->GetValue();
  912. }
  913. break;
  914. case Js::OpCode::MOVQ:
  915. {
  916. // The usual mechanism for encoding SSE/SSE2 instructions
  917. // doesn't work quite right for this one, so we must fixup
  918. // the encoding.
  919. if (REGNUM_ISXMMXREG(opr1->AsRegOpnd()->GetReg())) {
  920. if (opr2->IsRegOpnd() && this->GetOpndSize(opr2) == 8) { // QWORD_SIZE
  921. // Encoded as 66 REX.W 0F 6E ModRM
  922. opdope &= ~(DF2 | DF3);
  923. opdope |= D66;
  924. opcodeByte = 0x6E;
  925. goto modrm;
  926. }
  927. else {
  928. // Encoded as F3 0F 7E ModRM
  929. opdope &= ~(D66 | D66EX | DF2);
  930. opdope |= DF3;
  931. opcodeByte = 0x7E;
  932. goto modrm;
  933. }
  934. }
  935. //else if (TU_ISXMMXREG(opr2)) {
  936. else if (REGNUM_ISXMMXREG(opr2->AsRegOpnd()->GetReg())) {
  937. //if (TU_ISREG(opr1) && (TU_SIZE(opr1) == QWORD_SIZE)) {
  938. if (opr1->IsRegOpnd() && this->GetOpndSize(opr1) == 8) {// QWORD_SIZE
  939. // Encoded as 66 REX.W 0F 7E ModRM
  940. opdope &= ~(DF2 | DF3);
  941. opdope |= D66;
  942. opcodeByte = 0x7E;
  943. // Swap operands to get right behavior from modrm encode.
  944. IR::Opnd* tmp = opr1;
  945. opr1 = opr2;
  946. opr2 = tmp;
  947. goto modrm;
  948. }
  949. else {
  950. // Encoded as 66 0F D6
  951. opdope &= ~(DF2 | DF3);
  952. opdope |= D66;
  953. opcodeByte = 0xD6;
  954. goto modrm;
  955. }
  956. }
  957. }
  958. // FALL-THROUGH to MOVD
  959. case Js::OpCode::MOVD:
  960. if (opr2->IsRegOpnd() && REGNUM_ISXMMXREG(opr2->AsRegOpnd()->GetReg()))
  961. {
  962. // If the second operand is an XMM register, use the "store" form.
  963. if (opr1->IsRegOpnd())
  964. {
  965. // Swap operands to get right behavior from MODRM.
  966. IR::Opnd *tmp = opr1;
  967. opr1 = opr2;
  968. opr2 = tmp;
  969. }
  970. opcodeByte |= 0x10;
  971. }
  972. Assert(opr1->IsRegOpnd() && REGNUM_ISXMMXREG(opr1->AsRegOpnd()->GetReg()));
  973. goto modrm;
  974. case Js::OpCode::MOVLHPS:
  975. case Js::OpCode::MOVHLPS:
  976. Assert(opr1->IsRegOpnd() && REGNUM_ISXMMXREG(opr1->AsRegOpnd()->GetReg()));
  977. Assert(opr2->IsRegOpnd() && REGNUM_ISXMMXREG(opr2->AsRegOpnd()->GetReg()));
  978. goto modrm;
  979. case Js::OpCode::MOVMSKPD:
  980. case Js::OpCode::MOVMSKPS:
  981. /* Instruction form is "MOVMSKP[S/D] r32, xmm" */
  982. Assert(opr1->IsRegOpnd() && opr2->IsRegOpnd() && REGNUM_ISXMMXREG(opr2->AsRegOpnd()->GetReg()));
  983. goto modrm;
  984. case Js::OpCode::MOVSS:
  985. case Js::OpCode::MOVSD:
  986. case Js::OpCode::MOVAPD:
  987. case Js::OpCode::MOVAPS:
  988. case Js::OpCode::MOVUPS:
  989. case Js::OpCode::MOVHPD:
  990. if (!opr1->IsRegOpnd())
  991. {
  992. Assert(opr1->IsIndirOpnd() || opr1->IsMemRefOpnd() || opr1->IsSymOpnd());
  993. Assert(opr2->IsRegOpnd());
  994. Assert(REGNUM_ISXMMXREG(opr2->AsRegOpnd()->GetReg()));
  995. opcodeByte |= 0x01;
  996. }
  997. goto modrm;
  998. case Js::OpCode::NOP:
  999. if (instr->GetSrc1())
  1000. {
  1001. // Multibyte NOP.
  1002. Assert(instr->GetSrc1()->IsIntConstOpnd() && instr->GetSrc1()->GetType() == TyInt8);
  1003. unsigned nopSize = instr->GetSrc1()->AsIntConstOpnd()->AsUint32();
  1004. Assert(nopSize >= 2 && nopSize <= 4);
  1005. nopSize = max(2u, min(4u, nopSize)); // satisfy oacr
  1006. const BYTE *nopEncoding = Nop[nopSize - 1];
  1007. opcodeByte = nopEncoding[0];
  1008. for (unsigned i = 1; i < nopSize; i++)
  1009. {
  1010. *(m_pc)++ = nopEncoding[i];
  1011. }
  1012. }
  1013. skipRexByte = true;
  1014. break;
  1015. case Js::OpCode::XCHG:
  1016. if (instrSize == 1)
  1017. continue;
  1018. if (opr1->IsRegOpnd() && opr1->AsRegOpnd()->GetReg() == RegRAX
  1019. && opr2->IsRegOpnd())
  1020. {
  1021. uint8 reg = this->GetRegEncode(opr2->AsRegOpnd());
  1022. rexByte |= this->GetRexByte(REXR, opr2);
  1023. opcodeByte |= reg;
  1024. }
  1025. else if (opr2->IsRegOpnd() && opr2->AsRegOpnd()->GetReg() == RegRAX
  1026. && opr1->IsRegOpnd())
  1027. {
  1028. uint8 reg = this->GetRegEncode(opr1->AsRegOpnd());
  1029. rexByte |= this->GetRexByte(REXB, opr1);
  1030. opcodeByte |= reg;
  1031. }
  1032. else
  1033. {
  1034. continue;
  1035. }
  1036. break;
  1037. case Js::OpCode::PSLLDQ:
  1038. case Js::OpCode::PSRLDQ:
  1039. // SSE shift
  1040. Assert(opr1->IsRegOpnd());
  1041. rexByte |= this->EmitModRM(instr, opr1, this->GetOpcodeByte2(instr) >> 3);
  1042. break;
  1043. default:
  1044. AssertMsg(UNREACHED, "Unhandled opcode in SPECIAL form");
  1045. }
  1046. break;
  1047. case INVALID:
  1048. AssertMsg(UNREACHED, "No encoder form found");
  1049. return m_pc - instrStart;
  1050. default:
  1051. AssertMsg(UNREACHED, "Unhandled encoder form");
  1052. }
  1053. // If instr has W bit, set it appropriately.
  1054. if ((*form & WBIT) && !(opdope & DFLT) && instrSize != 1)
  1055. {
  1056. opcodeByte |= 0x1; // set WBIT
  1057. }
  1058. *popcodeByte = opcodeByte;
  1059. AssertMsg(m_pc - instrStart <= MachMaxInstrSize, "MachMaxInstrSize not set correctly");
  1060. // Near JMPs, all instructions that reference RSP implicitly and
  1061. // instructions that operate on registers smaller than 64 bits don't
  1062. // get a REX prefix.
  1063. EmitRexByte(prexByte, rexByte, skipRexByte || (instrSize < 8), reservedRexByte);
  1064. if (opdope & DSSE)
  1065. {
  1066. // extra imm8 byte for SSE instructions.
  1067. uint valueImm = 0;
  1068. if (src2 &&src2->IsIntConstOpnd())
  1069. {
  1070. valueImm = (uint)src2->AsIntConstOpnd()->GetImmediateValue(instr->m_func);
  1071. }
  1072. else
  1073. {
  1074. // src2(comparison byte) is missing in CMP instructions and is part of the opcode instead.
  1075. switch (instr->m_opcode)
  1076. {
  1077. case Js::OpCode::CMPLTPS:
  1078. case Js::OpCode::CMPLTPD:
  1079. valueImm = CMP_IMM8::LT;
  1080. break;
  1081. case Js::OpCode::CMPLEPS:
  1082. case Js::OpCode::CMPLEPD:
  1083. valueImm = CMP_IMM8::LE;
  1084. break;
  1085. case Js::OpCode::CMPEQPS:
  1086. case Js::OpCode::CMPEQPD:
  1087. valueImm = CMP_IMM8::EQ;
  1088. break;
  1089. case Js::OpCode::CMPNEQPS:
  1090. case Js::OpCode::CMPNEQPD:
  1091. valueImm = CMP_IMM8::NEQ;
  1092. break;
  1093. default:
  1094. Assert(UNREACHED);
  1095. }
  1096. }
  1097. *(m_pc++) = (valueImm & 0xff);
  1098. }
  1099. #if DEBUG
  1100. // Verify that the disassembly code for out-of-bounds typedArray handling can decode all the MOVs we emit.
  1101. // Call it on every MOV
  1102. if (LowererMD::IsAssign(instr) && (instr->GetDst()->IsIndirOpnd() || instr->GetSrc1()->IsIndirOpnd()))
  1103. {
  1104. CONTEXT context = { 0 };
  1105. EXCEPTION_POINTERS exceptionInfo;
  1106. exceptionInfo.ContextRecord = &context;
  1107. Js::ArrayAccessDecoder::InstructionData instrData;
  1108. BYTE *tempPc = instrStart;
  1109. instrData = Js::ArrayAccessDecoder::CheckValidInstr(tempPc, &exceptionInfo, instr->m_func->GetJnFunction());
  1110. // Make sure we can decode the instr
  1111. Assert(!instrData.isInvalidInstr);
  1112. // Verify the instruction size matches
  1113. Assert(instrData.instrSizeInByte == m_pc - instrStart);
  1114. // Note: We could verify other properties if deemed useful, like types, register values, etc...
  1115. }
  1116. #endif
  1117. return m_pc - instrStart;
  1118. }
  1119. }
  1120. void
  1121. EncoderMD::EmitRexByte(BYTE * prexByte, BYTE rexByte, bool skipRexByte, bool reservedRexByte)
  1122. {
  1123. if (skipRexByte)
  1124. {
  1125. // REX byte is not needed - let's remove it and move everything else by 1 byte
  1126. if (((rexByte)& 0x0F) == 0x8)
  1127. {
  1128. // If we didn't reserve the rex byte, we don't have to do anything
  1129. if (reservedRexByte)
  1130. {
  1131. Assert(m_pc > prexByte);
  1132. BYTE* current = prexByte;
  1133. while (current < m_pc)
  1134. {
  1135. *current = *(current + 1);
  1136. current++;
  1137. }
  1138. if (m_relocList != nullptr)
  1139. {
  1140. // if a reloc record was added as part of encoding this instruction - fix the pc in the reloc
  1141. EncodeRelocAndLabels &lastRelocEntry = m_relocList->Item(m_relocList->Count() - 1);
  1142. if (lastRelocEntry.m_ptr > prexByte && lastRelocEntry.m_ptr < m_pc)
  1143. {
  1144. Assert(lastRelocEntry.m_type != RelocTypeLabel);
  1145. lastRelocEntry.m_ptr = (BYTE*)lastRelocEntry.m_ptr - 1;
  1146. lastRelocEntry.m_origPtr = (BYTE*)lastRelocEntry.m_origPtr - 1;
  1147. }
  1148. }
  1149. }
  1150. return;
  1151. }
  1152. rexByte = rexByte & 0xF7;
  1153. }
  1154. // If we didn't reserve the rex byte, we need to move everything by 1 and make
  1155. // room for it.
  1156. if (!reservedRexByte)
  1157. {
  1158. Assert(m_pc > prexByte);
  1159. BYTE* current = m_pc;
  1160. while (current > prexByte)
  1161. {
  1162. *current = *(current - 1);
  1163. current--;
  1164. }
  1165. if (m_relocList != nullptr)
  1166. {
  1167. // if a reloc record was added as part of encoding this instruction - fix the pc in the reloc
  1168. EncodeRelocAndLabels &lastRelocEntry = m_relocList->Item(m_relocList->Count() - 1);
  1169. if (lastRelocEntry.m_ptr > prexByte && lastRelocEntry.m_ptr < m_pc)
  1170. {
  1171. Assert(lastRelocEntry.m_type != RelocTypeLabel);
  1172. lastRelocEntry.m_ptr = (BYTE*)lastRelocEntry.m_ptr + 1;
  1173. lastRelocEntry.m_origPtr = (BYTE*)lastRelocEntry.m_origPtr + 1;
  1174. }
  1175. }
  1176. m_pc++;
  1177. }
  1178. // Emit the rex byte
  1179. *prexByte = rexByte;
  1180. }
  1181. bool
  1182. EncoderMD::IsExtendedRegister(RegNum reg)
  1183. {
  1184. return REGNUM_ISXMMXREG(reg) ? (reg >= RegXMM8) : (reg >= RegR8);
  1185. }
  1186. int
  1187. EncoderMD::AppendRelocEntry(RelocType type, void *ptr, IR::LabelInstr *label)
  1188. {
  1189. if (m_relocList == nullptr)
  1190. m_relocList = Anew(m_encoder->m_tempAlloc, RelocList, m_encoder->m_tempAlloc);
  1191. EncodeRelocAndLabels reloc;
  1192. reloc.init(type, ptr, label);
  1193. return m_relocList->Add(reloc);
  1194. }
  1195. int
  1196. EncoderMD::FixRelocListEntry(uint32 index, int totalBytesSaved, BYTE *buffStart, BYTE* buffEnd)
  1197. {
  1198. BYTE* currentPc;
  1199. EncodeRelocAndLabels &relocRecord = m_relocList->Item(index);
  1200. int result = totalBytesSaved;
  1201. // LabelInstr ?
  1202. if (relocRecord.isLabel())
  1203. {
  1204. BYTE* newPC;
  1205. currentPc = relocRecord.getLabelCurrPC();
  1206. AssertMsg(currentPc >= buffStart && currentPc < buffEnd, "LabelInstr offset has to be within buffer.");
  1207. newPC = currentPc - totalBytesSaved;
  1208. // find the number of nops needed to align this loop top
  1209. if (relocRecord.isAlignedLabel() && !PHASE_OFF(Js::LoopAlignPhase, m_func))
  1210. {
  1211. ptrdiff_t diff = newPC - buffStart;
  1212. Assert(diff >= 0 && diff <= UINT_MAX);
  1213. uint32 offset = (uint32)diff;
  1214. // Since the final code buffer is page aligned, it is enough to align the offset of the label.
  1215. BYTE nopCount = (16 - (BYTE)(offset & 0xf)) % 16;
  1216. if (nopCount <= Js::Configuration::Global.flags.LoopAlignNopLimit)
  1217. {
  1218. // new label pc
  1219. newPC += nopCount;
  1220. relocRecord.setLabelNopCount(nopCount);
  1221. // adjust bytes saved
  1222. result -= nopCount;
  1223. }
  1224. }
  1225. relocRecord.setLabelCurrPC(newPC);
  1226. }
  1227. else
  1228. {
  1229. currentPc = (BYTE*) relocRecord.m_origPtr;
  1230. // ignore outside buffer offsets (e.g. JumpTable entries)
  1231. if (currentPc >= buffStart && currentPc < buffEnd)
  1232. {
  1233. if (relocRecord.m_type == RelocTypeInlineeEntryOffset)
  1234. {
  1235. // ptr points to imm32 offset of the instruction that needs to be adjusted
  1236. // offset is in top 28-bits, arg count in bottom 4
  1237. size_t field = *((size_t*) relocRecord.m_origPtr);
  1238. size_t offset = field >> 4;
  1239. uint32 count = field & 0xf;
  1240. AssertMsg(offset < (size_t)(buffEnd - buffStart), "Inlinee entry offset out of range");
  1241. *((size_t*) relocRecord.m_origPtr) = ((offset - totalBytesSaved) << 4) | count;
  1242. }
  1243. // adjust the ptr to the buffer itself
  1244. relocRecord.m_ptr = (BYTE*) relocRecord.m_ptr - totalBytesSaved;
  1245. }
  1246. }
  1247. return result;
  1248. }
  1249. void EncoderMD::AddLabelReloc(BYTE* relocAddress)
  1250. {
  1251. AppendRelocEntry(RelocTypeLabel, relocAddress);
  1252. }
  1253. ///----------------------------------------------------------------------------
  1254. ///
  1255. /// EncoderMD::FixMaps
  1256. /// Fixes the inlinee frame records and map based on BR shortening
  1257. ///
  1258. ///----------------------------------------------------------------------------
  1259. void
  1260. EncoderMD::FixMaps(uint32 brOffset, uint32 bytesSaved, uint32 *inlineeFrameRecordsIndex, uint32 *inlineeFrameMapIndex, uint32 *pragmaInstToRecordOffsetIndex, uint32 *offsetBuffIndex)
  1261. {
  1262. InlineeFrameRecords *recList = m_encoder->m_inlineeFrameRecords;
  1263. InlineeFrameMap *mapList = m_encoder->m_inlineeFrameMap;
  1264. PragmaInstrList *pInstrList = m_encoder->m_pragmaInstrToRecordOffset;
  1265. int32 i;
  1266. for (i = *inlineeFrameRecordsIndex; i < recList->Count() && recList->Item(i)->inlineeStartOffset <= brOffset; i++)
  1267. recList->Item(i)->inlineeStartOffset -= bytesSaved;
  1268. *inlineeFrameRecordsIndex = i;
  1269. for (i = *inlineeFrameMapIndex; i < mapList->Count() && mapList->Item(i).offset <= brOffset; i++)
  1270. mapList->Item(i).offset -= bytesSaved;
  1271. *inlineeFrameMapIndex = i;
  1272. for (i = *pragmaInstToRecordOffsetIndex; i < pInstrList->Count() && pInstrList->Item(i)->m_offsetInBuffer <= brOffset; i++)
  1273. pInstrList->Item(i)->m_offsetInBuffer -= bytesSaved;
  1274. *pragmaInstToRecordOffsetIndex = i;
  1275. #if DBG_DUMP
  1276. for (i = *offsetBuffIndex; (uint)i < m_encoder->m_instrNumber && m_encoder->m_offsetBuffer[i] <= brOffset; i++)
  1277. m_encoder->m_offsetBuffer[i] -= bytesSaved;
  1278. *offsetBuffIndex = i;
  1279. #endif
  1280. }
  1281. ///----------------------------------------------------------------------------
  1282. ///
  1283. /// EncoderMD::ApplyRelocs
  1284. ///
  1285. ///----------------------------------------------------------------------------
  1286. void
  1287. EncoderMD::ApplyRelocs(size_t codeBufferAddress_)
  1288. {
  1289. for (int32 i = 0; i < m_relocList->Count(); i++)
  1290. {
  1291. EncodeRelocAndLabels *reloc = &m_relocList->Item(i);
  1292. BYTE * relocAddress = (BYTE*)reloc->m_ptr;
  1293. uint32 pcrel;
  1294. switch (reloc->m_type)
  1295. {
  1296. case RelocTypeCallPcrel:
  1297. AssertMsg(UNREACHED, "PC relative calls not yet supported on amd64");
  1298. #if 0
  1299. {
  1300. pcrel = (uint32)(codeBufferAddress + (BYTE*)reloc->m_ptr - m_encoder->m_encodeBuffer + 4);
  1301. *(uint32 *)relocAddress -= pcrel;
  1302. break;
  1303. }
  1304. #endif
  1305. case RelocTypeBranch:
  1306. {
  1307. // The address of the target LabelInstr is saved at the reloc address.
  1308. IR::LabelInstr * labelInstr = reloc->getBrTargetLabel();
  1309. AssertMsg(labelInstr->GetPC() != nullptr, "Branch to unemitted label?");
  1310. if (reloc->isShortBr() )
  1311. {
  1312. // short branch
  1313. pcrel = (uint32)(labelInstr->GetPC() - ((BYTE*)reloc->m_ptr + 1));
  1314. AssertMsg((int32)pcrel >= -128 && (int32)pcrel <= 127, "Offset doesn't fit in imm8.");
  1315. *(BYTE*)relocAddress = (BYTE)pcrel;
  1316. }
  1317. else
  1318. {
  1319. pcrel = (uint32)(labelInstr->GetPC() - ((BYTE*)reloc->m_ptr + 4));
  1320. *(uint32 *)relocAddress = pcrel;
  1321. }
  1322. break;
  1323. }
  1324. case RelocTypeLabelUse:
  1325. {
  1326. IR::LabelInstr *labelInstr = *(IR::LabelInstr**)relocAddress;
  1327. AssertMsg(labelInstr->GetPC() != nullptr, "Branch to unemitted label?");
  1328. *(size_t *)relocAddress = (size_t)(labelInstr->GetPC() - m_encoder->m_encodeBuffer + codeBufferAddress_);
  1329. break;
  1330. }
  1331. case RelocTypeLabel:
  1332. case RelocTypeAlignedLabel:
  1333. case RelocTypeInlineeEntryOffset:
  1334. break;
  1335. default:
  1336. AssertMsg(UNREACHED, "Unknown reloc type");
  1337. }
  1338. }
  1339. }
  1340. #ifdef DBG
  1341. ///----------------------------------------------------------------------------
  1342. ///
  1343. /// EncodeRelocAndLabels::VerifyRelocList
  1344. /// Verify that the list of offsets within the encoder buffer range are in ascending order.
  1345. /// This includes offsets of immediate fields in the code and offsets of LabelInstrs
  1346. ///----------------------------------------------------------------------------
  1347. void
  1348. EncoderMD::VerifyRelocList(BYTE *buffStart, BYTE *buffEnd)
  1349. {
  1350. BYTE *last_pc = 0, *pc;
  1351. for (int32 i = 0; i < m_relocList->Count(); i ++)
  1352. {
  1353. EncodeRelocAndLabels &p = m_relocList->Item(i);
  1354. // LabelInstr ?
  1355. if (p.isLabel())
  1356. {
  1357. AssertMsg(p.m_ptr < buffStart || p.m_ptr >= buffEnd, "Invalid label instruction pointer.");
  1358. pc = ((IR::LabelInstr*)p.m_ptr)->GetPC();
  1359. AssertMsg(pc >= buffStart && pc < buffEnd, "LabelInstr offset has to be within buffer.");
  1360. }
  1361. else
  1362. pc = (BYTE*)p.m_ptr;
  1363. // The list is partially sorted, out of bound ptrs (JumpTable entries) don't follow.
  1364. if (pc >= buffStart && pc < buffEnd)
  1365. {
  1366. if (last_pc)
  1367. AssertMsg(pc >= last_pc, "Unordered reloc list.");
  1368. last_pc = pc;
  1369. }
  1370. }
  1371. }
  1372. #endif
  1373. BYTE
  1374. EncoderMD::GetRexByte(BYTE rexCode, IR::Opnd * opnd)
  1375. {
  1376. return this->GetRexByte(rexCode, opnd->AsRegOpnd()->GetReg());
  1377. }
  1378. BYTE
  1379. EncoderMD::GetRexByte(BYTE rexCode, RegNum reg)
  1380. {
  1381. if (this->IsExtendedRegister(reg))
  1382. {
  1383. return rexCode;
  1384. }
  1385. else
  1386. {
  1387. return 0;
  1388. }
  1389. }
  1390. void
  1391. EncoderMD::EncodeInlineeCallInfo(IR::Instr *instr, uint32 codeOffset)
  1392. {
  1393. Assert(instr->GetSrc1() &&
  1394. instr->GetSrc1()->IsAddrOpnd() &&
  1395. (instr->GetSrc1()->AsAddrOpnd()->m_address == (Js::Var)((size_t)instr->GetSrc1()->AsAddrOpnd()->m_address & 0xF)));
  1396. Js::Var inlineeCallInfo = 0;
  1397. // 60 (AMD64) bits on the InlineeCallInfo to store the
  1398. // offset of the start of the inlinee. We shouldn't have gotten here with more arguments
  1399. // than can fit in as many bits.
  1400. const bool encodeResult = Js::InlineeCallInfo::Encode(inlineeCallInfo,
  1401. ::Math::PointerCastToIntegral<uint32>(instr->GetSrc1()->AsAddrOpnd()->m_address), codeOffset);
  1402. Assert(encodeResult);
  1403. instr->GetSrc1()->AsAddrOpnd()->m_address = inlineeCallInfo;
  1404. }
  1405. bool EncoderMD::TryConstFold(IR::Instr *instr, IR::RegOpnd *regOpnd)
  1406. {
  1407. Assert(regOpnd->m_sym->IsConst());
  1408. if (regOpnd->m_sym->IsFloatConst())
  1409. {
  1410. return false;
  1411. }
  1412. bool isNotLargeConstant = Math::FitsInDWord(regOpnd->m_sym->GetLiteralConstValue_PostGlobOpt());
  1413. if (!isNotLargeConstant && (instr->m_opcode != Js::OpCode::MOV || !instr->GetDst()->IsRegOpnd()))
  1414. {
  1415. return false;
  1416. }
  1417. switch (GetInstrForm(instr))
  1418. {
  1419. case FORM_MOV:
  1420. if (!instr->GetSrc1()->IsRegOpnd())
  1421. {
  1422. return false;
  1423. }
  1424. break;
  1425. case FORM_PSHPOP:
  1426. if (instr->m_opcode != Js::OpCode::PUSH)
  1427. {
  1428. return false;
  1429. }
  1430. if (!instr->GetSrc1()->IsRegOpnd())
  1431. {
  1432. return false;
  1433. }
  1434. break;
  1435. case FORM_BINOP:
  1436. case FORM_SHIFT:
  1437. if (regOpnd != instr->GetSrc2())
  1438. {
  1439. return false;
  1440. }
  1441. break;
  1442. default:
  1443. return false;
  1444. }
  1445. if (regOpnd != instr->GetSrc1() && regOpnd != instr->GetSrc2())
  1446. {
  1447. if (!regOpnd->m_sym->IsConst() || regOpnd->m_sym->IsFloatConst())
  1448. {
  1449. return false;
  1450. }
  1451. // Check if it's the index opnd inside an indir
  1452. bool foundUse = false;
  1453. bool foldedAllUses = true;
  1454. IR::Opnd *const srcs[] = { instr->GetSrc1(), instr->GetSrc2(), instr->GetDst() };
  1455. for (int i = 0; i < sizeof(srcs) / sizeof(srcs[0]); ++i)
  1456. {
  1457. const auto src = srcs[i];
  1458. if (!src || !src->IsIndirOpnd())
  1459. {
  1460. continue;
  1461. }
  1462. const auto indir = src->AsIndirOpnd();
  1463. if (regOpnd == indir->GetBaseOpnd())
  1464. {
  1465. // Can't const-fold into the base opnd
  1466. foundUse = true;
  1467. foldedAllUses = false;
  1468. continue;
  1469. }
  1470. if (regOpnd != indir->GetIndexOpnd())
  1471. {
  1472. continue;
  1473. }
  1474. foundUse = true;
  1475. if (!regOpnd->m_sym->IsIntConst())
  1476. {
  1477. foldedAllUses = false;
  1478. continue;
  1479. }
  1480. // offset = indir.offset + (index << scale)
  1481. int32 offset = regOpnd->m_sym->GetIntConstValue();
  1482. if (indir->GetScale() != 0 && Int32Math::Shl(offset, indir->GetScale(), &offset) ||
  1483. indir->GetOffset() != 0 && Int32Math::Add(indir->GetOffset(), offset, &offset))
  1484. {
  1485. foldedAllUses = false;
  1486. continue;
  1487. }
  1488. indir->SetOffset(offset);
  1489. indir->SetIndexOpnd(nullptr);
  1490. }
  1491. return foundUse && foldedAllUses;
  1492. }
  1493. instr->ReplaceSrc(regOpnd, regOpnd->m_sym->GetConstOpnd());
  1494. return true;
  1495. }
  1496. bool EncoderMD::TryFold(IR::Instr *instr, IR::RegOpnd *regOpnd)
  1497. {
  1498. IR::Opnd *src1 = instr->GetSrc1();
  1499. IR::Opnd *src2 = instr->GetSrc2();
  1500. switch (GetInstrForm(instr))
  1501. {
  1502. case FORM_MOV:
  1503. if (!instr->GetDst()->IsRegOpnd() || regOpnd != src1)
  1504. {
  1505. return false;
  1506. }
  1507. break;
  1508. case FORM_BINOP:
  1509. if (regOpnd == src1 && instr->m_opcode == Js::OpCode::CMP && (src2->IsRegOpnd() || src1->IsImmediateOpnd()))
  1510. {
  1511. IR::Instr *instrNext = instr->GetNextRealInstrOrLabel();
  1512. if (instrNext->IsBranchInstr() && instrNext->AsBranchInstr()->IsConditional())
  1513. {
  1514. // Swap src and reverse branch
  1515. src2 = instr->UnlinkSrc1();
  1516. src1 = instr->UnlinkSrc2();
  1517. instr->SetSrc1(src1);
  1518. instr->SetSrc2(src2);
  1519. LowererMD::ReverseBranch(instrNext->AsBranchInstr());
  1520. }
  1521. else
  1522. {
  1523. return false;
  1524. }
  1525. }
  1526. if (regOpnd != src2 || !src1->IsRegOpnd())
  1527. {
  1528. return false;
  1529. }
  1530. break;
  1531. case FORM_MODRM:
  1532. if (src2 == nullptr)
  1533. {
  1534. if (!instr->GetDst()->IsRegOpnd() || regOpnd != src1 || EncoderMD::IsOPEQ(instr))
  1535. {
  1536. return false;
  1537. }
  1538. }
  1539. else
  1540. {
  1541. if (regOpnd != src2 || !src1->IsRegOpnd())
  1542. {
  1543. return false;
  1544. }
  1545. }
  1546. break;
  1547. case FORM_PSHPOP:
  1548. if (instr->m_opcode != Js::OpCode::PUSH)
  1549. {
  1550. return false;
  1551. }
  1552. if (!instr->GetSrc1()->IsRegOpnd())
  1553. {
  1554. return false;
  1555. }
  1556. break;
  1557. case FORM_TEST:
  1558. if (regOpnd == src1)
  1559. {
  1560. if (!src2->IsRegOpnd() && !src2->IsIntConstOpnd())
  1561. {
  1562. return false;
  1563. }
  1564. }
  1565. else if (src1->IsRegOpnd())
  1566. {
  1567. instr->SwapOpnds();
  1568. }
  1569. else
  1570. {
  1571. return false;
  1572. }
  1573. break;
  1574. default:
  1575. return false;
  1576. }
  1577. IR::SymOpnd *symOpnd = IR::SymOpnd::New(regOpnd->m_sym, regOpnd->GetType(), instr->m_func);
  1578. instr->ReplaceSrc(regOpnd, symOpnd);
  1579. return true;
  1580. }
  1581. bool EncoderMD::SetsConditionCode(IR::Instr *instr)
  1582. {
  1583. return instr->IsLowered() && (EncoderMD::GetOpdope(instr) & DSETCC);
  1584. }
  1585. bool EncoderMD::UsesConditionCode(IR::Instr *instr)
  1586. {
  1587. return instr->IsLowered() && (EncoderMD::GetOpdope(instr) & DUSECC);
  1588. }
  1589. bool EncoderMD::IsOPEQ(IR::Instr *instr)
  1590. {
  1591. return instr->IsLowered() && (EncoderMD::GetOpdope(instr) & DOPEQ);
  1592. }
  1593. void EncoderMD::UpdateRelocListWithNewBuffer(RelocList * relocList, BYTE * newBuffer, BYTE * oldBufferStart, BYTE * oldBufferEnd)
  1594. {
  1595. for (int32 i = 0; i < relocList->Count(); i++)
  1596. {
  1597. EncodeRelocAndLabels &reloc = relocList->Item(i);
  1598. if (reloc.isLabel())
  1599. {
  1600. IR::LabelInstr* label = reloc.getLabel();
  1601. BYTE* labelPC = label->GetPC();
  1602. Assert((BYTE*) reloc.m_origPtr >= oldBufferStart && (BYTE*) reloc.m_origPtr < oldBufferEnd);
  1603. label->SetPC(labelPC - oldBufferStart + newBuffer);
  1604. // nothing more to be done for a label
  1605. continue;
  1606. }
  1607. else if (reloc.m_type >= RelocTypeBranch && reloc.m_type <= RelocTypeLabelUse &&
  1608. (BYTE*) reloc.m_origPtr >= oldBufferStart && (BYTE*) reloc.m_origPtr < oldBufferEnd)
  1609. {
  1610. // we need to relocate all new offset that were originally within buffer
  1611. reloc.m_ptr = (BYTE*) reloc.m_ptr - oldBufferStart + newBuffer;
  1612. }
  1613. }
  1614. }