df9254e620570b45e6e8bcdf8ae9674c07b9070f
[fw/sdcc] / as / z80 / asout.c
1 /* asout.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  * 10-Nov-07 borutr:
12  *           - applied changes from 28-Oct-97 JLH:
13  *             - outsym: show s_id as string rather than array [NCPS]
14  */
15
16 #include <stdio.h>
17 #include <setjmp.h>
18 #include <string.h>
19 #include "asm.h"
20
21
22 /*)Module       asout.c
23  *
24  *      The module asout.c contains all the functions used to
25  *      generate the .REL assembler output file.
26  *
27  *
28  *      The  assemblers' output object file is an ascii file containing
29  *      the information needed by the linker  to  bind  multiple  object
30  *      modules into a complete loadable memory image.
31  *
32  *      The object module contains the following designators:
33  *
34  *              [XDQ][HL]
35  *                      X        Hexidecimal radix
36  *                      D        Decimal radix
37  *                      Q        Octal radix
38  *
39  *                      H        Most significant byte first
40  *                      L        Least significant byte first
41  *
42  *              H        Header
43  *              M        Module
44  *              A        Area
45  *              S        Symbol
46  *              T        Object code
47  *              R        Relocation information
48  *              P        Paging information
49  *
50  *
51  *      (1)     Radix Line
52  *
53  *      The  first  line  of  an object module contains the [XDQ][HL]
54  *      format specifier (i.e.  XH indicates  a  hexidecimal  file  with
55  *      most significant byte first) for the following designators.
56  *
57  *
58  *      (2)     Header Line
59  *
60  *              H aa areas gg global symbols
61  *
62  *      The  header  line  specifies  the number of areas(aa) and the
63  *      number of global symbols(gg) defined or referenced in  this  ob-
64  *      ject module segment.
65  *
66  *
67  *      (3)     Module Line
68  *
69  *              M name
70  *
71  *      The  module  line  specifies  the module name from which this
72  *      header segment was assembled.  The module line will  not  appear
73  *      if the .module directive was not used in the source program.
74  *
75  *
76  *      (4)     Symbol Line
77  *
78  *              S string Defnnnn
79  *
80  *                      or
81  *
82  *              S string Refnnnn
83  *
84  *      The  symbol line defines (Def) or references (Ref) the symbol
85  *      'string' with the value nnnn.  The defined value is relative  to
86  *      the  current area base address.  References to constants and ex-
87  *      ternal global symbols will always appear before the  first  area
88  *      definition.  References to external symbols will have a value of
89  *      zero.
90  *
91  *
92  *      (5)     Area Line
93  *
94  *              A label size ss flags ff
95  *
96  *      The  area  line  defines the area label, the size (ss) of the
97  *      area in bytes, and the area flags (ff).  The area flags  specify
98  *      the ABS, REL, CON, OVR, and PAG parameters:
99  *
100  *              OVR/CON (0x04/0x00 i.e.  bit position 2)
101  *
102  *              ABS/REL (0x08/0x00 i.e.  bit position 3)
103  *
104  *              PAG (0x10 i.e.  bit position 4)
105  *
106  *
107  *      (6)     T Line
108  *
109  *              T xx xx nn nn nn nn nn ...
110  *
111  *      The  T  line contains the assembled code output by the assem-
112  *      bler with xx xx being the offset address from the  current  area
113  *      base address and nn being the assembled instructions and data in
114  *      byte format.
115  *
116  *
117  *      (7)     R Line
118  *
119  *              R 0 0 nn nn n1 n2 xx xx ...
120  *
121  *      The R line provides the relocation information to the linker.
122  *      The nn nn value is the current area index, i.e.  which area  the
123  *      current  values  were  assembled.  Relocation information is en-
124  *      coded in groups of 4 bytes:
125  *
126  *      1.  n1 is the relocation mode and object format
127  *              1.  bit 0 word(0x00)/byte(0x01)
128  *              2.  bit 1 relocatable area(0x00)/symbol(0x02)
129  *              3.  bit 2 normal(0x00)/PC relative(0x04) relocation
130  *              4.  bit  3  1-byte(0x00)/2-byte(0x08) object format for
131  *                  byte data
132  *              5.  bit 4 signed(0x00)/unsigned(0x10) byte data
133  *              6.  bit 5 normal(0x00)/page '0'(0x20) reference
134  *              7.  bit 6 normal(0x00)/page 'nnn'(0x40) reference
135  *              8.  bit 7 normal(0x00)/MSB of value
136  *
137  *      2.  n2  is  a byte index into the corresponding (i.e.  pre-
138  *              ceeding) T line data (i.e.  a pointer to the data to be
139  *              updated  by  the  relocation).   The T line data may be
140  *              1-byte or  2-byte  byte  data  format  or  2-byte  word
141  *              format.
142  *
143  *      3.  xx xx  is the area/symbol index for the area/symbol be-
144  *              ing referenced.  the corresponding area/symbol is found
145  *              in the header area/symbol lists.
146  *
147  *
148  *      The groups of 4 bytes are repeated for each item requiring relo-
149  *      cation in the preceeding T line.
150  *
151  *
152  *      (8)     P Line
153  *
154  *              P 0 0 nn nn n1 n2 xx xx
155  *
156  *      The  P  line provides the paging information to the linker as
157  *      specified by a .setdp directive.  The format of  the  relocation
158  *      information is identical to that of the R line.  The correspond-
159  *      ing T line has the following information:
160  *              T xx xx aa aa bb bb
161  *
162  *      Where  aa aa is the area reference number which specifies the
163  *      selected page area and bb bb is the base address  of  the  page.
164  *      bb bb will require relocation processing if the 'n1 n2 xx xx' is
165  *      specified in the P line.  The linker will verify that  the  base
166  *      address is on a 256 byte boundary and that the page length of an
167  *      area defined with the PAG type is not larger than 256 bytes.
168  *
169  *      The  linker  defaults any direct page references to the first
170  *      area defined in the input REL file.  All ASxxxx assemblers  will
171  *      specify the _CODE area first, making this the default page area.
172  *
173  *
174  *      asout.c contains the following functions:
175  *              int     lobyte()
176  *              int     hibyte()
177  *              VOID    out()
178  *              VOID    outab()
179  *              VOID    outall()
180  *              VOID    outarea()
181  *              VOID    outaw()
182  *              VOID    outbuf()
183  *              VOID    outchk()
184  *              VOID    outdot()
185  *              VOID    outdp()
186  *              VOID    outgsd()
187  *              VOID    outrb()
188  *              VOID    outrw()
189  *              VOID    outsym()
190  *              VOID    out_lb()
191  *              VOID    out_lw()
192  *              VOID    out_rw()
193  *              VOID    out_tw()
194  *
195  *      The module asout.c contains the following local variables:
196  *              int     rel[]           relocation data for code/data array
197  *              int *   relp            pointer to rel array
198  *              int     txt[]           assembled code/data array
199  *              int *   txtp            pointer to txt array
200  */
201
202 #define  NTXT   16
203 #define  NREL   16
204
205 char     txt[NTXT];
206 char     rel[NREL];
207
208 char    *txtp = { &txt[0] };
209 char    *relp = { &rel[0] };
210
211 /*)Function     VOID    outab(b)
212  *
213  *              int     b               assembler data word
214  *
215  *      The function outab() processes a single word of
216  *      assembled data in absolute format.
217  *
218  *      local variables:
219  *              int *   txtp            pointer to data word
220  *
221  *      global variables:
222  *              int     oflag           -o, generate relocatable output flag
223  *              int     pass            assembler pass number
224  *
225  *      functions called:
226  *              VOID    outchk()        asout.c
227  *              VOID    out_lb()        asout.c
228  *
229  *      side effects:
230  *              The current assembly address is incremented by 1.
231  */
232
233 VOID
234 outab(int b)
235 {
236         if (pass == 2) {
237                 out_lb(b,0);
238                 if (oflag) {
239                         outchk(1, 0);
240                         *txtp++ = lobyte(b);
241                 }
242         }
243         ++dot.s_addr;
244 }
245
246 /*)Function     VOID    outaw(w)
247  *
248  *              int     w               assembler data word
249  *
250  *      The function outaw() processes a single word of
251  *      assembled data in absolute format.
252  *
253  *      local variables:
254  *              int *   txtp            pointer to data word
255  *
256  *      global variables:
257  *              int     oflag           -o, generate relocatable output flag
258  *              int     pass            assembler pass number
259  *
260  *      functions called:
261  *              VOID    outchk()        asout.c
262  *              VOID    out_lw()        asout.c
263  *
264  *      side effects:
265  *              The current assembly address is incremented by 2.
266  */
267
268 VOID
269 outaw(int w)
270 {
271         if (pass == 2) {
272                 out_lw(w,0);
273                 if (oflag) {
274                         outchk(2, 0);
275                         out_tw(w);
276                 }
277         }
278         dot.s_addr += 2;
279 }
280
281 /*)Function     VOID    outrb(esp, r)
282  *
283  *              expr *  esp             pointer to expr structure
284  *              int     r               relocation mode
285  *
286  *      The function outrb() processes a byte of generated code
287  *      in either absolute or relocatable format dependent upon
288  *      the data contained in the expr structure esp.  If the
289  *      .REL output is enabled then the appropriate information
290  *      is loaded into the txt and rel buffers.
291  *
292  *      local variables:
293  *              int     n               symbol/area reference number
294  *              int *   relp            pointer to rel array
295  *              int *   txtp            pointer to txt array
296  *
297  *      global variables:
298  *              sym     dot             defined as sym[0]
299  *              int     oflag           -o, generate relocatable output flag
300  *              int     pass            assembler pass number
301  *
302  *      functions called:
303  *              VOID    aerr()          assubr.c
304  *              VOID    outchk()        asout.c
305  *              VOID    out_lb()        asout.c
306  *              VOID    out_rb()        asout.c
307  *              VOID    out_tb()        asout.c
308  *
309  *      side effects:
310  *              The current assembly address is incremented by 1.
311  */
312
313 VOID
314 outrb(struct expr *esp, int r)
315 {
316         register int n;
317
318         if (pass == 2) {
319                 if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
320                         out_lb(lobyte(esp->e_addr),0);
321                         if (oflag) {
322                                 outchk(1, 0);
323                                 *txtp++ = lobyte(esp->e_addr);
324                         }
325                 } else {
326                         r |= R_BYTE | R_BYT2 | esp->e_rlcf;
327                         if (r & R_MSB) {
328                                 out_lb(hibyte(esp->e_addr),r|R_RELOC|R_HIGH);
329                         } else {
330                                 out_lb(lobyte(esp->e_addr),r|R_RELOC);
331                         }
332                         if (oflag) {
333                                 outchk(2, 4);
334                                 out_tw(esp->e_addr);
335                                 if (esp->e_flag) {
336                                         n = esp->e_base.e_sp->s_ref;
337                                         r |= R_SYM;
338                                 } else {
339                                         n = esp->e_base.e_ap->a_ref;
340                                 }
341                                 *relp++ = r;
342                                 *relp++ = txtp - txt - 2;
343                                 out_rw(n);
344                         }
345                 }
346         }
347         ++dot.s_addr;
348 }
349
350 /*)Function     VOID    outrw(esp, r)
351  *
352  *              expr *  esp             pointer to expr structure
353  *              int     r               relocation mode
354  *
355  *      The function outrw() processes a word of generated code
356  *      in either absolute or relocatable format dependent upon
357  *      the data contained in the expr structure esp.  If the
358  *      .REL output is enabled then the appropriate information
359  *      is loaded into the txt and rel buffers.
360  *
361  *      local variables:
362  *              int     n               symbol/area reference number
363  *              int *   relp            pointer to rel array
364  *              int *   txtp            pointer to txt array
365  *
366  *      global variables:
367  *              sym     dot             defined as sym[0]
368  *              int     oflag           -o, generate relocatable output flag
369  *              int     pass            assembler pass number
370  *
371  *      functions called:
372  *              VOID    aerr()          assubr.c
373  *              VOID    outchk()        asout.c
374  *              VOID    out_lw()        asout.c
375  *              VOID    out_rw()        asout.c
376  *              VOID    out_tw()        asout.c
377  *
378  *      side effects:
379  *              The current assembly address is incremented by 2.
380  */
381
382 VOID
383 outrw(struct expr *esp, int r)
384 {
385         register int n;
386
387         if (pass == 2) {
388                 if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
389                         out_lw(esp->e_addr,0);
390                         if (oflag) {
391                                 outchk(2, 0);
392                                 out_tw(esp->e_addr);
393                         }
394                 } else {
395                         r |= R_WORD | esp->e_rlcf;
396                         if (r & R_BYT2) {
397                                 rerr();
398                                 if (r & R_MSB) {
399                                         out_lw(hibyte(esp->e_addr),r|R_RELOC);
400                                 } else {
401                                         out_lw(lobyte(esp->e_addr),r|R_RELOC);
402                                 }
403                         } else {
404                                 out_lw(esp->e_addr,r|R_RELOC);
405                         }
406                         if (oflag) {
407                                 outchk(2, 4);
408                                 out_tw(esp->e_addr);
409                                 if (esp->e_flag) {
410                                         n = esp->e_base.e_sp->s_ref;
411                                         r |= R_SYM;
412                                 } else {
413                                         n = esp->e_base.e_ap->a_ref;
414                                 }
415                                 *relp++ = r;
416                                 *relp++ = txtp - txt - 2;
417                                 out_rw(n);
418                         }
419                 }
420         }
421         dot.s_addr += 2;
422 }
423
424 /*)Function     VOID    outdp(carea, esp)
425  *
426  *              area *  carea           pointer to current area strcuture
427  *              expr *  esp             pointer to expr structure
428  *
429  *      The function outdp() flushes the output buffer and
430  *      outputs paging information to the .REL file.
431  *
432  *      local variables:
433  *              int     n               symbol/area reference number
434  *              int     r               relocation mode
435  *              int *   relp            pointer to rel array
436  *              int *   txtp            pointer to txt array
437  *
438  *      global variables:
439  *              int     oflag           -o, generate relocatable output flag
440  *              int     pass            assembler pass number
441  *
442  *      functions called:
443  *              VOID    outbuf()        asout.c
444  *              VOID    outchk()        asout.c
445  *              VOID    out_rw()        asout.c
446  *              VOID    out_tw()        asout.c
447  *
448  *      side effects:
449  *              Output buffer flushed to .REL fiel.
450  *              Paging information dumped to .REL file.
451  */
452
453 VOID
454 outdp(struct area *carea, struct expr *esp)
455 {
456         register int n, r;
457
458         if (oflag && pass==2) {
459                 outchk(HUGE,HUGE);
460                 out_tw(carea->a_ref);
461                 out_tw(esp->e_addr);
462                 if (esp->e_flag || esp->e_base.e_ap!=NULL) {
463                         r = R_WORD;
464                         if (esp->e_flag) {
465                                 n = esp->e_base.e_sp->s_ref;
466                                 r |= R_SYM;
467                         } else {
468                                 n = esp->e_base.e_ap->a_ref;
469                         }
470                         *relp++ = r;
471                         *relp++ = txtp - txt - 2;
472                         out_rw(n);
473                 }
474                 outbuf("P");
475         }
476 }
477
478 /*)Function     VOID    outall()
479  *
480  *      The function outall() will output any bufferred assembled
481  *      data and relocation information (during pass 2 if the .REL
482  *      output has been enabled).
483  *
484  *      local variables:
485  *              none
486  *
487  *      global variables:
488  *              int     oflag           -o, generate relocatable output flag
489  *              int     pass            assembler pass number
490  *
491  *      functions called:
492  *              VOID    outbuf()        asout.c
493  *
494  *      side effects:
495  *              assembled data and relocation buffers will be cleared.
496  */
497
498 VOID
499 outall(void)
500 {
501         if (oflag && pass==2)
502                 outbuf("R");
503 }
504
505 /*)Function     VOID    outdot()
506  *
507  *      The function outdot() outputs information about the
508  *      current program counter value (during pass 2 if the .REL
509  *      output has been enabled).
510  *
511  *      local variables:
512  *              none
513  *
514  *      global variables:
515  *              int     oflag           -o, generate relocatable output flag
516  *              int     pass            assembler pass number
517  *
518  *      functions called:
519  *              int     fprintf()       c_library
520  *              VOID    out()           asout.c
521  *
522  *      side effects:
523  *              assembled data and relocation buffers will be cleared.
524  */
525
526 VOID
527 outdot(void)
528 {
529         if (oflag && pass==2) {
530                 fprintf(ofp, "T");
531                 out(txt,(int) (txtp-txt));
532                 fprintf(ofp, "\n");
533                 fprintf(ofp, "R");
534                 out(rel,(int) (relp-rel));
535                 fprintf(ofp, "\n");
536                 txtp = txt;
537                 relp = rel;
538         }
539 }
540
541 /*)Function     outchk(nt, nr)
542  *
543  *              int     nr              number of additional relocation words
544  *              int     nt              number of additional data words
545  *
546  *      The function outchk() checks the data and relocation buffers
547  *      for space to insert the nt data words and nr relocation words.
548  *      If space is not available then output the current data and
549  *      initialize the data buffers to receive the new data.
550  *
551  *      local variables:
552  *              area *  ap              pointer to an area structure
553  *              int *   relp            pointer to rel array
554  *              int *   txtp            pointer to txt array
555  *
556  *      global variables:
557  *              sym     dot             defined as sym[0]
558  *
559  *      functions called:
560  *              VOID    outbuf()        asout.c
561  *
562  *      side effects:
563  *              Data and relocation buffers may be emptied and initialized.
564  */
565
566 VOID
567 outchk(int nt, int nr)
568 {
569         register struct area *ap;
570
571         if (txtp+nt > &txt[NTXT] || relp+nr > &rel[NREL]) {
572                 outbuf("R");
573         }
574         if (txtp == txt) {
575                 out_tw(dot.s_addr);
576                 if ((ap = dot.s_area) != NULL) {
577                         *relp++ = R_WORD|R_AREA;
578                         *relp++ = 0;
579                         out_rw(ap->a_ref);
580                 }
581         }
582 }
583
584 /*)Function     VOID    outbuf()
585  *
586  *      The function outbuf() will output any bufferred data
587  *      and relocation information to the .REL file.  The output
588  *      buffer pointers and counters are initialized.
589  *
590  *      local variables:
591  *              int     rel[]           relocation data for code/data array
592  *              int *   relp            pointer to rel array
593  *              int     txt[]           assembled code/data array
594  *              int *   txtp            pointer to txt array
595  *
596  *      global variables:
597  *              FILE *  ofp             relocation output file handle
598  *
599  *      functions called:
600  *              VOID    out()           asout.c
601  *
602  *      side effects:
603  *              All bufferred data written to .REL file and
604  *              buffer pointers and counters initialized.
605  */
606
607 VOID
608 outbuf(char *s)
609 {
610         if (txtp > &txt[2]) {
611                 fprintf(ofp, "T");
612                 out(txt,(int) (txtp-txt));
613                 fprintf(ofp, "\n");
614                 fprintf(ofp, "%s", s);
615                 out(rel,(int) (relp-rel));
616                 fprintf(ofp, "\n");
617         }
618         txtp = txt;
619         relp = rel;
620 }
621
622 /*)Function     VOID    outgsd()
623  *
624  *      The function outgsd() performs the following:
625  *      (1)     outputs the .REL file radix
626  *      (2)     outputs the header specifying the number
627  *              of areas and global symbols
628  *      (3)     outputs the module name
629  *      (4)     set the reference number and output a symbol line
630  *              for all external global variables and absolutes
631  *      (5)     output an area name, set reference number and output
632  *              a symbol line for all global relocatables in the area.
633  *              Repeat this proceedure for all areas.
634  *
635  *      local variables:
636  *              area *  ap              pointer to an area structure
637  *              sym *   sp              pointer to a sym structure
638  *              int     i               loop counter
639  *              int     j               loop counter
640  *              int     c               string character value
641  *              int     narea           number of code areas
642  *              char *  ptr             string pointer
643  *              int     nglob           number of global symbols
644  *              int     rn              symbol reference number
645  *
646  *      global variables:
647  *              area *  areap           pointer to an area structure
648  *              char    module[]        module name string
649  *              sym * symhash[]         array of pointers to NHASH
650  *                                      linked symbol lists
651  *              int     xflag           -x, listing radix flag
652  *
653  *      functions called:
654  *              int     fprintf()       c_library
655  *              VOID    outarea()       asout.c
656  *              VOID    outsym()        asout.c
657  *              int     putc()          c_library
658  *
659  *      side effects:
660  *              All symbols are given reference numbers, all symbol
661  *              and area information is output to the .REL file.
662  */
663
664 VOID
665 outgsd(void)
666 {
667         register struct area *ap;
668         register struct sym  *sp;
669         register int i, j;
670         char *ptr;
671         int c, narea, nglob, rn;
672
673         /*
674          * Number of areas
675          */
676         narea = areap->a_ref + 1;
677
678         /*
679          * Number of global references/absolutes
680          */
681         nglob = 0;
682         for (i = 0; i < NHASH; ++i) {
683                 sp = symhash[i];
684                 while (sp) {
685                         if (sp->s_flag&S_GBL)
686                                 ++nglob;
687                         sp = sp->s_sp;
688                 }
689         }
690
691         /*
692          * Output Radix and number of areas and symbols
693          */
694         if (xflag == 0) {
695                 fprintf(ofp, "X%c\n", hilo ? 'H' : 'L');
696                 fprintf(ofp, "H %X areas %X global symbols\n", narea, nglob);
697         } else
698         if (xflag == 1) {
699                 fprintf(ofp, "Q%c\n", hilo ? 'H' : 'L');
700                 fprintf(ofp, "H %o areas %o global symbols\n", narea, nglob);
701         } else
702         if (xflag == 2) {
703                 fprintf(ofp, "D%c\n", hilo ? 'H' : 'L');
704                 fprintf(ofp, "H %u areas %u global symbols\n", narea, nglob);
705         }
706
707         /*
708          * Module name
709          */
710         if (module[0]) {
711                 fprintf(ofp, "M ");
712                 ptr = &module[0];
713                 while (ptr < &module[NCPS]) {
714                         if ((c = *ptr++) != 0)
715                                 putc(c, ofp);
716                 }
717                 putc('\n', ofp);
718         }
719
720     /*
721      * Sdcc compile options
722      */
723         if (strlen(optsdcc)) fprintf(ofp, "O %s\n", optsdcc);
724
725         /*
726          * Global references and absolutes.
727          */
728         rn = 0;
729         for (i=0; i<NHASH; ++i) {
730                 sp = symhash[i];
731                 while (sp) {
732                         if (sp->s_area==NULL && sp->s_flag&S_GBL) {
733                                 sp->s_ref = rn++;
734                                 outsym(sp);
735                         }
736                         sp = sp->s_sp;
737                 }
738         }
739
740         /*
741          * Global relocatables.
742          */
743         for (i=0; i<narea; ++i) {
744                 ap = areap;
745                 while (ap->a_ref != i)
746                         ap = ap->a_ap;
747                 outarea(ap);
748                 for (j=0; j<NHASH; ++j) {
749                         sp = symhash[j];
750                         while (sp) {
751                                 if (sp->s_area==ap && sp->s_flag&S_GBL) {
752                                         sp->s_ref = rn++;
753                                         outsym(sp);
754                                 }
755                                 sp = sp->s_sp;
756                         }
757                 }
758         }
759 }
760
761 /*)Function     VOID    outarea(ap)
762  *
763  *              area *  ap              pointer to an area structure
764  *
765  *      The function outarea()  outputs the A line to the .REL
766  *      file.  The A line contains the area's name, size, and
767  *      attributes.
768  *
769  *      local variables:
770  *              char *  ptr             pointer to area id string
771  *              int     c               character value
772  *
773  *      global variables:
774  *              FILE *  ofp             relocation output file handle
775  *              int     xflag           -x, listing radix flag
776  *
777  *      functions called:
778  *              int     fprintf()       c_library
779  *              int     putc()          c_library
780  *
781  *      side effects:
782  *              The A line is sent to the .REL file.
783  */
784
785 VOID
786 outarea(struct area *ap)
787 {
788         fprintf(ofp, "A %s", ap->a_id);
789         if (xflag == 0) {
790                 fprintf(ofp, " size %X flags %X\n", ap->a_size, ap->a_flag);
791         } else
792         if (xflag == 1) {
793                 fprintf(ofp, " size %o flags %o\n", ap->a_size, ap->a_flag);
794         } else
795         if (xflag == 2) {
796                 fprintf(ofp, " size %u flags %u\n", ap->a_size, ap->a_flag);
797         }
798 }
799
800 /*)Function     VOID    outsym(sp)
801  *
802  *              sym *   sp              pointer to a sym structure
803  *
804  *      The function outsym() outputs the S line to the .REL
805  *      file.  The S line contains the symbols name and whether the
806  *      the symbol is defined or referenced.
807  *
808  *      local variables:
809  *              char *  ptr             pointer to symbol id string
810  *              int     c               character value
811  *
812  *      global variables:
813  *              FILE *  ofp             relocation output file handle
814  *              int     xflag           -x, listing radix flag
815  *
816  *      functions called:
817  *              int     fprintf()       c_library
818  *              int     putc()          c_library
819  *
820  *      side effects:
821  *              The S line is sent to the .REL file.
822  */
823
824 VOID
825 outsym(struct sym *sp)
826 {
827         fprintf(ofp, "S %s", sp->s_id);
828         fprintf(ofp, " %s", sp->s_type==S_NEW ? "Ref" : "Def");
829         if (xflag == 0) {
830                 fprintf(ofp, "%04X\n", sp->s_addr);
831         } else
832         if (xflag == 1) {
833                 fprintf(ofp, "%06o\n", sp->s_addr);
834         } else
835         if (xflag == 2) {
836                 fprintf(ofp, "%05u\n", sp->s_addr);
837         }
838 }
839
840 /*)Function     VOID    out(p, n)
841  *
842  *              int     n               number of words to output
843  *              int *   p               pointer to data words
844  *
845  *      The function out() outputs the data words to the .REL file
846  *      int the specified radix.
847  *
848  *      local variables:
849  *              none
850  *
851  *      global variables:
852  *              FILE *  ofp             relocation output file handle
853  *              int     xflag           -x, listing radix flag
854  *
855  *      functions called:
856  *              int     fprintf()       c_library
857  *
858  *      side effects:
859  *              Data is sent to the .REL file.
860  */
861
862 VOID
863 out(char *p, int n)
864 {
865         while (n--) {
866                 if (xflag == 0) {
867                         fprintf(ofp, " %02X", (*p++)&0377);
868                 } else
869                 if (xflag == 1) {
870                         fprintf(ofp, " %03o", (*p++)&0377);
871                 } else
872                 if (xflag == 2) {
873                         fprintf(ofp, " %03u", (*p++)&0377);
874                 }
875         }
876 }
877
878 /*)Function     VOID    out_lb(b, t)
879  *
880  *              int     b               assembled data
881  *              int     t               relocation type
882  *
883  *      The function out_lb() copies the assembled data and
884  *      its relocation type to the list data buffers.
885  *
886  *      local variables:
887  *              none
888  *
889  *      global variables:
890  *              int *   cp              pointer to assembler output array cb[]
891  *              int *   cpt             pointer to assembler relocation type
892  *                                      output array cbt[]
893  *
894  *      functions called:
895  *              none
896  *
897  *      side effects:
898  *              Pointers to data and relocation buffers incremented by 1.
899  */
900
901 VOID
902 out_lb(int b,int t)
903 {
904         if (cp < &cb[NCODE]) {
905                 *cp++ = b;
906                 *cpt++ = t;
907         }
908 }
909
910 /*)Function     VOID    out_lw(n, t)
911  *
912  *              int     n               assembled data
913  *              int     t               relocation type
914  *
915  *      The function out_lw() copies the assembled data and
916  *      its relocation type to the list data buffers.
917  *
918  *      local variables:
919  *              none
920  *
921  *      global variables:
922  *              int *   cp              pointer to assembler output array cb[]
923  *              int *   cpt             pointer to assembler relocation type
924  *                                      output array cbt[]
925  *
926  *      functions called:
927  *              none
928  *
929  *      side effects:
930  *              Pointers to data and relocation buffers incremented by 2.
931  */
932
933 VOID
934 out_lw(int n,int t)
935 {
936         if (hilo) {
937                 out_lb(hibyte(n),t ? t|R_HIGH : 0);
938                 out_lb(lobyte(n),t);
939         } else {
940                 out_lb(lobyte(n),t);
941                 out_lb(hibyte(n),t ? t|R_HIGH : 0);
942         }
943 }
944
945 /*)Function     VOID    out_rw(n)
946  *
947  *              int     n               data word
948  *
949  *      The function out_rw() outputs the relocation (R)
950  *      data word as two bytes ordered according to hilo.
951  *
952  *      local variables:
953  *              int *   relp            pointer to rel array
954  *
955  *      global variables:
956  *              none
957  *
958  *      functions called:
959  *              int     lobyte()        asout.c
960  *              int     hibyte()        asout.c
961  *
962  *      side effects:
963  *              Pointer to relocation buffer incremented by 2.
964  */
965
966 VOID
967 out_rw(int n)
968 {
969         if (hilo) {
970                 *relp++ = hibyte(n);
971                 *relp++ = lobyte(n);
972         } else {
973                 *relp++ = lobyte(n);
974                 *relp++ = hibyte(n);
975         }
976 }
977
978 /*)Function     VOID    out_tw(n)
979  *
980  *              int     n               data word
981  *
982  *      The function out_tw() outputs the text (T)
983  *      data word as two bytes ordered according to hilo.
984  *
985  *      local variables:
986  *              int *   txtp            pointer to txt array
987  *
988  *      global variables:
989  *              none
990  *
991  *      functions called:
992  *              int     lobyte()        asout.c
993  *              int     hibyte()        asout.c
994  *
995  *      side effects:
996  *              Pointer to relocation buffer incremented by 2.
997  */
998
999 VOID
1000 out_tw(int n)
1001 {
1002         if (hilo) {
1003                 *txtp++ = hibyte(n);
1004                 *txtp++ = lobyte(n);
1005         } else {
1006                 *txtp++ = lobyte(n);
1007                 *txtp++ = hibyte(n);
1008         }
1009 }
1010
1011 /*)Function     int     lobyte(n)
1012  *
1013  *              int     n               data word
1014  *
1015  *      The function lobyte() returns the lower byte of
1016  *      integer n.
1017  *
1018  *      local variables:
1019  *              none
1020  *
1021  *      global variables:
1022  *              none
1023  *
1024  *      functions called:
1025  *              none
1026  *
1027  *      side effects:
1028  *              none
1029  */
1030
1031 int
1032 lobyte(int n)
1033 {
1034         return (n&0377);
1035 }
1036
1037 /*)Function     int     hibyte(n)
1038  *
1039  *              int     n               data word
1040  *
1041  *      The function hibyte() returns the higher byte of
1042  *      integer n.
1043  *
1044  *      local variables:
1045  *              none
1046  *
1047  *      global variables:
1048  *              none
1049  *
1050  *      functions called:
1051  *              none
1052  *
1053  *      side effects:
1054  *              none
1055  */
1056
1057 int
1058 hibyte(int n)
1059 {
1060         return ((n>>8)&0377);
1061 }
1062