/*                         
 * 68K/386 32-bit C compiler.
 *
 * copyright (c) 1997, 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 either the original sources or derived sources 
 * are distributed along with any executables derived from the originals.
 *
 * The author is not responsible for any damages that may arise from use
 * of this software, either idirect or consequential.
 *
 * V2.05 June 2002
 * David Lindauer, camille@bluegrass.net
 *
 * Credits to Mathew Brandt for original K&R C compiler
 *
 */
#include        <stdio.h>
#include				<ctype.h>
#include				<string.h>
#include        "lists.h"
#include        "expr.h"
#include        "c.h"
#include        "gen68.h"
#include 				"diag.h"

/*      variable initialization         */
extern int global_flag;
extern SYM *currentfunc;
extern HASHREC **gsyms;
extern OCODE *peep_insert, *peep_head, *peep_tail;
extern int prm_rel;
extern long nextlabel;
extern FILE *outputFile;
extern int	prm_asmfile;
extern int prm_lines;
extern int phiused;
extern int prm_cmangle;
extern int prm_optmult ;
extern LIST *localfuncs ;
extern LIST *libincludes ;

static struct slit *strtab;
enum e_gt  gentype = nogen;		/* Current DC type */
enum e_sg	 curseg = noseg;		/* Current seg */
int        outcol = 0;				/* Curront col (roughly) */
int 			 dataofs;						/* Offset from last label */
SYM *datasp;									/* Symbol of last named label */
static DATALINK *datahead, *datatail;	/* links for fixup gen */
static int phiput;
static LIST *mpthunklist;

ASMREG reglst[] = {
	{ 0 , 0 , 0 },
};
/* List of opcodes
 * This list MUST be in the same order as the op_ enums 
 */
