Initial revision
[fw/sdcc] / as / mcs51 / lkrloc.c
1 /* lkrloc.c */
2
3 /*
4  * (C) Copyright 1989-1995
5  * All Rights Reserved
6  *
7  * Alan R. Baldwin
8  * 721 Berkeley St.
9  * Kent, Ohio  44240
10  *
11  * 29-Oct-97 JLH:
12  *               - errdmp: show s_id as string rather than array [NCPS]
13  *               - relr: add support for 11 bit 8051 addressing
14  * 02-Apr-98 JLH: don't output empty hex records
15  */
16
17 #include <stdio.h>
18 #include <string.h>
19 #include <alloc.h>
20 #include "aslink.h"
21
22 /*)Module       lkrloc.c
23  *
24  *      The module lkrloc.c contains the functions which
25  *      perform the relocation calculations.
26  *
27  *      lkrloc.c contains the following functions:
28  *              addr_t  adb_b()
29  *              addr_t  adb_lo()
30  *              addr_t  adb_hi()
31  *              addr_t  adw_w()
32  *              addr_t  adw_lo()
33  *              addr_t  adw_hi()
34  *              VOID    erpdmp()
35  *              VOID    errdmp()
36  *              addr_t  evword()
37  *              VOID    prntval()
38  *              VOID    rele()
39  *              VOID    relerr()
40  *              VOID    relerp()
41  *              VOID    reloc()
42  *              VOID    relp()
43  *              VOID    relr()
44  *              VOID    relt()
45  *
46  *      lkrloc.c the local variable errmsg[].
47  *
48  */
49
50 /*)Function     VOID    reloc(c)
51  *
52  *                      char c          process code
53  *
54  *      The function reloc() calls a particular relocation
55  *      function determined by the process code.
56  *
57  *      local variable:
58  *              none
59  *
60  *      global variables:
61  *              int     lkerr           error flag
62  *
63  *      called functions:
64  *              int     fprintf()       c_library
65  *              VOID    rele()          lkrloc.c
66  *              VOID    relp()          lkrloc.c
67  *              VOID    relr()          lkrloc.c
68  *              VOId    relt()          lkrloc.c
69  *
70  *      side effects:
71  *              Refer to the called relocation functions.
72  *
73  */
74
75 VOID
76 reloc(c)
77 char c;
78 {
79         switch(c) {
80
81         case 'T':
82                 relt();
83                 break;
84
85         case 'R':
86                 relr();
87                 break;
88
89         case 'P':
90                 relp();
91                 break;
92
93         case 'E':
94                 rele();
95                 break;
96
97         default:
98                 fprintf(stderr, "Undefined Relocation Operation\n");
99                 lkerr++;
100                 break;
101
102         }
103 }
104
105
106 /*)Function     VOID    relt()
107  *
108  *      The function relt() evaluates a T line read by
109  *      the linker. Each byte value read is saved in the
110  *      rtval[] array, rtflg[] is set, and the number of
111  *      evaluations is maintained in rtcnt.
112  *
113  *              T Line
114  *
115  *              T xx xx nn nn nn nn nn ...
116  *
117  *
118  *              In:     "T n0 n1 n2 n3 ... nn"
119  *
120  *              Out:     0   1    2        ..  rtcnt
121  *                        +----+----+----+----+----+
122  *              rtval | n0 | n1 | n2 | .. | nn |
123  *                    +----+----+----+----+----+
124  *              rtflag|  1 |  1 |  1 |  1 |  1 |
125  *            +----+----+----+----+----+
126  *
127  *      The T line contains the assembled code output by the assem-
128  *      bler with xx xx being the offset address from the current area
129  *      base address and nn being the assembled instructions and data in
130  *      byte format.
131  *
132  *      local variable:
133  *              none
134  *
135  *      global variables:
136  *              int     rtcnt           number of values evaluated
137  *              int     rtflg[]         array of evaluation flags
138  *              int     rtval[]         array of evaluation values
139  *
140  *      called functions:
141  *              int     eval()          lkeval.c
142  *              int     more()          lklex.c
143  *
144  *      side effects:
145  *              Linker input T line evaluated.
146  *
147  */
148
149 VOID
150 relt()
151 {
152         rtcnt = 0;
153         while (more()) {
154                 if (rtcnt < NTXT) {
155                         rtval[rtcnt] = eval();
156                         rtflg[rtcnt] = 1;
157                         rtcnt++;
158                 }
159         }
160 }
161
162 /*)Function     VOID    relr()
163  *
164  *      The function relr() evaluates a R line read by
165  *      the linker.  The R line data is combined with the
166  *      previous T line data to perform the relocation of
167  *      code and data bytes.  The S19 / IHX output and
168  *      translation of the LST files to RST files may be
169  *      performed.
170  *
171  *              R Line
172  *
173  *              R 0 0 nn nn n1 n2 xx xx ...
174  *
175  *              The R line provides the relocation information to the linker.
176  *      The nn nn value is the current area index, i.e.  which area  the
177  *      current  values  were  assembled.  Relocation information is en-
178  *      coded in groups of 4 bytes:
179  *
180  *      1.      n1 is the relocation mode and object format
181  *                      1.      bit 0 word(0x00)/byte(0x01)
182  *                      2.      bit 1 relocatable area(0x00)/symbol(0x02)
183  *                      3.      bit 2 normal(0x00)/PC relative(0x04) relocation
184  *                      4.      bit  3  1-byte(0x00)/2-byte(0x08) object format for
185  *                      byte data
186  *                      5.      bit 4 signed(0x00)/unsigned(0x10) byte data
187  *                      6.      bit 5 normal(0x00)/page '0'(0x20) reference
188  *                      7.      bit 6 normal(0x00)/page 'nnn'(0x40) reference
189  *
190  *      2.      n2      is      a byte index into the corresponding (i.e.  pre-
191  *                      ceeding) T line data (i.e.      a pointer to the data to be
192  *                      updated  by  the  relocation).   The T line data may be
193  *                      1-byte or  2-byte  byte  data  format  or  2-byte  word
194  *                      format.
195  *
196  *      3.      xx xx  is the area/symbol index for the area/symbol be-
197  *                      ing referenced.  the corresponding area/symbol is found
198  *              in the header area/symbol lists.
199  *
200  *      The groups of 4 bytes are repeated for each item requiring relo-
201  *      cation in the preceeding T line.
202  *
203  *      local variable:
204  *              areax   **a             pointer to array of area pointers
205  *              int     aindex          area index
206  *              char    *errmsg[]       array of pointers to error strings
207  *              int     error           error code
208  *              int     lkerr           error flag
209  *              int     mode            relocation mode
210  *              adrr_t  paga            paging base area address
211  *              addr_t  pags            paging symbol address
212  *              addr_t  pc              relocated base address
213  *              addr_t  r               PCR relocation value
214  *              addr_t  reli            relocation initial value
215  *              addr_t  relv            relocation final value
216  *              int     rindex          symbol / area index
217  *              addr_t  rtbase          base code address
218  *              addr_t  rtofst          rtval[] index offset
219  *              int     rtp             index into T data
220  *              sym     **s             pointer to array of symbol pointers
221  *
222  *      global variables:
223  *              head    *hp             pointer to the head structure
224  *              rerr    rerr            linker error structure
225  *              FILE    *stderr         standard error device
226  *
227  *      called functions:
228  *              addr_t  adb_b()         lkrloc.c
229  *              addr_t  adb_lo()        lkrloc.c
230  *              addr_t  adb_hi()        lkrloc.c
231  *              addr_t  adw_w()         lkrloc.c
232  *              addr_t  evword()        lkrloc.c
233  *              int     eval()          lkeval.c
234  *              int     fprintf()       c_library
235  *              VOID    ihx()           lkihx.c
236  *              int     lkulist         lklist.c
237  *              int     more()          lklex.c
238  *              VOID    relerr()        lkrloc.c
239  *              VOID    s19()           lks19.c
240  *              int     symval()        lksym.c
241  *
242  *      side effects:
243  *              The R and T lines are combined to produce
244  *              relocated code and data.  Output S19 / IHX
245  *              and relocated listing files may be produced.
246  *
247  */
248
249 VOID
250 relr()
251 {
252         register int mode;
253         register addr_t reli, relv;
254         int aindex, rindex, rtp, error;
255         addr_t r, rtbase, rtofst, paga, pags, pc;
256         struct areax **a;
257         struct sym **s;
258
259         /*
260          * Get area and symbol lists
261          */
262         a = hp->a_list;
263         s = hp->s_list;
264
265         /*
266          * Verify Area Mode
267          */
268         if (eval() != (R_WORD | R_AREA) || eval()) {
269                 fprintf(stderr, "R input error\n");
270                 lkerr++;
271         }
272
273         /*
274          * Get area pointer
275          */
276         aindex = evword();
277         if (aindex >= hp->h_narea) {
278                 fprintf(stderr, "R area error\n");
279                 lkerr++;
280                 return;
281         }
282
283         /*
284          * Base values
285          */
286         rtbase = adw_w(0, 0);
287         rtofst = 2;
288
289         /*
290          * Relocate address
291          */
292         pc = adw_w(a[aindex]->a_addr, 0);
293
294         /*
295          * Do remaining relocations
296          */
297         while (more()) {
298                 error = 0;
299                 mode = eval();
300                 rtp = eval();
301                 rindex = evword();
302
303                 /*
304                  * R_SYM or R_AREA references
305                  */
306                 if (mode & R_SYM) {
307                         if (rindex >= hp->h_nglob) {
308                                 fprintf(stderr, "R symbol error\n");
309                                 lkerr++;
310                                 return;
311                         }
312                         reli = symval(s[rindex]);
313                 } else {
314                         if (rindex >= hp->h_narea) {
315                                 fprintf(stderr, "R area error\n");
316                                 lkerr++;
317                                 return;
318                         }
319                         reli = a[rindex]->a_addr;
320                 }
321
322                 /*
323                  * R_PCR addressing
324                  */
325                 if (mode & R_PCR) {
326                         if (mode & R_BYTE) {
327                                 reli -= (pc + (rtp-rtofst) + 1);
328                         } else {
329                                 reli -= (pc + (rtp-rtofst) + 2);
330                         }
331                 }
332
333                 /*
334                  * R_PAG0 or R_PAG addressing
335                  */
336                 if (mode & (R_PAG0|R_PAG)) {
337                         paga  = sdp.s_area->a_addr;
338                         pags  = sdp.s_addr;
339                         reli -= paga + pags;
340                 }
341
342                 /*
343                  * R_BYTE or R_WORD operation
344                  */
345                 if (mode & R_BYTE) {
346                         if (mode & R_BYT2) {
347                                 if (mode & R_MSB) {
348                                         relv = adb_hi(reli, rtp);
349                                 } else {
350                                         relv = adb_lo(reli, rtp);
351                                 }
352                         } else {
353                                 relv = adb_b(reli, rtp);
354                         }
355                 } else if (mode & R_J11) {
356                         /* JLH: 11 bit jump destination for 8051.  Forms
357                         /  two byte instruction with op-code bits
358                         /  in the MIDDLE!
359                         /  rtp points at 3 byte locus: first two
360                         /  will get the instructiion. third one
361                         /  has raw op-code.
362                         */
363         
364                         /* Calculate absolute destination
365                         /  relv must be on same 2K page as pc
366                         */
367                         relv = adw_w(reli, rtp);
368
369             if ((relv & ~0x7ff) != ((pc + rtp - rtofst) & ~0x7ff)) {
370                     error = 2;
371             }
372
373             /* Merge MSB (byte 0) with op-code, ignoring
374             /  top 5 bits of address.  Then hide the op-code
375             */
376             rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+2];
377             rtflg[rtp+2] = 0;
378                         rtofst += 1;
379                 } else {
380                         /*
381                          * R_WORD with the R_BYT2 mode is flagged
382                          * as an 'r' error by the assembler,
383                          * but it is processed here anyway.
384                          */
385 #if 0
386                     /* JLH: R_WORD and R_BYT2 together is now subsumed by R_J11 */
387                         if (mode & R_BYT2) {
388         
389                                 if (mode & R_MSB) {
390                                         relv = adw_hi(reli, rtp);
391                                 } else {
392                                         relv = adw_lo(reli, rtp);
393                                 }
394                         } else {
395                                 relv = adw_w(reli, rtp);
396                         }
397 #else
398                         relv = adw_w(reli, rtp);
399 #endif
400                 }
401
402                 /*
403                  * R_BYTE with R_BYT2 offset adjust
404                  */
405                 if (mode & R_BYTE) {
406                         if (mode & R_BYT2) {
407                                 rtofst += 1;
408                         }
409                 }
410
411                 /*
412                  * Unsigned Byte Checking
413                  */
414                 if (mode & R_USGN && mode & R_BYTE && relv & ~0xFF)
415                         error = 1;
416
417                 /*
418                  * PCR Relocation Error Checking
419                  */
420                 if (mode & R_PCR && mode & R_BYTE) {
421                         r = relv & ~0x7F;
422                         if (r != (addr_t) ~0x7F && r != 0)
423                                 error = 2; 
424                 }
425
426                 /*
427                  * Page Relocation Error Checking
428                  */
429                 /* if (mode & R_PAG0 && (relv & ~0xFF || paga || pags))
430                         error = 3;*/
431                 if (mode & R_PAG  && (relv & ~0xFF))
432                         error = 4;
433
434                 /*
435                  * Error Processing
436                  */
437                 if (error) {
438                         rerr.aindex = aindex;
439                         rerr.mode = mode;
440                         rerr.rtbase = rtbase + rtp - rtofst - 1;
441                         rerr.rindex = rindex;
442                         rerr.rval = relv - reli;
443                         relerr(errmsg[error-1]);
444                 }
445         }
446         if (uflag != 0) {
447                 lkulist(1);
448         }
449
450         /* JLH: output only if data (beyond two byte address) */
451         if ((oflag == 1) && (rtcnt > 2)) {
452                 ihx(1);
453         } else
454         if ((oflag == 2) && (rtcnt > 2)) {
455                 s19(1);
456         }
457 }
458
459 char *errmsg[] = {
460         "Unsigned Byte error",
461         "Byte PCR relocation error",
462         "Page0 relocation error",
463         "Page Mode relocation error"
464 };
465
466
467 /*)Function     VOID    relp()
468  *
469  *      The function relp() evaluates a P line read by
470  *      the linker.  The P line data is combined with the
471  *      previous T line data to set the base page address
472  *      and test the paging boundary and length.
473  *
474  *              P Line
475  *
476  *              P 0 0 nn nn n1 n2 xx xx
477  *
478  *      The P line provides the paging information to the linker as
479  *      specified by a .setdp directive.  The format of the relocation
480  *      information is identical to that of the R line.  The correspond-
481  *      ing T line has the following information:
482  *              T xx xx aa aa bb bb
483  *
484  *      Where aa aa is the area reference number which specifies the
485  *      selected page area and bb bb is the base address of the page.
486  *      bb bb will require relocation processing if the 'n1 n2 xx xx' is
487  *      specified in the P line.  The linker will verify that the base
488  *      address is on a 256 byte boundary and that the page length of an
489  *      area defined with the PAG type is not larger than 256 bytes.
490  *
491  *      local variable:
492  *              areax   **a             pointer to array of area pointers
493  *              int     aindex          area index
494  *              int     mode            relocation mode
495  *              addr_t  relv    relocation value
496  *              int     rindex          symbol / area index
497  *              int     rtp                     index into T data
498  *              sym     **s                     pointer to array of symbol pointers
499  *
500  *      global variables:
501  *              head *hp                pointer to the head structure
502  *              int     lkerr           error flag
503  *              sdp     sdp                     base page structure
504  *              FILE *stderr    standard error device
505  *
506  *      called functions:
507  *              addr_t adw_w()  lkrloc.c
508  *              addr_t evword() lkrloc.c
509  *              int     eval()          lkeval.c
510  *              int     fprintf()       c_library
511  *              int     more()          lklex.c
512  *              int     symval()        lksym.c
513  *
514  *      side effects:
515  *              The P and T lines are combined to set
516  *              the base page address and report any
517  *              paging errors.
518  *
519  */
520
521 VOID
522 relp()
523 {
524         register int aindex, rindex;
525         int mode, rtp;
526         addr_t relv;
527         struct areax **a;
528         struct sym **s;
529
530         /*
531          * Get area and symbol lists
532          */
533         a = hp->a_list;
534         s = hp->s_list;
535
536         /*
537          * Verify Area Mode
538          */
539         if (eval() != (R_WORD | R_AREA) || eval()) {
540                 fprintf(stderr, "P input error\n");
541                 lkerr++;
542         }
543
544         /*
545          * Get area pointer
546          */
547         aindex = evword();
548         if (aindex >= hp->h_narea) {
549                 fprintf(stderr, "P area error\n");
550                 lkerr++;
551                 return;
552         }
553
554         /*
555          * Do remaining relocations
556          */
557         while (more()) {
558                 mode = eval();
559                 rtp = eval();
560                 rindex = evword();
561
562                 /*
563                  * R_SYM or R_AREA references
564                  */
565                 if (mode & R_SYM) {
566                         if (rindex >= hp->h_nglob) {
567                                 fprintf(stderr, "P symbol error\n");
568                                 lkerr++;
569                                 return;
570                         }
571                         relv = symval(s[rindex]);
572                 } else {
573                         if (rindex >= hp->h_narea) {
574                                 fprintf(stderr, "P area error\n");
575                                 lkerr++;
576                                 return;
577                         }
578                         relv = a[rindex]->a_addr;
579                 }
580                 adw_w(relv, rtp);
581         }
582
583         /*
584          * Paged values
585          */
586         aindex = adw_w(0,2);
587         if (aindex >= hp->h_narea) {
588                 fprintf(stderr, "P area error\n");
589                 lkerr++;
590                 return;
591         }
592         sdp.s_areax = a[aindex];
593         sdp.s_area = sdp.s_areax->a_bap;
594         sdp.s_addr = adw_w(0,4);
595         if (sdp.s_area->a_addr & 0xFF || sdp.s_addr & 0xFF)
596                 relerp("Page Definition Boundary Error");
597 }
598
599 /*)Function     VOID    rele()
600  *
601  *      The function rele() closes all open output files
602  *      at the end of the linking process.
603  *
604  *      local variable:
605  *              none
606  *
607  *      global variables:
608  *              int     oflag           output type flag
609  *              int     uflag           relocation listing flag
610  *
611  *      called functions:
612  *              VOID    ihx()           lkihx.c
613  *              VOID    lkulist()       lklist.c
614  *              VOID    s19()           lks19.c
615  *
616  *      side effects:
617  *              All open output files are closed.
618  *
619  */
620
621 VOID
622 rele()
623 {
624         if (uflag != 0) {
625                 lkulist(0);
626         }
627         if (oflag == 1) {
628                 ihx(0);
629         } else
630         if (oflag == 2) {
631                 s19(0);
632         }
633 }
634
635 /*)Function     addr_t          evword()
636  *
637  *      The function evword() combines two byte values
638  *      into a single word value.
639  *
640  *      local variable:
641  *              addr_t  v               temporary evaluation variable
642  *
643  *      global variables:
644  *              hilo                    byte ordering parameter
645  *
646  *      called functions:
647  *              int     eval()          lkeval.c
648  *
649  *      side effects:
650  *              Relocation text line is scanned to combine
651  *              two byte values into a single word value.
652  *
653  */
654
655 addr_t
656 evword()
657 {
658         register addr_t v;
659
660         if (hilo) {
661                 v =  (eval() << 8);
662                 v +=  eval();
663         } else {
664                 v =   eval();
665                 v += (eval() << 8);
666         }
667         return(v);
668 }
669
670 /*)Function     addr_t          adb_b(v, i)
671  *
672  *              int     v               value to add to byte
673  *              int     i               rtval[] index
674  *
675  *      The function adb_b() adds the value of v to
676  *      the single byte value contained in rtval[i].
677  *      The new value of rtval[i] is returned.
678  *
679  *      local variable:
680  *              none
681  *
682  *      global variables:
683  *              none
684  *
685  *      called functions:
686  *              none
687  *
688  *      side effects:
689  *              The value of rtval[] is changed.
690  *
691  */
692
693 addr_t
694 adb_b(v, i)
695 register addr_t v;
696 register int i;
697 {
698         return(rtval[i] += v);
699 }
700
701 /*)Function     addr_t          adb_lo(v, i)
702  *
703  *              int     v               value to add to byte
704  *              int     i               rtval[] index
705  *
706  *      The function adb_lo() adds the value of v to the
707  *      double byte value contained in rtval[i] and rtval[i+1].
708  *      The new value of rtval[i] / rtval[i+1] is returned.
709  *      The MSB rtflg[] is cleared.
710  *
711  *      local variable:
712  *              addr_t  j               temporary evaluation variable
713  *
714  *      global variables:
715  *              hilo                    byte ordering parameter
716  *
717  *      called functions:
718  *              none
719  *
720  *      side effects:
721  *              The value of rtval[] is changed.
722  *              The rtflg[] value corresponding to the
723  *              MSB of the word value is cleared to reflect
724  *              the fact that the LSB is the selected byte.
725  *
726  */
727
728 addr_t
729 adb_lo(v, i)
730 addr_t  v;
731 int     i;
732 {
733         register addr_t j;
734
735         j = adw_w(v, i);
736         /*
737          * Remove Hi byte
738          */
739         if (hilo) {
740                 rtflg[i] = 0;
741         } else {
742                 rtflg[i+1] = 0;
743         }
744         return (j);
745 }
746
747 /*)Function     addr_t          adb_hi(v, i)
748  *
749  *              int     v               value to add to byte
750  *              int     i               rtval[] index
751  *
752  *      The function adb_hi() adds the value of v to the
753  *      double byte value contained in rtval[i] and rtval[i+1].
754  *      The new value of rtval[i] / rtval[i+1] is returned.
755  *      The LSB rtflg[] is cleared.
756  *
757  *      local variable:
758  *              addr_t  j               temporary evaluation variable
759  *
760  *      global variables:
761  *              hilo                    byte ordering parameter
762  *
763  *      called functions:
764  *              none
765  *
766  *      side effects:
767  *              The value of rtval[] is changed.
768  *              The rtflg[] value corresponding to the
769  *              LSB of the word value is cleared to reflect
770  *              the fact that the MSB is the selected byte.
771  *
772  */
773
774 addr_t
775 adb_hi(v, i)
776 addr_t  v;
777 int     i;
778 {
779         register addr_t j;
780
781         j = adw_w(v, i);
782         /*
783          * Remove Lo byte
784          */
785         if (hilo) {
786                 rtflg[i+1] = 0;
787         } else {
788                 rtflg[i] = 0;
789         }
790         return (j);
791 }
792
793 /*)Function     addr_t          adw_w(v, i)
794  *
795  *              int     v               value to add to word
796  *              int     i               rtval[] index
797  *
798  *      The function adw_w() adds the value of v to the
799  *      word value contained in rtval[i] and rtval[i+1].
800  *      The new value of rtval[i] / rtval[i+1] is returned.
801  *
802  *      local variable:
803  *              addr_t  j               temporary evaluation variable
804  *
805  *      global variables:
806  *              hilo                    byte ordering parameter
807  *
808  *      called functions:
809  *              none
810  *
811  *      side effects:
812  *              The word value of rtval[] is changed.
813  *
814  */
815
816 addr_t
817 adw_w(v, i)
818 register addr_t v;
819 register int i;
820 {
821         register addr_t j;
822
823         if (hilo) {
824                 j = v + (rtval[i] << 8) + (rtval[i+1] & 0xff);
825                 rtval[i] = (j >> 8) & 0xff;
826                 rtval[i+1] = j & 0xff;
827         } else {
828                 j = v + (rtval[i] & 0xff) + (rtval[i+1] << 8);
829                 rtval[i] = j & 0xff;
830                 rtval[i+1] = (j >> 8) & 0xff;
831         }
832         return(j);
833 }
834
835 /*)Function     addr_t          adw_lo(v, i)
836  *
837  *              int     v               value to add to byte
838  *              int     i               rtval[] index
839  *
840  *      The function adw_lo() adds the value of v to the
841  *      double byte value contained in rtval[i] and rtval[i+1].
842  *      The new value of rtval[i] / rtval[i+1] is returned.
843  *      The MSB rtval[] is zeroed.
844  *
845  *      local variable:
846  *              addr_t  j               temporary evaluation variable
847  *
848  *      global variables:
849  *              hilo                    byte ordering parameter
850  *
851  *      called functions:
852  *              none
853  *
854  *      side effects:
855  *              The value of rtval[] is changed.
856  *              The MSB of the word value is cleared to reflect
857  *              the fact that the LSB is the selected byte.
858  *
859  */
860
861 addr_t
862 adw_lo(v, i)
863 addr_t  v;
864 int     i;
865 {
866         register addr_t j;
867
868         j = adw_w(v, i);
869         /*
870          * Clear Hi byte
871          */
872         if (hilo) {
873                 rtval[i] = 0;
874         } else {
875                 rtval[i+1] = 0;
876         }
877         return (j);
878 }
879
880 /*)Function     addr_t          adw_hi(v, i)
881  *
882  *              int     v               value to add to byte
883  *              int     i               rtval[] index
884  *
885  *      The function adw_hi() adds the value of v to the
886  *      double byte value contained in rtval[i] and rtval[i+1].
887  *      The new value of rtval[i] / rtval[i+1] is returned.
888  *      The MSB and LSB values are interchanged.
889  *      The MSB rtval[] is zeroed.
890  *
891  *      local variable:
892  *              addr_t  j               temporary evaluation variable
893  *
894  *      global variables:
895  *              hilo                    byte ordering parameter
896  *
897  *      called functions:
898  *              none
899  *
900  *      side effects:
901  *              The value of rtval[] is changed.
902  *              The MSB and LSB values are interchanged and
903  *              then the MSB cleared.
904  *
905  */
906
907 addr_t
908 adw_hi(v, i)
909 addr_t  v;
910 int     i;
911 {
912         register addr_t j;
913
914         j = adw_w(v, i);
915         /*
916          * LSB = MSB, Clear MSB
917          */
918         if (hilo) {
919                 rtval[i+1] = rtval[i];
920                 rtval[i] = 0;
921         } else {
922                 rtval[i] = rtval[i+1];
923                 rtval[i+1] = 0;
924         }
925         return (j);
926 }
927
928 /*)Function     VOID    relerr(str)
929  *
930  *              char    *str            error string
931  *
932  *      The function relerr() outputs the error string to
933  *      stderr and to the map file (if it is open).
934  *
935  *      local variable:
936  *              none
937  *
938  *      global variables:
939  *              FILE    *mfp            handle for the map file
940  *
941  *      called functions:
942  *              VOID    errdmp()        lkrloc.c
943  *
944  *      side effects:
945  *              Error message inserted into map file.
946  *
947  */
948
949 VOID
950 relerr(str)
951 char *str;
952 {
953         errdmp(stderr, str);
954         if (mfp)
955                 errdmp(mfp, str);
956 }
957
958 /*)Function     VOID    errdmp(fptr, str)
959  *
960  *              FILE    *fptr           output file handle
961  *              char    *str            error string
962  *
963  *      The function errdmp() outputs the error string str
964  *      to the device specified by fptr.  Additional information
965  *      is output about the definition and referencing of
966  *      the symbol / area error.
967  *
968  *      local variable:
969  *              int     mode            error mode
970  *              int     aindex          area index
971  *              int     lkerr           error flag
972  *              int     rindex          error index
973  *              sym     **s             pointer to array of symbol pointers
974  *              areax   **a             pointer to array of area pointers
975  *              areax   *raxp           error area extension pointer
976  *
977  *      global variables:
978  *              sdp     sdp             base page structure
979  *
980  *      called functions:
981  *              int     fprintf()       c_library
982  *              VOID    prntval()       lkrloc.c
983  *
984  *      side effects:
985  *              Error reported.
986  *
987  */
988
989 VOID
990 errdmp(fptr, str)
991 FILE *fptr;
992 char *str;
993 {
994         int mode, aindex, rindex;
995         struct sym **s;
996         struct areax **a;
997         struct areax *raxp;
998
999         a = hp->a_list;
1000         s = hp->s_list;
1001
1002         mode = rerr.mode;
1003         aindex = rerr.aindex;
1004         rindex = rerr.rindex;
1005
1006         /*
1007          * Print Error
1008          */
1009         fprintf(fptr, "\n?ASlink-Warning-%s", str);
1010         lkerr++;
1011
1012         /*
1013          * Print symbol if symbol based
1014          */
1015         if (mode & R_SYM) {
1016                 fprintf(fptr, " for symbol %s\n",
1017                         &s[rindex]->s_id[0]);
1018         } else {
1019                 fprintf(fptr, "\n");
1020         }
1021
1022         /*
1023          * Print Ref Info
1024          */
1025         fprintf(fptr,
1026                 "         file        module      area        offset\n");
1027         fprintf(fptr,
1028                 "  Refby  %-8.8s    %-8.8s    %-8.8s    ",
1029                         hp->h_lfile->f_idp,
1030                         &hp->m_id[0],
1031                         &a[aindex]->a_bap->a_id[0]);
1032         prntval(fptr, rerr.rtbase);
1033
1034         /*
1035          * Print Def Info
1036          */
1037         if (mode & R_SYM) {
1038                 raxp = s[rindex]->s_axp;
1039         } else {
1040                 raxp = a[rindex];
1041         }
1042         fprintf(fptr,
1043                 "  Defin  %-8.8s    %-8.8s    %-8.8s    ",
1044                         raxp->a_bhp->h_lfile->f_idp,
1045                         &raxp->a_bhp->m_id[0],
1046                         &raxp->a_bap->a_id[0]);
1047         if (mode & R_SYM) {
1048                 prntval(fptr, s[rindex]->s_addr);
1049         } else {
1050                 prntval(fptr, rerr.rval);
1051         }
1052 }
1053
1054 /*)Function     VOID prntval(fptr, v)
1055  *
1056  *              FILE    *fptr   output file handle
1057  *              addr_t  v               value to output
1058  *
1059  *      The function prntval() outputs the value v, in the
1060  *      currently selected radix, to the device specified
1061  *      by fptr.
1062  *
1063  *      local variable:
1064  *              none
1065  *
1066  *      global variables:
1067  *              int     xflag           current radix
1068  *
1069  *      called functions:
1070  *              int     fprintf()       c_library
1071  *
1072  *      side effects:
1073  *              none
1074  *
1075  */
1076
1077 VOID
1078 prntval(fptr, v)
1079 FILE *fptr;
1080 addr_t v;
1081 {
1082         if (xflag == 0) {
1083                 fprintf(fptr, "%04X\n", v);
1084         } else
1085         if (xflag == 1) {
1086                 fprintf(fptr, "%06o\n", v);
1087         } else
1088         if (xflag == 2) {
1089                 fprintf(fptr, "%05u\n", v);
1090         }
1091 }
1092
1093 /*)Function     VOID    relerp(str)
1094  *
1095  *              char    *str            error string
1096  *
1097  *      The function relerp() outputs the paging error string to
1098  *      stderr and to the map file (if it is open).
1099  *
1100  *      local variable:
1101  *              none
1102  *
1103  *      global variables:
1104  *              FILE    *mfp            handle for the map file
1105  *
1106  *      called functions:
1107  *              VOID    erpdmp()        lkrloc.c
1108  *
1109  *      side effects:
1110  *              Error message inserted into map file.
1111  *
1112  */
1113
1114 VOID
1115 relerp(str)
1116 char *str;
1117 {
1118         erpdmp(stderr, str);
1119         if (mfp)
1120                 erpdmp(mfp, str);
1121 }
1122
1123 /*)Function     VOID    erpdmp(fptr, str)
1124  *
1125  *              FILE    *fptr           output file handle
1126  *              char    *str            error string
1127  *
1128  *      The function erpdmp() outputs the error string str
1129  *      to the device specified by fptr.
1130  *
1131  *      local variable:
1132  *              head    *thp            pointer to head structure
1133  *
1134  *      global variables:
1135  *              int             lkerr           error flag
1136  *              sdp             sdp                     base page structure
1137  *
1138  *      called functions:
1139  *              int     fprintf()               c_library
1140  *              VOID    prntval()       lkrloc.c
1141  *
1142  *      side effects:
1143  *              Error reported.
1144  *
1145  */
1146
1147 VOID
1148 erpdmp(fptr, str)
1149 FILE *fptr;
1150 char *str;
1151 {
1152         register struct head *thp;
1153
1154         thp = sdp.s_areax->a_bhp;
1155
1156         /*
1157          * Print Error
1158          */
1159         fprintf(fptr, "\n?ASlink-Warning-%s\n", str);
1160         lkerr++;
1161
1162         /*
1163          * Print PgDef Info
1164          */
1165         fprintf(fptr,
1166                 "         file        module      pgarea      pgoffset\n");
1167         fprintf(fptr,
1168                 "  PgDef  %-8.8s    %-8.8s    %-8.8s    ",
1169                         thp->h_lfile->f_idp,
1170                         &thp->m_id[0],
1171                         &sdp.s_area->a_id[0]);
1172         prntval(fptr, sdp.s_area->a_addr + sdp.s_addr);
1173 }