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