// Copyright (C) 1985-1998 by Symantec
// Copyright (C) 2000-2011 by Digital Mars
// All Rights Reserved
// http://www.digitalmars.com
// Written by Walter Bright
/*
 * This source file is made available for personal use
 * only. The license is in /dmd/src/dmd/backendlicense.txt
 * or /dm/src/dmd/backendlicense.txt
 * For any other uses, please contact Digital Mars.
 */


/* Generate op-code tables
 * Creates optab.c,debtab.c,cdxxx.c,elxxx.c
 */

#include        <stdio.h>
#include        <stdlib.h>
#include        <time.h>
#include        <assert.h>
#include        "cc.h"
#include        "oper.h"

void doreltables(FILE *f);
void dotab();
void dotytab();
void dooptab();
void fltables();

unsigned char xptab1[OPMAX],xptab2[OPMAX],xptab3[OPMAX];

int _binary[] =
        {OPadd,OPmul,OPand,OPmin,OPcond,OPcomma,OPdiv,OPmod,OPxor,
         OPor,OPoror,OPandand,OPshl,OPshr,OPashr,OPstreq,OPstrcpy,OPstrcat,OPstrcmp,
         OPpostinc,OPpostdec,OPeq,OPaddass,OPminass,OPmulass,OPdivass,
         OPmodass,OPshrass,OPashrass,OPshlass,OPandass,OPxorass,OPorass,
         OPle,OPgt,OPlt,OPge,OPeqeq,OPne,OPparam,OPcall,OPcallns,OPcolon,OPcolon2,
         OPbit,OPoutp,OPbrack,OParrowstar,OPmemcpy,OPmemcmp,OPmemset,
         OPunord,OPlg,OPleg,OPule,OPul,OPuge,OPug,OPue,OPngt,OPnge,
         OPnlt,OPnle,OPord,OPnlg,OPnleg,OPnule,OPnul,OPnuge,OPnug,OPnue,
         OPinfo,OParray,OPfield,OPnewarray,OPmultinewarray,OPinstanceof,OPfinalinstanceof,
         OPcheckcast,OPpair,OPrpair,
         OPbt,OPbtc,OPbtr,OPbts,OPror,OProl,
         OPscale,OPremquo,OPyl2x,OPyl2xp1,
        };
int _unary[] =
        {OPnot,OPcom,OPind,OPaddr,OPneg,OPuadd,
         OPabs,OPsqrt,OPrndtol,OPsin,OPcos,OPrint,
         OPpreinc,OPpredec,
         OPbool,OPstrlen,OPnullcheck,
         OPb_8,OPs16_32,OPu16_32,OPd_s32,OPd_u32,OPoffset,
         OPs32_d,OPu32_d,OPd_s16,OPs16_d,OP32_16,
         OPd_f,OPf_d,OPvp_fp,OPcvp_fp,OPu8_16,OPs8_16,OP16_8,
         OPd_ld, OPld_d,OPc_r,OPc_i,
         OPu32_64,OPs32_64,OP64_32,OPmsw,
         OPd_s64,OPs64_d,OPd_u64,OPu64_d,OPld_u64,
         OP128_64,OPs64_128,OPu64_128,
         OPucall,OPucallns,OPstrpar,OPstrctor,OPu16_d,OPd_u16,
         OPinp,OPnp_fp,OPnp_f16p,OPf16p_np,OParrow,OPnegass,
         OPctor,OPdtor,OPsetjmp,OPvoid,OParraylength,
         OPbsf,OPbsr,OPbswap,
         OPddtor,
        };
int _commut[] = {OPadd,OPand,OPor,OPxor,OPmul,OPeqeq,OPne,OPle,OPlt,OPge,OPgt,
         OPunord,OPlg,OPleg,OPule,OPul,OPuge,OPug,OPue,OPngt,OPnge,
         OPnlt,OPnle,OPord,OPnlg,OPnleg,OPnule,OPnul,OPnuge,OPnug,OPnue,
        };
int _assoc[] = {OPadd,OPand,OPor,OPxor,OPmul};
int _assign[] =
        {OPstreq,OPeq,OPaddass,OPminass,OPmulass,OPdivass,OPmodass,
         OPshrass,OPashrass,OPshlass,OPandass,OPxorass,OPorass,OPpostinc,OPpostdec,
         OPnegass,
        /* OPbtc,OPbtr,OPbts,*/
        };
int _wid[] =
        {OPadd,OPmin,OPand,OPor,OPxor,OPcom,OPneg,OPmul,OPaddass,OPnegass,
         OPminass,OPandass,OPorass,OPxorass,OPmulass,OPshlass,OPshl,OPshrass,
         OPashrass,
        };
int _eop0e[] =
        {OPadd,OPmin,OPxor,OPor,OPshl,OPshr,OPashr,OPpostinc,OPpostdec,OPaddass,
         OPminass,OPshrass,OPashrass,OPshlass,OPxorass,OPorass,
         OPror,OProl,
        };
int _eop00[] = {OPmul,OPand,OPmulass,OPandass};
int _eop1e[] = {OPmul,OPdiv,OPmulass,OPdivass};
int _call[] = {OPcall,OPucall,OPcallns,OPucallns};
int _rel[] = {OPeqeq,OPne,OPle,OPlt,OPgt,OPge,
         OPunord,OPlg,OPleg,OPule,OPul,OPuge,OPug,OPue,OPngt,OPnge,
         OPnlt,OPnle,OPord,OPnlg,OPnleg,OPnule,OPnul,OPnuge,OPnug,OPnue,
        };
int _logical[] = {OPeqeq,OPne,OPle,OPlt,OPgt,OPge,OPandand,OPoror,OPnot,OPbool,
         OPunord,OPlg,OPleg,OPule,OPul,OPuge,OPug,OPue,OPngt,OPnge,
         OPnlt,OPnle,OPord,OPnlg,OPnleg,OPnule,OPnul,OPnuge,OPnug,OPnue,
        };
int _def[] = {OPstreq,OPeq,OPaddass,OPminass,OPmulass,OPdivass,OPmodass,
                OPshrass,OPashrass,OPshlass,OPandass,OPxorass,OPorass,
                OPpostinc,OPpostdec,
                OPcall,OPucall,OPasm,OPstrcpy,OPmemcpy,OPmemset,OPstrcat,
                OPnegass,OPnewarray,OPmultinewarray,
                OPbtc,OPbtr,OPbts,
             };
int _sideff[] = {OPasm,OPucall,OPstrcpy,OPmemcpy,OPmemset,OPstrcat,
                OPcall,OPeq,OPstreq,OPpostinc,OPpostdec,
                OPaddass,OPminass,OPmulass,OPdivass,OPmodass,OPandass,
                OPorass,OPxorass,OPshlass,OPshrass,OPashrass,
                OPinp,OPoutp,OPnegass,OPctor,OPdtor,OPmark,OPvoid,OPnewarray,
                OPmultinewarray,OPcheckcast,OPnullcheck,
                OPbtc,OPbtr,OPbts,
                OPhalt,OPdctor,OPddtor,
                };
int _rtol[] = {OPeq,OPstreq,OPstrcpy,OPmemcpy,OPpostinc,OPpostdec,OPaddass,
                OPminass,OPmulass,OPdivass,OPmodass,OPandass,
                OPorass,OPxorass,OPshlass,OPshrass,OPashrass,
                OPcall,OPcallns,OPinfo,OPmemset,
                };
