/*       
   Copyright 1994-2003 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   02111-1307, USA.  

   You may contact the author at:

   mailto::camille@bluegrass.net

   or by snail mail at:

   David Lindauer
   850 Washburn Ave Apt 99
   Louisville, KY 40222
*/
/*
 * iout.c
 *
 * output routines for icode code gen.  Used only in optimizer tests.
 *
 */
#include        <stdio.h>
#include        "lists.h"
#include        "expr.h"
#include        "c.h"
#include				"iexpr.h"
#include 				"diag.h"
#include				"lists.h"

/*      variable initialization         */
extern HASHREC **gsyms;
extern QUAD *intermed_head;

enum e_gt { nogen, bytegen, wordgen, longgen, floatgen, doublegen, longdoublegen, srrefgen };
enum e_sg { noseg, codeseg, dataseg, bssxseg, stringseg, constseg, startupxseg,rundownxseg,cppxseg,xcpprdseg };

extern LIST *localfuncs ;
extern long nextlabel;
extern int global_flag;
extern int	prm_asmfile;
extern int prm_lines;
extern int phiused;
extern FILE *outputFile;
extern char outfile[];
extern LIST *libincludes;
extern int prm_cmangle;
extern SYM *currentfunc;

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 int phiput;

static struct slit *strtab;

/* Init module */
void outcodeini(void)
{
	gentype = nogen;
	curseg = noseg;
	outcol = 0;
	phiput = FALSE;
}
/*
 * ICODE op display handlers
 */