ASMNAME oplst[] = {
	{ "?reserved",op_reserved,0 },
	{ "?line#",op_reserved,0 },
	{ "?seq@",op_reserved,0 },
	{ "?slit",op_reserved,0 },
	{ "?label",op_reserved,0 },
	{ "?flabel",op_reserved,0 },
	{ "dc",op_reserved,0 },
	{ "?void", op_reserved, 0 },
	{ "dc",op_reserved,0 },
	{ "dc",op_reserved,0 },
	{ "abcd",op_abcd,OPE_NEGBCD },
	{ "add",op_add,OPE_MATH },
	{ "adda",op_adda,OPE_AMATH },
	{ "addi",op_addi,OPE_IMATH },
	{ "addq",op_addq,OPE_QMATH },
	{ "addx",op_addx,OPE_NEGBCD },
	{ "and",op_and,OPE_LOG },
	{ "andi",op_andi,OPE_ILOG },
	{ "asl",op_asl,OPE_SHIFT },
	{ "asr",op_asr,OPE_SHIFT },
	{ "bra",op_bra,OPE_BRA },
	{ "beq",op_beq,OPE_BRA },
	{ "bne",op_bne,OPE_BRA },
	{ "blt",op_blt,OPE_BRA },
	{ "ble",op_ble,OPE_BRA },
	{ "bgt",op_bgt,OPE_BRA },
	{ "bge",op_bge,OPE_BRA },
	{ "bhi",op_bhi,OPE_BRA },
	{ "bhs",op_bhs,OPE_BRA },
	{ "blo",op_blo,OPE_BRA },
	{ "bls",op_bls,OPE_BRA },
	{ "bsr",op_bsr,OPE_BRA },
	{ "bcc", op_bcc,OPE_BRA },
	{ "bcs", op_bcs,OPE_BRA },
	{ "bmi", op_bmi,OPE_BRA },
	{ "bpl", op_bpl,OPE_BRA },
	{ "bvc", op_bvc,OPE_BRA },
	{ "bvs", op_bvs,OPE_BRA },
	{ "bchg",op_bchg,OPE_BIT },
	{ "bclr",op_bclr,OPE_BIT },
	{ "bfchg",op_bfchg,OPE_BF1 },
	{ "bfclr",op_bfclr,OPE_BF1 },
	{ "bfexts",op_bfexts,OPE_BF2 },
	{ "bfextu",op_bfextu,OPE_BF2 },
	{ "bfffo",op_bfffo,OPE_BF2 },
	{ "bfins",op_bfins,OPE_BF3 },
	{ "bfset",op_bfset,OPE_BF1 },
	{ "bftst",op_bftst,OPE_BF1 },
	{ "bkpt", op_bkpt,0 },
	{ "bset",op_bset,OPE_BIT },
	{ "btst",op_btst,OPE_BIT },
	{ "chk",op_chk,OPE_EAD },
	{ "chk2",op_chk2,OPE_EAR },
	{ "clr",op_clr,OPE_EA },
	{ "cmp",op_cmp,OPE_CMP },
	{ "cmpa",op_cmpa,OPE_EAA },
	{ "cmpi",op_cmpi,OPE_IEA },
	{ "cmpm",op_cmpm,OPE_POSBCD },
	{ "cmp2",op_cmp2,OPE_EAR },
	{ "dbeq",op_dbeq,OPE_DBR },
	{ "dbne",op_dbne,OPE_DBR },
	{ "dblt",op_dblt,OPE_DBR },
	{ "dble",op_dble,OPE_DBR },
	{ "dbgt",op_dbgt,OPE_DBR },
	{ "dbge",op_dbge,OPE_DBR },
	{ "dbhi",op_dbhi,OPE_DBR },
	{ "dbhs",op_dbhs,OPE_DBR },
	{ "dblo",op_dblo,OPE_DBR },
	{ "dbls",op_dbls,OPE_DBR },
	{ "dbsr",op_dbsr,OPE_DBR },
	{ "dbcc", op_dbcc,OPE_DBR },
	{ "dbcs", op_dbcs,OPE_DBR },
	{ "dbmi", op_dbmi,OPE_DBR },
	{ "dbpl", op_dbpl,OPE_DBR },
	{ "dbvc", op_dbvc,OPE_DBR },
	{ "dbvs", op_dbvs,OPE_DBR },
	{ "dbt", op_dbt,OPE_DBR },
	{ "dbf", op_dbf,OPE_DBR },
	{ "dbra",op_dbra,OPE_DBR },
	{ "divs",op_divs,OPE_DIV },
	{ "divu",op_divu,OPE_DIV },
	{ "divsl",op_divsl,OPE_DIVL },
	{ "divul",op_divul,OPE_DIVL },
	{ "eor",op_eor,OPE_EOR },
	{ "eori",op_eori,OPE_ILOG },
	{ "exg",op_exg,OPE_RRL },
	{ "ext",op_ext,OPE_EXT },
	{ "extb",op_extb,OPE_EXTB },
	{ "illegal", op_illegal, 0 },
	{ "jmp",op_jmp,OPE_EA },
	{ "jsr",op_jsr,OPE_EA },
	{ "lea",op_lea,OPE_EAA },
	{ "link",op_link,OPE_AI },
	{ "lsl",op_lsl,OPE_SHIFT },
	{ "lsr",op_lsr,OPE_SHIFT },
	{ "move",op_move,OPE_MOVE },
	{ "movea",op_movea,OPE_MOVEA },
	{ "movec",op_movec,OPE_MOVEC },
	{ "movem",op_movem,OPE_MOVEM },
	{ "movep",op_movep,OPE_MOVEP },
	{ "moveq",op_moveq,OPE_MOVEQ },
	{ "moves",op_moves,OPE_MOVES },
	{ "muls",op_muls,OPE_MUL },
	{ "mulu",op_mulu,OPE_MUL },
	{ "nbcd",op_nbcd,OPE_EAB },
	{ "neg",op_neg,OPE_EA },
	{ "negx",op_negx,OPE_EA },
	{ "nop",op_nop,0 },
	{ "not",op_not,OPE_EA },
	{ "or",op_or,OPE_LOG },
	{ "ori",op_ori,OPE_ILOG },
	{ "pack",op_pack,OPE_PACK },
	{ "pea",op_pea,OPE_EA },
   { "rems",op_rems,OPE_DIV },
   { "remu",op_remu,OPE_DIV },
	{ "reset",op_reset,0 },
	{ "rol",op_rol,OPE_SHIFT },
	{ "ror",op_ror,OPE_SHIFT },
	{ "roxl",op_roxl,OPE_SHIFT },
	{ "roxr",op_roxr,OPE_SHIFT },
	{ "rtd",op_rtd,OPE_I },
	{ "rte",op_rte,0 },
	{ "rtr",op_rtr,0 },
	{ "rts",op_rts,0 },
	{ "sbcd",op_sbcd,0 },
	{ "seq",op_seq,OPE_SET },
	{ "sne",op_sne,OPE_SET },
	{ "slt",op_slt,OPE_SET },
	{ "sle",op_sle,OPE_SET },
	{ "sgt",op_sgt,OPE_SET },
	{ "sge",op_sge,OPE_SET },
	{ "shi",op_shi,OPE_SET },
	{ "shs",op_shs,OPE_SET },
	{ "slo",op_slo,OPE_SET },
	{ "sls",op_sls,OPE_SET },
	{ "ssr",op_ssr,OPE_SET },
	{ "scc", op_scc,OPE_SET },
	{ "scs", op_scs,OPE_SET },
	{ "smi", op_smi,OPE_SET },
	{ "spl", op_spl,OPE_SET },
	{ "svc", op_svc,OPE_SET },
	{ "svs", op_svs,OPE_SET },
	{ "st", op_st,OPE_SET },
	{ "sf", op_sf,OPE_SET },
	{ "sub",op_sub,OPE_MATH },
	{ "stop",op_stop,0 },
	{ "suba",op_suba,OPE_AMATH },
	{ "subi",op_subi,OPE_IMATH },
	{ "subq",op_subq,OPE_QMATH },
	{ "subx",op_subx,OPE_NEGBCD },
	{ "swap",op_swap,OPE_D },
	{ "tas",op_tas,OPE_EAB },
	{ "trap",op_trap,OPE_I },
	{ "trapeq",op_trapeq,OPE_TRAPcc },
	{ "trapne",op_trapne,OPE_TRAPcc },
	{ "traplt",op_traplt,OPE_TRAPcc },
	{ "traple",op_traple,OPE_TRAPcc },
	{ "trapgt",op_trapgt,OPE_TRAPcc },
	{ "trapge",op_trapge,OPE_TRAPcc },
	{ "traphi",op_traphi,OPE_TRAPcc },
	{ "traphs",op_traphs,OPE_TRAPcc },
	{ "traplo",op_traplo,OPE_TRAPcc },
	{ "trapls",op_trapls,OPE_TRAPcc },
	{ "trapsr",op_trapsr,OPE_TRAPcc },
	{ "trapcc", op_trapcc,OPE_TRAPcc },
	{ "trapcs", op_trapcs,OPE_TRAPcc },
	{ "trapmi", op_trapmi,OPE_TRAPcc },
	{ "trappl", op_trappl,OPE_TRAPcc },
	{ "trapvc", op_trapvc,OPE_TRAPcc },
	{ "trapvs", op_trapvs,OPE_TRAPcc },
	{ "trapt", op_trapt,OPE_TRAPcc },
	{ "trapf", op_trapf,OPE_TRAPcc },
	{ "trapv", op_trapv,OPE_TRAPcc },
	{ "tst",op_tst,OPE_EA },
	{ "unlk",op_unlk,OPE_A },
	{ "unpk",op_unpk,OPE_PACK },
	{ "fabs",op_fabs,OPE_FMATH },
	{ "facos",op_facos,OPE_FMATH },
	{ "fadd",op_fadd,OPE_FMATHX },
	{ "fasin",op_fasin,OPE_FMATH },
	{ "fatan",op_fatan,OPE_FMATH },
	{ "fatanh",op_fatanh,OPE_FMATH },
	{ "fbeq", op_fbeq, OPE_BRA },
	{ "fbne", op_fbne, OPE_BRA },
	{ "fbgt", op_fbgt, OPE_BRA },
	{ "fbngt", op_fbngt, OPE_BRA },
	{ "fbge", op_fbge,OPE_BRA },
	{ "fbnge", op_fbnge, OPE_BRA },
	{ "fblt", op_fblt, OPE_BRA },
	{ "fbnlt", op_fbnlt, OPE_BRA },
	{ "fble", op_fble, OPE_BRA },
	{ "fbnle", op_fbnle, OPE_BRA },
	{ "fbgl", op_fbgl, OPE_BRA },
	{ "fbngl", op_fbngl, OPE_BRA },
	{ "fbgle", op_fbgle, OPE_BRA },
	{ "fbngle", op_fbngle, OPE_BRA },
	{ "fbogt", op_fbogt, OPE_BRA },
	{ "fbule", op_fbule, OPE_BRA },
	{ "fboge", op_fboge, OPE_BRA },
	{ "fbult", op_fbult, OPE_BRA },
	{ "fbolt", op_fbolt, OPE_BRA },
	{ "fbuge", op_fbuge, OPE_BRA },
	{ "fbole", op_fbole, OPE_BRA },
	{ "fbugt", op_fbugt, OPE_BRA },
	{ "fbogl", op_fbogl, OPE_BRA },
	{ "fbueq", op_fbueq, OPE_BRA },
	{ "fbor", op_fbor, OPE_BRA },
	{ "fbun", op_fbun, OPE_BRA },
	{ "fbt", op_fbt, OPE_BRA },
	{ "fbf", op_fbf, OPE_BRA },
	{ "fbst", op_fbst, OPE_BRA },
	{ "fbsf", op_fbsf, OPE_BRA },
	{ "fbseq", op_fbseq, OPE_BRA },
	{ "fbsne", op_fbsne, OPE_BRA },
	{ "fcmp",op_fcmp,OPE_FMATH },
	{ "fcos",op_fcos,OPE_FMATH },
	{ "fcosh",op_fcosh,OPE_FMATH },
	{ "fdbeq", op_fdbeq, OPE_DBR },
	{ "fdbne", op_fdbne, OPE_DBR },
	{ "fdbgt", op_fdbgt, OPE_DBR },
	{ "fdbngt", op_fdbngt, OPE_DBR },
	{ "fdbge", op_fdbge, OPE_DBR },
	{ "fdbnge", op_fdbnge, OPE_DBR },
	{ "fdblt", op_fdblt, OPE_DBR },
	{ "fdbnlt", op_fdbnlt, OPE_DBR },
	{ "fdble", op_fdble, OPE_DBR },
	{ "fdbnle", op_fdbnle, OPE_DBR },
	{ "fdbgl", op_fdbgl, OPE_DBR },
	{ "fdbngl", op_fdbngl, OPE_DBR },
	{ "fdbgle", op_fdbgle, OPE_DBR },
	{ "fdbngle", op_fdbngle, OPE_DBR },
	{ "fdbogt", op_fdbogt, OPE_DBR },
	{ "fdbule", op_fdbule, OPE_DBR },
	{ "fdboge", op_fdboge, OPE_DBR },
	{ "fdbult", op_fdbult, OPE_DBR },
	{ "fdbolt", op_fdbolt, OPE_DBR },
	{ "fdbuge", op_fdbuge, OPE_DBR },
	{ "fdbole", op_fdbole, OPE_DBR },
	{ "fdbugt", op_fdbugt, OPE_DBR },
	{ "fdbogl", op_fdbogl, OPE_DBR },
	{ "fdbueq", op_fdbueq, OPE_DBR },
	{ "fdbor", op_fdbor, OPE_DBR },
	{ "fdbun", op_fdbun, OPE_DBR },
	{ "fdbt", op_fdbt, OPE_DBR },
	{ "fdbf", op_fdbf, OPE_DBR },
	{ "fdbst", op_fdbst, OPE_DBR },
	{ "fdbsf", op_fdbsf, OPE_DBR },
	{ "fdbseq", op_fdbseq, OPE_DBR },
	{ "fdbsne", op_fdbsne, OPE_DBR },
	{ "fdiv",op_fdiv,OPE_FMATHX },
	{ "fetox",op_fetox,OPE_FMATH },
	{ "fetoxm1",op_fetoxm1,OPE_FMATH },
	{ "fgetexp",op_fgetexp,OPE_FMATH },
	{ "fgetman",op_fgetman,OPE_FMATH },
	{ "fint",op_fint,OPE_FMATH },
	{ "fintrz",op_fintrz,OPE_FMATH },
	{ "flog10",op_flog10,OPE_FMATH },
	{ "flog2",op_flog2,OPE_FMATH },
	{ "flogn",op_flogn,OPE_FMATH },
	{ "flognp1",op_flognp1,OPE_FMATH },
	{ "fmod",op_fmod,OPE_FMATH },
	{ "fmove",op_fmove,OPE_FMOVE },
	{ "fmovecr",op_fmovecr,OPE_FMOVECR },
	{ "fmovem",op_fmovem,OPE_FMOVEM },
	{ "fmul",op_fmul,OPE_FMATHX },
	{ "fneg",op_fneg,OPE_FMATH },
	{ "fnop",op_fnop,0 },
	{ "frem",op_frem,OPE_FMATHX },
	{ "fscale",op_fscale,OPE_FMATHX },
	{ "fseq", op_fseq, OPE_SET },
	{ "fsne", op_fsne, OPE_SET },
	{ "fsgt", op_fsgt, OPE_SET },
	{ "fsngt", op_fsngt, OPE_SET },
	{ "fsge", op_fsge, OPE_SET },
	{ "fsnge", op_fsnge, OPE_SET },
	{ "fslt", op_fslt, OPE_SET },
	{ "fsnlt", op_fsnlt, OPE_SET },
	{ "fsle", op_fsle, OPE_SET },
	{ "fsnle", op_fsnle, OPE_SET },
	{ "fsgl", op_fsgl, OPE_SET },
	{ "fsngl", op_fsngl, OPE_SET },
	{ "fsgle", op_fsgle, OPE_SET },
	{ "fsngle", op_fsngle, OPE_SET },
	{ "fsogt", op_fsogt, OPE_SET },
	{ "fsule", op_fsule, OPE_SET },
	{ "fsoge", op_fsoge, OPE_SET },
	{ "fsult", op_fsult, OPE_SET },
	{ "fsolt", op_fsolt, OPE_SET },
	{ "fsuge", op_fsuge, OPE_SET },
	{ "fsole", op_fsole, OPE_SET },
	{ "fsugt", op_fsugt, OPE_SET },
	{ "fsogl", op_fsogl, OPE_SET },
	{ "fsueq", op_fsueq, OPE_SET },
	{ "fsor", op_fsor, OPE_SET },
	{ "fsun", op_fsun, OPE_SET },
	{ "fst", op_fst, OPE_SET },
	{ "fsf", op_fsf, OPE_SET },
	{ "fsst", op_fsst, OPE_SET },
	{ "fssf", op_fssf, OPE_SET },
	{ "fsseq", op_fsseq, OPE_SET },
	{ "fssne", op_fssne, OPE_SET },
	{ "fsgldiv",op_fsgldiv,OPE_FMATHX },
	{ "fsglmul",op_fsglmul,OPE_FMATHX },
	{ "fsin",op_fsin,OPE_FMATH },
	{ "fsincos",op_fsincos,OPE_FSINCOS },
	{ "fsinh",op_fsinh,OPE_FMATH },
	{ "fsqrt",op_fsqrt,OPE_FMATH },
	{ "fsub",op_fsub,OPE_FMATHX },
	{ "ftan",op_ftan,OPE_FMATH },
	{ "ftanh",op_ftanh,OPE_FMATH },
	{ "ftentox",op_ftentox,OPE_FMATH },
	{ "ftrapeq", op_ftrapeq, OPE_TRAPcc },
	{ "ftrapne", op_ftrapne, OPE_TRAPcc },
	{ "ftrapgt", op_ftrapgt, OPE_TRAPcc },
	{ "ftrapngt", op_ftrapngt, OPE_TRAPcc },
	{ "ftrapge", op_ftrapge, OPE_TRAPcc },
	{ "ftrapnge", op_ftrapnge, OPE_TRAPcc },
	{ "ftraplt", op_ftraplt, OPE_TRAPcc },
	{ "ftrapnlt", op_ftrapnlt, OPE_TRAPcc },
	{ "ftraple", op_ftraple, OPE_TRAPcc },
	{ "ftrapnle", op_ftrapnle, OPE_TRAPcc },
	{ "ftrapgl", op_ftrapgl, OPE_TRAPcc },
	{ "ftrapngl", op_ftrapngl, OPE_TRAPcc },
	{ "ftrapgle", op_ftrapgle, OPE_TRAPcc },
	{ "ftrapngle", op_ftrapngle, OPE_TRAPcc },
	{ "ftrapogt", op_ftrapogt, OPE_TRAPcc },
	{ "ftrapule", op_ftrapule, OPE_TRAPcc },
	{ "ftrapoge", op_ftrapoge, OPE_TRAPcc },
	{ "ftrapult", op_ftrapult, OPE_TRAPcc },
	{ "ftrapolt", op_ftrapolt, OPE_TRAPcc },
	{ "ftrapuge", op_ftrapuge, OPE_TRAPcc },
	{ "ftrapole", op_ftrapole, OPE_TRAPcc },
	{ "ftrapugt", op_ftrapugt, OPE_TRAPcc },
	{ "ftrapogl", op_ftrapogl, OPE_TRAPcc },
	{ "ftrapueq", op_ftrapueq, OPE_TRAPcc },
	{ "ftrapor", op_ftrapor, OPE_TRAPcc },
	{ "ftrapun", op_ftrapun, OPE_TRAPcc },
	{ "ftrapt", op_ftrapt, OPE_TRAPcc },
	{ "ftrapf", op_ftrapf, OPE_TRAPcc },
	{ "ftrapst", op_ftrapst, OPE_TRAPcc },
	{ "ftrapsf", op_ftrapsf, OPE_TRAPcc },
	{ "ftrapseq", op_ftrapseq, OPE_TRAPcc },
	{ "ftrapsne", op_ftrapsne, OPE_TRAPcc },
	{ "ftst",op_ftst,OPE_FONE },
	{ "ftwotox",op_ftwotox,OPE_FMATH },
	{ 0,0,0 },
 };
