*/
Are you blogging on PH? Get your free blog.
*/

View \EMITTER.C

An 8031/8051 assembler win source

Submitted By: Unknown
Rating: starstarstarstar (Rate It)


/*
 * emitter.c
 *
 * PACKAGE: as31 - 8031/8051 Assembler.
 *
 * DESCRIPTION:
 *      This file contains the code to generate various
 *      object code formats. Provisions exist to
 *      support many types of output formats within the
 *      same executable.
 *
 * REVISION HISTORY:
 *      Jan. 19, 1990 - Created. (Ken Stauffer)
 *      Jan. 29, 1990 - Added S-records (Theo Deraadt)
 *
 * AUTHOR:
 *      All code in this file written by Ken Stauffer (University of Calgary).
 *      January, 1990.
 */


#include <stdio.h>

#ifdef __TURBOC__
void    finishline(void);
void    dumpline(long, unsigned char *, int);
#endif

/*
 * DECLARE your own open(), close(), addr(), and byte() routines here.
 */


static void open1(), close1(), addr1(), byte1();
static void open2(), close2(), addr2(), byte2();
static void open3(), close3(), addr3(), byte3();
static void open4(), close4(), addr4(), byte4();

/*
 * ADD an entry to this table to register your
 * output format routines. Give your object format
 * a name to be specified with the -F option.
 */


static int format;

static struct {
        char    *name;
        void    (*e_open)();
        void    (*e_close)();
        void    (*e_addr)();
        void    (*e_byte)();
} formtab[] = {
        { "tdr",   open1, close1, addr1, byte1 },
        { "byte",  open2, close2, addr2, byte2 },
        { "od",    open3, close3, addr3, byte3 },
        { "srec2", open4, close4, addr4, byte4 },
        { "srec3", open4, close4, addr4, byte4 },
        { "srec4", open4, close4, addr4, byte4 }
};

#define FORMTABSIZE     (sizeof(formtab)/sizeof(formtab[0]))

void emitusage()
{
        int     i;

        fprintf(stderr, "\tfmt is one of:");

        for (i = 0; i < FORMTABSIZE; )  {
                fprintf(stderr, "%s", formtab[i].name);
                if (++i < FORMTABSIZE)
                        fprintf(stderr, ", ");
        }

        fprintf(stderr, ".\n");
}

void emitopen(file, ftype, arg)
char    *file, *ftype, *arg;
{
        int     i;

        if (ftype)  {
                for (i = 0; i < FORMTABSIZE; i++)  {
                        if (!strcmp(formtab[i].name, ftype))  {
                                format = i;
                                (*formtab[format].e_open)(file, ftype, arg);
                                return;
                        }
                }

                fprintf(stderr, "warning: no format \"%s\", using \"%s\"\n",
                        ftype, formtab[0].name);
        }

        /*
         * 0th entry is the default format type
         */


        format = 0;
        (*formtab[format].e_open)(file, ftype, arg);
}

void emitclose()
{
        (*formtab[format].e_close)();
}

void emitaddr(a)
long    a;
{
        (*formtab[format].e_addr)(a);
}

void emitbyte(b)
int     b;
{
        (*formtab[format].e_byte)(b);
}

/*
 * Individual file format routines appear here:
 *      Each file format must define the following routines:
 *            open()        - Called ONCE before any of the others.
 *                  It is passed with a filename and a format
 *                  specific argument.
 *
 *            close() - Called ONCE when no more emit_byte()
 *                  function calls will be made.
 *
 *            addr() - Called when ever a new address has been set
 *                  in the assembler (ie. .org, .skip).
 *                  This routine is also called once when the
 *                  location counter is set to 0 at the very start of
 *                  assembling.
 *
 *            byte() - Called with each byte to be outputed.
 */


/*
 * "tdr" format. For tdr's 68008 system. Generates a
 * script file readable by a debugger.
 *      [addr] : [byte] [byte] ..
 *
 * arg: This is a number in decimal which specifies
 *      the offset, -Ftdr -A0000
 *
 *      These options specifies the tdr format, with an argument
 *      of 0. This becomes the offset used in generating the
 *      script file. The default if no A is present is 0x10000.
 */


static long     addr;
static FILE     *fout;
static long     offset;
static int      newaddr;
static int      pos = -666;

static void open1(file, ftype, arg)
char    *file, *ftype, *arg;
{
        fout = fopen(file, "w");

        if (fout == NULL)  {
                fprintf(stderr, "Cannot open %s for writting.\n", file);
                exit(1);
        }

        if (arg)  {
                offset = atoi(arg);
        } else
                offset = 0x10000;
}

static void close1()
{
        if (pos != 15)
                fprintf(fout, "\n");

        fclose(fout);
}

static void addr1(a)
long    a;
{
        addr = a;
        newaddr = 1;
}

static void byte1(b)
unsigned char b;
{
        if (newaddr)  {
                if (pos != -666)
                        fprintf(fout, "\n");

                newaddr = 0;
                pos = 15;
                fprintf(fout, "%06X: ", addr + offset);
        } else if (pos == 15)
                fprintf(fout, "%06X: ", addr + offset);

        fprintf(fout, "%02X ", b & 0xff);

        if (pos-- == 0)  {
                fprintf(fout, "\n");
                pos = 15;
        }

        addr += 1;
}

/*
 * "byte" format.
 *      Like "tdr" but each byte is on a line by itself.
 *      This is nice for debugging. No -A is used.
 */


