]> git.gag.com Git - fw/sdcc/blob - as/mcs51/aslist.c
Initial revision
[fw/sdcc] / as / mcs51 / aslist.c
1 /* aslist.c */
2
3 /*
4  * (C) Copyright 1989-1995
5  * All Rights Reserved
6  *
7  * Alan R. Baldwin
8  * 721 Berkeley St.
9  * Kent, Ohio  44240
10  *
11  * 28-Oct-97 JLH: 
12  *           - lstsym: show s_id as string rather than array [NCPS]
13  */
14
15 #include <stdio.h>
16 #include <setjmp.h>
17 #include <string.h>
18 #include <alloc.h>
19 #include "asm.h"
20
21 /*)Module       aslist.c
22  *
23  *      The module aslist.c contains all the functions used
24  *      to generate the assembler list and symbol output files.
25  *
26  *      aslist.c contains the following functions:
27  *              VOID    list()
28  *              VOID    list1()
29  *              VOID    list2()
30  *              VOID    slew()
31  *              VOID    lstsym()
32  *
33  *      The module aslist.c contains no local/static variables
34  */
35
36 /*)Function     VOID    list()
37  *
38  *      The function list() generates the listing output
39  *      which includes the input source, line numbers,
40  *      and generated code.  Numerical output may be selected
41  *      as hexadecimal, decimal, or octal.
42  * 
43  *      local variables:
44  *              int *   wp              pointer to the assembled data bytes
45  *              int *   wpt             pointer to the data byte mode
46  *              int     nb              computed number of assembled bytes
47  *
48  *      global variables:
49  *              int     cb[]            array of assembler output values
50  *              int     cbt[]           array of assembler relocation types
51  *                                      describing the data in cb[]
52  *              int *   cp              pointer to assembler output array cb[]
53  *              int *   cpt             pointer to assembler relocation type
54  *                                      output array cbt[]
55  *              char    eb[]            array of generated error codes
56  *              char *  ep              pointer into error list
57  *                                      array eb[]
58  *              char    ib[]            assembler-source text line
59  *              FILE *  lfp             list output file handle
60  *              int     line            current assembler source line number
61  *              int     lmode           listing mode
62  *              int     xflag           -x, listing radix flag
63  *
64  *      functions called:
65  *              int     fprintf()       c_library
66  *              VOID    list1()         aslist.c
67  *              int     putc()          c_library
68  *              VOID    slew()          asslist.c
69  *
70  *      side effects:
71  *              Listing or symbol output updated.
72  */
73
74 VOID
75 list()
76 {
77         register char *wp;
78         register int *wpt;
79         register int nb;
80
81         if (lfp == NULL || lmode == NLIST)
82                 return;
83
84         /*
85          * Get Correct Line Number
86          */
87         if (incfil >= 0) {
88                 line = incline[incfil];
89                 if (line == 0) {
90                         if (incfil > 0) {
91                                 line = incline[incfil-1];
92                         } else {
93                                 line = srcline[cfile];
94                         }
95                 }
96         } else {
97                 line = srcline[cfile];
98         }
99
100         /*
101          * Move to next line.
102          */
103         slew(lfp, pflag);
104
105         /*
106          * Output a maximum of NERR error codes with listing.
107          */
108         while (ep < &eb[NERR])
109                 *ep++ = ' ';
110         fprintf(lfp, "%.2s", eb);
111
112         /*
113          * Source listing only option.
114          */
115         if (lmode == SLIST) {
116                 fprintf(lfp, "%24s%5u %s\n", "", line, ib);
117                 return;
118         }
119         if (lmode == ALIST) {
120                 outchk(HUGE,HUGE);
121         }
122
123         /*
124          * HEX output Option.
125          */
126         if (xflag == 0) {               /* HEX */
127                 /*
128                  * Equate only
129                  */
130                 if (lmode == ELIST) {
131                         fprintf(lfp, "%18s%04X", "", laddr);
132                         fprintf(lfp, "  %5u %s\n", line, ib);
133                         return;
134                 }
135
136                 /*
137                  * Address (with allocation)
138                  */
139                 fprintf(lfp, " %04X", laddr);
140                 if (lmode == ALIST || lmode == BLIST) {
141                         fprintf(lfp, "%19s%5u %s\n", "", line, ib);
142                         outdot();
143                         return;
144                 }
145                 wp = cb;
146                 wpt = cbt;
147                 nb = (int) (cp - cb);
148
149                 /*
150                  * First line of output for this source line with data.
151                  */
152                 list1(wp, wpt, nb, 1);
153                 fprintf(lfp, " %5u %s\n", line, ib);
154
155                 /*
156                  * Subsequent lines of output if more data.
157                  */
158                 while ((nb -= 6) > 0) {
159                         wp += 6;
160                         wpt += 6;
161                         slew(lfp, 0);
162                         fprintf(lfp, "%7s", "");
163                         list1(wp, wpt, nb, 0);
164                         putc('\n', lfp);
165                 }
166         } else
167         /*
168          * OCTAL output Option.
169          */
170         if (xflag == 1) {               /* OCTAL */
171                 /*
172                  * Equate only
173                  */
174                 if (lmode == ELIST) {
175                         fprintf(lfp, "%16s%06o", "", laddr);
176                         fprintf(lfp, "  %5u %s\n", line, ib);
177                         return;
178                 }
179
180                 /*
181                  * Address (with allocation)
182                  */
183                 fprintf(lfp, " %06o", laddr);
184                 if (lmode == ALIST || lmode == BLIST) {
185                         fprintf(lfp, "%17s%5u %s\n", "", line, ib);
186                         outdot();
187                         return;
188                 }
189                 wp = cb;
190                 wpt = cbt;
191                 nb = (int) (cp - cb);
192
193                 /*
194                  * First line of output for this source line with data.
195                  */
196                 list1(wp, wpt, nb, 1);
197                 fprintf(lfp, " %5u %s\n", line, ib);
198
199                 /*
200                  * Subsequent lines of output if more data.
201                  */
202                 while ((nb -= 4) > 0) {
203                         wp += 4;
204                         wpt += 4;
205                         slew(lfp, 0);
206                         fprintf(lfp, "%9s", "");
207                         list1(wp, wpt, nb, 0);
208                         putc('\n', lfp);
209                 }
210         } else
211         /*
212          * DECIMAL output Option.
213          */
214         if (xflag == 2) {               /* DECIMAL */
215                 /*
216                  * Equate only
217                  */
218                 if (lmode == ELIST) {
219                         fprintf(lfp, "%16s%05u", "", laddr);
220                         fprintf(lfp, "   %5u %s\n", line, ib);
221                         return;
222                 }
223
224                 /*
225                  * Address (with allocation)
226                  */
227                 fprintf(lfp, "  %05u", laddr);
228                 if (lmode == ALIST || lmode == BLIST) {
229                         fprintf(lfp, "%17s%5u %s\n", "", line, ib);
230                         outdot();
231                         return;
232                 }
233                 wp = cb;
234                 wpt = cbt;
235                 nb = (int) (cp - cb);
236
237                 /*
238                  * First line of output for this source line with data.
239                  */
240                 list1(wp, wpt, nb, 1);
241                 fprintf(lfp, " %5u %s\n", line, ib);
242
243                 /*
244                  * Subsequent lines of output if more data.
245                  */
246                 while ((nb -= 4) > 0) {
247                         wp += 4;
248                         wpt += 4;
249                         slew(lfp, 0);
250                         fprintf(lfp, "%9s", "");
251                         list1(wp, wpt, nb, 0);
252                         putc('\n', lfp);
253                 }
254         }
255 }
256
257 /*)Function     VOID    list1(wp, wpt, nw, f)
258  *
259  *              int     f               fill blank fields (1)
260  *              int     nb              number of data bytes
261  *              int *   wp              pointer to data bytes
262  *              int *   wpt             pointer to data byte mode
263  *
264  *      local variables:
265  *              int     i               loop counter
266  *
267  *      global variables:
268  *              int     xflag           -x, listing radix flag
269  *
270  *      functions called:
271  *              VOID    list2()         asslist.c
272  *              int     fprintf()       c_library
273  *
274  *      side effects:
275  *              Data formatted and output to listing.
276  */
277
278 VOID
279 list1(wp, wpt, nb, f)
280 register char *wp;
281 register int *wpt, nb, f;
282 {
283         register int i;
284
285         /*
286          * HEX output Option.
287          */
288         if (xflag == 0) {               /* HEX */
289                 /*
290                  * Bound number of words to HEX maximum per line.
291                  */
292                 if (nb > 6)
293                         nb = 6;
294
295                 /*
296                  * Output bytes.
297                  */
298                 for (i=0; i<nb; ++i) {
299                         list2(*wpt++);
300                         fprintf(lfp, "%02X", (*wp++)&0377);
301                 }
302
303                 /*
304                  * Output blanks if required.
305                  */
306                 if (f) {
307                         while (i < 6) {
308                                 fprintf(lfp, "   ");
309                                 ++i;
310                         }
311                 }
312         } else
313         /*
314          * OCTAL output Option.
315          */
316         if (xflag == 1) {               /* OCTAL */
317                 /*
318                  * Bound number of words to OCTAL maximum per line.
319                  */
320                 if (nb > 4)
321                         nb = 4;
322
323                 /*
324                  * Output bytes.
325                  */
326                 for (i=0; i<nb; ++i) {
327                         list2(*wpt++);
328                         fprintf(lfp, "%03o", (*wp++)&0377);
329                 }
330
331                 /*
332                  * Output blanks if required.
333                  */
334                 if (f) {
335                         while (i < 4) {
336                                 fprintf(lfp, "    ");
337                                 ++i;
338                         }
339                 }
340         } else
341         /*
342          * DECIMAL output Option.
343          */
344         if (xflag == 2) {               /* DECIMAL */
345                 /*
346                  * Bound number of words to DECIMAL maximum per line.
347                  */
348                 if (nb > 4)
349                         nb = 4;
350
351                 /*
352                  * Output bytes.
353                  */
354                 for (i=0; i<nb; ++i) {
355                         list2(*wpt++);
356                         fprintf(lfp, "%03u", (*wp++)&0377);
357                 }
358
359                 /*
360                  * Output blanks if required.
361                  */
362                 if (f) {
363                         while (i < 4) {
364                                 fprintf(lfp, "    ");
365                                 ++i;
366                         }
367                 }
368         }
369 }
370
371 /*)Function     VOID    list2(wpt)
372  *
373  *              int *   wpt             pointer to relocation mode
374  *
375  *      The function list2() outputs the selected
376  *      relocation flag as specified by fflag.
377  *
378  *      local variables:
379  *              int     c               relocation flag character
380  *              int     t               relocation mode
381  *
382  *      global variables:
383  *              int     fflag           -f(f), relocations flagged flag
384  *
385  *      functions called:
386  *              int     putc()          c_library
387  *
388  *      side effects:
389  *              Relocation flag output to listing file.
390  */
391
392 VOID
393 list2(t)
394 register int t;
395 {
396         register int c;
397
398         c = ' ';
399
400         /*
401          * Designate a relocatable word by `.
402          */
403         if (fflag == 1) {
404                 if (t & R_RELOC) {
405                         c = '`';
406                 }
407         } else
408         /*
409          * Designate a relocatable word by its mode:
410          *      page0 or paged          *
411          *      unsigned                u (v)
412          *      operand offset          p (q)
413          *      relocatable symbol      r (s)
414          */
415         if (fflag >= 2) {
416                 if (t & R_RELOC) {
417                         if (t & (R_PAG0|R_PAG)) {
418                                 c = '*';
419                         } else if (t & R_USGN) {
420                                 c = 'u';
421                         } else if (t & R_PCR) {
422                                 c = 'p';
423                         } else {
424                                 c = 'r';
425                         }
426                         if (t & R_HIGH) c += 1;
427                 }
428         }
429
430         /*
431          * Output the selected mode.
432          */
433         putc(c, lfp);
434 }
435
436 /*)Function     VOID    slew(fp, flag)
437  *
438  *              FILE *  fp              file handle for listing
439  *              int     flag            enable pagination
440  *
441  *      The function slew() increments the page line count.
442  *      If the page overflows and pagination is enabled:
443  *              1)      put out a page skip,
444  *              2)      a title,
445  *              3)      a subtitle,
446  *              4)      and reset the line count.
447  *
448  *      local variables:
449  *              none
450  *
451  *      global variables:
452  *              char    cpu[]           cpu type string
453  *              int     lop             current line number on page
454  *              int     page            current page number
455  *              char    stb[]           Subtitle string buffer
456  *              char    tb[]            Title string buffer
457  *
458  *      functions called:
459  *              int     fprintf()       c_library
460  *
461  *      side effects:
462  *              Increments page line counter, on overflow
463  *              a new page header is output to the listing file.
464  */
465
466 VOID
467 slew(fp,flag)
468 FILE *fp;
469 int flag;
470 {
471         if ((lop++ >= NLPP) && flag) {
472                 fprintf(fp, "\fASxxxx Assembler %s  (%s), page %u.\n",
473                         VERSION, cpu, ++page);
474                 fprintf(fp, "%s\n", tb);
475                 fprintf(fp, "%s\n\n", stb);
476                 lop = 5;
477         }
478 }
479
480 /*)Function     VOID    lstsym(fp)
481  *
482  *              FILE *  fp              file handle for output
483  *
484  *      The function lstsym() outputs alphabetically
485  *      sorted symbol and area tables.
486  *
487  *      local variables:
488  *              int     c               temporary
489  *              int     i               loop counter
490  *              int     j               temporary
491  *              int     k               temporary
492  *              char *  ptr             pointer to an id string
493  *              int     nmsym           number of symbols
494  *              int     narea           number of areas
495  *              sym *   sp              pointer to symbol structure
496  *              sym **  p               pointer to an array of
497  *                                      pointers to symbol structures
498  *              area *  ap              pointer to an area structure
499  *
500  *      global variables:
501  *              area *  areap           pointer to an area structure
502  *              char    aretbl[]        string "Area Table"
503  *              sym     dot             defined as sym[0]
504  *              char    stb[]           Subtitle string buffer
505  *              sym * symhash[]         array of pointers to NHASH
506  *                                      linked symbol lists
507  *              char    symtbl[]        string "Symbol Table"
508  *              FILE *  tfp             symbol table output file handle
509  *              int     xflag           -x, listing radix flag
510  *
511  *      functions called:
512  *              int     fprintf()       c_library
513  *              int     putc()          c_library
514  *              VOID    slew()          aslist.c
515  *              int     strcmp()        c_library
516  *              char *  strcpy()        c_library
517  *
518  *      side effects:
519  *              Symbol and area tables output.
520  */
521
522 VOID
523 lstsym(fp)
524 FILE *fp;
525 {
526         register int c, i, j, k;
527         register char *ptr;
528         int nmsym, narea;
529         struct sym *sp;
530         struct sym **p;
531         struct area *ap;
532
533         /*
534          * Symbol Table Header
535          */
536         strcpy(stb, &symtbl[0]);
537         lop = NLPP;
538         if (fp == tfp)
539                 page = 0;
540         slew(fp, 1);
541
542         /*
543          * Find number of symbols
544          */
545         nmsym = 0;
546         for (i=0; i<NHASH; i++) {
547                 sp = symhash[i];
548                 while (sp) {
549                         if (sp != &dot)
550                                 ++nmsym;
551                         sp = sp->s_sp;
552                 }
553         }
554         if (nmsym == 0)
555                 goto atable;
556
557         /*
558          * Allocate space for an array of pointers to symbols
559          * and load array.
560          */
561         if ((p = (struct sym **) malloc(sizeof((struct sym *) sp)*nmsym))
562                 == NULL) {
563                 fprintf(fp, "Insufficient space to build Symbol Table.\n");
564                 return;
565         }
566         nmsym = 0;
567         for (i=0; i<NHASH; i++) {
568                 sp = symhash[i];
569                 while (sp) {
570                         if (sp != &dot)
571                                 p[nmsym++] = sp;
572                         sp = sp->s_sp;
573                 }
574         }
575
576         /*
577          * Bubble Sort on Symbol Table Array
578          */
579         j = 1;
580         c = nmsym - 1;
581         while (j) {
582                 j = 0;
583                 for (i=0; i<c; ++i) {
584                         if (strcmp(&p[i]->s_id[0],&p[i+1]->s_id[0]) > 0) {
585                                 j = 1;
586                                 sp = p[i+1];
587                                 p[i+1] = p[i];
588                                 p[i] = sp;
589                         }
590                 }
591         }
592
593         /*
594          * Symbol Table Output
595          */
596         for (i=0; i<nmsym;) {
597                 sp = p[i];
598                 if (sp->s_area) {
599                         j = sp->s_area->a_ref;
600                         if (xflag == 0) {
601                                 fprintf(fp, " %2X ", j);
602                         } else
603                         if (xflag == 1) {
604                                 fprintf(fp, "%3o ", j);
605                         } else
606                         if (xflag == 2) {
607                                 fprintf(fp, "%3u ", j);
608                         }
609                 } else {
610                         fprintf(fp, "    ");
611                 }
612                 ptr = &sp->s_id[0];
613                 fprintf(fp, "%-60s", ptr );     /* JLH */
614
615                 if (sp->s_flag & S_ASG) {
616                         putc('=', fp);
617                 } else {
618                         putc(' ', fp);
619                 }
620                 if (sp->s_type == S_NEW) {
621                         if (xflag == 0) {
622                                 fprintf(fp, "  **** ");
623                         } else
624                         if (xflag == 1) {
625                                 fprintf(fp, "****** ");
626                         } else
627                         if (xflag == 2) {
628                                 fprintf(fp, " ***** ");
629                         }
630                 } else {
631                         j = sp->s_addr;
632                         if (xflag == 0) {
633                                 fprintf(fp, "  %04X ", j);
634                         } else
635                         if (xflag == 1) {
636                                 fprintf(fp, "%06o ", j);
637                         } else
638                         if (xflag == 2) {
639                                 fprintf(fp, " %05u ", j);
640                         }
641                 }
642                 j = 0;
643                 if (sp->s_flag & S_GBL) {
644                         putc('G', fp);
645                         ++j;
646                 }
647                 if (sp->s_area != NULL) {
648                         putc('R', fp);
649                         ++j;
650                 }
651                 if (sp->s_type == S_NEW) {
652                         putc('X', fp);
653                         ++j;
654                 }
655 #if NCPS-8
656                 putc('\n', fp);
657                 slew(fp, 0);
658                 ++i;
659 #else
660                 if (++i % 3 == 0) {
661                         putc('\n', fp);
662                         slew(fp, pflag);
663                 } else
664                 if (i < nmsym) {
665                         while (j++ < 4)
666                                 putc(' ', fp);
667                         fprintf(fp, "| ");
668                 }
669 #endif
670         }
671         putc('\n', fp);
672
673         /*
674          * Area Table Header
675          */
676
677 atable:
678         strcpy(stb, &aretbl[0]);
679         lop = NLPP;
680         slew(fp, 1);
681
682         /*
683          * Area Table Output
684          */
685         narea = 0;
686         ap = areap;
687         while (ap) {
688                 ++narea;
689                 ap = ap->a_ap;
690         }
691         for (i=0; i<narea; ++i) {
692                 ap = areap;
693                 for (j=i+1; j<narea; ++j)
694                         ap = ap->a_ap;
695                 j = ap->a_ref;
696                 if (xflag == 0) {
697                         fprintf(fp, "  %2X ", j);
698                 } else
699                 if (xflag == 1) {
700                         fprintf(fp, " %3o ", j);
701                 } else
702                 if (xflag == 2) {
703                         fprintf(fp, " %3u ", j);
704                 }
705                 ptr = &ap->a_id[0];
706                 while (ptr < &ap->a_id[NCPS]) {
707                         if ((c = *ptr++) != 0) {
708                                 putc(c, fp);
709                         } else {
710                                 putc(' ', fp);
711                         }
712                 }
713                 j = ap->a_size;
714                 k = ap->a_flag;
715                 if (xflag==0) {
716                         fprintf(fp, "   size %4X   flags %X\n", j, k);
717                 } else
718                 if (xflag==1) {
719                         fprintf(fp, "   size %6o   flags %o\n", j, k);
720                 } else
721                 if (xflag==2) {
722                         fprintf(fp, "   size %5u   flags %u\n", j, k);
723                 }
724         }               
725 }