scanner.cpp 40 KB

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