static void open2(file, ftype, arg)
char    *file, *ftype, *arg;
{
        fout = fopen(file, "w");

        if (fout == NULL)  {
                fprintf(stderr, "Cannot open %s for writting.\n", file);
                exit(1);
        }
}

static void close2()
{
        fclose(fout);
}

static void addr2(a)
long    a;
{
        addr = a;
}

static void byte2(b)
unsigned char b;
{
        fprintf(fout, "%04X: %02X\n", addr, b & 0xff);
        addr += 1;
}

/*
 * "od", this format shows 16 bytes per line, with address.
 *      It also includes ascii on one side.
 *
 * The format is similar to the od(1) program under Unix(tm).
 */


static int      pos3;
static unsigned char buf[16];
static long     saveaddr;

static void open3(file, ftype, arg)
char    *file, *arg;
{
        fout = fopen(file, "w");

        if (fout == NULL)  {
                fprintf(stderr, "Cannot open %s for writting.\n", file);
                exit(1);
        }
}

static void close3()
{
        dumpline(saveaddr, buf, pos3 - 1);
        fclose(fout);
}

static void addr3(a)
long    a;
{
        newaddr = 1;
        addr = a;
}

static void byte3(b)
unsigned char b;
{
        if (newaddr)  {
                dumpline(saveaddr, buf, pos3 - 1);
                pos3 = 0;
                newaddr = 0;
                saveaddr = addr;
        } else if (pos3 == 16)  {
                dumpline(saveaddr, buf, pos3 - 1);
                pos3 = 0;
                saveaddr = addr;
        }

        buf[pos3++] = b & 0x00ff;

        addr += 1;
}

void dumpline(a, b, len)
long    a;
unsigned char *b;
int     len;
{
        int     i;

        if (len <= 0)
                return;

        fprintf(fout, "%04X: ", a);

        for (i = 0; i < 8; i++)  {
                if (i <= len)
                        fprintf(fout, "%02X ", b[i]);
                else
                        fprintf(fout,"   ");
        }

        fprintf(fout, "- ");

        for (i = 8; i < 16; i++)  {
                if (i <= len)
                        fprintf(fout, "%02X ", b[i]);
                else
                        fprintf(fout, "   ");
        }

        fprintf(fout, "   ");

        for (i = 0; i < 16; i++)  {
                if (i <= len)
                        fprintf(fout, "%c",
                                (b[i] >= ' ' && b[i] <= '~') ? b[i] : '.' );
                else
                        break;
        }

        fprintf(fout, "\n");
}

/*
 * srecord format. This is called with "-Fsrec2", "-Fsrec3", or
 * "-Fsrec4"...
 *
 * arg: This is a number in decimal which specifies
 *      the offset, -Fsrec3 -A0000
 *
 *      These options specifies the tdr format, with an argument
 *      of 0. This becomes the offset used in generating the
 *      script file. The default if no A is present is 0x0000.
 */


#define SREC_BYTESPERLINE 32

static char     format4;
static int      check4, index4;
static char     buf4[SREC_BYTESPERLINE];
static long     address4;

static void open4(file, ftype, arg)
char    *file, *ftype, *arg;
{
        format4 = ftype[4];          /* will be '2' -- '4' */

        fout = fopen(file, "w");
        if (fout == NULL)  {
                fprintf(stderr, "Cannot open %s for writing.\n", file);
                exit(1);
        }

        if (arg)
                offset = atoi(arg);
        else
                offset = 0;

        fprintf(fout, "S0030000%02X\n", (~3 & 0xff));
}

static void close4()
{
        if (index4)
                finishline();

        switch (format4)  {
        case '2':
                fprintf(fout, "S9030000%02X\n", ~3 & 0xff);
                break;
        case '3':
                fprintf(fout, "S804000000%02X\n", ~4 & 0xff);
                break;
        case '4':
                fprintf(fout, "S70500000000%02X\n", ~5 & 0xff);
                break;
        }

        fclose(fout);
}

static void addr4(a)
long    a;
{
        if (index4 > 0)
                finishline();

        address4 = a + offset;
}

static void byte4(b)
{
        buf4[index4++] = b;
        if (index4 == SREC_BYTESPERLINE)  {
                finishline();
                address4 += SREC_BYTESPERLINE;
        }
}

void finishline()
{
        int     i;

        check4 = index4 + (address4 & 0xff) + ((address4 >> 8) & 0xff) + 4;

        switch (format4)  {
        case '2':
                fprintf(fout, "S1%02X%04X", index4 + 4, address4 & 0xffff);
                break;
        case '3':
                fprintf(fout, "S2%02X%06X", index4 + 6, address4 & 0xffffff);
                check4 += ((address4 >> 16) & 0xff) + 2;
                break;
        case '4':
                fprintf(fout, "S3%02X%08X", index4 + 8, address4);
                check4 += ((address4 >> 16) & 0xff) + ((address4 >> 24) & 0xff) + 4;
                break;
        }

        for (i = 0; i < index4; i++)  {
                fprintf(fout, "%02X", buf4[i] & 0xff);
                check4 += buf4[i];
        }

        fprintf(fout, "%02X\n", (~check4 & 0xff) );
        index4 = 0;
}

corner
© 1996-2008 CommunityHeaven LLC. All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
North American business development: Nicolai Wadstrom. Publisher: Lars Hagelin.