EncoderMD.cpp 56 KB

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