gbdk-releases/sdcc/as/mcs51/aslist.c
2015-01-10 16:25:09 +01:00

740 lines
13 KiB
C

/* aslist.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*
* 28-Oct-97 JLH:
* - lstsym: show s_id as string rather than array [NCPS]
*/
#include <stdio.h>
#include <setjmp.h>
#include <string.h>
#include <stdlib.h>
#include "asm.h"
/*)Module aslist.c
*
* The module aslist.c contains all the functions used
* to generate the assembler list and symbol output files.
*
* aslist.c contains the following functions:
* VOID list()
* VOID list1()
* VOID list2()
* VOID slew()
* VOID lstsym()
*
* The module aslist.c contains no local/static variables
*/
/*)Function VOID list()
*
* The function list() generates the listing output
* which includes the input source, line numbers,
* and generated code. Numerical output may be selected
* as hexadecimal, decimal, or octal.
*
* local variables:
* int * wp pointer to the assembled data bytes
* int * wpt pointer to the data byte mode
* int nb computed number of assembled bytes
*
* global variables:
* int cb[] array of assembler output values
* int cbt[] array of assembler relocation types
* describing the data in cb[]
* int * cp pointer to assembler output array cb[]
* int * cpt pointer to assembler relocation type
* output array cbt[]
* char eb[] array of generated error codes
* char * ep pointer into error list
* array eb[]
* char ib[] assembler-source text line
* FILE * lfp list output file handle
* int line current assembler source line number
* int lmode listing mode
* int xflag -x, listing radix flag
*
* functions called:
* int fprintf() c_library
* VOID list1() aslist.c
* int putc() c_library
* VOID slew() asslist.c
*
* side effects:
* Listing or symbol output updated.
*/
VOID
list()
{
register char *wp;
register int *wpt;
register int nb;
if (lfp == NULL || lmode == NLIST)
return;
/*
* Get Correct Line Number
*/
if (incfil >= 0) {
line = incline[incfil];
if (line == 0) {
if (incfil > 0) {
line = incline[incfil-1];
} else {
line = srcline[cfile];
}
}
} else {
line = srcline[cfile];
}
/*
* Move to next line.
*/
slew(lfp, pflag);
/*
* Output a maximum of NERR error codes with listing.
*/
while (ep < &eb[NERR])
*ep++ = ' ';
fprintf(lfp, "%.2s", eb);
/*
* Source listing only option.
*/
if (lmode == SLIST) {
fprintf(lfp, "%24s%5u %s\n", "", line, ib);
return;
}
if (lmode == ALIST) {
outchk(HUGE,HUGE);
}
/*
* HEX output Option.
*/
if (xflag == 0) { /* HEX */
/*
* Equate only
*/
if (lmode == ELIST) {
fprintf(lfp, "%18s%04X", "", laddr);
fprintf(lfp, " %5u %s\n", line, ib);
return;
}
/*
* Address (with allocation)
*/
fprintf(lfp, " %04X", laddr);
if (lmode == ALIST || lmode == BLIST) {
fprintf(lfp, "%19s%5u %s\n", "", line, ib);
outdot();
return;
}
wp = cb;
wpt = cbt;
nb = (int) (cp - cb);
/*
* First line of output for this source line with data.
*/
list1(wp, wpt, nb, 1);
fprintf(lfp, " %5u %s\n", line, ib);
/*
* Subsequent lines of output if more data.
*/
while ((nb -= 6) > 0) {
wp += 6;
wpt += 6;
slew(lfp, 0);
fprintf(lfp, "%7s", "");
list1(wp, wpt, nb, 0);
putc('\n', lfp);
}
} else
/*
* OCTAL output Option.
*/
if (xflag == 1) { /* OCTAL */
/*
* Equate only
*/
if (lmode == ELIST) {
fprintf(lfp, "%16s%06o", "", laddr);
fprintf(lfp, " %5u %s\n", line, ib);
return;
}
/*
* Address (with allocation)
*/
fprintf(lfp, " %06o", laddr);
if (lmode == ALIST || lmode == BLIST) {
fprintf(lfp, "%17s%5u %s\n", "", line, ib);
outdot();
return;
}
wp = cb;
wpt = cbt;
nb = (int) (cp - cb);
/*
* First line of output for this source line with data.
*/
list1(wp, wpt, nb, 1);
fprintf(lfp, " %5u %s\n", line, ib);
/*
* Subsequent lines of output if more data.
*/
while ((nb -= 4) > 0) {
wp += 4;
wpt += 4;
slew(lfp, 0);
fprintf(lfp, "%9s", "");
list1(wp, wpt, nb, 0);
putc('\n', lfp);
}
} else
/*
* DECIMAL output Option.
*/
if (xflag == 2) { /* DECIMAL */
/*
* Equate only
*/
if (lmode == ELIST) {
fprintf(lfp, "%16s%05u", "", laddr);
fprintf(lfp, " %5u %s\n", line, ib);
return;
}
/*
* Address (with allocation)
*/
fprintf(lfp, " %05u", laddr);
if (lmode == ALIST || lmode == BLIST) {
fprintf(lfp, "%17s%5u %s\n", "", line, ib);
outdot();
return;
}
wp = cb;
wpt = cbt;
nb = (int) (cp - cb);
/*
* First line of output for this source line with data.
*/
list1(wp, wpt, nb, 1);
fprintf(lfp, " %5u %s\n", line, ib);
/*
* Subsequent lines of output if more data.
*/
while ((nb -= 4) > 0) {
wp += 4;
wpt += 4;
slew(lfp, 0);
fprintf(lfp, "%9s", "");
list1(wp, wpt, nb, 0);
putc('\n', lfp);
}
}
}
/*)Function VOID list1(wp, wpt, nw, f)
*
* int f fill blank fields (1)
* int nb number of data bytes
* int * wp pointer to data bytes
* int * wpt pointer to data byte mode
*
* local variables:
* int i loop counter
*
* global variables:
* int xflag -x, listing radix flag
*
* functions called:
* VOID list2() asslist.c
* int fprintf() c_library
*
* side effects:
* Data formatted and output to listing.
*/
VOID
list1(wp, wpt, nb, f)
register char *wp;
register int *wpt, nb, f;
{
register int i;
/*
* HEX output Option.
*/
if (xflag == 0) { /* HEX */
/*
* Bound number of words to HEX maximum per line.
*/
if (nb > 6)
nb = 6;
/*
* Output bytes.
*/
for (i=0; i<nb; ++i) {
list2(*wpt++);
fprintf(lfp, "%02X", (*wp++)&0377);
}
/*
* Output blanks if required.
*/
if (f) {
while (i < 6) {
fprintf(lfp, " ");
++i;
}
}
} else
/*
* OCTAL output Option.
*/
if (xflag == 1) { /* OCTAL */
/*
* Bound number of words to OCTAL maximum per line.
*/
if (nb > 4)
nb = 4;
/*
* Output bytes.
*/
for (i=0; i<nb; ++i) {
list2(*wpt++);
fprintf(lfp, "%03o", (*wp++)&0377);
}
/*
* Output blanks if required.
*/
if (f) {
while (i < 4) {
fprintf(lfp, " ");
++i;
}
}
} else
/*
* DECIMAL output Option.
*/
if (xflag == 2) { /* DECIMAL */
/*
* Bound number of words to DECIMAL maximum per line.
*/
if (nb > 4)
nb = 4;
/*
* Output bytes.
*/
for (i=0; i<nb; ++i) {
list2(*wpt++);
fprintf(lfp, "%03u", (*wp++)&0377);
}
/*
* Output blanks if required.
*/
if (f) {
while (i < 4) {
fprintf(lfp, " ");
++i;
}
}
}
}
/*)Function VOID list2(wpt)
*
* int * wpt pointer to relocation mode
*
* The function list2() outputs the selected
* relocation flag as specified by fflag.
*
* local variables:
* int c relocation flag character
* int t relocation mode
*
* global variables:
* int fflag -f(f), relocations flagged flag
*
* functions called:
* int putc() c_library
*
* side effects:
* Relocation flag output to listing file.
*/
VOID
list2(t)
register int t;
{
register int c;
c = ' ';
/*
* Designate a relocatable word by `.
*/
if (fflag == 1) {
if (t & R_RELOC) {
c = '`';
}
} else
/*
* Designate a relocatable word by its mode:
* page0 or paged *
* unsigned u (v)
* operand offset p (q)
* relocatable symbol r (s)
*/
if (fflag >= 2) {
if (t & R_RELOC) {
if (t & (R_PAG0|R_PAG)) {
c = '*';
} else if (t & R_USGN) {
c = 'u';
} else if (t & R_PCR) {
c = 'p';
} else {
c = 'r';
}
if (t & R_HIGH) c += 1;
}
}
/*
* Output the selected mode.
*/
putc(c, lfp);
}
/*)Function VOID slew(fp, flag)
*
* FILE * fp file handle for listing
* int flag enable pagination
*
* The function slew() increments the page line count.
* If the page overflows and pagination is enabled:
* 1) put out a page skip,
* 2) a title,
* 3) a subtitle,
* 4) and reset the line count.
*
* local variables:
* none
*
* global variables:
* char cpu[] cpu type string
* int lop current line number on page
* int page current page number
* char stb[] Subtitle string buffer
* char tb[] Title string buffer
*
* functions called:
* int fprintf() c_library
*
* side effects:
* Increments page line counter, on overflow
* a new page header is output to the listing file.
*/
VOID
slew(fp,flag)
FILE *fp;
int flag;
{
if ((lop++ >= NLPP) && flag) {
fprintf(fp, "\fASxxxx Assembler %s (%s), page %u.\n",
VERSION, cpu, ++page);
fprintf(fp, "%s\n", tb);
fprintf(fp, "%s\n\n", stb);
lop = 5;
}
}
/* Used for qsort call in lstsym */
static int _cmpSym(const void *p1, const void *p2)
{
struct sym **s1 = (struct sym **)(p1);
struct sym **s2 = (struct sym **)(p2);
return strcmp((*s1)->s_id,(*s2)->s_id);
}
/*)Function VOID lstsym(fp)
*
* FILE * fp file handle for output
*
* The function lstsym() outputs alphabetically
* sorted symbol and area tables.
*
* local variables:
* int c temporary
* int i loop counter
* int j temporary
* int k temporary
* char * ptr pointer to an id string
* int nmsym number of symbols
* int narea number of areas
* sym * sp pointer to symbol structure
* sym ** p pointer to an array of
* pointers to symbol structures
* area * ap pointer to an area structure
*
* global variables:
* area * areap pointer to an area structure
* char aretbl[] string "Area Table"
* sym dot defined as sym[0]
* char stb[] Subtitle string buffer
* sym * symhash[] array of pointers to NHASH
* linked symbol lists
* char symtbl[] string "Symbol Table"
* FILE * tfp symbol table output file handle
* int xflag -x, listing radix flag
*
* functions called:
* int fprintf() c_library
* int putc() c_library
* VOID slew() aslist.c
* int strcmp() c_library
* char * strcpy() c_library
*
* side effects:
* Symbol and area tables output.
*/
VOID
lstsym(fp)
FILE *fp;
{
register int c, i, j, k;
register char *ptr;
int nmsym, narea;
struct sym *sp;
struct sym **p;
struct area *ap;
/*
* Symbol Table Header
*/
strcpy(stb, &symtbl[0]);
lop = NLPP;
if (fp == tfp)
page = 0;
slew(fp, 1);
/*
* Find number of symbols
*/
nmsym = 0;
for (i=0; i<NHASH; i++) {
sp = symhash[i];
while (sp) {
if (sp != &dot)
++nmsym;
sp = sp->s_sp;
}
}
if (nmsym == 0)
goto atable;
/*
* Allocate space for an array of pointers to symbols
* and load array.
*/
if ((p = (struct sym **) malloc(sizeof((struct sym *) sp)*nmsym))
== NULL) {
fprintf(fp, "Insufficient space to build Symbol Table.\n");
return;
}
nmsym = 0;
for (i=0; i<NHASH; i++) {
sp = symhash[i];
while (sp) {
if (sp != &dot)
p[nmsym++] = sp;
sp = sp->s_sp;
}
}
#if 0
/* BUBBLE SORT?? WTF??? */
/*
* Bubble Sort on Symbol Table Array
*/
j = 1;
c = nmsym - 1;
while (j) {
j = 0;
for (i=0; i<c; ++i) {
if (strcmp(&p[i]->s_id[0],&p[i+1]->s_id[0]) > 0) {
j = 1;
sp = p[i+1];
p[i+1] = p[i];
p[i] = sp;
}
}
}
#else
qsort(p, nmsym, sizeof(struct sym *), _cmpSym);
#endif
/*
* Symbol Table Output
*/
for (i=0; i<nmsym;) {
sp = p[i];
if (sp->s_area) {
j = sp->s_area->a_ref;
if (xflag == 0) {
fprintf(fp, " %2X ", j);
} else
if (xflag == 1) {
fprintf(fp, "%3o ", j);
} else
if (xflag == 2) {
fprintf(fp, "%3u ", j);
}
} else {
fprintf(fp, " ");
}
ptr = &sp->s_id[0];
fprintf(fp, "%-60s", ptr ); /* JLH */
if (sp->s_flag & S_ASG) {
putc('=', fp);
} else {
putc(' ', fp);
}
if (sp->s_type == S_NEW) {
if (xflag == 0) {
fprintf(fp, " **** ");
} else
if (xflag == 1) {
fprintf(fp, "****** ");
} else
if (xflag == 2) {
fprintf(fp, " ***** ");
}
} else {
j = sp->s_addr;
if (xflag == 0) {
fprintf(fp, " %04X ", j);
} else
if (xflag == 1) {
fprintf(fp, "%06o ", j);
} else
if (xflag == 2) {
fprintf(fp, " %05u ", j);
}
}
j = 0;
if (sp->s_flag & S_GBL) {
putc('G', fp);
++j;
}
if (sp->s_area != NULL) {
putc('R', fp);
++j;
}
if (sp->s_type == S_NEW) {
putc('X', fp);
++j;
}
#if NCPS-8
putc('\n', fp);
slew(fp, 0);
++i;
#else
if (++i % 3 == 0) {
putc('\n', fp);
slew(fp, pflag);
} else
if (i < nmsym) {
while (j++ < 4)
putc(' ', fp);
fprintf(fp, "| ");
}
#endif
}
putc('\n', fp);
/*
* Area Table Header
*/
atable:
strcpy(stb, &aretbl[0]);
lop = NLPP;
slew(fp, 1);
/*
* Area Table Output
*/
narea = 0;
ap = areap;
while (ap) {
++narea;
ap = ap->a_ap;
}
for (i=0; i<narea; ++i) {
ap = areap;
for (j=i+1; j<narea; ++j)
ap = ap->a_ap;
j = ap->a_ref;
if (xflag == 0) {
fprintf(fp, " %2X ", j);
} else
if (xflag == 1) {
fprintf(fp, " %3o ", j);
} else
if (xflag == 2) {
fprintf(fp, " %3u ", j);
}
ptr = &ap->a_id[0];
while (ptr < &ap->a_id[NCPS]) {
if ((c = *ptr++) != 0) {
putc(c, fp);
} else {
putc(' ', fp);
}
}
j = ap->a_size;
k = ap->a_flag;
if (xflag==0) {
fprintf(fp, " size %4X flags %X\n", j, k);
} else
if (xflag==1) {
fprintf(fp, " size %6o flags %o\n", j, k);
} else
if (xflag==2) {
fprintf(fp, " size %5u flags %u\n", j, k);
}
}
}