4 * Copyright (C) 1989-2009 Alan R. Baldwin
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
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.
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/>.
24 * With enhancements from
26 * John L. Hartman (JLH)
27 * jhartman at compuserve dot com
34 * The module aslist.c contains all the functions used
35 * to generate the assembler list and symbol output files.
37 * aslist.c contains the following functions:
44 * The module aslist.c contains no local/static variables
47 /*)Function VOID list()
49 * The function list() generates the listing output
50 * which includes the input source, line numbers,
51 * and generated code. Numerical output may be selected
52 * as hexadecimal, decimal, or octal.
55 * char * il pointer to assembler-source listing line
56 * int l_addr laddr (int) truncated to 2-bytes
57 * int n number of bytes listed per line
58 * int nb computed number of assembled bytes
59 * int nl number of bytes listed on this line
60 * int listing listing enable flags
61 * int paging computed paging enable flag
62 * char * wp pointer to the assembled data bytes
63 * int * wpt pointer to the data byte mode
64 * char * frmt pointer to format string
67 * int a_bytes T line addressing size
68 * int bflag -b(b), listing mode flag
69 * int cb[] array of assembler output values
70 * int cbt[] array of assembler relocation types
71 * describing the data in cb[]
72 * int * cp pointer to assembler output array cb[]
73 * int * cpt pointer to assembler relocation type
75 * char eb[] array of generated error codes
76 * char * ep pointer into error list
78 * char * ib string buffer containing
79 * assembler-source text line for processing
80 * char * ic string buffer containing
81 * assembler-source text line for listing
82 * a_uint laddr address of current assembler line,
83 * equate, or value of .if argument
84 * FILE * lfp list output file handle
85 * int line current assembler source line number
86 * int lmode listing mode
87 * int lnlist LIST-NLIST state
88 * int srcline source file line number
89 * int uflag -u, disable .list/.nlist processing
90 * int xflag -x, listing radix flag
93 * int fprintf() c_library
94 * VOID list1() aslist.c
95 * int putc() c_library
96 * VOID slew() asslist.c
99 * Listing or symbol output updated.
102 /* The Output Formats, No Cycle Count
104 11111111112222222222333333333344444-----
105 012345678901234567890123456789012345678901234-----
107 ee XXXX xx xx xx xx xx xx LLLLL ************* HEX(16)
108 ee 000000 ooo ooo ooo ooo LLLLL ************* OCTAL(16)
109 ee DDDDD ddd ddd ddd ddd LLLLL ************* DECIMAL(16)
115 11111111112222222222333333333344444-----
116 012345678901234567890123456789012345678901234-----
118 ee XXXXXX xx xx xx xx xx xx xx LLLLL ********* HEX(24)
119 ee OO000000 ooo ooo ooo ooo ooo LLLLL ********* OCTAL(24)
120 ee DDDDDDDD ddd ddd ddd ddd ddd LLLLL ********* DECIMAL(24)
126 11111111112222222222333333333344444-----
127 012345678901234567890123456789012345678901234-----
129 ee XXXXXXXX xx xx xx xx xx xx xx LLLLL ********* HEX(32)
130 eeOOOOO000000 ooo ooo ooo ooo ooo LLLLL ********* OCTAL(32)
131 ee DDDDDDDDDD ddd ddd ddd ddd ddd LLLLL ********* DECIMAL(32)
137 /* The Output Formats, With Cycle Count [nn]
139 11111111112222222222333333333344444-----
140 012345678901234567890123456789012345678901234-----
142 ee XXXX xx xx xx xx xx[nn]LLLLL ************* HEX(16)
143 ee 000000 ooo ooo ooo [nn]LLLLL ************* OCTAL(16)
144 ee DDDDD ddd ddd ddd [nn]LLLLL ************* DECIMAL(16)
150 11111111112222222222333333333344444-----
151 012345678901234567890123456789012345678901234-----
153 ee XXXXXX xx xx xx xx xx xx[nn]LLLLL ********* HEX(24)
154 ee OO000000 ooo ooo ooo ooo [nn]LLLLL ********* OCTAL(24)
155 ee DDDDDDDD ddd ddd ddd ddd [nn]LLLLL ********* DECIMAL(24)
161 11111111112222222222333333333344444-----
162 012345678901234567890123456789012345678901234-----
164 ee XXXXXXXX xx xx xx xx xx xx[nn]LLLLL ********* HEX(32)
165 eeOOOOO000000 ooo ooo ooo ooo [nn]LLLLL ********* OCTAL(32)
166 ee DDDDDDDDDD ddd ddd ddd ddd [nn]LLLLL ********* DECIMAL(32)
182 /* ib/ic are dynamically allocated */
190 * Get Correct Line Number
200 * Listing Control Override
204 if (lmode
== NLIST
) {
212 paging
= !pflag
&& ((lnlist
& LIST_PAG
) || (uflag
== 1)) ? 1 : 0;
215 * ALIST/BLIST Output Processing
217 if (lmode
== ALIST
) {
218 outchk(ASXHUGE
,ASXHUGE
);
220 if (lmode
== ALIST
|| lmode
== BLIST
) {
225 * Check NO-LIST Conditions
227 if ((lfp
== NULL
) || (lmode
== NLIST
)) {
232 * ALIST/BLIST Output Processing
234 if (lmode
== ALIST
) {
235 outchk(ASXHUGE
,ASXHUGE
);
245 * LIST_ERR - Output a maximum of NERR error codes with listing.
247 if (listing
& LIST_ERR
) {
248 while (ep
< &eb
[NERR
])
250 fprintf(lfp
, "%.2s", eb
);
257 * Source listing Option.
259 if (lmode
== SLIST
) {
260 if (listing
& LIST_LOC
) {
263 case 2: frmt
= "%24s%5u %s\n"; break;
265 case 4: frmt
= "%32s%5u %s\n"; break;
267 fprintf(lfp
, frmt
, "", line
, il
);
271 case 2: frmt
= "%29s %s\n"; break;
273 case 4: frmt
= "%37s %s\n"; break;
275 fprintf(lfp
, frmt
, "", il
);
281 * Truncate (int) to N-Bytes
287 * Equate Listing Option
289 if (lmode
== ELIST
) {
290 if (listing
& LIST_EQT
) {
297 case 2: frmt
= "%19s%04lX"; break;
298 case 3: frmt
= "%25s%06lX"; break;
299 case 4: frmt
= "%23s%08lX"; break;
304 case 2: frmt
= "%19s%04X"; break;
305 case 3: frmt
= "%25s%06X"; break;
306 case 4: frmt
= "%23s%08X"; break;
315 case 2: frmt
= "%17s%06lo"; break;
316 case 3: frmt
= "%23s%08lo"; break;
317 case 4: frmt
= "%20s%011lo"; break;
322 case 2: frmt
= "%17s%06o"; break;
323 case 3: frmt
= "%23s%08o"; break;
324 case 4: frmt
= "%20s%011o"; break;
329 case 2: /* DECIMAL */
333 case 2: frmt
= "%18s%05lu"; break;
334 case 3: frmt
= "%23s%08lu"; break;
335 case 4: frmt
= "%21s%010lu"; break;
340 case 2: frmt
= "%18s%05u"; break;
341 case 3: frmt
= "%23s%08u"; break;
342 case 4: frmt
= "%21s%010u"; break;
347 fprintf(lfp
, frmt
, "", l_addr
);
351 case 2: frmt
= "%23s"; break;
353 case 4: frmt
= "%31s"; break;
355 fprintf(lfp
, frmt
, "");
357 if ((listing
& LIST_LIN
) && (listing
& LIST_SRC
)) {
358 fprintf(lfp
, " %5u %s\n", line
, il
);
360 if (listing
& LIST_LIN
) {
361 fprintf(lfp
, " %5u\n", line
);
363 if (listing
& LIST_SRC
) {
364 fprintf(lfp
, " %5s %s\n", "", il
);
372 * LIST_LOC - Location Address
374 if (listing
& LIST_LOC
) {
381 case 2: frmt
= " %04lX"; break;
382 case 3: frmt
= " %06lX"; break;
383 case 4: frmt
= " %08lX"; break;
388 case 2: frmt
= " %04X"; break;
389 case 3: frmt
= " %06X"; break;
390 case 4: frmt
= " %08X"; break;
399 case 2: frmt
= " %06lo"; break;
400 case 3: frmt
= " %08lo"; break;
401 case 4: frmt
= "%011lo"; break;
406 case 2: frmt
= " %06o"; break;
407 case 3: frmt
= " %08o"; break;
408 case 4: frmt
= "%011o"; break;
413 case 2: /* DECIMAL */
417 case 2: frmt
= " %05lu"; break;
418 case 3: frmt
= " %08lu"; break;
419 case 4: frmt
= " %010lu"; break;
424 case 2: frmt
= " %05u"; break;
425 case 3: frmt
= " %08u"; break;
426 case 4: frmt
= " %010u"; break;
431 fprintf(lfp
, frmt
, l_addr
);
435 case 2: frmt
= "%5s"; break;
437 case 4: frmt
= "%10s"; break;
439 fprintf(lfp
, frmt
, "");
443 * ALIST/BLIST Listing Options
445 if (lmode
== ALIST
|| lmode
== BLIST
) {
446 if (listing
& LIST_LIN
) {
452 case 2: frmt
= "%19s%5u %s\n"; break;
454 case 4: frmt
= "%22s%5u %s\n"; break;
461 case 2: frmt
= "%17s%5u %s\n"; break;
463 case 4: frmt
= "%21s%5u %s\n"; break;
467 case 2: /* DECIMAL */
470 case 2: frmt
= "%17s%5u %s\n"; break;
472 case 4: frmt
= "%21s%5u %s\n"; break;
476 fprintf(lfp
, frmt
, "", line
, il
);
483 case 2: frmt
= "%19s%5s %s\n"; break;
485 case 4: frmt
= "%22s%5s %s\n"; break;
492 case 2: frmt
= "%17s%5s %s\n"; break;
494 case 4: frmt
= "%21s%5s %s\n"; break;
498 case 2: /* DECIMAL */
501 case 2: frmt
= "%17s%5s %s\n"; break;
503 case 4: frmt
= "%21s%5s %s\n"; break;
507 fprintf(lfp
, frmt
, "", "", il
);
513 * LIST_BIN - Binary Listing Option
514 * LIST_CYC - Opcode Cycles Option
515 * LIST_LIN - Line Number Option
516 * LIST_SRC - Source Listing Option
518 if (!(listing
& (LIST_BIN
| LIST_CYC
| LIST_LIN
| LIST_SRC
))) {
531 case 2: n
= 6; frmt
= "%7s"; break;
533 case 4: n
= 7; frmt
= "%12s"; break;
540 case 2: n
= 4; frmt
= "%9s"; break;
542 case 4: n
= 5; frmt
= "%13s"; break;
546 case 2: /* DECIMAL */
549 case 2: n
= 4; frmt
= "%9s"; break;
551 case 4: n
= 5; frmt
= "%13s"; break;
558 nb
= (int) (cp
- cb
);
561 * If we list cycles, decrease max. bytes on first line.
563 nl
= (!cflag
&& !(opcycles
& OPCY_NONE
) && (listing
& LIST_CYC
)) ? (n
-1) : n
;
566 * First line of output for this source line with data.
568 if (listing
& (LIST_LIN
| LIST_SRC
)) {
569 list1(wp
, wpt
, nb
, nl
, 1, listing
);
570 if ((listing
& LIST_LIN
) && (listing
& LIST_SRC
)) {
571 fprintf(lfp
, "%5u %s", line
, il
);
573 if (listing
& LIST_LIN
) {
574 fprintf(lfp
, "%5u", line
);
576 if (listing
& LIST_SRC
) {
577 fprintf(lfp
, "%5s %s", "", il
);
580 list1(wp
, wpt
, nb
, nl
, listing
& LIST_CYC
, listing
);
585 * Subsequent lines of output if more data.
587 if (listing
& LIST_BIN
) {
588 while ((nb
- nl
) > 0) {
594 fprintf(lfp
, frmt
, "");
595 list1(wp
, wpt
, nb
, nl
, 0, listing
);
601 /*)Function VOID list1(wp, wpt, nw, n, f, g)
603 * int g listing enable flags
604 * int f fill blank fields (1)
605 * int n number of bytes listed per line
606 * int nb number of data bytes
607 * int * wp pointer to data bytes
608 * int * wpt pointer to data byte mode
614 * int xflag -x, listing radix flag
617 * VOID list2() asslist.c
618 * int fprintf() c_library
621 * Data formatted and output to listing.
625 list1(char *wp
, int *wpt
, int nb
, int n
, int f
, int g
)
642 case 2: /* DECIMAL */
654 for (i
=0; i
<nb
; ++i
) {
657 fprintf(lfp
, frmt1
, (*wp
++)&0377);
659 fprintf(lfp
, "%s", frmt2
);
664 * Output blanks if required.
668 fprintf(lfp
, "%s", frmt2
);
673 * If we list cycles, put them out, first line only
675 if (f
&& (g
& LIST_CYC
) && !cflag
&& !(opcycles
& OPCY_NONE
)) {
676 fprintf(lfp
, "%s%c%2d%c",
677 (xflag
!= 0) ? " " : "", CYCNT_BGN
, opcycles
, CYCNT_END
);
684 /*)Function VOID list2(wpt)
686 * int * wpt pointer to relocation mode
688 * The function list2() outputs the selected
689 * relocation flag as specified by fflag.
692 * int c relocation flag character
693 * int t relocation mode
696 * int fflag -f(f), relocations flagged flag
699 * int putc() c_library
702 * Relocation flag output to listing file.
713 * Designate a relocatable word by `.
721 * Designate a relocatable word by its mode:
724 * operand offset p (q)
725 * relocatable symbol r (s)
732 if (t
& (R_PAG0
|R_PAGN
)) {
740 if (t
& R_HIGH
) c
+= 1;
745 * Output the selected mode.
750 /*)Function VOID slew(fp, flag)
752 * FILE * fp file handle for listing
753 * int flag enable pagination
755 * The function slew() increments the page line count.
756 * If the page overflows and pagination is enabled:
757 * 1) put out a page skip,
760 * 4) and reset the line count.
766 * int a_bytes T line addressing size
767 * char cpu[] cpu type string
768 * int lop current line number on page
769 * int page current page number
770 * char stb[] Subtitle string buffer
771 * char tb[] Title string buffer
774 * int fprintf() c_library
777 * Increments page line counter, on overflow
778 * a new page header is output to the listing file.
782 slew(FILE *fp
, int flag
)
792 *12345678901234567890123456789012345678901234567890123456789012345678901234567890
793 *ASxxxx Assembler Vxx.xx (Motorola 6809) Page 1
795 sprintf(tp
, "ASxxxx Assembler %s (%s)", VERSION
, cpu
);
796 sprintf(np
, "Page %u", ++page
);
798 * Total string length is 78 characters.
800 n
= 78 - strlen(tp
) - strlen(np
);
804 fprintf(fp
, "\f%s%*s%s\n", tp
, n
, " " ,np
);
806 *12345678901234567890123456789012345678901234567890123456789012345678901234567890
807 *Hexadecimal [16-Bits] Sun Sep 15 17:22:25 2013
811 case 0: frmt
= "Hexadecimal [%d-Bits]\n"; break;
812 case 1: frmt
= "Octal [%d-Bits]\n"; break;
813 case 2: frmt
= "Decimal [%d-Bits]\n"; break;
815 fprintf(fp
, frmt
, 8 * a_bytes
);
816 fprintf(fp
, "%s\n", tb
);
817 fprintf(fp
, "%s\n\n", stb
);
826 /* Used for qsort call in lstsym */
827 static int _cmpSym(const void *p1
, const void *p2
)
829 struct sym
**s1
= (struct sym
**)(p1
);
830 struct sym
**s2
= (struct sym
**)(p2
);
831 return strcmp((*s1
)->s_id
,(*s2
)->s_id
);
833 /* end sdas specific */
835 /*)Function VOID lstsym(fp)
837 * FILE * fp file handle for output
839 * The function lstsym() outputs alphabetically
840 * sorted symbol and area tables.
848 * int nmsym number of symbols
849 * int narea number of areas
850 * int nbank number of banks
851 * sym ** p pointer to an array of
852 * pointers to symbol structures
853 * int paging computed paging enable flag
854 * char * ptr pointer to an id string
855 * a_uint sa temporary
856 * sym * sp pointer to symbol structure
857 * area * ap pointer to an area structure
860 * int a_bytes T line addressing size
861 * area * areap pointer to an area structure
862 * char aretbl[] string "Area Table"
863 * sym dot defined as sym[0]
864 * int lnlist LIST-NLIST state
865 * char stb[] Subtitle string buffer
866 * sym * symhash[] array of pointers to NHASH
867 * linked symbol lists
868 * char symtbl[] string "Symbol Table"
869 * FILE * tfp symbol table output file handle
870 * int uflag LIST-NLIST override flag
871 * int wflag -w, wide listing flag
872 * int xflag -x, listing radix flag
875 * int fprintf() c_library
876 * int putc() c_library
877 * VOID slew() aslist.c
878 * int strcmp() c_library
879 * char * strcpy() c_library
880 * char * new() assym.c
883 * Symbol and area tables output.
889 int i
, j
, k
, n
, paging
;
890 int nmsym
, narea
, nbank
;
898 * Symbol Table Header
900 strcpy(stb
, &symtbl
[0]);
906 paging
= !pflag
&& ((lnlist
& LIST_PAG
) || (uflag
== 1)) ? 1 : 0;
911 * Find number of symbols
914 for (i
=0; i
<NHASH
; i
++) {
926 * Allocate space for an array of pointers to symbols
929 p
= (struct sym
**) new (sizeof((struct sym
*) sp
)*nmsym
);
931 fprintf(fp
, "Insufficient space to build Symbol Table.\n");
935 for (i
=0; i
<NHASH
; i
++) {
946 /* BUBBLE SORT?? WTF??? */
948 * Bubble Sort on Symbol Table Array
954 for (i
=0; i
<c
; ++i
) {
955 if (strcmp(&p
[i
]->s_id
[0],&p
[i
+1]->s_id
[0]) > 0) {
965 qsort(p
, nmsym
, sizeof(struct sym
*), _cmpSym
);
967 /* end sdas specific */
970 * Symbol Table Output
972 for (i
=0; i
<nmsym
;) {
975 j
= sp
->s_area
->a_ref
;
978 case 0: frmt
= " %2X "; break;
979 case 1: frmt
= "%3o "; break;
980 case 2: frmt
= "%3u "; break;
982 fprintf(fp
, frmt
, j
);
989 fprintf(fp
, "%-60.60s", ptr
); /* JLH */
991 fprintf(fp
, "%-8.8s", ptr
);
993 if (sp
->s_flag
& S_ASG
) {
998 if (sp
->s_type
== S_NEW
) {
1004 case 0: frmt
= " **** "; break;
1005 case 1: frmt
= "****** "; break;
1006 case 2: frmt
= " ***** "; break;
1013 case 0: frmt
= " ****** "; break;
1014 case 1: frmt
= "******** "; break;
1015 case 2: frmt
= "******** "; break;
1022 case 0: frmt
= " ******** "; break;
1023 case 1: frmt
= "*********** "; break;
1024 case 2: frmt
= " ********** "; break;
1029 fprintf(fp
, "%s", frmt
);
1038 case 0: frmt
= " %04lX "; break;
1039 case 1: frmt
= "%06lo "; break;
1040 case 2: frmt
= " %05lu "; break;
1047 case 0: frmt
= " %06lX "; break;
1048 case 1: frmt
= "%08lo "; break;
1049 case 2: frmt
= "%08lu "; break;
1056 case 0: frmt
= " %08lX "; break;
1057 case 1: frmt
= "%011lo "; break;
1058 case 2: frmt
= " %010lu "; break;
1068 case 0: frmt
= " %04X "; break;
1069 case 1: frmt
= "%06o "; break;
1070 case 2: frmt
= " %05u "; break;
1077 case 0: frmt
= " %06X "; break;
1078 case 1: frmt
= "%08o "; break;
1079 case 2: frmt
= "%08u "; break;
1086 case 0: frmt
= " %08X "; break;
1087 case 1: frmt
= "%011o "; break;
1088 case 2: frmt
= " %010u "; break;
1093 fprintf(fp
, frmt
, sa
);
1097 if (sp
->s_flag
& S_GBL
) {
1101 if (sp
->s_flag
& S_LCL
) {
1105 if (sp
->s_area
!= NULL
) {
1109 if (sp
->s_type
== S_NEW
) {
1114 putc('\n', fp
); /* JLH */
1139 strcpy(stb
, &aretbl
[0]);
1154 for (n
=0; n
<nbank
; ++n
) {
1155 for (i
=0; i
<narea
; ++i
) {
1157 for (j
=i
+1; j
<narea
; ++j
)
1162 case 0: frmt
= " %2X "; break;
1163 case 1: frmt
= " %3o "; break;
1164 case 2: frmt
= " %3u "; break;
1166 fprintf(fp
, frmt
, j
);
1170 fprintf(fp
, "%-40.40s", ptr
);
1172 fprintf(fp
, "%-8.8s", ptr
);
1183 case 0: frmt
= " size %4lX flags %4X\n"; break;
1184 case 1: frmt
= " size %6lo flags %6o\n"; break;
1185 case 2: frmt
= " size %5lu flags %6u\n"; break;
1192 case 0: frmt
= " size %6lX flags %4X\n"; break;
1193 case 1: frmt
= " size %8lo flags %6o\n"; break;
1194 case 2: frmt
= " size %8lu flags %6u\n"; break;
1201 case 0: frmt
= " size %8lX flags %4X\n"; break;
1202 case 1: frmt
= " size %11lo flags %6o\n"; break;
1203 case 2: frmt
= " size %10lu flags %6u\n"; break;
1213 case 0: frmt
= " size %4X flags %4X\n"; break;
1214 case 1: frmt
= " size %6o flags %6o\n"; break;
1215 case 2: frmt
= " size %5u flags %6u\n"; break;
1222 case 0: frmt
= " size %6X flags %4X\n"; break;
1223 case 1: frmt
= " size %8o flags %6o\n"; break;
1224 case 2: frmt
= " size %8u flags %6u\n"; break;
1231 case 0: frmt
= " size %8X flags %4X\n"; break;
1232 case 1: frmt
= " size %11o flags %6o\n"; break;
1233 case 2: frmt
= " size %10u flags %6u\n"; break;
1238 fprintf(fp
, frmt
, sa
, k
);