void dump_muldivval(void)
{
}
/* Init module */
void outcodeini(void)
{
	strtab = 0 ;
	gentype = nogen;
	curseg = noseg;
	outcol = 0;
	datahead = datatail = 0;   
	phiput = FALSE;
	mpthunklist = 0;
}
/*
 * Register a fixup 
 */
void datalink(int flag)
{
	DATALINK *p;
	if (!prm_rel)
		return;
	global_flag++;							/* Global tab */
	p = xalloc(sizeof(DATALINK));
	p->sp = datasp;
	p->type = flag;
	p->offset = dataofs;
	p->next = 0;
	if (datahead) {
		datatail->next = p;
		datatail=datatail->next;
	}
	else
		datahead = datatail = p;
	global_flag--;
}
void nl(void)
/*
 * New line
 */
{    if (prm_asmfile) {
       if(outcol > 0) {
                fputc('\n',outputFile);
                outcol = 0;
                gentype = nogen;
                }
			 if (phiused && !phiput)
								fputc(0x1f,outputFile);
		 }
}
/* Put an opcode
 */
void outop(char *name)
{
	fputc('\t',outputFile);
	while (*name)
		fputc(toupper(*name++),outputFile);
}
void putop(int op)
{       
	if (op > op_ftwotox)
    DIAG("illegal opcode.");
	else
		outop(oplst[op].word);
}

