home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 163_01 / cc41.c < prev    next >
Text File  |  1990-11-20  |  9KB  |  458 lines

  1. /*
  2. ** Note on conditional jumps:
  3. **
  4. ** Unfortunately, we have to generate:
  5. **   Jxx $+5
  6. **   JMP label
  7. ** so that we never have the possibility of a short jump out of range.
  8. ** It would be nice if the assembler were smart enough to do this for us.
  9. ** Failing that, we will probably have to wait for a version which generates
  10. ** OBJ modules directly to get this type of optimization in any but some
  11. ** special cases.
  12. */
  13.  
  14. /*
  15. ** print all assembler info before any code is generated
  16. */
  17. header()  {
  18.   outstr("CODESEG "); ol("SEGMENT BYTE PUBLIC 'CODE'");
  19.   ol("ASSUME CS:CODESEG,SS:DATASEG,ES:DATASEG,DS:DATASEG");
  20.   ol("DB 0"); /* assure that no procedure has an address of "NULL" */
  21.   outstr("DATASEG"); ol("SEGMENT PUBLIC 'DATA'");
  22.   dmode = 1;
  23.   ol("DB 0"); /* assure that no variable has an address of "NULL" */
  24.   }
  25.  
  26. /*
  27. ** print any assembler stuff needed at the end
  28. */
  29. trailer()   {
  30.   int k;
  31.   char c;
  32.   if(dmode) {outstr("DATASEG "); ol("ENDS");}
  33.   outstr("CODESEG "); ol("ENDS");
  34.   outstr("%OUT End of pass");
  35.   nl();
  36. #ifdef HASH
  37.   if(search("MAIN_ENT", macn, NAMESIZE+2, MACNEND, MACNBR, 0)) {
  38.     ot("END");
  39.     k=getint(cptr+NAMESIZE, 2);
  40.     if(*(macq+k) >= ' ') { /* don't output end label if null */
  41.       outbyte(' ');
  42.       outname(macq+k);
  43.       }
  44.     nl();
  45.     }
  46. #else
  47.   if(k=findmac("MAIN_ENT")) {
  48.     ot("END");
  49.     if(*(macq+k) >= ' ') { /* don't output end label if null */
  50.       outbyte(' ');
  51.       outname(macq+k);
  52.       }
  53.     nl();
  54.     }
  55. #endif
  56.   else { /* force a reference to the setup module */
  57.     ot("EXTRN ");
  58.     outname("_LOGIN");
  59.     outstr(":NEAR");
  60.     nl();
  61.     ol("END");
  62.     }
  63.   }
  64.  
  65. /*
  66. ** load # args before function call
  67. */
  68. loadargc(val) int val;  {
  69. #ifdef HASH
  70.   if(search("NOCCARGC", macn, NAMESIZE+2, MACEND, MACNBR, 0)==0) {
  71. #else
  72.   if(findmac("NOCCARGC")==0) {
  73. #endif
  74.     ot("MOV DL,");
  75.     outdec(val);
  76.     nl();
  77.     }
  78.   }
  79.  
  80. /*
  81. ** generate assembler comment delimiter
  82. */
  83. comment() {
  84.   cout(';', output);
  85.   }
  86.  
  87. /*
  88. ** generate assembler comment delimiter in staging buffer
  89. */
  90. comment2() {
  91.   outbyte(';');
  92.   }
  93.  
  94. /*
  95. ** generate a name which does not conflict with compiler reserved words
  96. */
  97. outname(name) char *name; {
  98.   outstr("Q");
  99.   outstr(name);
  100.   }
  101.  
  102. /*
  103. ** declare entry point ("PUBLIC")
  104. */
  105. entry(size) int size; {
  106.   ot("PUBLIC ");
  107.   outname(ssname);
  108.   nl();
  109.   }
  110.  
  111. /*
  112. ** generate start of global data
  113. */
  114. startglob() {
  115.   if(dmode==0) {outstr("DATASEG"); ol("SEGMENT PUBLIC 'DATA'"); dmode = 1;}
  116.   outname(ssname);
  117.   }
  118.  
  119. /*
  120. ** generate start of a function
  121. */
  122. startfun(funname) char funname[]; {
  123.   if(dmode) {outstr("DATASEG"); ol("ENDS"); dmode = 0;}
  124.   outname(funname);
  125.   ol("PROC NEAR");
  126.   ol("PUSH BP");
  127.   ol("MOV BP,SP");
  128.   }
  129.  
  130. /*
  131. ** generate end of a function
  132. */
  133. endfun(funname) char funname[]; {
  134.   outname(funname);
  135.   ol("ENDP");
  136.   }
  137.  
  138. /*
  139. ** generate start of literals from a function
  140. */
  141. startlit() {
  142.   if(dmode==0) {outstr("DATASEG"); ol("SEGMENT PUBLIC 'DATA'"); dmode = 1;}
  143.   }
  144.  
  145. /*
  146. ** declare external reference
  147. */
  148. external(name,type,ident) char *name; int type, ident; {
  149.   if(ident==FUNCTION) {
  150.     if(dmode) {outstr("DATASEG"); ol("ENDS"); dmode = 0;}
  151.     ot("EXTRN ");
  152.     outname(name);
  153.     outstr(":NEAR");
  154.     }
  155.   else {
  156.     if(dmode==0) {outstr("DATASEG"); ol("SEGMENT PUBLIC 'DATA'"); dmode = 1;}
  157.     ot("EXTRN ");
  158.     outname(name);
  159.     if((type==CCHAR) & (ident!=POINTER))
  160.       outstr(":BYTE");
  161.     else
  162.       outstr(":WORD");
  163.     }
  164.   nl();
  165.   }
  166.  
  167. /*
  168. ** fetch object indirect to primary register
  169. */
  170. indirect(lval) int lval[]; {
  171.   /*
  172.   ** (It would be advantageous if the compiler loaded addresses into the
  173.   ** secondary when it plans to follow immediately with an "indirect()".
  174.   ** Failing this, or in addition to it, "peephole()" could look for
  175.   ** combinations such as "getloc()" followed by "indirect()" and replace
  176.   ** the generated code with a direct load relative to BP.)
  177.   */
  178.   ol("MOV SI,AX");
  179.   if(lval[1]==CCHAR) {
  180.     ol("MOV AL,[SI]");
  181.     ol("CBW");
  182.     }
  183.   else ol("MOV AX,[SI]");
  184.   }
  185.  
  186. /*
  187. ** fetch a static memory cell into primary register
  188. */
  189. getmem(lval)  int lval[]; {
  190.   char *sym;
  191.   sym=lval[0];
  192.   if((sym[IDENT]!=POINTER)&(sym[TYPE]==CCHAR)) {
  193.     ot("MOV AL,");
  194.     outname(sym+NAME);
  195.     nl();
  196.     ol("CBW");
  197.     }
  198.   else {
  199.     ot("MOV AX,");
  200.     outname(sym+NAME);
  201.     nl();
  202.     }
  203.   }
  204.  
  205. /*
  206. ** fetch addr of the specified global symbol into primary register
  207. */
  208. address(sym) char *sym; {
  209.   ot("MOV AX,OFFSET ");
  210.   outname(sym+NAME);
  211.   nl();
  212.   }
  213.  
  214. /*
  215. ** fetch addr of what follows into primary register
  216. */
  217. addr2() {
  218.   ot("MOV AX,OFFSET ");
  219.   }
  220.  
  221. /*
  222. ** fetch addr of the specified local symbol into primary register
  223. */
  224. getloc(sym) char *sym; {
  225.   int displace; /* displacement from BP */
  226.   if((displace=getint(sym+OFFSET, OFFSIZE))>=0) {
  227.     ot("LEA AX,[BP]+");
  228.     outdec(displace);
  229.     }
  230.   else {
  231.     ot("LEA AX,[BP]-");
  232.     outdec(-displace);
  233.     }
  234.   nl();
  235.   }
  236.  
  237. /*
  238. ** store primary register into static cell
  239. */
  240. putmem(lval)  int lval[]; {
  241.   char *sym;
  242.   ot("MOV ");
  243.   sym=lval[0];
  244.   outname(sym+NAME);
  245.   if((sym[IDENT]!=POINTER)&(sym[TYPE]==CCHAR)) outstr(",AL");
  246.   else outstr(",AX");
  247.   nl();
  248.   }
  249.  
  250. /*
  251. ** put on the stack the type object in primary register
  252. ** (store primary register at address in secondary register)
  253. */
  254. putstk(lval) int lval[]; {
  255.   if(lval[1]==CCHAR) ol("MOV [BX],AL");
  256.   else ol("MOV [BX],AX");
  257.   }
  258.  
  259. /*
  260. ** move primary register to secondary
  261. */
  262. move() {
  263.   ol("MOV BX,AX");
  264.   }
  265.  
  266. /*
  267. ** swap primary and secondary registers
  268. */
  269. swap() {
  270.   ol("XCHG AX,BX");
  271.   }
  272.  
  273. /*
  274. ** partial instruction to get immediate value
  275. ** into primary register
  276. */
  277. immed() {
  278.   ot("MOV AX,");
  279.   }
  280.  
  281. /*
  282. ** partial instruction to get immediate operand
  283. ** into secondary register
  284. */
  285. immed2() {
  286.   ot("MOV BX,");
  287.   }
  288.  
  289. /*
  290. ** push primary register onto stack
  291. */
  292. push() {
  293.   ol("PUSH AX");
  294.   csp=csp-BPW;
  295.   }
  296.  
  297. /*
  298. ** pop stack to the secondary register
  299. */
  300. pop() {
  301.   ol("POP BX");
  302.   csp=csp+BPW;
  303.   }
  304.  
  305. /*
  306. ** swap primary register and stack
  307. */
  308. swapstk() {
  309.   ot("XCHG AX,[BP]-");
  310.   outdec(-csp);
  311.   nl();
  312.   }
  313.  
  314. /*
  315. ** process switch case statements
  316. */
  317. sw(label, value) int label, value; {
  318.   ot("CMP AX,");
  319.   outdec(value);
  320.   nl();
  321.   ol("JNE $+5");
  322.   ol("DB 0E9H"); /* force a long jump the hard way */
  323.   ot("DW ");
  324.   printlabel(label);
  325.   outstr("-$-2");
  326.   nl();
  327.   }
  328.  
  329. /*
  330. ** call specified subroutine name
  331. */
  332. call(sname) char *sname; {
  333.   ot("CALL ");
  334.   outname(sname);
  335.   nl();
  336.   }
  337.  
  338. /*
  339. ** return from subroutine
  340. */
  341. ret() {
  342.   ol("POP BP"); /* restores caller's stack frame pointer */
  343.   ol("RET"); /* return to caller */
  344.   }
  345.  
  346. /*
  347. ** perform subroutine call to value on the stack
  348. */
  349. callstk() {
  350.   ol("POP AX");
  351.   ol("CALL AX");
  352.   csp=csp+BPW;
  353.   }
  354.  
  355. /*
  356. ** jump to internal label number
  357. */
  358. jump(label) int label; {
  359.   ot("JMP ");
  360.   printlabel(label);
  361.   nl();
  362.   }
  363.  
  364. /*
  365. ** test primary register and jump if false
  366. */
  367. testjump(label) int label; {
  368.   ol("AND AX,AX");
  369.   ol("JNZ $+5");
  370.   jump(label);
  371.   }
  372.  
  373. /*
  374. ** test primary register against zero and jump if false
  375. */
  376. zerojump(oper, label, lval) int oper, label, lval[]; {
  377.   clearstage(lval[7], 0); /* purge conventional code */
  378.   oper(label);
  379.   }
  380.  
  381. /*
  382. ** define storage according to size
  383. */
  384. defstorage(size) int size; {
  385.   if(size==1) ot("DB ");
  386.   else        ot("DW ");
  387.   }
  388.  
  389. /*
  390. ** generate zeros for storage initialization (0,0, . . . or nnn DUP(0))
  391. */
  392. genzeros(count) int count; {
  393.   outdec(count);
  394.   outstr(" DUP(0)");
  395.   nl();
  396.   return 0; /* would return >0 if not all zeros could be gened on one line */
  397.   }
  398.  
  399. /*
  400. ** point to following object(s)
  401. ** (generated for initialization of static pointers, eg:
  402. **   "char *x = &"hi there"
  403. ** I think)
  404. */
  405. point() {
  406.   ol("DW $+2");
  407.   }
  408.  
  409. /*
  410. ** modify stack pointer to value given
  411. */
  412. modstk(newsp) int newsp; {
  413.   int k;
  414.   k=newsp-csp;
  415.   if(k==0) return newsp;
  416.   if(newsp==0) {
  417.     ol("MOV SP,BP");
  418.     return newsp;
  419.     }
  420.   if(k>=0) {
  421.     if(k<5) {
  422.       if(k&1) {
  423.         ol("INC SP");
  424.         k--;
  425.         }
  426.       while(k) {
  427.         ol("POP CX");
  428.         k=k-BPW;
  429.         }
  430.       return newsp;
  431.       }
  432.     }
  433.   if(k<0) {
  434.     if(k>-5) {
  435.       if(k&1) {
  436.         ol("DEC SP");
  437.         k++;
  438.         }
  439.       while(k) {
  440.         ol("PUSH CX");
  441.         k=k+BPW;
  442.         }
  443.       return newsp;
  444.       }
  445.     }
  446.   ot("LEA SP,[BP]-");
  447.   outdec(-newsp);
  448.   nl();
  449.   return newsp;
  450.   }
  451.  
  452. /*
  453. ** double primary register
  454. */
  455. doublereg() {ol("ADD AX,AX");}
  456.  
  457.  
  458.