int _ae[] = {OPvar,OPconst,OPrelconst,OPneg,
                OPabs,OPsqrt,OPrndtol,OPsin,OPcos,OPrint,OPscale,
                OPstrlen,OPstrcmp,OPind,OPaddr,
                OPnot,OPbool,OPcom,OPadd,OPmin,OPmul,OPand,OPor,OPmemcmp,
                OPxor,OPdiv,OPmod,OPshl,OPshr,OPashr,OPeqeq,OPne,OPle,OPlt,OPge,OPgt,
                OPunord,OPlg,OPleg,OPule,OPul,OPuge,OPug,OPue,OPngt,OPnge,
                OPnlt,OPnle,OPord,OPnlg,OPnleg,OPnule,OPnul,OPnuge,OPnug,OPnue,
                OPs16_32,OPu16_32,OPd_s32,OPd_u32,OPoffset,OPu16_d,OPd_u16,
                OPs32_d,OPu32_d,OPd_s16,OPs16_d,OP32_16,OPnp_fp,OPnp_f16p,OPf16p_np,
                OPd_f,OPf_d,OPvp_fp,OPcvp_fp,OPu8_16,OPs8_16,OP16_8,
                OPd_ld,OPld_d,OPc_r,OPc_i,
                OPu32_64,OPs32_64,OP64_32,OPmsw,
                OPd_s64,OPs64_d,OPd_u64,OPu64_d,OPld_u64,
                OP128_64,OPs64_128,OPu64_128,
                OPsizeof,OParray,OPfield,OPinstanceof,OPfinalinstanceof,OPcheckcast,OParraylength,
                OPcallns,OPucallns,OPnullcheck,OPpair,OPrpair,
                OPbsf,OPbsr,OPbt,OPbswap,OPb_8,
                OPgot,OPremquo,
                OPnullptr,
                OProl,OPror,
                /*OPcomma,OPbit,OPoror,OPandand,OPcond,OPcolon,OPcolon2*/};
int _exp[] = {OPvar,OPconst,OPrelconst,OPneg,OPabs,OPsqrt,OPrndtol,OPrint,
                OPsin,OPcos,OPscale,OPyl2x,OPyl2xp1,
                OPstrlen,OPstrcmp,OPind,OPaddr,
                OPnot,OPbool,OPcom,OPadd,OPmin,OPmul,OPand,OPor,OPstring,
                OPxor,OPdiv,OPmod,OPshl,OPshr,OPashr,OPeqeq,OPne,OPle,OPlt,OPge,OPgt,
                OPunord,OPlg,OPleg,OPule,OPul,OPuge,OPug,OPue,OPngt,OPnge,
                OPnlt,OPnle,OPord,OPnlg,OPnleg,OPnule,OPnul,OPnuge,OPnug,OPnue,
                OPcomma,OPasm,OPsizeof,OPmemcmp,
                OPs16_32,OPu16_32,OPd_s32,OPd_u32,OPoffset,OPu16_d,OPd_u16,
                OPs32_d,OPu32_d,OPd_s16,OPs16_d,OP32_16,OPnp_fp,OPnp_f16p,OPf16p_np,
                OPd_f,OPf_d,OPvp_fp,OPcvp_fp,OPu8_16,OPs8_16,OP16_8,
                OPd_ld, OPld_d,OPc_r,OPc_i,
                OPu32_64,OPs32_64,OP64_32,OPmsw,
                OPd_s64,OPs64_d,OPd_u64,OPu64_d,OPld_u64,
                OP128_64,OPs64_128,OPu64_128,
                OPbit,OPind,OPucall,OPucallns,OPnullcheck,
                OParray,OPfield,OPinstanceof,OPfinalinstanceof,OPcheckcast,OParraylength,OPhstring,
                OPcall,OPcallns,OPeq,OPstreq,OPpostinc,OPpostdec,
                OPaddass,OPminass,OPmulass,OPdivass,OPmodass,OPandass,
                OPorass,OPxorass,OPshlass,OPshrass,OPashrass,OPoror,OPandand,OPcond,
                OPbsf,OPbsr,OPbt,OPbtc,OPbtr,OPbts,OPbswap,
                OProl,OPror,
                OPpair,OPrpair,OPframeptr,OPgot,OPremquo,
                OPcolon,OPcolon2,OPasm,OPstrcpy,OPmemcpy,OPmemset,OPstrcat,OPnegass};
int _boolnop[] = {OPuadd,OPbool,OPs16_32,OPu16_32,
                OPs16_d,
                OPf_d,OPvp_fp,OPcvp_fp,OPu8_16,OPs8_16,
                OPd_ld, OPld_d,
                OPu32_64,OPs32_64,/*OP64_32,OPmsw,*/
                OPs64_128,OPu64_128,
                OPu16_d,OPnp_fp,OPb_8,
                OPnullptr,
                };
int _lvalue[] = {OPvar,OPind,OPcomma,OPbit,
                OPfield,OParray};

FILE *fdeb;

int main()
{
    printf("OPTABGEN... generating files\n");
    fdeb = fopen("debtab.c","w");
    dooptab();
    dotab();
    fltables();
    dotytab();
    fclose(fdeb);
    return 0;
}

int cost(unsigned op)
{       unsigned c;

        c = 0;                          /* default cost                 */
        if (xptab1[op] & _OTunary)
                c += 2;
        else if (xptab1[op] & _OTbinary)
                c += 7;
        if (xptab2[op] & _OTlogical)
                c += 3;
        switch (op)
        {   case OPvar: c += 1; break;
            case OPmul: c += 3; break;
            case OPdiv:
            case OPmod: c += 4; break;
            case OProl:
            case OPror:
            case OPshl:
            case OPashr:
            case OPshr: c += 2; break;
            case OPnewarray:
            case OPmultinewarray:
            case OPcall:
            case OPucall:
            case OPcallns:
            case OPucallns:
                                c += 10; break; // very high cost for function calls
            case OParray:       c = 5; break;
        }
        return c;
}

void dooptab()
{       int i;
        FILE *f;

        /* Load optab[] */
#define X1(arr,mask) for(i=0;i<sizeof(arr)/sizeof(int);i++)xptab1[arr[i]]|=mask;
#define X2(arr,mask) for(i=0;i<sizeof(arr)/sizeof(int);i++)xptab2[arr[i]]|=mask;
#define X3(arr,mask) for(i=0;i<sizeof(arr)/sizeof(int);i++)xptab3[arr[i]]|=mask;

        X1(_binary,_OTbinary);
        X1(_unary,_OTunary);
        X1(_commut,_OTcommut);
        X1(_assoc,_OTassoc);
        X1(_sideff,_OTsideff);
        X1(_eop0e,_OTeop0e);
        X1(_eop00,_OTeop00);
        X1(_eop1e,_OTeop1e);

        X2(_logical,_OTlogical);
        X2(_wid,_OTwid);
        X2(_call,_OTcall);
        X2(_rtol,_OTrtol);
        X2(_assign,_OTassign);
        X2(_def,_OTdef);
        X2(_ae,_OTae);
        X2(_exp,_OTexp);

        X3(_boolnop,_OTboolnop);

#undef X3
#undef X2
#undef X1

        f = fopen("optab.c","w");
        fprintf(f,"const unsigned char optab1[OPMAX] =\n\t{");
        for (i = 0; i < OPMAX; i++)
        {       if ((i & 7) == 0)
                        fprintf(f,"\n\t");
                fprintf(f,"0x%x",xptab1[i]);
                if (i != OPMAX - 1)
                        fprintf(f,",");
        }
        fprintf(f,"\t};\n");
        fprintf(f,"const unsigned char optab2[OPMAX] =\n\t{");
        for (i = 0; i < OPMAX; i++)
        {       if ((i & 7) == 0)
                        fprintf(f,"\n\t");
                fprintf(f,"0x%x",xptab2[i]);
                if (i != OPMAX - 1)
                        fprintf(f,",");
        }
        fprintf(f,"\t};\n");
        fprintf(f,"const unsigned char optab3[OPMAX] =\n\t{");
        for (i = 0; i < OPMAX; i++)
        {       if ((i & 7) == 0)
                        fprintf(f,"\n\t");
                fprintf(f,"0x%x",xptab3[i]);
                if (i != OPMAX - 1)
                        fprintf(f,",");
        }
        fprintf(f,"\t};\n");

        fprintf(f,"const unsigned char opcost[OPMAX] =\n\t{");
        for (i = 0; i < OPMAX; i++)
        {       if ((i & 7) == 0)
                        fprintf(f,"\n\t");
                fprintf(f,"0x%x",cost(i));
                if (i != OPMAX - 1)
                        fprintf(f,",");
        }
        fprintf(f,"\t};\n");

        doreltables(f);
        fclose(f);
}

