scanner.cpp 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091
  1. /*****************************************************************************
  2. * dcc project scanner module
  3. * Implements a simple state driven scanner to convert 8086 machine code into
  4. * I-code
  5. * (C) Cristina Cifuentes, Jeff Ledermann
  6. ****************************************************************************/
  7. #include "scanner.h"
  8. #include "msvc_fixes.h"
  9. #include "dcc.h"
  10. #include "project.h"
  11. #include <cstring>
  12. #include <map>
  13. #include <string>
  14. /* Parser flags */
  15. #define TO_REG 0x000100 /* rm is source */
  16. #define S_EXT 0x000200 /* sign extend */
  17. #define OP386 0x000400 /* 386 op-code */
  18. #define NSP 0x000800 /* NOT_HLL if SP is src or dst */
  19. static void rm(int i);
  20. static void modrm(int i);
  21. static void segrm(int i);
  22. static void data1(int i);
  23. static void data2(int i);
  24. static void regop(int i);
  25. static void segop(int i);
  26. static void strop(int i);
  27. static void escop(int i);
  28. static void axImp(int i);
  29. static void alImp(int i);
  30. static void axSrcIm(int i);
  31. static void memImp(int i);
  32. static void memReg0(int i);
  33. static void memOnly(int i);
  34. static void dispM(int i);
  35. static void dispS(int i);
  36. static void dispN(int i);
  37. static void dispF(int i);
  38. static void prefix(int i);
  39. static void immed(int i);
  40. static void shift(int i);
  41. static void arith(int i);
  42. static void trans(int i);
  43. static void const1(int i);
  44. static void const3(int i);
  45. static void none1(int i);
  46. static void none2(int i);
  47. static void checkInt(int i);
  48. #define IC llIcode
  49. struct StateTabelEntry {
  50. void (*state1)(int);
  51. void (*state2)(int);
  52. uint32_t flg;
  53. llIcode opcode;
  54. };
  55. static const StateTabelEntry stateTable[] = {
  56. { modrm, none2, B , iADD }, /* 00 */
  57. { modrm, none2, 0 , iADD }, /* 01 */
  58. { modrm, none2, TO_REG | B , iADD }, /* 02 */
  59. { modrm, none2, TO_REG , iADD }, /* 03 */
  60. { data1, axImp, B , iADD }, /* 04 */
  61. { data2, axImp, 0 , iADD }, /* 05 */
  62. { segop, none2, NO_SRC , iPUSH }, /* 06 */
  63. { segop, none2, NO_SRC , iPOP }, /* 07 */
  64. { modrm, none2, B , iOR }, /* 08 */
  65. { modrm, none2, NSP , iOR }, /* 09 */
  66. { modrm, none2, TO_REG | B , iOR }, /* 0A */
  67. { modrm, none2, TO_REG | NSP , iOR }, /* 0B */
  68. { data1, axImp, B , iOR }, /* 0C */
  69. { data2, axImp, 0 , iOR }, /* 0D */
  70. { segop, none2, NO_SRC , iPUSH }, /* 0E */
  71. { none1, none2, OP386 , iINVALID }, /* 0F */
  72. { modrm, none2, B , iADC }, /* 10 */
  73. { modrm, none2, NSP , iADC }, /* 11 */
  74. { modrm, none2, TO_REG | B , iADC }, /* 12 */
  75. { modrm, none2, TO_REG | NSP , iADC }, /* 13 */
  76. { data1, axImp, B , iADC }, /* 14 */
  77. { data2, axImp, 0 , iADC }, /* 15 */
  78. { segop, none2, NOT_HLL | NO_SRC , iPUSH }, /* 16 */
  79. { segop, none2, NOT_HLL | NO_SRC , iPOP }, /* 17 */
  80. { modrm, none2, B , iSBB }, /* 18 */
  81. { modrm, none2, NSP , iSBB }, /* 19 */
  82. { modrm, none2, TO_REG | B , iSBB }, /* 1A */
  83. { modrm, none2, TO_REG | NSP , iSBB }, /* 1B */
  84. { data1, axImp, B , iSBB }, /* 1C */
  85. { data2, axImp, 0 , iSBB }, /* 1D */
  86. { segop, none2, NO_SRC , iPUSH }, /* 1E */
  87. { segop, none2, NO_SRC , iPOP }, /* 1F */
  88. { modrm, none2, B , iAND }, /* 20 */
  89. { modrm, none2, NSP , iAND }, /* 21 */
  90. { modrm, none2, TO_REG | B , iAND }, /* 22 */
  91. { modrm, none2, TO_REG | NSP , iAND }, /* 23 */
  92. { data1, axImp, B , iAND }, /* 24 */
  93. { data2, axImp, 0 , iAND }, /* 25 */
  94. { prefix, none2, 0 , (IC)rES}, /* 26 */
  95. { none1, axImp, NOT_HLL | B|NO_SRC , iDAA }, /* 27 */
  96. { modrm, none2, B , iSUB }, /* 28 */
  97. { modrm, none2, 0 , iSUB }, /* 29 */
  98. { modrm, none2, TO_REG | B , iSUB }, /* 2A */
  99. { modrm, none2, TO_REG , iSUB }, /* 2B */
  100. { data1, axImp, B , iSUB }, /* 2C */
  101. { data2, axImp, 0 , iSUB }, /* 2D */
  102. { prefix, none2, 0 , (IC)rCS}, /* 2E */
  103. { none1, axImp, NOT_HLL | B|NO_SRC , iDAS }, /* 2F */
  104. { modrm, none2, B , iXOR }, /* 30 */
  105. { modrm, none2, NSP , iXOR }, /* 31 */
  106. { modrm, none2, TO_REG | B , iXOR }, /* 32 */
  107. { modrm, none2, TO_REG | NSP , iXOR }, /* 33 */
  108. { data1, axImp, B , iXOR }, /* 34 */
  109. { data2, axImp, 0 , iXOR }, /* 35 */
  110. { prefix, none2, 0 , (IC)rSS}, /* 36 */
  111. { none1, axImp, NOT_HLL | NO_SRC , iAAA }, /* 37 */
  112. { modrm, none2, B , iCMP }, /* 38 */
  113. { modrm, none2, NSP , iCMP }, /* 39 */
  114. { modrm, none2, TO_REG | B , iCMP }, /* 3A */
  115. { modrm, none2, TO_REG | NSP , iCMP }, /* 3B */
  116. { data1, axImp, B , iCMP }, /* 3C */
  117. { data2, axImp, 0 , iCMP }, /* 3D */
  118. { prefix, none2, 0 , (IC)rDS}, /* 3E */
  119. { none1, axImp, NOT_HLL | NO_SRC , iAAS }, /* 3F */
  120. { regop, none2, 0 , iINC }, /* 40 */
  121. { regop, none2, 0 , iINC }, /* 41 */
  122. { regop, none2, 0 , iINC }, /* 42 */
  123. { regop, none2, 0 , iINC }, /* 43 */
  124. { regop, none2, NOT_HLL , iINC }, /* 44 */
  125. { regop, none2, 0 , iINC }, /* 45 */
  126. { regop, none2, 0 , iINC }, /* 46 */
  127. { regop, none2, 0 , iINC }, /* 47 */
  128. { regop, none2, 0 , iDEC }, /* 48 */
  129. { regop, none2, 0 , iDEC }, /* 49 */
  130. { regop, none2, 0 , iDEC }, /* 4A */
  131. { regop, none2, 0 , iDEC }, /* 4B */
  132. { regop, none2, NOT_HLL , iDEC }, /* 4C */
  133. { regop, none2, 0 , iDEC }, /* 4D */
  134. { regop, none2, 0 , iDEC }, /* 4E */
  135. { regop, none2, 0 , iDEC }, /* 4F */
  136. { regop, none2, NO_SRC , iPUSH }, /* 50 */
  137. { regop, none2, NO_SRC , iPUSH }, /* 51 */
  138. { regop, none2, NO_SRC , iPUSH }, /* 52 */
  139. { regop, none2, NO_SRC , iPUSH }, /* 53 */
  140. { regop, none2, NOT_HLL | NO_SRC , iPUSH }, /* 54 */
  141. { regop, none2, NO_SRC , iPUSH }, /* 55 */
  142. { regop, none2, NO_SRC , iPUSH }, /* 56 */
  143. { regop, none2, NO_SRC , iPUSH }, /* 57 */
  144. { regop, none2, NO_SRC , iPOP }, /* 58 */
  145. { regop, none2, NO_SRC , iPOP }, /* 59 */
  146. { regop, none2, NO_SRC , iPOP }, /* 5A */
  147. { regop, none2, NO_SRC , iPOP }, /* 5B */
  148. { regop, none2, NOT_HLL | NO_SRC , iPOP }, /* 5C */
  149. { regop, none2, NO_SRC , iPOP }, /* 5D */
  150. { regop, none2, NO_SRC , iPOP }, /* 5E */
  151. { regop, none2, NO_SRC , iPOP }, /* 5F */
  152. { none1, none2, NOT_HLL | NO_OPS , iPUSHA}, /* 60 */
  153. { none1, none2, NOT_HLL | NO_OPS , iPOPA }, /* 61 */
  154. { memOnly, modrm, TO_REG | NSP , iBOUND}, /* 62 */
  155. { none1, none2, OP386 , iINVALID }, /* 63 */
  156. { none1, none2, OP386 , iINVALID }, /* 64 */
  157. { none1, none2, OP386 , iINVALID }, /* 65 */
  158. { none1, none2, OP386 , iINVALID }, /* 66 */
  159. { none1, none2, OP386 , iINVALID }, /* 67 */
  160. { data2, none2, NO_SRC , iPUSH }, /* 68 */
  161. { modrm, data2, TO_REG | NSP , iIMUL }, /* 69 */
  162. { data1, none2, S_EXT | NO_SRC , iPUSH }, /* 6A */
  163. { modrm, data1, TO_REG | NSP | S_EXT , iIMUL }, /* 6B */
  164. { strop, memImp, NOT_HLL | B|IM_OPS , iINS }, /* 6C */
  165. { strop, memImp, NOT_HLL | IM_OPS , iINS }, /* 6D */
  166. { strop, memImp, NOT_HLL | B|IM_OPS , iOUTS }, /* 6E */
  167. { strop, memImp, NOT_HLL | IM_OPS , iOUTS }, /* 6F */
  168. { dispS, none2, NOT_HLL , iJO }, /* 70 */
  169. { dispS, none2, NOT_HLL , iJNO }, /* 71 */
  170. { dispS, none2, 0 , iJB }, /* 72 */
  171. { dispS, none2, 0 , iJAE }, /* 73 */
  172. { dispS, none2, 0 , iJE }, /* 74 */
  173. { dispS, none2, 0 , iJNE }, /* 75 */
  174. { dispS, none2, 0 , iJBE }, /* 76 */
  175. { dispS, none2, 0 , iJA }, /* 77 */
  176. { dispS, none2, 0 , iJS }, /* 78 */
  177. { dispS, none2, 0 , iJNS }, /* 79 */
  178. { dispS, none2, NOT_HLL , iJP }, /* 7A */
  179. { dispS, none2, NOT_HLL , iJNP }, /* 7B */
  180. { dispS, none2, 0 , iJL }, /* 7C */
  181. { dispS, none2, 0 , iJGE }, /* 7D */
  182. { dispS, none2, 0 , iJLE }, /* 7E */
  183. { dispS, none2, 0 , iJG }, /* 7F */
  184. { immed, data1, B , iINVALID }, /* 80 */
  185. { immed, data2, NSP , iINVALID }, /* 81 */
  186. { immed, data1, B , iINVALID }, /* 82 */ /* ?? */
  187. { immed, data1, NSP | S_EXT , iINVALID }, /* 83 */
  188. { modrm, none2, TO_REG | B , iTEST }, /* 84 */
  189. { modrm, none2, TO_REG | NSP , iTEST }, /* 85 */
  190. { modrm, none2, TO_REG | B , iXCHG }, /* 86 */
  191. { modrm, none2, TO_REG | NSP , iXCHG }, /* 87 */
  192. { modrm, none2, B , iMOV }, /* 88 */
  193. { modrm, none2, 0 , iMOV }, /* 89 */
  194. { modrm, none2, TO_REG | B , iMOV }, /* 8A */
  195. { modrm, none2, TO_REG , iMOV }, /* 8B */
  196. { segrm, none2, NSP , iMOV }, /* 8C */
  197. { memOnly, modrm, TO_REG | NSP , iLEA }, /* 8D */
  198. { segrm, none2, TO_REG | NSP , iMOV }, /* 8E */
  199. { memReg0, none2, NO_SRC , iPOP }, /* 8F */
  200. { none1, none2, NO_OPS , iNOP }, /* 90 */
  201. { regop, axImp, 0 , iXCHG }, /* 91 */
  202. { regop, axImp, 0 , iXCHG }, /* 92 */
  203. { regop, axImp, 0 , iXCHG }, /* 93 */
  204. { regop, axImp, NOT_HLL , iXCHG }, /* 94 */
  205. { regop, axImp, 0 , iXCHG }, /* 95 */
  206. { regop, axImp, 0 , iXCHG }, /* 96 */
  207. { regop, axImp, 0 , iXCHG }, /* 97 */
  208. { alImp, axImp, SRC_B | S_EXT , iSIGNEX}, /* 98 */
  209. {axSrcIm, axImp, IM_DST | S_EXT , iSIGNEX}, /* 99 */
  210. { dispF, none2, TO_REG , iCALLF }, /* 9A */ // TO_REG set to use SRC when processing setAddress
  211. { none1, none2, FLOAT_OP| NO_OPS , iWAIT }, /* 9B */
  212. { none1, none2, NOT_HLL | NO_OPS , iPUSHF}, /* 9C */
  213. { none1, none2, NOT_HLL | NO_OPS , iPOPF }, /* 9D */
  214. { none1, none2, NOT_HLL | NO_OPS , iSAHF }, /* 9E */
  215. { none1, none2, NOT_HLL | NO_OPS , iLAHF }, /* 9F */
  216. { dispM, axImp, B , iMOV }, /* A0 */
  217. { dispM, axImp, 0 , iMOV }, /* A1 */
  218. { dispM, axImp, TO_REG | B , iMOV }, /* A2 */
  219. { dispM, axImp, TO_REG , iMOV }, /* A3 */
  220. { strop, memImp, B | IM_OPS , iMOVS }, /* A4 */
  221. { strop, memImp, IM_OPS , iMOVS }, /* A5 */
  222. { strop, memImp, B | IM_OPS , iCMPS }, /* A6 */
  223. { strop, memImp, IM_OPS , iCMPS }, /* A7 */
  224. { data1, axImp, B , iTEST }, /* A8 */
  225. { data2, axImp, 0 , iTEST }, /* A9 */
  226. { strop, memImp, B | IM_OPS , iSTOS }, /* AA */
  227. { strop, memImp, IM_OPS , iSTOS }, /* AB */
  228. { strop, memImp, B | IM_OPS , iLODS }, /* AC */
  229. { strop, memImp, IM_OPS , iLODS }, /* AD */
  230. { strop, memImp, B | IM_OPS , iSCAS }, /* AE */
  231. { strop, memImp, IM_OPS , iSCAS }, /* AF */
  232. { regop, data1, B , iMOV }, /* B0 */
  233. { regop, data1, B , iMOV }, /* B1 */
  234. { regop, data1, B , iMOV }, /* B2 */
  235. { regop, data1, B , iMOV }, /* B3 */
  236. { regop, data1, B , iMOV }, /* B4 */
  237. { regop, data1, B , iMOV }, /* B5 */
  238. { regop, data1, B , iMOV }, /* B6 */
  239. { regop, data1, B , iMOV }, /* B7 */
  240. { regop, data2, 0 , iMOV }, /* B8 */
  241. { regop, data2, 0 , iMOV }, /* B9 */
  242. { regop, data2, 0 , iMOV }, /* BA */
  243. { regop, data2, 0 , iMOV }, /* BB */
  244. { regop, data2, NOT_HLL , iMOV }, /* BC */
  245. { regop, data2, 0 , iMOV }, /* BD */
  246. { regop, data2, 0 , iMOV }, /* BE */
  247. { regop, data2, 0 , iMOV }, /* BF */
  248. { shift, data1, B , iINVALID }, /* C0 */
  249. { shift, data1, NSP | SRC_B , iINVALID }, /* C1 */
  250. { data2, none2, 0 , iRET }, /* C2 */
  251. { none1, none2, NO_OPS , iRET }, /* C3 */
  252. { memOnly, modrm, TO_REG | NSP , iLES }, /* C4 */
  253. { memOnly, modrm, TO_REG | NSP , iLDS }, /* C5 */
  254. { memReg0, data1, B , iMOV }, /* C6 */
  255. { memReg0, data2, 0 , iMOV }, /* C7 */
  256. { data2, data1, 0 , iENTER}, /* C8 */
  257. { none1, none2, NO_OPS , iLEAVE}, /* C9 */
  258. { data2, none2, 0 , iRETF }, /* CA */
  259. { none1, none2, NO_OPS , iRETF }, /* CB */
  260. { const3, none2, NOT_HLL , iINT }, /* CC */
  261. { data1,checkInt, NOT_HLL , iINT }, /* CD */
  262. { none1, none2, NOT_HLL | NO_OPS , iINTO }, /* CE */
  263. { none1, none2, NOT_HLL | NO_OPS , iIRET }, /* Cf */
  264. { shift, const1, B , iINVALID }, /* D0 */
  265. { shift, const1, SRC_B , iINVALID }, /* D1 */
  266. { shift, none1, B , iINVALID }, /* D2 */
  267. { shift, none1, SRC_B , iINVALID }, /* D3 */
  268. { data1, axImp, NOT_HLL , iAAM }, /* D4 */
  269. { data1, axImp, NOT_HLL , iAAD }, /* D5 */
  270. { none1, none2, 0 , iINVALID }, /* D6 */
  271. { memImp, axImp, NOT_HLL | B| IM_OPS , iXLAT }, /* D7 */
  272. { escop, none2, FLOAT_OP , iESC }, /* D8 */
  273. { escop, none2, FLOAT_OP , iESC }, /* D9 */
  274. { escop, none2, FLOAT_OP , iESC }, /* DA */
  275. { escop, none2, FLOAT_OP , iESC }, /* DB */
  276. { escop, none2, FLOAT_OP , iESC }, /* DC */
  277. { escop, none2, FLOAT_OP , iESC }, /* DD */
  278. { escop, none2, FLOAT_OP , iESC }, /* DE */
  279. { escop, none2, FLOAT_OP , iESC }, /* Df */
  280. { dispS, none2, 0 , iLOOPNE}, /* E0 */
  281. { dispS, none2, 0 , iLOOPE}, /* E1 */
  282. { dispS, none2, 0 , iLOOP }, /* E2 */
  283. { dispS, none2, 0 , iJCXZ }, /* E3 */
  284. { data1, axImp, NOT_HLL | B|NO_SRC , iIN }, /* E4 */
  285. { data1, axImp, NOT_HLL | NO_SRC , iIN }, /* E5 */
  286. { data1, axImp, NOT_HLL | B|NO_SRC , iOUT }, /* E6 */
  287. { data1, axImp, NOT_HLL | NO_SRC , iOUT }, /* E7 */
  288. { dispN, none2, 0 , iCALL }, /* E8 */
  289. { dispN, none2, 0 , iJMP }, /* E9 */
  290. { dispF, none2, 0 , iJMPF }, /* EA */
  291. { dispS, none2, 0 , iJMP }, /* EB */
  292. { none1, axImp, NOT_HLL | B|NO_SRC , iIN }, /* EC */
  293. { none1, axImp, NOT_HLL | NO_SRC , iIN }, /* ED */
  294. { none1, axImp, NOT_HLL | B|NO_SRC , iOUT }, /* EE */
  295. { none1, axImp, NOT_HLL | NO_SRC , iOUT }, /* EF */
  296. { none1, none2, NOT_HLL | NO_OPS , iLOCK }, /* F0 */
  297. { none1, none2, 0 , iINVALID }, /* F1 */
  298. { prefix, none2, 0 , iREPNE}, /* F2 */
  299. { prefix, none2, 0 , iREPE }, /* F3 */
  300. { none1, none2, NOT_HLL | NO_OPS , iHLT }, /* F4 */
  301. { none1, none2, NO_OPS , iCMC }, /* F5 */
  302. { arith, none1, B , iINVALID }, /* F6 */
  303. { arith, none1, NSP , iINVALID }, /* F7 */
  304. { none1, none2, NO_OPS , iCLC }, /* F8 */
  305. { none1, none2, NO_OPS , iSTC }, /* F9 */
  306. { none1, none2, NOT_HLL | NO_OPS , iCLI }, /* FA */
  307. { none1, none2, NOT_HLL | NO_OPS , iSTI }, /* FB */
  308. { none1, none2, NO_OPS , iCLD }, /* FC */
  309. { none1, none2, NO_OPS , iSTD }, /* FD */
  310. { trans, none1, B , iINVALID }, /* FE */
  311. { trans, none1, NSP , iINVALID } /* FF */
  312. } ;
  313. static uint16_t SegPrefix, RepPrefix;
  314. static const uint8_t *pInst; /* Ptr. to current uint8_t of instruction */
  315. static ICODE * pIcode; /* Ptr to Icode record filled in by scan() */
  316. static void decodeBranchTgt(x86_insn_t &insn)
  317. {
  318. x86_op_t *tgt_op = insn.x86_get_branch_target();
  319. if(tgt_op->type==op_expression)
  320. return; // unhandled for now
  321. if(tgt_op->type==op_register)
  322. return; // unhandled for now
  323. int32_t addr = tgt_op->getAddress();
  324. if(tgt_op->is_relative())
  325. {
  326. addr = (uint16_t)(addr + insn.addr + insn.size);
  327. }
  328. pIcode->ll()->replaceSrc((uint32_t)addr);
  329. pIcode->ll()->setFlags(I);
  330. // PROG &prog(Project::get()->prog);
  331. // long off = (short)getWord(); /* Signed displacement */
  332. // assert(addr==(uint32_t)(off + (unsigned)(pInst - prog.image())));
  333. }
  334. static void convertUsedFlags(x86_insn_t &from,ICODE &to)
  335. {
  336. to.ll()->flagDU.d=0;
  337. to.ll()->flagDU.u=0;
  338. if(from.containsFlag(insn_eflag_carry,from.flags_set))
  339. to.ll()->flagDU.d |= Cf;
  340. if(from.containsFlag(insn_eflag_sign,from.flags_set))
  341. to.ll()->flagDU.d |= Sf;
  342. if(from.containsFlag(insn_eflag_zero,from.flags_set))
  343. to.ll()->flagDU.d |= Zf;
  344. if(from.containsFlag(insn_eflag_direction,from.flags_set))
  345. to.ll()->flagDU.d |= Df;
  346. if(from.containsFlag(insn_eflag_carry,from.flags_tested))
  347. to.ll()->flagDU.u |= Cf;
  348. if(from.containsFlag(insn_eflag_sign,from.flags_tested))
  349. to.ll()->flagDU.u |= Sf;
  350. if(from.containsFlag(insn_eflag_zero,from.flags_tested))
  351. to.ll()->flagDU.u |= Zf;
  352. if(from.containsFlag(insn_eflag_direction,from.flags_tested))
  353. to.ll()->flagDU.u |= Df;
  354. }
  355. static void convertPrefix(x86_insn_prefix prefix,ICODE &to)
  356. {
  357. if(prefix ==insn_no_prefix)
  358. return;
  359. // insn_lock - no need to handle
  360. RepPrefix = (uint16_t)prefix & ~insn_lock;
  361. }
  362. /****************************************************************************
  363. Checks for int 34 to int 3B - if so, converts to ESC nn instruction
  364. ****************************************************************************/
  365. static void fixFloatEmulation(x86_insn_t &insn)
  366. {
  367. if(insn.operand_count==0)
  368. return;
  369. if(insn.group!=x86_insn_t::insn_interrupt)
  370. return;
  371. PROG &prog(Project::get()->prog);
  372. uint16_t wOp=insn.x86_get_imm()->data.word;
  373. if ((wOp < 0x34) or (wOp > 0x3B))
  374. return;
  375. uint8_t buf[16];
  376. /* This is a Borland/Microsoft floating point emulation instruction. Treat as if it is an ESC opcode */
  377. int actual_valid_bytes=std::min(16U,prog.cbImage-insn.offset);
  378. memcpy(buf,prog.image()+insn.offset,actual_valid_bytes);
  379. X86_Disasm ds(opt_16_bit);
  380. x86_insn_t patched_insn;
  381. //patch actual instruction into buffer;
  382. buf[1] = wOp-0x34+0xD8;
  383. ds.x86_disasm(buf,actual_valid_bytes,0,1,&patched_insn);
  384. patched_insn.addr = insn.addr; // actual address
  385. patched_insn.offset = insn.offset; // actual offset
  386. insn = patched_insn;
  387. insn.size += 1; // to account for emulator call INT
  388. }
  389. int disassembleOneLibDisasm(uint32_t ip,x86_insn_t &l)
  390. {
  391. PROG &prog(Project::get()->prog);
  392. X86_Disasm ds(opt_16_bit);
  393. int cnt=ds.x86_disasm(prog.image(),prog.cbImage,0,ip,&l);
  394. if(cnt and l.is_valid())
  395. {
  396. fixFloatEmulation(l); //can change 'l'
  397. }
  398. if(l.is_valid())
  399. return l.size;
  400. return 0;
  401. }
  402. eReg convertRegister(const x86_reg_t &reg)
  403. {
  404. if( (reg_pc==reg.type) or (0==reg.id))
  405. return rUNDEF;
  406. eReg regmap[]={ rUNDEF,
  407. rUNDEF,rUNDEF,rUNDEF,rUNDEF, //eax ecx ebx edx
  408. rSP,rUNDEF,rUNDEF,rDI, //esp ebp esi edi
  409. rAX,rCX,rDX,rBX,
  410. rSP,rBP,rSI,rDI,
  411. rAL,rCL,rDL,rBL,
  412. rAH,rCH,rDH,rBH
  413. };
  414. std::map<std::string,eReg> nameToEnum = {{"es",rES},{"ds",rDS},{"cs",rCS},{"ss",rSS}};
  415. if(nameToEnum.find(reg.name)!=nameToEnum.end())
  416. return nameToEnum[reg.name];
  417. assert(reg.id<sizeof(regmap)/sizeof(eReg));
  418. assert(regmap[reg.id]!=rUNDEF);
  419. return regmap[reg.id];
  420. }
  421. LLOperand convertExpression(const x86_ea_t &from)
  422. {
  423. // BASE + Scale*Index + Disp
  424. LLOperand res;
  425. res.seg = rDS;
  426. /*
  427. INDEX_BX_SI = 22, // "bx+si"
  428. INDEX_BX_DI, // "bx+di"
  429. INDEX_BP_SI, // "bp+si"
  430. INDEX_BP_DI, // "bp+di"
  431. INDEX_SI, // "si"
  432. INDEX_DI, // "di"
  433. INDEX_BP, // "bp"
  434. INDEX_BX, // "bx"
  435. */
  436. if(from.base.id)
  437. {
  438. eReg base_reg = convertRegister(from.base);
  439. eReg index_reg = convertRegister(from.index);
  440. // if(base_reg==rBX)
  441. switch(base_reg)
  442. {
  443. case rDI:
  444. res.regi = INDEX_DI; break;
  445. case rBP:
  446. res.seg=rSS;
  447. switch(index_reg)
  448. {
  449. case rDI:
  450. res.regi = INDEX_BP_DI; break;
  451. case rSI:
  452. res.regi = INDEX_BP_SI; break;
  453. case rUNDEF:
  454. res.regi = INDEX_BP; break;
  455. default:
  456. assert(false);
  457. }
  458. break;
  459. case rBX:
  460. switch(index_reg)
  461. {
  462. case rDI:
  463. res.regi = INDEX_BX_DI; break;
  464. case rSI:
  465. res.regi = INDEX_BX_SI; break;
  466. case rUNDEF:
  467. res.regi = INDEX_BX; break;
  468. default:
  469. assert(false);
  470. }
  471. break;
  472. default:
  473. assert(false);
  474. }
  475. assert(index_reg==rUNDEF);
  476. }
  477. assert(from.scale==0);
  478. if(from.index.id)
  479. {
  480. assert(false);
  481. }
  482. res.off = from.disp;
  483. return res;
  484. }
  485. LLOperand convertOperand(const x86_op_t &from)
  486. {
  487. LLOperand res;
  488. switch(from.type)
  489. {
  490. case op_unused:
  491. break;
  492. case op_register:
  493. res.regi = convertRegister(from.data.reg); break;
  494. case op_immediate:
  495. res.opz = from.data.sdword; break;
  496. case op_expression:
  497. res = convertExpression(from.data.expression); break;
  498. case op_offset:
  499. {
  500. LLOperand res;
  501. res.seg = rDS;
  502. res.off = from.data.offset;
  503. break;
  504. }
  505. default:
  506. fprintf(stderr,"convertOperand does not know how to convert %d\n",from.type);
  507. }
  508. if(res.isSet() and (res.seg == rUNDEF))
  509. {
  510. res.seg = rDS;
  511. }
  512. return res;
  513. }
  514. /*****************************************************************************
  515. Scans one machine instruction at offset ip in prog.Image and returns error.
  516. At the same time, fill in low-level icode details for the scanned inst.
  517. ****************************************************************************/
  518. eErrorId scan(uint32_t ip, ICODE &p)
  519. {
  520. PROG &prog(Project::get()->prog);
  521. int op;
  522. p = ICODE();
  523. p.type = LOW_LEVEL_ICODE;
  524. p.ll()->label = ip; /* ip is absolute offset into image*/
  525. if (ip >= (uint32_t)prog.cbImage)
  526. {
  527. return (IP_OUT_OF_RANGE);
  528. }
  529. int cnt=disassembleOneLibDisasm(ip,p.insn);
  530. if(cnt)
  531. {
  532. convertUsedFlags(p.insn,p);
  533. convertPrefix(p.insn.prefix,p);
  534. }
  535. SegPrefix = RepPrefix = 0;
  536. pInst = prog.image() + ip;
  537. pIcode = &p;
  538. do
  539. {
  540. op = *pInst++; /* First state - trivial */
  541. /* Convert to Icode.opcode */
  542. p.ll()->set(stateTable[op].opcode,stateTable[op].flg & ICODEMASK);
  543. (*stateTable[op].state1)(op); /* Second state */
  544. (*stateTable[op].state2)(op); /* Third state */
  545. } while (stateTable[op].state1 == prefix); /* Loop if prefix */
  546. if(p.insn.group == x86_insn_t::insn_controlflow)
  547. {
  548. if(p.insn.x86_get_branch_target())
  549. decodeBranchTgt(p.insn);
  550. }
  551. // LLOperand conv = convertOperand(*p.insn.get_dest());
  552. // assert(conv==p.ll()->dst);
  553. if (p.ll()->getOpcode()!=iINVALID)
  554. {
  555. /* Save bytes of image used */
  556. p.ll()->numBytes = (uint8_t)((pInst - prog.image()) - ip);
  557. if(p.insn.is_valid())
  558. assert(p.ll()->numBytes == p.insn.size);
  559. p.ll()->numBytes = p.insn.size;
  560. return ((SegPrefix)? FUNNY_SEGOVR: /* Seg. Override invalid */
  561. (RepPrefix ? FUNNY_REP: NO_ERR));/* REP prefix invalid */
  562. }
  563. /* Else opcode error */
  564. return ((stateTable[op].flg & OP386)? INVALID_386OP: INVALID_OPCODE);
  565. }
  566. /***************************************************************************
  567. relocItem - returns true if uint16_t pointed at is in relocation table
  568. **************************************************************************/
  569. static bool relocItem(const uint8_t *p)
  570. {
  571. PROG &prog(Project::get()->prog);
  572. int i;
  573. uint32_t off = p - prog.image();
  574. for (i = 0; i < prog.cReloc; i++)
  575. if (prog.relocTable[i] == off)
  576. return true;
  577. return false;
  578. }
  579. /***************************************************************************
  580. getWord - returns next uint16_t from image
  581. **************************************************************************/
  582. static uint16_t getWord(void)
  583. {
  584. uint16_t w = LH(pInst);
  585. pInst += 2;
  586. return w;
  587. }
  588. /****************************************************************************
  589. signex - returns uint8_t sign extended to int
  590. ***************************************************************************/
  591. static int signex(uint8_t b)
  592. {
  593. long s = b;
  594. return ((b & 0x80)? (int)(0xFFFFFF00 | s): (int)s);
  595. }
  596. /****************************************************************************
  597. * setAddress - Updates the source or destination field for the current
  598. * icode, based on fdst and the TO_REG flag.
  599. * Note: fdst == true is for the r/m part of the field (dest, unless TO_REG)
  600. * fdst == false is for reg part of the field
  601. ***************************************************************************/
  602. static void setAddress(int i, bool fdst, uint16_t seg, int16_t reg, uint16_t off)
  603. {
  604. /* If not to register (i.e. to r/m), and talking about r/m, then this is dest */
  605. LLOperand *pm = (! (stateTable[i].flg & TO_REG) == fdst) ? &pIcode->ll()->m_dst : &pIcode->ll()->src();
  606. /* Set segment. A later procedure (lookupAddr in proclist.c) will
  607. * provide the value of this segment in the field segValue.
  608. */
  609. if (seg) /* segment override */
  610. {
  611. pm->seg = pm->segOver = (eReg)seg;
  612. }
  613. else
  614. { /* no override, check indexed register */
  615. if ((reg >= INDEX_BX_SI) and (reg == INDEX_BP_SI or reg == INDEX_BP_DI or reg == INDEX_BP))
  616. {
  617. pm->seg = rSS; /* indexed on bp */
  618. }
  619. else
  620. {
  621. pm->seg = rDS; /* any other indexed reg */
  622. }
  623. }
  624. pm->regi = (eReg)reg;
  625. pm->off = (int16_t)off;
  626. if (reg and (reg < INDEX_BX_SI) and (stateTable[i].flg & B))
  627. {
  628. pm->regi = Machine_X86::subRegL(pm->regi);
  629. }
  630. if (seg) /* So we can catch invalid use of segment overrides */
  631. {
  632. SegPrefix = 0;
  633. }
  634. }
  635. /****************************************************************************
  636. rm - Decodes r/m part of modrm uint8_t for dst (unless TO_REG) part of icode
  637. ***************************************************************************/
  638. static void rm(int i)
  639. {
  640. uint8_t mod = *pInst >> 6;
  641. uint8_t rm = *pInst++ & 7;
  642. switch (mod) {
  643. case 0: /* No disp unless rm == 6 */
  644. if (rm == 6) {
  645. setAddress(i, true, SegPrefix, 0, getWord());
  646. pIcode->ll()->setFlags(WORD_OFF);
  647. }
  648. else
  649. setAddress(i, true, SegPrefix, rm + INDEX_BX_SI, 0);
  650. break;
  651. case 1: /* 1 uint8_t disp */
  652. setAddress(i, true, SegPrefix, rm+INDEX_BX_SI, (uint16_t)signex(*pInst++));
  653. break;
  654. case 2: /* 2 uint8_t disp */
  655. setAddress(i, true, SegPrefix, rm + INDEX_BX_SI, getWord());
  656. pIcode->ll()->setFlags(WORD_OFF);
  657. break;
  658. case 3: /* reg */
  659. setAddress(i, true, 0, rm + rAX, 0);
  660. break;
  661. }
  662. //pIcode->insn.get_dest()->
  663. if ((stateTable[i].flg & NSP) and (pIcode->ll()->src().getReg2()==rSP or
  664. pIcode->ll()->m_dst.getReg2()==rSP))
  665. pIcode->ll()->setFlags(NOT_HLL);
  666. }
  667. /****************************************************************************
  668. modrm - Sets up src and dst from modrm uint8_t
  669. ***************************************************************************/
  670. static void modrm(int i)
  671. {
  672. setAddress(i, false, 0, REG(*pInst) + rAX, 0);
  673. rm(i);
  674. }
  675. /****************************************************************************
  676. segrm - seg encoded as reg of modrm
  677. ****************************************************************************/
  678. static void segrm(int i)
  679. {
  680. int reg = REG(*pInst) + rES;
  681. if (reg > rDS or (reg == rCS and (stateTable[i].flg & TO_REG)))
  682. pIcode->ll()->setOpcode((llIcode)0); // setCBW because it has that index
  683. else {
  684. setAddress(i, false, 0, (int16_t)reg, 0);
  685. rm(i);
  686. }
  687. }
  688. /****************************************************************************
  689. regop - src/dst reg encoded as low 3 bits of opcode
  690. ***************************************************************************/
  691. static void regop(int i)
  692. {
  693. setAddress(i, false, 0, ((int16_t)i & 0x7) + rAX, 0);
  694. pIcode->ll()->replaceDst(pIcode->ll()->src());
  695. }
  696. /*****************************************************************************
  697. segop - seg encoded in middle of opcode
  698. *****************************************************************************/
  699. static void segop(int i)
  700. {
  701. if(i==0x1E) {
  702. // printf("es");
  703. }
  704. setAddress(i, true, 0, (((int16_t)i & 0x18) >> 3) + rES, 0);
  705. }
  706. /****************************************************************************
  707. axImp - Plugs an implied AX dst
  708. ***************************************************************************/
  709. static void axImp(int i)
  710. {
  711. setAddress(i, true, 0, rAX, 0);
  712. }
  713. /* Implied AX source */
  714. static void axSrcIm (int )
  715. {
  716. pIcode->ll()->replaceSrc(rAX);//src.regi = rAX;
  717. }
  718. /* Implied AL source */
  719. static void alImp (int )
  720. {
  721. pIcode->ll()->replaceSrc(rAL);//src.regi = rAL;
  722. }
  723. /*****************************************************************************
  724. memImp - Plugs implied src memory operand with any segment override
  725. ****************************************************************************/
  726. static void memImp(int i)
  727. {
  728. setAddress(i, false, SegPrefix, 0, 0);
  729. }
  730. /****************************************************************************
  731. memOnly - Instruction is not valid if modrm refers to register (i.e. mod == 3)
  732. ***************************************************************************/
  733. static void memOnly(int )
  734. {
  735. if ((*pInst & 0xC0) == 0xC0)
  736. pIcode->ll()->setOpcode(iINVALID);
  737. }
  738. /****************************************************************************
  739. memReg0 - modrm for 'memOnly' and Reg field must also be 0
  740. ****************************************************************************/
  741. static void memReg0(int i)
  742. {
  743. if (REG(*pInst) or (*pInst & 0xC0) == 0xC0)
  744. pIcode->ll()->setOpcode(iINVALID);
  745. else
  746. rm(i);
  747. }
  748. /***************************************************************************
  749. immed - Sets up dst and opcode from modrm uint8_t
  750. **************************************************************************/
  751. static void immed(int i)
  752. {
  753. static llIcode immedTable[8] = {iADD, iOR, iADC, iSBB, iAND, iSUB, iXOR, iCMP};
  754. pIcode->ll()->setOpcode(immedTable[REG(*pInst)]) ;
  755. rm(i);
  756. if (pIcode->ll()->getOpcode() == iADD or pIcode->ll()->getOpcode() == iSUB)
  757. pIcode->ll()->clrFlags(NOT_HLL); /* Allow ADD/SUB SP, immed */
  758. }
  759. /****************************************************************************
  760. shift - Sets up dst and opcode from modrm uint8_t
  761. ***************************************************************************/
  762. static void shift(int i)
  763. {
  764. static llIcode shiftTable[8] =
  765. {
  766. (llIcode)iROL, (llIcode)iROR, (llIcode)iRCL, (llIcode)iRCR,
  767. (llIcode)iSHL, (llIcode)iSHR, (llIcode)0, (llIcode)iSAR};
  768. pIcode->ll()->setOpcode(shiftTable[REG(*pInst)]);
  769. rm(i);
  770. pIcode->ll()->replaceSrc(rCL); //src.regi =
  771. }
  772. /****************************************************************************
  773. trans - Sets up dst and opcode from modrm uint8_t
  774. ***************************************************************************/
  775. static void trans(int i)
  776. {
  777. static llIcode transTable[8] =
  778. {
  779. iINC, iDEC, iCALL, iCALLF,
  780. iJMP, iJMPF,iPUSH, (llIcode)0
  781. };
  782. LLInst *ll = pIcode->ll();
  783. // if(transTable[REG(*pInst)]==iPUSH) {
  784. // printf("es");
  785. // }
  786. if ((uint8_t)REG(*pInst) < 2 or not (stateTable[i].flg & B)) { /* INC & DEC */
  787. ll->setOpcode(transTable[REG(*pInst)]); /* valid on bytes */
  788. rm(i);
  789. ll->replaceSrc( pIcode->ll()->m_dst );
  790. if (ll->match(iJMP) or ll->match(iCALL) or ll->match(iCALLF))
  791. ll->setFlags(NO_OPS);
  792. else if (ll->match(iINC) or ll->match(iPUSH) or ll->match(iDEC))
  793. ll->setFlags(NO_SRC);
  794. }
  795. }
  796. /****************************************************************************
  797. arith - Sets up dst and opcode from modrm uint8_t
  798. ****************************************************************************/
  799. static void arith(int i)
  800. {
  801. uint8_t opcode;
  802. static llIcode arithTable[8] =
  803. {
  804. iTEST, iINVALID, iNOT, iNEG,
  805. iMUL , iIMUL, iDIV, iIDIV
  806. };
  807. opcode = arithTable[REG(*pInst)];
  808. pIcode->ll()->setOpcode((llIcode)opcode);
  809. rm(i);
  810. if (opcode == iTEST)
  811. {
  812. if (stateTable[i].flg & B)
  813. data1(i);
  814. else
  815. data2(i);
  816. }
  817. else if (not (opcode == iNOT or opcode == iNEG))
  818. {
  819. pIcode->ll()->replaceSrc( pIcode->ll()->m_dst );
  820. setAddress(i, true, 0, rAX, 0); /* dst = AX */
  821. }
  822. else if (opcode == iNEG or opcode == iNOT)
  823. pIcode->ll()->setFlags(NO_SRC);
  824. if ((opcode == iDIV) or (opcode == iIDIV))
  825. {
  826. if ( not pIcode->ll()->testFlags(B) )
  827. pIcode->ll()->setFlags(IM_TMP_DST);
  828. }
  829. }
  830. /*****************************************************************************
  831. data1 - Sets up immed from 1 uint8_t data
  832. *****************************************************************************/
  833. static void data1(int i)
  834. {
  835. pIcode->ll()->replaceSrc(LLOperand::CreateImm2((stateTable[i].flg & S_EXT)? signex(*pInst++): *pInst++,1));
  836. pIcode->ll()->setFlags(I);
  837. }
  838. /*****************************************************************************
  839. data2 - Sets up immed from 2 uint8_t data
  840. ****************************************************************************/
  841. static void data2(int )
  842. {
  843. if (relocItem(pInst))
  844. pIcode->ll()->setFlags(SEG_IMMED);
  845. /* ENTER is a special case, it does not take a destination operand,
  846. * but this field is being used as the number of bytes to allocate
  847. * on the stack. The procedure level is stored in the immediate
  848. * field. There is no source operand; therefore, the flag flg is
  849. * set to NO_OPS. */
  850. if (pIcode->ll()->getOpcode() == iENTER)
  851. {
  852. pIcode->ll()->m_dst.off = getWord();
  853. pIcode->ll()->setFlags(NO_OPS);
  854. }
  855. else
  856. pIcode->ll()->replaceSrc(getWord());
  857. pIcode->ll()->setFlags(I);
  858. }
  859. /****************************************************************************
  860. dispM - 2 uint8_t offset without modrm (== mod 0, rm 6) (Note:TO_REG bits are
  861. reversed)
  862. ****************************************************************************/
  863. static void dispM(int i)
  864. {
  865. setAddress(i, false, SegPrefix, 0, getWord());
  866. }
  867. /****************************************************************************
  868. dispN - 2 uint8_t disp as immed relative to ip
  869. ****************************************************************************/
  870. static void dispN(int )
  871. {
  872. //PROG &prog(Project::get()->prog);
  873. /*long off = (short)*/getWord(); /* Signed displacement */
  874. /* Note: the result of the subtraction could be between 32k and 64k, and
  875. still be positive; it is an offset from prog.Image. So this must be
  876. treated as unsigned */
  877. // decodeBranchTgt();
  878. }
  879. /***************************************************************************
  880. dispS - 1 byte disp as immed relative to ip
  881. ***************************************************************************/
  882. static void dispS(int )
  883. {
  884. /*long off =*/ signex(*pInst++); /* Signed displacement */
  885. // decodeBranchTgt();
  886. }
  887. /****************************************************************************
  888. dispF - 4 byte disp as immed 20-bit target address
  889. ***************************************************************************/
  890. static void dispF(int i)
  891. {
  892. uint16_t off = (unsigned)getWord();
  893. uint16_t seg = (unsigned)getWord();
  894. // FIXME: this is wrong since seg here is seg value, but setAddress treats it as register id
  895. setAddress(i, true, seg, 0, off);
  896. // decodeBranchTgt();
  897. }
  898. /****************************************************************************
  899. prefix - picks up prefix uint8_t for following instruction (LOCK is ignored
  900. on purpose)
  901. ****************************************************************************/
  902. static void prefix(int )
  903. {
  904. if ((pIcode->ll()->getOpcode() == iREPE) or (pIcode->ll()->getOpcode() == iREPNE))
  905. RepPrefix = pIcode->ll()->getOpcode();
  906. else
  907. SegPrefix = pIcode->ll()->getOpcode();
  908. }
  909. inline void BumpOpcode(LLInst &ll)
  910. {
  911. llIcode ic(ll.getOpcode());
  912. ic = (llIcode)(((int)ic)+1); // Bump this icode via the int type
  913. ll.setOpcode(ic);
  914. }
  915. /*****************************************************************************
  916. strop - checks RepPrefix and converts string instructions accordingly
  917. *****************************************************************************/
  918. static void strop(int )
  919. {
  920. if (RepPrefix)
  921. {
  922. if ( pIcode->ll()->match(iCMPS) or pIcode->ll()->match(iSCAS) )
  923. {
  924. if(pIcode->insn.prefix & insn_rep_zero)
  925. {
  926. BumpOpcode(*pIcode->ll()); // iCMPS -> iREPE_CMPS
  927. BumpOpcode(*pIcode->ll());
  928. }
  929. else if(pIcode->insn.prefix & insn_rep_notzero)
  930. BumpOpcode(*pIcode->ll()); // iX -> iREPNE_X
  931. }
  932. else
  933. if(pIcode->insn.prefix & insn_rep_zero)
  934. BumpOpcode(*pIcode->ll()); // iX -> iREPE_X
  935. if (pIcode->ll()->match(iREP_LODS) )
  936. pIcode->ll()->setFlags(NOT_HLL);
  937. RepPrefix = 0;
  938. }
  939. }
  940. /***************************************************************************
  941. escop - esc operands
  942. ***************************************************************************/
  943. static void escop(int i)
  944. {
  945. pIcode->ll()->replaceSrc(REG(*pInst) + (uint32_t)((i & 7) << 3));
  946. pIcode->ll()->setFlags(I);
  947. rm(i);
  948. }
  949. /****************************************************************************
  950. const1
  951. ****************************************************************************/
  952. static void const1(int )
  953. {
  954. pIcode->ll()->replaceSrc(1);
  955. pIcode->ll()->setFlags(I);
  956. }
  957. /*****************************************************************************
  958. const3
  959. ****************************************************************************/
  960. static void const3(int )
  961. {
  962. pIcode->ll()->replaceSrc(3);
  963. pIcode->ll()->setFlags(I);
  964. }
  965. /****************************************************************************
  966. none1
  967. ****************************************************************************/
  968. static void none1(int )
  969. {
  970. }
  971. /****************************************************************************
  972. none2 - Sets the NO_OPS flag if the operand is immediate
  973. ****************************************************************************/
  974. static void none2(int )
  975. {
  976. if ( pIcode->ll()->testFlags(I) )
  977. pIcode->ll()->setFlags(NO_OPS);
  978. }
  979. /****************************************************************************
  980. Checks for int 34 to int 3B - if so, converts to ESC nn instruction
  981. ****************************************************************************/
  982. static void checkInt(int )
  983. {
  984. uint16_t wOp = (uint16_t) pIcode->ll()->src().getImm2();
  985. if ((wOp >= 0x34) and (wOp <= 0x3B))
  986. {
  987. /* This is a Borland/Microsoft floating point emulation instruction.
  988. Treat as if it is an ESC opcode */
  989. pIcode->ll()->replaceSrc(wOp - 0x34);
  990. pIcode->ll()->set(iESC,FLOAT_OP);
  991. escop(wOp - 0x34 + 0xD8);
  992. }
  993. }