parser.cpp 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214
  1. /****************************************************************************
  2. * dcc project procedure list builder
  3. * (C) Cristina Cifuentes, Mike van Emmerik, Jeff Ledermann
  4. ****************************************************************************/
  5. #include <string.h>
  6. #include <stdlib.h> /* For exit() */
  7. #include <sstream>
  8. #include <stdio.h>
  9. #include <algorithm>
  10. #include "dcc.h"
  11. using namespace std;
  12. static void FollowCtrl (Function * pProc, CALL_GRAPH * pcallGraph, STATE * pstate);
  13. static boolT process_JMP (ICODE * pIcode, STATE * pstate,
  14. CALL_GRAPH * pcallGraph);
  15. static boolT process_CALL(ICODE * pIcode, CALL_GRAPH * pcallGraph,
  16. STATE * pstate);
  17. static void process_operands(ICODE * pIcode, Function * pProc, STATE * pstate,
  18. Int ix);
  19. static void setBits(int16 type, dword start, dword len);
  20. static SYM * updateGlobSym(dword operand, Int size, word duFlag);
  21. static void process_MOV(ICODE * pIcode, STATE * pstate);
  22. static SYM * lookupAddr (LLOperand *pm, STATE * pstate, Int size, word duFlag);
  23. void interactDis(Function * initProc, Int ic);
  24. static dword SynthLab;
  25. /* Parses the program, builds the call graph, and returns the list of
  26. * procedures found */
  27. void parse (CALL_GRAPH * *pcallGraph)
  28. {
  29. STATE state;
  30. /* Set initial state */
  31. memset(&state, 0, sizeof(STATE));
  32. state.setState(rES, 0); /* PSP segment */
  33. state.setState(rDS, 0);
  34. state.setState(rCS, prog.initCS);
  35. state.setState(rSS, prog.initSS);
  36. state.setState(rSP, prog.initSP);
  37. state.IP = ((dword)prog.initCS << 4) + prog.initIP;
  38. SynthLab = SYNTHESIZED_MIN;
  39. // default-construct a Function object !
  40. pProcList.push_back(Function::Create());
  41. /* Check for special settings of initial state, based on idioms of the
  42. startup code */
  43. state.checkStartup();
  44. Function &start_proc(pProcList.front());
  45. /* Make a struct for the initial procedure */
  46. if (prog.offMain != -1)
  47. {
  48. /* We know where main() is. Start the flow of control from there */
  49. start_proc.procEntry = prog.offMain;
  50. /* In medium and large models, the segment of main may (will?) not be
  51. the same as the initial CS segment (of the startup code) */
  52. state.setState(rCS, prog.segMain);
  53. start_proc.name = "main";
  54. state.IP = prog.offMain;
  55. }
  56. else
  57. {
  58. /* Create initial procedure at program start address */
  59. start_proc.name="start";
  60. start_proc.procEntry = (dword)state.IP;
  61. }
  62. /* The state info is for the first procedure */
  63. start_proc.state = state;
  64. /* Set up call graph initial node */
  65. *pcallGraph = new CALL_GRAPH;
  66. (*pcallGraph)->proc = pProcList.begin();
  67. /* This proc needs to be called to set things up for LibCheck(), which
  68. checks a proc to see if it is a know C (etc) library */
  69. SetupLibCheck();
  70. /* Recursively build entire procedure list */
  71. pProcList.front().FollowCtrl (*pcallGraph, &state);
  72. /* This proc needs to be called to clean things up from SetupLibCheck() */
  73. CleanupLibCheck();
  74. }
  75. /* Updates the type of the symbol in the symbol table. The size is updated
  76. * if necessary (0 means no update necessary). */
  77. static void updateSymType (dword symbol, hlType symType, Int size)
  78. { Int i;
  79. for (i = 0; i < symtab.size(); i++)
  80. if (symtab[i].label == symbol)
  81. {
  82. symtab[i].type = symType;
  83. if (size != 0)
  84. symtab[i].size = size;
  85. break;
  86. }
  87. }
  88. /* Returns the size of the string pointed by sym and delimited by delim.
  89. * Size includes delimiter. */
  90. Int strSize (byte *sym, char delim)
  91. {
  92. Int i;
  93. for (i = 0; *sym++ != delim; i++)
  94. ;
  95. return (i+1);
  96. }
  97. Function *fakeproc=Function::Create(0,0,"fake");
  98. /* FollowCtrl - Given an initial procedure, state information and symbol table
  99. * builds a list of procedures reachable from the initial procedure
  100. * using a depth first search. */
  101. void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
  102. {
  103. ICODE _Icode, *pIcode; /* This gets copied to pProc->Icode[] later */
  104. ICODE eIcode; /* extra icodes for iDIV, iIDIV, iXCHG */
  105. SYM * psym;
  106. dword offset;
  107. eErrorId err;
  108. boolT done = FALSE;
  109. dword lab;
  110. if (name.find("chkstk") != string::npos)
  111. {
  112. // Danger! Dcc will likely fall over in this code.
  113. // So we act as though we have done with this proc
  114. // pProc->flg &= ~TERMINATES; // Not sure about this
  115. done = TRUE;
  116. // And mark it as a library function, so structure() won't choke on it
  117. flg |= PROC_ISLIB;
  118. return;
  119. }
  120. if (option.VeryVerbose)
  121. {
  122. printf("Parsing proc %s at %lX\n", name.c_str(), pstate->IP);
  123. }
  124. while (! done && ! (err = scan(pstate->IP, &_Icode)))
  125. {
  126. pstate->IP += (dword)_Icode.ic.ll.numBytes;
  127. setBits(BM_CODE, _Icode.ic.ll.label, (dword)_Icode.ic.ll.numBytes);
  128. process_operands(&_Icode,pstate);
  129. /* Keep track of interesting instruction flags in procedure */
  130. flg |= (_Icode.ic.ll.flg & (NOT_HLL | FLOAT_OP));
  131. /* Check if this instruction has already been parsed */
  132. if (Icode.labelSrch(_Icode.ic.ll.label, lab))
  133. { /* Synthetic jump */
  134. _Icode.type = LOW_LEVEL;
  135. _Icode.ic.ll.opcode = iJMP;
  136. _Icode.ic.ll.flg = I | SYNTHETIC | NO_OPS;
  137. _Icode.ic.ll.src.SetImmediateOp(Icode[lab].GetLlLabel());
  138. _Icode.ic.ll.label = SynthLab++;
  139. }
  140. /* Copy Icode to Proc */
  141. if ((_Icode.ic.ll.opcode == iDIV) || (_Icode.ic.ll.opcode == iIDIV))
  142. {
  143. /* MOV rTMP, reg */
  144. memset (&eIcode, 0, sizeof (ICODE));
  145. eIcode.type = LOW_LEVEL;
  146. eIcode.ic.ll.opcode = iMOV;
  147. eIcode.ic.ll.dst.regi = rTMP;
  148. if (_Icode.ic.ll.flg & B)
  149. {
  150. eIcode.ic.ll.flg |= B;
  151. eIcode.ic.ll.src.regi = rAX;
  152. eIcode.setRegDU( rAX, eUSE);
  153. }
  154. else /* implicit dx:ax */
  155. {
  156. eIcode.ic.ll.flg |= IM_SRC;
  157. eIcode.setRegDU( rAX, eUSE);
  158. eIcode.setRegDU( rDX, eUSE);
  159. }
  160. eIcode.setRegDU( rTMP, eDEF);
  161. eIcode.ic.ll.flg |= SYNTHETIC;
  162. /* eIcode.ic.ll.label = SynthLab++; */
  163. eIcode.ic.ll.label = _Icode.ic.ll.label;
  164. Icode.addIcode(&eIcode);
  165. /* iDIV, iIDIV */
  166. Icode.addIcode(&_Icode);
  167. /* iMOD */
  168. memset (&eIcode, 0, sizeof (ICODE));
  169. eIcode.type = LOW_LEVEL;
  170. eIcode.ic.ll.opcode = iMOD;
  171. eIcode.ic.ll.src = _Icode.ic.ll.src;
  172. eIcode.du = _Icode.du;
  173. eIcode.ic.ll.flg = (_Icode.ic.ll.flg | SYNTHETIC);
  174. eIcode.ic.ll.label = SynthLab++;
  175. pIcode = Icode.addIcode(&eIcode);
  176. }
  177. else if (_Icode.ic.ll.opcode == iXCHG)
  178. {
  179. /* MOV rTMP, regDst */
  180. memset (&eIcode, 0, sizeof (ICODE));
  181. eIcode.type = LOW_LEVEL;
  182. eIcode.ic.ll.opcode = iMOV;
  183. eIcode.ic.ll.dst.regi = rTMP;
  184. eIcode.ic.ll.src.regi = _Icode.ic.ll.dst.regi;
  185. eIcode.setRegDU( rTMP, eDEF);
  186. eIcode.setRegDU( eIcode.ic.ll.src.regi, eUSE);
  187. eIcode.ic.ll.flg |= SYNTHETIC;
  188. /* eIcode.ic.ll.label = SynthLab++; */
  189. eIcode.ic.ll.label = _Icode.ic.ll.label;
  190. Icode.addIcode(&eIcode);
  191. /* MOV regDst, regSrc */
  192. _Icode.ic.ll.opcode = iMOV;
  193. _Icode.ic.ll.flg |= SYNTHETIC;
  194. /* Icode.ic.ll.label = SynthLab++; */
  195. Icode.addIcode(&_Icode);
  196. _Icode.ic.ll.opcode = iXCHG; /* for next case */
  197. /* MOV regSrc, rTMP */
  198. memset (&eIcode, 0, sizeof (ICODE));
  199. eIcode.type = LOW_LEVEL;
  200. eIcode.ic.ll.opcode = iMOV;
  201. eIcode.ic.ll.dst.regi = _Icode.ic.ll.src.regi;
  202. eIcode.ic.ll.src.regi = rTMP;
  203. eIcode.setRegDU( eIcode.ic.ll.dst.regi, eDEF);
  204. eIcode.setRegDU( rTMP, eUSE);
  205. eIcode.ic.ll.flg |= SYNTHETIC;
  206. eIcode.ic.ll.label = SynthLab++;
  207. pIcode = Icode.addIcode(&eIcode);
  208. }
  209. else
  210. pIcode = Icode.addIcode(&_Icode);
  211. switch (_Icode.ic.ll.opcode) {
  212. /*** Conditional jumps ***/
  213. case iLOOP: case iLOOPE: case iLOOPNE:
  214. case iJB: case iJBE: case iJAE: case iJA:
  215. case iJL: case iJLE: case iJGE: case iJG:
  216. case iJE: case iJNE: case iJS: case iJNS:
  217. case iJO: case iJNO: case iJP: case iJNP:
  218. case iJCXZ:
  219. { STATE StCopy;
  220. int ip = Icode.size()-1; /* Index of this jump */
  221. ICODE &prev(Icode.back()); /* Previous icode */
  222. boolT fBranch = FALSE;
  223. pstate->JCond.regi = 0;
  224. /* This sets up range check for indexed JMPs hopefully
  225. * Handles JA/JAE for fall through and JB/JBE on branch
  226. */
  227. if (ip > 0 && prev.ic.ll.opcode == iCMP && (prev.ic.ll.flg & I))
  228. {
  229. pstate->JCond.immed = (int16)prev.ic.ll.src.op();
  230. if (_Icode.ic.ll.opcode == iJA || _Icode.ic.ll.opcode == iJBE)
  231. pstate->JCond.immed++;
  232. if (_Icode.ic.ll.opcode == iJAE || _Icode.ic.ll.opcode == iJA)
  233. pstate->JCond.regi = prev.ic.ll.dst.regi;
  234. fBranch = (boolT)
  235. (_Icode.ic.ll.opcode == iJB || _Icode.ic.ll.opcode == iJBE);
  236. }
  237. StCopy = *pstate;
  238. //memcpy(&StCopy, pstate, sizeof(STATE));
  239. /* Straight line code */
  240. this->FollowCtrl (pcallGraph, &StCopy); // recurrent ?
  241. if (fBranch) /* Do branching code */
  242. {
  243. pstate->JCond.regi = prev.ic.ll.dst.regi;
  244. }
  245. /* Next icode. Note: not the same as GetLastIcode() because of the call
  246. to FollowCtrl() */
  247. pIcode = Icode.GetIcode(ip);
  248. } /* Fall through to do the jump path */
  249. /*** Jumps ***/
  250. case iJMP:
  251. case iJMPF: /* Returns TRUE if we've run into a loop */
  252. done = process_JMP (pIcode, pstate, pcallGraph);
  253. break;
  254. /*** Calls ***/
  255. case iCALL:
  256. case iCALLF:
  257. done = process_CALL (pIcode, pcallGraph, pstate);
  258. break;
  259. /*** Returns ***/
  260. case iRET:
  261. case iRETF:
  262. this->flg |= (_Icode.ic.ll.opcode == iRET)? PROC_NEAR:PROC_FAR;
  263. /* Fall through */
  264. case iIRET:
  265. this->flg &= ~TERMINATES;
  266. done = TRUE;
  267. break;
  268. case iINT:
  269. if (_Icode.ic.ll.src.op() == 0x21 && pstate->f[rAH])
  270. {
  271. Int funcNum = pstate->r[rAH];
  272. Int operand;
  273. Int size;
  274. /* Save function number */
  275. Icode.back().ic.ll.dst.off = (int16)funcNum;
  276. //Icode.GetIcode(Icode.GetNumIcodes() - 1)->
  277. /* Program termination: int21h, fn 00h, 31h, 4Ch */
  278. done = (boolT)(funcNum == 0x00 || funcNum == 0x31 ||
  279. funcNum == 0x4C);
  280. /* String functions: int21h, fn 09h */
  281. if (pstate->f[rDX]) /* offset goes into DX */
  282. if (funcNum == 0x09)
  283. {
  284. operand = ((dword)(word)pstate->r[rDS]<<4) +
  285. (dword)(word)pstate->r[rDX];
  286. size = prog.fCOM ?
  287. strSize (&prog.Image[operand], '$') :
  288. strSize (&prog.Image[operand + 0x100], '$');
  289. updateSymType (operand, TYPE_STR, size);
  290. }
  291. }
  292. else if ((_Icode.ic.ll.src.op() == 0x2F) && (pstate->f[rAH]))
  293. {
  294. Icode.back().ic.ll.dst.off = pstate->r[rAH];
  295. }
  296. else /* Program termination: int20h, int27h */
  297. done = (boolT)(_Icode.ic.ll.src.op() == 0x20 ||
  298. _Icode.ic.ll.src.op() == 0x27);
  299. if (done)
  300. pIcode->ic.ll.flg |= TERMINATES;
  301. break;
  302. case iMOV:
  303. process_MOV(pIcode, pstate);
  304. break;
  305. /* case iXCHG:
  306. process_MOV (pIcode, pstate);
  307. break; **** HERE ***/
  308. case iSHL:
  309. if (pstate->JCond.regi == _Icode.ic.ll.dst.regi)
  310. if ((_Icode.ic.ll.flg & I) && _Icode.ic.ll.src.op() == 1)
  311. pstate->JCond.immed *= 2;
  312. else
  313. pstate->JCond.regi = 0;
  314. break;
  315. case iLEA:
  316. if (_Icode.ic.ll.src.regi == 0) /* direct mem offset */
  317. pstate->setState( _Icode.ic.ll.dst.regi, _Icode.ic.ll.src.off);
  318. break;
  319. case iLDS: case iLES:
  320. if ((psym = lookupAddr(&_Icode.ic.ll.src, pstate, 4, eDuVal::USE))
  321. /* && (Icode.ic.ll.flg & SEG_IMMED) */ ) {
  322. offset = LH(&prog.Image[psym->label]);
  323. pstate->setState( (_Icode.ic.ll.opcode == iLDS)? rDS: rES,
  324. LH(&prog.Image[psym->label + 2]));
  325. pstate->setState( _Icode.ic.ll.dst.regi, (int16)offset);
  326. psym->type = TYPE_PTR;
  327. }
  328. break;
  329. }
  330. }
  331. if (err) {
  332. this->flg &= ~TERMINATES;
  333. if (err == INVALID_386OP || err == INVALID_OPCODE)
  334. {
  335. fatalError(err, prog.Image[_Icode.ic.ll.label], _Icode.ic.ll.label);
  336. this->flg |= PROC_BADINST;
  337. }
  338. else if (err == IP_OUT_OF_RANGE)
  339. fatalError (err, _Icode.ic.ll.label);
  340. else
  341. reportError(err, _Icode.ic.ll.label);
  342. }
  343. }
  344. /* process_JMP - Handles JMPs, returns TRUE if we should end recursion */
  345. boolT Function::process_JMP (ICODE * pIcode, STATE *pstate, CALL_GRAPH * pcallGraph)
  346. {
  347. static byte i2r[4] = {rSI, rDI, rBP, rBX};
  348. ICODE _Icode;
  349. dword cs, offTable, endTable;
  350. dword i, k, seg, target;
  351. dword tmp;
  352. if (pIcode->ic.ll.flg & I)
  353. {
  354. if (pIcode->ic.ll.opcode == iJMPF)
  355. pstate->setState( rCS, LH(prog.Image + pIcode->ic.ll.label + 3));
  356. i = pstate->IP = pIcode->ic.ll.src.op();
  357. if ((long)i < 0)
  358. {
  359. exit(1);
  360. }
  361. /* Return TRUE if jump target is already parsed */
  362. return Icode.labelSrch(i, tmp);
  363. }
  364. /* We've got an indirect JMP - look for switch() stmt. idiom of the form
  365. * JMP word ptr word_offset[rBX | rSI | rDI] */
  366. seg = (pIcode->ic.ll.src.seg)? pIcode->ic.ll.src.seg: rDS;
  367. /* Ensure we have a word offset & valid seg */
  368. if (pIcode->ic.ll.opcode == iJMP && (pIcode->ic.ll.flg & WORD_OFF) &&
  369. pstate->f[seg] &&
  370. (pIcode->ic.ll.src.regi == INDEXBASE + 4 ||
  371. pIcode->ic.ll.src.regi == INDEXBASE + 5 || /* Idx reg. BX, SI, DI */
  372. pIcode->ic.ll.src.regi == INDEXBASE + 7))
  373. {
  374. offTable = ((dword)(word)pstate->r[seg] << 4) + pIcode->ic.ll.src.off;
  375. /* Firstly look for a leading range check of the form:-
  376. * CMP {BX | SI | DI}, immed
  377. * JA | JAE | JB | JBE
  378. * This is stored in the current state as if we had just
  379. * followed a JBE branch (i.e. [reg] lies between 0 - immed).
  380. */
  381. if (pstate->JCond.regi == i2r[pIcode->ic.ll.src.regi-(INDEXBASE+4)])
  382. endTable = offTable + pstate->JCond.immed;
  383. else
  384. endTable = (dword)prog.cbImage;
  385. /* Search for first byte flagged after start of table */
  386. for (i = offTable; i <= endTable; i++)
  387. if (BITMAP(i, BM_CODE | BM_DATA))
  388. break;
  389. endTable = i & ~1; /* Max. possible table size */
  390. /* Now do some heuristic pruning. Look for ptrs. into the table
  391. * and for addresses that don't appear to point to valid code.
  392. */
  393. cs = (dword)(word)pstate->r[rCS] << 4;
  394. for (i = offTable; i < endTable; i += 2)
  395. {
  396. target = cs + LH(&prog.Image[i]);
  397. if (target < endTable && target >= offTable)
  398. endTable = target;
  399. else if (target >= (dword)prog.cbImage)
  400. endTable = i;
  401. }
  402. for (i = offTable; i < endTable; i += 2)
  403. {
  404. target = cs + LH(&prog.Image[i]);
  405. /* Be wary of 00 00 as code - it's probably data */
  406. if (! (prog.Image[target] || prog.Image[target+1]) ||
  407. scan(target, &_Icode))
  408. endTable = i;
  409. }
  410. /* Now for each entry in the table take a copy of the current
  411. * state and recursively call FollowCtrl(). */
  412. if (offTable < endTable)
  413. {
  414. STATE StCopy;
  415. Int ip;
  416. dword *psw;
  417. setBits(BM_DATA, offTable, endTable - offTable);
  418. pIcode->ic.ll.flg |= SWITCH;
  419. pIcode->ic.ll.caseTbl.numEntries = (endTable - offTable) / 2;
  420. psw = (dword*)allocMem(pIcode->ic.ll.caseTbl.numEntries*sizeof(dword));
  421. pIcode->ic.ll.caseTbl.entries = psw;
  422. for (i = offTable, k = 0; i < endTable; i += 2)
  423. {
  424. memcpy(&StCopy, pstate, sizeof(STATE));
  425. StCopy.IP = cs + LH(&prog.Image[i]);
  426. ip = Icode.size();
  427. FollowCtrl (pcallGraph, &StCopy);
  428. Icode.GetIcode(ip)->ic.ll.caseTbl.numEntries = k++;
  429. Icode.GetIcode(ip)->ic.ll.flg |= CASE;
  430. *psw++ = Icode[ip].GetLlLabel();
  431. }
  432. return TRUE;
  433. }
  434. }
  435. /* Can't do anything with this jump */
  436. flg |= PROC_IJMP;
  437. flg &= ~TERMINATES;
  438. interactDis(this, this->Icode.size()-1);
  439. return TRUE;
  440. }
  441. /* Process procedure call.
  442. * Note: We assume that CALL's will return unless there is good evidence to
  443. * the contrary - thus we return FALSE unless all paths in the called
  444. * procedure end in DOS exits. This is reasonable since C procedures
  445. * will always include the epilogue after the call anyway and it's to
  446. * be assumed that if an assembler program contains a CALL that the
  447. * programmer expected it to come back - otherwise surely a JMP would
  448. * have been used. */
  449. boolT Function::process_CALL (ICODE * pIcode, CALL_GRAPH * pcallGraph, STATE *pstate)
  450. {
  451. Int ip = Icode.size() - 1;
  452. STATE localState; /* Local copy of the machine state */
  453. dword off;
  454. boolT indirect;
  455. /* For Indirect Calls, find the function address */
  456. indirect = FALSE;
  457. //pIcode->ic.ll.immed.proc.proc=fakeproc;
  458. if ( not pIcode->isLlFlag(I) )
  459. {
  460. /* Not immediate, i.e. indirect call */
  461. if (pIcode->ic.ll.dst.regi && (!option.Calls))
  462. {
  463. /* We have not set the brave option to attempt to follow
  464. the execution path through register indirect calls.
  465. So we just exit this function, and ignore the call.
  466. We probably should not have parsed this deep, anyway.
  467. */
  468. return FALSE;
  469. }
  470. /* Offset into program image is seg:off of read input */
  471. /* Note: this assumes that the pointer itself is at
  472. es:0 where es:0 is the start of the image. This is
  473. usually wrong! Consider also CALL [BP+0E] in which the
  474. segment for the pointer is in SS! - Mike */
  475. off = (dword)(word)pIcode->ic.ll.dst.off +
  476. ((dword)(word)pIcode->ic.ll.dst.segValue << 4);
  477. /* Address of function is given by 4 (CALLF) or 2 (CALL) bytes at
  478. * previous offset into the program image */
  479. dword tgtAddr=0;
  480. if (pIcode->ic.ll.opcode == iCALLF)
  481. tgtAddr= LH(&prog.Image[off]) + (dword)(LH(&prog.Image[off+2])) << 4;
  482. else
  483. tgtAddr= LH(&prog.Image[off]) + (dword)(word)state.r[rCS] << 4;
  484. pIcode->ic.ll.src.SetImmediateOp( tgtAddr );
  485. pIcode->ic.ll.flg |= I;
  486. indirect = TRUE;
  487. }
  488. /* Process CALL. Function address is located in pIcode->ic.ll.immed.op */
  489. if (pIcode->ic.ll.flg & I)
  490. {
  491. /* Search procedure list for one with appropriate entry point */
  492. ilFunction iter= std::find_if(pProcList.begin(),pProcList.end(),
  493. [pIcode](const Function &f) ->
  494. bool { return f.procEntry==pIcode->ic.ll.src.op(); });
  495. /* Create a new procedure node and save copy of the state */
  496. if (iter==pProcList.end())
  497. {
  498. pProcList.push_back(Function::Create());
  499. Function &x(pProcList.back());
  500. iter = (++pProcList.rbegin()).base();
  501. x.procEntry = pIcode->ic.ll.src.op();
  502. LibCheck(x);
  503. if (x.flg & PROC_ISLIB)
  504. {
  505. /* A library function. No need to do any more to it */
  506. pcallGraph->insertCallGraph (this, iter);
  507. iter = (++pProcList.rbegin()).base();
  508. Icode.GetIcode(ip)->ic.ll.src.proc.proc = &x;
  509. return false;
  510. }
  511. if (indirect)
  512. x.flg |= PROC_ICALL;
  513. if (x.name.empty()) /* Don't overwrite existing name */
  514. {
  515. ostringstream os;
  516. os<<"proc_"<< ++prog.cProcs;
  517. x.name = os.str();
  518. }
  519. x.depth = x.depth + 1;
  520. x.flg |= TERMINATES;
  521. /* Save machine state in localState, load up IP and CS.*/
  522. localState = *pstate;
  523. pstate->IP = pIcode->ic.ll.src.op();
  524. if (pIcode->ic.ll.opcode == iCALLF)
  525. pstate->setState( rCS, LH(prog.Image + pIcode->ic.ll.label + 3));
  526. x.state = *pstate;
  527. /* Insert new procedure in call graph */
  528. pcallGraph->insertCallGraph (this, iter);
  529. /* Process new procedure */
  530. x.FollowCtrl (pcallGraph, pstate);
  531. /* Restore segment registers & IP from localState */
  532. pstate->IP = localState.IP;
  533. pstate->setState( rCS, localState.r[rCS]);
  534. pstate->setState( rDS, localState.r[rDS]);
  535. pstate->setState( rES, localState.r[rES]);
  536. pstate->setState( rSS, localState.r[rSS]);
  537. }
  538. else
  539. pcallGraph->insertCallGraph (this, iter);
  540. Icode[ip].ic.ll.src.proc.proc = &(*iter); // ^ target proc
  541. /* return ((p->flg & TERMINATES) != 0); */
  542. return FALSE;
  543. }
  544. return FALSE; // Cristina, please check!!
  545. }
  546. /* process_MOV - Handles state changes due to simple assignments */
  547. static void process_MOV(ICODE * pIcode, STATE * pstate)
  548. {
  549. SYM * psym, *psym2; /* Pointer to symbol in global symbol table */
  550. byte dstReg = pIcode->ic.ll.dst.regi;
  551. byte srcReg = pIcode->ic.ll.src.regi;
  552. if (dstReg > 0 && dstReg < INDEXBASE)
  553. {
  554. if (pIcode->ic.ll.flg & I)
  555. pstate->setState( dstReg, (int16)pIcode->ic.ll.src.op());
  556. else if (srcReg == 0) /* direct memory offset */
  557. {
  558. psym = lookupAddr(&pIcode->ic.ll.src, pstate, 2, eDuVal::USE);
  559. if (psym && ((psym->flg & SEG_IMMED) || psym->duVal.val))
  560. pstate->setState( dstReg, LH(&prog.Image[psym->label]));
  561. }
  562. else if (srcReg < INDEXBASE && pstate->f[srcReg]) /* reg */
  563. {
  564. pstate->setState( dstReg, pstate->r[srcReg]);
  565. /* Follow moves of the possible index register */
  566. if (pstate->JCond.regi == srcReg)
  567. pstate->JCond.regi = dstReg;
  568. }
  569. }
  570. else if (dstReg == 0) { /* direct memory offset */
  571. psym = lookupAddr (&pIcode->ic.ll.dst, pstate, 2, eDEF);
  572. if (psym && ! (psym->duVal.val)) /* no initial value yet */
  573. if (pIcode->ic.ll.flg & I) { /* immediate */
  574. prog.Image[psym->label] = (byte)pIcode->ic.ll.src.op();
  575. prog.Image[psym->label+1] = (byte)(pIcode->ic.ll.src.op()>>8);
  576. psym->duVal.val = 1;
  577. }
  578. else if (srcReg == 0) { /* direct mem offset */
  579. psym2 = lookupAddr (&pIcode->ic.ll.src, pstate, 2, eDuVal::USE);
  580. if (psym2 && ((psym->flg & SEG_IMMED) || (psym->duVal.val)))
  581. {
  582. prog.Image[psym->label] = (byte)prog.Image[psym2->label];
  583. prog.Image[psym->label+1] =
  584. (byte)(prog.Image[psym2->label+1] >> 8);
  585. psym->duVal.val=1;
  586. }
  587. }
  588. else if (srcReg < INDEXBASE && pstate->f[srcReg]) /* reg */
  589. {
  590. prog.Image[psym->label] = (byte)pstate->r[srcReg];
  591. prog.Image[psym->label+1] = (byte)(pstate->r[srcReg] >> 8);
  592. psym->duVal.val;
  593. }
  594. }
  595. }
  596. /* Type of the symbol according to the number of bytes it uses */
  597. static hlType cbType[] = {TYPE_UNKNOWN, TYPE_BYTE_UNSIGN, TYPE_WORD_SIGN,
  598. TYPE_UNKNOWN, TYPE_LONG_SIGN};
  599. /* Creates an entry in the global symbol table (symtab) if the variable
  600. * is not there yet. If it is part of the symtab, the size of the variable
  601. * is checked and updated if the old size was less than the new size (ie.
  602. * the maximum size is always saved). */
  603. static SYM * updateGlobSym (dword operand, Int size, word duFlag)
  604. {
  605. Int i;
  606. /* Check for symbol in symbol table */
  607. for (i = 0; i < symtab.size(); i++)
  608. if (symtab[i].label == operand)
  609. {
  610. if (symtab[i].size < size)
  611. symtab[i].size = size;
  612. break;
  613. }
  614. /* New symbol, not in symbol table */
  615. if (i == symtab.size())
  616. {
  617. SYM v;
  618. sprintf (v.name, "var%05lX", operand);
  619. v.label = operand;
  620. v.size = size;
  621. v.type = cbType[size];
  622. if (duFlag == eDuVal::USE) /* must already have init value */
  623. {
  624. v.duVal.use =1; // USEVAL;
  625. v.duVal.val =1;
  626. }
  627. else
  628. {
  629. v.duVal.setFlags(duFlag);
  630. }
  631. symtab.push_back(v);
  632. }
  633. return (&symtab[i]);
  634. }
  635. /* Updates the offset entry to the stack frame table (arguments),
  636. * and returns a pointer to such entry. */
  637. static void updateFrameOff (STKFRAME * ps, int16 off, Int size, word duFlag)
  638. {
  639. Int i;
  640. /* Check for symbol in stack frame table */
  641. for (i = 0; i < ps->sym.size(); i++)
  642. {
  643. if (ps->sym[i].off == off)
  644. {
  645. if (ps->sym[i].size < size)
  646. {
  647. ps->sym[i].size = size;
  648. }
  649. break;
  650. }
  651. }
  652. /* New symbol, not in table */
  653. if (i == ps->sym.size())
  654. {
  655. STKSYM new_sym;
  656. sprintf (new_sym.name, "arg%ld", i);
  657. new_sym.off = off;
  658. new_sym.size = size;
  659. new_sym.type = cbType[size];
  660. if (duFlag == eDuVal::USE) /* must already have init value */
  661. {
  662. new_sym.duVal.use=1;
  663. //new_sym.duVal.val=1;
  664. }
  665. else
  666. {
  667. new_sym.duVal.setFlags(duFlag);
  668. }
  669. ps->sym.push_back(new_sym);
  670. ps->numArgs++;
  671. }
  672. /* Save maximum argument offset */
  673. if ((dword)ps->maxOff < (off + (dword)size))
  674. ps->maxOff = off + (int16)size;
  675. }
  676. /* lookupAddr - Looks up a data reference in the symbol table and stores it
  677. * if necessary.
  678. * Returns a pointer to the symbol in the
  679. * symbol table, or Null if it's not a direct memory offset. */
  680. static SYM * lookupAddr (LLOperand *pm, STATE *pstate, Int size, word duFlag)
  681. {
  682. Int i;
  683. SYM * psym;
  684. dword operand;
  685. if (pm->regi == 0) { /* Global var */
  686. if (pm->segValue) { /* there is a value in the seg field */
  687. operand = opAdr (pm->segValue, pm->off);
  688. psym = updateGlobSym (operand, size, duFlag);
  689. /* Check for out of bounds */
  690. if (psym->label >= (dword)prog.cbImage)
  691. return (NULL);
  692. return (psym);
  693. }
  694. else if (pstate->f[pm->seg]) { /* new value */
  695. pm->segValue = pstate->r[pm->seg];
  696. operand = opAdr(pm->segValue, pm->off);
  697. i = symtab.size();
  698. psym = updateGlobSym (operand, size, duFlag);
  699. /* Flag new memory locations that are segment values */
  700. if (symtab.size() > i)
  701. {
  702. if (size == 4)
  703. operand += 2; /* High word */
  704. for (i = 0; i < prog.cReloc; i++)
  705. if (prog.relocTable[i] == operand) {
  706. psym->flg = SEG_IMMED;
  707. break;
  708. }
  709. }
  710. /* Check for out of bounds */
  711. if (psym->label >= (dword)prog.cbImage)
  712. return (NULL);
  713. return (psym);
  714. }
  715. }
  716. return (NULL);
  717. }
  718. /* setState - Assigns a value to a reg. */
  719. void STATE::setState(word reg, int16 value)
  720. {
  721. value &= 0xFFFF;
  722. r[reg] = value;
  723. f[reg] = TRUE;
  724. switch (reg) {
  725. case rAX: case rCX: case rDX: case rBX:
  726. r[reg + rAL - rAX] = value & 0xFF;
  727. f[reg + rAL - rAX] = TRUE;
  728. r[reg + rAH - rAX] = (value >> 8) & 0xFF;
  729. f[reg + rAH - rAX] = TRUE;
  730. break;
  731. case rAL: case rCL: case rDL: case rBL:
  732. if (f[reg - rAL + rAH]) {
  733. r[reg - rAL + rAX] =(r[reg - rAL + rAH] << 8) + (value & 0xFF);
  734. f[reg - rAL + rAX] = TRUE;
  735. }
  736. break;
  737. case rAH: case rCH: case rDH: case rBH:
  738. if (f[reg - rAH + rAL])
  739. {
  740. r[reg - rAH + rAX] = r[reg - rAH + rAL] + ((value & 0xFF) << 8);
  741. f[reg - rAH + rAX] = TRUE;
  742. }
  743. break;
  744. }
  745. }
  746. /* labelSrchRepl - Searches Icode for instruction with label = target, and
  747. replaces *pIndex with an icode index */
  748. bool labelSrch(CIcodeRec &pIcode, Int numIp, dword target, Int *pIndex)
  749. {
  750. Int i;
  751. for (i = 0; i < numIp; i++)
  752. {
  753. if (pIcode[i].ic.ll.label == target)
  754. {
  755. *pIndex = i;
  756. return true;
  757. }
  758. }
  759. return false;
  760. }
  761. static void setBits(int16 type, dword start, dword len)
  762. /* setBits - Sets memory bitmap bits for BM_CODE or BM_DATA (additively) */
  763. {
  764. dword i;
  765. if (start < (dword)prog.cbImage)
  766. {
  767. if (start + len > (dword)prog.cbImage)
  768. len = (dword)(prog.cbImage - start);
  769. for (i = start + len - 1; i >= start; i--)
  770. {
  771. prog.map[i >> 2] |= type << ((i & 3) << 1);
  772. if (i == 0) break; // Fixes inf loop!
  773. }
  774. }
  775. }
  776. /* DU bit definitions for each reg value - including index registers */
  777. std::bitset<32> duReg[] = { 0x00,
  778. 0x11001, 0x22002, 0x44004, 0x88008, /* word regs */
  779. 0x10, 0x20, 0x40, 0x80,
  780. 0x100, 0x200, 0x400, 0x800, /* seg regs */
  781. 0x1000, 0x2000, 0x4000, 0x8000, /* byte regs */
  782. 0x10000, 0x20000, 0x40000, 0x80000,
  783. 0x100000, /* tmp reg */
  784. 0x48, 0x88, 0x60, 0xA0, /* index regs */
  785. 0x40, 0x80, 0x20, 0x08 };
  786. /* Checks which registers where used and updates the du.u flag.
  787. * Places local variables on the local symbol table.
  788. * Arguments: d : SRC or DST icode operand
  789. * pIcode: ptr to icode instruction
  790. * pProc : ptr to current procedure structure
  791. * pstate: ptr to current procedure state
  792. * size : size of the operand
  793. * ix : current index into icode array */
  794. static void use (opLoc d, ICODE * pIcode, Function * pProc, STATE * pstate, Int size, Int ix)
  795. {
  796. LLOperand * pm = (d == SRC)? &pIcode->ic.ll.src: &pIcode->ic.ll.dst;
  797. SYM * psym;
  798. if (pm->regi == 0 || pm->regi >= INDEXBASE)
  799. {
  800. if (pm->regi == INDEXBASE + 6) /* indexed on bp */
  801. {
  802. if (pm->off >= 2)
  803. updateFrameOff (&pProc->args, pm->off, size, eDuVal::USE);
  804. else if (pm->off < 0)
  805. pProc->localId.newByteWordStk (TYPE_WORD_SIGN, pm->off, 0);
  806. }
  807. else if (pm->regi == INDEXBASE + 2 || pm->regi == INDEXBASE + 3)
  808. pProc->localId.newByteWordStk (TYPE_WORD_SIGN, pm->off,
  809. (byte)((pm->regi == INDEXBASE + 2) ? rSI : rDI));
  810. else if ((pm->regi >= INDEXBASE + 4) && (pm->regi <= INDEXBASE + 7))
  811. {
  812. if ((pm->seg == rDS) && (pm->regi == INDEXBASE + 7)) /* bx */
  813. {
  814. if (pm->off > 0) /* global indexed variable */
  815. pProc->localId.newIntIdx(pm->segValue, pm->off, rBX,ix, TYPE_WORD_SIGN);
  816. }
  817. pIcode->du.use |= duReg[pm->regi];
  818. }
  819. else if (psym = lookupAddr(pm, pstate, size, eDuVal::USE))
  820. {
  821. setBits (BM_DATA, psym->label, (dword)size);
  822. pIcode->ic.ll.flg |= SYM_USE;
  823. pIcode->ic.ll.caseTbl.numEntries = psym - &symtab[0];
  824. }
  825. }
  826. /* Use of register */
  827. else if ((d == DST) || ((d == SRC) && (pIcode->ic.ll.flg & I) != I))
  828. pIcode->du.use |= duReg[pm->regi];
  829. }
  830. /* Checks which registers were defined (ie. got a new value) and updates the
  831. * du.d flag.
  832. * Places local variables in the local symbol table. */
  833. static void def (opLoc d, ICODE * pIcode, Function * pProc, STATE * pstate, Int size,
  834. Int ix)
  835. {
  836. LLOperand *pm = (d == SRC)? &pIcode->ic.ll.src: &pIcode->ic.ll.dst;
  837. SYM * psym;
  838. if (pm->regi == 0 || pm->regi >= INDEXBASE)
  839. {
  840. if (pm->regi == INDEXBASE + 6) /* indexed on bp */
  841. {
  842. if (pm->off >= 2)
  843. updateFrameOff (&pProc->args, pm->off, size, eDEF);
  844. else if (pm->off < 0)
  845. pProc->localId.newByteWordStk (TYPE_WORD_SIGN, pm->off, 0);
  846. }
  847. else if (pm->regi == INDEXBASE + 2 || pm->regi == INDEXBASE + 3)
  848. {
  849. pProc->localId.newByteWordStk(TYPE_WORD_SIGN, pm->off,
  850. (byte)((pm->regi == INDEXBASE + 2) ? rSI : rDI));
  851. }
  852. else if ((pm->regi >= INDEXBASE + 4) && (pm->regi <= INDEXBASE + 7))
  853. {
  854. if ((pm->seg == rDS) && (pm->regi == INDEXBASE + 7)) /* bx */
  855. {
  856. if (pm->off > 0) /* global var */
  857. pProc->localId.newIntIdx(pm->segValue, pm->off, rBX,ix, TYPE_WORD_SIGN);
  858. }
  859. pIcode->du.use |= duReg[pm->regi];
  860. }
  861. else if (psym = lookupAddr(pm, pstate, size, eDEF))
  862. {
  863. setBits(BM_DATA, psym->label, (dword)size);
  864. pIcode->ic.ll.flg |= SYM_DEF;
  865. pIcode->ic.ll.caseTbl.numEntries = psym - &symtab[0];
  866. }
  867. }
  868. /* Definition of register */
  869. else if ((d == DST) || ((d == SRC) && (pIcode->ic.ll.flg & I) != I))
  870. {
  871. pIcode->du.def |= duReg[pm->regi];
  872. pIcode->du1.numRegsDef++;
  873. }
  874. }
  875. /* use_def - operand is both use and def'd.
  876. * Note: the destination will always be a register, stack variable, or global
  877. * variable. */
  878. static void use_def(opLoc d, ICODE * pIcode, Function * pProc, STATE * pstate, Int cb,
  879. Int ix)
  880. {
  881. LLOperand * pm = (d == SRC)? &pIcode->ic.ll.src: &pIcode->ic.ll.dst;
  882. use (d, pIcode, pProc, pstate, cb, ix);
  883. if (pm->regi < INDEXBASE) /* register */
  884. {
  885. pIcode->du.def |= duReg[pm->regi];
  886. pIcode->du1.numRegsDef++;
  887. }
  888. }
  889. /* Set DU vector, local variables and arguments, and DATA bits in the
  890. * bitmap */
  891. void Function::process_operands(ICODE * pIcode, STATE * pstate)
  892. {
  893. Int ix=Icode.size();
  894. Int i;
  895. Int sseg = (pIcode->ic.ll.src.seg)? pIcode->ic.ll.src.seg: rDS;
  896. Int cb = (pIcode->ic.ll.flg & B) ? 1: 2;
  897. flags32 Imm = (pIcode->ic.ll.flg & I);
  898. switch (pIcode->ic.ll.opcode) {
  899. case iAND: case iOR: case iXOR:
  900. case iSAR: case iSHL: case iSHR:
  901. case iRCL: case iRCR: case iROL: case iROR:
  902. case iADD: case iADC: case iSUB: case iSBB:
  903. if (! Imm) {
  904. use(SRC, pIcode, this, pstate, cb, ix);
  905. }
  906. case iINC: case iDEC: case iNEG: case iNOT:
  907. case iAAA: case iAAD: case iAAM: case iAAS:
  908. case iDAA: case iDAS:
  909. use_def(DST, pIcode, this, pstate, cb, ix);
  910. break;
  911. case iXCHG:
  912. /* This instruction is replaced by 3 instructions, only need
  913. * to define the src operand and use the destination operand
  914. * in the mean time. */
  915. use(SRC, pIcode, this, pstate, cb, ix);
  916. def(DST, pIcode, this, pstate, cb, ix);
  917. break;
  918. case iTEST: case iCMP:
  919. if (! Imm)
  920. use(SRC, pIcode, this, pstate, cb, ix);
  921. use(DST, pIcode, this, pstate, cb, ix);
  922. break;
  923. case iDIV: case iIDIV:
  924. use(SRC, pIcode, this, pstate, cb, ix);
  925. if (cb == 1)
  926. pIcode->du.use |= duReg[rTMP];
  927. break;
  928. case iMUL: case iIMUL:
  929. use(SRC, pIcode, this, pstate, cb, ix);
  930. if (! Imm)
  931. {
  932. use (DST, pIcode, this, pstate, cb, ix);
  933. if (cb == 1)
  934. {
  935. pIcode->du.def |= duReg[rAX];
  936. pIcode->du1.numRegsDef++;
  937. }
  938. else
  939. {
  940. pIcode->du.def |= (duReg[rAX] | duReg[rDX]);
  941. pIcode->du1.numRegsDef += 2;
  942. }
  943. }
  944. else
  945. def (DST, pIcode, this, pstate, cb, ix);
  946. break;
  947. case iSIGNEX:
  948. cb = (pIcode->ic.ll.flg & SRC_B) ? 1 : 2;
  949. if (cb == 1) /* byte */
  950. {
  951. pIcode->du.def |= duReg[rAX];
  952. pIcode->du1.numRegsDef++;
  953. pIcode->du.use |= duReg[rAL];
  954. }
  955. else /* word */
  956. {
  957. pIcode->du.def |= (duReg[rDX] | duReg[rAX]);
  958. pIcode->du1.numRegsDef += 2;
  959. pIcode->du.use |= duReg[rAX];
  960. }
  961. break;
  962. case iCALLF: /* Ignore def's on CS for now */
  963. cb = 4;
  964. case iCALL: case iPUSH: case iPOP:
  965. if (! Imm) {
  966. if (pIcode->ic.ll.opcode == iPOP)
  967. def(DST, pIcode, this, pstate, cb, ix);
  968. else
  969. use(DST, pIcode, this, pstate, cb, ix);
  970. }
  971. break;
  972. case iESC: /* operands may be larger */
  973. use(DST, pIcode, this, pstate, cb, ix);
  974. break;
  975. case iLDS: case iLES:
  976. pIcode->du.def |= duReg[(pIcode->ic.ll.opcode == iLDS) ? rDS : rES];
  977. pIcode->du1.numRegsDef++;
  978. cb = 4;
  979. case iMOV:
  980. use(SRC, pIcode, this, pstate, cb, ix);
  981. def(DST, pIcode, this, pstate, cb, ix);
  982. break;
  983. case iLEA:
  984. use(SRC, pIcode, this, pstate, 2, ix);
  985. def(DST, pIcode, this, pstate, 2, ix);
  986. break;
  987. case iBOUND:
  988. use(SRC, pIcode, this, pstate, 4, ix);
  989. use(DST, pIcode, this, pstate, cb, ix);
  990. break;
  991. case iJMPF:
  992. cb = 4;
  993. case iJMP:
  994. if (! Imm)
  995. use(SRC, pIcode, this, pstate, cb, ix);
  996. break;
  997. case iLOOP: case iLOOPE: case iLOOPNE:
  998. pIcode->du.def |= duReg[rCX];
  999. pIcode->du1.numRegsDef++;
  1000. case iJCXZ:
  1001. pIcode->du.use |= duReg[rCX];
  1002. break;
  1003. case iREPNE_CMPS: case iREPE_CMPS: case iREP_MOVS:
  1004. pIcode->du.def |= duReg[rCX];
  1005. pIcode->du1.numRegsDef++;
  1006. pIcode->du.use |= duReg[rCX];
  1007. case iCMPS: case iMOVS:
  1008. pIcode->du.def |= duReg[rSI] | duReg[rDI];
  1009. pIcode->du1.numRegsDef += 2;
  1010. pIcode->du.use |= duReg[rSI] | duReg[rDI] | duReg[rES] | duReg[sseg];
  1011. break;
  1012. case iREPNE_SCAS: case iREPE_SCAS: case iREP_STOS: case iREP_INS:
  1013. pIcode->du.def |= duReg[rCX];
  1014. pIcode->du1.numRegsDef++;
  1015. pIcode->du.use |= duReg[rCX];
  1016. case iSCAS: case iSTOS: case iINS:
  1017. pIcode->du.def |= duReg[rDI];
  1018. pIcode->du1.numRegsDef++;
  1019. if (pIcode->ic.ll.opcode == iREP_INS || pIcode->ic.ll.opcode== iINS)
  1020. {
  1021. pIcode->du.use |= duReg[rDI] | duReg[rES] | duReg[rDX];
  1022. }
  1023. else
  1024. {
  1025. pIcode->du.use |= duReg[rDI] | duReg[rES] | duReg[(cb == 2)? rAX: rAL];
  1026. }
  1027. break;
  1028. case iREP_LODS:
  1029. pIcode->du.def |= duReg[rCX];
  1030. pIcode->du1.numRegsDef++;
  1031. pIcode->du.use |= duReg[rCX];
  1032. case iLODS:
  1033. pIcode->du.def |= duReg[rSI] | duReg[(cb==2)? rAX: rAL];
  1034. pIcode->du1.numRegsDef += 2;
  1035. pIcode->du.use |= duReg[rSI] | duReg[sseg];
  1036. break;
  1037. case iREP_OUTS:
  1038. pIcode->du.def |= duReg[rCX];
  1039. pIcode->du1.numRegsDef++;
  1040. pIcode->du.use |= duReg[rCX];
  1041. case iOUTS:
  1042. pIcode->du.def |= duReg[rSI];
  1043. pIcode->du1.numRegsDef++;
  1044. pIcode->du.use |= duReg[rSI] | duReg[rDX] | duReg[sseg];
  1045. break;
  1046. case iIN: case iOUT:
  1047. def(DST, pIcode, this, pstate, cb, ix);
  1048. if (! Imm)
  1049. {
  1050. pIcode->du.use |= duReg[rDX];
  1051. }
  1052. break;
  1053. }
  1054. for (i = rSP; i <= rBH; i++) /* Kill all defined registers */
  1055. if (pIcode->ic.ll.flagDU.d & (1 << i))
  1056. pstate->f[i] = FALSE;
  1057. }