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