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