static void op_line(QUAD *q)
{
			if (!prm_lines)
				return;
			fprintf(outputFile,";\n; Line %d:\t%s\n;",(int)q->dc.label,(char *)q->dc.left);
}
static void op_passthrough(QUAD *q)
{
			fprintf(outputFile,"%s\n",(char *)q->dc.left);
}
static void op_label(QUAD *q)
{
		fprintf(outputFile,"L_%d:",q->dc.label);
}
static void putsingle(IMODE *ap,char *string)
{
		fprintf(outputFile,"\t%s",string);
		if (ap) {
			fputc('\t',outputFile);
			putamode(ap);
		}
}
static void op_goto(QUAD *q)
{
		fprintf(outputFile,"\tGOTO\tL_%d:PC",q->dc.label);
}
static void op_gosub(QUAD *q)
{
		putsingle(q->dc.left,"GOSUB");
}
static void op_trap(QUAD *q)
{
		putsingle(q->dc.left,"TRAP");
}
static void op_int(QUAD *q)
{
		putsingle(q->dc.left,"INT");
}
static void op_ret(QUAD *q)
{
		fprintf(outputFile,"\tRET\n");
}
static void op_rett(QUAD *q)
{
		fprintf(outputFile,"\tRETT\n");
}
static void putbin(QUAD *q, char  *str)
{
		fputc('\t',outputFile);
		putamode(q->ans);
		fprintf(outputFile," = ");
		putamode(q->dc.left);
		fprintf(outputFile," %s ",str);
		putamode(q->dc.right);
}
static void op_add(QUAD *q)
{
		putbin(q,"+");
}
static void op_sub(QUAD *q)
{
		putbin(q,"-");
}
static void op_udiv(QUAD *q)
{
		putbin(q,"U/");
}
static void op_umod(QUAD *q)
{
		putbin(q,"U%");
}
static void op_sdiv(QUAD *q)
{
		putbin(q,"S/");
}
static void op_smod(QUAD *q)
{
		putbin(q,"S%");
}
static void op_umul(QUAD *q)
{
		putbin(q,"U*");
}
static void op_smul(QUAD *q)
{
		putbin(q,"S*");
}
static void op_lsl(QUAD *q)
{
		putbin(q,"<<");
}
static void op_lsr(QUAD *q)
{
		putbin(q,"U>>");
}
static void op_asl(QUAD *q)
{
		putbin(q,"<<");
}
static void op_asr(QUAD *q)
{
		putbin(q,"S>>");
}
static void op_and(QUAD *q)
{
		putbin(q,"&");
}
static void op_or(QUAD *q)
{
		putbin(q,"|");
}
static void op_eor(QUAD *q)
{
		putbin(q,"^");
}
static void putunary(QUAD *q, char  *str)
{
		fputc('\t',outputFile);
		putamode(q->ans);
		fprintf(outputFile," = ");
		fprintf(outputFile," %s ",str);
		putamode(q->dc.left);
}
static void op_setnz(QUAD *q)
{
		putunary(q,"SETNZ");
}
static void op_neg(QUAD *q)
{
      putunary(q,"-");
}
static void op_not(QUAD *q)
{
      putunary(q,"~");
}
static void op_assn(QUAD *q)
{
		putunary(q,"");
}
static void op_genword(QUAD *q)
{
		putsingle(q->dc.left,"GENWORD");
}
static void op_coswitch(QUAD *q)
{
		fprintf(outputFile,"\tCOSWITCH(");
		putamode(q->ans);
		fputc(',',outputFile);
		putamode(q->dc.left);
		fputc(',',outputFile);
		putamode(q->dc.right);
		fputc(',',outputFile);
		fprintf(outputFile,"L_%d:PC)", q->dc.label);
}
static void op_dc(QUAD *q)
{
		fprintf(outputFile,"\tDC.L\tL_%d:PC",q->dc.label);
}
static void op_assnblock(QUAD *q)
{
		fputc('\t',outputFile);
		putamode(q->ans);
      fprintf(outputFile, " BLOCK= ") ;
		putamode(q->dc.left);
      fprintf(outputFile,"(") ;
      putamode(q->dc.right) ;
      fprintf(outputFile,")") ;
}
static void putjmp(QUAD *q,char *str)
{
		fprintf(outputFile,"\tCONDGO\tL_%d:PC ; ",q->dc.label);
		if (q->dc.left)
			putamode(q->dc.left);
		fprintf(outputFile," %s ",str);
		if (q->dc.right)
			putamode(q->dc.right);
}
static void putset(QUAD *q, char *str)
{
      putamode(q->ans) ;
      fprintf(outputFile," = ") ;
      putamode(q->dc.left) ;
      fprintf(outputFile," %s ",str) ;
      putamode(q->dc.right) ;
}
static void op_jc(QUAD *q)
{
		putjmp(q,"U<");
}
static void op_ja(QUAD *q)
{
		putjmp(q,"U>");
}
static void op_je(QUAD *q)
{
		putjmp(q,"==");
}
static void op_jnc(QUAD *q)
{
		putjmp(q,"U>=");
}
static void op_jbe(QUAD *q)
{
		putjmp(q,"U<=");
}
static void op_jne(QUAD *q)
{
		putjmp(q,"!=");
}
static void op_jl(QUAD *q)
{
		putjmp(q,"S<");
}
static void op_jg(QUAD *q)
{
		putjmp(q,"S>");
}
static void op_jle(QUAD *q)
{
		putjmp(q,"S<=");
}
static void op_jge(QUAD *q)
{
		putjmp(q,"S>=");
}
static void op_setc(QUAD *q)
{
      putset(q,"U<");
}
static void op_seta(QUAD *q)
{
      putset(q,"U>");
}
static void op_sete(QUAD *q)
{
      putset(q,"==");
}
static void op_setnc(QUAD *q)
{
      putset(q,"U>=");
}
static void op_setbe(QUAD *q)
{
      putset(q,"U<=");
}
static void op_setne(QUAD *q)
{
      putset(q,"!=");
}
static void op_setl(QUAD *q)
{
      putset(q,"S<");
}
static void op_setg(QUAD *q)
{
      putset(q,"S>");
}
static void op_setle(QUAD *q)
{
      putset(q,"S<=");
}
static void op_setge(QUAD *q)
{
      putset(q,"S>=");
}
static void op_parm(QUAD *q)
{
		fprintf(outputFile,"\tPARM\t");
		putamode(q->dc.left);
}
static void op_parmadj(QUAD *q)
{
		fprintf(outputFile,"\tPARMADJ\t");
		putamode(q->dc.left);
}
static void op_parmblock(QUAD *q)
{
		fputs("\tPARMBLOCK",outputFile);
		fprintf(outputFile,"{%d}=\t ",(int)q->dc.right);
		putamode(q->dc.left);
}
static void op_cppini(QUAD *q)
{
		fputs("\tCPPINI",outputFile);
}
static void op_block(QUAD *q)
{
		fprintf(outputFile,"\tBLOCK\t%d",q->dc.label+1);
}
static void op_livein(QUAD *q)
{
	DIAG("iout: propogated live-in node");
}
static void op_icon(QUAD *q)
{
		fputc('\t',outputFile);
		putamode(q->ans);
		fprintf(outputFile," = #%lX",q->dc.v.i);
}
static void op_fcon(QUAD *q)
{
		fputc('\t',outputFile);
		putamode(q->ans);
		fprintf(outputFile," = #%f",q->dc.v.f);
}
/* List of opcodes
 * This list MUST be in the same order as the op_ enums 
 */
