disassem.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. /****************************************************************************
  2. * dcc project disassembler
  3. * (C) Cristina Cifuentes, Mike van Emmerik, Jeff Ledermann
  4. ****************************************************************************/
  5. #include <stdint.h>
  6. #include <vector>
  7. #include <map>
  8. #include <sstream>
  9. #include <iomanip>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <malloc.h> /* For free() */
  13. #include "dcc.h"
  14. #include "symtab.h"
  15. #include "disassem.h"
  16. // Note: for the time being, there is no interactive disassembler
  17. // for unix
  18. #ifndef __UNIX__
  19. #include <conio.h> // getch() etc
  20. #endif
  21. using namespace std;
  22. #define POS_LAB 15 /* Position of label */
  23. #define POS_OPC 20 /* Position of opcode */
  24. #define POS_OPR 25 /* Position of operand */
  25. #define WID_PTR 10 /* Width of the "xword ptr" lingo */
  26. #define POS_OPR2 POS_OPR+WID_PTR /* Position of operand after "xword ptr" */
  27. #define POS_CMT 54 /* Position of comment */
  28. #define DELTA_ICODE 16 /* Number of icodes to realloc by each time */
  29. /* The following opcodes are for mod != 3 */
  30. static const char *szFlops1[] =
  31. {
  32. /* 0 1 2 3 4 5 6 7 */
  33. "FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */
  34. "FLD", "???", "FST", "???", "FLDENV","FLDCW", "FSTENV","FSTSW", /* 08 */
  35. "FIADD", "FIMUL", "FICOM","FICOMP","FISUB", "FISUBR","FIDIV", "FIDIVR", /* 10 */
  36. "FILD", "???", "FIST", "FISTP", "???", "???", "???", "FSTP", /* 18 */
  37. "FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 20 */
  38. "FLD", "FLD", "FST", "FSTP", "FRESTOR","???", "FSAVE", "FSTSW", /* 28 */
  39. "FIADD", "FIMUL", "FICOM","FICOMP","FISUB", "FISUBR","FIDIV", "FIDIVR", /* 30 */
  40. "FILD", "???", "FIST", "FISTP", "FBLD", "???", "FBSTP", "FISTP" /* 38 */
  41. };
  42. /* The following opcodes are for mod == 3 */
  43. static const char *szFlops2[] =
  44. {
  45. /* 0 1 2 3 4 5 6 7 */
  46. "FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */
  47. "FLD", "FXCH", "FNOP", "???", "", "", "", "", /* 08 */
  48. "FIADD", "FIMUL", "FICOM","FICOMP","FISUB", "", "FIDIV", "FIDIVR", /* 10 */
  49. "FILD", "???", "FIST", "FISTP", "???", "???", "???", "FSTP", /* 18 */
  50. "FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 20 */
  51. "FFREE", "FSTP", "FST", "???", "FUCOM", "FUCOMP","???", "???", /* 28 */
  52. "FADDP", "FMULP", "FICOM","", "FSUBRP","FISUBR","FDIVRP","FDIVP", /* 30 */
  53. "FILD", "???", "FIST", "FISTP", "", "???", "FBSTP", "FISTP" /* 38 */
  54. };
  55. static const char *szFlops0C[] =
  56. {
  57. "FCHS", "FABS", "???", "???", "FTST", "FXAM", "???", "???"
  58. };
  59. static const char *szFlops0D[] =
  60. {
  61. "FLD1", "FLDL2T","FLDL2E","FLDP1", "FLDLG2","FLDLN2","FLDZ", "???"
  62. };
  63. static const char *szFlops0E[] =
  64. {
  65. "F2XM1", "FYL2X", "FPTAN", "FPATAN","FXTRACT","FPREM1","FDECSTP","FINCSTP"
  66. };
  67. static const char *szFlops0F[] =
  68. {
  69. "FPREM", "FYLXP1","FSQRT", "FSINCOS","FRNDINT","FSCALE","FSIN","FCOS"
  70. };
  71. static const char *szFlops15[] =
  72. {
  73. "???", "FUCOMPP", "???", "???", "???", "???", "???", "???"
  74. };
  75. static const char *szFlops1C[] =
  76. {
  77. "???", "???", "FCLEX", "FINIT", "FTST", "FXAM", "???", "???"
  78. };
  79. static const char *szFlops33[] =
  80. {
  81. "???", "FCOMPP", "???", "???", "???", "???", "???", "???"
  82. };
  83. static const char *szFlops3C[] =
  84. {
  85. "FSTSWAX","???", "???", "???", "???", "???", "???", "???"
  86. };
  87. //static const char *szIndex[8] = {"bx+si", "bx+di", "bp+si", "bp+di", "si", "di","bp","bx" };
  88. //static const char *szBreg[8] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" };
  89. //static const char *szWreg[12] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
  90. // "es", "cs", "ss", "ds" };
  91. static const char *szPtr[2] = { "word ptr ", "byte ptr " };
  92. //void dis1LineOp(int i, boolT fWin, char attr, uint16_t *len, Function * pProc);
  93. static void formatRM(ostringstream &p, uint32_t flg, const LLOperand &pm);
  94. static ostringstream &strDst(ostringstream &os, uint32_t flg, LLOperand &pm);
  95. static char *strHex(uint32_t d);
  96. static int checkScanned(uint32_t pcCur);
  97. static void setProc(Function * proc);
  98. static void dispData(uint16_t dataSeg);
  99. boolT callArg(uint16_t off, char *temp); /* Check for procedure name */
  100. //static FILE *dis_g_fp;
  101. static CIcodeRec pc;
  102. static int cb, j, numIcode, allocIcode;
  103. static map<int,int> pl;
  104. static uint32_t nextInst;
  105. static boolT fImpure;
  106. //static int g_lab;
  107. static Function * pProc; /* Points to current proc struct */
  108. struct POSSTACK_ENTRY
  109. {
  110. int ic; /* An icode offset */
  111. Function * pProc; /* A pointer to a PROCEDURE structure */
  112. } ;
  113. vector<POSSTACK_ENTRY> posStack; /* position stack */
  114. uint8_t iPS; /* Index into the stack */
  115. //static char cbuf[256]; /* Has to be 256 for wgetstr() to work */
  116. // These are "curses equivalent" functions. (Used to use curses for all this,
  117. // but it was too much of a distribution hassle
  118. #define printfd(x) printf(x)
  119. #define dis_newline() printf("\n")
  120. #define dis_show() // Nothing to do unless using Curses
  121. void LLInst::findJumpTargets(CIcodeRec &_pc)
  122. {
  123. if (testFlags(I) && ! testFlags(JMP_ICODE) && isJmpInst())
  124. {
  125. /* Replace the immediate operand with an icode index */
  126. iICODE labTgt=_pc.labelSrch(src.op());
  127. if (labTgt!=_pc.end())
  128. {
  129. src.SetImmediateOp(labTgt->loc_ip);
  130. /* This icode is the target of a jump */
  131. labTgt->ll()->setFlags(TARGET);
  132. setFlags(JMP_ICODE); /* So its not done twice */
  133. }
  134. else
  135. {
  136. /* This jump cannot be linked to a label */
  137. setFlags(NO_LABEL);
  138. }
  139. }
  140. }
  141. /*****************************************************************************
  142. * disassem - Prints a disassembled listing of a procedure.
  143. * pass == 1 generates output on file .a1
  144. * pass == 2 generates output on file .a2
  145. * pass == 3 generates output on file .b
  146. ****************************************************************************/
  147. void Disassembler::disassem(Function * ppProc)
  148. {
  149. pProc = ppProc; /* Save the passes pProc */
  150. createSymTables();
  151. allocIcode = numIcode = pProc->Icode.size();
  152. cb = allocIcode * sizeof(ICODE);
  153. if (numIcode == 0)
  154. {
  155. return; /* No Icode */
  156. }
  157. /* Open the output file (.a1 or .a2 only) */
  158. if (pass != 3)
  159. {
  160. auto p = (pass == 1)? asm1_name: asm2_name;
  161. m_fp.open(p,ios_base::app);
  162. if (!m_fp.is_open())
  163. {
  164. fatalError(CANNOT_OPEN, p);
  165. }
  166. }
  167. pc=pProc->Icode;
  168. /* Create temporary code array */
  169. // Mike: needs objectising!
  170. //pc = (ICODE *)memcpy(allocMem(cb), pProc->Icode.GetFirstIcode(), (size_t)cb);
  171. if (pass == 1)
  172. {
  173. /* Bind jump offsets to labels */
  174. //for (i = 0; i < numIcode; i++)
  175. for( ICODE &icode : pc)
  176. {
  177. LLInst *ll=icode.ll();
  178. ll->findJumpTargets(pc);
  179. }
  180. }
  181. /* Create label array to keep track of location => label name */
  182. pl.clear();
  183. /* Write procedure header */
  184. if (pass != 3)
  185. {
  186. std::string near_far=(pProc->flg & PROC_FAR)? "FAR": "NEAR";
  187. m_fp << "\t\t"<<pProc->name<<" PROC "<< near_far<<"\n";
  188. }
  189. /* Loop over array printing each record */
  190. nextInst = 0;
  191. for( ICODE &icode : pc)
  192. {
  193. this->dis1Line(*icode.ll(),icode.loc_ip,pass);
  194. }
  195. /* Write procedure epilogue */
  196. if (pass != 3)
  197. {
  198. m_fp << "\n\t\t"<<pProc->name<<" ENDP\n\n";
  199. m_fp.close();
  200. }
  201. pc.clear();
  202. destroySymTables();
  203. }
  204. /****************************************************************************
  205. * dis1Line() - disassemble one line to stream fp * *
  206. * i is index into Icode for this proc *
  207. * It is assumed that icode i is already scanned *
  208. ****************************************************************************/
  209. void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
  210. {
  211. ostringstream oper_stream;
  212. ostringstream hex_bytes;
  213. ostringstream result_stream;
  214. ostringstream opcode_with_mods;
  215. ostringstream operands_s;
  216. oper_stream << uppercase;
  217. hex_bytes << uppercase;
  218. /* Disassembly stage 1 --
  219. * Do not try to display NO_CODE entries or synthetic instructions,
  220. * other than JMPs, that have been introduced for def/use analysis. */
  221. if ((option.asm1) &&
  222. ( inst.testFlags(NO_CODE) ||
  223. (inst.testFlags(SYNTHETIC) && (inst.getOpcode() != iJMP))))
  224. {
  225. return;
  226. }
  227. else if (inst.testFlags(NO_CODE))
  228. {
  229. return;
  230. }
  231. if (inst.testFlags(TARGET | CASE))
  232. {
  233. if (pass == 3)
  234. cCode.appendCode("\n"); /* Print to c code buffer */
  235. else
  236. m_fp<< "\n"; /* No, print to the stream */
  237. }
  238. /* Find next instruction label and print hex bytes */
  239. if (inst.testFlags(SYNTHETIC))
  240. nextInst = inst.label;
  241. else
  242. {
  243. cb = (uint32_t) inst.numBytes;
  244. nextInst = inst.label + cb;
  245. /* Output hexa code in program image */
  246. if (pass != 3)
  247. {
  248. for (j = 0; j < cb; j++)
  249. {
  250. hex_bytes << hex << setw(2) << setfill('0') << uint16_t(prog.Image[inst.label + j]);
  251. }
  252. hex_bytes << ' ';
  253. }
  254. }
  255. oper_stream << setw(POS_LAB) << left<< hex_bytes.str();
  256. /* Check if there is a symbol here */
  257. selectTable(Label);
  258. oper_stream << setw(5)<<left; // align for the labels
  259. {
  260. ostringstream lab_contents;
  261. if (readVal(lab_contents, inst.label, 0))
  262. {
  263. lab_contents << ':'; /* Also removes the null */
  264. }
  265. else if (inst.testFlags(TARGET)) /* Symbols override Lnn labels */
  266. {
  267. /* Print label */
  268. if (pl.count(loc_ip)==0)
  269. {
  270. pl[loc_ip] = ++g_lab;
  271. }
  272. lab_contents<< "L"<<pl[loc_ip]<<':';
  273. }
  274. oper_stream<< lab_contents.str();
  275. }
  276. if ((inst.getOpcode()==iSIGNEX )&& inst.testFlags(B))
  277. {
  278. inst.setOpcode(iCBW);
  279. }
  280. opcode_with_mods<<Machine_X86::opcodeName(inst.getOpcode());
  281. switch ( inst.getOpcode() )
  282. {
  283. case iADD: case iADC: case iSUB: case iSBB: case iAND: case iOR:
  284. case iXOR: case iTEST: case iCMP: case iMOV: case iLEA: case iXCHG:
  285. strDst(operands_s,inst.getFlag(), inst.dst);
  286. inst.strSrc(operands_s);
  287. break;
  288. case iESC:
  289. inst.flops(operands_s);
  290. break;
  291. case iSAR: case iSHL: case iSHR: case iRCL: case iRCR: case iROL:
  292. case iROR:
  293. strDst(operands_s,inst.getFlag() | I, inst.dst);
  294. if(inst.testFlags(I))
  295. inst.strSrc(operands_s);
  296. else
  297. operands_s<<", cl";
  298. break;
  299. case iINC: case iDEC: case iNEG: case iNOT: case iPOP:
  300. strDst(operands_s,inst.getFlag() | I, inst.dst);
  301. break;
  302. case iPUSH:
  303. if (inst.testFlags(I))
  304. {
  305. operands_s<<strHex(inst.src.op());
  306. }
  307. else
  308. {
  309. strDst(operands_s,inst.getFlag() | I, inst.dst);
  310. }
  311. break;
  312. case iDIV: case iIDIV: case iMUL: case iIMUL: case iMOD:
  313. if (inst.testFlags(I))
  314. {
  315. strDst(operands_s,inst.getFlag(), inst.dst) <<", ";
  316. formatRM(operands_s, inst.getFlag(), inst.src);
  317. inst.strSrc(operands_s);
  318. }
  319. else
  320. strDst(operands_s,inst.getFlag() | I, inst.src);
  321. break;
  322. case iLDS: case iLES: case iBOUND:
  323. strDst(operands_s,inst.getFlag(), inst.dst)<<", dword ptr";
  324. inst.strSrc(operands_s,true);
  325. break;
  326. case iJB: case iJBE: case iJAE: case iJA:
  327. case iJL: case iJLE: case iJGE: case iJG:
  328. case iJE: case iJNE: case iJS: case iJNS:
  329. case iJO: case iJNO: case iJP: case iJNP:
  330. case iJCXZ:case iLOOP: case iLOOPE:case iLOOPNE:
  331. case iJMP: case iJMPF:
  332. /* Check if there is a symbol here */
  333. {
  334. ICODE *lab=pc.GetIcode(inst.src.op());
  335. selectTable(Label);
  336. if ((inst.src.op() < (uint32_t)numIcode) && /* Ensure in range */
  337. readVal(operands_s, lab->ll()->label, 0))
  338. {
  339. break; /* Symbolic label. Done */
  340. }
  341. }
  342. if (inst.testFlags(NO_LABEL))
  343. {
  344. //strcpy(p + WID_PTR, strHex(pIcode->ll()->immed.op));
  345. operands_s<<strHex(inst.src.op());
  346. }
  347. else if (inst.testFlags(I) )
  348. {
  349. j = inst.src.op();
  350. if (pl.count(j)==0) /* Forward jump */
  351. {
  352. pl[j] = ++g_lab;
  353. }
  354. if (inst.getOpcode() == iJMPF)
  355. {
  356. operands_s<<" far ptr ";
  357. }
  358. operands_s<<"L"<<pl[j];
  359. }
  360. else if (inst.getOpcode() == iJMPF)
  361. {
  362. operands_s<<"dword ptr";
  363. inst.strSrc(operands_s,true);
  364. }
  365. else
  366. {
  367. strDst(operands_s,I, inst.src);
  368. }
  369. break;
  370. case iCALL: case iCALLF:
  371. if (inst.testFlags(I))
  372. {
  373. if((inst.getOpcode() == iCALL))
  374. operands_s<< "near";
  375. else
  376. operands_s<< " far";
  377. operands_s<<" ptr "<<(inst.src.proc.proc)->name;
  378. }
  379. else if (inst.getOpcode() == iCALLF)
  380. {
  381. operands_s<<"dword ptr ";
  382. inst.strSrc(operands_s,true);
  383. }
  384. else
  385. strDst(operands_s,I, inst.src);
  386. break;
  387. case iENTER:
  388. operands_s<<strHex(inst.dst.off)<<", ";
  389. operands_s<<strHex(inst.src.op());
  390. break;
  391. case iRET: case iRETF: case iINT:
  392. if (inst.testFlags(I))
  393. {
  394. operands_s<<strHex(inst.src.op());
  395. }
  396. break;
  397. case iCMPS: case iREPNE_CMPS: case iREPE_CMPS:
  398. case iSCAS: case iREPNE_SCAS: case iREPE_SCAS:
  399. case iSTOS: case iREP_STOS:
  400. case iLODS: case iREP_LODS:
  401. case iMOVS: case iREP_MOVS:
  402. case iINS: case iREP_INS:
  403. case iOUTS: case iREP_OUTS:
  404. if (inst.src.segOver)
  405. {
  406. bool is_dx_src=(inst.getOpcode() == iOUTS || inst.getOpcode() == iREP_OUTS);
  407. if(is_dx_src)
  408. operands_s<<"dx, "<<szPtr[inst.getFlag() & B];
  409. else
  410. operands_s<<szPtr[inst.getFlag() & B];
  411. if (inst.getOpcode() == iLODS ||
  412. inst.getOpcode() == iREP_LODS ||
  413. inst.getOpcode() == iOUTS ||
  414. inst.getOpcode() == iREP_OUTS)
  415. {
  416. operands_s<<Machine_X86::regName(inst.src.segOver); // szWreg[src.segOver-rAX]
  417. }
  418. else
  419. {
  420. operands_s<<"es:[di], "<<Machine_X86::regName(inst.src.segOver);
  421. }
  422. operands_s<<":[si]";
  423. }
  424. else
  425. {
  426. (inst.getFlag() & B)? opcode_with_mods<< "B": opcode_with_mods<< "W";
  427. }
  428. break;
  429. case iXLAT:
  430. if (inst.src.segOver)
  431. {
  432. operands_s<<" "<<szPtr[1];
  433. operands_s<<Machine_X86::regName(inst.src.segOver)<<":[bx]";
  434. }
  435. break;
  436. case iIN:
  437. (inst.getFlag() & B)? operands_s<<"al, " : operands_s<< "ax, ";
  438. (inst.testFlags(I))? operands_s << strHex(inst.src.op()) : operands_s<< "dx";
  439. break;
  440. case iOUT:
  441. {
  442. std::string d1=((inst.testFlags(I))? strHex(inst.src.op()): "dx");
  443. std::string d2=((inst.getFlag() & B) ? ", al": ", ax");
  444. operands_s<<d1 << d2;
  445. }
  446. break;
  447. default:
  448. break;
  449. }
  450. oper_stream << setw(15) << left <<opcode_with_mods.str();
  451. oper_stream << operands_s.str();
  452. /* Comments */
  453. if (inst.testFlags(SYNTHETIC))
  454. {
  455. fImpure = FALSE;
  456. }
  457. else
  458. {
  459. for (j = inst.label, fImpure = 0; j > 0 && j < (int)nextInst; j++)
  460. {
  461. fImpure |= BITMAP(j, BM_DATA);
  462. }
  463. }
  464. result_stream << setw(54) << left << oper_stream.str();
  465. /* Check for user supplied comment */
  466. selectTable(Comment);
  467. ostringstream cbuf;
  468. if (readVal(cbuf, inst.label, 0))
  469. {
  470. result_stream <<"; "<<cbuf.str();
  471. }
  472. else if (fImpure || (inst.testFlags(SWITCH | CASE | SEG_IMMED | IMPURE | SYNTHETIC | TERMINATES)))
  473. {
  474. if (inst.testFlags(CASE))
  475. {
  476. result_stream << ";Case l"<< inst.caseTbl.numEntries;
  477. }
  478. if (inst.testFlags(SWITCH))
  479. {
  480. result_stream << ";Switch ";
  481. }
  482. if (fImpure)
  483. {
  484. result_stream << ";Accessed as data ";
  485. }
  486. if (inst.testFlags(IMPURE))
  487. {
  488. result_stream << ";Impure operand ";
  489. }
  490. if (inst.testFlags(SEG_IMMED))
  491. {
  492. result_stream << ";Segment constant";
  493. }
  494. if (inst.testFlags(TERMINATES))
  495. {
  496. result_stream << ";Exit to DOS";
  497. }
  498. }
  499. /* Comment on iINT icodes */
  500. if (inst.getOpcode() == iINT)
  501. inst.writeIntComment(result_stream);
  502. /* Display output line */
  503. if(pass==3)
  504. {
  505. /* output to .b code buffer */
  506. if (inst.testFlags(SYNTHETIC))
  507. result_stream<<";Synthetic inst";
  508. if (pass == 3) /* output to .b code buffer */
  509. cCode.appendCode("%s\n", result_stream.str().c_str());
  510. }
  511. else
  512. {
  513. char buf[12];
  514. /* output to .a1 or .a2 file */
  515. if (not inst.testFlags(SYNTHETIC) )
  516. {
  517. sprintf(buf,"%03ld %06lX",loc_ip, inst.label);
  518. }
  519. else /* SYNTHETIC instruction */
  520. {
  521. sprintf(buf,"%03ld ",loc_ip);
  522. result_stream<<";Synthetic inst";
  523. }
  524. m_fp<<buf<< " " << result_stream.str() << "\n";
  525. }
  526. }
  527. /****************************************************************************
  528. * formatRM
  529. ***************************************************************************/
  530. static void formatRM(std::ostringstream &p, uint32_t flg, const LLOperand &pm)
  531. {
  532. //char seg[4];
  533. if (pm.segOver)
  534. {
  535. p <<Machine_X86::regName(pm.segOver)<<':';
  536. //strcat(strcpy(seg, szWreg[pm.segOver - rAX]), ":");
  537. }
  538. //else *seg = '\0';
  539. if (pm.regi == rUNDEF)
  540. {
  541. p<<"["<<strHex((uint32_t)pm.off)<<"]";
  542. }
  543. else if (pm.isReg())
  544. {
  545. p<<Machine_X86::regName(pm.regi);
  546. // if(flg & B)
  547. // p << szBreg[pm.regi - rAL];
  548. // else
  549. // p << szWreg[pm.regi - rAX];
  550. }
  551. else if (pm.off)
  552. {
  553. if (pm.off < 0)
  554. {
  555. p <<"["<<Machine_X86::regName(pm.regi)<<"-"<<strHex((uint32_t)(- pm.off))<<"]";
  556. }
  557. else
  558. {
  559. p <<"["<<Machine_X86::regName(pm.regi)<<"+"<<strHex((uint32_t)(pm.off))<<"]";
  560. }
  561. }
  562. else
  563. p <<"["<<Machine_X86::regName(pm.regi)<<"]";
  564. }
  565. /*****************************************************************************
  566. * strDst
  567. ****************************************************************************/
  568. static ostringstream & strDst(ostringstream &os,uint32_t flg, LLOperand &pm)
  569. {
  570. /* Immediates to memory require size descriptor */
  571. //os << setw(WID_PTR);
  572. if ((flg & I) and not pm.isReg())
  573. os << szPtr[flg & B];
  574. formatRM(os, flg, pm);
  575. return os;
  576. }
  577. /****************************************************************************
  578. * strSrc *
  579. ****************************************************************************/
  580. ostringstream &LLInst::strSrc(ostringstream &os,bool skip_comma)
  581. {
  582. if(false==skip_comma)
  583. os<<", ";
  584. if (testFlags(I))
  585. os<<strHex(src.op());
  586. else if (testFlags(IM_SRC)) /* level 2 */
  587. os<<"dx:ax";
  588. else
  589. formatRM(os, getFlag(), src);
  590. return os;
  591. }
  592. /****************************************************************************
  593. * strHex *
  594. ****************************************************************************/
  595. static char *strHex(uint32_t d)
  596. {
  597. static char buf[10];
  598. d &= 0xFFFF;
  599. sprintf(buf, "0%lX%s", d, (d > 9)? "h": "");
  600. return (buf + (buf[1] <= '9'));
  601. }
  602. /****************************************************************************
  603. * interactDis - interactive disassembler *
  604. ****************************************************************************/
  605. void interactDis(Function * initProc, int initIC)
  606. {
  607. printf("Sorry - interactive disasassembler option not available for Unix\n");
  608. return;
  609. }
  610. /* Handle the floating point opcodes (icode iESC) */
  611. void LLInst::flops(std::ostringstream &out)
  612. {
  613. char bf[30];
  614. uint8_t op = (uint8_t)src.op();
  615. /* Note that op is set to the escape number, e.g.
  616. esc 0x38 is FILD */
  617. if ( not dst.isReg() )
  618. {
  619. /* The mod/rm mod bits are not set to 11 (i.e. register). This is the normal floating point opcode */
  620. out<<szFlops1[op]<<' ';
  621. out <<setw(10);
  622. if ((op == 0x29) || (op == 0x1F))
  623. {
  624. strcpy(bf, "tbyte ptr ");
  625. }
  626. else switch (op & 0x30)
  627. {
  628. case 0x00:
  629. case 0x10:
  630. strcpy(bf, "dword ptr ");
  631. break;
  632. case 0x20:
  633. strcpy(bf, "qword ptr ");
  634. break;
  635. case 0x30:
  636. switch (op)
  637. {
  638. case 0x3C: /* FBLD */
  639. case 0x3E: /* FBSTP */
  640. strcpy(bf, "tbyte ptr ");
  641. break;
  642. case 0x3D: /* FILD 64 bit */
  643. case 0x3F: /* FISTP 64 bit */
  644. strcpy(bf, "qword ptr ");
  645. break;
  646. default:
  647. strcpy(bf, "uint16_t ptr ");
  648. break;
  649. }
  650. }
  651. formatRM(out, getFlag(), dst);
  652. }
  653. else
  654. {
  655. /* The mod/rm mod bits are set to 11 (i.e. register).
  656. Could be specials (0x0C-0x0F, etc), or the st(i) versions of
  657. normal opcodes. Because the opcodes are slightly different for
  658. this case (e.g. op=04 means FSUB if reg != 3, but FSUBR for
  659. reg == 3), a separate table is used (szFlops2). */
  660. int destRegIdx=dst.regi - rAX;
  661. switch (op)
  662. {
  663. case 0x0C:
  664. out << szFlops0C[destRegIdx];
  665. break;
  666. case 0x0D:
  667. out << szFlops0D[destRegIdx];
  668. break;
  669. case 0x0E:
  670. out << szFlops0E[destRegIdx];
  671. break;
  672. case 0x0F:
  673. out << szFlops0F[destRegIdx];
  674. break;
  675. case 0x15:
  676. out << szFlops15[destRegIdx];
  677. break;
  678. case 0x1C:
  679. out << szFlops1C[destRegIdx];
  680. break;
  681. case 0x33:
  682. out << szFlops33[destRegIdx];
  683. break;
  684. case 0x3C:
  685. out << szFlops3C[destRegIdx];
  686. break;
  687. default:
  688. out << szFlops2[op];
  689. if ((op >= 0x20) && (op <= 0x27))
  690. {
  691. /* This is the ST(i), ST form. */
  692. out << "ST("<<destRegIdx - rAX<<"),ST";
  693. }
  694. else
  695. {
  696. /* ST, ST(i) */
  697. out << "ST,ST("<<destRegIdx;
  698. }
  699. break;
  700. }
  701. }
  702. }