4 * Copyright (C) 1989-2021 Alan R. Baldwin
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.
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.
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/>.
28 * - outsym: show s_id as string rather than array [NCPS]
29 * - Added outr11 to support 8051's 11 bit destination address
38 * The module asout.c contains all the functions used to
39 * generate the .REL assembler output file.
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.
46 * The object module contains the following designators:
53 * H Most significant byte first
54 * L Least significant byte first
56 * 2 16-Bit Relocatable Addresses/Data
57 * 3 24-Bit Relocatable Addresses/Data
58 * 4 32-Bit Relocatable Addresses/Data
65 * R Relocation information
66 * P Paging information
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.
79 * H aa areas gg global symbols
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.
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.
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
113 * A label size ss flags ff
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:
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)
126 * T xx xx nn nn nn nn nn ...
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
136 * R 0 0 nn nn n1 n2 xx xx ...
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:
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
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
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.
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.
165 * The groups of 4 bytes are repeated for each item requiring relo-
166 * cation in the preceeding T line.
171 * P 0 0 nn nn n1 n2 xx xx
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
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.
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.
191 * asout.c contains the following functions:
222 /*)Function VOID outab(v)
223 *)Function VOID outaw(v)
224 *)Function VOID outa3b(v)
225 *)Function VOID outa4b(v)
227 * a_uint v assembler data
229 * Dispatch to output routine of 1 to 4 absolute bytes.
238 * VOID outaxb() asout.c
241 * Absolute data is processed.
268 /*)Function VOID outaxb(i, v)
270 * int i output byte count
271 * a_uint v assembler data
273 * The function outaxb() processes 1 to 4 bytes of
274 * assembled data in absolute format.
280 * sym dot defined as sym[0]
281 * int oflag -o, generate relocatable output flag
282 * int pass assembler pass number
285 * VOID outatxb() asout.c
286 * VOID outchk() asout.c
287 * VOID out_lxb() asout.c
290 * The current assembly address is incremented by i.
294 outaxb(int i
, a_uint v
)
306 * Update the Program Counter
309 dot
.s_addr
+= (i
/p_bytes
) + (i
% p_bytes
? 1 : 0);
313 /*)Function VOID write_rmode(r, n)
315 * int r relocation mode
318 * write_rmode puts the passed relocation mode into the
319 * output relp buffer, escaping it if necessary.
322 * char * relp Pointer to R Line Values
325 * VOID rerr() assubr.c
328 * relp is incremented appropriately.
331 write_rmode(int r
, int n
)
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).
338 if ((r
> 0xff) || ((r
& R_ESCAPE_MASK
) == R_ESCAPE_MASK
))
340 /* Hack in up to an extra 4 bits of flags with escape. */
343 /* uh-oh.. we have more than 4 extra bits. */
345 "Internal error: relocation mode 0x%X too big.\n",
349 /* printf("escaping relocation mode\n"); */
350 *relp
++ = R_ESCAPE_MASK
| (r
>> 8);
359 /* end sdas specific */
361 /*)Function VOID outatxb(i, v)
363 * int i number of bytes to process
364 * a_uint v assembler data
366 * The function outatxb() outputs i bytes
372 * int hilo byte order
373 * char * txtp Pointer to T Line Values
376 * int lobyte() asout.c
377 * int hibyte() asout.c
378 * int thrdbyte() asout.c
379 * int frthbyte() asout.c
382 * i bytes are placed into the T Line Buffer.
386 outatxb(int i
, a_uint v
)
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
);
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
);
401 /*)Function VOID outrb(esp, r)
403 * expr * esp pointer to expr structure
404 * int r relocation mode
406 * Dispatch functions for processing relocatable data.
415 * int outrxb() asout.c
418 * relocatable data processed
422 outrb(struct expr
*esp
, int r
)
428 /*)Function VOID outrxb(i, esp, r)
430 * int i output byte count
431 * expr * esp pointer to expr structure
432 * int r relocation mode
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.
441 * int m signed value mask
442 * int n unsigned value mask
443 * symbol/area reference number
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
454 * VOID outchk() asout.c
455 * VOID out_lb() asout.c
456 * VOID out_rb() asout.c
457 * VOID out_tb() asout.c
460 * R and T Lines updated. Listing updated.
461 * The current assembly address is incremented by i.
465 outrxb(int i
, struct expr
*esp
, int r
)
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.
477 * Mask Value Selection
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 */
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 */
499 (void)m
; //temporary fix warning
504 if (((r
& (R_SGND
| R_USGN
| R_PAGX
| R_PCR
)) == R_PAG0
) &&
505 ((n
& esp
->e_addr
) != 0))
506 xerr('d', "Page 0 Address Error.");
508 out_lxb(i
,esp
->e_addr
,0);
511 outatxb(i
,esp
->e_addr
);
514 if ((i
== 1) && (!is_sdas() || !(is_sdas_target_8051_like() || is_sdas_target_stm8()))) {
515 r
|= R_BYTE
| R_BYTX
| esp
->e_rlcf
;
517 out_lb(hibyte(esp
->e_addr
),r
|R_RELOC
|R_HIGH
);
519 out_lb(lobyte(esp
->e_addr
),r
|R_RELOC
);
523 out_txb(a_bytes
, esp
->e_addr
);
525 n
= esp
->e_base
.e_sp
->s_ref
;
528 n
= esp
->e_base
.e_ap
->a_ref
;
531 *relp
++ = txtp
- txt
- a_bytes
;
535 /* sdas mcs51 specific */
536 /* We are generating a single byte of relocatable
539 * We generate a 24 bit address. The linker will
540 * select a single byte based on whether R_MSB or
544 r
|= R_BYTE
| R_BYT3
| esp
->e_rlcf
;
547 /* Probably should mark this differently in the
550 out_lb(thrdbyte(esp
->e_addr
),r
|R_RELOC
|R_HIGH
);
552 else if (r
& R_MSB
) {
553 out_lb(hibyte(esp
->e_addr
),r
|R_RELOC
|R_HIGH
);
555 out_lb(lobyte(esp
->e_addr
),r
|R_RELOC
);
559 out_txb(a_bytes
, esp
->e_addr
);
561 n
= esp
->e_base
.e_sp
->s_ref
;
564 n
= esp
->e_base
.e_ap
->a_ref
;
566 write_rmode(r
, txtp
- txt
- a_bytes
);
569 /* end sdas mcs51 specific */
574 * Update the Program Counter
577 dot
.s_addr
+= (i
/p_bytes
) + (i
% p_bytes
? 1 : 0);
580 /*)Function VOID outrw(esp, r)
582 * expr * esp pointer to expr structure
583 * int r relocation mode
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.
592 * int n symbol/area reference number
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
602 * VOID outchk() asout.c
603 * VOID out_lw() asout.c
604 * VOID out_rw() asout.c
605 * VOID out_txb() asout.c
608 * The current assembly address is incremented by 2.
612 outrw(struct expr
*esp
, int r
)
618 if (is_sdas() && is_sdas_target_8051_like() && esp
->e_addr
> 0xffff) {
621 "large constant 0x%x truncated to 16 bits\n",
624 /* end sdas specific */
625 if (esp
->e_flag
==0 && esp
->e_base
.e_ap
==NULL
) {
626 out_lxb(2,esp
->e_addr
,0);
629 out_txb(2,esp
->e_addr
);
632 r
|= R_WORD
| esp
->e_rlcf
;
636 out_lw(hibyte(esp
->e_addr
),r
|R_RELOC
);
638 out_lw(lobyte(esp
->e_addr
),r
|R_RELOC
);
641 out_lw(esp
->e_addr
,r
|R_RELOC
);
644 if (!is_sdas() || !(is_sdas_target_8051_like() || is_sdas_target_stm8())) {
646 out_txb(2, esp
->e_addr
);
648 n
= esp
->e_base
.e_sp
->s_ref
;
651 n
= esp
->e_base
.e_ap
->a_ref
;
654 *relp
++ = txtp
- txt
- 2;
658 out_txb(2, esp
->e_addr
);
660 n
= esp
->e_base
.e_sp
->s_ref
;
663 n
= esp
->e_base
.e_ap
->a_ref
;
668 /* If this happens, the linker will
669 * attempt to process this 16 bit field
670 * as 24 bits. That would be bad.
673 "***Internal error: C24 out in "
677 write_rmode(r
, txtp
- txt
- 2);
686 /*)Function VOID outr3b(esp, r)
688 * expr * esp pointer to expr structure
689 * int r relocation mode
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.
698 * int n symbol/area reference number
699 * int esprv merged value
700 * int p_bytes program counter update temporary
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
711 * VOID outchk() asout.c
712 * VOID out_lxb() asout.c
713 * VOID out_rw() asout.c
714 * VOID out_txb() asout.c
717 * R and T Lines updated. Listing updated.
718 * The current assembly address is incremented by i.
722 outr3b(struct expr
*esp
, int r
)
730 if (esp
->e_flag
==0 && esp
->e_base
.e_ap
==NULL
) {
731 /* This is a constant expression. */
738 /* This is a symbol. */
739 r
|= R_WORD
| esp
->e_rlcf
;
741 /* I have no idea what this case is. */
744 out_lw(hibyte(esprv
),r
|R_RELOC
);
746 out_lw(lobyte(esprv
),r
|R_RELOC
);
749 out_lxb(i
,esprv
,r
|R_RELOC
);
752 outchk(2*a_bytes
, 5);
753 out_txb(a_bytes
, esp
->e_addr
);
755 n
= esp
->e_base
.e_sp
->s_ref
;
758 n
= esp
->e_base
.e_ap
->a_ref
;
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.
770 "***Internal error: BYTE out in 24 "
771 "bit flat mode unexpected.\n");
775 write_rmode(r
| R_C24
, txtp
- txt
- a_bytes
);
782 * Update the Program Counter
785 dot
.s_addr
+= (i
/p_bytes
) + (i
% p_bytes
? 1 : 0);
789 /*)Function VOID outdp(carea, esp, r)
791 * area * carea pointer to current area structure
792 * expr * esp pointer to expr structure
793 * int r optional PAGX relocation coding
795 * The function outdp() flushes the output buffer and
796 * outputs paging information to the .REL file.
799 * int n symbol/area reference number
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
809 * VOID outbuf() asout.c
810 * VOID outchk() asout.c
811 * VOID out_rw() asout.c
812 * VOID out_txb() asout.c
815 * Output buffer flushed to .REL file.
816 * Paging information dumped to .REL file.
820 outdp(struct area
*carea
, struct expr
*esp
, int r
)
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
) {
832 fprintf(stderr
, "?ASxxxx-OUTDP-NULL-POINTER error.\n\n");
835 n
= esp
->e_base
.e_sp
->s_ref
;
838 n
= esp
->e_base
.e_ap
->a_ref
;
841 write_rmode(r
, txtp
- txt
- a_bytes
);
848 /*)Function VOID outall()
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).
858 * int oflag -o, generate relocatable output flag
859 * int pass assembler pass number
862 * VOID outbuf() asout.c
865 * assembled data and relocation buffers will be cleared.
871 if (oflag
&& pass
==2)
875 /*)Function VOID outdot()
877 * The function outdot() outputs information about the
878 * current program counter value (during pass 2 if the .REL
879 * output has been enabled).
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
893 * int fprintf() c_library
897 * assembled data and relocation buffers will be cleared.
903 if (oflag
&& pass
==2) {
905 out(txt
,(int) (txtp
-txt
));
908 out(rel
,(int) (relp
-rel
));
915 /*)Function outchk(nt, nr)
917 * int nr number of additional relocation words
918 * int nt number of additional data words
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.
926 * area * ap pointer to an area structure
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
937 * VOID outbuf() asout.c
938 * VOID out_rw() asout.c
939 * VOID out_txb() asout.c
942 * Data and relocation buffers may be emptied and initialized.
946 outchk(int nt
, int nr
)
950 if (txtp
+nt
> &txt
[NTXT
] || relp
+nr
> &rel
[NREL
]) {
954 out_txb(a_bytes
, dot
.s_addr
);
955 if ((ap
= dot
.s_area
) != NULL
) {
956 write_rmode(R_WORD
|R_AREA
, 0);
962 /*)Function VOID outbuf(s)
964 * char * s "R" or "P" or ("I" illegal)
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.
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
982 * int fprintf() c_library
986 * All bufferred data written to .REL file and
987 * buffer pointers and counters initialized.
993 if (txtp
> &txt
[a_bytes
]) {
995 out(txt
,(int) (txtp
-txt
));
997 fprintf(ofp
, "%s", s
);
998 out(rel
,(int) (relp
-rel
));
1015 fprintf(ofp
, "X%c%d\n", (int) hilo
? 'H' : 'L', a_bytes
);
1018 fprintf(ofp
, "Q%c%d\n", (int) hilo
? 'H' : 'L', a_bytes
);
1021 fprintf(ofp
, "D%c%d\n", (int) hilo
? 'H' : 'L', a_bytes
);
1025 /*)Function VOID outgsd()
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.
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
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
1059 * int fprintf() c_library
1060 * VOID outarea() asout.c
1061 * VOID outsym() asout.c
1064 * All symbols are given reference numbers, all symbol
1065 * and area information is output to the .REL file.
1075 int narea
, nglob
, rn
;
1080 narea
= areap
->a_ref
+ 1;
1083 * Number of global references/absolutes
1086 for (i
= 0; i
< NHASH
; ++i
) {
1089 if (sp
->s_flag
&S_GBL
)
1098 * Output number of areas and symbols
1101 fprintf(ofp
, "H %X areas %X global symbols\n", narea
, nglob
);
1104 fprintf(ofp
, "H %o areas %o global symbols\n", narea
, nglob
);
1107 fprintf(ofp
, "H %u areas %u global symbols\n", narea
, nglob
);
1116 fprintf(ofp
, "%s\n", ptr
);
1121 * Sdcc compile options
1123 if (is_sdas() && NULL
!= optsdcc
) fprintf(ofp
, "O %s\n", optsdcc
);
1124 /* end sdas specific */
1127 * Global references and absolutes.
1130 for (i
=0; i
<NHASH
; ++i
) {
1133 if (sp
->s_area
==NULL
&& sp
->s_flag
&S_GBL
) {
1142 * Global relocatables.
1144 for (i
=0; i
<narea
; ++i
) {
1146 while (ap
->a_ref
!= i
)
1149 for (j
=0; j
<NHASH
; ++j
) {
1152 if (sp
->s_area
==ap
&& sp
->s_flag
&S_GBL
) {
1162 /*)Function VOID outarea(ap)
1164 * area * ap pointer to an area structure
1166 * The function outarea() outputs the A line to the .REL
1167 * file. The A line contains the area's name, size,
1171 * char * frmt pointer to format string
1174 * FILE * ofp relocation output file handle
1175 * int xflag -x, listing radix flag
1178 * int fprintf() c_library
1181 * The A line is sent to the .REL file.
1185 outarea(struct area
*ap
)
1190 fprintf(ofp
, "%s", &ap
->a_id
[0]);
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;
1199 fprintf(ofp
, frmt
, ap
->a_size
, ap
->a_flag
);
1203 fprintf(ofp
, " addr %X", ap
->a_addr
);
1206 fprintf(ofp
, " addr %o", ap
->a_addr
);
1209 fprintf(ofp
, " addr %u", ap
->a_addr
);
1211 /* end sdas specific */
1216 /*)Function VOID outsym(sp)
1218 * sym * sp pointer to a sym structure
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.
1225 * char * frmt pointer to format string
1226 * int s_addr (int) truncated to 2-bytes
1229 * int a_bytes argument size in bytes
1230 * FILE * ofp relocation output file handle
1231 * int xflag -x, listing radix flag
1234 * int fprintf() c_library
1237 * The S line is sent to the .REL file.
1241 outsym(struct sym
*sp
)
1246 s_addr
= sp
->s_addr
;
1249 fprintf(ofp
, "%s", &sp
->s_id
[0]);
1250 fprintf(ofp
, " %s", sp
->s_type
==S_NEW
? "Ref" : "Def");
1258 case 2: frmt
= "%04lX\n"; break;
1259 case 3: frmt
= "%06lX\n"; break;
1260 case 4: frmt
= "%08lX\n"; break;
1267 case 2: frmt
= "%06lo\n"; break;
1268 case 3: frmt
= "%08lo\n"; break;
1269 case 4: frmt
= "%011lo\n"; break;
1276 case 2: frmt
= "%05lu\n"; break;
1277 case 3: frmt
= "%08lu\n"; break;
1278 case 4: frmt
= "%010lu\n"; break;
1288 case 2: frmt
= "%04X\n"; break;
1289 case 3: frmt
= "%06X\n"; break;
1290 case 4: frmt
= "%08X\n"; break;
1297 case 2: frmt
= "%06o\n"; break;
1298 case 3: frmt
= "%08o\n"; break;
1299 case 4: frmt
= "%011o\n"; break;
1306 case 2: frmt
= "%05u\n"; break;
1307 case 3: frmt
= "%08u\n"; break;
1308 case 4: frmt
= "%010u\n"; break;
1314 fprintf(ofp
, frmt
, s_addr
);
1317 /*)Function VOID out(p, n)
1319 * int n number of words to output
1320 * int * p pointer to data words
1322 * The function out() outputs the data words to the .REL file
1323 * in the specified radix.
1329 * FILE * ofp relocation output file handle
1330 * int xflag -x, listing radix flag
1333 * int fprintf() c_library
1336 * Data is sent to the .REL file.
1344 fprintf(ofp
, " %02X", (*p
++)&0377);
1347 fprintf(ofp
, " %03o", (*p
++)&0377);
1350 fprintf(ofp
, " %03u", (*p
++)&0377);
1355 /*)Function VOID out_lb(v, t)
1357 * a_uint v assembled data
1358 * int t relocation type
1360 * The function out_lb() copies the assembled data and
1361 * its relocation type to the list data buffers.
1367 * int * cp pointer to assembler output array cb[]
1368 * int * cpt pointer to assembler relocation type
1369 * output array cbt[]
1375 * Pointers to data and relocation buffers incremented by 1.
1379 out_lb(a_uint v
, int t
)
1381 if (cp
< &cb
[NCODE
]) {
1387 /*)Function VOID out_lw(v, t)
1388 *)Function VOID out_l3b(v, t)
1389 *)Function VOID out_l4b(v, t)
1391 * a_uint v assembled data
1392 * int t relocation type
1394 * Dispatch functions for processing listing data.
1406 * Listing data processed.
1410 out_lw(a_uint v
, int t
)
1416 out_l3b(a_uint v
, int t
)
1422 out_l4b(a_uint v
, int t
)
1427 /*)Function VOID out_lxb(i, v, t)
1429 * int i output byte count
1430 * a_uint v assembled data
1431 * int t relocation type
1433 * Dispatch function for list processing.
1439 * int hilo byte order
1442 * VOID out_lb() asout.c
1445 * i list bytes are processed.
1449 out_lxb(int i
, a_uint v
, int t
)
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
);
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);
1462 /*)Function VOID out_rw(v)
1464 * a_uint v assembled data
1466 * The function out_rw() outputs the relocation (R)
1467 * data word as two bytes ordered according to hilo.
1473 * int hilo byte order
1474 * char * relp Pointer to R Line Values
1477 * int lobyte() asout.c
1478 * int hibyte() asout.c
1481 * Pointer to relocation buffer incremented by 2.
1488 *relp
++ = hibyte(v
);
1489 *relp
++ = lobyte(v
);
1491 *relp
++ = lobyte(v
);
1492 *relp
++ = hibyte(v
);
1496 /*)Function VOID out_txb(i, v)
1498 * int i T Line byte count
1499 * a_uint v data word
1501 * The function out_txb() outputs the text (T)
1502 * data word as i bytes ordered according to hilo.
1507 * int hilo byte order
1508 * char * txtp Pointer to T Line Values
1511 * int lobyte() asout.c
1512 * int hibyte() asout.c
1513 * int thrdbyte() asout.c
1514 * int frthbyte() asout.c
1517 * T Line buffer updated.
1521 out_txb(int i
, a_uint v
)
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
);
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
);
1536 /*)Function int lobyte(v)
1537 *)Function int hibyte(v)
1538 *)Function int thrdbyte(v)
1539 *)Function int frthbyte(v)
1541 * a_uint v assembled data
1543 * These functions return the 1st, 2nd, 3rd, or 4th byte
1562 return ((int) (v
&0377));
1568 return ((int) ((v
>>8)&0377));
1574 return ((int) ((v
>>16)&0377));
1580 return ((int) ((v
>>24)&0377));
1584 * JLH: Output relocatable 11 bit jump/call
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.
1589 /*)Function VOID outrwm(esp, r, v)
1591 * expr * esp pointer to expr structure
1592 * int r relocation mode
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.
1604 * This function based on code by
1606 * jhartman@compuserve.com
1609 * int n symbol/area reference number
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
1619 * VOID outchk() asout.c
1620 * VOID out_lw() asout.c
1621 * VOID out_rw() asout.c
1622 * VOID out_txb() asout.c
1625 * The current assembly address is incremented by 2.
1628 outrwm(struct expr
*esp
, int r
, a_uint v
)
1633 if (!is_sdas() || !is_sdas_target_8051_like()) {
1634 if (esp
->e_flag
==0 && esp
->e_base
.e_ap
==NULL
) {
1636 * Absolute Destination
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.
1644 esp
->e_base
.e_sp
= &sym
[1];
1647 * Relocatable Destination. Build THREE
1648 * byte output: relocatable word, followed
1649 * by op-code. Linker will combine them.
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
);
1657 out_txb(2, esp
->e_addr
);
1661 n
= esp
->e_base
.e_sp
->s_ref
;
1664 n
= esp
->e_base
.e_ap
->a_ref
;
1667 *relp
++ = txtp
- txt
- 3;
1671 if (esp
->e_flag
==0 && esp
->e_base
.e_ap
==NULL
) {
1672 /* Absolute destination.
1673 * Listing shows only the address.
1675 out_lw(esp
->e_addr
,0);
1678 out_txb(2, esp
->e_addr
);
1681 write_rmode(r
, txtp
- txt
- 3);
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.
1690 r
|= R_WORD
| esp
->e_rlcf
;
1691 out_lw(esp
->e_addr
,r
|R_RELOC
);
1694 out_txb(2, esp
->e_addr
);
1698 n
= esp
->e_base
.e_sp
->s_ref
;
1701 n
= esp
->e_base
.e_ap
->a_ref
;
1703 write_rmode(r
, txtp
- txt
- 3);
1713 * Output relocatable 19 bit jump/call
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.
1719 outr3bm(struct expr
* esp
, int r
, a_uint v
)
1724 if (esp
->e_flag
==0 && esp
->e_base
.e_ap
==NULL
) {
1725 /* Absolute destination.
1726 * Listing shows only the address.
1728 out_lw(esp
->e_addr
,0);
1731 out_txb(3, esp
->e_addr
);
1734 write_rmode(r
, txtp
- txt
- 4);
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.
1743 r
|= R_WORD
| esp
->e_rlcf
;
1744 out_l3b(esp
->e_addr
,r
|R_RELOC
);
1747 out_txb(3, esp
->e_addr
);
1751 n
= esp
->e_base
.e_sp
->s_ref
;
1754 n
= esp
->e_base
.e_ap
->a_ref
;
1756 write_rmode(r
, txtp
- txt
- 4);
1765 * PDK: Output relocatable 11 bit goto/call
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.
1770 /*)Function VOID outrwp(esp, op, mask, jump)
1772 * expr * esp pointer to expr structure
1774 * a_uint mask address mask
1775 * int jump call/goto relocation data
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.
1785 * This function based on code by
1787 * jhartman@compuserve.com
1790 * int n symbol/area reference number
1791 * int r relocation information
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
1801 * VOID outchk() asout.c
1802 * VOID out_lw() asout.c
1803 * VOID out_rw() asout.c
1804 * VOID out_txb() asout.c
1807 * The current assembly address is incremented by 2.
1810 outrwp(struct expr
*esp
, a_uint op
, a_uint mask
, int jump
)
1815 if (esp
->e_flag
==0 && esp
->e_base
.e_ap
==NULL
) {
1817 * Absolute Destination
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.
1825 esp
->e_base
.e_sp
= &sym
[1];
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
1832 if (esp
->e_rlcf
& R_BYTX
) {
1834 /* We might select the MSB/LSB of an address in RAM. In
1835 * that case the linker should not convert the address
1838 if (!esp
->e_flag
&& !memcmp(esp
->e_base
.e_ap
->a_id
, "DATA", 4)) {
1845 /* Some (address) marker bits might have been shifted out of
1846 * range. Revert this and put them back where they belong.
1848 if (esp
->e_addr
& ~0xFFFF) {
1849 int marker
= esp
->e_addr
& 0x10000;
1850 esp
->e_addr
&= ~0x10000;
1851 esp
->e_addr
|= marker
>> 1;
1855 * Relocatable Destination. Build FOUR
1856 * byte output: relocatable word, followed
1857 * by op-code. Linker will combine them.
1860 n
= op
| (esp
->e_addr
& mask
);
1861 out_lw(n
,r
|R_RELOC
);
1864 out_txb(2, esp
->e_addr
);
1866 out_txb(1, (int)get_sdas_target());
1869 n
= esp
->e_base
.e_sp
->s_ref
;
1872 n
= esp
->e_base
.e_ap
->a_ref
;
1875 *relp
++ = txtp
- txt
- 5;