EncoderMD.cpp 55 KB

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