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