void putsym(char *buf, SYM *sp, char *p)
{
  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.
 */
{        char buf[100] ;
				SYM *sp ;
				 switch( offset->nodetype )
                {
								case en_autoreg:
                case en_autocon:
                case en_icon:
                case en_lcon:
                case en_iucon:
                case en_lucon:
                case en_ccon:
								case en_absacon:
                        fprintf(outputFile,"$%lX",offset->v.i);
												break;
								case en_rcon:
								case en_fcon:
								case en_lrcon:
												fprintf(outputFile,"%.16f",offset->v.f);
												break;
                case en_labcon:
                case en_nalabcon:
                        fprintf(outputFile,"L_%ld",offset->v.i);
                        break;
								case en_napccon:
                case en_nacon:
												sp = offset->v.sp ;
												putsym(buf,sp,sp->name) ;
                        fprintf(outputFile,"%s",buf);
                        break;
                case en_add: case en_addstruc:
                        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 putsize(AMODE *ap)
{
	switch(ap->sz) {
		case 0:
		case 4:
												fprintf(outputFile,".L");
												break;
		case 2:
												fprintf(outputFile,".W");
												break;
		case 1:
												fprintf(outputFile,".B");
												break;
	}
}
void putamode(AMODE *ap)
/*
 *      outputFile a general addressing mode.
 */
{       int scale,t;
				switch( ap->mode &0x1ff)
                {
								case am_fpcr:
												fprintf(outputFile, "FPCR");
												break;
								case am_fpsr:
												fprintf(outputFile, "FPSR");
												break;
								case am_usp:
												fprintf(outputFile, "USP");
												break;
								case am_sfc:
												fprintf(outputFile, "SFC");
												break;
								case am_dfc:
												fprintf(outputFile, "DFC");
												break;
								case am_vbr:
												fprintf(outputFile, "VBR");
												break;
								case am_cacr:
												fprintf(outputFile, "CACR");
												break;
								case am_caar:
												fprintf(outputFile, "CAAR");
												break;
								case am_msp:
												fprintf(outputFile, "MSP");
												break;
								case am_isp:
												fprintf(outputFile, "ISP");
												break;
								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_adirect:
												fputc('(',outputFile);
                        putconst(ap->offset);
												fputc(')',outputFile);
												putlen(ap->preg);
                        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_pcindxaddr:
                        fprintf(outputFile,"(");
                        putconst(ap->offset);
                        fprintf(outputFile,",PC)");
                        fprintf(outputFile,",A%d",ap->sreg);
												putsize(ap);
												if (scale != 1)
													fprintf(outputFile,"*%d",scale);
												fputc(')', outputFile);
                        break;
								case am_pcindxdata:
                        fprintf(outputFile,"(");
                        putconst(ap->offset);
                        fprintf(outputFile,",PC)");
                        fprintf(outputFile,",D%d",ap->sreg);
												putsize(ap);
												if (scale != 1)
													fprintf(outputFile,"*%d",scale);
												fputc(')', outputFile);
                        break;
                case am_baseindxdata:
												scale = 1;
												t = ap->scale;
												while (t--)
													scale <<=1;
                        fprintf(outputFile,"(");
                        putconst(ap->offset);
												if (ap->preg != -1)
                        	fprintf(outputFile,",A%d",ap->preg);
                        fprintf(outputFile,",D%d",ap->sreg);
												putsize(ap);
												if (scale != 1)
													fprintf(outputFile,"*%d",scale);
												fputc(')', outputFile);
                        break;
                case am_baseindxaddr:
												scale = 1;
												t = ap->scale;
												while (t--)
													scale <<=1;
                        fprintf(outputFile,"(");
                        putconst(ap->offset);
												if (ap->preg != -1)
                        	fprintf(outputFile,",A%d",ap->preg);
                        fprintf(outputFile,",A%d",ap->sreg);
												putsize(ap);
												if (scale != 1)
													fprintf(outputFile,"*%d",scale);
												fputc(')', outputFile);
                        break;
								case am_iimem:
                        fprintf(outputFile,"([");
                        putconst(ap->offset);
                        fprintf(outputFile,"],");
                        putconst(ap->offset2);
                        fprintf(outputFile,"),");
												break;
								case am_iiprea:
												scale = 1;
												t = ap->scale;
												while (t--)
													scale <<=1;
                        fprintf(outputFile,"([");
                        putconst(ap->offset);
												if (ap->preg != -1)
                        	fprintf(outputFile,",A%d",ap->preg);
                        fprintf(outputFile,"],");
												if (ap->sreg != -1) {
                        	fprintf(outputFile,",A%d",ap->sreg);
													putsize(ap);
													if (scale != 1)
														fprintf(outputFile,"*%d",scale);
                        	fprintf(outputFile,",");
												}
                        putconst(ap->offset2);
                        fprintf(outputFile,"),");
												break;
								case am_iipred:
												scale = 1;
												t = ap->scale;
												while (t--)
													scale <<=1;
                        fprintf(outputFile,"([");
                        putconst(ap->offset);
												if (ap->preg != -1)
                        	fprintf(outputFile,",A%d",ap->preg);
                        fprintf(outputFile,"],");
												if (ap->sreg != -1) {
                        	fprintf(outputFile,"D%d",ap->sreg);
													putsize(ap);
													if (scale != 1)
														fprintf(outputFile,"*%d",scale);
                        	fprintf(outputFile,",");
												}
                        putconst(ap->offset2);
                        fprintf(outputFile,"),");
												break;
								case am_iiposta:
												scale = 1;
												t = ap->scale;
												while (t--)
													scale <<=1;
                        fprintf(outputFile,"([");
                        putconst(ap->offset);
                        fprintf(outputFile,"],");
												if (ap->preg != -1)
                        	fprintf(outputFile,"A%d,",ap->preg);
												if (ap->sreg != -1) {
                        	fprintf(outputFile,"A%d",ap->sreg);
													putsize(ap);
													if (scale != 1)
														fprintf(outputFile,"*%d",scale);
                        	fprintf(outputFile,",");
												}
                        putconst(ap->offset2);
                        fprintf(outputFile,"),");
												break;
								case am_iipostd:
												scale = 1;
												t = ap->scale;
												while (t--)
													scale <<=1;
                        fprintf(outputFile,"([");
                        putconst(ap->offset);
                        fprintf(outputFile,"],");
												if (ap->preg != -1)
                        	fprintf(outputFile,"A%d,",ap->preg);
												if (ap->sreg != -1) {
                        	fprintf(outputFile,"D%d",ap->sreg);
													putsize(ap);
													if (scale != 1)
														fprintf(outputFile,"*%d",scale);
                        	fprintf(outputFile,",");
												}
                        putconst(ap->offset2);
                        fprintf(outputFile,"),");
												break;
								case am_iiprepca:
												scale = 1;
												t = ap->scale;
												while (t--)
													scale <<=1;
                        fprintf(outputFile,"([");
                        putconst(ap->offset);
                        fprintf(outputFile,",PC",ap->preg);
                        fprintf(outputFile,"],");
												if (ap->sreg != -1) {
                        	fprintf(outputFile,",A%d",ap->sreg);
													putsize(ap);
													if (scale != 1)
														fprintf(outputFile,"*%d",scale);
                        	fprintf(outputFile,",");
												}
                        putconst(ap->offset2);
                        fprintf(outputFile,"),");
												break;
								case am_iiprepcd:
												scale = 1;
												t = ap->scale;
												while (t--)
													scale <<=1;
                        fprintf(outputFile,"([");
                        putconst(ap->offset);
                        fprintf(outputFile,",PC,",ap->preg);
                        fprintf(outputFile,"],");
												if (ap->sreg != -1) {
                        	fprintf(outputFile,"D%d",ap->sreg);
													putsize(ap);
													if (scale != 1)
														fprintf(outputFile,"*%d",scale);
                        	fprintf(outputFile,",");
												}
                        putconst(ap->offset2);
                        fprintf(outputFile,"),");
												break;
								case am_iipostpca:
												scale = 1;
												t = ap->scale;
												while (t--)
													scale <<=1;
                        fprintf(outputFile,"([");
                        putconst(ap->offset);
                        fprintf(outputFile,"],");
                        fprintf(outputFile,"PC,",ap->preg);
												if (ap->sreg != -1) {
                        	fprintf(outputFile,"A%d",ap->sreg);
													putsize(ap);
													if (scale != 1)
														fprintf(outputFile,"*%d",scale);
                        	fprintf(outputFile,",");
												}
                        putconst(ap->offset2);
                        fprintf(outputFile,"),");
												break;
								case am_iipostpcd:
												scale = 1;
												t = ap->scale;
												while (t--)
													scale <<=1;
                        fprintf(outputFile,"([");
                        putconst(ap->offset);
                        fprintf(outputFile,"],");
                        fprintf(outputFile,"PC,",ap->preg);
												if (ap->sreg != -1) {
                        	fprintf(outputFile,"D%d",ap->sreg);
													putsize(ap);
													if (scale != 1)
														fprintf(outputFile,"*%d",scale);
                        	fprintf(outputFile,",");
												}
                        putconst(ap->offset2);
                        fprintf(outputFile,"),");
												break;
                case am_mask:
                        put_mask((int)ap->offset);
                        break;
								case am_fmask:
                        put_fmask((int)ap->offset);
                        break;
                default:
                        DIAG("illegal address mode.");
                        break;
                }
	if (ap->mode & am_bits)
		fprintf(outputFile," { %d : %d }", ap->bf1, ap->bf2);
}

void put_code(OCODE *cd)
/*
 *      outputFile a generic instruction.
 */
{    
		int op = cd->opcode,len = cd->length;
		AMODE *aps = cd->oper1,*apd = cd->oper2, *ape = cd->oper3;   
		if (op == op_void)
			return ;
		nl();
		if (!prm_asmfile)	{
			;/* oc_putop(cd); */
			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_slit)
			DIAG("slit in put_code") ;

		if( op == op_dcl)
		{
			putop(op);
			putlen(len);
      fprintf(outputFile,"\t");
			putamode(aps);
			if (prm_rel)
				fprintf(outputFile,"-*");
      fprintf(outputFile,"\n");
			return;
		}
	else
		{	
			putop(op);
     	putlen(len);
		}
    if( aps != 0 )
    {
      fprintf(outputFile,"\t");
			putamode(aps);
      if( apd != 0 )
      {
				if (apd->mode != am_bf)
          fprintf(outputFile,",");
        putamode(apd);
				if (ape) {
					if (ape->mode != am_bf)
						fprintf(outputFile,",");
					putamode(ape);
				}
      }
    }
  fprintf(outputFile,"\n");
}

void put_fmask(int mask)
/*
 *      generate a register mask for floating restore and save.
 */
{
				unsigned put = FALSE,i,bit;
 					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)
/*
 *      generate a register mask for integer restore and save.
 */
{
				unsigned put = FALSE,i,bit;
 					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(SYM *sp)
/*
 *      generate a named label.
 */
{
		char buf[100] ;
		putsym(buf,sp,sp->name) ;
		datasp = sp;
		if (prm_asmfile) {
				nl();
        fprintf(outputFile,"%s:\n",buf);
		}
		else
			;/* oc_namedlab(sp); */
		dataofs = 0;
}

void put_label(int label)
/*
 *      outputFile a compiler generated label.
 */
{
       	if (prm_asmfile) {
					nl();
					fprintf(outputFile,"L_%ld:\n",label);
				}
				else
					;/* oc_unnamedlab(cd); */
}
void put_staticlabel(long label)
{
				if (prm_asmfile) {
					nl();
					fprintf(outputFile,"L_%ld:\n",label);
				}
}

void genfloat(float val)
/*
 * Output a float value
 */
{ 		if (prm_asmfile)
        if( gentype == floatgen && outcol < 60) {
                fprintf(outputFile,",%.16f",(double)val);
                outcol += 8;
                }
        else    {
                nl();
                fprintf(outputFile,"\tDC.S\t%.16f",(double)val);
                gentype = floatgen;
                outcol = 19;
                }
			else
				;/* oc_genfloat(val); */
	dataofs+=4;
}

void gendouble(double val)
/*
 * Output a double value
 */
{ 		if (prm_asmfile)
        if( gentype == doublegen && outcol < 60) {
                fprintf(outputFile,",%.16f",val);
                outcol += 8;
                }
        else    {
                nl();
                fprintf(outputFile,"\tDC.D\t%.16f",val);
                gentype = doublegen;
                outcol = 19;
                }
			else
				;/* oc_gendouble(val); */
	dataofs+=8;
}
void genlongdouble(long double val)
/*
 * Output a double value
 */
{ 		if (prm_asmfile)
        if( gentype == longdoublegen && outcol < 60) {
                fprintf(outputFile,",%.16lf",val);
                outcol += 8;
                }
        else    {
                nl();
                fprintf(outputFile,"\tDC.X\t%.16lf",val);
                gentype = longdoublegen;
                outcol = 19;
                }
			else
				;/* oc_genlongdouble(val); */
	dataofs+=8;
}

int genstring(char *str, int uselong, int len)
/*
 * Generate a string literal
 */
{
	xstringseg() ;
        if (uselong) {
								len/=2;
                while  (len--) {
                        genword(*((short *)str));
                        str+=2;
                }
                return pstrlen(str)*2;
        }
        else {
                while (len--)
                        genbyte(*str++);
                return strlen(str);
        }
}
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;
                }
			else
				;/* oc_genbyte(val); */
	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;
                }
			else
				;/* oc_genword(val); */
	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;
                }
			else
				;/* oc_genlong(val); */
	dataofs+=4;
}
void genlonglong(long val)
/*
 * Output a long value
 */
{     if (prm_asmfile)
        if( gentype == longgen && outcol < 56) {
                fprintf(outputFile,",0,$%lX",val);
                outcol += 10;
                }
        else    {
                nl();
                fprintf(outputFile,"\tDC.L\t0,$%lX",val);
                gentype = longgen;
                outcol = 25;
                }
			else
				;/* oc_genlong(val); */
	dataofs+=4;
}
/*
 * Generate a startup or rundown reference
 */
