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