scanner.cpp 38 KB

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