home *** CD-ROM | disk | FTP | other *** search
/ messroms.de / 2007-01-13_www.messroms.de.zip / VZ200 / TOOLS / ZCCSRC.ZIP / scc / codez80.c next >
C/C++ Source or Header  |  2000-03-09  |  11KB  |  760 lines

  1. /*    File code8080.c: 2.2 (84/08/31,10:05:09) */
  2. /*% cc -O -c %
  3.  *
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include "defs.h"
  8. #include "data.h"
  9. #include "proto.h"
  10.  
  11. /*
  12.  *    Some predefinitions:
  13.  *
  14.  *    INTSIZE is the size of an integer in the target machine
  15.  *    BYTEOFF is the offset of an byte within an integer on the
  16.  *        target machine. (ie: 8080,pdp11 = 0, 6809 = 1, 360 = 3)
  17.  *    This compiler assumes that an integer is the SAME length as
  18.  *    a pointer - in fact, the compiler uses INTSIZE for both.
  19.  */
  20. #define    INTSIZE    2
  21. #define    BYTEOFF    0
  22.  
  23. int savestkp;
  24.  
  25. /* Print all assembler info before any code is generated */
  26. void header(char *n)
  27. {
  28.     outstr(";\tSmall C z80;\n;\tCoder (2.5,00/03/03)\n;");
  29.     FEvers();
  30.     nl();
  31.     ol(".globl\t.gchar,.gint,.pchar,.pint,.bool,.sxt,.or,.and,.xor");
  32.     ol(".globl\t.eq,.ne,.gt,.le,.ge,.lt,.uge,.ult,.ugt,.ule");
  33.     ol(".globl\t.asr,.asl,.sub,.neg,.com,.lneg,.mul,.div,.mod");
  34.     ol(".globl\t.case");
  35.     outstr("\t.module");
  36.     ol(n);
  37. }
  38.  
  39. /* New line */
  40. void nl(void)
  41. {
  42.     outbyte(EOL);
  43. }
  44.  
  45. /* Default path to prepend to includes */
  46. char *inclib(void)
  47. {
  48.     return ("");
  49. }
  50.  
  51. /* Initialize macros */
  52. void initmac(void)
  53. {
  54.     defmac("Z80\t1");
  55.     defmac("smallc\t1");
  56. }
  57.  
  58. /* Return aligned address */
  59. int galign(int t)
  60. {
  61.     return (t);
  62. }
  63.  
  64. /* Return size of an integer */
  65. int intsize(void)
  66. {
  67.     return (INTSIZE);
  68. }
  69.  
  70. /*
  71.  *    Return offset of less significant byte within word
  72.  *    (ie: 8080 & pdp11 is 0, 6809 is 1, 360 is 3)
  73.  */
  74. int byteoff(void)
  75. {
  76.     return (BYTEOFF);
  77. }
  78.  
  79. /* Output internal generated label prefix */
  80. void olprfix(void)
  81. {
  82.     outbyte('.');
  83. }
  84.  
  85. /* Output a label definition terminator */
  86. void col(void)
  87. {
  88.     outbyte(':');
  89. }
  90.  
  91. /* Begin a comment line for the assembler */
  92. void comment(void)
  93. {
  94.     outbyte(';');
  95. }
  96.  
  97. /* Emit user label prefix */
  98. void prefix(void)
  99. {
  100. }
  101.  
  102.  
  103. /* Print any assembler stuff needed after all code */
  104. void trailer(void)
  105. {
  106. }
  107.  
  108. /* Function prologue */
  109. void prologue(void)
  110. {
  111. }
  112.  
  113. #ifdef FRAME_IX
  114. /* set up frame pointer */
  115. int frame(void)
  116. {
  117.     ol("push\tix");
  118.     ol("ld\tix, #0");   /* make ix point to where sp was before push */
  119.     ol("add\tix, sp");
  120.     stkp = stkp - INTSIZE;
  121.     savestkp = stkp;
  122.     return (INTSIZE);
  123. }
  124. #endif
  125.  
  126. /* text (code) segment */
  127. void gtext(void)
  128. {
  129.     ol(".area\t_CODE");
  130. }
  131.  
  132. /* data segment */
  133. void gdata(void)
  134. {
  135.     ol(".area\t_DATA");
  136. }
  137.  
  138. /* bss segment */
  139. void gbss(void)
  140. {
  141.     ol(".area\t_BSS");
  142. }
  143.  
  144. /* Output the variable symbol at scptr as an extrn or a public */
  145. void ppubext(char *scptr)
  146. {
  147.     if (cptr[STORAGE] == STATIC)
  148.         return;
  149.     ot(scptr[STORAGE] == EXTERN ? ".globl\t" : ".globl\t");
  150.     prefix();
  151.     outstr(scptr);
  152.     nl();
  153. }
  154.  
  155. /* Output the function symbol at scptr as an extrn or a public */
  156. void fpubext(char *scptr)
  157. {
  158.     if (scptr[STORAGE] == STATIC)
  159.         return;
  160.     ot(scptr[OFFSET] == FUNCTION ? ".globl\t" : ".globl\t");
  161.     prefix();
  162.     outstr(scptr);
  163.     nl();
  164. }
  165.  
  166. /* Output a decimal number to the assembler file */
  167. void onum(int num)
  168. {
  169.     outdec(num);        /* pdp11 needs a "." here */
  170. }
  171.  
  172.  
  173. /* Fetch a static memory cell into the primary register */
  174. void getmem(char *sym)
  175. {
  176.     if ((sym[IDENT] != POINTER) & (sym[TYPE] == CCHAR))
  177.     {
  178.         ot("ld\ta,(");
  179.         outstr(sym + NAME);
  180.         outbyte(')');
  181. #ifdef    FRAME_IX
  182.         ot(";static");
  183. #endif
  184.         nl();
  185.         gcall(".sxt");
  186.     }
  187.     else
  188.     {
  189.         ot("ld\thl,(");
  190.         outstr(sym + NAME);
  191.         outbyte(')');
  192. #ifdef    FRAME_IX
  193.         ot(";static");
  194. #endif
  195.         nl();
  196.     }
  197. }
  198.  
  199. /*
  200.  *    fetch the address of the specified symbol into the primary register
  201.  */
  202. void getloc(char *sym)
  203. {
  204.     int i;
  205.  
  206.     immed();
  207.     if (sym[STORAGE] == LSTATIC)
  208.     {
  209.         printlabel(glint(sym));
  210. #ifdef    FRAME_IX
  211.         ot(";static");
  212. #endif
  213.         nl();
  214.     }
  215.     else
  216.     {
  217.         outdec(glint(sym) - stkp);
  218. #ifdef    FRAME_IX
  219.         /* generate the annotation only if in range of (ix) addressing */
  220.         if ((i = glint(sym) - savestkp) >= -128 && i <= 127)
  221.         {
  222.             ot(";");
  223.             outdec(i);
  224.             outstr("(ix) [");
  225.             outstr(sym);
  226.             outstr("]");
  227.         }
  228. #endif
  229.         nl();
  230.         ol("add\thl,sp");
  231.     }
  232. }
  233.  
  234. /*
  235.  *    store the primary register into the specified static memory cell
  236.  */
  237. void putmem(char *sym)
  238. {
  239.     if ((sym[IDENT] != POINTER) & (sym[TYPE] == CCHAR))
  240.     {
  241.         ol("ld\ta,l");
  242.         ot("ld\t(");
  243.         outstr(sym + NAME);
  244.         outstr("),a");
  245.         nl();
  246.     }
  247.     else
  248.     {
  249.         ot("ld\t(");
  250.         outstr(sym + NAME);
  251. #ifdef    FRAME_IX
  252.         outstr("),hl\t;static");
  253. #else
  254.         outstr("),hl");
  255. #endif
  256.         nl();
  257.     }
  258. }
  259.  
  260. /*
  261.  *    store the specified object type in the primary register
  262.  *    at the address on the top of the stack
  263.  */
  264. void putstk(char typeobj)
  265. {
  266.     gpop();
  267.     if (typeobj == CCHAR)
  268.         gcall(".pchar");
  269.     else
  270.         gcall(".pint");
  271. }
  272.  
  273. /*
  274.  *    fetch the specified object type indirect through the primary
  275.  *    register into the primary register
  276.  */
  277. void indirect(char typeobj)
  278. {
  279.     if (typeobj == CCHAR)
  280.         gcall(".gchar");
  281.     else
  282.         gcall(".gint");
  283. }
  284.  
  285. /*
  286.  *    swap the primary and secondary registers
  287.  */
  288. void swap(void)
  289. {
  290.     ol("ex\tde,hl");
  291. }
  292.  
  293. /*
  294.  *    print partial instruction to get an immediate value into
  295.  *    the primary register
  296.  */
  297. void immed(void)
  298. {
  299.     ot("ld\thl,#");
  300. }
  301.  
  302. /*
  303.  *    push the primary register onto the stack
  304.  */
  305. void gpush(void)
  306. {
  307.     ol("push\thl");
  308.     stkp = stkp - INTSIZE;
  309. }
  310.  
  311. /*
  312.  *    pop the top of the stack into the secondary register
  313.  */
  314. void gpop(void)
  315. {
  316.     ol("pop\tde");
  317.     stkp = stkp + INTSIZE;
  318. }
  319.  
  320. /*
  321.  *    swap the primary register and the top of the stack
  322.  */
  323. void swapstk(void)
  324. {
  325.     ol("ex\t(sp),hl");
  326. }
  327.  
  328. /*
  329.  *    call the specified subroutine name
  330.  */
  331. void gcall(char *sname)
  332. {
  333.     ot("call\t");
  334.     outstr(sname);
  335.     nl();
  336. }
  337.  
  338. /*
  339.  *    return from subroutine
  340.  */
  341. void gret(void)
  342. {
  343.     if (frameix)
  344.         ol("pop\tix");
  345.     ol("ret");
  346. }
  347.  
  348. /*
  349.  *    perform subroutine call to value on top of stack
  350.  */
  351. void callstk(void)
  352. {
  353.     immed();
  354.     outstr("+5");
  355.     nl();
  356.     swapstk();
  357.     ol("jp\t(hl)");
  358.     stkp = stkp + INTSIZE;
  359. }
  360.  
  361. /*
  362.  *    jump to specified internal label number
  363.  */
  364. void jump(int label)
  365. {
  366.     ot("j\t");
  367.     printlabel(label);
  368.     nl();
  369. }
  370.  
  371. /*
  372.  *    test the primary register and jump if false to label
  373.  */
  374. void testjump(int label, int ft)
  375. {
  376.     ol("ld\ta,h");
  377.     ol("or\tl");
  378.     if (ft)
  379.         ot("j\tnz,");
  380.     else
  381.         ot("j\tz,");
  382.     printlabel(label);
  383.     nl();
  384. }
  385.  
  386. /*
  387.  *    print pseudo-op  to define a byte
  388.  */
  389. void defbyte(void)
  390. {
  391.     ot(".db\t");
  392. }
  393.  
  394. /*
  395.  *    print pseudo-op to define storage
  396.  */
  397. void defstorage(void)
  398. {
  399.     ot(".ds\t");
  400. }
  401.  
  402. /*
  403.  *    print pseudo-op to define a word
  404.  */
  405. void defword(void)
  406. {
  407.     ot(".dw\t");
  408. }
  409.  
  410. /*
  411.  *    modify the stack pointer to the new value indicated
  412.  */
  413. int modstk(int newstkp)
  414. {
  415.     int k;
  416.  
  417.     k = galign(newstkp - stkp);
  418.     if (k == 0)
  419.         return (newstkp);
  420.     if (k > 0)
  421.     {
  422.         if (k < 8)
  423.         {
  424.             if (k & 1)
  425.             {
  426.                 ol("inc\tsp");
  427.                 k--;
  428.             }
  429.             while (k)
  430.             {
  431.                 ol("pop\tbc");
  432.                 k = k - INTSIZE;
  433.             }
  434.             return (newstkp);
  435.         }
  436.     }
  437.     else
  438.     {
  439.         if (k > -8)
  440.         {
  441.             if (k & 1)
  442.             {
  443.                 ol("dec\tsp");
  444.                 k++;
  445.             }
  446.             while (k)
  447.             {
  448.                 ol("push\tbc");
  449.                 k = k + INTSIZE;
  450.             }
  451.             return (newstkp);
  452.         }
  453.     }
  454.     swap();
  455.     immed();
  456.     outdec(k);
  457.     nl();
  458.     ol("add\thl,sp");
  459.     ol("ld\tsp,hl");
  460.     swap();
  461.     return (newstkp);
  462. }
  463.  
  464. /*
  465.  *    multiply the primary register by INTSIZE
  466.  */
  467. void gaslint(void)
  468. {
  469.     ol("add\thl,hl");
  470. }
  471.  
  472. /*
  473.  *    divide the primary register by INTSIZE
  474.  */
  475. void gasrint(void)
  476. {
  477. #if 1
  478.     ol("srl\th");
  479.     ol("rr\tl");
  480. #else
  481.     gpush();                           /* push primary in prep for gasr */
  482.     immed();
  483.     onum(1);
  484.     nl();
  485.     gasr();                               /* divide by two */
  486. #endif
  487. }
  488.  
  489. /*
  490.  *    Case jump instruction
  491.  */
  492. void gjcase(void)
  493. {
  494.     ot("jp\t.case");
  495.     nl();
  496. }
  497.  
  498. /*
  499.  *    add the primary and secondary registers
  500.  *    if lval2 is int pointer and lval is not, scale lval
  501.  */
  502. void gadd(int *lval, int *lval2)
  503. {
  504.     gpop();
  505.     if (dbltest(lval2, lval))
  506.     {
  507.         swap();
  508.         gaslint();
  509.         swap();
  510.     }
  511.     ol("add\thl,de");
  512. }
  513.  
  514. /*
  515.  *    subtract the primary register from the secondary
  516.  */
  517. void gsub(void)
  518. {
  519.     gpop();
  520.     gcall(".sub");
  521. }
  522.  
  523. /*
  524.  *    multiply the primary and secondary registers
  525.  *    (result in primary)
  526.  */
  527. void gmult(void)
  528. {
  529.     gpop();
  530.     gcall(".mul");
  531. }
  532.  
  533. /*
  534.  *    divide the secondary register by the primary
  535.  *    (quotient in primary, remainder in secondary)
  536.  */
  537. void gdiv(void)
  538. {
  539.     gpop();
  540.     gcall(".div");
  541. }
  542.  
  543. /*
  544.  *    compute the remainder (mod) of the secondary register
  545.  *    divided by the primary register
  546.  *    (remainder in primary, quotient in secondary)
  547.  */
  548. void gmod(void)
  549. {
  550.     gpop();
  551.     gcall(".mod");
  552. }
  553.  
  554. /*
  555.  *    inclusive 'or' the primary and secondary registers
  556.  */
  557. void gor(void)
  558. {
  559.     gpop();
  560.     gcall(".or");
  561. }
  562.  
  563. /*
  564.  *    exclusive 'or' the primary and secondary registers
  565.  */
  566. void gxor(void)
  567. {
  568.     gpop();
  569.     gcall(".xor");
  570. }
  571.  
  572. /*
  573.  *    'and' the primary and secondary registers
  574.  */
  575. void gand(void)
  576. {
  577.     gpop();
  578.     gcall(".and");
  579. }
  580.  
  581. /*
  582.  *    arithmetic shift right the secondary register the number of
  583.  *    times in the primary register
  584.  *    (results in primary register)
  585.  */
  586. void gasr(void)
  587. {
  588.     gpop();
  589.     gcall(".asr");
  590. }
  591.  
  592. /*
  593.  *    arithmetic shift left the secondary register the number of
  594.  *    times in the primary register
  595.  *    (results in primary register)
  596.  */
  597. void gasl(void)
  598. {
  599.     gpop();
  600.     gcall(".asl");
  601. }
  602.  
  603. /*
  604.  *    two's complement of primary register
  605.  */
  606. void gneg(void)
  607. {
  608.     gcall(".neg");
  609. }
  610.  
  611. /*
  612.  *    logical complement of primary register
  613.  */
  614. void glneg(void)
  615. {
  616.     gcall(".lneg");
  617. }
  618.  
  619. /*
  620.  *    one's complement of primary register
  621.  */
  622. void gcom(void)
  623. {
  624.     gcall(".com");
  625. }
  626.  
  627. /*
  628.  *    Convert primary value into logical value (0 if 0, 1 otherwise)
  629.  */
  630. void gbool(void)
  631. {
  632.     gcall(".bool");
  633. }
  634.  
  635. /*
  636.  *    increment the primary register by 1 if char, INTSIZE if int
  637.  */
  638. void ginc(int lval[])
  639. {
  640.     ol("inc\thl");
  641.     if (lval[2] == CINT)
  642.         ol("inc\thl");
  643. }
  644.  
  645. /*
  646.  *    decrement the primary register by one if char, INTSIZE if int
  647.  */
  648. void gdec(int lval[])
  649. {
  650.     ol("dec\thl");
  651.     if (lval[2] == CINT)
  652.         ol("dec\thl");
  653. }
  654.  
  655. /*
  656.  *    following are the conditional operators.
  657.  *    they compare the secondary register against the primary register
  658.  *    and put a literl 1 in the primary if the condition is true,
  659.  *    otherwise they clear the primary register
  660.  */
  661.  
  662. /*
  663.  *    equal
  664.  */
  665. void geq(void)
  666. {
  667.     gpop();
  668.     gcall(".eq");
  669. }
  670.  
  671. /*
  672.  *    not equal
  673.  */
  674. void gne(void)
  675. {
  676.     gpop();
  677.     gcall(".ne");
  678. }
  679.  
  680. /*
  681.  *    less than (signed)
  682.  */
  683. void glt(void)
  684. {
  685.     gpop();
  686.     gcall(".lt");
  687. }
  688.  
  689. /*
  690.  *    less than or equal (signed)
  691.  */
  692. void gle(void)
  693. {
  694.     gpop();
  695.     gcall(".le");
  696. }
  697.  
  698. /*
  699.  *    greater than (signed)
  700.  */
  701. void ggt(void)
  702. {
  703.     gpop();
  704.     gcall(".gt");
  705. }
  706.  
  707. /*
  708.  *    greater than or equal (signed)
  709.  */
  710. void gge(void)
  711. {
  712.     gpop();
  713.     gcall(".ge");
  714. }
  715.  
  716. /*
  717.  *    less than (unsigned)
  718.  */
  719. void gult(void)
  720. {
  721.     gpop();
  722.     gcall(".ult");
  723. }
  724.  
  725. /*
  726.  *    less than or equal (unsigned)
  727.  */
  728. void gule(void)
  729. {
  730.     gpop();
  731.     gcall(".ule");
  732. }
  733.  
  734. /*
  735.  *    greater than (unsigned)
  736.  */
  737. void gugt(void)
  738. {
  739.     gpop();
  740.     gcall(".ugt");
  741. }
  742.  
  743. /*
  744.  *    greater than or equal (unsigned)
  745.  */
  746. void guge(void)
  747. {
  748.     gpop();
  749.     gcall(".uge");
  750. }
  751.  
  752. /* Squirrel away argument count in a register that modstk doesn't touch. */
  753. void gnargs(int d)
  754. {
  755.     ot("ld\ta,#");
  756.     onum(d);
  757.     nl();
  758. }
  759.  
  760.