/********************************************************
 */

void doreltables(FILE *f)
{
        static struct
        {   enum OPER op;       /* operator                             */
            enum OPER inot;     /* for logical negation                 */
            enum OPER swap;     /* if operands are swapped              */
            enum OPER integral; /* if operands are integral types       */
            int exception;      /* if invalid exception is generated    */
            int unord;          /* result of unordered operand(s)       */
        } reltables[] =
        { /*    op      not     swap    int     exc     unord   */
            { OPeqeq,   OPne,   OPeqeq, OPeqeq, 0,      0 },
            { OPne,     OPeqeq, OPne,   OPne,   0,      1 },
            { OPgt,     OPngt,  OPlt,   OPgt,   1,      0 },
            { OPge,     OPnge,  OPle,   OPge,   1,      0 },
            { OPlt,     OPnlt,  OPgt,   OPlt,   1,      0 },
            { OPle,     OPnle,  OPge,   OPle,   1,      0 },

            { OPunord, OPord,   OPunord, (enum OPER)0,0,1 },
            { OPlg,     OPnlg,  OPlg,   OPne,   1,      0 },
            { OPleg,    OPnleg, OPleg,  (enum OPER)1,1, 0 },
            { OPule,    OPnule, OPuge,  OPle,   0,      1 },
            { OPul,     OPnul,  OPug,   OPlt,   0,      1 },
            { OPuge,    OPnuge, OPule,  OPge,   0,      1 },
            { OPug,     OPnug,  OPul,   OPgt,   0,      1 },
            { OPue,     OPnue,  OPue,   OPeqeq, 0,      1 },

            { OPngt,    OPgt,   OPnlt,  OPle,   1,      1 },
            { OPnge,    OPge,   OPnle,  OPlt,   1,      1 },
            { OPnlt,    OPlt,   OPngt,  OPge,   1,      1 },
            { OPnle,    OPle,   OPnge,  OPgt,   1,      1 },
            { OPord,    OPunord, OPord, (enum OPER)1,0, 0 },
            { OPnlg,    OPlg,   OPnlg,  OPeqeq, 1,      1 },
            { OPnleg,   OPleg,  OPnleg, (enum OPER)0,1, 1 },
            { OPnule,   OPule,  OPnuge, OPgt,   0,      0 },
            { OPnul,    OPul,   OPnug,  OPge,   0,      0 },
            { OPnuge,   OPuge,  OPnule, OPlt,   0,      0 },
            { OPnug,    OPug,   OPnul,  OPle,   0,      0 },
            { OPnue,    OPue,   OPnue,  OPne,   0,      0 },
        };
#define RELMAX arraysize(reltables)
        enum OPER rel_not[RELMAX];
        enum OPER rel_swap[RELMAX];
        enum OPER rel_integral[RELMAX];
        int rel_exception[RELMAX];
        int rel_unord[RELMAX];
        int i;

        for (i = 0; i < RELMAX; i++)
        {   int j = (int)(reltables[i].op) - RELOPMIN;

            assert(j >= 0 && j < RELMAX);
            rel_not      [j] = reltables[i].inot;
            rel_swap     [j] = reltables[i].swap;
            rel_integral [j] = reltables[i].integral;
            rel_exception[j] = reltables[i].exception;
            rel_unord    [j] = reltables[i].unord;
        }

    fprintf(f,"unsigned char rel_not[] =\n{ ");
    for (i = 0; i < arraysize(rel_not); i++)
    {   fprintf(f,"0x%02x,",rel_not[i]);
        if ((i & 7) == 7 && i < arraysize(rel_not) - 1)
            fprintf(f,"\n  ");
    }
    fprintf(f,"\n};\n");

    fprintf(f,"unsigned char rel_swap[] =\n{ ");
    for (i = 0; i < arraysize(rel_swap); i++)
    {   fprintf(f,"0x%02x,",rel_swap[i]);
        if ((i & 7) == 7 && i < arraysize(rel_swap) - 1)
            fprintf(f,"\n  ");
    }
    fprintf(f,"\n};\n");

    fprintf(f,"unsigned char rel_integral[] =\n{ ");
    for (i = 0; i < arraysize(rel_integral); i++)
    {   fprintf(f,"0x%02x,",rel_integral[i]);
        if ((i & 7) == 7 && i < arraysize(rel_integral) - 1)
            fprintf(f,"\n  ");
    }
    fprintf(f,"\n};\n");

    fprintf(f,"unsigned char rel_exception[] =\n{ ");
    for (i = 0; i < arraysize(rel_exception); i++)
    {   fprintf(f,"0x%02x,",rel_exception[i]);
        if ((i & 7) == 7 && i < arraysize(rel_exception) - 1)
            fprintf(f,"\n  ");
    }
    fprintf(f,"\n};\n");

    fprintf(f,"unsigned char rel_unord[] =\n{ ");
    for (i = 0; i < arraysize(rel_unord); i++)
    {   fprintf(f,"0x%02x,",rel_unord[i]);
        if ((i & 7) == 7 && i < arraysize(rel_unord) - 1)
            fprintf(f,"\n  ");
    }
    fprintf(f,"\n};\n");
}


/********************************************************
 */

const char *debtab[OPMAX],*cdxxx[OPMAX],*elxxx[OPMAX];

