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