void gensrref(SYM *sp,int val)
{
			char buf[256] ;
			putsym(buf,sp,sp->name) ;
			if (prm_asmfile)
        if( gentype == srrefgen && outcol < 56) {
                fprintf(outputFile,",%s,%d",buf,val);
                outcol += strlen(sp->name)+1;
                }
        else    {
                nl();
                fprintf(outputFile,"\tDC.L\t%s,%d",buf,val);
                gentype = srrefgen;
                outcol = 25;
                }
			else 
				;/* oc_gensrref(sp,val); */
}

void genref(SYM *sp,int offset)
/*
 * Output a reference to the data area (also gens fixups )
 */
{       char    sign;
			char buf[256],name[256];
			putsym(name,sp,sp->name) ;
        if( offset < 0) {
                sign = '-';
                offset = -offset;
                }
        else
                sign = '+';
			sprintf(buf,"%s%c%d",name,sign,offset);
			datalink(FALSE);
			if (prm_asmfile) {
        if( gentype == longgen && outcol < 55 - strlen(name)) {
                fprintf(outputFile,",%s",buf);
                outcol += (11 + strlen(name));
                }
        else    {
                nl();
                fprintf(outputFile,"\tDC.L\t%s",buf);
                outcol = 26 + strlen(name);
                gentype = longgen;
                }
			}
			else
				;/* oc_genref(sp,val); */
	dataofs+=4;
}
void genpcref(SYM *sp,int offset)
/*
 * Output a reference to the code area (also gens fixups )
 */
{       char    sign;
				char buf[256],name[256];
				putsym(name,sp,sp->name) ;
        if( offset < 0) {
                sign = '-';
                offset = -offset;
                }
        else
                sign = '+';
			sprintf(buf,"%s%c%d",name,sign,offset);
			datalink(TRUE);
			if (prm_asmfile) {
        if( gentype == longgen && outcol < 55 - strlen(name)) {
                fprintf(outputFile,",%s",buf);
                outcol += (11 + strlen(name));
                }
        else    {
                nl();
                fprintf(outputFile,"\tDC.L\t%s",buf);
                outcol = 26 + strlen(name);
                gentype = longgen;
                }
			}
			else
				;/* oc_genpcref(sp,val); */
	dataofs+=4;
}

