hlicode.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. /*
  2. * File: hlIcode.c
  3. * Purpose: High-level icode routines
  4. * Date: September-October 1993
  5. * (C) Cristina Cifuentes
  6. */
  7. #include <cassert>
  8. #include <string.h>
  9. #include <string>
  10. #include <sstream>
  11. #include "dcc.h"
  12. using namespace std;
  13. #define ICODE_DELTA 25
  14. /* Masks off bits set by duReg[] */
  15. std::bitset<32> maskDuReg[] = { 0x00,
  16. 0xFEEFFE, 0xFDDFFD, 0xFBB00B, 0xF77007, /* uint16_t regs */
  17. 0xFFFFEF, 0xFFFFDF, 0xFFFFBF, 0xFFFF7F,
  18. 0xFFFEFF, 0xFFFDFF, 0xFFFBFF, 0xFFF7FF, /* seg regs */
  19. 0xFFEFFF, 0xFFDFFF, 0xFFBFFF, 0xFF7FFF, /* uint8_t regs */
  20. 0xFEFFFF, 0xFDFFFF, 0xFBFFFF, 0xF7FFFF,
  21. 0xEFFFFF, /* tmp reg */
  22. 0xFFFFB7, 0xFFFF77, 0xFFFF9F, 0xFFFF5F, /* index regs */
  23. 0xFFFFBF, 0xFFFF7F, 0xFFFFDF, 0xFFFFF7 };
  24. static char buf[lineSize]; /* Line buffer for hl icode output */
  25. /* Places the new HLI_ASSIGN high-level operand in the high-level icode array */
  26. void HLTYPE::setAsgn(COND_EXPR *lhs, COND_EXPR *rhs)
  27. {
  28. set(lhs,rhs);
  29. }
  30. void ICODE::checkHlCall()
  31. {
  32. //assert((ll()->immed.proc.cb != 0)||ll()->immed.proc.proc!=0);
  33. }
  34. /* Places the new HLI_CALL high-level operand in the high-level icode array */
  35. void ICODE::newCallHl()
  36. {
  37. type = HIGH_LEVEL;
  38. hl()->opcode = HLI_CALL;
  39. hl()->call.proc = ll()->src.proc.proc;
  40. hl()->call.args = new STKFRAME;
  41. if (ll()->src.proc.cb != 0)
  42. hl()->call.args->cb = ll()->src.proc.cb;
  43. else if(hl()->call.proc)
  44. hl()->call.args->cb =hl()->call.proc->cbParam;
  45. else
  46. {
  47. printf("Function with no cb set, and no valid oper.call.proc , probaby indirect call\n");
  48. hl()->call.args->cb = 0;
  49. }
  50. }
  51. /* Places the new HLI_POP/HLI_PUSH/HLI_RET high-level operand in the high-level icode
  52. * array */
  53. void ICODE::setUnary(hlIcode op, COND_EXPR *exp)
  54. {
  55. type = HIGH_LEVEL;
  56. hl()->set(op,exp);
  57. }
  58. /* Places the new HLI_JCOND high-level operand in the high-level icode array */
  59. void ICODE::setJCond(COND_EXPR *cexp)
  60. {
  61. type = HIGH_LEVEL;
  62. hl()->set(HLI_JCOND,cexp);
  63. }
  64. /* Sets the invalid field to TRUE as this low-level icode is no longer valid,
  65. * it has been replaced by a high-level icode. */
  66. void ICODE ::invalidate()
  67. {
  68. invalid = TRUE;
  69. }
  70. /* Removes the defined register regi from the lhs subtree.
  71. * If all registers
  72. * of this instruction are unused, the instruction is invalidated (ie. removed)
  73. */
  74. bool ICODE::removeDefRegi (eReg regi, int thisDefIdx, LOCAL_ID *locId)
  75. {
  76. int numDefs;
  77. numDefs = du1.numRegsDef;
  78. if (numDefs == thisDefIdx)
  79. {
  80. for ( ; numDefs > 0; numDefs--)
  81. {
  82. if (du1.used(numDefs-1)||(du.lastDefRegi[regi]))
  83. break;
  84. }
  85. }
  86. if (numDefs == 0)
  87. {
  88. invalidate();
  89. return true;
  90. }
  91. HlTypeSupport *p=hl()->get();
  92. if(p and p->removeRegFromLong(regi,locId))
  93. {
  94. du1.numRegsDef--;
  95. du.def &= maskDuReg[regi];
  96. }
  97. return false;
  98. }
  99. HLTYPE LLInst::createCall()
  100. {
  101. HLTYPE res(HLI_CALL);
  102. res.call.proc = src.proc.proc;
  103. res.call.args = new STKFRAME;
  104. if (src.proc.cb != 0)
  105. res.call.args->cb = src.proc.cb;
  106. else if(res.call.proc)
  107. res.call.args->cb =res.call.proc->cbParam;
  108. else
  109. {
  110. printf("Function with no cb set, and no valid oper.call.proc , probaby indirect call\n");
  111. res.call.args->cb = 0;
  112. }
  113. return res;
  114. }
  115. #if 0
  116. HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
  117. {
  118. HLTYPE res(HLI_INVALID);
  119. if ( testFlags(NOT_HLL) )
  120. return res;
  121. flg = getFlag();
  122. switch (getOpcode())
  123. {
  124. case iADD:
  125. rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
  126. res.setAsgn(lhs, rhs);
  127. break;
  128. case iAND:
  129. rhs = COND_EXPR::boolOp (lhs, rhs, AND);
  130. res.setAsgn(lhs, rhs);
  131. break;
  132. case iCALL:
  133. case iCALLF:
  134. //TODO: this is noop pIcode->checkHlCall();
  135. res=createCall();
  136. break;
  137. case iDEC:
  138. rhs = COND_EXPR::idKte (1, 2);
  139. rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
  140. res.setAsgn(lhs, rhs);
  141. break;
  142. case iDIV:
  143. case iIDIV:/* should be signed div */
  144. rhs = COND_EXPR::boolOp (lhs, rhs, DIV);
  145. if ( ll->testFlags(B) )
  146. {
  147. lhs = COND_EXPR::idReg (rAL, 0, &localId);
  148. pIcode->setRegDU( rAL, eDEF);
  149. }
  150. else
  151. {
  152. lhs = COND_EXPR::idReg (rAX, 0, &localId);
  153. pIcode->setRegDU( rAX, eDEF);
  154. }
  155. res.setAsgn(lhs, rhs);
  156. break;
  157. case iIMUL:
  158. rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
  159. lhs = COND_EXPR::id (*pIcode, LHS_OP, func, i, *pIcode, NONE);
  160. res.setAsgn(lhs, rhs);
  161. break;
  162. case iINC:
  163. rhs = COND_EXPR::idKte (1, 2);
  164. rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
  165. res.setAsgn(lhs, rhs);
  166. break;
  167. case iLEA:
  168. rhs = COND_EXPR::unary (ADDRESSOF, rhs);
  169. res.setAsgn(lhs, rhs);
  170. break;
  171. case iMOD:
  172. rhs = COND_EXPR::boolOp (lhs, rhs, MOD);
  173. if ( ll->testFlags(B) )
  174. {
  175. lhs = COND_EXPR::idReg (rAH, 0, &localId);
  176. pIcode->setRegDU( rAH, eDEF);
  177. }
  178. else
  179. {
  180. lhs = COND_EXPR::idReg (rDX, 0, &localId);
  181. pIcode->setRegDU( rDX, eDEF);
  182. }
  183. res.setAsgn(lhs, rhs);
  184. break;
  185. case iMOV: res.setAsgn(lhs, rhs);
  186. break;
  187. case iMUL:
  188. rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
  189. lhs = COND_EXPR::id (*pIcode, LHS_OP, this, i, *pIcode, NONE);
  190. res.setAsgn(lhs, rhs);
  191. break;
  192. case iNEG:
  193. rhs = COND_EXPR::unary (NEGATION, lhs);
  194. res.setAsgn(lhs, rhs);
  195. break;
  196. case iNOT:
  197. rhs = COND_EXPR::boolOp (NULL, rhs, NOT);
  198. res.setAsgn(lhs, rhs);
  199. break;
  200. case iOR:
  201. rhs = COND_EXPR::boolOp (lhs, rhs, OR);
  202. res.setAsgn(lhs, rhs);
  203. break;
  204. case iPOP: res.set(HLI_POP, lhs);
  205. break;
  206. case iPUSH: res.set(HLI_PUSH, lhs);
  207. break;
  208. case iRET:
  209. case iRETF:
  210. res.set(HLI_RET, NULL);
  211. break;
  212. case iSHL:
  213. rhs = COND_EXPR::boolOp (lhs, rhs, SHL);
  214. res.setAsgn(lhs, rhs);
  215. break;
  216. case iSAR: /* signed */
  217. case iSHR:
  218. rhs = COND_EXPR::boolOp (lhs, rhs, SHR); /* unsigned*/
  219. res.setAsgn(lhs, rhs);
  220. break;
  221. case iSIGNEX:
  222. res.setAsgn(lhs, rhs);
  223. break;
  224. case iSUB:
  225. rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
  226. res.setAsgn(lhs, rhs);
  227. break;
  228. case iXCHG:
  229. break;
  230. case iXOR:
  231. rhs = COND_EXPR::boolOp (lhs, rhs, XOR);
  232. res.setAsgn(lhs, rhs);
  233. break;
  234. }
  235. return res;
  236. }
  237. #endif
  238. /* Translates LOW_LEVEL icodes to HIGH_LEVEL icodes - 1st stage.
  239. * Note: this process should be done before data flow analysis, which
  240. * refines the HIGH_LEVEL icodes. */
  241. void Function::highLevelGen()
  242. {
  243. int numIcode; /* number of icode instructions */
  244. iICODE pIcode; /* ptr to current icode node */
  245. COND_EXPR *lhs, *rhs; /* left- and right-hand side of expression */
  246. uint32_t flg; /* icode flags */
  247. numIcode = Icode.size();
  248. for (iICODE i = Icode.begin(); i!=Icode.end() ; ++i)
  249. {
  250. assert(numIcode==Icode.size());
  251. pIcode = i; //Icode.GetIcode(i)
  252. LLInst *ll = pIcode->ll();
  253. if ( ll->testFlags(NOT_HLL) )
  254. pIcode->invalidate();
  255. if ((pIcode->type != LOW_LEVEL) or not pIcode->valid() )
  256. continue;
  257. flg = ll->getFlag();
  258. if ((flg & IM_OPS) != IM_OPS) /* not processing IM_OPS yet */
  259. if ((flg & NO_OPS) != NO_OPS) /* if there are opers */
  260. {
  261. if ( not ll->testFlags(NO_SRC) ) /* if there is src op */
  262. rhs = COND_EXPR::id (*pIcode->ll(), SRC, this, i, *pIcode, NONE);
  263. lhs = COND_EXPR::id (*pIcode->ll(), DST, this, i, *pIcode, NONE);
  264. }
  265. switch (ll->getOpcode())
  266. {
  267. case iADD:
  268. rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
  269. pIcode->setAsgn(lhs, rhs);
  270. break;
  271. case iAND:
  272. rhs = COND_EXPR::boolOp (lhs, rhs, AND);
  273. pIcode->setAsgn(lhs, rhs);
  274. break;
  275. case iCALL:
  276. case iCALLF:
  277. pIcode->type = HIGH_LEVEL;
  278. pIcode->hl( ll->createCall() );
  279. break;
  280. case iDEC:
  281. rhs = COND_EXPR::idKte (1, 2);
  282. rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
  283. pIcode->setAsgn(lhs, rhs);
  284. break;
  285. case iDIV:
  286. case iIDIV:/* should be signed div */
  287. rhs = COND_EXPR::boolOp (lhs, rhs, DIV);
  288. if ( ll->testFlags(B) )
  289. {
  290. lhs = COND_EXPR::idReg (rAL, 0, &localId);
  291. pIcode->setRegDU( rAL, eDEF);
  292. }
  293. else
  294. {
  295. lhs = COND_EXPR::idReg (rAX, 0, &localId);
  296. pIcode->setRegDU( rAX, eDEF);
  297. }
  298. pIcode->setAsgn(lhs, rhs);
  299. break;
  300. case iIMUL:
  301. rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
  302. lhs = COND_EXPR::id (*ll, LHS_OP, this, i, *pIcode, NONE);
  303. pIcode->setAsgn(lhs, rhs);
  304. break;
  305. case iINC:
  306. rhs = COND_EXPR::idKte (1, 2);
  307. rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
  308. pIcode->setAsgn(lhs, rhs);
  309. break;
  310. case iLEA:
  311. rhs = COND_EXPR::unary (ADDRESSOF, rhs);
  312. pIcode->setAsgn(lhs, rhs);
  313. break;
  314. case iMOD:
  315. rhs = COND_EXPR::boolOp (lhs, rhs, MOD);
  316. if ( ll->testFlags(B) )
  317. {
  318. lhs = COND_EXPR::idReg (rAH, 0, &localId);
  319. pIcode->setRegDU( rAH, eDEF);
  320. }
  321. else
  322. {
  323. lhs = COND_EXPR::idReg (rDX, 0, &localId);
  324. pIcode->setRegDU( rDX, eDEF);
  325. }
  326. pIcode->setAsgn(lhs, rhs);
  327. break;
  328. case iMOV: pIcode->setAsgn(lhs, rhs);
  329. break;
  330. case iMUL:
  331. rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
  332. lhs = COND_EXPR::id (*ll, LHS_OP, this, i, *pIcode, NONE);
  333. pIcode->setAsgn(lhs, rhs);
  334. break;
  335. case iNEG: rhs = COND_EXPR::unary (NEGATION, lhs);
  336. pIcode->setAsgn(lhs, rhs);
  337. break;
  338. case iNOT:
  339. rhs = COND_EXPR::boolOp (NULL, rhs, NOT);
  340. pIcode->setAsgn(lhs, rhs);
  341. break;
  342. case iOR:
  343. rhs = COND_EXPR::boolOp (lhs, rhs, OR);
  344. pIcode->setAsgn(lhs, rhs);
  345. break;
  346. case iPOP: pIcode->setUnary(HLI_POP, lhs);
  347. break;
  348. case iPUSH: pIcode->setUnary(HLI_PUSH, lhs);
  349. break;
  350. case iRET:
  351. case iRETF: pIcode->setUnary(HLI_RET, NULL);
  352. break;
  353. case iSHL:
  354. rhs = COND_EXPR::boolOp (lhs, rhs, SHL);
  355. pIcode->setAsgn(lhs, rhs);
  356. break;
  357. case iSAR: /* signed */
  358. case iSHR:
  359. rhs = COND_EXPR::boolOp (lhs, rhs, SHR); /* unsigned*/
  360. pIcode->setAsgn(lhs, rhs);
  361. break;
  362. case iSIGNEX: pIcode->setAsgn(lhs, rhs);
  363. break;
  364. case iSUB:
  365. rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
  366. pIcode->setAsgn(lhs, rhs);
  367. break;
  368. case iXCHG:
  369. break;
  370. case iXOR:
  371. rhs = COND_EXPR::boolOp (lhs, rhs, XOR);
  372. pIcode->setAsgn(lhs, rhs);
  373. break;
  374. }
  375. }
  376. }
  377. /* Modifies the given conditional operator to its inverse. This is used
  378. * in if..then[..else] statements, to reflect the condition that takes the
  379. * then part. */
  380. COND_EXPR *COND_EXPR::inverse ()
  381. {
  382. static condOp invCondOp[] = {GREATER, GREATER_EQUAL, NOT_EQUAL, EQUAL,
  383. LESS_EQUAL, LESS, DUMMY,DUMMY,DUMMY,DUMMY,
  384. DUMMY, DUMMY, DUMMY, DUMMY, DUMMY, DUMMY,
  385. DUMMY, DBL_OR, DBL_AND};
  386. COND_EXPR *res=0;
  387. if (type == BOOLEAN_OP)
  388. {
  389. switch ( op() )
  390. {
  391. case LESS_EQUAL: case LESS: case EQUAL:
  392. case NOT_EQUAL: case GREATER: case GREATER_EQUAL:
  393. res = this->clone();
  394. res->boolExpr.op = invCondOp[op()];
  395. return res;
  396. case AND: case OR: case XOR: case NOT: case ADD:
  397. case SUB: case MUL: case DIV: case SHR: case SHL: case MOD:
  398. return COND_EXPR::unary (NEGATION, this->clone());
  399. case DBL_AND: case DBL_OR:
  400. res = this->clone();
  401. res->boolExpr.op = invCondOp[op()];
  402. res->boolExpr.lhs=lhs()->inverse ();
  403. res->boolExpr.rhs=rhs()->inverse ();
  404. return res;
  405. } /* eos */
  406. }
  407. else if (type == NEGATION) //TODO: memleak here
  408. {
  409. return expr.unaryExp->clone();
  410. }
  411. return this->clone();
  412. /* other types are left unmodified */
  413. }
  414. /* Returns the string that represents the procedure call of tproc (ie. with
  415. * actual parameters) */
  416. std::string writeCall (Function * tproc, STKFRAME * args, Function * pproc, int *numLoc)
  417. {
  418. int i; /* counter of # arguments */
  419. string condExp;
  420. ostringstream s;
  421. s<<tproc->name<<" (";
  422. for (i = 0; i < args->sym.size(); i++)
  423. {
  424. s << walkCondExpr (args->sym[i].actual, pproc, numLoc);
  425. if (i < (args->sym.size() - 1))
  426. s << ", ";
  427. }
  428. s << ")";
  429. return s.str();
  430. }
  431. /* Displays the output of a HLI_JCOND icode. */
  432. char *writeJcond (HLTYPE h, Function * pProc, int *numLoc)
  433. {
  434. assert(h.expr());
  435. memset (buf, ' ', sizeof(buf));
  436. buf[0] = '\0';
  437. strcat (buf, "if ");
  438. COND_EXPR *inverted=h.expr()->inverse();
  439. //inverseCondOp (&h.exp);
  440. std::string e = walkCondExpr (inverted, pProc, numLoc);
  441. delete inverted;
  442. strcat (buf, e.c_str());
  443. strcat (buf, " {\n");
  444. return (buf);
  445. }
  446. /* Displays the inverse output of a HLI_JCOND icode. This is used in the case
  447. * when the THEN clause of an if..then..else is empty. The clause is
  448. * negated and the ELSE clause is used instead. */
  449. char *writeJcondInv (HLTYPE h, Function * pProc, int *numLoc)
  450. {
  451. memset (buf, ' ', sizeof(buf));
  452. buf[0] = '\0';
  453. strcat (buf, "if ");
  454. std::string e = walkCondExpr (h.expr(), pProc, numLoc);
  455. strcat (buf, e.c_str());
  456. strcat (buf, " {\n");
  457. return (buf);
  458. }
  459. string AssignType::writeOut(Function *pProc, int *numLoc)
  460. {
  461. ostringstream ostr;
  462. ostr << walkCondExpr (lhs, pProc, numLoc);
  463. ostr << " = ";
  464. ostr << walkCondExpr (rhs, pProc, numLoc);
  465. ostr << ";\n";
  466. return ostr.str();
  467. }
  468. string CallType::writeOut(Function *pProc, int *numLoc)
  469. {
  470. ostringstream ostr;
  471. ostr << writeCall (proc, args, pProc,numLoc);
  472. ostr << ";\n";
  473. return ostr.str();
  474. }
  475. string ExpType::writeOut(Function *pProc, int *numLoc)
  476. {
  477. return walkCondExpr (v, pProc, numLoc);
  478. }
  479. /* Returns a string with the contents of the current high-level icode.
  480. * Note: this routine does not output the contens of HLI_JCOND icodes. This is
  481. * done in a separate routine to be able to support the removal of
  482. * empty THEN clauses on an if..then..else. */
  483. string HLTYPE::write1HlIcode (Function * pProc, int *numLoc)
  484. {
  485. string e;
  486. ostringstream ostr;
  487. HlTypeSupport *p = get();
  488. switch (opcode)
  489. {
  490. case HLI_ASSIGN:
  491. return p->writeOut(pProc,numLoc);
  492. case HLI_CALL:
  493. return p->writeOut(pProc,numLoc);
  494. case HLI_RET:
  495. e = p->writeOut(pProc,numLoc);
  496. if (! e.empty())
  497. ostr << "return (" << e << ");\n";
  498. break;
  499. case HLI_POP:
  500. ostr << "HLI_POP ";
  501. ostr << p->writeOut(pProc,numLoc);
  502. ostr << "\n";
  503. break;
  504. case HLI_PUSH:
  505. ostr << "HLI_PUSH ";
  506. ostr << p->writeOut(pProc,numLoc);
  507. ostr << "\n";
  508. break;
  509. }
  510. return ostr.str();
  511. }
  512. int power2 (int i)
  513. /* Returns the value of 2 to the power of i */
  514. {
  515. if (i == 0)
  516. return (1);
  517. return (2 << (i-1));
  518. }
  519. /* Writes the registers/stack variables that are used and defined by this
  520. * instruction. */
  521. void ICODE::writeDU(int idx)
  522. {
  523. {
  524. ostringstream ostr;
  525. for (int i = 0; i < (INDEXBASE-1); i++)
  526. if (du.def[i])
  527. ostr << allRegs[i] << " ";
  528. if (!ostr.str().empty())
  529. printf ("Def (reg) = %s\n", ostr.str().c_str());
  530. }
  531. {
  532. ostringstream ostr;
  533. for (int i = 0; i < (INDEXBASE-1); i++)
  534. if (du.def[i])
  535. ostr << allRegs[i] << " ";
  536. if (!ostr.str().empty())
  537. printf ("Def (reg) = %s\n", ostr.str().c_str());
  538. for (int i = 0; i < INDEXBASE; i++)
  539. {
  540. if (du.use[i])
  541. ostr << allRegs[i] << " ";
  542. }
  543. if (!ostr.str().empty())
  544. printf ("Use (reg) = %s\n", ostr.str().c_str());
  545. }
  546. /* Print du1 chain */
  547. printf ("# regs defined = %d\n", du1.numRegsDef);
  548. for (int i = 0; i < MAX_REGS_DEF; i++)
  549. {
  550. if (du1.used(i))
  551. {
  552. printf ("%d: du1[%d][] = ", idx, i);
  553. #ifdef _lint
  554. for (auto ik=du1.idx[i].uses.begin(); ik!=du1.idx[i].uses.end(); ++ik)
  555. {
  556. auto j(*ik);
  557. #else
  558. for(auto j : du1.idx[i].uses)
  559. {
  560. #endif
  561. printf ("%d ", j->loc_ip);
  562. }
  563. printf ("\n");
  564. }
  565. }
  566. /* For HLI_CALL, print # parameter bytes */
  567. if (hl()->opcode == HLI_CALL)
  568. printf ("# param bytes = %d\n", hl()->call.args->cb);
  569. printf ("\n");
  570. }