void dotab()
{ int i;
  FILE *f;

#if BSDUNIX
#define X(d,e,c) debtab[i]=d;cdxxx[i]="c",elxxx[i]="e";break
#else
#define X(d,e,c) debtab[i]=d;cdxxx[i]=#c,elxxx[i]=#e;break
#endif
  for (i = 0; i < OPMAX; i++)
  {
    switch (i)
    {
        case OPunde:    X("unde",       elerr,  cderr);
        case OPadd:     X("+",          eladd,  cdorth);
        case OPmul:     X("*",          elmul,  cdmul);
        case OPand:     X("&",          elbitwise,cdorth);
        case OPmin:     X("-",          elmin,  cdorth);
        case OPnot:     X("!",          elnot,  cdnot);
        case OPcom:     X("~",          elcom,  cdcom);
        case OPcond:    X("?",          elcond, cdcond);
        case OPcomma:   X(",",          elcomma,cdcomma);
        case OPremquo:  X("/%",         elremquo, cdmul);
        case OPdiv:     X("/",          eldiv,  cdmul);
        case OPmod:     X("%",          elmod,  cdmul);
        case OPxor:     X("^",          elxor,  cdorth);
        case OPvp_fp:   X("vptrfptr",   elvptrfptr,cdcnvt);
        case OPcvp_fp:  X("cvptrfptr",  elvptrfptr,cdcnvt);
        case OPstring:  X("string",     elstring,cderr);
        case OPrelconst: X("relconst",  elzot, cdrelconst);
        case OPinp:     X("inp",        elzot, cdport);
        case OPoutp:    X("outp",       elzot, cdport);
        case OPasm:     X("asm",        elzot, cdasm);
        case OPinfo:    X("info",       elinfo,cdinfo);
        case OPdctor:   X("dctor",      elzot, cddctor);
        case OPddtor:   X("ddtor",      elddtor, cdddtor);
        case OPctor:    X("ctor",       elinfo,cdctor);
        case OPdtor:    X("dtor",       elinfo,cddtor);
        case OPmark:    X("mark",       elinfo,cdmark);
        case OPvoid:    X("void",       elzot, cdvoid);
        case OPhalt:    X("halt",       elzot, cdhalt);
        case OPnullptr: X("nullptr",    elerr, cderr);
        case OPpair:    X("pair",       elpair, cdpair);
        case OPrpair:   X("rpair",      elpair, cdpair);

        case OPnewarray: X("newarray",  elnewarray,cderr);
        case OPmultinewarray: X("mnewarray",    elmultinewarray,cderr);
        case OPinstanceof: X("instanceof",      elinstanceof,cderr);
        case OPfinalinstanceof: X("finalinstanceof",    elfinalinstanceof,cderr);
        case OPcheckcast: X("checkcast",        elcheckcast,cderr);
        case OParraylength: X("length", elarraylength,cderr);
        case OParray:   X("array",      elarray,cderr);
        case OPfield:   X("field",      elfield,cderr);
        case OPhstring: X("hstring",    elhstring,cderr);
        case OPnullcheck: X("nullcheck", elnullcheck,cdnullcheck);

        case OPor:      X("|",          elor,   cdorth);
        case OPoror:    X("||",         eloror, cdloglog);
        case OPandand:  X("&&",         elandand,cdloglog);
        case OProl:     X("<<|",        elshl,  cdshift);
        case OPror:     X(">>|",        elshl,  cdshift);
        case OPshl:     X("<<",         elshl,  cdshift);
        case OPshr:     X(">>>",        elshr,  cdshift);
        case OPashr:    X(">>",         elshr,  cdshift);
        case OPbit:     X("bit",        elbit,  cderr);
        case OPind:     X("*",          elind,  cdind);
        case OPaddr:    X("&",          eladdr, cderr);
        case OPneg:     X("-",          elneg,  cdneg);
        case OPuadd:    X("+",          elzot,  cderr);
        case OPabs:     X("abs",        evalu8, cdabs);
        case OPsqrt:    X("sqrt",       evalu8, cdneg);
        case OPsin:     X("sin",        evalu8, cdneg);
        case OPcos:     X("cos",        evalu8, cdneg);
        case OPrint:    X("rint",       evalu8, cdneg);
        case OPrndtol:  X("rndtol",     evalu8, cdrndtol);
        case OPscale:   X("scale",      elzot,  cdscale);
        case OPyl2x:    X("yl2x",       elzot,  cdscale);
        case OPyl2xp1:  X("yl2xp1",     elzot,  cdscale);
        case OPstrlen:  X("strlen",     elzot,  cdstrlen);
        case OPstrcpy:  X("strcpy",     elstrcpy,cdstrcpy);
        case OPmemcpy:  X("memcpy",     elmemxxx,cdmemcpy);
        case OPmemset:  X("memset",     elmemxxx,cdmemset);
        case OPstrcat:  X("strcat",     elzot,  cderr);
        case OPstrcmp:  X("strcmp",     elstrcmp,cdstrcmp);
        case OPmemcmp:  X("memcmp",     elmemxxx,cdmemcmp);
        case OPsetjmp:  X("setjmp",     elzot,  cdsetjmp);
        case OPnegass:  X("negass",     elnegass, cdaddass);
        case OPpreinc:  X("U++",        elzot,  cderr);
        case OPpredec:  X("U--",        elzot,  cderr);
        case OPstreq:   X("streq",      elstruct,cdstreq);
        case OPpostinc: X("++",         elpost, cdpost);
        case OPpostdec: X("--",         elpost, cdpost);
        case OPeq:      X("=",          eleq,   cdeq);
        case OPaddass:  X("+=",         elopass,cdaddass);
        case OPminass:  X("-=",         elopass,cdaddass);
        case OPmulass:  X("*=",         elopass,cdmulass);
        case OPdivass:  X("/=",         elopass,cdmulass);
        case OPmodass:  X("%=",         elopass,cdmulass);
        case OPshrass:  X(">>>=",       elopass,cdshass);
        case OPashrass: X(">>=",        elopass,cdshass);
        case OPshlass:  X("<<=",        elopass,cdshass);
        case OPandass:  X("&=",         elopass,cdaddass);
        case OPxorass:  X("^=",         elopass,cdaddass);
        case OPorass:   X("|=",         elopass,cdaddass);

        case OPle:      X("<=",         elcmp,  cdcmp);
        case OPgt:      X(">",          elcmp,  cdcmp);
        case OPlt:      X("<",          elcmp,  cdcmp);
        case OPge:      X(">=",         elcmp,  cdcmp);
        case OPeqeq:    X("==",         elcmp,  cdcmp);
        case OPne:      X("!=",         elcmp,  cdcmp);

        case OPunord:   X("!<>=",       elcmp,  cdcmp);
        case OPlg:      X("<>",         elcmp,  cdcmp);
        case OPleg:     X("<>=",        elcmp,  cdcmp);
        case OPule:     X("!>",         elcmp,  cdcmp);
        case OPul:      X("!>=",        elcmp,  cdcmp);
        case OPuge:     X("!<",         elcmp,  cdcmp);
        case OPug:      X("!<=",        elcmp,  cdcmp);
        case OPue:      X("!<>",        elcmp,  cdcmp);
        case OPngt:     X("~>",         elcmp,  cdcmp);
        case OPnge:     X("~>=",        elcmp,  cdcmp);
        case OPnlt:     X("~<",         elcmp,  cdcmp);
        case OPnle:     X("~<=",        elcmp,  cdcmp);
        case OPord:     X("~!<>=",      elcmp,  cdcmp);
        case OPnlg:     X("~<>",        elcmp,  cdcmp);
        case OPnleg:    X("~<>=",       elcmp,  cdcmp);
        case OPnule:    X("~!>",        elcmp,  cdcmp);
        case OPnul:     X("~!>=",       elcmp,  cdcmp);
        case OPnuge:    X("~!<",        elcmp,  cdcmp);
        case OPnug:     X("~!<=",       elcmp,  cdcmp);
        case OPnue:     X("~!<>",       elcmp,  cdcmp);

        case OPnp_fp:   X("ptrlptr",    elptrlptr,cdshtlng);
        case OPnp_f16p: X("tofar16",    elzot,  cdfar16);
        case OPf16p_np: X("fromfar16",  elzot,  cdfar16);
        case OPs16_32:  X("s16_32",     evalu8, cdshtlng);
        case OPu16_32:  X("u16_32",     evalu8, cdshtlng);
        case OPd_s32:   X("d_s32",      evalu8, cdcnvt);
        case OPb_8:     X("b_8",        evalu8, cdcnvt);
        case OPs32_d:   X("s32_d",      evalu8, cdcnvt);
        case OPd_s16:   X("d_s16",      evalu8, cdcnvt);
        case OPs16_d:   X("s16_d",      evalu8, cdcnvt);
        case OPd_u16:   X("d_u16",      evalu8, cdcnvt);
        case OPu16_d:   X("u16_d",      evalu8, cdcnvt);
        case OPd_u32:   X("d_u32",      evalu8, cdcnvt);
        case OPu32_d:   X("u32_d",      evalu8, cdcnvt);
        case OPoffset:  X("offset",     ellngsht,cdlngsht);
        case OP32_16:   X("32_16",      ellngsht,cdlngsht);
        case OPd_f:     X("d_f",        evalu8, cdcnvt);
        case OPf_d:     X("f_d",        evalu8, cdcnvt);
        case OPd_ld:    X("d_ld",       evalu8, cdcnvt);
        case OPld_d:    X("ld_d",       evalu8, cdcnvt);
        case OPc_r:     X("c_r",        elc_r,  cdconvt87);
        case OPc_i:     X("c_i",        elc_i,  cdconvt87);
        case OPu8_16:   X("u8_16",      elbyteint, cdbyteint);
        case OPs8_16:   X("s8_16",      elbyteint, cdbyteint);
        case OP16_8:    X("16_8",       ellngsht,cdlngsht);
        case OPu32_64:  X("u32_64",     evalu8, cdshtlng);
        case OPs32_64:  X("s32_64",     evalu8, cdshtlng);
        case OP64_32:   X("64_32",      el64_32, cdlngsht);
        case OPu64_128: X("u64_128",    evalu8, cdshtlng);
        case OPs64_128: X("s64_128",    evalu8, cdshtlng);
        case OP128_64:  X("128_64",     el64_32, cdlngsht);
        case OPmsw:     X("msw",        evalu8, cdmsw);

        case OPd_s64:   X("d_s64",      evalu8, cdcnvt);
        case OPs64_d:   X("s64_d",      evalu8, cdcnvt);
        case OPd_u64:   X("d_u64",      evalu8, cdcnvt);
        case OPu64_d:   X("u64_d",      evalu8, cdcnvt);
        case OPld_u64:  X("ld_u64",     evalu8, cdcnvt);
        case OPparam:   X("param",      elparam, cderr);
        case OPsizeof:  X("sizeof",     elzot,  cderr);
        case OParrow:   X("->",         elzot,  cderr);
        case OParrowstar: X("->*",      elzot,  cderr);
        case OPcolon:   X("colon",      elzot,  cderr);
        case OPcolon2:  X("colon2",     elzot,  cderr);
        case OPbool:    X("bool",       elbool, cdnot);
        case OPcall:    X("call",       elcall, cdfunc);
        case OPucall:   X("ucall",      elcall, cdfunc);
        case OPcallns:  X("callns",     elcall, cdfunc);
        case OPucallns: X("ucallns",    elcall, cdfunc);
        case OPstrpar:  X("strpar",     elstruct, cderr);
        case OPstrctor: X("strctor",    elzot,  cderr);
        case OPstrthis: X("strthis",    elzot,  cdstrthis);
        case OPconst:   X("const",      elerr,  cderr);
        case OPvar:     X("var",        elerr,  loaddata);
        case OPreg:     X("reg",        elerr,  cderr);
        case OPnew:     X("new",        elerr,  cderr);
        case OPanew:    X("new[]",      elerr,  cderr);
        case OPdelete:  X("delete",     elerr,  cderr);
        case OPadelete: X("delete[]",   elerr,  cderr);
        case OPbrack:   X("brack",      elerr,  cderr);
        case OPframeptr: X("frameptr",  elzot,  cdframeptr);
        case OPgot:     X("got",        elzot,  cdgot);

        case OPbsf:     X("bsf",        elzot,  cdbscan);
        case OPbsr:     X("bsr",        elzot,  cdbscan);
        case OPbt:      X("bt",         elzot,  cdbt);
        case OPbtc:     X("btc",        elzot,  cdbt);
        case OPbtr:     X("btr",        elzot,  cdbt);
        case OPbts:     X("bts",        elzot,  cdbt);

        case OPbswap:   X("bswap",      evalu8, cdbswap);

        default:
                printf("opcode hole x%x\n",i);
                exit(EXIT_FAILURE);
#undef X
    }
  }

  fprintf(fdeb,"static const char *debtab[OPMAX] = \n\t{\n");
  for (i = 0; i < OPMAX - 1; i++)
        fprintf(fdeb,"\t\"%s\",\n",debtab[i]);
  fprintf(fdeb,"\t\"%s\"\n\t};\n",debtab[i]);

  f = fopen("cdxxx.c","w");
  fprintf(f,"code *(*cdxxx[OPMAX]) (elem *,regm_t *) = \n\t{\n");
  for (i = 0; i < OPMAX - 1; i++)
        fprintf(f,"\t%s,\n",cdxxx[i]);
  fprintf(f,"\t%s\n\t};\n",cdxxx[i]);
  fclose(f);

  f = fopen("elxxx.c","w");
  fprintf(f,"static elem *(*elxxx[OPMAX]) (elem *) = \n\t{\n");
  for (i = 0; i < OPMAX - 1; i++)
        fprintf(f,"\t%s,\n",elxxx[i]);
  fprintf(f,"\t%s\n\t};\n",elxxx[i]);
  fclose(f);
}