void genstorage(int nbytes)
/*
 * Output bytes of storage
 */
{			if (prm_asmfile) {
        nl();
        fprintf(outputFile,"\tDS.B\t$%X\n",nbytes);
			}
			else
				;/* oc_genstorage(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;
                }
			else
				;/* oc_genlabref(n); */
	datalink(TRUE);
	dataofs+=4;
}

int     stringlit(char *s, int uselong, int len)
/*
 *      make s a string literal and return it's label number.
 */
{      
				struct slit     *lp = strtab;
        if (uselong)
					len *= 2;
        if (prm_optmult) {
          while (lp) {
						if (len == lp->len && !memcmp(lp->str,s,len))
        		  return lp->label;
            lp = lp->next;
          }
        }
        ++global_flag;          /* always allocate from global space. */
        lp = xalloc(sizeof(struct slit));
        lp->label = nextlabel++;
        lp->str = malloc(len);
				memcpy(lp->str,s,len);
				lp->len = len;
        lp->next = strtab;
                                lp->type = uselong;
        strtab = lp;
        --global_flag;
        return lp->label;
}
void dumplits(void)
{
        while( strtab != 0) {
                xstringseg() ;
                nl();
                put_label(strtab->label);
                genstring(strtab->str,strtab->type,strtab->len-1);
                if (strtab->type)
                	genword(0);
                else
                	genbyte(0);
                strtab = strtab->next;
                }
        nl();
}

