ao386msc.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. Unit ao386msc;
  2. Interface
  3. uses i386base;
  4. { enable the following define if memory references can have both a base and }
  5. { index register in 1 operand }
  6. {$define RefsHaveIndexReg}
  7. { enable the following define if memory references can have a scaled index }
  8. {$define RefsHaveScale}
  9. { enable the following define if memory references can have a segment }
  10. { override }
  11. {$define RefsHaveSegment}
  12. { enable the following define if memory references can have a symbol }
  13. { value }
  14. {$define RefsHaveSymbol}
  15. Type
  16. {possible actions on an operand: read, write or modify (= read & write)}
  17. TOpAction = (OpAct_Read, OpAct_Write, OpAct_Modify, OpAct_Unknown);
  18. { type of a normal instruction }
  19. TInstr = Tai386;
  20. PInstr = ^TInstr;
  21. TFlag = (DirFlag);
  22. TFlagContents = (F_Unknown, F_Clear, F_Set);
  23. TCondRegs = Object
  24. Flags: Array[TFlag] of TFlagContents;
  25. Constructor Init;
  26. Procedure InitFlag(f: TFlag);
  27. Procedure SetFlag(f: TFlag);
  28. Procedure ClearFlag(f: TFlag);
  29. Function GetFlag(f: TFlag): TFlagContents;
  30. End;
  31. {What an instruction can change}
  32. TChange = (C_None,
  33. {Read from a register}
  34. C_REAX, C_RECX, C_REDX, C_REBX, C_RESP, C_REBP, C_RESI, C_REDI,
  35. {write from a register}
  36. C_WEAX, C_WECX, C_WEDX, C_WEBX, C_WESP, C_WEBP, C_WESI, C_WEDI,
  37. {read and write from/to a register}
  38. C_RWEAX, C_RWECX, C_RWEDX, C_RWEBX, C_RWESP, C_RWEBP, C_RWESI, C_RWEDI,
  39. {modify the contents of a register with the purpose of using
  40. this changed content afterwards (add/sub/..., but e.g. not rep
  41. or movsd)}
  42. {$ifdef arithopt}
  43. C_MEAX, C_MECX, C_MEDX, C_MEBX, C_MESP, C_MEBP, C_MESI, C_MEDI,
  44. {$endif arithopt}
  45. C_CDirFlag {clear direction flag}, C_SDirFlag {set dir flag},
  46. C_RFlags, C_WFlags, C_RWFlags, C_FPU,
  47. C_Rop1, C_Wop1, C_RWop1,
  48. C_Rop2, C_Wop2, C_RWop2,
  49. C_Rop3, C_WOp3, C_RWOp3,
  50. {$ifdef arithopt}
  51. C_Mop1, C_Mop2, C_Mop3,
  52. {$endif arithopt}
  53. C_WMemEDI,
  54. C_All);
  55. Const
  56. {$ifndef arithopt}
  57. C_MEAX = C_RWEAX;
  58. C_MECX = C_RWECX;
  59. C_MEDX = C_RWEDX;
  60. C_MEBX = C_RWEBX;
  61. C_MESP = C_RWESP;
  62. C_MEBP = C_RWEBP;
  63. C_MESI = C_RWESI;
  64. C_MEDI = C_RWEDI;
  65. C_Mop1 = C_RWOp1;
  66. C_Mop2 = C_RWOp2;
  67. C_Mop3 = C_RWOp3;
  68. {$endif arithopt}
  69. { the maximum number of things (registers, memory, ...) a single instruction }
  70. { changes }
  71. MaxCh = 3;
  72. { the maximum number of operands an instruction has }
  73. MaxOps = 3;
  74. {Oper index of operand that contains the source (reference) with a load }
  75. {instruction }
  76. LoadSrc = 0;
  77. {Oper index of operand that contains the destination (register) with a load }
  78. {instruction }
  79. LoadDst = 1;
  80. {Oper index of operand that contains the source (register) with a store }
  81. {instruction }
  82. StoreSrc = 0;
  83. {Oper index of operand that contains the destination (reference) with a load }
  84. {instruction }
  85. StoreDst = 1;
  86. { low and high maximum width general purpose register }
  87. LoGPReg = R_EAX;
  88. HiGPReg = R_EDI;
  89. { low and high of every possible width general purpose register (same as }
  90. { above on most architctures apart from the 80x86) }
  91. LoReg = R_EAX;
  92. HiReg = R_BL;
  93. { Stack pointer }
  94. StackPtr = R_ESP;
  95. Const AsmInstr: Array[tasmop] Of TAsmInstrucProp = (
  96. {A_<NONE>} (Ch: (C_All, C_None, C_None)), { new }
  97. {A_LOCK} (Ch: (C_None, C_None, C_None)),
  98. {A_REP} (Ch: (C_RWECX, C_RFlags, C_None)),
  99. {A_REPE} (Ch: (C_RWECX, C_RFlags, C_None)),
  100. {A_REPNE} (Ch: (C_RWECX, C_RFlags, C_None)),
  101. {A_REPNZ} (Ch: (C_WECX, C_RWFLAGS, C_None)), { new }
  102. {A_REPZ} (Ch: (C_WECX, C_RWFLAGS, C_None)), { new }
  103. {A_SEGCS} (Ch: (C_None, C_None, C_None)), { new }
  104. {A_SEGES} (Ch: (C_None, C_None, C_None)), { new }
  105. {A_SEGDS} (Ch: (C_None, C_None, C_None)), { new }
  106. {A_SEGFS} (Ch: (C_None, C_None, C_None)), { new }
  107. {A_SEGGS} (Ch: (C_None, C_None, C_None)), { new }
  108. {A_SEGSS} (Ch: (C_None, C_None, C_None)), { new }
  109. {A_AAA} (Ch: (C_MEAX, C_WFlags, C_None)),
  110. {A_AAD} (Ch: (C_MEAX, C_WFlags, C_None)),
  111. {A_AAM} (Ch: (C_MEAX, C_WFlags, C_None)),
  112. {A_AAS} (Ch: (C_MEAX, C_WFlags, C_None)),
  113. {A_ADC} (Ch: (C_Mop2, C_Rop1, C_RWFlags)),
  114. {A_ADD} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
  115. {A_AND} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
  116. {A_ARPL} (Ch: (C_WFlags, C_None, C_None)),
  117. {A_BOUND} (Ch: (C_Rop1, C_None, C_None)),
  118. {A_BSF} (Ch: (C_Wop2, C_WFlags, C_Rop1)),
  119. {A_BSR} (Ch: (C_Wop2, C_WFlags, C_Rop1)),
  120. {A_BSWAP} (Ch: (C_MOp1, C_None, C_None)), { new }
  121. {A_BT} (Ch: (C_WFlags, C_Rop1, C_None)),
  122. {A_BTC} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
  123. {A_BTR} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
  124. {A_BTS} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
  125. {A_CALL} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
  126. {A_CBW} (Ch: (C_MEAX, C_None, C_None)),
  127. {A_CDQ} (Ch: (C_MEAX, C_WEDX, C_None)),
  128. {A_CLC} (Ch: (C_WFlags, C_None, C_None)),
  129. {A_CLD} (Ch: (C_CDirFlag, C_None, C_None)),
  130. {A_CLI} (Ch: (C_WFlags, C_None, C_None)),
  131. {A_CLTS} (Ch: (C_None, C_None, C_None)),
  132. {A_CMC} (Ch: (C_WFlags, C_None, C_None)),
  133. {A_CMP} (Ch: (C_WFlags, C_None, C_None)),
  134. {A_CMPSB} (Ch: (C_All, C_None, C_None)), { new }
  135. {A_CMPSD} (Ch: (C_All, C_None, C_None)), { new }
  136. {A_CMPSW} (Ch: (C_All, C_None, C_None)), { new }
  137. {A_CMPXCHG} (Ch: (C_All, C_None, C_None)), { new }
  138. {A_CMPXCHG486} (Ch: (C_All, C_None, C_None)), { new }
  139. {A_CMPXCHG8B} (Ch: (C_All, C_None, C_None)), { new }
  140. {A_CPUID} (Ch: (C_All, C_None, C_none)),
  141. {A_CWD} (Ch: (C_MEAX, C_WEDX, C_None)),
  142. {A_CWDE} (Ch: (C_MEAX, C_None, C_None)),
  143. {A_DAA} (Ch: (C_MEAX, C_None, C_None)),
  144. {A_DAS} (Ch: (C_MEAX, C_None, C_None)),
  145. {A_DEC} (Ch: (C_Mop1, C_WFlags, C_None)),
  146. {A_DIV} (Ch: (C_RWEAX, C_WEDX, C_WFlags)),
  147. {A_EMMS} (Ch: (C_FPU, C_None, C_None)), { new }
  148. {A_ENTER} (Ch: (C_RWESP, C_None, C_None)),
  149. {A_EQU} (Ch: (C_None, C_None, C_None)), { new }
  150. {A_F2XM1} (Ch: (C_FPU, C_None, C_None)),
  151. {A_FABS} (Ch: (C_FPU, C_None, C_None)),
  152. {A_FADD} (Ch: (C_FPU, C_None, C_None)),
  153. {A_FADDP} (Ch: (C_FPU, C_None, C_None)),
  154. {A_FBLD} (Ch: (C_Rop1, C_FPU, C_None)),
  155. {A_FBSTP} (Ch: (C_Wop1, C_FPU, C_None)),
  156. {A_FCHS} (Ch: (C_FPU, C_None, C_None)),
  157. {A_FCLEX} (Ch: (C_FPU, C_None, C_None)),
  158. {A_FCMOVB} (Ch: (C_FPU, C_RFLAGS, C_None)), { new }
  159. {A_FCMOVBE} (Ch: (C_FPU, C_RFLAGS, C_None)), { new }
  160. {A_FCMOVE} (Ch: (C_FPU, C_RFLAGS, C_None)), { new }
  161. {A_FCMOVNB} (Ch: (C_FPU, C_RFLAGS, C_None)), { new }
  162. {A_FCMOVNBE} (Ch: (C_FPU, C_RFLAGS, C_None)), { new }
  163. {A_FCMOVNE} (Ch: (C_FPU, C_RFLAGS, C_None)), { new }
  164. {A_FCMOVNU} (Ch: (C_FPU, C_RFLAGS, C_None)), { new }
  165. {A_FCMOVU} (Ch: (C_FPU, C_RFLAGS, C_None)), { new }
  166. {A_FCOM} (Ch: (C_FPU, C_None, C_None)),
  167. {A_FCOMI} (Ch: (C_WFLAGS, C_None, C_None)), { new }
  168. {A_FCOMIP} (Ch: (C_FPU, C_WFLAGS, C_None)), { new }
  169. {A_FCOMP} (Ch: (C_FPU, C_None, C_None)),
  170. {A_FCOMPP} (Ch: (C_FPU, C_None, C_None)),
  171. {A_FCOS} (Ch: (C_FPU, C_None, C_None)),
  172. {A_FDECSTP} (Ch: (C_FPU, C_None, C_None)),
  173. {A_FDISI} (Ch: (C_FPU, C_None, C_None)),
  174. {A_FDIV} (Ch: (C_FPU, C_None, C_None)),
  175. {A_FDIVP} (Ch: (C_FPU, C_None, C_None)),
  176. {A_FDIVR} (Ch: (C_FPU, C_None, C_None)),
  177. {A_FDIVRP} (Ch: (C_FPU, C_None, C_None)),
  178. {A_FEMMS} (Ch: (C_All, C_None, C_None)), { new }
  179. {A_FENI} (Ch: (C_FPU, C_None, C_None)),
  180. {A_FFREE} (Ch: (C_FPU, C_None, C_None)),
  181. {A_FIADD} (Ch: (C_FPU, C_None, C_None)),
  182. {A_FICOM} (Ch: (C_FPU, C_None, C_None)),
  183. {A_FICOMP} (Ch: (C_FPU, C_None, C_None)),
  184. {A_FIDIV} (Ch: (C_FPU, C_None, C_None)),
  185. {A_FIDIVR} (Ch: (C_FPU, C_None, C_None)),
  186. {A_FILD} (Ch: (C_FPU, C_None, C_None)),
  187. {A_FIMUL} (Ch: (C_FPU, C_None, C_None)),
  188. {A_FINCSTP} (Ch: (C_FPU, C_None, C_None)),
  189. {A_FINIT} (Ch: (C_FPU, C_None, C_None)),
  190. {A_FIST} (Ch: (C_Wop1, C_None, C_None)),
  191. {A_FISTP} (Ch: (C_Wop1, C_None, C_None)),
  192. {A_FISUB} (Ch: (C_FPU, C_None, C_None)),
  193. {A_FISUBR} (Ch: (C_FPU, C_None, C_None)), { new }
  194. {A_FLD} (Ch: (C_Rop1, C_FPU, C_None)),
  195. {A_FLD1} (Ch: (C_FPU, C_None, C_None)),
  196. {A_FLDCW} (Ch: (C_FPU, C_None, C_None)),
  197. {A_FLDENV} (Ch: (C_FPU, C_None, C_None)),
  198. {A_FLDL2E} (Ch: (C_FPU, C_None, C_None)),
  199. {A_FLDL2T} (Ch: (C_FPU, C_None, C_None)),
  200. {A_FLDLG2} (Ch: (C_FPU, C_None, C_None)),
  201. {A_FLDLN2} (Ch: (C_FPU, C_None, C_None)),
  202. {A_FLDPI} (Ch: (C_FPU, C_None, C_None)),
  203. {A_FLDZ} (Ch: (C_FPU, C_None, C_None)),
  204. {A_FMUL} (Ch: (C_FPU, C_None, C_None)),
  205. {A_FMULP} (Ch: (C_FPU, C_None, C_None)),
  206. {A_FNCLEX} (Ch: (C_FPU, C_None, C_None)),
  207. {A_FNDISI} (Ch: (C_FPU, C_None, C_None)),
  208. {A_FNENI} (Ch: (C_FPU, C_None, C_None)),
  209. {A_FNINIT} (Ch: (C_FPU, C_None, C_None)),
  210. {A_FNOP} (Ch: (C_FPU, C_None, C_None)),
  211. {A_FNSAVE} (Ch: (C_FPU, C_None, C_None)),
  212. {A_FNSTCW} (Ch: (C_Wop1, C_None, C_None)),
  213. {A_FNSTENV} (Ch: (C_Wop1, C_None, C_None)),
  214. {A_FNSTSW} (Ch: (C_Wop1, C_None, C_None)),
  215. {A_FPATAN} (Ch: (C_FPU, C_None, C_None)),
  216. {A_FPREM} (Ch: (C_FPU, C_None, C_None)),
  217. {A_FPREM1} (Ch: (C_FPU, C_None, C_None)),
  218. {A_FPTAN} (Ch: (C_FPU, C_None, C_None)),
  219. {A_FRNDINT} (Ch: (C_FPU, C_None, C_None)),
  220. {A_FRSTOR} (Ch: (C_FPU, C_None, C_None)),
  221. {A_FSAVE} (Ch: (C_Wop1, C_None, C_None)),
  222. {A_FSCALE} (Ch: (C_FPU, C_None, C_None)),
  223. {A_FSETPM} (Ch: (C_FPU, C_None, C_None)),
  224. {A_FSIN} (Ch: (C_FPU, C_None, C_None)),
  225. {A_FSINCOS} (Ch: (C_FPU, C_None, C_None)),
  226. {A_FSQRT} (Ch: (C_FPU, C_None, C_None)),
  227. {A_FST} (Ch: (C_Wop1, C_None, C_None)),
  228. {A_FSTCW} (Ch: (C_Wop1, C_None, C_None)),
  229. {A_FSTENV} (Ch: (C_Wop1, C_None, C_None)),
  230. {A_FSTP} (Ch: (C_Wop1, C_FPU, C_None)),
  231. {A_FSTSW} (Ch: (C_Wop1, C_None, C_None)),
  232. {A_FSUB} (Ch: (C_FPU, C_None, C_None)),
  233. {A_FSUBP} (Ch: (C_FPU, C_None, C_None)),
  234. {A_FSUBR} (Ch: (C_FPU, C_None, C_None)),
  235. {A_FSUBRP} (Ch: (C_FPU, C_None, C_None)),
  236. {A_FTST} (Ch: (C_FPU, C_None, C_None)),
  237. {A_FUCOM} (Ch: (C_None, C_None, C_None)), {changes fpu status word}
  238. {A_FUCOMI} (Ch: (C_WFLAGS, C_None, C_None)), { new }
  239. {A_FUCOMIP} (Ch: (C_FPU, C_WFLAGS, C_None)), { new }
  240. {A_FUCOMP} (Ch: (C_FPU, C_None, C_None)),
  241. {A_FUCOMPP} (Ch: (C_FPU, C_None, C_None)),
  242. {A_FWAIT} (Ch: (C_FPU, C_None, C_None)),
  243. {A_FXAM} (Ch: (C_FPU, C_None, C_None)),
  244. {A_FXCH} (Ch: (C_FPU, C_None, C_None)),
  245. {A_FXTRACT} (Ch: (C_FPU, C_None, C_None)),
  246. {A_FYL2X} (Ch: (C_FPU, C_None, C_None)),
  247. {A_FYL2XP1} (Ch: (C_FPU, C_None, C_None)),
  248. {A_HLT} (Ch: (C_None, C_None, C_None)),
  249. {A_IBTS} (Ch: (C_All, C_None, C_None)), { new }
  250. {A_ICEBP} (Ch: (C_All, C_None, C_None)), { new }
  251. {A_IDIV} (Ch: (C_RWEAX, C_WEDX, C_WFlags)), {handled separately, because modifies more than three things}
  252. {A_IMUL} (Ch: (C_RWEAX, C_WEDX, C_WFlags)), {handled separately, because several forms exist}
  253. {A_IN} (Ch: (C_Wop2, C_Rop1, C_None)),
  254. {A_INC} (Ch: (C_Mop1, C_WFlags, C_None)),
  255. {A_INSB} (Ch: (C_WMemEDI, C_RWEDI, C_None)), { new }
  256. {A_INSD} (Ch: (C_WMemEDI, C_RWEDI, C_None)), { new }
  257. {A_INSW} (Ch: (C_WMemEDI, C_RWEDI, C_None)), { new }
  258. {A_INT} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
  259. {A_INT01} (Ch: (C_All, C_None, C_None)), { new }
  260. {A_INT1} (Ch: (C_All, C_None, C_None)), { new }
  261. {A_INT3} (Ch: (C_None, C_None, C_None)),
  262. {A_INTO} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
  263. {A_INVD} (Ch: (C_All, C_None, C_None)), { new }
  264. {A_INVLPG} (Ch: (C_All, C_None, C_None)), { new }
  265. {A_IRET} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
  266. {A_IRETD} (Ch: (C_All, C_None, C_None)), { new }
  267. {A_IRETW} (Ch: (C_All, C_None, C_None)), { new }
  268. {A_JCXZ} (Ch: (C_RECX, C_None, C_None)),
  269. {A_JECXZ} (Ch: (C_RECX, C_None, C_None)),
  270. {A_JMP} (Ch: (C_None, C_None, C_None)),
  271. {A_LAHF} (Ch: (C_WEAX, C_RFlags, C_None)),
  272. {A_LAR} (Ch: (C_Wop2, C_None, C_None)),
  273. {A_LDS} (Ch: (C_Wop2, C_None, C_None)),
  274. {A_LEA} (Ch: (C_Wop2, C_Rop1, C_None)),
  275. {A_LEAVE} (Ch: (C_RWESP, C_None, C_None)),
  276. {A_LES} (Ch: (C_Wop2, C_None, C_None)),
  277. {A_LFS} (Ch: (C_Wop2, C_None, C_None)),
  278. {A_LGDT} (Ch: (C_None, C_None, C_None)),
  279. {A_LGS} (Ch: (C_Wop2, C_None, C_None)),
  280. {A_LIDT} (Ch: (C_None, C_None, C_None)),
  281. {A_LLDT} (Ch: (C_None, C_None, C_None)),
  282. {A_LMSW} (Ch: (C_None, C_None, C_None)),
  283. {A_LOADALL} (Ch: (C_All, C_None, C_None)), { new }
  284. {A_LOADALL286} (Ch: (C_All, C_None, C_None)), { new }
  285. {A_LODSB} (Ch: (C_WEAX, C_RWESI, C_None)), { new }
  286. {A_LODSD} (Ch: (C_WEAX, C_RWESI, C_None)), { new }
  287. {A_LODSW} (Ch: (C_WEAX, C_RWESI, C_None)), { new }
  288. {A_LOOP} (Ch: (C_RWECX, C_None, C_None)),
  289. {A_LOOPE} (Ch: (C_RWECX, C_RFlags, C_None)),
  290. {A_LOOPNE} (Ch: (C_RWECX, C_RFlags, C_None)),
  291. {A_LOOPNZ} (Ch: (C_RWECX, C_RFlags, C_None)),
  292. {A_LOOPZ} (Ch: (C_RWECX, C_RFlags, C_None)),
  293. {A_LSL} (Ch: (C_Wop2, C_WFlags, C_None)),
  294. {A_LSS} (Ch: (C_Wop2, C_None, C_None)),
  295. {A_LTR} (Ch: (C_None, C_None, C_None)),
  296. {A_MOV} (Ch: (C_Wop2, C_Rop1, C_None)),
  297. {A_MOVD} (Ch: (C_All, C_None, C_None)), { new }
  298. {A_MOVQ} (Ch: (C_All, C_None, C_None)), { new }
  299. {A_MOVSB} (Ch: (C_All, C_Rop1, C_None)),
  300. {A_MOVSD} (Ch: (C_All, C_None, C_None)), { new }
  301. {A_MOVSW} (Ch: (C_All, C_None, C_None)), { new }
  302. {A_MOVSX} (Ch: (C_Wop2, C_Rop1, C_None)),
  303. {A_MOVZX} (Ch: (C_Wop2, C_Rop1, C_None)),
  304. {A_MUL} (Ch: (C_RWEAX, C_WEDX, C_WFlags)), {handled separately, because modifies more than three things}
  305. {A_NEG} (Ch: (C_Mop1, C_None, C_None)),
  306. {A_NOP} (Ch: (C_None, C_None, C_None)),
  307. {A_NOT} (Ch: (C_Mop1, C_WFlags, C_None)),
  308. {A_OR} (Ch: (C_Mop2, C_WFlags, C_None)),
  309. {A_OUT} (Ch: (C_Rop1, C_Rop2, C_None)),
  310. {A_OUTSB} (Ch: (C_All, C_None, C_None)), { new }
  311. {A_OUTSD} (Ch: (C_All, C_None, C_None)), { new }
  312. {A_OUTSW} (Ch: (C_All, C_None, C_None)), { new }
  313. {A_PACKSSDW} (Ch: (C_All, C_None, C_None)), { new }
  314. {A_PACKSSWB} (Ch: (C_All, C_None, C_None)), { new }
  315. {A_PACKUSWB} (Ch: (C_All, C_None, C_None)), { new }
  316. {A_PADDB} (Ch: (C_All, C_None, C_None)), { new }
  317. {A_PADDD} (Ch: (C_All, C_None, C_None)), { new }
  318. {A_PADDSB} (Ch: (C_All, C_None, C_None)), { new }
  319. {A_PADDSIW} (Ch: (C_All, C_None, C_None)), { new }
  320. {A_PADDSW} (Ch: (C_All, C_None, C_None)), { new }
  321. {A_PADDUSB} (Ch: (C_All, C_None, C_None)), { new }
  322. {A_PADDUSW} (Ch: (C_All, C_None, C_None)), { new }
  323. {A_PADDW} (Ch: (C_All, C_None, C_None)), { new }
  324. {A_PAND} (Ch: (C_All, C_None, C_None)), { new }
  325. {A_PANDN} (Ch: (C_All, C_None, C_None)), { new }
  326. {A_PAVEB} (Ch: (C_All, C_None, C_None)), { new }
  327. {A_PAVGUSB} (Ch: (C_All, C_None, C_None)), { new }
  328. {A_PCMPEQB} (Ch: (C_All, C_None, C_None)), { new }
  329. {A_PCMPEQD} (Ch: (C_All, C_None, C_None)), { new }
  330. {A_PCMPEQW} (Ch: (C_All, C_None, C_None)), { new }
  331. {A_PCMPGTB} (Ch: (C_All, C_None, C_None)), { new }
  332. {A_PCMPGTD} (Ch: (C_All, C_None, C_None)), { new }
  333. {A_PCMPGTW} (Ch: (C_All, C_None, C_None)), { new }
  334. {A_PDISTIB} (Ch: (C_All, C_None, C_None)), { new }
  335. {A_PF2ID} (Ch: (C_All, C_None, C_None)), { new }
  336. {A_PFACC} (Ch: (C_All, C_None, C_None)), { new }
  337. {A_PFADD} (Ch: (C_All, C_None, C_None)), { new }
  338. {A_PFCMPEQ} (Ch: (C_All, C_None, C_None)), { new }
  339. {A_PFCMPGE} (Ch: (C_All, C_None, C_None)), { new }
  340. {A_PFCMPGT} (Ch: (C_All, C_None, C_None)), { new }
  341. {A_PFMAX} (Ch: (C_All, C_None, C_None)), { new }
  342. {A_PFMIN} (Ch: (C_All, C_None, C_None)), { new }
  343. {A_PFMUL} (Ch: (C_All, C_None, C_None)), { new }
  344. {A_PFRCP} (Ch: (C_All, C_None, C_None)), { new }
  345. {A_PFRCPIT1} (Ch: (C_All, C_None, C_None)), { new }
  346. {A_PFRCPIT2} (Ch: (C_All, C_None, C_None)), { new }
  347. {A_PFRSQIT1} (Ch: (C_All, C_None, C_None)), { new }
  348. {A_PFRSQRT} (Ch: (C_All, C_None, C_None)), { new }
  349. {A_PFSUB} (Ch: (C_All, C_None, C_None)), { new }
  350. {A_PFSUBR} (Ch: (C_All, C_None, C_None)), { new }
  351. {A_PI2FD} (Ch: (C_All, C_None, C_None)), { new }
  352. {A_PMACHRIW} (Ch: (C_All, C_None, C_None)), { new }
  353. {A_PMADDWD} (Ch: (C_All, C_None, C_None)), { new }
  354. {A_PMAGW} (Ch: (C_All, C_None, C_None)), { new }
  355. {A_PMULHRIW} (Ch: (C_All, C_None, C_None)), { new }
  356. {A_PMULHRWA} (Ch: (C_All, C_None, C_None)), { new }
  357. {A_PMULHRWC} (Ch: (C_All, C_None, C_None)), { new }
  358. {A_PMULHW} (Ch: (C_All, C_None, C_None)), { new }
  359. {A_PMULLW} (Ch: (C_All, C_None, C_None)), { new }
  360. {A_PMVGEZB} (Ch: (C_All, C_None, C_None)), { new }
  361. {A_PMVLZB} (Ch: (C_All, C_None, C_None)), { new }
  362. {A_PMVNZB} (Ch: (C_All, C_None, C_None)), { new }
  363. {A_PMVZB} (Ch: (C_All, C_None, C_None)), { new }
  364. {A_POP} (Ch: (C_Wop1, C_RWESP, C_None)),
  365. {A_POPA} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
  366. {A_POPAD} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
  367. {A_POPAW} (Ch: (C_All, C_None, C_None)), { new }
  368. {A_POPF} (Ch: (C_RWESP, C_WFlags, C_None)),
  369. {A_POPFD} (Ch: (C_RWESP, C_WFlags, C_None)),
  370. {A_POPFW} (Ch: (C_RWESP, C_WFLAGS, C_None)), { new }
  371. {A_POR} (Ch: (C_All, C_None, C_None)), { new }
  372. {A_PREFETCH} (Ch: (C_All, C_None, C_None)), { new }
  373. {A_PREFETCHW} (Ch: (C_All, C_None, C_None)), { new }
  374. {A_PSLLD} (Ch: (C_All, C_None, C_None)), { new }
  375. {A_PSLLQ} (Ch: (C_All, C_None, C_None)), { new }
  376. {A_PSLLW} (Ch: (C_All, C_None, C_None)), { new }
  377. {A_PSRAD} (Ch: (C_All, C_None, C_None)), { new }
  378. {A_PSRAW} (Ch: (C_All, C_None, C_None)), { new }
  379. {A_PSRLD} (Ch: (C_All, C_None, C_None)), { new }
  380. {A_PSRLQ} (Ch: (C_All, C_None, C_None)), { new }
  381. {A_PSRLW} (Ch: (C_All, C_None, C_None)), { new }
  382. {A_PSUBB} (Ch: (C_All, C_None, C_None)), { new }
  383. {A_PSUBD} (Ch: (C_All, C_None, C_None)), { new }
  384. {A_PSUBSB} (Ch: (C_All, C_None, C_None)), { new }
  385. {A_PSUBSIW} (Ch: (C_All, C_None, C_None)), { new }
  386. {A_PSUBSW} (Ch: (C_All, C_None, C_None)), { new }
  387. {A_PSUBUSB} (Ch: (C_All, C_None, C_None)), { new }
  388. {A_PSUBUSW} (Ch: (C_All, C_None, C_None)), { new }
  389. {A_PSUBW} (Ch: (C_All, C_None, C_None)), { new }
  390. {A_PUNPCKHBW} (Ch: (C_All, C_None, C_None)), { new }
  391. {A_PUNPCKHDQ} (Ch: (C_All, C_None, C_None)), { new }
  392. {A_PUNPCKHWD} (Ch: (C_All, C_None, C_None)), { new }
  393. {A_PUNPCKLBW} (Ch: (C_All, C_None, C_None)), { new }
  394. {A_PUNPCKLDQ} (Ch: (C_All, C_None, C_None)), { new }
  395. {A_PUNPCKLWD} (Ch: (C_All, C_None, C_None)), { new }
  396. {A_PUSH} (Ch: (C_Rop1, C_RWESP, C_None)),
  397. {A_PUSHA} (Ch: (C_All, C_None, C_None)),
  398. {A_PUSHAD} (Ch: (C_All, C_None, C_None)),
  399. {A_PUSHAW} (Ch: (C_All, C_None, C_None)), { new }
  400. {A_PUSHF} (Ch: (C_RWESP, C_RFlags, C_None)),
  401. {A_PUSHFD} (Ch: (C_RWESP, C_RFlags, C_None)),
  402. {A_PUSHFW} (Ch: (C_RWESP, C_RFLAGS, C_None)), { new }
  403. {A_PXOR} (Ch: (C_All, C_None, C_None)), { new }
  404. {A_RCL} (Ch: (C_Mop2, C_Rop1, C_RWFlags)),
  405. {A_RCR} (Ch: (C_Mop2, C_Rop1, C_RWFlags)),
  406. {A_RDMSR} (Ch: (C_WEAX, C_WEDX, C_None)), { new }
  407. {A_RDPMC} (Ch: (C_WEAX, C_WEDX, C_None)), { new }
  408. {A_RDTSC} (Ch: (C_WEAX, C_WEDX, C_None)), { new }
  409. {A_RESB} (Ch: (C_All, C_None, C_None)), { new }
  410. {A_RET} (Ch: (C_All, C_None, C_None)),
  411. {A_RETF} (Ch: (C_All, C_None, C_None)), { new }
  412. {A_RETN} (Ch: (C_All, C_None, C_None)), { new }
  413. {A_ROL} (Ch: (C_Mop2, C_Rop1, C_RWFlags)),
  414. {A_ROR} (Ch: (C_Mop2, C_Rop1, C_RWFlags)),
  415. {A_RSM} (Ch: (C_All, C_None, C_None)), { new }
  416. {A_SAHF} (Ch: (C_WFlags, C_REAX, C_None)),
  417. {A_SAL} (Ch: (C_Mop2, C_Rop1, C_RWFlags)),
  418. {A_SALC} (Ch: (C_WEAX, C_RFLAGS, C_None)), { new }
  419. {A_SAR} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
  420. {A_SBB} (Ch: (C_Mop2, C_Rop1, C_RWFlags)),
  421. {A_SCASB} (Ch: (C_All, C_None, C_None)), { new }
  422. {A_SCASD} (Ch: (C_All, C_None, C_None)), { new }
  423. {A_SCASW} (Ch: (C_All, C_None, C_None)), { new }
  424. {A_SGDT} (Ch: (C_Wop1, C_None, C_None)),
  425. {A_SHL} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
  426. {A_SHLD} (Ch: (C_MOp3, C_RWFlags, C_Rop2)),
  427. {A_SHR} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
  428. {A_SHRD} (Ch: (C_MOp3, C_RWFlags, C_Rop2)),
  429. {A_SIDT} (Ch: (C_Wop1, C_None, C_None)),
  430. {A_SLDT} (Ch: (C_Wop1, C_None, C_None)),
  431. {A_SMI} (Ch: (C_All, C_None, C_None)), { new }
  432. {A_SMSW} (Ch: (C_Wop1, C_None, C_None)),
  433. {A_STC} (Ch: (C_WFlags, C_None, C_None)),
  434. {A_STD} (Ch: (C_SDirFlag, C_None, C_None)),
  435. {A_STI} (Ch: (C_WFlags, C_None, C_None)),
  436. {A_STOSB} (Ch: (C_REAX, C_WMemEDI, C_RWEDI)), { new }
  437. {A_STOSD} (Ch: (C_REAX, C_WMemEDI, C_RWEDI)), { new }
  438. {A_STOSW} (Ch: (C_REAX, C_WMemEDI, C_RWEDI)), { new }
  439. {A_STR} (Ch: (C_Wop1, C_None, C_None)),
  440. {A_SUB} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
  441. {A_TEST} (Ch: (C_WFlags, C_Rop1, C_Rop2)),
  442. {A_UMOV} (Ch: (C_All, C_None, C_None)), { new }
  443. {A_VERR} (Ch: (C_WFlags, C_None, C_None)),
  444. {A_VERW} (Ch: (C_WFlags, C_None, C_None)),
  445. {A_WAIT} (Ch: (C_None, C_None, C_None)),
  446. {A_WBINVD} (Ch: (C_None, C_None, C_None)), { new }
  447. {A_WRMSR} (Ch: (C_All, C_None, C_None)), { new }
  448. {A_XADD} (Ch: (C_All, C_None, C_None)), { new }
  449. {A_XBTS} (Ch: (C_All, C_None, C_None)), { new }
  450. {A_XCHG} (Ch: (C_RWop1, C_RWop2, C_None)), {(might be) handled seperately}
  451. {A_XLAT} (Ch: (C_WEAX, C_REBX, C_None)),
  452. {A_XLATB} (Ch: (C_WEAX, C_REBX, C_None)),
  453. {A_XOR} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
  454. {A_CMOV} (Ch: (C_ROp1, C_WOp2, C_RFLAGS)), { new }
  455. {A_J} (Ch: (C_None, C_None, C_None)), { new }
  456. {A_SET} (Ch: (C_WEAX, C_RFLAGS, C_None)) { new }
  457. );
  458. Function RegMaxSize(Reg: TRegister): TRegister;
  459. Function RegsSameSize(Reg1, Reg2: TRegister): Boolean;
  460. Function IsLoadInstr(p: pai): Boolean;
  461. Implementation
  462. {************************ TCondRegs ************************}
  463. Constructor TCondRegs.init;
  464. Begin
  465. FillChar(Flags, SizeOf(Flags), Byte(F_Unknown))
  466. End;
  467. Procedure TCondRegs.InitFlag(f: TFlag);
  468. Begin
  469. Flags[f] := F_Unknown
  470. End;
  471. Procedure TCondRegs.SetFlag(f: TFlag);
  472. Begin
  473. Flags[f] := F_Set
  474. End;
  475. Procedure TCondRegs.ClearFlag(f: TFlag);
  476. Begin
  477. Flags[f] : =F_Clear
  478. End;
  479. Function GetFlag(f: TFlag): TFlagContents;
  480. Begin
  481. GetFlag := Flags[f]
  482. End;
  483. {*************************************************************}
  484. Function RegMaxSize(Reg: TRegister): TRegister;
  485. {Returns the 32 bit component of Reg if it exists, otherwise Reg is returned}
  486. Begin
  487. RegMaxSize := Reg;
  488. If (Reg >= R_AX)
  489. Then
  490. If (Reg <= R_DI)
  491. Then RegMaxSize := Reg16ToReg32(Reg)
  492. Else
  493. If (Reg <= R_BL)
  494. Then RegMaxSize := Reg8toReg32(Reg);
  495. End;
  496. Function RegsSameSize(Reg1, Reg2: TRegister): Boolean;
  497. {returns true if Reg1 and Reg2 are of the same size (so if they're both
  498. 8bit, 16bit or 32bit)}
  499. Begin
  500. If (Reg1 <= R_EDI)
  501. Then RegsSameSize := (Reg2 <= R_EDI)
  502. Else
  503. If (Reg1 <= R_DI)
  504. Then RegsSameSize := (Reg2 in [R_AX..R_DI])
  505. Else
  506. If (Reg1 <= R_BL)
  507. Then RegsSameSize := (Reg2 in [R_AL..R_BL])
  508. Else RegsSameSize := False
  509. End;
  510. Function IsLoadInstr(p: pai): Boolean;
  511. { returns true if p is a load instruction (loads value from memory in a }
  512. { register) }
  513. Begin
  514. IsLoadInstr :=
  515. (p^.typ = ait_instruction) and
  516. ((PInstr(p)^.OpCode = A_MOV) or
  517. (PInstr(p)^.OpCode = A_MOVZX) or
  518. (PInstr(p)^.OpCode = A_MOVSX)) And
  519. (PInstr(p)^.oper[LoadSrc].typ = top_ref));
  520. End;
  521. Function IsStoreInstr(p: pai): Boolean;
  522. { returns true if p is a load instruction (loads value from memory in a }
  523. { register) }
  524. Begin
  525. IsLoadInstr :=
  526. (p^.typ = ait_instruction) and
  527. ((PInstr(p)^.OpCode = A_MOV) or
  528. (PInstr(p)^.OpCode = A_MOVZX) or
  529. (PInstr(p)^.OpCode = A_MOVSX)) And
  530. (PInstr(p)^.oper[StoreDst].typ = top_ref));
  531. End;
  532. Function TCh2Reg(Ch: TChange): TRegister;
  533. {converts a TChange variable to a TRegister}
  534. Begin
  535. If (Ch <= C_REDI) Then
  536. TCh2Reg := TRegister(Byte(Ch))
  537. Else
  538. If (Ch <= C_WEDI) Then
  539. TCh2Reg := TRegister(Byte(Ch) - Byte(C_REDI))
  540. Else
  541. If (Ch <= C_RWEDI) Then
  542. TCh2Reg := TRegister(Byte(Ch) - Byte(C_WEDI))
  543. Else InternalError($db)
  544. End;
  545. Function RegReadByInstr(Reg: TRegister; p: Pai);
  546. Begin
  547. RegReadByInstr := False;
  548. If (p^.typ = ait_instruction) Then
  549. Case p^.opcode of
  550. A_IMUL:
  551. With PInstr(p)^ Do
  552. RegReadByInstr :=
  553. RegInOp(Reg,op[0]) or
  554. RegInOp(Reg,op[1]) or
  555. ((op[1]^.typ = top_none) and
  556. (op[2]^.typ = top_none) and
  557. (reg in [R_EAX,R_EDX]))
  558. A_IDIV, A_MUL:
  559. RegReadByInstr :=
  560. RegInOp(Reg,op[0]) or
  561. (Reg = R_EAX) or
  562. ((Reg = R_EDX) and
  563. (p^.opcode = A_IDIV) and
  564. (p^.size = S_L));
  565. End.