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