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