static void (*oplst[])() = { /* NOPROTO */
	op_line, op_passthrough,
	op_label, op_goto, op_gosub, op_trap, op_int,op_ret, op_rett,
	op_add, op_sub, op_udiv, op_umod, op_sdiv, op_smod, op_umul, op_smul,
	op_lsl, op_lsr, op_asl, op_asr,
   op_neg, op_not, op_and, op_or, op_eor,
   op_setne, op_sete, op_setc, op_seta, op_setnc, op_setbe,
   op_setl, op_setg, op_setle, op_setge,
	op_assn, op_genword, op_coswitch, op_dc, op_assnblock,
	op_jc,op_ja,op_je,op_jnc,op_jbe,op_jne,op_jl,op_jg,op_jle,op_jge,
	op_parm, op_parmadj, op_parmblock,op_cppini,op_block,op_livein,
	op_icon, op_fcon

 };
void putsym(char *buf, SYM *sp, char *p)
{
  if (!p) {
   buf[0] = 0 ;
   return ;
  }
  if (sp->alias)
    strcpy(buf,sp->alias);
  else {
		if (sp->pascaldefn) {
			char *q=buf;
			if (prm_cmangle)
				p++;
			while (*p)
#ifdef COLDFIRE
				*q++ = *p++ ;
#else
				*q++ = toupper(*p++);
#endif
			*q = 0;
		}
		else if (sp->isstdcall) {
			if (prm_cmangle)
				p++;
			strcpy(buf,p);
		} else
    	strcpy(buf,p);
	}
}
void putconst(ENODE *offset)
/*
 *      put a constant to the outputFile file.
 */
{       
				switch( offset->nodetype )
                {
                        case en_icon: case en_lcon: case en_iucon: case en_lucon:
                        case en_ccon:
                                    fprintf(outputFile,"%lX",offset->v.i);
												break;
                        case en_llcon: case en_llucon:
                                    fprintf(outputFile,"%lX",offset->v.i);
												break;
                        case en_fcon: case en_rcon: case en_lrcon:
                        case en_fimaginarycon: case en_rimaginarycon:
                        case en_lrimaginarycon:
                                    fprintf(outputFile,"%e",offset->v.f) ;
								case en_tempref:	
												fprintf(outputFile,"TEMP%d",((SYM *)offset->v.p[0])->value.i);
												break;
								case en_autoreg:
                        fprintf(outputFile,"%s:REG",((SYM *)offset->v.sp)->name);
												break;
                case en_autocon:
                        fprintf(outputFile,"%s:LINK",((SYM *)offset->v.sp)->name);
												break;
								case en_nalabcon:
                        fprintf(outputFile,"L_%ld:RAM",offset->v.sp->value.i);
                        break;
                case en_labcon:
                        fprintf(outputFile,"L_%ld:PC",offset->v.i);
                        break;
								case en_napccon:
                        fprintf(outputFile,"%s:PC",((SYM *)offset->v.sp)->name);
                        break;
                case en_nacon:
                        fprintf(outputFile,"%s:RAM",((SYM *)offset->v.sp)->name);
                        break;
                case en_absacon:
                        fprintf(outputFile,"$%lX:ABS",((SYM *)offset->v.sp)->name);
												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:
                        fputc('-',outputFile);
                        putconst(offset->v.p[0]);
                        break;
                default:
                        DIAG("illegal constant node.");
                        break;
                }
}
void putlen(int l)
/*
 *      append the length field to a value
 */
{       
					switch( l )
                {
                case 0:
                        fprintf(outputFile,".0");
                        break;
                case 1:
                case 5:
                        fprintf(outputFile,".UB");
                        break;
								case -1:
                        fprintf(outputFile,".B");
                        break;
                case 2:
                        fprintf(outputFile,".UW");
                        break;
                case -2:
                        fprintf(outputFile,".W");
                        break;
                case 4:
                        fprintf(outputFile,".UL");
                        break;
                case -4:
                        fprintf(outputFile,".L");
                        break;
                case 6:
                        fprintf(outputFile,".ULL");
                        break;
                case -6:
                        fprintf(outputFile,".LL");
                        break;
                        case 7:
												fprintf(outputFile,".S");
												break;
								case 8:
												fprintf(outputFile,".D");
												break;
								case 10:
												fprintf(outputFile,".X");
												break;
                        case 15:
                                    fprintf(outputFile,".SI") ;
                                    break ;
                        case 16:
                                    fprintf(outputFile,".DI") ;
                                    break ;
                        case 17:
                                    fprintf(outputFile,".XI") ;
                                    break ;
                        case 20:
                                    fprintf(outputFile,".SC") ;
                                    break ;
                        case 21:
                                    fprintf(outputFile,".DC") ;
                                    break ;
                        case 22:
                                    fprintf(outputFile,".XC") ;
                                    break ;
                default:
                        DIAG("illegal length field.");
                        break;
                }
}

