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