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