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