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