void fltables()
{       FILE *f;
        int i;
        char segfl[FLMAX];
        char datafl[FLMAX];
        char stackfl[FLMAX];
        char flinsymtab[FLMAX];

        static char indatafl[] =        /* is FLxxxx a data type?       */
        { FLdata,FLudata,FLreg,FLpseudo,FLauto,FLpara,FLextern,FLtmp,
          FLcs,FLfltreg,FLallocatmp,FLdatseg,FLndp,FLtlsdata,FLbprel,
          FLstack,FLregsave };
#if TARGET_SEGMENTED
        static char indatafl_s[] = { FLfardata, };
#endif

        static char instackfl[] =       /* is FLxxxx a stack data type? */
        { FLauto,FLpara,FLtmp,FLcs,FLfltreg,FLallocatmp,FLndp,FLbprel,FLstack,FLregsave };

        static char inflinsymtab[] =    /* is FLxxxx in the symbol table? */
        { FLdata,FLudata,FLreg,FLpseudo,FLauto,FLpara,FLextern,FLtmp,FLfunc,
          FLtlsdata,FLbprel,FLstack };
#if TARGET_SEGMENTED
        static char inflinsymtab_s[] = { FLfardata,FLcsdata, };
#endif

        for (i = 0; i < FLMAX; i++)
                datafl[i] = stackfl[i] = flinsymtab[i] = 0;

        for (i = 0; i < sizeof(indatafl); i++)
                datafl[indatafl[i]] = 1;

        for (i = 0; i < sizeof(instackfl); i++)
                stackfl[instackfl[i]] = 1;

        for (i = 0; i < sizeof(inflinsymtab); i++)
                flinsymtab[inflinsymtab[i]] = 1;

#if TARGET_SEGMENTED
        for (i = 0; i < sizeof(indatafl_s); i++)
                datafl[indatafl_s[i]] = 1;

        for (i = 0; i < sizeof(inflinsymtab_s); i++)
                flinsymtab[inflinsymtab_s[i]] = 1;
#endif

/* Segment registers    */
#define ES      0
#define CS      1
#define SS      2
#define DS      3

        for (i = 0; i < FLMAX; i++)
        {   switch (i)
            {
                case 0:         segfl[i] = -1;  break;
                case FLconst:   segfl[i] = -1;  break;
                case FLoper:    segfl[i] = -1;  break;
                case FLfunc:    segfl[i] = CS;  break;
                case FLdata:    segfl[i] = DS;  break;
                case FLudata:   segfl[i] = DS;  break;
                case FLreg:     segfl[i] = -1;  break;
                case FLpseudo:  segfl[i] = -1;  break;
                case FLauto:    segfl[i] = SS;  break;
                case FLstack:   segfl[i] = SS;  break;
                case FLbprel:   segfl[i] = SS;  break;
                case FLpara:    segfl[i] = SS;  break;
                case FLextern:  segfl[i] = DS;  break;
                case FLtmp:     segfl[i] = SS;  break;
                case FLcode:    segfl[i] = CS;  break;
                case FLblock:   segfl[i] = CS;  break;
                case FLblockoff: segfl[i] = CS; break;
                case FLcs:      segfl[i] = SS;  break;
                case FLregsave: segfl[i] = SS;  break;
                case FLndp:     segfl[i] = SS;  break;
                case FLswitch:  segfl[i] = -1;  break;
                case FLfltreg:  segfl[i] = SS;  break;
                case FLoffset:  segfl[i] = -1;  break;
#if TARGET_SEGMENTED
                case FLfardata: segfl[i] = -1;  break;
                case FLcsdata:  segfl[i] = CS;  break;
#endif
                case FLdatseg:  segfl[i] = DS;  break;
                case FLctor:    segfl[i] = -1;  break;
                case FLdtor:    segfl[i] = -1;  break;
                case FLdsymbol: segfl[i] = -1;  break;
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
                case FLgot:     segfl[i] = -1;  break;
                case FLgotoff:  segfl[i] = -1;  break;
#endif
                case FLlocalsize: segfl[i] = -1;        break;
                case FLtlsdata: segfl[i] = -1;  break;
                case FLframehandler:    segfl[i] = -1;  break;
                case FLasm:     segfl[i] = -1;  break;
                case FLallocatmp:       segfl[i] = SS;  break;
                default:
                        printf("error in segfl[%d]\n", i);
                        exit(1);
            }
        }

        f = fopen("fltables.c","w");

        fprintf(f,"const char datafl[FLMAX] = \n\t{ ");
        for (i = 0; i < FLMAX - 1; i++)
                fprintf(f,"%d,",datafl[i]);
        fprintf(f,"%d };\n",datafl[i]);

        fprintf(f,"const char stackfl[FLMAX] = \n\t{ ");
        for (i = 0; i < FLMAX - 1; i++)
                fprintf(f,"%d,",stackfl[i]);
        fprintf(f,"%d };\n",stackfl[i]);

        fprintf(f,"const char segfl[FLMAX] = \n\t{ ");
        for (i = 0; i < FLMAX - 1; i++)
                fprintf(f,"%d,",segfl[i]);
        fprintf(f,"%d };\n",segfl[i]);

        fprintf(f,"const char flinsymtab[FLMAX] = \n\t{ ");
        for (i = 0; i < FLMAX - 1; i++)
                fprintf(f,"%d,",flinsymtab[i]);
        fprintf(f,"%d };\n",flinsymtab[i]);

        fclose(f);
}

