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