EncoderMD.cpp 77 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "Backend.h"
  6. #include "ARMEncode.h"
  7. #include "Language/JavascriptFunctionArgIndex.h"
  8. const FormTable * InstrEncode[]={
  9. #define MACRO(name, jnLayout, attrib, byte2, form, opbyte, ...) opbyte,
  10. #include "MdOpCodes.h"
  11. #undef ASMDAT
  12. };
  13. ///----------------------------------------------------------------------------
  14. ///
  15. /// EncoderMD::Init
  16. ///
  17. ///----------------------------------------------------------------------------
  18. void
  19. EncoderMD::Init(Encoder *encoder)
  20. {
  21. m_encoder = encoder;
  22. m_relocList = nullptr;
  23. }
  24. ///----------------------------------------------------------------------------
  25. ///
  26. /// EncoderMD::GetRegEncode
  27. ///
  28. /// Get the encoding of a given register.
  29. ///
  30. ///----------------------------------------------------------------------------
  31. const BYTE
  32. EncoderMD::GetRegEncode(IR::RegOpnd *regOpnd)
  33. {
  34. return GetRegEncode(regOpnd->GetReg());
  35. }
  36. const BYTE
  37. EncoderMD::GetRegEncode(RegNum reg)
  38. {
  39. return RegEncode[reg];
  40. }
  41. const BYTE
  42. EncoderMD::GetFloatRegEncode(IR::RegOpnd *regOpnd)
  43. {
  44. //Each double register holds two single precision registers.
  45. BYTE regEncode = GetRegEncode(regOpnd->GetReg()) * 2;
  46. AssertMsg(regEncode <= LAST_FLOAT_REG_NUM, "Impossible to allocate higher registers on VFP");
  47. return regEncode;
  48. }
  49. ///----------------------------------------------------------------------------
  50. ///
  51. /// EncoderMD::GetOpdope
  52. ///
  53. /// Get the dope vector of a particular instr. The dope vector describes
  54. /// certain properties of an instr.
  55. ///
  56. ///----------------------------------------------------------------------------
  57. uint32
  58. EncoderMD::GetOpdope(IR::Instr *instr)
  59. {
  60. return GetOpdope(instr->m_opcode);
  61. }
  62. uint32
  63. EncoderMD::GetOpdope(Js::OpCode op)
  64. {
  65. return Opdope[op - (Js::OpCode::MDStart+1)];
  66. }
  67. //
  68. // EncoderMD::CanonicalizeInstr :
  69. // Put the instruction in its final form for encoding. This may involve
  70. // expanding a pseudo-op such as LEA or changing an opcode to indicate the
  71. // op bits the encoder should use.
  72. //
  73. // Return the size of the final instruction's encoding.
  74. //
  75. InstructionType EncoderMD::CanonicalizeInstr(IR::Instr* instr)
  76. {
  77. if (!instr->IsLowered())
  78. {
  79. return InstructionType::None;
  80. }
  81. switch (instr->m_opcode)
  82. {
  83. CASE_OPCODES_ALWAYS_THUMB2
  84. return InstructionType::Thumb2;
  85. CASE_OPCODES_NEVER_THUMB2
  86. return InstructionType::Thumb;
  87. case Js::OpCode::MOV:
  88. return this->CanonicalizeMov(instr);
  89. case Js::OpCode::B:
  90. return InstructionType::Thumb2; // For now only T2 branches are encoded
  91. case Js::OpCode::BL:
  92. return InstructionType::Thumb2;
  93. case Js::OpCode::BNE:
  94. case Js::OpCode::BEQ:
  95. case Js::OpCode::BLT:
  96. case Js::OpCode::BLE:
  97. case Js::OpCode::BGE:
  98. case Js::OpCode::BGT:
  99. case Js::OpCode::BCS:
  100. case Js::OpCode::BCC:
  101. case Js::OpCode::BHI:
  102. case Js::OpCode::BLS:
  103. case Js::OpCode::BMI:
  104. case Js::OpCode::BPL:
  105. case Js::OpCode::BVS:
  106. case Js::OpCode::BVC:
  107. return InstructionType::Thumb2; // For now only T2 branches are encoded
  108. case Js::OpCode::CMP:
  109. return this->CmpEncodeType(instr);
  110. case Js::OpCode::CMN:
  111. return this->CmnEncodeType(instr);
  112. case Js::OpCode::CMP_ASR31:
  113. return InstructionType::Thumb2;
  114. case Js::OpCode::POP:
  115. return this->PushPopEncodeType(instr->GetSrc1()->AsIndirOpnd(), instr->GetDst()->AsRegBVOpnd());
  116. case Js::OpCode::PUSH:
  117. return this->PushPopEncodeType(instr->GetDst()->AsIndirOpnd(), instr->GetSrc1()->AsRegBVOpnd());
  118. case Js::OpCode::LDR:
  119. return this->CanonicalizeLoad(instr);
  120. case Js::OpCode::STR:
  121. return this->CanonicalizeStore(instr);
  122. case Js::OpCode::LEA:
  123. return this->CanonicalizeLea(instr);
  124. case Js::OpCode::ADD:
  125. case Js::OpCode::ADDS:
  126. return this->CanonicalizeAdd(instr);
  127. case Js::OpCode::SUB:
  128. case Js::OpCode::SUBS:
  129. return this->CanonicalizeSub(instr);
  130. case Js::OpCode::AND:
  131. case Js::OpCode::EOR:
  132. case Js::OpCode::MUL:
  133. case Js::OpCode::ORR:
  134. case Js::OpCode::RSB:
  135. case Js::OpCode::RSBS:
  136. case Js::OpCode::BIC:
  137. return this->Alu3EncodeType(instr);
  138. case Js::OpCode::EOR_ASR31:
  139. return InstructionType::Thumb2;
  140. case Js::OpCode::SMULL:
  141. case Js::OpCode::SMLAL:
  142. return InstructionType::Thumb2;
  143. case Js::OpCode::MVN:
  144. return this->Alu2EncodeType(instr->GetDst(), instr->GetSrc1());
  145. case Js::OpCode::TST:
  146. return this->Alu2EncodeType(instr->GetSrc1(), instr->GetSrc2());
  147. case Js::OpCode::ASR:
  148. case Js::OpCode::ASRS:
  149. case Js::OpCode::LSL:
  150. case Js::OpCode::LSR:
  151. return this->ShiftEncodeType(instr);
  152. case Js::OpCode::VSTR:
  153. case Js::OpCode::VSTR32:
  154. case Js::OpCode::VLDR:
  155. case Js::OpCode::VLDR32:
  156. case Js::OpCode::VABS:
  157. case Js::OpCode::VSQRT:
  158. case Js::OpCode::VMOV:
  159. case Js::OpCode::VMOVARMVFP:
  160. case Js::OpCode::VCVTF64F32:
  161. case Js::OpCode::VCVTF32F64:
  162. case Js::OpCode::VCVTF64S32:
  163. case Js::OpCode::VCVTF64U32:
  164. case Js::OpCode::VCVTS32F64:
  165. case Js::OpCode::VCVTRS32F64:
  166. case Js::OpCode::VPUSH:
  167. case Js::OpCode::VPOP:
  168. case Js::OpCode::VADDF64:
  169. case Js::OpCode::VSUBF64:
  170. case Js::OpCode::VMULF64:
  171. case Js::OpCode::VDIVF64:
  172. case Js::OpCode::VNEGF64:
  173. case Js::OpCode::VCMPF64:
  174. case Js::OpCode::VMRS:
  175. case Js::OpCode::VMRSR:
  176. case Js::OpCode::VMSR:
  177. return InstructionType::Vfp;
  178. default:
  179. AssertMsg(UNREACHED, "Unexpected opcode in IsInstrThumb2");
  180. return InstructionType::None;
  181. }
  182. }
  183. // CanonicalizeMov: Determine the size of the encoding and change the opcode
  184. // if necessary to indicate a wide instruction. (We do this for MOV, LDR, and STR
  185. // to cut down on the time it takes to search all the possible forms.)
  186. InstructionType EncoderMD::CanonicalizeMov(IR::Instr * instr)
  187. {
  188. // 3 possibilities:
  189. // 1. MOV (T1):
  190. // - uint8 to low reg
  191. // - any reg to reg
  192. // 2. MOVW (T2):
  193. // - uint16 to reg
  194. // 3. MOV_W (T2):
  195. // - mod const imm to reg
  196. IR::RegOpnd *dstOpnd = instr->GetDst()->AsRegOpnd();
  197. IR::Opnd *srcOpnd = instr->GetSrc1();
  198. if (srcOpnd->IsRegOpnd())
  199. {
  200. // All reg to reg copies are 2 bytes.
  201. return InstructionType::Thumb;
  202. }
  203. IntConstType immed = srcOpnd->GetImmediateValue();
  204. if (IS_LOWREG(dstOpnd->GetReg()) &&
  205. IS_CONST_UINT8(immed))
  206. {
  207. // uint8 -> low reg
  208. return InstructionType::Thumb;
  209. }
  210. // Wide MOV instruction. Choose the opcode based on the constant.
  211. if (IS_CONST_UINT16(immed))
  212. {
  213. instr->m_opcode = Js::OpCode::MOVW;
  214. }
  215. else
  216. {
  217. Assert(CanEncodeModConst12(immed));
  218. instr->m_opcode = Js::OpCode::MOV_W;
  219. }
  220. return InstructionType::Thumb2;
  221. }
  222. // CanonicalizeLoad: Determine the size of the encoding and change the opcode
  223. // if necessary to indicate a wide instruction. (We do this for MOV, LDR, and STR
  224. // to cut down on the time it takes to search all the possible forms.)
  225. InstructionType EncoderMD::CanonicalizeLoad(IR::Instr * instr)
  226. {
  227. IR::Opnd *memOpnd = instr->GetSrc1();
  228. // Note: sign-extension of less-than-4-byte loads requires a wide instruction.
  229. if (memOpnd->GetSize() == 4 || memOpnd->IsUnsigned())
  230. {
  231. if (!this->IsWideMemInstr(instr->GetSrc1(), instr->GetDst()->AsRegOpnd()))
  232. {
  233. return InstructionType::Thumb;
  234. }
  235. }
  236. instr->m_opcode = Js::OpCode::LDR_W;
  237. return InstructionType::Thumb2;
  238. }
  239. // CanonicalizeStore: Determine the size of the encoding and change the opcode
  240. // if necessary to indicate a wide instruction. (We do this for MOV, LDR, and STR
  241. // to cut down on the time it takes to search all the possible forms.)
  242. InstructionType EncoderMD::CanonicalizeStore(IR::Instr * instr)
  243. {
  244. if (this->IsWideMemInstr(instr->GetDst(), instr->GetSrc1()->AsRegOpnd()))
  245. {
  246. instr->m_opcode = Js::OpCode::STR_W;
  247. return InstructionType::Thumb2;
  248. }
  249. return InstructionType::Thumb;
  250. }
  251. // IsWideMemInstr: Shared by LDR and STR.
  252. // Determine the width of the encoding based on the operand properties.
  253. bool EncoderMD::IsWideMemInstr(IR::Opnd *memOpnd, IR::RegOpnd *regOpnd)
  254. {
  255. // LDR/STR rn, [rbase + rindex], or
  256. // LDR/STR rn, [rbase + offset]
  257. // If rn is not low reg, instr is wide.
  258. if (!IS_LOWREG(regOpnd->GetReg()))
  259. {
  260. return true;
  261. }
  262. // Pull the base and index/offset from the indirection.
  263. RegNum baseReg;
  264. IR::RegOpnd *indexOpnd;
  265. int32 offset;
  266. if (memOpnd->IsSymOpnd())
  267. {
  268. indexOpnd = nullptr;
  269. this->BaseAndOffsetFromSym(memOpnd->AsSymOpnd(), &baseReg, &offset, this->m_func);
  270. }
  271. else
  272. {
  273. IR::IndirOpnd *indirOpnd = memOpnd->AsIndirOpnd();
  274. // Scaled index operands require wide instruction.
  275. if (indirOpnd->GetScale() > 0)
  276. {
  277. return true;
  278. }
  279. baseReg = indirOpnd->GetBaseOpnd()->GetReg();
  280. indexOpnd = indirOpnd->GetIndexOpnd();
  281. offset = indirOpnd->GetOffset();
  282. }
  283. Assert(offset == 0 || indexOpnd == nullptr);
  284. if (indexOpnd)
  285. {
  286. // Both base and index must be low regs.
  287. return !IS_LOWREG(baseReg) || !IS_LOWREG(indexOpnd->GetReg());
  288. }
  289. else
  290. {
  291. size_t size = memOpnd->GetSize();
  292. if (!IS_LOWREG(baseReg) && (baseReg != RegSP || size != 4))
  293. {
  294. // Base reg must be low or SP (and we only have 4-byte SP-relative ops).
  295. return true;
  296. }
  297. // Short encodings shift the offset based on the size of the load/store.
  298. // (E.g., 4-byte load shifts the offset by 2.)
  299. if (offset & (size - 1))
  300. {
  301. // Can't use a short encoding if we lose bits by shifting the offset.
  302. return true;
  303. }
  304. uint32 shiftBits = Math::Log2(size);
  305. if (baseReg == RegSP)
  306. {
  307. // LDR/STR rn, [SP + uint8:00]
  308. return !IS_CONST_UINT8(offset >> shiftBits);
  309. }
  310. else
  311. {
  312. // LDR/STR rn, [base + uint5:size]
  313. return !IS_CONST_UINT5(offset >> shiftBits);
  314. }
  315. }
  316. }
  317. InstructionType EncoderMD::CanonicalizeAdd(IR::Instr * instr)
  318. {
  319. IR::Opnd *src2 = instr->GetSrc2();
  320. IntConstType immed = 0;
  321. // Check cases that apply to ADD but not SUB.
  322. if (src2->IsRegOpnd())
  323. {
  324. // Check for rm = ADD rm, rn
  325. if (instr->m_opcode != Js::OpCode::ADDS &&
  326. instr->GetDst()->AsRegOpnd()->IsSameReg(instr->GetSrc1()))
  327. {
  328. return InstructionType::Thumb;
  329. }
  330. }
  331. else
  332. {
  333. immed = src2->GetImmediateValue();
  334. // Check for rm = ADD SP, uint8:00
  335. if (IS_LOWREG(instr->GetDst()->AsRegOpnd()->GetReg()))
  336. {
  337. if (instr->GetSrc1()->AsRegOpnd()->GetReg() == RegSP)
  338. {
  339. if ((immed & 3) == 0 && IS_CONST_UINT8(immed >> 2))
  340. {
  341. return InstructionType::Thumb;
  342. }
  343. }
  344. }
  345. }
  346. // Now check the shared ADD/SUB cases.
  347. if (this->IsWideAddSub(instr))
  348. {
  349. // The instr is definitely wide. Let the opcode indicate that if we're using the uint12 form.
  350. // Note that the uint12 form can't set the status bits.
  351. if (!src2->IsRegOpnd() && !this->CanEncodeModConst12(immed))
  352. {
  353. Assert(instr->m_opcode != Js::OpCode::ADDS);
  354. Assert(IS_CONST_UINT12(immed));
  355. instr->m_opcode = Js::OpCode::ADDW;
  356. }
  357. return InstructionType::Thumb2;
  358. }
  359. return InstructionType::Thumb;
  360. }
  361. InstructionType EncoderMD::CanonicalizeSub(IR::Instr * instr)
  362. {
  363. if (this->IsWideAddSub(instr))
  364. {
  365. IR::Opnd *src2 = instr->GetSrc2();
  366. // The instr is definitely wide. Let the opcode indicate that if we're using the uint12 form.
  367. // Note that the uint12 form can't set the status bits.
  368. if (!src2->IsRegOpnd() && !this->CanEncodeModConst12(src2->GetImmediateValue()))
  369. {
  370. Assert(instr->m_opcode != Js::OpCode::SUBS);
  371. Assert(IS_CONST_UINT12(src2->GetImmediateValue()));
  372. instr->m_opcode = Js::OpCode::SUBW;
  373. }
  374. return InstructionType::Thumb2;
  375. }
  376. return InstructionType::Thumb;
  377. }
  378. bool EncoderMD::IsWideAddSub(IR::Instr * instr)
  379. {
  380. IR::RegOpnd *dst = instr->GetDst()->AsRegOpnd();
  381. IR::RegOpnd *src1 = instr->GetSrc1()->AsRegOpnd();
  382. IR::Opnd *src2 = instr->GetSrc2();
  383. IntConstType immed;
  384. if (dst->GetReg() == RegSP)
  385. {
  386. // The one short form is SP = op SP, uint7:00
  387. if (src1->GetReg() != RegSP)
  388. {
  389. return true;
  390. }
  391. if (src2->IsRegOpnd())
  392. {
  393. return true;
  394. }
  395. immed = src2->GetImmediateValue();
  396. return ((immed & 3) != 0) || !IS_CONST_UINT7(immed >> 2);
  397. }
  398. else
  399. {
  400. // low1 = op low2, low3 or
  401. // low1 = op low2, uint3 or
  402. // low1 = op low1, uint8
  403. if (!IS_LOWREG(dst->GetReg()) || !IS_LOWREG(src1->GetReg()))
  404. {
  405. return true;
  406. }
  407. if (src2->IsRegOpnd())
  408. {
  409. return !IS_LOWREG(src2->AsRegOpnd()->GetReg());
  410. }
  411. else
  412. {
  413. immed = src2->GetImmediateValue();
  414. return dst->IsSameReg(src1) ? !IS_CONST_UINT8(immed) : !IS_CONST_UINT3(immed);
  415. }
  416. }
  417. }
  418. InstructionType EncoderMD::CanonicalizeLea(IR::Instr * instr)
  419. {
  420. RegNum baseReg;
  421. int32 offset;
  422. IR::Opnd* src1 = instr->UnlinkSrc1();
  423. if (src1->IsSymOpnd())
  424. {
  425. // We may as well turn this LEA into the equivalent ADD instruction and let the common ADD
  426. // logic handle it.
  427. IR::SymOpnd *symOpnd = src1->AsSymOpnd();
  428. this->BaseAndOffsetFromSym(symOpnd, &baseReg, &offset, this->m_func);
  429. symOpnd->Free(this->m_func);
  430. instr->SetSrc1(IR::RegOpnd::New(nullptr, baseReg, TyMachReg, this->m_func));
  431. instr->SetSrc2(IR::IntConstOpnd::New(offset, TyMachReg, this->m_func));
  432. }
  433. else
  434. {
  435. IR::IndirOpnd *indirOpnd = src1->AsIndirOpnd();
  436. IR::RegOpnd *baseOpnd = indirOpnd->GetBaseOpnd();
  437. IR::RegOpnd *indexOpnd = indirOpnd->GetIndexOpnd();
  438. offset = indirOpnd->GetOffset();
  439. Assert(offset == 0 || indexOpnd == nullptr);
  440. instr->SetSrc1(baseOpnd);
  441. if (indexOpnd)
  442. {
  443. AssertMsg(indirOpnd->GetScale() == 0, "NYI Needs shifted register support for ADD");
  444. instr->SetSrc2(indexOpnd);
  445. }
  446. else
  447. {
  448. instr->SetSrc2(IR::IntConstOpnd::New(offset, TyMachReg, this->m_func));
  449. }
  450. indirOpnd->Free(this->m_func);
  451. }
  452. instr->m_opcode = Js::OpCode::ADD;
  453. return this->CanonicalizeAdd(instr);
  454. }
  455. InstructionType EncoderMD::CmpEncodeType(IR::Instr * instr)
  456. {
  457. // CMP:
  458. // - low reg, uint8
  459. // - any reg, any reg
  460. IR::Opnd *src2 = instr->GetSrc2();
  461. if (src2->IsRegOpnd())
  462. {
  463. Assert(instr->GetSrc1()->IsRegOpnd());
  464. return InstructionType::Thumb;
  465. }
  466. if (IS_LOWREG(instr->GetSrc1()->AsRegOpnd()->GetReg()) &&
  467. IS_CONST_UINT8(src2->GetImmediateValue()))
  468. {
  469. return InstructionType::Thumb;
  470. }
  471. return InstructionType::Thumb2;
  472. }
  473. InstructionType EncoderMD::CmnEncodeType(IR::Instr * instr)
  474. {
  475. // CMN:
  476. // - low reg, low reg
  477. // - any reg, uint8
  478. // - any reg, any reg
  479. IR::Opnd *src2 = instr->GetSrc2();
  480. if (src2->IsRegOpnd())
  481. {
  482. // low reg, low reg
  483. if (IS_LOWREG(instr->GetSrc1()->AsRegOpnd()->GetReg()) && IS_LOWREG(instr->GetSrc2()->AsRegOpnd()->GetReg()))
  484. {
  485. return InstructionType::Thumb;
  486. }
  487. }
  488. // any reg, uint8
  489. // any reg, any reg
  490. return InstructionType::Thumb2;
  491. }
  492. InstructionType EncoderMD::PushPopEncodeType(IR::IndirOpnd *target, IR::RegBVOpnd * opnd)
  493. {
  494. if(target->GetBaseOpnd()->GetReg() != RegSP)
  495. {
  496. return InstructionType::Thumb2;
  497. }
  498. // NOTE: because T1 encoding permits LR here, we could theoretically check for it specially,
  499. // but in practice we never push LR without R11, so it would never help. If that changes, we
  500. // should make this function smarter.
  501. BYTE lastRegEncode = (BYTE)opnd->m_value.GetPrevBit();
  502. Assert(lastRegEncode != BVInvalidIndex);
  503. return lastRegEncode > RegEncode[RegR7] ? InstructionType::Thumb2 : InstructionType::Thumb;
  504. }
  505. InstructionType EncoderMD::Alu2EncodeType(IR::Opnd *opnd1, IR::Opnd *opnd2)
  506. {
  507. // Shared by TST (checks src1 and src2) and MVN (checks dst and src1), which is why we pass
  508. // operands rather than the whole instruction.
  509. // Short encoding requires two low regs as operands.
  510. if (!opnd1->IsRegOpnd() || !IS_LOWREG(opnd1->AsRegOpnd()->GetReg()))
  511. {
  512. return InstructionType::Thumb2;
  513. }
  514. if (!opnd2->IsRegOpnd() || !IS_LOWREG(opnd2->AsRegOpnd()->GetReg()))
  515. {
  516. return InstructionType::Thumb2;
  517. }
  518. return InstructionType::Thumb;
  519. }
  520. InstructionType EncoderMD::Alu3EncodeType(IR::Instr * instr)
  521. {
  522. // Check for rm = op rm, rn
  523. IR::RegOpnd *dst = instr->GetDst()->AsRegOpnd();
  524. if (!IS_LOWREG(dst->GetReg()) ||
  525. !dst->IsSameReg(instr->GetSrc1()))
  526. {
  527. return InstructionType::Thumb2;
  528. }
  529. IR::Opnd *src2 = instr->GetSrc2();
  530. if (!src2->IsRegOpnd() || !IS_LOWREG(src2->AsRegOpnd()->GetReg()))
  531. {
  532. return InstructionType::Thumb2;
  533. }
  534. return InstructionType::Thumb;
  535. }
  536. InstructionType EncoderMD::ShiftEncodeType(IR::Instr * instr)
  537. {
  538. // 2 short forms:
  539. // rm = op rn, uint5
  540. // rm = op rm, rn
  541. IR::RegOpnd *dst = instr->GetDst()->AsRegOpnd();
  542. if (!IS_LOWREG(dst->GetReg()))
  543. {
  544. return InstructionType::Thumb2;
  545. }
  546. IR::RegOpnd *src1 = instr->GetSrc1()->AsRegOpnd();
  547. IR::Opnd *src2 = instr->GetSrc2();
  548. if (src2->IsRegOpnd())
  549. {
  550. return (IS_LOWREG(src2->AsRegOpnd()->GetReg()) && dst->IsSameReg(src1)) ? InstructionType::Thumb : InstructionType::Thumb2;
  551. }
  552. else
  553. {
  554. Assert(IS_CONST_UINT5(src2->GetImmediateValue()));
  555. return IS_LOWREG(src1->GetReg()) ? InstructionType::Thumb : InstructionType::Thumb2;
  556. }
  557. }
  558. int
  559. EncoderMD::IndirForm(int form, int *pOpnnum, RegNum baseReg, IR::Opnd *indexOpnd)
  560. {
  561. int opnnum = *pOpnnum;
  562. form |= FSRC(INDIR, opnnum++);
  563. switch (baseReg)
  564. {
  565. case RegSP:
  566. form |= FSRC(SP, opnnum++);
  567. break ;
  568. case RegPC:
  569. form |= FSRC(PC, opnnum++);
  570. break;
  571. default:
  572. form |= FSRC(REG, opnnum++);
  573. break;
  574. }
  575. if (indexOpnd == nullptr)
  576. {
  577. // UTC does this for OPBASED. Seems to be based on the assumption
  578. // that we have either an offset or an index, but not both.
  579. form |= FSRC(CONST, opnnum++); // OFFSET
  580. }
  581. else
  582. {
  583. form |= FSRC(REG, opnnum++); // INDEX
  584. }
  585. *pOpnnum = opnnum;
  586. return form;
  587. }
  588. //---------------------------------------------------------------------------
  589. //
  590. // CoGenIForms()
  591. //
  592. // parses the instruction tuple and generates the corresponding 'form' constant
  593. //
  594. //---------------------------------------------------------------------------
  595. int
  596. EncoderMD::GetForm(IR::Instr *instr, int32 size)
  597. {
  598. int form;
  599. int opnnum; //Current looping operand in the instruction
  600. int operands; //Represents if the current operand is dst or source
  601. RegNum regNum;
  602. IR::Opnd* dst;
  603. IR::Opnd* opn;
  604. IR::IndirOpnd *indirOpnd;
  605. bool sameSrcDst = false;
  606. bool T2instr = false;
  607. form = 0;
  608. T2instr = (size == 4);
  609. // Set THUMB or THUMB2 instruction, this is to figure out if the form is T2 or T1.
  610. if (T2instr)
  611. {
  612. form |= FTHUMB2;
  613. }
  614. else
  615. {
  616. sameSrcDst = true;
  617. form |= FTHUMB;
  618. }
  619. dst = instr->GetDst();
  620. if (dst == nullptr || LowererMD::IsCall(instr))
  621. {
  622. opn = instr->GetSrc1();
  623. opnnum = 1;
  624. operands = 1;
  625. if (instr->IsBranchInstr() && instr->AsBranchInstr()->GetTarget())
  626. {
  627. // Treat the label reference as the first source.
  628. form |= FSRC(LABEL, opnnum++);
  629. }
  630. }
  631. else
  632. {
  633. opn = dst;
  634. opnnum = 0;
  635. operands = 0;
  636. }
  637. bool done = false;
  638. while (opn != nullptr)
  639. {
  640. switch (opn->GetKind())
  641. {
  642. case IR::OpndKindIntConst:
  643. case IR::OpndKindFloatConst:
  644. case IR::OpndKindAddr: //UTC - CASE_DATAADDRTUPLE
  645. {
  646. form |= FSRC(CONST, opnnum++);
  647. }
  648. break;
  649. case IR::OpndKindReg:
  650. {
  651. regNum = opn->AsRegOpnd()->GetReg();
  652. switch (regNum)
  653. {
  654. case RegSP:
  655. case RegPC:
  656. if (size != 4 || instr->m_opcode == Js::OpCode::LDRRET)
  657. {
  658. if (regNum == RegSP)
  659. {
  660. form |= FSRC(SP, opnnum++);
  661. }
  662. else
  663. {
  664. form |= FSRC(PC, opnnum++);
  665. }
  666. break;
  667. }
  668. // FALL THROUGH!
  669. default:
  670. if (regNum >= RegR0 && regNum <= RegPC)
  671. {
  672. if ((regNum > RegR7) && (!T2instr))
  673. {
  674. form |= FSET(REG,28);
  675. }
  676. if (operands == 0)
  677. { // dst operands
  678. form |= FSRC(REG,opnnum++);
  679. }
  680. else
  681. { // src operands
  682. if (sameSrcDst && dst && opn->AsRegOpnd()->IsSameReg(dst))
  683. {
  684. form |= FSRC(REG,0); // same src,dst
  685. sameSrcDst = false;
  686. }
  687. else
  688. {
  689. form |= FSRC(REG, opnnum++);
  690. }
  691. }
  692. }
  693. else if (regNum >= RegR0 && regNum <= LAST_DOUBLE_REG)
  694. {
  695. form |= FSRC(DREG, opnnum++);
  696. }
  697. break;
  698. }
  699. }
  700. break;
  701. case IR::OpndKindHelperCall:
  702. {
  703. form |= FSRC(CODE, opnnum++);
  704. }
  705. break;
  706. case IR::OpndKindRegBV:
  707. {
  708. Assert(instr->m_opcode == Js::OpCode::PUSH || instr->m_opcode == Js::OpCode::POP
  709. || instr->m_opcode == Js::OpCode::VPUSH || instr->m_opcode == Js::OpCode::VPOP);
  710. BVIndex count = opn->AsRegBVOpnd()->GetValue().Count();
  711. Assert(count > 0);
  712. // Note: only the wide encoding distinguishes between single- and multiple-register push/pop.
  713. if (count == 1 && T2instr)
  714. {
  715. form |= FSRC(REG, opnnum++);
  716. }
  717. break;
  718. }
  719. case IR::OpndKindIndir:
  720. indirOpnd = opn->AsIndirOpnd();
  721. form = this->IndirForm(form, &opnnum, indirOpnd->GetBaseOpnd()->GetReg(), indirOpnd->GetIndexOpnd());
  722. break;
  723. case IR::OpndKindSym:
  724. {
  725. RegNum baseReg;
  726. int32 offset;
  727. AssertMsg(opn->AsSymOpnd()->m_sym->IsStackSym(), "Should only see stackSym syms in encoder.");
  728. form |= FSRC(INDIR, opnnum++);
  729. this->BaseAndOffsetFromSym(opn->AsSymOpnd(), &baseReg, &offset, this->m_func);
  730. if (baseReg == RegSP)
  731. {
  732. form |= FSRC(SP, opnnum++);
  733. }
  734. else
  735. {
  736. form |= FSRC(REG, opnnum++);
  737. form |= FSRC(CONST, opnnum++);
  738. }
  739. break;
  740. }
  741. case IR::OpndKindLabel:
  742. form |= FSRC(LABEL, opnnum++);
  743. break;
  744. case IR::OpndKindMemRef:
  745. // Deref of literal address
  746. AssertMsg(0, "NYI");
  747. return 0;
  748. default:
  749. AssertMsg(UNREACHED, "Unrecognized kind");
  750. return 0;
  751. }
  752. if (done)
  753. {
  754. //If we have traversed all the 3 operands exit.
  755. break;
  756. }
  757. if (LowererMD::IsCall(instr))
  758. {
  759. break;
  760. }
  761. if (opn == dst)
  762. {
  763. opn = instr->GetSrc1();
  764. if (instr->IsBranchInstr() && instr->AsBranchInstr()->GetTarget())
  765. {
  766. // Treat the label reference as the first source.
  767. form |= FSRC(LABEL, opnnum++);
  768. }
  769. }
  770. else
  771. {
  772. opn = instr->GetSrc2();
  773. done = true;
  774. }
  775. operands = 1;
  776. }
  777. return (form);
  778. }
  779. bool EncoderMD::EncodeImmediate16(int32 constant, DWORD * result)
  780. {
  781. if (constant > 0xFFFF)
  782. {
  783. return FALSE;
  784. }
  785. DWORD encode = ((constant & 0xFF) << 16) |
  786. ((constant & 0x0700) << 20) |
  787. ((constant & 0x0800) >> 1) |
  788. ((constant & 0xF000) >> 12);
  789. *result |= encode;
  790. return TRUE;
  791. }
  792. ENCODE_32
  793. EncoderMD::EncodeT2Immediate12(ENCODE_32 encode, int32 constant)
  794. {
  795. Assert((constant & 0xFFFFF000) == 0);
  796. ENCODE_32 encoded = (constant & 0x800) >> (11-10);
  797. encoded |= (constant & 0x700) << (16+12-8);
  798. encoded |= (constant & 0xFF) << 16;
  799. encode |= encoded;
  800. return encode;
  801. }
  802. ENCODE_32
  803. EncoderMD::EncodeT2Offset(ENCODE_32 encode, IR::Instr *instr, int offset, int bitOffset)
  804. {
  805. if (EncoderMD::IsShifterUpdate(instr))
  806. {
  807. Assert(IS_CONST_INT8(offset));
  808. encode |= 9 << 24;
  809. if (!EncoderMD::IsShifterSub(instr))
  810. {
  811. encode |= 1 << 25;
  812. }
  813. if (!EncoderMD::IsShifterPost(instr))
  814. {
  815. encode |= 1 << 26;
  816. }
  817. }
  818. else
  819. {
  820. if (offset >=0)
  821. {
  822. Assert(IS_CONST_UINT12(offset));
  823. encode |= 1 << 7;
  824. }
  825. else
  826. {
  827. offset = -offset;
  828. Assert(IS_CONST_UINT8(offset));
  829. encode |= 0x0C000000;
  830. }
  831. }
  832. encode |= offset << bitOffset;
  833. return encode;
  834. }
  835. //---------------------------------------------------------------------------
  836. //
  837. // GenerateEncoding()
  838. //
  839. // generates the encoding for the specified tuple/form by applying the
  840. // associated encoding steps
  841. //
  842. //---------------------------------------------------------------------------
  843. ENCODE_32
  844. EncoderMD::GenerateEncoding(IR::Instr* instr, IFORM iform, BYTE *pc, int32 size, InstructionType instrType)
  845. {
  846. ENCODE_32 encode = 0 ;
  847. DWORD encoded = 0;
  848. IR::Opnd* opn = 0;
  849. IR::Opnd* dst = 0;
  850. IR::Opnd* reg = 0; //tupReg;
  851. IR::IndirOpnd *indirOpnd;
  852. Js::OpCode opcode = instr->m_opcode;
  853. const AssemblyStep *AsmSteps = nullptr;
  854. const FormTable *ftp = nullptr;
  855. int bitOffset;
  856. int offset;
  857. bool fUpdate;
  858. bool fSub;
  859. bool fPost;
  860. int done = false;
  861. int32 constant = 0; //UTC IVALTYPE
  862. bool constantValid = false;
  863. RegNum regNum;
  864. unsigned int iType = 0, SFlag = 0;
  865. dst = instr->GetDst();
  866. if(opcode == Js::OpCode::MLS)
  867. {
  868. Assert(instr->m_prev->GetDst()->IsRegOpnd() && (instr->m_prev->GetDst()->AsRegOpnd()->GetReg() == RegR12));
  869. }
  870. if (dst == nullptr || LowererMD::IsCall(instr))
  871. {
  872. opn = instr->GetSrc1();
  873. reg = opn;
  874. }
  875. else if (opcode == Js::OpCode::POP || opcode == Js::OpCode::VPOP)
  876. {
  877. opn = instr->GetSrc1();
  878. reg = dst;
  879. }
  880. else
  881. {
  882. opn = dst;
  883. reg = opn;
  884. }
  885. for (ftp = InstrEncode[opcode - (Js::OpCode::MDStart + 1)]; !done && ftp->form != FORM_NOMORE; ftp++)
  886. {
  887. if (ftp->form != iform)
  888. {
  889. if (!((iform & (1<<28)) == 0 && THUMB2_THUMB1_FORM(ftp->form, iform)))
  890. {
  891. continue;
  892. }
  893. }
  894. AsmSteps = ftp->steps;
  895. done = false;
  896. constantValid=0;
  897. while (!done)
  898. {
  899. switch (*AsmSteps++)
  900. {
  901. case STEP_NEXTOPN:
  902. // Get Next operand
  903. if (opn == dst)
  904. {
  905. opn = instr->GetSrc1();
  906. }
  907. else
  908. {
  909. Assert(opn == instr->GetSrc1());
  910. opn = instr->GetSrc2();
  911. }
  912. reg = opn;
  913. continue;
  914. case STEP_CONSTANT:
  915. Assert(opn->IsImmediateOpnd());
  916. constant = opn->GetImmediateValue();
  917. constantValid = true;
  918. continue;
  919. case STEP_CALL:
  920. continue;
  921. case STEP_T2_BRANCH24:
  922. // Constant encoded with 24bits
  923. EncodeReloc::New(&m_relocList, RelocTypeBranch24, m_pc, instr->AsBranchInstr()->GetTarget(), m_encoder->m_tempAlloc);
  924. continue;
  925. case STEP_T2_BRANCH20:
  926. // Constant encoded with 20bits.
  927. EncodeReloc::New(&m_relocList, RelocTypeBranch20, m_pc, instr->AsBranchInstr()->GetTarget(), m_encoder->m_tempAlloc);
  928. continue;
  929. case STEP_REG:
  930. Assert(reg != nullptr);
  931. Assert(reg->IsRegOpnd());
  932. bitOffset = *AsmSteps++;
  933. regNum = (RegNum)this->GetRegEncode(reg->AsRegOpnd());
  934. encode |= regNum << bitOffset;
  935. continue;
  936. case STEP_HREG:
  937. Assert(reg != nullptr);
  938. Assert(reg->IsRegOpnd());
  939. bitOffset = *AsmSteps++;
  940. regNum = (RegNum)this->GetRegEncode(reg->AsRegOpnd());
  941. encode |= (regNum & 0x7) << bitOffset;
  942. continue;
  943. case STEP_R12:
  944. bitOffset = *AsmSteps++;
  945. regNum = (RegNum)this->GetRegEncode(RegR12);
  946. encode |= regNum << bitOffset;
  947. continue;
  948. case STEP_HBIT:
  949. Assert(reg != nullptr);
  950. Assert(reg->IsRegOpnd());
  951. regNum = (RegNum)this->GetRegEncode(reg->AsRegOpnd());
  952. if (regNum >= MAX_INT_REGISTERS_LOW)
  953. {
  954. bitOffset = *AsmSteps;
  955. encode |= 1 << bitOffset;
  956. }
  957. AsmSteps++;
  958. continue;
  959. case STEP_OPEQ:
  960. Assert(instr->GetDst()->AsRegOpnd()->IsSameReg(instr->GetSrc1()));
  961. continue;
  962. case STEP_DUMMY_REG:
  963. Assert(opn->AsRegOpnd()->GetReg() == RegSP ||
  964. opn->AsRegOpnd()->GetReg() == RegPC);
  965. continue;
  966. case STEP_OPCODE:
  967. //ASSERTTNR(!(instr & ftp->inst), tupInstr);
  968. encode |= ftp->inst;
  969. continue;
  970. case STEP_FIXUP:
  971. /*
  972. if (TU_ISINDIR(tupOpn)) {
  973. if (fApplyFixup)
  974. CoApplyFixup(tupOpn, dataBuf);
  975. }*/
  976. continue;
  977. case STEP_LDR:
  978. Assert(!constantValid);
  979. switch (opn->GetType())
  980. {
  981. case TyInt8:
  982. constant = 0x5600;
  983. case TyInt16:
  984. constant = 0x5e00;
  985. break;
  986. case TyInt32:
  987. case TyUint32:
  988. case TyVar:
  989. constant = 0x5800;
  990. break;
  991. case TyUint8:
  992. constant = 0x5c00;
  993. break;
  994. case TyUint16:
  995. constant = 0x5a00;
  996. break;
  997. }
  998. encode |= constant;
  999. continue;
  1000. case STEP_LDRI:
  1001. Assert(!constantValid);
  1002. switch (opn->GetType())
  1003. {
  1004. case TyInt8:
  1005. case TyInt16:
  1006. constant = 0;
  1007. break;
  1008. case TyInt32:
  1009. case TyUint32:
  1010. case TyVar:
  1011. constant = 0x6800;
  1012. break;
  1013. case TyUint8:
  1014. constant = 0x7800;
  1015. break;
  1016. case TyUint16:
  1017. constant = 0x8800;
  1018. break;
  1019. }
  1020. encode |= constant;
  1021. continue;
  1022. case STEP_STRI:
  1023. Assert(!constantValid);
  1024. switch (opn->GetType())
  1025. {
  1026. case TyInt8:
  1027. case TyUint8:
  1028. constant = 0x7000;
  1029. break;
  1030. case TyInt16:
  1031. case TyUint16:
  1032. constant = 0x8000;
  1033. break;
  1034. case TyInt32:
  1035. case TyUint32:
  1036. case TyVar:
  1037. constant = 0x6000;
  1038. break;
  1039. }
  1040. encode |= constant;
  1041. continue;
  1042. case STEP_STR:
  1043. Assert(!constantValid);
  1044. switch (opn->GetType())
  1045. {
  1046. case TyInt8:
  1047. case TyUint8:
  1048. constant = 0x5400;
  1049. break;
  1050. case TyInt16:
  1051. case TyUint16:
  1052. constant = 0x5200;
  1053. break;
  1054. case TyInt32:
  1055. case TyUint32:
  1056. case TyVar:
  1057. constant = 0x5000;
  1058. break;
  1059. }
  1060. encode |= constant;
  1061. continue;
  1062. case STEP_IMM:
  1063. bitOffset = *AsmSteps++;
  1064. if (opn->IsIndirOpnd())
  1065. {
  1066. offset = opn->AsIndirOpnd()->GetOffset();
  1067. }
  1068. else
  1069. {
  1070. this->BaseAndOffsetFromSym(opn->AsSymOpnd(), &regNum, &offset, this->m_func);
  1071. }
  1072. switch (opn->GetSize())
  1073. {
  1074. case 1:
  1075. break;
  1076. case 2:
  1077. Assert(!(offset & 0x1));
  1078. offset = offset >> 1;
  1079. break;
  1080. case 4:
  1081. Assert(!(offset & 0x3)); //check for word-align
  1082. offset = offset >> 2;
  1083. break;
  1084. default:
  1085. Assert(UNREACHED);
  1086. offset = 0;
  1087. }
  1088. Assert(IS_CONST_UINT5(offset));
  1089. encode |= offset << bitOffset;
  1090. continue;
  1091. case STEP_UIMM3:
  1092. bitOffset = *AsmSteps++;
  1093. Assert(constantValid);
  1094. Assert(IS_CONST_UINT3(constant));
  1095. encode |= constant << bitOffset;
  1096. continue;
  1097. case STEP_IMM_W7:
  1098. Assert(constantValid);
  1099. Assert(!(constant & 0x3)); // check for word-alignment
  1100. constant = constant >> 2; // remove rightmost two zero bits
  1101. Assert(IS_CONST_UINT7(constant));
  1102. encode |= constant;
  1103. constantValid = false;
  1104. continue;
  1105. case STEP_IMM_DPW8:
  1106. Assert(constantValid);
  1107. Assert(IS_CONST_UINT8(constant >> 2));
  1108. Assert(constant % 4 == 0);
  1109. encode |= constant >> 2;
  1110. constantValid = false;
  1111. continue;
  1112. case STEP_IMM_W8:
  1113. if (opn->IsSymOpnd())
  1114. {
  1115. this->BaseAndOffsetFromSym(opn->AsSymOpnd(), &regNum, &offset, this->m_func);
  1116. }
  1117. else
  1118. {
  1119. offset = opn->AsIndirOpnd()->GetOffset();
  1120. }
  1121. Assert(offset % 4 == 0);
  1122. Assert(IS_CONST_UINT8(offset >> 2));
  1123. encode |= offset >> 2;
  1124. continue;
  1125. case STEP_T2_IMM_16:
  1126. if (!EncodeImmediate16(constant, &encoded))
  1127. {
  1128. AssertMsg(false,"constant > than 16 bits");
  1129. }
  1130. encode |= encoded;
  1131. continue;
  1132. case STEP_T2_IMM_12:
  1133. encode = this->EncodeT2Immediate12(encode, constant);
  1134. continue;
  1135. case STEP_OFFSET:
  1136. {
  1137. unsigned int R_bit = 0;
  1138. if (ISSTORE(instr->m_opcode))
  1139. {
  1140. if (TESTREGBIT(constant, RegLR))
  1141. {
  1142. R_bit = 1 << 8;
  1143. }
  1144. CLEARREGBIT(constant, RegLR);
  1145. }
  1146. else
  1147. {
  1148. if (TESTREGBIT(constant, RegPC))
  1149. {
  1150. R_bit = 1 << 8;
  1151. }
  1152. CLEARREGBIT(constant, RegPC);
  1153. }
  1154. Assert(IS_CONST_UINT8(constant));
  1155. encode |= (CO_UIMMED8(constant) | R_bit);
  1156. constantValid=false;
  1157. continue;
  1158. }
  1159. case STEP_SCALE_CONST:
  1160. {
  1161. bitOffset = *AsmSteps++;
  1162. byte scale = opn->AsIndirOpnd()->GetScale();
  1163. Assert(IS_CONST_UINT5(scale));
  1164. encode |= scale << bitOffset;
  1165. continue;
  1166. }
  1167. case STEP_SHIFTER_CONST:
  1168. bitOffset = *AsmSteps++;
  1169. // TODO: When we have IR that can send Shifts we will
  1170. // need to translate the following:
  1171. // As of now instructions do not have a mechanism to
  1172. // provide the shift offset.
  1173. //ASSERTNR(IS_CONST_UINT5(TU_SHIFTER_SHIFT(tupOpn)));
  1174. //instr |= TU_SHIFTER_SHIFT(tupOpn) << to;
  1175. continue;
  1176. case STEP_BASEREG:
  1177. bitOffset = *AsmSteps++;
  1178. if (opn->IsIndirOpnd())
  1179. {
  1180. regNum = opn->AsIndirOpnd()->GetBaseOpnd()->GetReg();
  1181. }
  1182. else
  1183. {
  1184. this->BaseAndOffsetFromSym(opn->AsSymOpnd(), &regNum, &offset, this->m_func);
  1185. }
  1186. encode |= RegEncode[regNum] << bitOffset;
  1187. continue;
  1188. case STEP_INDEXED:
  1189. Assert(opn->IsIndirOpnd());
  1190. Assert(opn->AsIndirOpnd()->GetIndexOpnd() != nullptr);
  1191. Assert(opn->AsIndirOpnd()->GetOffset() == 0);
  1192. continue;
  1193. case STEP_INDEXREG:
  1194. bitOffset = *AsmSteps++;
  1195. reg = opn->AsIndirOpnd()->GetIndexOpnd();
  1196. Assert(reg != nullptr);
  1197. Assert(reg->IsRegOpnd());
  1198. regNum = (RegNum)this->GetRegEncode(reg->AsRegOpnd());
  1199. encode |= regNum << bitOffset;
  1200. continue;
  1201. case STEP_INDIR:
  1202. Assert(opn->IsIndirOpnd() ||
  1203. (opn->IsSymOpnd() && opn->AsSymOpnd()->m_sym->IsStackSym()));
  1204. continue;
  1205. case STEP_BASED:
  1206. Assert((opn->IsIndirOpnd() && opn->AsIndirOpnd()->GetIndexOpnd() == nullptr) ||
  1207. (opn->IsSymOpnd() && opn->AsSymOpnd()->m_sym->IsStackSym()));
  1208. continue;
  1209. case STEP_T2_REGLIST:
  1210. //ASSERTTNR(constant_valid, tupOpn);
  1211. encode |= constant << 16;
  1212. constantValid = false;
  1213. if (EncoderMD::IsShifterUpdate(instr))
  1214. {
  1215. encode |= 0x20;
  1216. }
  1217. continue;
  1218. case STEP_UIMM5:
  1219. bitOffset = *AsmSteps++;
  1220. Assert(constantValid);
  1221. Assert(IS_CONST_UINT5(constant));
  1222. encode |= constant << bitOffset;
  1223. constantValid = false;
  1224. continue;
  1225. case STEP_UIMM8:
  1226. Assert(constantValid);
  1227. Assert(IS_CONST_UINT8(constant));
  1228. encode |= constant;
  1229. constantValid = false;
  1230. continue;
  1231. case STEP_REGLIST:
  1232. {
  1233. indirOpnd = opn->AsIndirOpnd();
  1234. Assert(indirOpnd->GetIndexOpnd() == nullptr);
  1235. constant = indirOpnd->GetOffset();
  1236. IR::Opnd *opndRD;
  1237. if (EncoderMD::IsLoad(instr))
  1238. {
  1239. opndRD = instr->GetDst();
  1240. }
  1241. else
  1242. {
  1243. opndRD = instr->GetSrc1();
  1244. }
  1245. if (!constant)
  1246. {
  1247. BVUnit32 registers = opndRD->AsRegBVOpnd()->GetValue();
  1248. uint32 regenc;
  1249. BVIndex index = registers.GetNextBit();
  1250. // Note: only the wide encoding distinguishes between
  1251. // single- and multiple-register push/pop.
  1252. if (registers.Count() > 1 || size == 2)
  1253. {
  1254. // Add the physical register number
  1255. do
  1256. {
  1257. regenc = 1 << index;
  1258. constant |= regenc;
  1259. }while ((index = registers.GetNextBit(index + 1))!= BVInvalidIndex);
  1260. }
  1261. else
  1262. {
  1263. bitOffset = *AsmSteps++;
  1264. Assert(index < RegEncode[RegSP]);
  1265. encode |= index << bitOffset;
  1266. continue;
  1267. }
  1268. }
  1269. if (size == 4)
  1270. {
  1271. fSub = EncoderMD::IsShifterSub(instr);
  1272. fUpdate = EncoderMD::IsShifterUpdate(instr);
  1273. encode |= fSub << 8;
  1274. encode |= !fSub << 7;
  1275. encode |= fUpdate << 5;
  1276. }
  1277. constantValid=true;
  1278. }
  1279. continue;
  1280. case STEP_T1_SETS_CR0:
  1281. {
  1282. //ASSERTTNR(Tuple::FindReg(TU_DST(tupInstr), RG_SYM(CR0)) != nullptr, tupInstr);
  1283. }
  1284. continue;
  1285. case STEP_SBIT:
  1286. {
  1287. if (this->SetsSBit(instr))
  1288. {
  1289. bitOffset = *AsmSteps;
  1290. encode |= 1 << bitOffset;
  1291. }
  1292. AsmSteps++;
  1293. }
  1294. continue;
  1295. case STEP_NOSBIT:
  1296. // just asserts that we're not supposed to set the condition flags
  1297. //
  1298. Assert(!this->SetsSBit(instr));
  1299. continue;
  1300. case STEP_MODCONST_12:
  1301. if (!EncodeModConst12(constant, &encoded))
  1302. {
  1303. Assert(UNREACHED);
  1304. }
  1305. encode |= encoded;
  1306. continue;
  1307. case STEP_T2_MEMIMM_POS12_NEG8:
  1308. bitOffset = *AsmSteps++;
  1309. Assert(opn != nullptr);
  1310. if (opn->IsIndirOpnd())
  1311. {
  1312. Assert(opn->AsIndirOpnd()->GetIndexOpnd() == nullptr);
  1313. offset = opn->AsIndirOpnd()->GetOffset();
  1314. // TODO: Handle literal pool loads, if necessary
  1315. // <tfs #775202>: LDR_W could have $Label Fixup for literal-pool
  1316. //if (TU_FEFIXUPSYM(tupOpn) && SS_ISLABEL(TU_FEFIXUPSYM(tupOpn))) {
  1317. // offset += (SS_OFFSET(TU_FEFIXUPSYM(tupOpn)) - ((pc & (~3)) + 4));
  1318. //}
  1319. }
  1320. else if (opn->IsSymOpnd())
  1321. {
  1322. Assert(opn->AsSymOpnd()->m_sym->IsStackSym());
  1323. this->BaseAndOffsetFromSym(opn->AsSymOpnd(), &regNum, &offset, this->m_func);
  1324. }
  1325. else
  1326. {
  1327. Assert(opn->IsImmediateOpnd());
  1328. offset = opn->GetImmediateValue();
  1329. }
  1330. encode = this->EncodeT2Offset(encode, instr, offset, bitOffset);
  1331. continue;
  1332. case STEP_T2_IMMSTACK_POS12_NEG8:
  1333. bitOffset = *AsmSteps++;
  1334. Assert(opn != nullptr);
  1335. Assert(opn->IsSymOpnd() && opn->AsSymOpnd()->m_sym->IsStackSym());
  1336. this->BaseAndOffsetFromSym(opn->AsSymOpnd(), &regNum, &offset, this->m_func);
  1337. encode = this->EncodeT2Offset(encode, instr, offset, bitOffset);
  1338. encode |= RegEncode[regNum];
  1339. continue;
  1340. case STEP_T2_STACKSYM_IMM_12:
  1341. // Used by LEA. Encode base reg at the given bit offset and 12-bit constant
  1342. // as a normal ADDW immediate.
  1343. bitOffset = *AsmSteps++;
  1344. Assert(opn != nullptr);
  1345. Assert(opn->IsSymOpnd() && opn->AsSymOpnd()->m_sym->IsStackSym());
  1346. this->BaseAndOffsetFromSym(opn->AsSymOpnd(), &regNum, &offset, this->m_func);
  1347. encode |= RegEncode[regNum] << bitOffset;
  1348. encode = this->EncodeT2Immediate12(encode, offset);
  1349. continue;
  1350. case STEP_T2_MEM_TYPE:
  1351. {
  1352. Assert((ftp->inst & 0xFF00) == 0xF800);
  1353. switch (opn->GetType())
  1354. {
  1355. case TyInt8:
  1356. SFlag = 1;
  1357. iType = 0;
  1358. break;
  1359. case TyUint8:
  1360. SFlag = 0;
  1361. iType = 0;
  1362. break;
  1363. case TyInt16:
  1364. SFlag = 1;
  1365. iType = 1;
  1366. break;
  1367. case TyUint16:
  1368. iType = 1;
  1369. SFlag = 0;
  1370. break;
  1371. case TyInt32:
  1372. case TyUint32:
  1373. case TyVar:
  1374. SFlag = 0;
  1375. iType = 2;
  1376. break;
  1377. default:
  1378. Assert(UNREACHED);
  1379. }
  1380. if (!EncoderMD::IsLoad(instr))
  1381. {
  1382. SFlag = 0;
  1383. }
  1384. encode |= (SFlag << 8) | (iType << 5);
  1385. continue;
  1386. }
  1387. case STEP_T2_SHIFT_IMM_5:
  1388. #if DBG
  1389. if(instr->m_opcode == Js::OpCode::ASR ||
  1390. instr->m_opcode == Js::OpCode::ASRS ||
  1391. instr->m_opcode == Js::OpCode::LSR)
  1392. {
  1393. // Encoding zero is interpreted as 32
  1394. // for these instructions.
  1395. Assert(constant != 0);
  1396. }
  1397. #endif
  1398. Assert(IS_CONST_UINT5(constant));
  1399. encoded = (constant & 0x03) << (16+6);
  1400. encoded |= (constant & 0x1c) << (16+12-2);
  1401. encode |= encoded;
  1402. continue;
  1403. case STEP_MOVW_reloc:
  1404. Assert(opn && opn->IsLabelOpnd());
  1405. if (opn->AsLabelOpnd()->GetLabel()->m_isDataLabel)
  1406. {
  1407. Assert(!opn->AsLabelOpnd()->GetLabel()->isInlineeEntryInstr);
  1408. EncodeReloc::New(&m_relocList, RelocTypeDataLabelLow, m_pc, opn->AsLabelOpnd()->GetLabel(), m_encoder->m_tempAlloc);
  1409. }
  1410. else
  1411. {
  1412. EncodeReloc::New(&m_relocList, RelocTypeLabelLow, m_pc, opn->AsLabelOpnd()->GetLabel(), m_encoder->m_tempAlloc);
  1413. }
  1414. continue;
  1415. case STEP_MOVT_reloc:
  1416. Assert(opn && opn->IsLabelOpnd());
  1417. EncodeReloc::New(&m_relocList, RelocTypeLabelHigh, m_pc, opn->AsLabelOpnd()->GetLabel(), m_encoder->m_tempAlloc);
  1418. continue;
  1419. case STEP_DREG:
  1420. {
  1421. int bbit = 0;
  1422. DWORD tmp = 0;
  1423. Assert(opn != nullptr && opn->IsRegOpnd());
  1424. bitOffset = *AsmSteps++;
  1425. bbit = *AsmSteps++;
  1426. regNum = (RegNum)GetRegEncode(opn->AsRegOpnd());
  1427. //Check to see if register number is valid
  1428. Assert(regNum >= 0 && regNum <= LAST_DOUBLE_REG_NUM);
  1429. tmp |= (regNum & 0xf) << bitOffset;
  1430. tmp |= ((regNum >> 4) & 0x1) << bbit;
  1431. Assert(0 == (encode & tmp));
  1432. encode |= tmp;
  1433. continue;
  1434. }
  1435. case STEP_SREG:
  1436. {
  1437. int bbit = 0;
  1438. DWORD tmp = 0;
  1439. Assert(opn != nullptr && opn->IsRegOpnd());
  1440. bitOffset = *AsmSteps++;
  1441. bbit = *AsmSteps++;
  1442. regNum = (RegNum)GetFloatRegEncode(opn->AsRegOpnd());
  1443. //Check to see if register number is valid
  1444. Assert(regNum >= 0 && regNum <= LAST_FLOAT_REG_NUM);
  1445. tmp |= (regNum & 0x1) << bbit;
  1446. tmp |= (regNum >> 1) << bitOffset;
  1447. Assert(0 == (encode & tmp));
  1448. encode |= tmp;
  1449. continue;
  1450. }
  1451. case STEP_IMM_S8:
  1452. {
  1453. Assert(opn!=nullptr);
  1454. AssertMsg(instrType == InstructionType::Vfp, "This step is specific to VFP instructions");
  1455. if (opn->IsIndirOpnd())
  1456. {
  1457. Assert(opn->AsIndirOpnd()->GetIndexOpnd() == nullptr);
  1458. offset = opn->AsIndirOpnd()->GetOffset();
  1459. // TODO: Handle literal pool loads, if necessary
  1460. // <tfs #775202>: LDR_W could have $Label Fixup for literal-pool
  1461. //if (TU_FEFIXUPSYM(tupOpn) && SS_ISLABEL(TU_FEFIXUPSYM(tupOpn))) {
  1462. // offset += (SS_OFFSET(TU_FEFIXUPSYM(tupOpn)) - ((pc & (~3)) + 4));
  1463. //}
  1464. }
  1465. else if (opn->IsSymOpnd())
  1466. {
  1467. Assert(opn->AsSymOpnd()->m_sym->IsStackSym());
  1468. this->BaseAndOffsetFromSym(opn->AsSymOpnd(), &regNum, &offset, this->m_func);
  1469. }
  1470. else
  1471. {
  1472. offset = 0;
  1473. AssertMsg(false, "Why are we here");
  1474. }
  1475. if (offset < 0)
  1476. {
  1477. //IsShifterSub(tupOpn) = TRUE; //Doesn't seem necessary for us, why does UTC set this?
  1478. offset = -offset;
  1479. encode &= ~(1 << 7);
  1480. }
  1481. else
  1482. {
  1483. encode |= (1 << 7);
  1484. }
  1485. // Set the W (writeback) bit if IsShifterUpdate is
  1486. // specified.
  1487. if (EncoderMD::IsShifterUpdate(instr))
  1488. {
  1489. encode |= (1 << 5);
  1490. // Set the P (pre-indexed) bit to be the complement
  1491. // of IsShifterPost
  1492. if (EncoderMD::IsShifterPost(instr))
  1493. {
  1494. encode &= ~(1 << 8);
  1495. }
  1496. else
  1497. {
  1498. encode |= (1 << 8);
  1499. }
  1500. }
  1501. else
  1502. {
  1503. // Clear the W bit and set the P bit (offset
  1504. // addressing).
  1505. encode &= ~(1 << 5);
  1506. encode |= (1 << 8);
  1507. }
  1508. Assert(IS_CONST_UINT8(offset >> 2));
  1509. encode |= ((offset >> 2) << 16);
  1510. continue;
  1511. }
  1512. case STEP_DREGLIST:
  1513. {
  1514. IR::Opnd *opndRD;
  1515. if (EncoderMD::IsLoad(instr))
  1516. {
  1517. opndRD = instr->GetDst();
  1518. }
  1519. else
  1520. {
  1521. opndRD = instr->GetSrc1();
  1522. }
  1523. BVUnit32 registers = opndRD->AsRegBVOpnd()->GetValue();
  1524. DWORD first = registers.GetNextBit();
  1525. DWORD last = (DWORD)-1;
  1526. _BitScanReverse((DWORD*)&last, (DWORD)registers.GetWord());
  1527. Assert(last >= first && last <= LAST_DOUBLE_CALLEE_SAVED_REG_NUM);
  1528. encode |= (CO_UIMMED8((last - first + 1) * 2)) << 16;
  1529. encode |= (first << 28);
  1530. }
  1531. continue;
  1532. case STEP_AM5:
  1533. Assert(opn->IsIndirOpnd());
  1534. Assert(opn->AsIndirOpnd()->GetIndexOpnd() == nullptr);
  1535. Assert(opn->AsIndirOpnd()->GetOffset() == 0);
  1536. fPost = EncoderMD::IsShifterPost(instr);
  1537. fSub = EncoderMD::IsShifterSub(instr);
  1538. fUpdate = EncoderMD::IsShifterUpdate(instr);
  1539. // update addressing mode
  1540. encode |= !fPost << 8;
  1541. encode |= !fSub << 7;
  1542. encode |= fUpdate << 5;
  1543. continue;
  1544. case STEP_DONE:
  1545. done = true;
  1546. break;
  1547. default:
  1548. #if DBG
  1549. instr->Dump();
  1550. AssertMsg(UNREACHED, "Unrecognized assembly step");
  1551. #endif
  1552. return 0;
  1553. }
  1554. break;
  1555. }
  1556. }
  1557. #if DBG
  1558. if (!done)
  1559. {
  1560. instr->Dump();
  1561. Output::Flush();
  1562. AssertMsg(UNREACHED, "Unsupported Instruction Form");
  1563. }
  1564. #endif
  1565. return encode;
  1566. }
  1567. #ifdef INSERT_NOPS
  1568. ptrdiff_t insertNops(BYTE *pc, ENCODE_32 outInstr, uint count, uint size)
  1569. {
  1570. //Insert count nops in the beginning
  1571. for(int i = 0; i < count;i++)
  1572. {
  1573. *(ENCODE_32 *)(pc + i * sizeof(ENCODE_32)) = 0x8000F3AF;
  1574. }
  1575. if (size == sizeof(ENCODE_16))
  1576. {
  1577. *(ENCODE_16 *)(pc + count * sizeof(ENCODE_32)) = (ENCODE_16)(outInstr & 0x0000ffff);
  1578. *(ENCODE_16 *)(pc + sizeof(ENCODE_16) + count * sizeof(ENCODE_32)) = (ENCODE_16)(0xBF00);
  1579. }
  1580. else
  1581. {
  1582. Assert(size == sizeof(ENCODE_32));
  1583. *(ENCODE_32 *)(pc + count * sizeof(ENCODE_32)) = outInstr;
  1584. }
  1585. //Insert count nops at the end;
  1586. for(int i = count + 1; i < (2 *count + 1); i++)
  1587. {
  1588. *(ENCODE_32 *)(pc + i * sizeof(ENCODE_32)) = 0x8000F3AF;
  1589. }
  1590. return MachInt*(2*count + 1);
  1591. }
  1592. #endif //INSERT_NOPS
  1593. #ifdef SOFTWARE_FIXFOR_HARDWARE_BUGWIN8_502326
  1594. bool
  1595. EncoderMD::IsBuggyHardware()
  1596. {
  1597. return true;
  1598. // TODO: Enable this for restricting to Qualcomm Krait cores affected: KR28M2A10, KR28M2A11, KR28M2A12
  1599. /*
  1600. AssertMsg(AutoSystemInfo::Data.wProcessorArchitecture == 5, "This has to be ARM architecture");
  1601. if (((AutoSystemInfo::Data.wProcessorLevel & 0xFC0) == 0x40) && ((AutoSystemInfo::Data.wProcessorRevision & 0xF0) == 0))
  1602. {
  1603. #if DBG_DUMP
  1604. if (Js::Configuration::Global.flags.Trace.IsEnabled(Js::EncoderPhase))
  1605. {
  1606. Output::Print(_u("TRACE: Running in buggy hardware.\n"));
  1607. }
  1608. #endif
  1609. return true;
  1610. }
  1611. return false;
  1612. */
  1613. }
  1614. bool
  1615. EncoderMD::CheckBranchInstrCriteria(IR::Instr* instr)
  1616. {
  1617. if (ISQBUGGYBR(instr->m_opcode))
  1618. {
  1619. return true;
  1620. }
  1621. #if DBG
  1622. switch (instr->m_opcode)
  1623. {
  1624. case Js::OpCode::RET: //This is never Thumb2 hence we are safe in this hardware bug
  1625. return false;
  1626. case Js::OpCode::BL:
  1627. AssertMsg(false, "We don't generate these now. Include in the opcode list above for BL T1 encodings");
  1628. return false;
  1629. case Js::OpCode::BLX:
  1630. AssertMsg(instr->GetSrc1()->IsRegOpnd(),"If we generate label include in the opcode list above");
  1631. //Fallthrough
  1632. default:
  1633. {
  1634. //Assert to make sure none of the other instructions have target as PC register.
  1635. if (instr->GetDst() && instr->GetDst()->IsRegOpnd())
  1636. {
  1637. AssertMsg(instr->GetDst()->AsRegOpnd()->GetReg() != RegPC, "Check for this opcode above");
  1638. }
  1639. }
  1640. }
  1641. #endif
  1642. return false;
  1643. }
  1644. #endif //SOFTWARE_FIXFOR_HARDWARE_BUGWIN8_502326
  1645. ///----------------------------------------------------------------------------
  1646. ///
  1647. /// EncoderMD::Encode
  1648. ///
  1649. /// Emit the ARM encoding for the given instruction in the passed in
  1650. /// buffer ptr.
  1651. ///
  1652. ///----------------------------------------------------------------------------
  1653. ptrdiff_t
  1654. EncoderMD::Encode(IR::Instr *instr, BYTE *pc, BYTE* beginCodeAddress)
  1655. {
  1656. m_pc = pc;
  1657. ENCODE_32 outInstr;
  1658. IFORM iform;
  1659. int size = 0;
  1660. // Instructions must be lowered, we don't handle non-MD opcodes here.
  1661. Assert(instr != nullptr);
  1662. if (instr->IsLowered() == false)
  1663. {
  1664. if (instr->IsLabelInstr())
  1665. {
  1666. if (instr->isInlineeEntryInstr)
  1667. {
  1668. Js::Var inlineeCallInfo = 0;
  1669. const bool encodeResult = Js::InlineeCallInfo::Encode(inlineeCallInfo, instr->AsLabelInstr()->GetOffset(), m_pc - m_encoder->m_encodeBuffer);
  1670. Assert(encodeResult);
  1671. //We are re-using offset to save the inlineeCallInfo which will be patched in ApplyRelocs
  1672. //This is a cleaner way to patch MOVW\MOVT pair with the right inlineeCallInfo
  1673. instr->AsLabelInstr()->ResetOffset((uint32)inlineeCallInfo);
  1674. }
  1675. else
  1676. {
  1677. instr->AsLabelInstr()->SetPC(m_pc);
  1678. if (instr->AsLabelInstr()->m_id == m_func->m_unwindInfo.GetPrologStartLabel())
  1679. {
  1680. m_func->m_unwindInfo.SetPrologOffset(m_pc - m_encoder->m_encodeBuffer);
  1681. }
  1682. else if (instr->AsLabelInstr()->m_id == m_func->m_unwindInfo.GetEpilogEndLabel())
  1683. {
  1684. // This is the last instruction in the epilog. Any instructions that follow
  1685. // are separated code, so the unwind info will have to represent them as a function
  1686. // fragment. (If there's no separated code, then this offset will equal the total
  1687. // code size.)
  1688. m_func->m_unwindInfo.SetEpilogEndOffset(m_pc - m_encoder->m_encodeBuffer - m_func->m_unwindInfo.GetPrologOffset());
  1689. }
  1690. }
  1691. }
  1692. #if DBG_DUMP
  1693. if (instr->IsEntryInstr() && Js::Configuration::Global.flags.DebugBreak.Contains(m_func->GetFunctionNumber()))
  1694. {
  1695. IR::Instr *int3 = IR::Instr::New(Js::OpCode::DEBUGBREAK, m_func);
  1696. return this->Encode(int3, m_pc);
  1697. }
  1698. #endif
  1699. return 0;
  1700. }
  1701. #ifdef SOFTWARE_FIXFOR_HARDWARE_BUGWIN8_502326
  1702. if (IsBuggyHardware())
  1703. {
  1704. // Hardware bug is in Qualcomm 8960. 32 bit thumb branch instructions might not jump to the correct address in following
  1705. // conditions:
  1706. // a.3 T16 thumb instruction followed by T32 branch instruction (conditional\unconditional & RegPc load).
  1707. // b.Branch instruction starts at 0x*****FBE
  1708. // As we don't know the final address, instead of checking for 0x*FBE we just check for offset 0x*E
  1709. // as the final function start address is always aligned at 16 byte boundary (EMIT_BUFFER_ALIGNMENT)
  1710. if (consecutiveThumbInstrCount >= 3 && (((uint)(m_pc - beginCodeAddress) & 0xF) == 0xE) && CheckBranchInstrCriteria(instr))
  1711. {
  1712. Assert(beginCodeAddress);
  1713. IR::Instr *nop = IR::Instr::New(Js::OpCode::VMOV,
  1714. IR::RegOpnd::New(nullptr, RegD15, TyMachDouble, this->m_func),
  1715. IR::RegOpnd::New(nullptr, RegD15, TyMachDouble, this->m_func),
  1716. m_func);
  1717. size = this->Encode(nop, m_pc);
  1718. consecutiveThumbInstrCount = 0;
  1719. size+= this->Encode(instr, m_pc + size);
  1720. #if DBG_DUMP
  1721. if (Js::Configuration::Global.flags.Trace.IsEnabled(Js::EncoderPhase))
  1722. {
  1723. Output::Print(_u("TRACE: Avoiding Branch instruction and Dummy nops at 0x*E \n"));
  1724. }
  1725. #endif
  1726. Assert(size == 8);
  1727. // We are okay with returning size 8 as the previous 3 thumb instructions any way would have saved 6 bytes
  1728. // and doesn't alter the logic of allocating temp buffer based on MachMaxInstrSize
  1729. return size;
  1730. }
  1731. }
  1732. #endif
  1733. InstructionType instrType = this->CanonicalizeInstr(instr);
  1734. switch(instrType)
  1735. {
  1736. case Thumb:
  1737. size = 2;
  1738. consecutiveThumbInstrCount++;
  1739. break;
  1740. case Thumb2:
  1741. size = 4;
  1742. consecutiveThumbInstrCount = 0;
  1743. break;
  1744. case Vfp:
  1745. size = 4;
  1746. consecutiveThumbInstrCount = 0;
  1747. break;
  1748. default: Assert(false);
  1749. }
  1750. AssertMsg(size != MachChar, "Thumb2 is never single Byte");
  1751. iform = (IFORM)GetForm(instr, size);
  1752. outInstr = GenerateEncoding(instr, iform, m_pc, size, instrType);
  1753. if (outInstr == 0)
  1754. {
  1755. return 0;
  1756. }
  1757. // TODO: Check if VFP/Neon instructions in Thumb-2 mode we need to swap the instruction halfwords
  1758. if (size == sizeof(ENCODE_16))
  1759. {
  1760. #ifdef INSERT_NOPS
  1761. return insertNops(m_pc, outInstr, CountNops, sizeof(ENCODE_16));
  1762. #else
  1763. //2 byte Thumb encoding
  1764. Assert((outInstr & 0xffff0000) == 0);
  1765. *(ENCODE_16 *)m_pc = (ENCODE_16)(outInstr & 0x0000ffff);
  1766. return MachShort;
  1767. #endif
  1768. }
  1769. else if (size == sizeof(ENCODE_32))
  1770. {
  1771. #ifdef INSERT_NOPS
  1772. return insertNops(m_pc, outInstr, CountNops, sizeof(ENCODE_32));
  1773. #else
  1774. //4 byte Thumb2 encoding
  1775. *(ENCODE_32 *)m_pc = outInstr ;
  1776. return MachInt;
  1777. #endif
  1778. }
  1779. AssertMsg(UNREACHED, "Unexpected size");
  1780. return 0;
  1781. }
  1782. bool
  1783. EncoderMD::CanEncodeModConst12(DWORD constant)
  1784. {
  1785. DWORD encode;
  1786. return EncodeModConst12(constant, &encode);
  1787. }
  1788. bool
  1789. EncoderMD::EncodeModConst12(DWORD constant, DWORD * result)
  1790. {
  1791. unsigned int a, b, c, d, rotation, firstbit, lastbit, temp=0;
  1792. if (constant == 0)
  1793. {
  1794. *result = 0;
  1795. return true;
  1796. }
  1797. a = constant & 0xff;
  1798. b = (constant >> 8) & 0xff;
  1799. c = (constant >> 16) & 0xff;
  1800. d = (constant >> 24) & 0xff;
  1801. _BitScanReverse((DWORD*)&firstbit, constant);
  1802. _BitScanForward((DWORD*)&lastbit, constant);
  1803. if (! ((a == 0 && c == 0 && b == d)
  1804. || (b == 0 && d == 0 && a == c)
  1805. || (a == b && b == c && c == d)
  1806. || (firstbit-lastbit < 8) ))
  1807. {
  1808. return false;
  1809. }
  1810. *result = 0;
  1811. if (constant <= 0xFF)
  1812. {
  1813. *result |= constant << 16;
  1814. }
  1815. else if (firstbit-lastbit < 8)
  1816. {
  1817. if (firstbit > 7)
  1818. {
  1819. temp |= 0x7F & (constant >> (firstbit-7));
  1820. rotation = 32-firstbit+7;
  1821. }
  1822. else
  1823. {
  1824. temp |= 0x7F & (constant << (7-firstbit));
  1825. rotation = 7-firstbit;
  1826. }
  1827. *result = (temp & 0xFF) << 16;
  1828. *result |= (0x10 & rotation) << 6;
  1829. *result |= (0xE & rotation) << 27;
  1830. *result |= (0x1 & rotation) << 23;
  1831. }
  1832. else
  1833. {
  1834. if (a==0 && c==0 && b==d)
  1835. {
  1836. *result |= 0x20000000; // HW2[12]
  1837. *result |= (0xFF & b) << 16;
  1838. }
  1839. else if (a==c && b==0 && d==0)
  1840. {
  1841. *result |= 0x10000000;
  1842. *result |= (0xFF & a) << 16;
  1843. }
  1844. else if (a==b && b==c && c==d)
  1845. {
  1846. *result |= 0x30000000;
  1847. *result |= (0xFF & d) << 16;
  1848. }
  1849. else
  1850. {
  1851. Assert(UNREACHED);
  1852. }
  1853. }
  1854. return true;
  1855. }
  1856. ///----------------------------------------------------------------------------
  1857. ///
  1858. /// EncodeReloc::New
  1859. ///
  1860. ///----------------------------------------------------------------------------
  1861. void
  1862. EncodeReloc::New(EncodeReloc **pHead, RelocType relocType, BYTE *offset, IR::Instr *relocInstr, ArenaAllocator *alloc)
  1863. {
  1864. EncodeReloc *newReloc = AnewStruct(alloc, EncodeReloc);
  1865. newReloc->m_relocType = relocType;
  1866. newReloc->m_consumerOffset = offset;
  1867. newReloc->m_next = *pHead;
  1868. newReloc->m_relocInstr = relocInstr;
  1869. *pHead = newReloc;
  1870. }
  1871. ENCODE_32 EncoderMD::CallOffset(int x)
  1872. {
  1873. Assert(IS_CONST_INT24(x >> 1));
  1874. ENCODE_32 ret;
  1875. int Sflag = (x & 0x1000000) >> 24;
  1876. int off23 = (x & 0x800000) >> 23;
  1877. int off22 = (x & 0x400000) >> 22;
  1878. ret = (x & 0xFFE) << 15;
  1879. ret |= (x & 0x3FF000) >> 12;
  1880. ret |= (((~off23) ^ Sflag) & 0x1) << (16+13);
  1881. ret |= (((~off22) ^ Sflag) & 0x1) << (16+11);
  1882. ret |= (Sflag << 10);
  1883. return ret;
  1884. }
  1885. ENCODE_32 EncoderMD::BranchOffset_T2_24(int x)
  1886. {
  1887. x -= 4;
  1888. Assert(IS_CONST_INT24(x >> 1));
  1889. int ret;
  1890. int Sflag = (x & 0x1000000) >> 24;
  1891. int off23 = (x & 0x800000) >> 23;
  1892. int off22 = (x & 0x400000) >> 22;
  1893. ret = (x & 0xFFE) << 15;
  1894. ret |= (x & 0x3FF000) >> 12;
  1895. ret |= (((~off23) ^ Sflag) & 0x1) << (16+13);
  1896. ret |= (((~off22) ^ Sflag) & 0x1) << (16+11);
  1897. ret |= (Sflag << 10);
  1898. return INSTR_TYPE(ret);
  1899. }
  1900. ENCODE_32 EncoderMD::BranchOffset_T2_20(int x)
  1901. {
  1902. x -= 4;
  1903. Assert(IS_CONST_INT21(x));
  1904. uint32 ret;
  1905. uint32 Sflag = (x & 0x100000) >> 20;
  1906. uint32 off19 = (x & 0x80000) >> 19;
  1907. uint32 off18 = (x & 0x40000) >> 18;
  1908. ret = (x & 0xFFE) << 15;
  1909. ret |= (x & 0x3F000) >> 12;
  1910. ret |= off18 << (13+16);
  1911. ret |= off19 << (11+16);
  1912. ret |= (Sflag << 10);
  1913. return ret;
  1914. }
  1915. void
  1916. EncoderMD::BaseAndOffsetFromSym(IR::SymOpnd *symOpnd, RegNum *pBaseReg, int32 *pOffset, Func * func)
  1917. {
  1918. StackSym *stackSym = symOpnd->m_sym->AsStackSym();
  1919. RegNum baseReg = func->GetLocalsPointer();
  1920. int32 offset = stackSym->m_offset + symOpnd->m_offset;
  1921. if (baseReg == RegSP)
  1922. {
  1923. // SP points to the base of the argument area. Non-reg SP points directly to the locals.
  1924. offset += (func->m_argSlotsForFunctionsCalled * MachRegInt);
  1925. if (func->GetMaxInlineeArgOutCount())
  1926. {
  1927. Assert(func->HasInlinee());
  1928. if ((!stackSym->IsArgSlotSym() || stackSym->m_isOrphanedArg) && !stackSym->IsParamSlotSym())
  1929. {
  1930. offset += func->GetInlineeArgumentStackSize();
  1931. }
  1932. }
  1933. }
  1934. if (stackSym->IsParamSlotSym())
  1935. {
  1936. offset += func->m_localStackHeight + func->m_ArgumentsOffset;
  1937. if (!EncoderMD::CanEncodeLoadStoreOffset(offset))
  1938. {
  1939. // Use the frame pointer. No need to hoist an offset for a param.
  1940. baseReg = FRAME_REG;
  1941. offset = stackSym->m_offset + symOpnd->m_offset - (Js::JavascriptFunctionArgIndex_Frame * MachRegInt);
  1942. Assert(EncoderMD::CanEncodeLoadStoreOffset(offset));
  1943. }
  1944. }
  1945. #ifdef DBG
  1946. else
  1947. {
  1948. // Locals are offset by the size of the area allocated for stack args.
  1949. Assert(offset >= 0);
  1950. Assert(baseReg != RegSP || (uint)offset >= (func->m_argSlotsForFunctionsCalled * MachRegInt));
  1951. if (func->GetMaxInlineeArgOutCount())
  1952. {
  1953. Assert(baseReg == RegSP);
  1954. if (stackSym->IsArgSlotSym() && !stackSym->m_isOrphanedArg)
  1955. {
  1956. Assert(stackSym->m_isInlinedArgSlot);
  1957. Assert((uint)offset <= ((func->m_argSlotsForFunctionsCalled + func->GetMaxInlineeArgOutCount()) * MachRegInt));
  1958. }
  1959. else
  1960. {
  1961. AssertMsg(stackSym->IsAllocated(), "StackSym offset should be set");
  1962. Assert((uint)offset > ((func->m_argSlotsForFunctionsCalled + func->GetMaxInlineeArgOutCount()) * MachRegInt));
  1963. }
  1964. }
  1965. // TODO: restore the following assert (very useful) once we have a way to tell whether prolog/epilog
  1966. // gen is complete.
  1967. //Assert(offset < func->m_localStackHeight);
  1968. }
  1969. #endif
  1970. *pBaseReg = baseReg;
  1971. *pOffset = offset;
  1972. }
  1973. ///----------------------------------------------------------------------------
  1974. ///
  1975. /// EncoderMD::ApplyRelocs
  1976. /// We apply relocations to the temporary buffer using the target buffer's address
  1977. /// before we copy the contents of the temporary buffer to the target buffer.
  1978. ///----------------------------------------------------------------------------
  1979. void
  1980. EncoderMD::ApplyRelocs(uint32 codeBufferAddress, size_t codeSize, uint* bufferCRC, BOOL isBrShorteningSucceeded, bool isFinalBufferValidation)
  1981. {
  1982. for (EncodeReloc *reloc = m_relocList; reloc; reloc = reloc->m_next)
  1983. {
  1984. BYTE * relocAddress = reloc->m_consumerOffset;
  1985. int32 pcrel;
  1986. ENCODE_32 encode = *(ENCODE_32*)relocAddress;
  1987. switch (reloc->m_relocType)
  1988. {
  1989. case RelocTypeBranch20:
  1990. {
  1991. IR::LabelInstr * labelInstr = reloc->m_relocInstr->AsLabelInstr();
  1992. Assert(!labelInstr->isInlineeEntryInstr);
  1993. AssertMsg(labelInstr->GetPC() != nullptr, "Branch to unemitted label?");
  1994. pcrel = (uint32)(labelInstr->GetPC() - reloc->m_consumerOffset);
  1995. encode |= BranchOffset_T2_20(pcrel);
  1996. *(uint32 *)relocAddress = encode;
  1997. break;
  1998. }
  1999. case RelocTypeBranch24:
  2000. {
  2001. IR::LabelInstr * labelInstr = reloc->m_relocInstr->AsLabelInstr();
  2002. Assert(!labelInstr->isInlineeEntryInstr);
  2003. AssertMsg(labelInstr->GetPC() != nullptr, "Branch to unemitted label?");
  2004. pcrel = (uint32)(labelInstr->GetPC() - reloc->m_consumerOffset);
  2005. encode |= BranchOffset_T2_24(pcrel);
  2006. *(ENCODE_32 *)relocAddress = encode;
  2007. break;
  2008. }
  2009. case RelocTypeDataLabelLow:
  2010. {
  2011. IR::LabelInstr * labelInstr = reloc->m_relocInstr->AsLabelInstr();
  2012. Assert(!labelInstr->isInlineeEntryInstr && labelInstr->m_isDataLabel);
  2013. AssertMsg(labelInstr->GetPC() != nullptr, "Branch to unemitted label?");
  2014. pcrel = ((labelInstr->GetPC() - m_encoder->m_encodeBuffer + codeBufferAddress) & 0xFFFF);
  2015. if (!EncodeImmediate16(pcrel, (DWORD*) &encode))
  2016. {
  2017. Assert(UNREACHED);
  2018. }
  2019. *(ENCODE_32 *) relocAddress = encode;
  2020. break;
  2021. }
  2022. case RelocTypeLabelLow:
  2023. {
  2024. // Absolute (not relative) label address (lower 16 bits)
  2025. IR::LabelInstr * labelInstr = reloc->m_relocInstr->AsLabelInstr();
  2026. if (!labelInstr->isInlineeEntryInstr)
  2027. {
  2028. AssertMsg(labelInstr->GetPC() != nullptr, "Branch to unemitted label?");
  2029. // Note that the bottom bit must be set, since this is a Thumb code address.
  2030. pcrel = ((labelInstr->GetPC() - m_encoder->m_encodeBuffer + codeBufferAddress) & 0xFFFF) | 1;
  2031. }
  2032. else
  2033. {
  2034. //This is a encoded low 16 bits.
  2035. pcrel = labelInstr->GetOffset() & 0xFFFF;
  2036. }
  2037. if (!EncodeImmediate16(pcrel, (DWORD*) &encode))
  2038. {
  2039. Assert(UNREACHED);
  2040. }
  2041. *(ENCODE_32 *) relocAddress = encode;
  2042. break;
  2043. }
  2044. case RelocTypeLabelHigh:
  2045. {
  2046. // Absolute (not relative) label address (upper 16 bits)
  2047. IR::LabelInstr * labelInstr = reloc->m_relocInstr->AsLabelInstr();
  2048. if (!labelInstr->isInlineeEntryInstr)
  2049. {
  2050. AssertMsg(labelInstr->GetPC() != nullptr, "Branch to unemitted label?");
  2051. pcrel = (labelInstr->GetPC() - m_encoder->m_encodeBuffer + codeBufferAddress) >> 16;
  2052. // We only record the relocation on the low byte of the pair
  2053. }
  2054. else
  2055. {
  2056. //This is a encoded high 16 bits.
  2057. pcrel = labelInstr->GetOffset() >> 16;
  2058. }
  2059. if (!EncodeImmediate16(pcrel, (DWORD*) &encode))
  2060. {
  2061. Assert(UNREACHED);
  2062. }
  2063. *(ENCODE_32 *) relocAddress = encode;
  2064. break;
  2065. }
  2066. case RelocTypeLabel:
  2067. {
  2068. IR::LabelInstr * labelInstr = reloc->m_relocInstr->AsLabelInstr();
  2069. AssertMsg(labelInstr->GetPC() != nullptr, "Branch to unemitted label?");
  2070. /* For Thumb instruction set -> OR 1 with the address*/
  2071. *(uint32 *)relocAddress = (uint32)(labelInstr->GetPC() - m_encoder->m_encodeBuffer + codeBufferAddress) | 1;
  2072. break;
  2073. }
  2074. default:
  2075. AssertMsg(UNREACHED, "Unknown reloc type");
  2076. }
  2077. }
  2078. }
  2079. void
  2080. EncoderMD::EncodeInlineeCallInfo(IR::Instr *instr, uint32 codeOffset)
  2081. {
  2082. IR::LabelInstr* inlineeStart = instr->AsLabelInstr();
  2083. Assert((inlineeStart->GetOffset() & 0x0F) == inlineeStart->GetOffset());
  2084. return;
  2085. }
  2086. bool EncoderMD::TryConstFold(IR::Instr *instr, IR::RegOpnd *regOpnd)
  2087. {
  2088. Assert(regOpnd->m_sym->IsConst());
  2089. if (instr->m_opcode == Js::OpCode::MOV)
  2090. {
  2091. if (instr->GetSrc1() != regOpnd)
  2092. {
  2093. return false;
  2094. }
  2095. if (!instr->GetDst()->IsRegOpnd())
  2096. {
  2097. return false;
  2098. }
  2099. instr->ReplaceSrc(regOpnd, regOpnd->m_sym->GetConstOpnd());
  2100. LegalizeMD::LegalizeInstr(instr, false);
  2101. return true;
  2102. }
  2103. else
  2104. {
  2105. return false;
  2106. }
  2107. }
  2108. bool EncoderMD::TryFold(IR::Instr *instr, IR::RegOpnd *regOpnd)
  2109. {
  2110. if (LowererMD::IsAssign(instr))
  2111. {
  2112. if (!instr->GetDst()->IsRegOpnd() || regOpnd != instr->GetSrc1())
  2113. {
  2114. return false;
  2115. }
  2116. IR::SymOpnd *symOpnd = IR::SymOpnd::New(regOpnd->m_sym, regOpnd->GetType(), instr->m_func);
  2117. instr->ReplaceSrc(regOpnd, symOpnd);
  2118. LegalizeMD::LegalizeInstr(instr, false);
  2119. return true;
  2120. }
  2121. else
  2122. {
  2123. return false;
  2124. }
  2125. }
  2126. void EncoderMD::AddLabelReloc(BYTE* relocAddress)
  2127. {
  2128. Assert(relocAddress != nullptr);
  2129. EncodeReloc::New(&m_relocList, RelocTypeLabel, relocAddress, *(IR::Instr**)relocAddress, m_encoder->m_tempAlloc);
  2130. }