void putamode(IMODE *ap)
/*
 *      output a general addressing mode.
 */
{       
				/* We want to see if the compiler does anything wrong with
				 * volatiles
				 */
				if (ap->offset && ap->offset->cflags & DF_VOL)
					fputc('%',outputFile);
				switch( ap->mode )
                {
                case i_immed:
                        fputc('#',outputFile);
                        putconst(ap->offset);
												break;
								case i_ind:
                        fputc('*',outputFile);
                case i_direct:
                        putconst(ap->offset);
                        break;
								case i_rsp:
												fprintf(outputFile,"SP");
												break;
								case i_rret:
												fprintf(outputFile,"RV");
												break;
								case i_rlink:
												fprintf(outputFile,"LINK");
												break;
								case i_rstruct:
												fprintf(outputFile,"STRUCTRET");
												return;
								case i_rstructstar:
												fprintf(outputFile,"*STRUCTRET");
												return;
                default:
                        DIAG("illegal address mode.");
                        break;
                }
				if (ap->bits)
					fprintf(outputFile,"{%d:%d}",ap->startbit,ap->bits);
				putlen(ap->size);
}

void put_code(QUAD *q)
/*
 *      output a generic instruction.
 */
{       
		if (!prm_asmfile)	
			return;
		(*oplst[q->dc.opcode])(q);
  	fputc('\n',outputFile);
}
/*
 * Low level routinne to rewrite code for processor and dump it.
 * Here we only need dump
 */
void rewrite_icode(void)
{
      QUAD *q = intermed_head ;
		while (q) {
			put_code(q);
			q = q->fwd;
		}
      intermed_head = 0 ;
}

