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