/*
 * Switch to cseg 
 */
void cseg(void)
{			if (prm_asmfile)
       	if( curseg != codeseg) {
                nl();
                fprintf(outputFile,"\tSECTION\tcode\n");
                curseg = codeseg;
                }
}
void xconstseg(void)
{      if (prm_asmfile)
					return ;
         if( curseg != constseg) {
                nl();
								fprintf(outputFile,"\tSECTION\tconst\n") ;
								curseg = constseg ;
					}
}
void xstringseg(void)
{      if (prm_asmfile)
					return ;
         if( curseg != stringseg) {
                nl();
								fprintf(outputFile,"\tSECTION\tstring\n") ;
								curseg = stringseg ;
					}
}
/*
 * 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 != cpprseg) {
                nl();
                fprintf(outputFile,"\tSECTION\tcppexit\n");
                curseg = cpprseg;
                }
}
void gen_virtual(SYM *sp)
/*
 * Generate a virtual segment
 */
{
	if (prm_asmfile) {
		nl();
		fprintf(outputFile,"@%s\tVIRTUAL",sp->name);
	}
}
void gen_endvirtual(SYM *sp)
/*
 * Generate the end of a virtual segment
 */
{
	if (prm_asmfile) {
		nl();
		fprintf(outputFile,"@%s\tENDVIRTUAL",sp->name);
	}
}
SYM *gen_mp_virtual_thunk(SYM *vsp)
{
	LIST *v = mpthunklist;
	SYM *sp;
	while (v) {
		sp = (SYM *)v->data;
		if (sp->value.i == vsp->value.classdata.vtabindex)
			return sp;
		v = v->link;
	}
	global_flag ++;
	sp = xalloc(sizeof(SYM));
	sp->name = xalloc(16);
	sp->value.i = vsp->value.classdata.vtabindex;
	sprintf(sp->name,"LMP_%d",nextlabel++);
	sp->storage_class = sc_static;
  sp->staticlabel=FALSE;
	v = xalloc(sizeof(LIST));
	v->data = sp;
	v->link = mpthunklist;
	mpthunklist = v;
	global_flag--;
	if (prm_asmfile) {
		char buf[100];
		sprintf(buf,"@$mpt$%d",vsp->value.classdata.vtabindex);
		cseg();
    nl();
		fprintf(outputFile,"@%s\tVIRTUAL\n",buf);
		fprintf(outputFile,"%s:\n",sp->name);
      fprintf(outputFile,"\tmove.l\t(4,A7),A0\n");
      if (vsp->value.classdata.vtaboffs)
         fprintf(outputFile,"\tmove.l\t($0%X,A0),A0\n",vsp->value.classdata.vtaboffs);
      else
         fprintf(outputFile,"\tmove.l\t(A0),A0\n");
		fprintf(outputFile,"\tjmp.l\t($0%X,A0)\n",vsp->value.classdata.vtabindex);
		curseg = -1 ;
		cseg() ;
	}
	return sp;
}
void genlongref(DATALINK *p)
/*
 * Generate a reference reference for fixup tables
 */
{
	if (prm_asmfile) 
        if( gentype == longgen && outcol < 56) {
                fprintf(outputFile,",%s+$%X",p->sp->name,p->offset);
                outcol += 10;
                }
        else    {
                nl();
                fprintf(outputFile,"\tDC.L\t%s+$%X",p->sp->name,p->offset);
                gentype = longgen;
                outcol = 25;
                }
	else
		;/* oc_longen(p->sp,p->offset); */
}
/*
 * Assembly file header
 */
