* as/hc08/Makefile.bcc, as/hc08/Makefile.in, as/hc08/as_hc08.dsp,
[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  *              char *  ptr             pointer to an id string
569  *              int     nmsym           number of symbols
570  *              int     narea           number of areas
571  *              sym *   sp              pointer to symbol structure
572  *              sym **  p               pointer to an array of
573  *                                      pointers to symbol structures
574  *              area *  ap              pointer to an area structure
575  *
576  *      global variables:
577  *              area *  areap           pointer to an area structure
578  *              char    aretbl[]        string "Area Table"
579  *              sym     dot             defined as sym[0]
580  *              char    stb[]           Subtitle string buffer
581  *              sym * symhash[]         array of pointers to NHASH
582  *                                      linked symbol lists
583  *              char    symtbl[]        string "Symbol Table"
584  *              FILE *  tfp             symbol table output file handle
585  *              int     xflag           -x, listing radix flag
586  *
587  *      functions called:
588  *              int     fprintf()       c_library
589  *              int     putc()          c_library
590  *              VOID    slew()          aslist.c
591  *              int     strcmp()        c_library
592  *              char *  strcpy()        c_library
593  *
594  *      side effects:
595  *              Symbol and area tables output.
596  */
597
598 VOID
599 lstsym(fp)
600 FILE *fp;
601 {
602         register int c, i, j, k;
603         int nmsym, narea;
604         struct sym *sp;
605         struct sym **p;
606         struct area *ap;
607
608         /*
609          * Symbol Table Header
610          */
611         strcpy(stb, &symtbl[0]);
612         lop = NLPP;
613         if (fp == tfp)
614                 page = 0;
615         slew(fp, 1);
616
617         /*
618          * Find number of symbols
619          */
620         nmsym = 0;
621         for (i=0; i<NHASH; i++) {
622                 sp = symhash[i];
623                 while (sp) {
624                         if (sp != &dot)
625                                 ++nmsym;
626                         sp = sp->s_sp;
627                 }
628         }
629         if (nmsym == 0)
630                 goto atable;
631
632         /*
633          * Allocate space for an array of pointers to symbols
634          * and load array.
635          */
636         if ((p = (struct sym **) malloc(sizeof((struct sym *) sp)*nmsym))
637                 == NULL) {
638                 fprintf(fp, "Insufficient space to build Symbol Table.\n");
639                 return;
640         }
641         nmsym = 0;
642         for (i=0; i<NHASH; i++) {
643                 sp = symhash[i];
644                 while (sp) {
645                         if (sp != &dot)
646                                 p[nmsym++] = sp;
647                         sp = sp->s_sp;
648                 }
649         }
650
651         /*
652          * Bubble Sort on Symbol Table Array
653          */
654         j = 1;
655         c = nmsym - 1;
656         while (j) {
657                 j = 0;
658                 for (i=0; i<c; ++i) {
659                         if (strcmp(&p[i]->s_id[0],&p[i+1]->s_id[0]) > 0) {
660                                 j = 1;
661                                 sp = p[i+1];
662                                 p[i+1] = p[i];
663                                 p[i] = sp;
664                         }
665                 }
666         }
667
668         /*
669          * Symbol Table Output
670          */
671         for (i=0; i<nmsym;) {
672                 sp = p[i];
673                 if (sp->s_area) {
674                         j = sp->s_area->a_ref;
675                         if (xflag == 0) {
676                                 fprintf(fp, " %2X ", j);
677                         } else
678                         if (xflag == 1) {
679                                 fprintf(fp, "%3o ", j);
680                         } else
681                         if (xflag == 2) {
682                                 fprintf(fp, "%3u ", j);
683                         }
684                 } else {
685                         fprintf(fp, "    ");
686                 }
687                 fprintf(fp, "%-60s", sp->s_id);
688                 if (sp->s_flag & S_ASG) {
689                         putc('=', fp);
690                 } else {
691                         putc(' ', fp);
692                 }
693                 if (sp->s_type == S_NEW) {
694                         if (xflag == 0) {
695                                 fprintf(fp, "  **** ");
696                         } else
697                         if (xflag == 1) {
698                                 fprintf(fp, "****** ");
699                         } else
700                         if (xflag == 2) {
701                                 fprintf(fp, " ***** ");
702                         }
703                 } else {
704                         j = sp->s_addr;
705                         if (xflag == 0) {
706                                 fprintf(fp, "  %04X ", j);
707                         } else
708                         if (xflag == 1) {
709                                 fprintf(fp, "%06o ", j);
710                         } else
711                         if (xflag == 2) {
712                                 fprintf(fp, " %05u ", j);
713                         }
714                 }
715                 j = 0;
716                 if (sp->s_flag & S_GBL) {
717                         putc('G', fp);
718                         ++j;
719                 }
720                 if (sp->s_area != NULL) {
721                         putc('R', fp);
722                         ++j;
723                 }
724                 if (sp->s_type == S_NEW) {
725                         putc('X', fp);
726                         ++j;
727                 }
728 #if NCPS-8
729                 putc('\n', fp);
730                 slew(fp, 0);
731                 ++i;
732 #else
733                 if (++i % 3 == 0) {
734                         putc('\n', fp);
735                         slew(fp, pflag);
736                 } else
737                 if (i < nmsym) {
738                         while (j++ < 4)
739                                 putc(' ', fp);
740                         fprintf(fp, "| ");
741                 }
742 #endif
743         }
744         putc('\n', fp);
745
746         /*
747          * Area Table Header
748          */
749
750 atable:
751         strcpy(stb, &aretbl[0]);
752         lop = NLPP;
753         slew(fp, 1);
754
755         /*
756          * Area Table Output
757          */
758         narea = 0;
759         ap = areap;
760         while (ap) {
761                 ++narea;
762                 ap = ap->a_ap;
763         }
764         for (i=0; i<narea; ++i) {
765                 ap = areap;
766                 for (j=i+1; j<narea; ++j)
767                         ap = ap->a_ap;
768                 j = ap->a_ref;
769                 if (xflag == 0) {
770                         fprintf(fp, "  %2X ", j);
771                 } else
772                 if (xflag == 1) {
773                         fprintf(fp, " %3o ", j);
774                 } else
775                 if (xflag == 2) {
776                         fprintf(fp, " %3u ", j);
777                 }
778                 fprintf(fp, "%-60s", ap->a_id);
779                 j = ap->a_size;
780                 k = ap->a_flag;
781                 if (xflag==0) {
782                         fprintf(fp, "   size %4X   flags %X\n", j, k);
783                 } else
784                 if (xflag==1) {
785                         fprintf(fp, "   size %6o   flags %o\n", j, k);
786                 } else
787                 if (xflag==2) {
788                         fprintf(fp, "   size %5u   flags %u\n", j, k);
789                 }
790         }
791 }