home *** CD-ROM | disk | FTP | other *** search
- /*
- * 68K/386 32-bit C compiler.
- *
- * copyright (c) 1996, David Lindauer
- *
- * This compiler is intended for educational use. It may not be used
- * for profit without the express written consent of the author.
- *
- * It may be freely redistributed, as long as this notice remains intact
- * and sources are distributed along with any executables derived from them.
- *
- * The author is not responsible for damages, either direct or consequential,
- * that may arise from use of this software.
- *
- * v1.5 August 1996
- * David Lindauer, gclind01@starbase.spd.louisville.edu
- *
- * Credits to Mathew Brandt for original K&R C compiler
- *
- */
- #include <stdio.h>
- #include "expr.h"
- #include "c.h"
- #include "gen.h"
- #include "cglbdec.h"
-
- /* variable initialization */
- extern HASHREC **globalhash;
-
- enum e_gt { nogen, bytegen, wordgen, longgen, floatgen, doublegen, longdoublegen, srrefgen };
- enum e_sg { noseg, codeseg, dataseg, bssxseg,startupxseg,rundownxseg,cppxseg };
-
- extern int prm_asmfile;
- extern int prm_lines;
- extern int phiused;
-
- int gentype = nogen; /* Current DC type */
- int curseg = noseg; /* Current seg */
- int outcol = 0; /* Curront col (roughly) */
- int dataofs; /* Offset from last label */
- char dataname[40]; /* Name of last label */
- static DATALINK *datahead, *datatail; /* links for fixup gen */
- static int phiput;
-
- /* Init module */
- void outcodeini(void)
- {
- gentype = nogen;
- curseg = noseg;
- outcol = 0;
- datahead = datatail = 0;
- phiput = FALSE;
- }
- /* List of opcodes
- * This list MUST be in the same order as the op_ enums
- */
- char *oplst[] = {
- "LINE#","SEQ@", "DC",
- "MOVE", "MOVEQ", "ADD",
- "ADDI", "ADDQ", "SUB",
- "SUBI", "SUBQ", "MULS",
- "MULU", "DIVS", "DIVU",
- "AND","ANDI","OR","ORI",
- "EOR","ASL","ASR",
- "JMP","JSR","MOVEM",
- "RTS","RTE","BRA","BEQ",
- "BNE","BLT","BLE",
- "BGT","BGE","BHI",
- "BHS","BLO","BLS",
- "TST","EXT","LEA","SWAP",
- "NEG","NOT","CMP","CLR",
- "LINK","UNLK","???LABEL???",
- "PEA","CMPI","DC","DC","BSR",
- "DIVSL","DIVUL","EXG", "TRAP","LSL","LSR",
- "BSET","BCLR","BTST","BFINS","BFEXTU","BFEXTS","BFCLR","BFTST",
- "FMOVE","FMOVEM","FADD","FSUB","FMUL","FDIV","FMOD",
- "FCMP", "FTST", "FNEG", "FBEQ","FBNE","FBGT","FBGE","FBLT","FBLE"
- };
- /*
- * Register a fixup
- */
- void datalink(int flag)
- {
- DATALINK *p;
- global_flag++; /* Global tab */
- p = xalloc(sizeof(DATALINK));
- p->string = litlate(dataname);
- p->type = flag;
- p->offset = dataofs;
- p->next = 0;
- if (datahead) {
- datatail->next = p;
- datatail=datatail->next;
- }
- else
- datahead = datatail = p;
- global_flag--;
- }
- /* Put an opcode
- */
- void putop(int op)
- {
- if (op > op_fble)
- diag("illegal opcode.");
- else
- fprintf(outputFile,"\t%s",oplst[op]);
- }
-
- void putconst(ENODE *offset)
- /*
- * put a constant to the outputFile file.
- */
- { switch( offset->nodetype )
- {
- case en_autoreg:
- case en_autocon:
- case en_icon:
- fprintf(outputFile,"$%lX",offset->v.i);
- break;
- case en_acon:
- fprintf(outputFile,"$%lX",offset->v.i);
- break;
- case en_rcon:
- fprintf(outputFile,"%f",offset->v.f);
- break;
- case en_nalabcon:
- case en_labcon:
- fprintf(outputFile,"L_%ld",offset->v.i);
- break;
- case en_napccon:
- case en_nacon:
- fprintf(outputFile,"%s",offset->v.p[0]);
- break;
- case en_absacon:
- if (isshort(offset))
- fprintf(outputFile,"($%lX).W",offset->v.p[0]);
- else
- fprintf(outputFile,"($%lX).L",offset->v.p[0]);
- break;
- case en_add:
- putconst(offset->v.p[0]);
- fprintf(outputFile,"+");
- putconst(offset->v.p[1]);
- break;
- case en_sub:
- putconst(offset->v.p[0]);
- fprintf(outputFile,"-");
- putconst(offset->v.p[1]);
- break;
- case en_uminus:
- fprintf(outputFile,"-");
- putconst(offset->v.p[0]);
- break;
- default:
- diag("illegal constant node.");
- break;
- }
- }
- void putlen(int l)
- /*
- * append the length field to an instruction.
- */
- { switch( l )
- {
- case 0:
- break; /* no length field */
- case 1:
- fprintf(outputFile,".B");
- break;
- case 2:
- fprintf(outputFile,".W");
- break;
- case 4:
- fprintf(outputFile,".L");
- break;
- case 6:
- fprintf(outputFile,".S");
- break;
- case 8:
- fprintf(outputFile,".D");
- break;
- case 10:
- fprintf(outputFile,".X");
- break;
- default:
- diag("illegal length field.");
- break;
- }
- }
-
- void putamode(AMODE *ap)
- /*
- * outputFile a general addressing mode.
- */
- { switch( ap->mode )
- {
- case am_sr:
- fprintf(outputFile, "SR");
- break;
- case am_bf:
- fprintf(outputFile," {%d:%d}",ap->preg,ap->sreg);
- break;
- case am_divsl:
- fprintf(outputFile,"D%d:D%d",ap->preg, ap->sreg);
- break;
- case am_immed:
- fprintf(outputFile,"#");
- case am_direct:
- putconst(ap->offset);
- break;
- case am_areg:
- fprintf(outputFile,"A%d",ap->preg);
- break;
- case am_dreg:
- fprintf(outputFile,"D%d",ap->preg);
- break;
- case am_freg:
- fprintf(outputFile,"FP%d",ap->preg);
- break;
- case am_ind:
- fprintf(outputFile,"(A%d)",ap->preg);
- break;
- case am_ainc:
- fprintf(outputFile,"(A%d)+",ap->preg);
- break;
- case am_adec:
- fprintf(outputFile,"-(A%d)",ap->preg);
- break;
- case am_indx:
- fprintf(outputFile,"(");
- putconst(ap->offset);
- fprintf(outputFile,",A%d)",ap->preg);
- break;
- case am_pcindx:
- fprintf(outputFile,"(");
- putconst(ap->offset);
- fprintf(outputFile,",PC)");
- break;
- case am_xpc:
- fprintf(outputFile,"(");
- putconst(ap->offset);
- fprintf(outputFile,",PC,D%d.L)",ap->preg);
- break;
- case am_indx2:
- fprintf(outputFile,"(");
- putconst(ap->offset);
- fprintf(outputFile,",A%d,D%d.L)",ap->preg,ap->sreg);
- break;
- case am_indx3:
- fprintf(outputFile,"(");
- putconst(ap->offset);
- fprintf(outputFile,",A%d,A%d.L)",ap->preg,ap->sreg);
- break;
- case am_mask:
- put_mask((int)ap->offset, ap->preg);
- break;
- case am_fmask:
- put_fmask((int)ap->offset, ap->preg);
- break;
- default:
- diag("illegal address mode.");
- break;
- }
- }
-
- void put_code(int op,int len,AMODE *aps,AMODE *apd,AMODE *ape)
- /*
- * outputFile a generic instruction.
- */
- {
- if (!prm_asmfile)
- return;
- if (op == op_line) {
- if (!prm_lines)
- return;
- fprintf(outputFile,";\n; Line %d:\t%s\n;\n",len,(char *)aps);
- return;
- }
- if( op == op_dcl)
- {
- putop(op);
- putlen(len);
- fprintf(outputFile,"\t");
- putamode(aps);
- fprintf(outputFile,"-*");
- if (apd) {
- fprintf(outputFile,"-6\n");
- putop(op);
- putlen(4);
- fprintf(outputFile,"\t");
- putamode(apd);
- }
- fprintf(outputFile,"\n");
- return;
- }
- else
- {
- putop(op);
- putlen(len);
- }
- if( aps != 0 )
- {
- fprintf(outputFile,"\t");
- if( op == op_cmp || op == op_cmpi )
- putamode( apd );
- else
- putamode(aps);
- if( apd != 0 )
- {
- if (apd->mode != am_bf)
- fprintf(outputFile,",");
- if( op == op_cmp || op == op_cmpi )
- putamode( aps );
- else
- putamode(apd);
- if (ape) {
- if (ape->mode != am_bf)
- fprintf(outputFile,",");
- putamode(ape);
- }
- }
- }
- if (op == op_dcr)
- fprintf(outputFile,"-*-6\n");
- fprintf(outputFile,"\n");
- }
-
- void put_fmask(int mask, int reverse)
- /*
- * generate a register mask for floating restore and save.
- */
- {
- unsigned put = FALSE,i,bit;
- if (!reverse) {
- bit = 0x80;
- for (i=0; i < 8; i++) {
- if (bit & (unsigned) mask) {
- if (put)
- fputc('/', outputFile);
- put = TRUE;
- putreg(i+16);
- }
- bit >>= 1;
- }
-
- }
- else{
- bit = 1;
- for (i=0; i < 8; i++) {
- if (bit & (unsigned)mask) {
- if (put)
- fputc('/', outputFile);
- put = TRUE;
- putreg(i+16);
- }
- bit <<= 1;
- }
- }
- }
- void put_mask(int mask, int reverse)
- /*
- * generate a register mask for integer restore and save.
- */
- {
- unsigned put = FALSE,i,bit;
- if (!reverse) {
- bit = 0x8000;
- for (i=0; i < 16; i++) {
- if (bit & (unsigned) mask) {
- if (put)
- fputc('/', outputFile);
- put = TRUE;
- putreg(i);
- }
- bit >>= 1;
- }
-
- }
- else{
- bit = 1;
- for (i=0; i < 16; i++) {
- if (bit & (unsigned)mask) {
- if (put)
- fputc('/', outputFile);
- put = TRUE;
- putreg(i);
- }
- bit <<= 1;
- }
- }
- }
-
- void putreg(int r)
- /*
- * generate a register name from a tempref number.
- */
- { if( r < 8 )
- fprintf(outputFile,"D%d",r);
- else if (r <16)
- fprintf(outputFile,"A%d",r - 8);
- else fprintf(outputFile,"FP%d",r-16);
- }
-
- void gen_strlab(char *s)
- /*
- * generate a named label.
- */
- {
- sprintf(dataname,"%s",s);
- if (prm_asmfile)
- fprintf(outputFile,"%s:\n",dataname);
- dataofs = 0;
- }
-
- void put_label(int lab)
- /*
- * outputFile a compiler generated label.
- */
- {
- sprintf(dataname,"L_%d",lab);
- if (prm_asmfile)
- fprintf(outputFile,"%s:\n",dataname);
- dataofs = 0;
- }
-
- void genfloat(float val)
- /*
- * Output a float value
- */
- { if (prm_asmfile)
- if( gentype == floatgen && outcol < 60) {
- fprintf(outputFile,",%f",val);
- outcol += 8;
- }
- else {
- nl();
- fprintf(outputFile,"\tDC.S\t%f",val);
- gentype = floatgen;
- outcol = 19;
- }
- dataofs+=4;
- }
-
- void gendouble(double val)
- /*
- * Output a double value
- */
- { if (prm_asmfile)
- if( gentype == doublegen && outcol < 60) {
- fprintf(outputFile,",%f",val);
- outcol += 8;
- }
- else {
- nl();
- fprintf(outputFile,"\tDC.D\t%f",val);
- gentype = doublegen;
- outcol = 19;
- }
- dataofs+=8;
- }
- void genlongdouble(long double val)
- /*
- * Output a double value
- */
- { if (prm_asmfile)
- if( gentype == longdoublegen && outcol < 60) {
- fprintf(outputFile,",%f",val);
- outcol += 8;
- }
- else {
- nl();
- fprintf(outputFile,"\tDT\t%f",val);
- gentype = longdoublegen;
- outcol = 19;
- }
- dataofs+=8;
- }
-
- void genbyte(long val)
- /*
- * Output a byte value
- */
- { if (prm_asmfile)
- if( gentype == bytegen && outcol < 60) {
- fprintf(outputFile,",$%X",val & 0x00ff);
- outcol += 4;
- }
- else {
- nl();
- fprintf(outputFile,"\tDC.B\t$%X",val & 0x00ff);
- gentype = bytegen;
- outcol = 19;
- }
- dataofs+=1;
- }
-
- void genword(long val)
- /*
- * Output a word value
- */
- { if (prm_asmfile)
- if( gentype == wordgen && outcol < 58) {
- fprintf(outputFile,",$%X",val & 0x0ffff);
- outcol += 6;
- }
- else {
- nl();
- fprintf(outputFile,"\tDC.W\t$%X",val & 0x0ffff);
- gentype = wordgen;
- outcol = 21;
- }
- dataofs+=2;
- }
-
- void genlong(long val)
- /*
- * Output a long value
- */
- { if (prm_asmfile)
- if( gentype == longgen && outcol < 56) {
- fprintf(outputFile,",$%lX",val);
- outcol += 10;
- }
- else {
- nl();
- fprintf(outputFile,"\tDC.L\t$%lX",val);
- gentype = longgen;
- outcol = 25;
- }
- dataofs+=4;
- }
- void gensrref(char *name,int val)
- {
- if (prm_asmfile)
- if( gentype == srrefgen && outcol < 56) {
- fprintf(outputFile,",%s,%d",name,val);
- outcol += strlen(name)+1;
- }
- else {
- nl();
- fprintf(outputFile,"\tDC.L\t%s,%d",name,val);
- gentype = srrefgen;
- outcol = 25;
- }
- }
-
- void genref(SYM *sp,int offset)
- /*
- * Output a reference to the data area (also gens fixups )
- */
- { char sign;
- char buf[40];
- if( offset < 0) {
- sign = '-';
- offset = -offset;
- }
- else
- sign = '+';
- sprintf(buf,"%s%c%d",sp->name,sign,offset);
- datalink(FALSE);
- if (prm_asmfile) {
- if( gentype == longgen && outcol < 55 - strlen(sp->name)) {
- fprintf(outputFile,",%s",buf);
- outcol += (11 + strlen(sp->name));
- }
- else {
- nl();
- fprintf(outputFile,"\tDC.L\t%s",buf);
- outcol = 26 + strlen(sp->name);
- gentype = longgen;
- }
- }
- dataofs+=4;
- }
- void genpcref(SYM *sp,int offset)
- /*
- * Output a reference to the code area (also gens fixups )
- */
- { char sign;
- char buf[40];
- if( offset < 0) {
- sign = '-';
- offset = -offset;
- }
- else
- sign = '+';
- sprintf(buf,"%s%c%d",sp->name,sign,offset);
- datalink(TRUE);
- if (prm_asmfile) {
- if( gentype == longgen && outcol < 55 - strlen(sp->name)) {
- fprintf(outputFile,",%s",buf);
- outcol += (11 + strlen(sp->name));
- }
- else {
- nl();
- fprintf(outputFile,"\tDC.L\t%s",buf);
- outcol = 26 + strlen(sp->name);
- gentype = longgen;
- }
- }
- dataofs+=4;
- }
-
- void genstorage(int nbytes)
- /*
- * Output bytes of storage
- */
- { if (prm_asmfile) {
- nl();
- fprintf(outputFile,"\tDS.B\t$%X\n",nbytes);
- }
- dataofs+=nbytes;
- }
-
- void gen_labref(int n)
- /*
- * Generate a reference to a label
- */
- { if (prm_asmfile)
- if( gentype == longgen && outcol < 58) {
- fprintf(outputFile,",L_%d",n);
- outcol += 6;
- }
- else {
- nl();
- fprintf(outputFile,"\tDC.L\tL_%d",n);
- outcol = 22;
- gentype = longgen;
- }
- datalink(TRUE);
- dataofs+=4;
- }
-
- int stringlit(char *s)
- /*
- * make s a string literal and return it's label number.
- */
- { struct slit *lp;
- ++global_flag; /* always allocate from global space. */
- lp = xalloc(sizeof(struct slit));
- lp->label = nextlabel++;
- lp->str = litlate(s);
- lp->next = strtab;
- strtab = lp;
- --global_flag;
- return lp->label;
- }
-
- void dumplits(void)
- /*
- * dump the string literal pool.
- */
- { char *cp;
- while( strtab != 0) {
- cseg();
- nl();
- put_label(strtab->label);
- cp = strtab->str;
- while(*cp)
- genbyte(*cp++);
- genbyte(0);
- strtab = strtab->next;
- }
- nl();
- }
-
- void nl(void)
- /*
- * New line
- */
- { if (prm_asmfile) {
- if(outcol > 0) {
- fputc('\n',outputFile);
- outcol = 0;
- gentype = nogen;
- }
- if (phiused && !phiput)
- fputc(0x1f,outputFile);
- }
- }
- /*
- * Switch to cseg
- */
- void cseg(void)
- { if (prm_asmfile)
- if( curseg != codeseg) {
- nl();
- fprintf(outputFile,"\tSECTION\tcode\n");
- curseg = codeseg;
- }
- }
- /*
- * Switch to dseg
- */
- void dseg(void)
- { if (prm_asmfile)
- if( curseg != dataseg) {
- nl();
- fprintf(outputFile,"\tSECTION\tdata\n");
- curseg = dataseg;
- }
- }
- /*
- * Switch to bssseg
- */
- void bssseg(void)
- { if (prm_asmfile)
- if( curseg != bssxseg) {
- nl();
- fprintf(outputFile,"\tSECTION\tbss\n");
- curseg = bssxseg;
- }
- }
- /*
- * Switch to startupseg
- */
- void startupseg(void)
- { if (prm_asmfile)
- if( curseg != startupxseg) {
- nl();
- fprintf(outputFile,"\tSECTION\tcstartup\n");
- curseg = startupxseg;
- }
- }
- /*
- * Switch to rundownseg
- */
- void rundownseg(void)
- { if (prm_asmfile)
- if( curseg != rundownxseg) {
- nl();
- fprintf(outputFile,"\tSECTION\tcrundown\n");
- curseg = rundownxseg;
- }
- }
- /*
- * Switch to cppseg
- */
- void cppseg(void)
- { if (prm_asmfile)
- if( curseg != cppxseg) {
- nl();
- fprintf(outputFile,"\tSECTION\tcppinit\n");
- curseg = cppxseg;
- }
- }
- void gen_virtual(char *name)
- {
- if (prm_asmfile) {
- nl();
- fprintf(outputFile,"@%s\tVIRTUAL",name);
- }
- }
- void gen_endvirtual(char *name)
- {
- if (prm_asmfile) {
- nl();
- fprintf(outputFile,"@%s\tENDVIRTUAL",name);
- }
- }
- void genlongref(DATALINK *p)
- /*
- * Generate a reference reference for fixup tables
- */
- {
- if( gentype == longgen && outcol < 56) {
- fprintf(outputFile,",%s+$%X",p->string,p->offset);
- outcol += 10;
- }
- else {
- nl();
- fprintf(outputFile,"\tDC.L\t%s+$%X",p->string,p->offset);
- gentype = longgen;
- outcol = 25;
- }
- }
- void putexterns(void)
- /*
- * Output the fixup tables and the global/external list
- */
- { SYM *sp;
- DATALINK *p;
- int i;
- if (prm_asmfile){
- int started = FALSE;
- p = datahead;
- while (p) {
- if (p->type) {
- if (!started) {
- nl();
- fprintf(outputFile,"\tSECTION\tcodefix\n");
- started = TRUE;
- }
- genlongref(p);
- }
- p = p->next;
- }
- started = FALSE;
- p = datahead;
- while (p) {
- if (!p->type) {
- if (!started) {
- nl();
- fprintf(outputFile,"\tSECTION\tdatafix\n");
- started = TRUE;
- }
- genlongref(p);
- }
- p = p->next;
- }
- nl();
- for (i=0; i < HASHTABLESIZE; i++) {
- if ((sp=(SYM *) globalhash[i]) != 0) {
- while (sp) {
- if( sp->storage_class == sc_external && sp->extflag)
- fprintf(outputFile,"\tXREF\t%s\n",sp->name);
- else if( sp->storage_class == sc_global )
- fprintf(outputFile,"\tXDEF\t%s\n",sp->name);
- sp = sp->next;
- }
- }
- }
- }
- }