void asm_header(void)
{
}
void globaldef(SYM *sp)
/*
 * Stick in a global definition
 */
{
	char name[100] ;
	putsym(name,sp,sp->name) ;
	if (prm_asmfile) {
		nl();
    fprintf(outputFile,"\tXDEF\t%s\n",name);
	}
}
void output_alias(char *name, char *alias)
{
                fprintf(outputFile,"%s EQU\t<%s>\n",name,alias);
}
void putexterns(void)
/*
 * Output the fixup tables and the global/external list
 */
{       SYM     *sp;
			DATALINK *p;
			int i,notyetg;
				int started = FALSE;
				p = datahead;
				curseg = fixcseg;
#ifndef COLDFIRE
				while (p) {
					if (p->type) {
						if (!started && prm_asmfile) {
                nl();
                fprintf(outputFile,"\tSECTION\tcodefix\n");
								started = TRUE;
						}
						genlongref(p);
					}
					p = p->next;
				}
				started = FALSE;
				p = datahead;
				curseg = fixdseg;
				while (p) {
					if (!p->type) {
						if (!started && prm_asmfile) {
                nl();
                fprintf(outputFile,"\tSECTION\tdatafix\n");
								started = TRUE;
						}
						genlongref(p);
					}
					p = p->next;
				}
#endif
			curseg = noseg;
			if (prm_asmfile) {
				nl();
				for (i=0; i < HASHTABLESIZE; i++) {
					if ((sp=(SYM *) gsyms[i]) != 0) {
						while (sp) {
                if( (sp->storage_class = sc_external || sp->storage_class == sc_externalfunc) && sp->extflag && !(sp->tp->cflags & DF_INTRINS)) {
								char buf[256];
								putsym(buf,sp,sp->name) ;
            	  fprintf(outputFile,"\tXREF\t%s\n",buf);
							}
	        		sp = sp->next;
						}
					}
			  }
          while (localfuncs) {
						sp = localfuncs->data ;
            if( sp->storage_class == sc_externalfunc && sp->extflag && !(sp->tp->cflags & DF_INTRINS)) {
                  char buf[100] ;
									putsym(buf,sp,p);
  	              fprintf(outputFile,"\tXREF\t%s\n",buf);
    	      }
        	  localfuncs = localfuncs->link ;
					}
  	       	if (libincludes) {
    	        while (libincludes) {
      	        fprintf(outputFile,"\tINCLUDELIB\t%s\n",libincludes->data);
        	      libincludes = libincludes->link;
          	  }
            	fputc('\n',outputFile);
	          }
  	        fprintf(outputFile,"\tEND\n");
    	   
      
			}
			else
			;/* oc_gencode(); */
}