1 /* asout.c */
2 
3 /*
4  *  Copyright (C) 1989-2009  Alan R. Baldwin
5  *
6  *  This program is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  *
20  * Alan R. Baldwin
21  * 721 Berkeley St.
22  * Kent, Ohio  44240
23  *
24  */
25 
26 /*
27  * 28-Oct-97 JLH:
28  *           - outsym: show s_id as string rather than array [NCPS]
29  *           - Added outr11 to support 8051's 11 bit destination address
30  */
31 
32 #include "sdas.h"
33 #include "asxxxx.h"
34 
35 
36 /*)Module       asout.c
37  *
38  *      The module asout.c contains all the functions used to
39  *      generate the .REL assembler output file.
40  *
41  *
42  *      The  assemblers' output object file is an ascii file containing
43  *      the information needed by the linker  to  bind  multiple  object
44  *      modules into a complete loadable memory image.
45  *
46  *      The object module contains the following designators:
47  *
48  *              [XDQ][HL][234]
49  *                      X        Hexadecimal radix
50  *                      D        Decimal radix
51  *                      Q        Octal radix
52  *
53  *                      H        Most significant byte first
54  *                      L        Least significant byte first
55  *
56  *                      2        16-Bit Relocatable Addresses/Data
57  *                      3        24-Bit Relocatable Addresses/Data
58  *                      4        32-Bit Relocatable Addresses/Data
59  *
60  *              H       Header
61  *              M       Module
62  *              A       Area
63  *              S       Symbol
64  *              T       Object code
65  *              R       Relocation information
66  *              P       Paging information
67  *
68  *
69  *      (1)     Radix Line
70  *
71  *      The  first  line  of  an object module contains the [XDQ][HL][234]
72  *      format specifier (i.e.  XH2 indicates  a  hexadecimal  file  with
73  *      most significant byte first and 16-bit addresses) for the
74  *      following designators.
75  *
76  *
77  *      (2)     Header Line
78  *
79  *              H aa areas gg global symbols
80  *
81  *      The  header  line  specifies  the number of areas(aa) and the
82  *      number of global symbols(gg) defined or referenced in  this  ob-
83  *      ject module segment.
84  *
85  *
86  *      (3)     Module Line
87  *
88  *              M name
89  *
90  *      The  module  line  specifies  the module name from which this
91  *      header segment was assembled.  The module line will  not  appear
92  *      if the .module directive was not used in the source program.
93  *
94  *
95  *      (4)     Symbol Line
96  *
97  *              S string Defnnnn
98  *
99  *                      or
100  *
101  *              S string Refnnnn
102  *
103  *      The  symbol line defines (Def) or references (Ref) the symbol
104  *      'string' with the value nnnn.  The defined value is relative  to
105  *      the  current area base address.  References to constants and ex-
106  *      ternal global symbols will always appear before the  first  area
107  *      definition.  References to external symbols will have a value of
108  *      zero.
109  *
110  *
111  *      (5)     Area Line
112  *
113  *              A label size ss flags ff
114  *
115  *      The  area  line  defines the area label, the size (ss) of the
116  *      area in bytes, and the area flags (ff).  The area flags
117  *      specify the area properties:
118  *
119  *              OVR/CON (0x04/0x00 i.e.  bit position 2)
120  *              ABS/REL (0x08/0x00 i.e.  bit position 3)
121  *              PAG (0x10 i.e.  bit position 4)
122  *
123  *
124  *      (6)     T Line
125  *
126  *              T xx xx nn nn nn nn nn ...
127  *
128  *      The  T  line contains the assembled code output by the assem-
129  *      bler with xx xx being the offset address from the  current  area
130  *      base address and nn being the assembled instructions and data in
131  *      byte format.
132  *
133  *
134  *      (7)     R Line
135  *
136  *              R 0 0 nn nn n1 n2 xx xx ...
137  *
138  *      The R line provides the relocation information to the linker.
139  *      The nn nn value is the current area index, i.e.  which area  the
140  *      current  values  were  assembled.  Relocation information is en-
141  *      coded in groups of 4 bytes:
142  *
143  *      1.  n1 is the relocation mode and object format
144  *              1.  bit 0 word(0x00)/byte(0x01)
145  *              2.  bit 1 relocatable area(0x00)/symbol(0x02)
146  *              3.  bit 2 normal(0x00)/PC relative(0x04) relocation
147  *              4.  bit  3  1-byte(0x00)/2-byte(0x08) object format for
148  *                  byte data
149  *              5.  bit 4 signed(0x00)/unsigned(0x10) byte data
150  *              6.  bit 5 normal(0x00)/page '0'(0x20) reference
151  *              7.  bit 6 normal(0x00)/page 'nnn'(0x40) reference
152  *              8.  bit 7 normal(0x00)/MSB of value
153  *
154  *      2.  n2  is  a byte index into the corresponding
155  *              (i.e.  preceeding) T line data (i.e.  a pointer to
156  *              the data to be updated  by  the  relocation).
157  *              The T line data may be 1-byte or 2-byte byte data
158  *              format or 2-byte word format.
159  *
160  *      3.  xx xx  is the area/symbol index for the area/symbol be-
161  *              ing referenced.  the corresponding area/symbol is found
162  *              in the header area/symbol lists.
163  *
164  *
165  *      The groups of 4 bytes are repeated for each item requiring relo-
166  *      cation in the preceeding T line.
167  *
168  *
169  *      (8)     P Line
170  *
171  *              P 0 0 nn nn n1 n2 xx xx
172  *
173  *      The  P  line provides the paging information to the linker as
174  *      specified by a .setdp directive.  The format of  the  relocation
175  *      information is identical to that of the R line.  The correspond-
176  *      ing T line has the following information:
177  *              T xx xx aa aa bb bb
178  *
179  *      Where  aa aa is the area reference number which specifies the
180  *      selected page area and bb bb is the base address  of  the  page.
181  *      bb bb will require relocation processing if the 'n1 n2 xx xx' is
182  *      specified in the P line.  The linker will verify that  the  base
183  *      address is on a 256 byte boundary and that the page length of an
184  *      area defined with the PAG type is not larger than 256 bytes.
185  *
186  *      The  linker  defaults any direct page references to the first
187  *      area defined in the input REL file.  All ASxxxx assemblers  will
188  *      specify the _CODE area first, making this the default page area.
189  *
190  *
191  *      asout.c contains the following functions:
192  *              int     lobyte()
193  *              int     hibyte()
194  *              int     thrdbyte()
195  *              int     frthbyte()
196  *              VOID    out()
197  *              VOID    outall()
198  *              VOID    outarea()
199  *              VOID    outbuf()
200  *              VOID    outchk()
201  *              VOID    outdp()
202  *              VOID    outdot()
203  *              VOID    outgsd()
204  *              VOID    outsym()
205  *              VOID    outab()
206  *              VOID    outaw()
207  *              VOID    outa3b()
208  *              VOID    outa4b()
209  *              VOID    outaxb()
210  *              VOID    outatxb()
211  *              VOID    outrb()
212  *              VOID    outrw()
213  *              VOID    outr11()
214  *              VOID    out_lb()
215  *              VOID    out_lw()
216  *              VOID    out_l3b()
217  *              VOID    out_l4b()
218  *              VOID    out_lxb()
219  *              VOID    out_txb()
220  */
221 
222 /*)Function     VOID    outab(v)
223  *)Function     VOID    outaw(v)
224  *)Function     VOID    outa3b(v)
225  *)Function     VOID    outa4b(v)
226  *
227  *              a_uint  v               assembler data
228  *
229  *      Dispatch to output routine of 1 to 4 absolute bytes.
230  *
231  *      local variables:
232  *              none
233  *
234  *      global variables:
235  *              none
236  *
237  *      functions called:
238  *              VOID    outaxb()        asout.c
239  *
240  *      side effects:
241  *              Absolute data is processed.
242  */
243 
244 VOID
outab(a_uint v)245 outab(a_uint v)
246 {
247         outaxb(1, v);
248 }
249 
250 VOID
outaw(a_uint v)251 outaw(a_uint v)
252 {
253         outaxb(2, v);
254 }
255 
256 VOID
outa3b(a_uint v)257 outa3b(a_uint v)
258 {
259         outaxb(3, v);
260 }
261 
262 VOID
outa4b(a_uint v)263 outa4b(a_uint v)
264 {
265         outaxb(4, v);
266 }
267 
268 /*)Function     VOID    outaxb(i, v)
269  *
270  *              int     i               output byte count
271  *              a_uint  v               assembler data
272  *
273  *      The function outaxb() processes 1 to 4 bytes of
274  *      assembled data in absolute format.
275  *
276  *      local variables:
277  *              int p_bytes
278  *
279  *      global variables:
280  *              sym     dot             defined as sym[0]
281  *              int     oflag           -o, generate relocatable output flag
282  *              int     pass            assembler pass number
283  *
284  *      functions called:
285  *              VOID    outatxb()       asout.c
286  *              VOID    outchk()        asout.c
287  *              VOID    out_lxb()       asout.c
288  *
289  *      side effects:
290  *              The current assembly address is incremented by i.
291  */
292 
293 VOID
outaxb(int i,a_uint v)294 outaxb(int i, a_uint v)
295 {
296         int p_bytes;
297 
298         if (pass == 2) {
299                 out_lxb(i, v, 0);
300                 if (oflag) {
301                         outchk(i, 0);
302                         outatxb(i, v);
303                 }
304         }
305         /*
306          * Update the Program Counter
307          */
308         p_bytes = 1;
309         dot.s_addr += (i/p_bytes) + (i % p_bytes ? 1 : 0);
310 }
311 
312 /* sdas specific */
313 /*)Function     VOID    write_rmode(r, n)
314  *
315  *              int     r               relocation mode
316  *              int     n               byte index
317  *
318  *      write_rmode puts the passed relocation mode into the
319  *      output relp buffer, escaping it if necessary.
320  *
321  *      global variables:
322  *              char *  relp            Pointer to R Line Values
323  *
324  *      functions called:
325  *              VOID    rerr()          assubr.c
326  *
327  *      side effects:
328  *              relp is incremented appropriately.
329  */
330 VOID
write_rmode(int r,int n)331 write_rmode(int r, int n)
332 {
333     /* We need to escape the relocation mode if it is greater
334      * than a byte, or if it happens to look like an escape.
335      * (I don't think that the latter case is legal, but
336      * better safe than sorry).
337      */
338     if ((r > 0xff) || ((r & R_ESCAPE_MASK) == R_ESCAPE_MASK))
339     {
340         /* Hack in up to an extra 4 bits of flags with escape. */
341         if (r > 0xfff)
342         {
343              /* uh-oh.. we have more than 4 extra bits. */
344              fprintf(stderr,
345                      "Internal error: relocation mode 0x%X too big.\n",
346                      r);
347              rerr();
348         }
349         /* printf("escaping relocation mode\n"); */
350         *relp++ = R_ESCAPE_MASK | (r >> 8);
351         *relp++ = r & 0xff;
352     }
353     else
354     {
355         *relp++ = r;
356     }
357     *relp++ = n;
358 }
359 /* end sdas specific */
360 
361 /*)Function     VOID    outatxb(i, v)
362  *
363  *              int     i               number of bytes to process
364  *              int     v               assembler data
365  *
366  *      The function outatxb() outputs i bytes
367  *
368  *      local variables:
369  *              none
370  *
371  *      global variables:
372  *              int     hilo            byte order
373  *              char *  txtp            Pointer to T Line Values
374  *
375  *      functions called:
376  *              int     lobyte()        asout.c
377  *              int     hibyte()        asout.c
378  *              int     thrdbyte()      asout.c
379  *              int     frthbyte()      asout.c
380  *
381  *      side effects:
382  *              i bytes are placed into the T Line Buffer.
383  */
384 
385 VOID
outatxb(int i,a_uint v)386 outatxb(int i, a_uint v)
387 {
388         if ((int) hilo) {
389                 if (i >= 4) *txtp++ = frthbyte(v);
390                 if (i >= 3) *txtp++ = thrdbyte(v);
391                 if (i >= 2) *txtp++ = hibyte(v);
392                 if (i >= 1) *txtp++ = lobyte(v);
393         } else {
394                 if (i >= 1) *txtp++ = lobyte(v);
395                 if (i >= 2) *txtp++ = hibyte(v);
396                 if (i >= 3) *txtp++ = thrdbyte(v);
397                 if (i >= 4) *txtp++ = frthbyte(v);
398         }
399 }
400 
401 /*)Function     VOID    outrb(esp, r)
402  *
403  *              expr *  esp             pointer to expr structure
404  *              int     r               relocation mode
405  *
406  *      Dispatch functions for processing relocatable data.
407  *
408  *      local variables:
409  *              none
410  *
411  *      global variables:
412  *              none
413  *
414  *      functions called:
415  *              int     outrxb()        asout.c
416  *
417  *      side effects:
418  *              relocatable data processed
419  */
420 
421 VOID
outrb(struct expr * esp,int r)422 outrb(struct expr *esp, int r)
423 {
424         outrxb(1, esp, r);
425 }
426 
427 
428 /*)Function     VOID    outrxb(i, esp, r)
429  *
430  *              int     i               output byte count
431  *              expr *  esp             pointer to expr structure
432  *              int     r               relocation mode
433  *
434  *      The function outrxb() processes 1 to 4 bytes of generated code
435  *      in either absolute or relocatable format dependent upon
436  *      the data contained in the expr structure esp.  If the
437  *      .REL output is enabled then the appropriate information
438  *      is loaded into the txt and rel buffers.
439  *
440  *      local variables:
441  *              int     m               signed value mask
442  *              int     n               unsigned value mask
443  *                                      symbol/area reference number
444  *
445  *      global variables:
446  *              int     a_bytes         T Line byte count
447  *              sym     dot             defined as sym[0]
448  *              int     oflag           -o, generate relocatable output flag
449  *              int     pass            assembler pass number
450  *              char *  relp            Pointer to R Line Values
451  *              char *  txtp            Pointer to T Line Values
452  *
453  *      functions called:
454  *              VOID    outchk()        asout.c
455  *              VOID    out_lb()        asout.c
456  *              VOID    out_rb()        asout.c
457  *              VOID    out_tb()        asout.c
458  *
459  *      side effects:
460  *              R and T Lines updated.  Listing updated.
461  *              The current assembly address is incremented by i.
462  */
463 
464 VOID
outrxb(int i,struct expr * esp,int r)465 outrxb(int i, struct expr *esp, int r)
466 {
467         a_uint m, n;
468         int p_bytes;
469 
470         if (pass == 2) {
471                 if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
472                         /* This is a constant; simply write the
473                          * const byte to the T line and don't
474                          * generate any relocation info.
475                          */
476                         /*
477                          * Mask Value Selection
478                          */
479 #ifdef  LONGINT
480                         switch(i) {
481                         default:
482                         case 1: m = (a_uint) ~0x0000007Fl;      n = (a_uint) ~0x000000FFl;      break;  /* 1 byte  */
483                         case 2: m = (a_uint) ~0x00007FFFl;      n = (a_uint) ~0x0000FFFFl;      break;  /* 2 bytes */
484                         case 3: m = (a_uint) ~0x007FFFFFl;      n = (a_uint) ~0x00FFFFFFl;      break;  /* 3 bytes */
485                         case 4: m = (a_uint) ~0x7FFFFFFFl;      n = (a_uint) ~0xFFFFFFFFl;      break;  /* 4 bytes */
486                         }
487 #else
488                         switch(i) {
489                         default:
490                         case 1: m = (a_uint) ~0x0000007F;       n = (a_uint) ~0x000000FF;       break;  /* 1 byte  */
491                         case 2: m = (a_uint) ~0x00007FFF;       n = (a_uint) ~0x0000FFFF;       break;  /* 2 bytes */
492                         case 3: m = (a_uint) ~0x007FFFFF;       n = (a_uint) ~0x00FFFFFF;       break;  /* 3 bytes */
493                         case 4: m = (a_uint) ~0x7FFFFFFF;       n = (a_uint) ~0xFFFFFFFF;       break;  /* 4 bytes */
494                         }
495 #endif
496                         /*
497                          * Signed Range Check
498                          */
499                         (void)m; //temporary fix warning
500 
501                         /*
502                          * Page0 Range Check
503                          */
504                         if (((r & (R_SGND | R_USGN | R_PAGX | R_PCR)) == R_PAG0) &&
505                            ((n & esp->e_addr) != 0))
506                                 err('d');
507 
508                         out_lxb(i,esp->e_addr,0);
509                         if (oflag) {
510                                 outchk(i,0);
511                                 outatxb(i,esp->e_addr);
512                         }
513                 } else {
514                         if ((i == 1) && (!is_sdas() || !(is_sdas_target_8051_like() || is_sdas_target_stm8()))) {
515                                 r |= R_BYTE | R_BYTX | esp->e_rlcf;
516                                 if (r & R_MSB) {
517                                         out_lb(hibyte(esp->e_addr),r|R_RELOC|R_HIGH);
518                                 } else {
519                                         out_lb(lobyte(esp->e_addr),r|R_RELOC);
520                                 }
521                                 if (oflag) {
522                                         outchk(a_bytes, 4);
523                                         out_txb(a_bytes, esp->e_addr);
524                                         if (esp->e_flag) {
525                                                 n = esp->e_base.e_sp->s_ref;
526                                                 r |= R_SYM;
527                                         } else {
528                                                 n = esp->e_base.e_ap->a_ref;
529                                         }
530                                         *relp++ = r;
531                                         *relp++ = txtp - txt - a_bytes;
532                                         out_rw(n);
533                                 }
534                         } else {
535                                 /* sdas mcs51 specific */
536                                 /* We are generating a single byte of relocatable
537                                  * info.
538                                  *
539                                  * We generate a 24 bit address. The linker will
540                                  * select a single byte based on whether R_MSB or
541                                  * R_HIB is set.
542                                  */
543                                 /* 24 bit mode. */
544                                 r |= R_BYTE | R_BYT3 | esp->e_rlcf;
545                                 if (r & R_HIB)
546                                 {
547                                     /* Probably should mark this differently in the
548                                      * listing file.
549                                      */
550                                     out_lb(thrdbyte(esp->e_addr),r|R_RELOC|R_HIGH);
551                                 }
552                                 else if (r & R_MSB) {
553                                     out_lb(hibyte(esp->e_addr),r|R_RELOC|R_HIGH);
554                                 } else {
555                                     out_lb(lobyte(esp->e_addr),r|R_RELOC);
556                                 }
557                                 if (oflag) {
558                                     outchk(a_bytes, 5);
559                                     out_txb(a_bytes, esp->e_addr);
560                                     if (esp->e_flag) {
561                                             n = esp->e_base.e_sp->s_ref;
562                                             r |= R_SYM;
563                                     } else {
564                                             n = esp->e_base.e_ap->a_ref;
565                                     }
566                                     write_rmode(r, txtp - txt - a_bytes);
567                                     out_rw(n);
568                                 }
569                                 /* end sdas mcs51 specific */
570                         }
571                 }
572         }
573         /*
574          * Update the Program Counter
575          */
576         p_bytes = 1;
577         dot.s_addr += (i/p_bytes) + (i % p_bytes ? 1 : 0);
578 }
579 
580 /*)Function     VOID    outrw(esp, r)
581  *
582  *              expr *  esp             pointer to expr structure
583  *              int     r               relocation mode
584  *
585  *      The function outrw() processes a word of generated code
586  *      in either absolute or relocatable format dependent upon
587  *      the data contained in the expr structure esp.  If the
588  *      .REL output is enabled then the appropriate information
589  *      is loaded into the txt and rel buffers.
590  *
591  *      local variables:
592  *              int     n               symbol/area reference number
593  *
594  *      global variables:
595  *              sym     dot             defined as sym[0]
596  *              int     oflag           -o, generate relocatable output flag
597  *              int     pass            assembler pass number
598  *              char *  relp            Pointer to R Line Values
599  *              char *  txtp            Pointer to T Line Values
600  *
601  *      functions called:
602  *              VOID    outchk()        asout.c
603  *              VOID    out_lw()        asout.c
604  *              VOID    out_rw()        asout.c
605  *              VOID    out_txb()       asout.c
606  *
607  *      side effects:
608  *              The current assembly address is incremented by 2.
609  */
610 
611 VOID
outrw(struct expr * esp,int r)612 outrw(struct expr *esp, int r)
613 {
614         int n;
615 
616         if (pass == 2) {
617                 /* sdas specific */
618                 if (is_sdas() && is_sdas_target_8051_like() && esp->e_addr > 0xffff) {
619                     warnBanner();
620                     fprintf(stderr,
621                             "large constant 0x%x truncated to 16 bits\n",
622                             esp->e_addr);
623                 }
624                 /* end sdas specific */
625                 if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
626                         out_lxb(2,esp->e_addr,0);
627                         if (oflag) {
628                                 outchk(2,0);
629                                 out_txb(2,esp->e_addr);
630                         }
631                 } else {
632                         r |= R_WORD | esp->e_rlcf;
633                         if (r & R_BYTX) {
634                                 rerr();
635                                 if (r & R_MSB) {
636                                         out_lw(hibyte(esp->e_addr),r|R_RELOC);
637                                 } else {
638                                         out_lw(lobyte(esp->e_addr),r|R_RELOC);
639                                 }
640                         } else {
641                                 out_lw(esp->e_addr,r|R_RELOC);
642                         }
643                         if (oflag) {
644                                 if (!is_sdas() || !(is_sdas_target_8051_like() || is_sdas_target_stm8())) {
645                                         outchk(2, 4);
646                                         out_txb(2, esp->e_addr);
647                                         if (esp->e_flag) {
648                                                 n = esp->e_base.e_sp->s_ref;
649                                                 r |= R_SYM;
650                                         } else {
651                                                 n = esp->e_base.e_ap->a_ref;
652                                         }
653                                         *relp++ = r;
654                                         *relp++ = txtp - txt - 2;
655                                         out_rw(n);
656                                 } else {
657                                         outchk(2, 5);
658                                         out_txb(2, esp->e_addr);
659                                         if (esp->e_flag) {
660                                                 n = esp->e_base.e_sp->s_ref;
661                                                 r |= R_SYM;
662                                         } else {
663                                                 n = esp->e_base.e_ap->a_ref;
664                                         }
665 
666                                         if (IS_C24(r))
667                                         {
668                                             /* If this happens, the linker will
669                                              * attempt to process this 16 bit field
670                                              * as 24 bits. That would be bad.
671                                              */
672                                             fprintf(stderr,
673                                                     "***Internal error: C24 out in "
674                                                     "outrw()\n");
675                                             rerr();
676                                         }
677                                         write_rmode(r, txtp - txt - 2);
678                                         out_rw(n);
679                                 }
680                         }
681                 }
682         }
683         dot.s_addr += 2;
684 }
685 
686 /*)Function     VOID    outr3b(esp, r)
687  *
688  *              expr *  esp             pointer to expr structure
689  *              int     r               relocation mode
690  *
691  *      The function outr3b() processes 24 bits of generated code
692  *      in either absolute or relocatable format dependent upon
693  *      the data contained in the expr structure esp.  If the
694  *      .REL output is enabled then the appropriate information
695  *      is loaded into the txt and rel buffers.
696  *
697  *      local variables:
698  *              int     n               symbol/area reference number
699  *              int     esprv           merged value
700  *              int     p_bytes         program counter update temporary
701  *
702  *      global variables:
703  *              int     a_bytes         T Line byte count
704  *              sym     dot             defined as sym[0]
705  *              int     oflag           -o, generate relocatable output flag
706  *              int     pass            assembler pass number
707  *              char *  relp            Pointer to R Line Values
708  *              char *  txtp            Pointer to T Line Values
709  *
710  *      functions called:
711  *              VOID    outchk()        asout.c
712  *              VOID    out_lxb()       asout.c
713  *              VOID    out_rw()        asout.c
714  *              VOID    out_txb()       asout.c
715  *
716  *      side effects:
717  *              R and T Lines updated.  Listing updated.
718  *              The current assembly address is incremented by i.
719  */
720 
721 VOID
outr3b(struct expr * esp,int r)722 outr3b(struct expr *esp, int r)
723 {
724         int i = 3;
725         a_uint esprv;
726         int n, p_bytes;
727 
728         if (pass == 2) {
729                 esprv = esp->e_addr;
730                 if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
731                         /* This is a constant expression. */
732                         out_lxb(i,esprv,0);
733                         if (oflag) {
734                                 outchk(i,0);
735                                 out_txb(i,esprv);
736                         }
737                 } else {
738                         /* This is a symbol. */
739                         r |= R_WORD | esp->e_rlcf;
740                         if (r & R_BYTX) {
741                                 /* I have no idea what this case is. */
742                                 rerr();
743                                 if (r & R_MSB) {
744                                         out_lw(hibyte(esprv),r|R_RELOC);
745                                 } else {
746                                         out_lw(lobyte(esprv),r|R_RELOC);
747                                 }
748                         } else {
749                                 out_lxb(i,esprv,r|R_RELOC);
750                         }
751                         if (oflag) {
752                                 outchk(2*a_bytes, 5);
753                                 out_txb(a_bytes, esp->e_addr);
754                                 if (esp->e_flag) {
755                                         n = esp->e_base.e_sp->s_ref;
756                                         r |= R_SYM;
757                                 } else {
758                                         n = esp->e_base.e_ap->a_ref;
759                                 }
760 
761                                 if (r & R_BYTE)
762                                 {
763                                     /* If this occurs, we cannot properly
764                                      * code the relocation data with the
765                                      * R_C24 flag. This means the linker
766                                      * will fail to do the 24 bit relocation.
767                                      * Which will suck.
768                                      */
769                                     fprintf(stderr,
770                                             "***Internal error: BYTE out in 24 "
771                                             "bit flat mode unexpected.\n");
772                                     rerr();
773                                 }
774 
775                                 write_rmode(r | R_C24, txtp - txt - a_bytes);
776 
777                                 out_rw(n);
778                         }
779                 }
780         }
781         /*
782          * Update the Program Counter
783          */
784         p_bytes = 1;
785         dot.s_addr += (i/p_bytes) + (i % p_bytes ? 1 : 0);
786 }
787 
788 
789 /*)Function     VOID    outdp(carea, esp, r)
790  *
791  *              area *  carea           pointer to current area structure
792  *              expr *  esp             pointer to expr structure
793  *              int     r               optional PAGX relocation coding
794  *
795  *      The function outdp() flushes the output buffer and
796  *      outputs paging information to the .REL file.
797  *
798  *      local variables:
799  *              int     n               symbol/area reference number
800  *
801  *      global variables:
802  *              int     a_bytes         T Line byte count
803  *              int     oflag           -o, generate relocatable output flag
804  *              int     pass            assembler pass number
805  *              char *  relp            Pointer to R Line Values
806  *              char *  txtp            Pointer to T Line Values
807  *
808  *      functions called:
809  *              VOID    outbuf()        asout.c
810  *              VOID    outchk()        asout.c
811  *              VOID    out_rw()        asout.c
812  *              VOID    out_txb()       asout.c
813  *
814  *      side effects:
815  *              Output buffer flushed to .REL file.
816  *              Paging information dumped to .REL file.
817  */
818 
819 VOID
outdp(struct area * carea,struct expr * esp,int r)820 outdp(struct area *carea, struct expr *esp, int r)
821 {
822         a_uint n;
823 
824         if (oflag && pass==2) {
825                 outchk(ASXHUGE, ASXHUGE);
826                 out_txb(a_bytes, carea->a_ref);
827                 out_txb(a_bytes, esp->e_addr);
828                 if (esp->e_flag || esp->e_base.e_ap!=NULL) {
829                         if (esp->e_base.e_ap == NULL) {
830                                 n = area[1].a_ref;
831                                 r |= R_AREA;
832                                 fprintf(stderr, "?ASxxxx-OUTDP-NULL-POINTER error.\n\n");
833                         } else
834                         if (esp->e_flag) {
835                                 n = esp->e_base.e_sp->s_ref;
836                                 r |= R_SYM;
837                         } else {
838                                 n = esp->e_base.e_ap->a_ref;
839                                 r |= R_AREA;
840                         }
841                         write_rmode(r, txtp - txt - a_bytes);
842                         out_rw(n);
843                 }
844                 outbuf("P");
845         }
846 }
847 
848 /*)Function     VOID    outall()
849  *
850  *      The function outall() will output any bufferred assembled
851  *      data and relocation information (during pass 2 if the .REL
852  *      output has been enabled).
853  *
854  *      local variables:
855  *              none
856  *
857  *      global variables:
858  *              int     oflag           -o, generate relocatable output flag
859  *              int     pass            assembler pass number
860  *
861  *      functions called:
862  *              VOID    outbuf()        asout.c
863  *
864  *      side effects:
865  *              assembled data and relocation buffers will be cleared.
866  */
867 
868 VOID
outall(void)869 outall(void)
870 {
871         if (oflag && pass==2)
872                 outbuf("R");
873 }
874 
875 /*)Function     VOID    outdot()
876  *
877  *      The function outdot() outputs information about the
878  *      current program counter value (during pass 2 if the .REL
879  *      output has been enabled).
880  *
881  *      local variables:
882  *              none
883  *
884  *      global variables:
885  *              int     oflag           -o, generate relocatable output flag
886  *              int     pass            assembler pass number
887  *              char    rel[]           relocation data for code/data array
888  *              char *  relp            Pointer to R Line Values
889  *              char    txt[]           assembled code/data array
890  *              char *  txtp            Pointer to T Line Values
891  *
892  *      functions called:
893  *              int     fprintf()       c_library
894  *              VOID    out()           asout.c
895  *
896  *      side effects:
897  *              assembled data and relocation buffers will be cleared.
898  */
899 
900 VOID
outdot(void)901 outdot(void)
902 {
903         if (oflag && pass==2) {
904                 fprintf(ofp, "T");
905                 out(txt,(int) (txtp-txt));
906                 fprintf(ofp, "\n");
907                 fprintf(ofp, "R");
908                 out(rel,(int) (relp-rel));
909                 fprintf(ofp, "\n");
910                 txtp = txt;
911                 relp = rel;
912         }
913 }
914 
915 /*)Function     outchk(nt, nr)
916  *
917  *              int     nr              number of additional relocation words
918  *              int     nt              number of additional data words
919  *
920  *      The function outchk() checks the data and relocation buffers
921  *      for space to insert the nt data words and nr relocation words.
922  *      If space is not available then output the current data and
923  *      initialize the data buffers to receive the new data.
924  *
925  *      local variables:
926  *              area *  ap              pointer to an area structure
927  *
928  *      global variables:
929  *              int     a_bytes         T Line byte count
930  *              sym     dot             defined as sym[0]
931  *              char    rel[]           relocation data for code/data array
932  *              char *  relp            Pointer to R Line Values
933  *              char    txt[]           assembled code/data array
934  *              char *  txtp            Pointer to T Line Values
935  *
936  *      functions called:
937  *              VOID    outbuf()        asout.c
938  *              VOID    out_rw()        asout.c
939  *              VOID    out_txb()       asout.c
940  *
941  *      side effects:
942  *              Data and relocation buffers may be emptied and initialized.
943  */
944 
945 VOID
outchk(int nt,int nr)946 outchk(int nt, int nr)
947 {
948         struct area *ap;
949 
950         if (txtp+nt > &txt[NTXT] || relp+nr > &rel[NREL]) {
951                 outbuf("R");
952         }
953         if (txtp == txt) {
954                 out_txb(a_bytes, dot.s_addr);
955                 if ((ap = dot.s_area) != NULL) {
956                         write_rmode(R_WORD|R_AREA, 0);
957                         out_rw(ap->a_ref);
958                 }
959         }
960 }
961 
962 /*)Function     VOID    outbuf(s)
963  *
964  *              char *  s               "R" or "P" or ("I" illegal)
965  *
966  *      The function outbuf() will output any bufferred data
967  *      and relocation information to the .REL file.  The output
968  *      buffer pointers and counters are initialized.
969  *
970  *      local variables:
971  *              none
972  *
973  *      global variables:
974  *              int     a_bytes         T Line byte count
975  *              FILE *  ofp             relocation output file handle
976  *              char    rel[]           relocation data for code/data array
977  *              char *  relp            Pointer to R Line Values
978  *              char    txt[]           assembled code/data array
979  *              char *  txtp            Pointer to T Line Values
980  *
981  *      functions called:
982  *              int     fprintf()       c_library
983  *              VOID    out()           asout.c
984  *
985  *      side effects:
986  *              All bufferred data written to .REL file and
987  *              buffer pointers and counters initialized.
988  */
989 
990 VOID
outbuf(char * s)991 outbuf(char *s)
992 {
993         if (txtp > &txt[a_bytes]) {
994                 fprintf(ofp, "T");
995                 out(txt,(int) (txtp-txt));
996                 fprintf(ofp, "\n");
997                 fprintf(ofp, "%s", s);
998                 out(rel,(int) (relp-rel));
999                 fprintf(ofp, "\n");
1000         }
1001         txtp = txt;
1002         relp = rel;
1003 }
1004 
1005 VOID
outradix()1006 outradix()
1007 {
1008         if (pass < 2)
1009                 return;
1010 
1011         /*
1012          * Output Radix
1013          */
1014         if (xflag == 0) {
1015                 fprintf(ofp, "X%c%d\n", (int) hilo ? 'H' : 'L', a_bytes);
1016         } else
1017         if (xflag == 1) {
1018                 fprintf(ofp, "Q%c%d\n", (int) hilo ? 'H' : 'L', a_bytes);
1019         } else
1020         if (xflag == 2) {
1021                 fprintf(ofp, "D%c%d\n", (int) hilo ? 'H' : 'L', a_bytes);
1022         }
1023 }
1024 
1025 /*)Function     VOID    outgsd()
1026  *
1027  *      The function outgsd() performs the following:
1028  *      (1)     outputs the .REL file radix
1029  *      (2)     outputs the header specifying the number
1030  *              of areas and global symbols
1031  *      (3)     outputs the module name
1032  *      (4)     set the reference number and output a symbol line
1033  *              for all external global variables and absolutes
1034  *      (5)     output an area name, set reference number and output
1035  *              a symbol line for all global relocatables in the area.
1036  *              Repeat this proceedure for all areas.
1037  *
1038  *      local variables:
1039  *              area *  ap              pointer to an area structure
1040  *              sym *   sp              pointer to a sym structure
1041  *              int     i               loop counter
1042  *              int     j               loop counter
1043  *              int     c               string character value
1044  *              int     narea           number of code areas
1045  *              int     nglob           number of global symbols
1046  *              char *  ptr             string pointer
1047  *              int     rn              symbol reference number
1048  *
1049  *      global variables:
1050  *              int     a_bytes         T Line byte count
1051  *              area *  areap           pointer to an area structure
1052  *              int     hilo            byte order
1053  *              char    module[]        module name string
1054  *              sym *   symhash[]       array of pointers to NHASH
1055  *                                      linked symbol lists
1056  *              int     xflag           -x, listing radix flag
1057  *
1058  *      functions called:
1059  *              int     fprintf()       c_library
1060  *              VOID    outarea()       asout.c
1061  *              VOID    outsym()        asout.c
1062  *
1063  *      side effects:
1064  *              All symbols are given reference numbers, all symbol
1065  *              and area information is output to the .REL file.
1066  */
1067 
1068 VOID
outgsd(void)1069 outgsd(void)
1070 {
1071         struct area *ap;
1072         struct sym  *sp;
1073         int i, j;
1074         char *ptr;
1075         int narea, nglob, rn;
1076 
1077         /*
1078          * Number of areas
1079          */
1080         narea = areap->a_ref + 1;
1081 
1082         /*
1083          * Number of global references/absolutes
1084          */
1085         nglob = 0;
1086         for (i = 0; i < NHASH; ++i) {
1087                 sp = symhash[i];
1088                 while (sp) {
1089                         if (sp->s_flag&S_GBL)
1090                                 nglob += 1;
1091                         sp = sp->s_sp;
1092                 }
1093         }
1094 
1095         outradix();
1096 
1097         /*
1098          * Output number of areas and symbols
1099          */
1100         if (xflag == 0) {
1101                 fprintf(ofp, "H %X areas %X global symbols\n", narea, nglob);
1102         } else
1103         if (xflag == 1) {
1104                 fprintf(ofp, "H %o areas %o global symbols\n", narea, nglob);
1105         } else
1106         if (xflag == 2) {
1107                 fprintf(ofp, "H %u areas %u global symbols\n", narea, nglob);
1108         }
1109 
1110         /*
1111          * Module name
1112          */
1113         if (module[0]) {
1114                 fprintf(ofp, "M ");
1115                 ptr = &module[0];
1116                 fprintf(ofp, "%s\n", ptr);
1117         }
1118 
1119         /* sdas specific */
1120         /*
1121          * Sdcc compile options
1122          */
1123         if (is_sdas() && NULL != optsdcc) fprintf(ofp, "O %s\n", optsdcc);
1124         /* end sdas specific */
1125 
1126         /*
1127          * Global references and absolutes.
1128          */
1129         rn = 0;
1130         for (i=0; i<NHASH; ++i) {
1131                 sp = symhash[i];
1132                 while (sp) {
1133                         if (sp->s_area==NULL && sp->s_flag&S_GBL) {
1134                                 sp->s_ref = rn++;
1135                                 outsym(sp);
1136                         }
1137                         sp = sp->s_sp;
1138                 }
1139         }
1140 
1141         /*
1142          * Global relocatables.
1143          */
1144         for (i=0; i<narea; ++i) {
1145                 ap = areap;
1146                 while (ap->a_ref != i)
1147                         ap = ap->a_ap;
1148                 outarea(ap);
1149                 for (j=0; j<NHASH; ++j) {
1150                         sp = symhash[j];
1151                         while (sp) {
1152                                 if (sp->s_area==ap && sp->s_flag&S_GBL) {
1153                                         sp->s_ref = rn++;
1154                                         outsym(sp);
1155                                 }
1156                                 sp = sp->s_sp;
1157                         }
1158                 }
1159         }
1160 }
1161 
1162 /*)Function     VOID    outarea(ap)
1163  *
1164  *              area *  ap              pointer to an area structure
1165  *
1166  *      The function outarea()  outputs the A line to the .REL
1167  *      file.  The A line contains the area's name, size,
1168  *      and attributes.
1169  *
1170  *      local variables:
1171  *              char *  frmt            pointer to format string
1172  *
1173  *      global variables:
1174  *              FILE *  ofp             relocation output file handle
1175  *              int     xflag           -x, listing radix flag
1176  *
1177  *      functions called:
1178  *              int     fprintf()       c_library
1179  *
1180  *      side effects:
1181  *              The A line is sent to the .REL file.
1182  */
1183 
1184 VOID
outarea(struct area * ap)1185 outarea(struct area *ap)
1186 {
1187         char * frmt;
1188 
1189         fprintf(ofp, "A ");
1190         fprintf(ofp, "%s", &ap->a_id[0]);
1191 
1192         switch(xflag) {
1193         default:
1194         case 0: frmt = " size %X flags %X";     break;
1195         case 1: frmt = " size %o flags %o";     break;
1196         case 2: frmt = " size %u flags %u";     break;
1197         }
1198 
1199         fprintf(ofp, frmt, ap->a_size, ap->a_flag);
1200         if (is_sdas()) {
1201                 /* sdas specific */
1202                 if (xflag == 0) {
1203                         fprintf(ofp, " addr %X", ap->a_addr);
1204                 } else
1205                 if (xflag == 1) {
1206                         fprintf(ofp, " addr %o", ap->a_addr);
1207                 } else
1208                 if (xflag == 2) {
1209                         fprintf(ofp, " addr %u", ap->a_addr);
1210                 }
1211                 /* end sdas specific */
1212         }
1213         fprintf(ofp, "\n");
1214 }
1215 
1216 /*)Function     VOID    outsym(sp)
1217  *
1218  *              sym *   sp              pointer to a sym structure
1219  *
1220  *      The function outsym() outputs the S line to the .REL
1221  *      file.  The S line contains the symbols name and whether the
1222  *      the symbol is defined or referenced.
1223  *
1224  *      local variables:
1225  *              char *  frmt            pointer to format string
1226  *              int     s_addr          (int) truncated to 2-bytes
1227  *
1228  *      global variables:
1229  *              int     a_bytes         argument size in bytes
1230  *              FILE *  ofp             relocation output file handle
1231  *              int     xflag           -x, listing radix flag
1232  *
1233  *      functions called:
1234  *              int     fprintf()       c_library
1235  *
1236  *      side effects:
1237  *              The S line is sent to the .REL file.
1238  */
1239 
1240 VOID
outsym(struct sym * sp)1241 outsym(struct sym *sp)
1242 {
1243         char *frmt;
1244         a_uint s_addr;
1245 
1246         s_addr = sp->s_addr;
1247 
1248         fprintf(ofp, "S ");
1249         fprintf(ofp, "%s", &sp->s_id[0]);
1250         fprintf(ofp, " %s", sp->s_type==S_NEW ? "Ref" : "Def");
1251 
1252 #ifdef  LONGINT
1253         switch(xflag) {
1254         default:
1255         case 0:
1256                 switch(a_bytes) {
1257                 default:
1258                 case 2: frmt = "%04lX\n"; break;
1259                 case 3: frmt = "%06lX\n"; break;
1260                 case 4: frmt = "%08lX\n"; break;
1261                 }
1262                 break;
1263 
1264         case 1:
1265                 switch(a_bytes) {
1266                 default:
1267                 case 2: frmt = "%06lo\n"; break;
1268                 case 3: frmt = "%08lo\n"; break;
1269                 case 4: frmt = "%011lo\n"; break;
1270                 }
1271                 break;
1272 
1273         case 2:
1274                 switch(a_bytes) {
1275                 default:
1276                 case 2: frmt = "%05lu\n"; break;
1277                 case 3: frmt = "%08lu\n"; break;
1278                 case 4: frmt = "%010lu\n"; break;
1279                 }
1280                 break;
1281         }
1282 #else
1283         switch(xflag) {
1284         default:
1285         case 0:
1286                 switch(a_bytes) {
1287                 default:
1288                 case 2: frmt = "%04X\n"; break;
1289                 case 3: frmt = "%06X\n"; break;
1290                 case 4: frmt = "%08X\n"; break;
1291                 }
1292                 break;
1293 
1294         case 1:
1295                 switch(a_bytes) {
1296                 default:
1297                 case 2: frmt = "%06o\n"; break;
1298                 case 3: frmt = "%08o\n"; break;
1299                 case 4: frmt = "%011o\n"; break;
1300                 }
1301                 break;
1302 
1303         case 2:
1304                 switch(a_bytes) {
1305                 default:
1306                 case 2: frmt = "%05u\n"; break;
1307                 case 3: frmt = "%08u\n"; break;
1308                 case 4: frmt = "%010u\n"; break;
1309                 }
1310                 break;
1311         }
1312 #endif
1313 
1314         fprintf(ofp, frmt, s_addr);
1315 }
1316 
1317 /*)Function     VOID    out(p, n)
1318  *
1319  *              int     n               number of words to output
1320  *              int *   p               pointer to data words
1321  *
1322  *      The function out() outputs the data words to the .REL file
1323  *      in the specified radix.
1324  *
1325  *      local variables:
1326  *              none
1327  *
1328  *      global variables:
1329  *              FILE *  ofp             relocation output file handle
1330  *              int     xflag           -x, listing radix flag
1331  *
1332  *      functions called:
1333  *              int     fprintf()       c_library
1334  *
1335  *      side effects:
1336  *              Data is sent to the .REL file.
1337  */
1338 
1339 VOID
out(char * p,int n)1340 out(char *p, int n)
1341 {
1342         while (n--) {
1343                 if (xflag == 0) {
1344                         fprintf(ofp, " %02X", (*p++)&0377);
1345                 } else
1346                 if (xflag == 1) {
1347                         fprintf(ofp, " %03o", (*p++)&0377);
1348                 } else
1349                 if (xflag == 2) {
1350                         fprintf(ofp, " %03u", (*p++)&0377);
1351                 }
1352         }
1353 }
1354 
1355 /*)Function     VOID    out_lb(v, t)
1356  *
1357  *              a_uint  v               assembled data
1358  *              int     t               relocation type
1359  *
1360  *      The function out_lb() copies the assembled data and
1361  *      its relocation type to the list data buffers.
1362  *
1363  *      local variables:
1364  *              none
1365  *
1366  *      global variables:
1367  *              int *   cp              pointer to assembler output array cb[]
1368  *              int *   cpt             pointer to assembler relocation type
1369  *                                      output array cbt[]
1370  *
1371  *      functions called:
1372  *              none
1373  *
1374  *      side effects:
1375  *              Pointers to data and relocation buffers incremented by 1.
1376  */
1377 
1378 VOID
out_lb(a_uint v,int t)1379 out_lb(a_uint v, int t)
1380 {
1381         if (cp < &cb[NCODE]) {
1382                 *cp++ = (char) v;
1383                 *cpt++ = t;
1384         }
1385 }
1386 
1387 /*)Function     VOID    out_lw(v, t)
1388  *)Function     VOID    out_l3b(v, t)
1389  *)Function     VOID    out_l4b(v, t)
1390  *
1391  *              a_uint  v               assembled data
1392  *              int     t               relocation type
1393  *
1394  *      Dispatch functions for processing listing data.
1395  *
1396  *      local variables:
1397  *              none
1398  *
1399  *      global variables:
1400  *              none
1401  *
1402  *      functions called:
1403  *              none
1404  *
1405  *      side effects:
1406  *              Listing data processed.
1407  */
1408 
1409 VOID
out_lw(a_uint v,int t)1410 out_lw(a_uint v, int t)
1411 {
1412         out_lxb(2, v, t);
1413 }
1414 
1415 VOID
out_l3b(a_uint v,int t)1416 out_l3b(a_uint v, int t)
1417 {
1418         out_lxb(3, v, t);
1419 }
1420 
1421 VOID
out_l4b(a_uint v,int t)1422 out_l4b(a_uint v, int t)
1423 {
1424         out_lxb(4, v, t);
1425 }
1426 
1427 /*)Function     VOID    out_lxb(i, v, t)
1428  *
1429  *              int     i               output byte count
1430  *              a_uint  v               assembled data
1431  *              int     t               relocation type
1432  *
1433  *      Dispatch function for list processing.
1434  *
1435  *      local variables:
1436  *              none
1437  *
1438  *      global variables:
1439  *              int     hilo            byte order
1440  *
1441  *      functions called:
1442  *              VOID    out_lb()        asout.c
1443  *
1444  *      side effects:
1445  *              i list bytes are processed.
1446  */
1447 
1448 VOID
out_lxb(int i,a_uint v,int t)1449 out_lxb(int i, a_uint v, int t)
1450 {
1451         if ((int) hilo) {
1452                 if (i >= 3) out_lb(thrdbyte(v),t ? t|R_HIGH : 0);
1453                 if (i >= 2) out_lb(hibyte(v),t);
1454                 if (i >= 1) out_lb(lobyte(v),t);
1455         } else {
1456                 if (i >= 1) out_lb(lobyte(v),t);
1457                 if (i >= 2) out_lb(hibyte(v),t);
1458                 if (i >= 3) out_lb(thrdbyte(v),t ? t|R_HIGH : 0);
1459         }
1460 }
1461 
1462 /*)Function     VOID    out_rw(v)
1463  *
1464  *              a_uint  v               assembled data
1465  *
1466  *      The function out_rw() outputs the relocation (R)
1467  *      data word as two bytes ordered according to hilo.
1468  *
1469  *      local variables:
1470  *              none
1471  *
1472  *      global variables:
1473  *              int     hilo            byte order
1474  *              char *  relp            Pointer to R Line Values
1475  *
1476  *      functions called:
1477  *              int     lobyte()        asout.c
1478  *              int     hibyte()        asout.c
1479  *
1480  *      side effects:
1481  *              Pointer to relocation buffer incremented by 2.
1482  */
1483 
1484 VOID
out_rw(a_uint v)1485 out_rw(a_uint v)
1486 {
1487         if ((int) hilo) {
1488                 *relp++ = hibyte(v);
1489                 *relp++ = lobyte(v);
1490         } else {
1491                 *relp++ = lobyte(v);
1492                 *relp++ = hibyte(v);
1493         }
1494 }
1495 
1496 /*)Function     VOID    out_txb(i, v)
1497  *
1498  *              int     i               T Line byte count
1499  *              a_uint  v               data word
1500  *
1501  *      The function out_txb() outputs the text (T)
1502  *      data word as i bytes ordered according to hilo.
1503  *
1504  *      local variables:
1505  *
1506  *      global variables:
1507  *              int     hilo            byte order
1508  *              char *  txtp            Pointer to T Line Values
1509  *
1510  *      functions called:
1511  *              int     lobyte()        asout.c
1512  *              int     hibyte()        asout.c
1513  *              int     thrdbyte()      asout.c
1514  *              int     frthbyte()      asout.c
1515  *
1516  *      side effects:
1517  *              T Line buffer updated.
1518  */
1519 
1520 VOID
out_txb(int i,a_uint v)1521 out_txb(int i, a_uint v)
1522 {
1523         if ((int) hilo) {
1524                 if (i >= 4) *txtp++ = frthbyte(v);
1525                 if (i >= 3) *txtp++ = thrdbyte(v);
1526                 if (i >= 2) *txtp++ = hibyte(v);
1527                 if (i >= 1) *txtp++ = lobyte(v);
1528         } else {
1529                 if (i >= 1) *txtp++ = lobyte(v);
1530                 if (i >= 2) *txtp++ = hibyte(v);
1531                 if (i >= 3) *txtp++ = thrdbyte(v);
1532                 if (i >= 4) *txtp++ = frthbyte(v);
1533         }
1534 }
1535 
1536 /*)Function     int     lobyte(v)
1537  *)Function     int     hibyte(v)
1538  *)Function     int     thrdbyte(v)
1539  *)Function     int     frthbyte(v)
1540  *
1541  *              a_uint  v               assembled data
1542  *
1543  *      These functions return the 1st, 2nd, 3rd, or 4th byte
1544  *      of integer v.
1545  *
1546  *      local variables:
1547  *              none
1548  *
1549  *      global variables:
1550  *              none
1551  *
1552  *      functions called:
1553  *              none
1554  *
1555  *      side effects:
1556  *              none
1557  */
1558 
1559 int
lobyte(a_uint v)1560 lobyte(a_uint v)
1561 {
1562         return ((int) v&0377);
1563 }
1564 
1565 int
hibyte(a_uint v)1566 hibyte(a_uint v)
1567 {
1568         return ((int) (v>>8)&0377);
1569 }
1570 
1571 int
thrdbyte(a_uint v)1572 thrdbyte(a_uint v)
1573 {
1574         return ((int) (v>>16)&0377);
1575 }
1576 
1577 int
frthbyte(a_uint v)1578 frthbyte(a_uint v)
1579 {
1580         return ((int) (v>>24)&0377);
1581 }
1582 
1583 /*
1584  * JLH: Output relocatable 11 bit jump/call
1585  *
1586  * This function is derived from outrw(), adding the parameter for the
1587  * 11 bit address.  This form of address is used only on the 8051 and 8048.
1588  */
1589 /*)Function     VOID    outrwm(esp, r, v)
1590  *
1591  *              expr *  esp             pointer to expr structure
1592  *              int     r               relocation mode
1593  *              int     v               opcode
1594  *
1595  *      The function outrwm() processes a word of generated code
1596  *      in either absolute or relocatable format dependent upon
1597  *      the data contained in the expr structure esp.  If the
1598  *      .REL output is enabled then the appropriate information
1599  *      is loaded into the txt and rel buffers.  The code is output
1600  *      in a special format to the linker to allow relocation and
1601  *      merging of the opcode and an 11 bit paged address as required
1602  *      by the 8051 architecture.
1603  *
1604  *      This function based on code by
1605  *              John L. Hartman
1606  *              jhartman@compuserve.com
1607  *
1608  *      local variables:
1609  *              int     n               symbol/area reference number
1610  *
1611  *      global variables:
1612  *              sym     dot             defined as sym[0]
1613  *              int     oflag           -o, generate relocatable output flag
1614  *              int     pass            assembler pass number
1615  *              char *  relp            Pointer to R Line Values
1616  *              char *  txtp            Pointer to T Line Values
1617  *
1618  *      functions called:
1619  *              VOID    outchk()        asout.c
1620  *              VOID    out_lw()        asout.c
1621  *              VOID    out_rw()        asout.c
1622  *              VOID    out_txb()       asout.c
1623  *
1624  *      side effects:
1625  *              The current assembly address is incremented by 2.
1626  */
1627 VOID
outrwm(struct expr * esp,int r,a_uint v)1628 outrwm(struct expr *esp, int r, a_uint v)
1629 {
1630         int n;
1631 
1632         if (pass == 2) {
1633                 if (!is_sdas() || !is_sdas_target_8051_like()) {
1634                         if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
1635                                 /*
1636                                  * Absolute Destination
1637                                  *
1638                                  * Use the global symbol '.__.ABS.'
1639                                  * of value zero and force the assembler
1640                                  * to use this absolute constant as the
1641                                  * base value for the relocation.
1642                                  */
1643                                 esp->e_flag = 1;
1644                                 esp->e_base.e_sp = &sym[1];
1645                         }
1646                         /*
1647                          * Relocatable Destination.  Build THREE
1648                          * byte output: relocatable word, followed
1649                          * by op-code.  Linker will combine them.
1650                          */
1651                         r |= R_WORD | esp->e_rlcf;
1652                         n = ((esp->e_addr & 0x0700) >> 3) | v;
1653                         n = (n << 8) | (esp->e_addr & 0xFF);
1654                         out_lw(n,r|R_RELOC);
1655                         if (oflag) {
1656                                 outchk(3, 4);
1657                                 out_txb(2, esp->e_addr);
1658                                 *txtp++ = v;
1659 
1660                                 if (esp->e_flag) {
1661                                         n = esp->e_base.e_sp->s_ref;
1662                                         r |= R_SYM;
1663                                 } else {
1664                                         n = esp->e_base.e_ap->a_ref;
1665                                 }
1666                                 *relp++ = r;
1667                                 *relp++ = txtp - txt - 3;
1668                                 out_rw(n);
1669                         }
1670                 } else {
1671                         if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
1672                                 /* Absolute destination.
1673                                  * Listing shows only the address.
1674                                  */
1675                                 out_lw(esp->e_addr,0);
1676                                 if (oflag) {
1677                                         outchk(3, 0);
1678                                         out_txb(2, esp->e_addr);
1679                                         *txtp++ = v;
1680 
1681                                         write_rmode(r, txtp - txt - 3);
1682                                         out_rw(0xFFFF);
1683                                 }
1684                         } else {
1685                                 /* Relocatable destination.  Build THREE
1686                                  * byte output: relocatable word, followed
1687                                  * by op-code.  Linker will combine them.
1688                                  * Listing shows only the address.
1689                                  */
1690                                 r |= R_WORD | esp->e_rlcf;
1691                                 out_lw(esp->e_addr,r|R_RELOC);
1692                                 if (oflag) {
1693                                         outchk(3, 5);
1694                                         out_txb(2, esp->e_addr);
1695                                         *txtp++ = v;
1696 
1697                                         if (esp->e_flag) {
1698                                                 n = esp->e_base.e_sp->s_ref;
1699                                                 r |= R_SYM;
1700                                         } else {
1701                                                 n = esp->e_base.e_ap->a_ref;
1702                                         }
1703                                         write_rmode(r, txtp - txt - 3);
1704                                         out_rw(n);
1705                                 }
1706                         }
1707                 }
1708         }
1709         dot.s_addr += 2;
1710 }
1711 
1712 /*
1713  * Output relocatable 19 bit jump/call
1714  *
1715  * This function is derived from outrw(), adding the parameter for the
1716  * 19 bit address.  This form of address is used only in the DS80C390.
1717  */
1718 VOID
outr3bm(struct expr * esp,int r,a_uint v)1719 outr3bm(struct expr * esp, int r, a_uint v)
1720 {
1721         int n;
1722 
1723         if (pass == 2) {
1724                 if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
1725                         /* Absolute destination.
1726                          * Listing shows only the address.
1727                          */
1728                         out_lw(esp->e_addr,0);
1729                         if (oflag) {
1730                                 outchk(4, 0);
1731                                 out_txb(3, esp->e_addr);
1732                                 *txtp++ = v;
1733 
1734                                 write_rmode(r, txtp - txt - 4);
1735                                 out_rw(0xFFFF);
1736                         }
1737                 } else {
1738                         /* Relocatable destination.  Build FOUR
1739                          * byte output: relocatable 24-bit entity, followed
1740                          * by op-code.  Linker will combine them.
1741                          * Listing shows only the address.
1742                          */
1743                         r |= R_WORD | esp->e_rlcf;
1744                         out_l3b(esp->e_addr,r|R_RELOC);
1745                         if (oflag) {
1746                                 outchk(4, 5);
1747                                 out_txb(3, esp->e_addr);
1748                                 *txtp++ = v;
1749 
1750                                 if (esp->e_flag) {
1751                                         n = esp->e_base.e_sp->s_ref;
1752                                         r |= R_SYM;
1753                                 } else {
1754                                         n = esp->e_base.e_ap->a_ref;
1755                                 }
1756                                 write_rmode(r, txtp - txt - 4);
1757                                 out_rw(n);
1758                         }
1759                 }
1760         }
1761         dot.s_addr += 3;
1762 }
1763 
1764 /*
1765  * PDK: Output relocatable 11 bit goto/call
1766  *
1767  * This function is derived from outrw(), adding the parameter for the
1768  * 11 bit address.  This form of address is used only on the pdk.
1769  */
1770 /*)Function     VOID    outrwp(esp, op, mask, jump)
1771  *
1772  *              expr *      esp             pointer to expr structure
1773  *              a_uint      op              opcode
1774  *              a_uint      mask            address mask
1775  *              int         jump            call/goto relocation data
1776  *
1777  *      The function outrwp() processes a word of generated code
1778  *      in either absolute or relocatable format dependent upon
1779  *      the data contained in the expr structure esp.  If the
1780  *      .REL output is enabled then the appropriate information
1781  *      is loaded into the txt and rel buffers.  The code is output
1782  *      in a special format to the linker to allow relocation and
1783  *      merging of the opcode.
1784  *
1785  *      This function based on code by
1786  *              John L. Hartman
1787  *              jhartman@compuserve.com
1788  *
1789  *      local variables:
1790  *              int     n               symbol/area reference number
1791  *              int     r               relocation information
1792  *
1793  *      global variables:
1794  *              sym     dot             defined as sym[0]
1795  *              int     oflag           -o, generate relocatable output flag
1796  *              int     pass            assembler pass number
1797  *              char *  relp            Pointer to R Line Values
1798  *              char *  txtp            Pointer to T Line Values
1799  *
1800  *      functions called:
1801  *              VOID    outchk()        asout.c
1802  *              VOID    out_lw()        asout.c
1803  *              VOID    out_rw()        asout.c
1804  *              VOID    out_txb()       asout.c
1805  *
1806  *      side effects:
1807  *              The current assembly address is incremented by 2.
1808  */
1809 VOID
outrwp(struct expr * esp,a_uint op,a_uint mask,int jump)1810 outrwp(struct expr *esp, a_uint op, a_uint mask, int jump)
1811 {
1812         int n, r = R_J11;
1813 
1814         if (pass == 2) {
1815                 if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
1816                         /*
1817                          * Absolute Destination
1818                          *
1819                          * Use the global symbol '.__.ABS.'
1820                          * of value zero and force the assembler
1821                          * to use this absolute constant as the
1822                          * base value for the relocation.
1823                          */
1824                         esp->e_flag = 1;
1825                         esp->e_base.e_sp = &sym[1];
1826                 }
1827 
1828                 /* We need to select either the MSB or LSB of the address.
1829                  * Reset relocation marker so that the linker knows what to do
1830                  * with it.
1831                  */
1832                 if (esp->e_rlcf & R_BYTX) {
1833                         r |= R_BYTE;
1834                         /* We might select the MSB/LSB of an address in RAM. In
1835                          * that case the linker should not convert the address
1836                          * to words.
1837                          */
1838                         if (!esp->e_flag && !memcmp(esp->e_base.e_ap->a_id, "DATA", 4)) {
1839                                 r |= R_USGN;
1840                         }
1841                 } else {
1842                         r |= R_WORD;
1843                 }
1844 
1845                 /* Some (address) marker bits might have been shifted out of
1846                  * range. Revert this and put them back where they belong.
1847                  */
1848                 if (esp->e_addr & ~0xFFFF) {
1849                         int marker = esp->e_addr & 0x10000;
1850                         esp->e_addr &= ~0x10000;
1851                         esp->e_addr |= marker >> 1;
1852                 }
1853 
1854                 /*
1855                  * Relocatable Destination.  Build FOUR
1856                  * byte output: relocatable word, followed
1857                  * by op-code.  Linker will combine them.
1858                  */
1859                 r |= esp->e_rlcf;
1860                 n =  op | (esp->e_addr & mask);
1861                 out_lw(n,r|R_RELOC);
1862                 if (oflag) {
1863                         outchk(5, 4);
1864                         out_txb(2, esp->e_addr);
1865                         out_txb(2, op);
1866                         out_txb(1, (int)get_sdas_target());
1867 
1868                         if (esp->e_flag) {
1869                                 n = esp->e_base.e_sp->s_ref;
1870                                 r |= R_SYM;
1871                         } else {
1872                                 n = esp->e_base.e_ap->a_ref;
1873                         }
1874                         *relp++ = r;
1875                         *relp++ = txtp - txt - 5;
1876                         out_rw(n);
1877                 }
1878         }
1879         dot.s_addr += 2;
1880 }
1881