void gen_strlab(SYM *sp)
/*
 *      generate a named label.
 */
{
      char buf[100];
      putsym(buf,sp,sp->name);
		if (prm_asmfile)
       fprintf(outputFile,"%s:\n",buf);
		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 put_staticlabel(long label)
{
	put_label(label);
}

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,"\tDC.X\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 genlonglong(LLONG_TYPE val)
/*
 * Output a long value
 */
{     if (prm_asmfile)
        if( gentype == longgen && outcol < 56) {
#ifdef BCC32
                fprintf(outputFile,"\tDC.L\t0%lXH,0%lXH",val,val < 0 ? -1 : 0);
#else
                fprintf(outputFile,"\tDC.L\t0%lXH,0%lXH",val,val>>32);
#endif
                outcol += 10;
                }
        else    {
                nl();
#ifdef BCC32
                fprintf(outputFile,"\tDC.L\t0%lXH,0%lXH",val,val < 0 ? -1 : 0);
#else
                fprintf(outputFile,"\tDC.L\t0%lXH,0%lXH",val,val>>32);
#endif
                gentype = longgen;
                outcol = 25;
                }
}
void genaddress(char *string)
/*
 * Output a long value
 */
{     if (prm_asmfile)
        if( gentype == longgen && outcol < 56) {
                fprintf(outputFile,",%s",string);
                outcol += strlen(string);
                }
        else    {
                nl();
                fprintf(outputFile,"\tDC.L\t%s",string);
                gentype = longgen;
                outcol = 25;
                }
	dataofs+=4;
}
void gensrref(char *name,int val)
/*
 * Output a startup/rundown reference
 */
{
			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);
			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);
			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;
                }
	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;
        if (strtab) {
                nl();
                fprintf(outputFile,"\tSECTION\tstring\n");
                curseg = stringseg;
        }
        while( strtab != 0) {
                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 cpprdseg(void)
{     if (prm_asmfile)  
            if( curseg != xcpprdseg) {
                nl();
                fprintf(outputFile,"\tSECTION\tcpprundown\n");
                curseg = xcpprdseg;
                }
}
void xconstseg(void)
{     if (prm_asmfile)  
            if( curseg != constseg) {
                nl();
                fprintf(outputFile,"\tSECTION\tconst\n");
                curseg = cppxseg;
                }
}
void exitseg(void)
{
}
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 asm_header(void)
{
	fprintf(outputFile,";Icode test - %s\n\n",outfile);
}
void globaldef(SYM *sp)
{
	char buf[100],*q=buf,*p=sp->name;
	if (curseg == codeseg && currentfunc->pascaldefn) {
		if (prm_cmangle)
			p++;
		while(*p)
			*q++=toupper(*p++);
		*q++ = 0;
	}
	else
		strcpy(buf,p);
  fprintf(outputFile,"\tPUBLIC\t%s\n",buf);
}			
void output_alias(SYM *sp)
{
   char buf[256];
   putsym(buf,sp,sp->name) ;
  fprintf(outputFile,"%s EQU\t<%s>\n",buf,sp->alias);
}                       
int put_exfunc(SYM *sp, int notyet)
{
                  char buf[100],*q=buf,*p=sp->name;
									putsym(buf,sp,p);
              	    if (notyet) {
                	    fprintf(outputFile,"\n\t.CODE\n");
                  	  notyet = FALSE;
                   }
                   if (sp->tp->type == bt_func || sp->tp->type == bt_ifunc)
                     fprintf(outputFile,"\tEXTRN\t%s:PROC\n",buf);
                   else
                     fprintf(outputFile,"\tEXTRN\t%s:DATA\n",buf);
                   if (sp->importable)
                     fprintf(outputFile,"\timport %s %s\n",buf,sp->importfile) ;
	return notyet ;
}
int put_expfunc(SYM *sp, int notyet)
{
         char buf[256] ;
                  if (notyet) {
                        fprintf(outputFile,"\n.CODE\n") ;
    	                notyet = FALSE;
      	            }
                     putsym(buf,sp,sp->name) ;
                     fprintf(outputFile,"\texport %s\n",buf) ;
}
void putexterns(void)
/*
 * Output the fixup tables and the global/external list
 */
{       SYM     *sp;
                        int i;
				LIST *l ;
        char buf[100] ;
        if (prm_asmfile){
          int notyet = TRUE;
          nl();
          exitseg();
          for (i=0; i < HASHTABLESIZE; i++) {
            if ((sp=(SYM *) gsyms[i]) != 0) {
              while (sp) {
                 if( sp->storage_class == sc_externalfunc && sp->extflag && !(sp->tp->cflags & DF_INTRINS))
									notyet = put_exfunc(sp,notyet) ;
                 if( sp->storage_class == sc_external && sp->extflag)
                  notyet = put_exfunc(sp,notyet) ;
                 if (sp->storage_class == sc_defunc) {
                  SYM *sp1 = sp->tp->lst.head ;
                  while (sp1) {
                     if( sp1->storage_class == sc_externalfunc && sp1->extflag && !(sp1->tp->cflags & DF_INTRINS)) {
                           notyet = put_exfunc(sp1,notyet) ;
                     }
                     sp1 = sp1->next ;
                  }
                 }
                 if (sp->exportable)
                   notyet = put_expfunc(sp,notyet) ;
                 sp = sp->next;
          	  }
            }
  	      }
            
              while (localfuncs) {
								sp = localfuncs->data ;
                if( sp->storage_class == sc_externalfunc && sp->extflag && !(sp->tp->cflags & DF_INTRINS)) 
                  notyet = put_exfunc(sp,notyet) ;
                 if (sp->exportable)
                  notyet = put_expfunc(sp,notyet) ;
        	      localfuncs = localfuncs->link ;
          	  }
    	    notyet = TRUE;

  	        if (libincludes) {
    	        while (libincludes) {
      	        fprintf(outputFile,"\tINCLUDELIB\t%s\n",libincludes->data);
        	      libincludes = libincludes->link;
          	  }
            	fputc('\n',outputFile);
	          }
  	        fprintf(outputFile,"\tEND\n");
    	    }
}
