disassem.cpp 22 KB

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