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