void dotytab()
{
    static tym_t _ptr[]      = { TYjhandle,TYnptr };
#if TARGET_SEGMENTED
    static tym_t _ptr_nflat[]= { TYsptr,TYcptr,TYf16ptr,TYfptr,TYhptr,TYvptr };
#endif
    static tym_t _real[]     = { TYfloat,TYdouble,TYdouble_alias,TYldouble,
                               };
    static tym_t _imaginary[] = {
                                 TYifloat,TYidouble,TYildouble,
                               };
    static tym_t _complex[] =  {
                                 TYcfloat,TYcdouble,TYcldouble,
                               };
    static tym_t _integral[] = { TYbool,TYchar,TYschar,TYuchar,TYshort,
                                 TYwchar_t,TYushort,TYenum,TYint,TYuint,
                                 TYlong,TYulong,TYllong,TYullong,TYdchar,
                                 TYchar16, TYcent, TYucent };
    static tym_t _ref[]      = { TYnref,TYref };
    static tym_t _func[]     = { TYnfunc,TYnpfunc,TYnsfunc,TYifunc,TYmfunc,TYjfunc,TYhfunc };
#if TARGET_SEGMENTED
    static tym_t _ref_nflat[] = { TYfref };
    static tym_t _func_nflat[]= { TYffunc,TYfpfunc,TYf16func,TYfsfunc,TYnsysfunc,TYfsysfunc, };
#endif
    static tym_t _uns[]     = { TYuchar,TYushort,TYuint,TYulong,
#if MARS
                                TYwchar_t,
#endif
                                TYdchar,TYullong,TYucent,TYchar16 };
#if !MARS
    static tym_t _mptr[]    = { TYmemptr };
#endif
    static tym_t _nullptr[] = { TYnullptr };
#if TARGET_SEGMENTED
#if OMFOBJ
    static tym_t _fv[]      = { TYfptr, TYvptr };
#endif
#if TARGET_WINDOS
    static tym_t _farfunc[] = { TYffunc,TYfpfunc,TYfsfunc,TYfsysfunc };
#endif
#endif
    static tym_t _pasfunc[] = { TYnpfunc,TYnsfunc,TYmfunc,TYjfunc };
#if TARGET_SEGMENTED
    static tym_t _pasfunc_nf[] = { TYfpfunc,TYf16func,TYfsfunc, };
#endif
    static tym_t _revfunc[] = { TYnpfunc,TYjfunc };
#if TARGET_SEGMENTED
    static tym_t _revfunc_nf[] = { TYfpfunc,TYf16func, };
#endif
    static tym_t _short[]     = { TYbool,TYchar,TYschar,TYuchar,TYshort,
                                  TYwchar_t,TYushort,TYchar16 };
    static tym_t _aggregate[] = { TYstruct,TYarray };

    static struct
    {
        const char *string;     /* name of type                 */
        tym_t ty;       /* TYxxxx                       */
        tym_t unsty;    /* conversion to unsigned type  */
        tym_t relty;    /* type for relaxed type checking */
        int size;
        int debtyp;     /* Codeview 1 type in debugger record   */
        int debtyp4;    /* Codeview 4 type in debugger record   */
    } typetab[] =
    {
/* Note that chars are signed, here     */
"bool",         TYbool,         TYbool,    TYchar,      1,      0x80,   0x30,
"char",         TYchar,         TYuchar,   TYchar,      1,      0x80,   0x70,
"signed char",  TYschar,        TYuchar,   TYchar,      1,      0x80,   0x10,
"unsigned char",TYuchar,        TYuchar,   TYchar,      1,      0x84,   0x20,
"char16_t",     TYchar16,       TYchar16,  TYint,       2,      0x85,   0x21,
"short",        TYshort,        TYushort,  TYint,       SHORTSIZE, 0x81,0x11,
"wchar_t",      TYwchar_t,      TYwchar_t, TYint,       SHORTSIZE, 0x85,0x71,
"unsigned short",TYushort,      TYushort,  TYint,       SHORTSIZE, 0x85,0x21,

// These values are adjusted for 32 bit ints in cv_init() and util_set32()
"enum",         TYenum,         TYuint,    TYint,       -1,        0x81,0x72,
"int",          TYint,          TYuint,    TYint,       2,         0x81,0x72,
"unsigned",     TYuint,         TYuint,    TYint,       2,         0x85,0x73,

"long",         TYlong,         TYulong,   TYlong,      LONGSIZE,  0x82,0x12,
"unsigned long",TYulong,        TYulong,   TYlong,      LONGSIZE,  0x86,0x22,
"dchar",        TYdchar,        TYdchar,   TYlong,      4,         0x86,0x78,
"long long",    TYllong,        TYullong,  TYllong,     LLONGSIZE, 0x82,0x13,
"uns long long",TYullong,       TYullong,  TYllong,     LLONGSIZE, 0x86,0x23,
"cent",         TYcent,         TYucent,   TYcent,      16,        0x82,0x13,
"ucent",        TYucent,        TYucent,   TYcent,      16,        0x86,0x23,
"float",        TYfloat,        TYfloat,   TYfloat,     FLOATSIZE, 0x88,0x40,
"double",       TYdouble,       TYdouble,  TYdouble,    DOUBLESIZE,0x89,0x41,
"double alias", TYdouble_alias, TYdouble_alias,  TYdouble_alias,8, 0x89,0x41,
"long double",  TYldouble,      TYldouble,  TYldouble,  LNGDBLSIZE, 0x89,0x42,

"imaginary float",      TYifloat,       TYifloat,   TYifloat,   FLOATSIZE, 0x88,0x40,
"imaginary double",     TYidouble,      TYidouble,  TYidouble,  DOUBLESIZE,0x89,0x41,
"imaginary long double",TYildouble,     TYildouble, TYildouble, LNGDBLSIZE,0x89,0x42,

"complex float",        TYcfloat,       TYcfloat,   TYcfloat,   2*FLOATSIZE, 0x88,0x50,
"complex double",       TYcdouble,      TYcdouble,  TYcdouble,  2*DOUBLESIZE,0x89,0x51,
"complex long double",  TYcldouble,     TYcldouble, TYcldouble, 2*LNGDBLSIZE,0x89,0x52,

"__near *",     TYjhandle,      TYjhandle, TYjhandle,   2,  0x20,       0x100,
"nullptr_t",    TYnullptr,      TYnullptr, TYptr,       2,  0x20,       0x100,
"*",            TYnptr,         TYnptr,    TYnptr,      2,  0x20,       0x100,
"&",            TYref,          TYref,     TYref,       -1,     0,      0,
"void",         TYvoid,         TYvoid,    TYvoid,      -1,     0x85,   3,
"struct",       TYstruct,       TYstruct,  TYstruct,    -1,     0,      0,
"array",        TYarray,        TYarray,   TYarray,     -1,     0x78,   0,
"C func",       TYnfunc,        TYnfunc,   TYnfunc,     -1,     0x63,   0,
"Pascal func",  TYnpfunc,       TYnpfunc,  TYnpfunc,    -1,     0x74,   0,
"std func",     TYnsfunc,       TYnsfunc,  TYnsfunc,    -1,     0x63,   0,
"*",            TYptr,          TYptr,     TYptr,       2,  0x20,       0x100,
"member func",  TYmfunc,        TYmfunc,   TYmfunc,     -1,     0x64,   0,
"D func",       TYjfunc,        TYjfunc,   TYjfunc,     -1,     0x74,   0,
"C func",       TYhfunc,        TYhfunc,   TYhfunc,     -1,     0,      0,
"__near &",     TYnref,         TYnref,    TYnref,      2,      0,      0,

#if TARGET_SEGMENTED
"__ss *",       TYsptr,         TYsptr,    TYsptr,      2,  0x20,       0x100,
"__cs *",       TYcptr,         TYcptr,    TYcptr,      2,  0x20,       0x100,
"__far16 *",    TYf16ptr,       TYf16ptr,  TYf16ptr,    4,  0x40,       0x200,
"__far *",      TYfptr,         TYfptr,    TYfptr,      4,  0x40,       0x200,
"__huge *",     TYhptr,         TYhptr,    TYhptr,      4,  0x40,       0x300,
"__handle *",   TYvptr,         TYvptr,    TYvptr,      4,  0x40,       0x200,
"far C func",   TYffunc,        TYffunc,   TYffunc,     -1,     0x64,   0,
"far Pascal func", TYfpfunc,    TYfpfunc,  TYfpfunc,    -1,     0x73,   0,
"far std func", TYfsfunc,       TYfsfunc,  TYfsfunc,    -1,     0x64,   0,
"_far16 Pascal func", TYf16func, TYf16func, TYf16func,  -1,     0x63,   0,
"sys func",     TYnsysfunc,     TYnsysfunc,TYnsysfunc,  -1,     0x63,   0,
"far sys func", TYfsysfunc,     TYfsysfunc,TYfsysfunc,  -1,     0x64,   0,
"__far &",      TYfref,         TYfref,    TYfref,      4,      0,      0,
#endif
#if !MARS
"interrupt func", TYifunc,      TYifunc,   TYifunc,     -1,     0x64,   0,
"memptr",       TYmemptr,       TYmemptr,  TYmemptr,    -1,     0,      0,
"ident",        TYident,        TYident,   TYident,     -1,     0,      0,
"template",     TYtemplate,     TYtemplate, TYtemplate, -1,     0,      0,
"vtshape",      TYvtshape,      TYvtshape,  TYvtshape,  -1,     0,      0,
#endif
    };

    FILE *f;
    static unsigned tytab[64 * 4];
    static tym_t tytouns[64 * 4];
    static tym_t _tyrelax[TYMAX];
    static tym_t _tyequiv[TYMAX];
    static signed char tysize[64 * 4];
    static const char *tystring[TYMAX];
    static unsigned char dttab[TYMAX];
    static unsigned short dttab4[TYMAX];
    int i;

/* Repeat everything 4 times to account for the mTYconst and mTYvolatile bits */
#define T1(arr,mask) for (i=0; i<arraysize(arr); i++) \
                     {  tytab[arr[i]] |= mask; \
                        tytab[arr[i] + 64] |= mask; \
                        tytab[arr[i] + 128] |= mask; \
                        tytab[arr[i] + 192] |= mask; \
                     };
#define T2(arr,mask) for (i=0; i<arraysize(arr); i++) \
                     {  tytab[arr[i]] |= mask; \
                        tytab[arr[i] + 64] |= mask; \
                        tytab[arr[i] + 128] |= mask; \
                        tytab[arr[i] + 192] |= mask; \
                     };

    T1(_ptr,      TYFLptr);
#if TARGET_SEGMENTED
    T1(_ptr_nflat,TYFLptr);
#endif
    T1(_real,     TYFLreal);
    T1(_integral, TYFLintegral);
    T1(_imaginary,TYFLimaginary);
    T1(_complex,  TYFLcomplex);
    T1(_uns,      TYFLuns);
#if !MARS
    T1(_mptr,     TYFLmptr);
#endif

#if OMFOBJ && TARGET_SEGMENTED
    T1(_fv,       TYFLfv);
    T2(_farfunc,  TYFLfarfunc);
#endif
    T2(_pasfunc,  TYFLpascal);
    T2(_revfunc,  TYFLrevparam);
    T2(_short,    TYFLshort);
    T2(_aggregate,TYFLaggregate);
    T2(_ref,      TYFLref);
    T2(_func,     TYFLfunc);
    T2(_nullptr,  TYFLnullptr);
#if TARGET_SEGMENTED
    T2(_pasfunc_nf, TYFLpascal);
    T2(_revfunc_nf, TYFLrevparam);
    T2(_ref_nflat,  TYFLref);
    T2(_func_nflat, TYFLfunc);
#endif
#undef T1
#undef T2

    f = fopen("tytab.c","w");

    fprintf(f,"unsigned tytab[] =\n{ ");
    for (i = 0; i < arraysize(tytab); i++)
    {   fprintf(f,"0x%02x,",tytab[i]);
        if ((i & 7) == 7 && i < arraysize(tytab) - 1)
            fprintf(f,"\n  ");
    }
    fprintf(f,"\n};\n");

#if 0
    fprintf(f,"unsigned char tytab2[] =\n{ ");
    for (i = 0; i < arraysize(tytab2); i++)
    {   fprintf(f,"0x%02x,",tytab2[i]);
        if ((i & 7) == 7 && i < arraysize(tytab2) - 1)
            fprintf(f,"\n  ");
    }
    fprintf(f,"\n};\n");
#endif

    for (i = 0; i < arraysize(typetab); i++)
    {   tytouns[typetab[i].ty] = typetab[i].unsty;
        tytouns[typetab[i].ty | mTYconst] = typetab[i].unsty | mTYconst;
        tytouns[typetab[i].ty | mTYvolatile] = typetab[i].unsty | mTYvolatile;
        tytouns[typetab[i].ty | mTYconst | mTYvolatile] =
                typetab[i].unsty | mTYconst | mTYvolatile;
    }
    fprintf(f,"const tym_t tytouns[] =\n{ ");
    for (i = 0; i < arraysize(tytouns); i++)
    {   fprintf(f,"0x%02x,",tytouns[i]);
        if ((i & 7) == 7 && i < arraysize(tytouns) - 1)
            fprintf(f,"\n  ");
    }
    fprintf(f,"\n};\n");

    for (i = 0; i < arraysize(typetab); i++)
    {   tysize[typetab[i].ty | 0x00] = typetab[i].size;
        tysize[typetab[i].ty | 0x40] = typetab[i].size;
        tysize[typetab[i].ty | 0x80] = typetab[i].size;
        tysize[typetab[i].ty | 0xC0] = typetab[i].size;
        /*printf("tysize[%d] = %d\n",typetab[i].ty,typetab[i].size);*/
    }
    fprintf(f,"signed char tysize[] =\n{ ");
    for (i = 0; i < arraysize(tysize); i++)
    {   fprintf(f,"%d,",tysize[i]);
        if ((i & 7) == 7 && i < arraysize(tysize) - 1)
            fprintf(f,"\n  ");
    }
    fprintf(f,"\n};\n");

    for (i = 0; i < arraysize(tysize); i++)
        tysize[i] = 0;
    for (i = 0; i < arraysize(typetab); i++)
    {   signed char sz = typetab[i].size;
        switch (typetab[i].ty)
        {
            case TYldouble:
            case TYildouble:
            case TYcldouble:
#if TARGET_OSX
                sz = 16;
#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
                sz = 4;
#elif TARGET_WINDOS
                sz = 2;
#else
#error "fix this"
#endif
                break;
        }
        tysize[typetab[i].ty | 0x00] = sz;
        tysize[typetab[i].ty | 0x40] = sz;
        tysize[typetab[i].ty | 0x80] = sz;
        tysize[typetab[i].ty | 0xC0] = sz;
        /*printf("tyalignsize[%d] = %d\n",typetab[i].ty,typetab[i].size);*/
    }
    fprintf(f,"signed char tyalignsize[] =\n{ ");
    for (i = 0; i < arraysize(tysize); i++)
    {   fprintf(f,"%d,",tysize[i]);
        if ((i & 7) == 7 && i < arraysize(tysize) - 1)
            fprintf(f,"\n  ");
    }
    fprintf(f,"\n};\n");

    for (i = 0; i < arraysize(typetab); i++)
    {   _tyrelax[typetab[i].ty] = typetab[i].relty;
        /*printf("_tyrelax[%d] = %d\n",typetab[i].ty,typetab[i].relty);*/
    }
    fprintf(f,"unsigned char _tyrelax[] =\n{ ");
    for (i = 0; i < arraysize(_tyrelax); i++)
    {   fprintf(f,"0x%02x,",_tyrelax[i]);
        if ((i & 7) == 7 && i < arraysize(_tyrelax) - 1)
            fprintf(f,"\n  ");
    }
    fprintf(f,"\n};\n");

    /********** tyequiv[] ************/
    for (i = 0; i < arraysize(_tyequiv); i++)
        _tyequiv[i] = i;
    _tyequiv[TYchar] = TYschar;         /* chars are signed by default  */

    // These values are adjusted in util_set32() for 32 bit ints
    _tyequiv[TYint] = TYshort;
    _tyequiv[TYuint] = TYushort;

    fprintf(f,"unsigned char tyequiv[] =\n{ ");
    for (i = 0; i < arraysize(_tyequiv); i++)
    {   fprintf(f,"0x%02x,",_tyequiv[i]);
        if ((i & 7) == 7 && i < arraysize(_tyequiv) - 1)
            fprintf(f,"\n  ");
    }
    fprintf(f,"\n};\n");

    for (i = 0; i < arraysize(typetab); i++)
        tystring[typetab[i].ty] = typetab[i].string;
    fprintf(f,"const char *tystring[] =\n{ ");
    for (i = 0; i < arraysize(tystring); i++)
    {   fprintf(f,"\"%s\",",tystring[i]);
        if ((i & 7) == 7 && i < arraysize(tystring) - 1)
            fprintf(f,"\n  ");
    }
    fprintf(f,"\n};\n");

    for (i = 0; i < arraysize(typetab); i++)
        dttab[typetab[i].ty] = typetab[i].debtyp;
    fprintf(f,"unsigned char dttab[] =\n{ ");
    for (i = 0; i < arraysize(dttab); i++)
    {   fprintf(f,"0x%02x,",dttab[i]);
        if ((i & 7) == 7 && i < arraysize(dttab) - 1)
            fprintf(f,"\n  ");
    }
    fprintf(f,"\n};\n");

    for (i = 0; i < arraysize(typetab); i++)
        dttab4[typetab[i].ty] = typetab[i].debtyp4;
    fprintf(f,"unsigned short dttab4[] =\n{ ");
    for (i = 0; i < arraysize(dttab4); i++)
    {   fprintf(f,"0x%02x,",dttab4[i]);
        if ((i & 7) == 7 && i < arraysize(dttab4) - 1)
            fprintf(f,"\n  ");
    }
    fprintf(f,"\n};\n");

    fclose(f);
}
