* asranlib/asranlib.c, link/lkar.h, link/lkar.c:
[fw/sdcc] / as / link / hc08 / 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  * 29-Oct-97 JLH:
21  *               - errdmp: show s_id as string rather than array [NCPS]
22  *               - relr: add support for 11 bit 8051 addressing
23  * 02-Apr-98 JLH: don't output empty hex records
24  */
25
26 #include <stdio.h>
27 #include <string.h>
28 #include "aslink.h"
29
30 /*)Module       lkrloc.c
31  *
32  *      The module lkrloc.c contains the functions which
33  *      perform the relocation calculations.
34  *
35  *      lkrloc.c contains the following functions:
36  *              Addr_T  adb_b()
37  *              Addr_T  adb_lo()
38  *              Addr_T  adb_hi()
39  *              Addr_T  adw_w()
40  *              Addr_T  adw_lo()
41  *              Addr_T  adw_hi()
42  *              VOID    erpdmp()
43  *              VOID    errdmp()
44  *              Addr_T  evword()
45  *              VOID    prntval()
46  *              VOID    rele()
47  *              VOID    relerr()
48  *              VOID    relerp()
49  *              VOID    reloc()
50  *              VOID    relp()
51  *              VOID    relr()
52  *              VOID    relt()
53  *
54  *      lkrloc.c the local variable errmsg[].
55  *
56  */
57
58 /* Global which holds the upper 16 bits of the last 32 bit area adress
59  * output. Useful only for iHex mode.
60  */
61 int    lastExtendedAddress=-1;
62
63 /* Static variable which holds the index of last processed area.
64  * Useful only for iHex mode.
65  */
66 static int lastAreaIndex = -1;
67
68 /*)Function     VOID    reloc(c)
69  *
70  *                      char c          process code
71  *
72  *      The function reloc() calls a particular relocation
73  *      function determined by the process code.
74  *
75  *      local variable:
76  *              none
77  *
78  *      global variables:
79  *              int     lkerr           error flag
80  *
81  *      called functions:
82  *              int     fprintf()       c_library
83  *              VOID    rele()          lkrloc.c
84  *              VOID    relp()          lkrloc.c
85  *              VOID    relr()          lkrloc.c
86  *              VOId    relt()          lkrloc.c
87  *
88  *      side effects:
89  *              Refer to the called relocation functions.
90  *
91  */
92
93 VOID reloc(char c)
94 {
95         switch(c) {
96
97         case 'T':
98                 relt();
99                 break;
100
101         case 'R':
102                 relr();
103                 break;
104
105         case 'P':
106                 relp();
107                 break;
108
109         case 'E':
110                 rele();
111                 break;
112
113         default:
114                 fprintf(stderr, "Undefined Relocation Operation\n");
115                 lkerr++;
116                 break;
117
118         }
119 }
120
121
122 /*)Function     VOID    relt()
123  *
124  *      The function relt() evaluates a T line read by
125  *      the linker. Each byte value read is saved in the
126  *      rtval[] array, rtflg[] is set, and the number of
127  *      evaluations is maintained in rtcnt.
128  *
129  *              T Line
130  *
131  *              T xx xx nn nn nn nn nn ...
132  *
133  *
134  *              In:     "T n0 n1 n2 n3 ... nn"
135  *
136  *              Out:     0   1    2        ..  rtcnt
137  *                        +----+----+----+----+----+
138  *              rtval | n0 | n1 | n2 | .. | nn |
139  *                    +----+----+----+----+----+
140  *              rtflag|  1 |  1 |  1 |  1 |  1 |
141  *            +----+----+----+----+----+
142  *
143  *      The T line contains the assembled code output by the assem-
144  *      bler with xx xx being the offset address from the current area
145  *      base address and nn being the assembled instructions and data in
146  *      byte format.
147  *
148  *      local variable:
149  *              none
150  *
151  *      global variables:
152  *              int     rtcnt           number of values evaluated
153  *              int     rtflg[]         array of evaluation flags
154  *              int     rtval[]         array of evaluation values
155  *
156  *      called functions:
157  *              int     eval()          lkeval.c
158  *              int     more()          lklex.c
159  *
160  *      side effects:
161  *              Linker input T line evaluated.
162  *
163  */
164
165 VOID relt(VOID)
166 {
167         rtcnt = 0;
168         while (more()) {
169                 if (rtcnt < NTXT) {
170                         rtval[rtcnt] = eval();
171                         rtflg[rtcnt] = 1;
172                         rtcnt++;
173                 }
174         }
175 }
176
177 /*)Function     VOID    relr()
178  *
179  *      The function relr() evaluates a R line read by
180  *      the linker.  The R line data is combined with the
181  *      previous T line data to perform the relocation of
182  *      code and data bytes.  The S19 / IHX output and
183  *      translation of the LST files to RST files may be
184  *      performed.
185  *
186  *              R Line
187  *
188  *              R 0 0 nn nn n1 n2 xx xx ...
189  *
190  *              The R line provides the relocation information to the linker.
191  *      The nn nn value is the current area index, i.e.  which area  the
192  *      current  values  were  assembled.  Relocation information is en-
193  *      coded in groups of 4 bytes:
194  *
195  *      1.      n1 is the relocation mode and object format
196  *                      1.      bit 0 word(0x00)/byte(0x01)
197  *                      2.      bit 1 relocatable area(0x00)/symbol(0x02)
198  *                      3.      bit 2 normal(0x00)/PC relative(0x04) relocation
199  *                      4.      bit  3  1-byte(0x00)/2-byte(0x08) object format for
200  *                      byte data
201  *                      5.      bit 4 signed(0x00)/unsigned(0x10) byte data
202  *                      6.      bit 5 normal(0x00)/page '0'(0x20) reference
203  *                      7.      bit 6 normal(0x00)/page 'nnn'(0x40) reference
204  *
205  *      2.      n2      is      a byte index into the corresponding (i.e.  pre-
206  *                      ceeding) T line data (i.e.      a pointer to the data to be
207  *                      updated  by  the  relocation).   The T line data may be
208  *                      1-byte or  2-byte  byte  data  format  or  2-byte  word
209  *                      format.
210  *
211  *      3.      xx xx  is the area/symbol index for the area/symbol be-
212  *                      ing referenced.  the corresponding area/symbol is found
213  *              in the header area/symbol lists.
214  *
215  *      The groups of 4 bytes are repeated for each item requiring relo-
216  *      cation in the preceeding T line.
217  *
218  *      local variable:
219  *              areax   **a             pointer to array of area pointers
220  *              int     aindex          area index
221  *              char    *errmsg[]       array of pointers to error strings
222  *              int     error           error code
223  *              int     lkerr           error flag
224  *              int     mode            relocation mode
225  *              adrr_t  paga            paging base area address
226  *              Addr_T  pags            paging symbol address
227  *              Addr_T  pc              relocated base address
228  *              Addr_T  r               PCR relocation value
229  *              Addr_T  reli            relocation initial value
230  *              Addr_T  relv            relocation final value
231  *              int     rindex          symbol / area index
232  *              Addr_T  rtbase          base code address
233  *              Addr_T  rtofst          rtval[] index offset
234  *              int     rtp             index into T data
235  *              sym     **s             pointer to array of symbol pointers
236  *
237  *      global variables:
238  *              head    *hp             pointer to the head structure
239  *              rerr    rerr            linker error structure
240  *              FILE    *stderr         standard error device
241  *
242  *      called functions:
243  *              Addr_T  adb_b()         lkrloc.c
244  *              Addr_T  adb_lo()        lkrloc.c
245  *              Addr_T  adb_hi()        lkrloc.c
246  *              Addr_T  adw_w()         lkrloc.c
247  *              VOID    elf()           lkelf.c
248  *              Addr_T  evword()        lkrloc.c
249  *              int     eval()          lkeval.c
250  *              int     fprintf()       c_library
251  *              VOID    ihx()           lkihx.c
252  *              int     lkulist         lklist.c
253  *              int     more()          lklex.c
254  *              VOID    relerr()        lkrloc.c
255  *              VOID    s19()           lks19.c
256  *              int     symval()        lksym.c
257  *
258  *      side effects:
259  *              The R and T lines are combined to produce
260  *              relocated code and data.  Output S19 / IHX
261  *              and relocated listing files may be produced.
262  *
263  */
264
265 VOID relr(VOID)
266 {
267         register int mode;
268         register Addr_T reli, relv;
269         int aindex, rindex, rtp, error;
270         Addr_T r, rtbase, rtofst, paga, pags, pc;
271         struct areax **a;
272         struct sym **s;
273
274         /*
275          * Get area and symbol lists
276          */
277         a = hp->a_list;
278         s = hp->s_list;
279
280         /*
281          * Verify Area Mode
282          */
283         if (eval() != (R_WORD | R_AREA) || eval()) {
284                 fprintf(stderr, "R input error\n");
285                 lkerr++;
286         }
287
288         /*
289          * Get area pointer
290          */
291         aindex = evword();
292         if (aindex >= hp->h_narea) {
293                 fprintf(stderr, "R area error\n");
294                 lkerr++;
295                 return;
296         }
297         ap = a[aindex]->a_bap;
298
299         /*
300          * Base values
301          */
302         rtbase = adw_w(0, 0);
303         rtofst = 2;
304
305         /*
306          * Relocate address
307          */
308         pc = adw_w(a[aindex]->a_addr, 0);
309
310         #if 0
311         printf("area %d base address: 0x%x size: 0x%x rtbase: 0x%x\n", aindex,
312                 a[aindex]->a_addr, a[aindex]->a_size, rtbase);
313         #endif
314         /*
315          * Do remaining relocations
316          */
317         while (more()) {
318                 error = 0;
319                 mode = eval();
320
321                 if ((mode & R_ESCAPE_MASK) == R_ESCAPE_MASK)
322                 {
323                     mode = ((mode & ~R_ESCAPE_MASK) << 8) | eval();
324                     /* printf("unescaping rmode\n"); */
325                 }
326
327                 rtp = eval();
328                 rindex = evword();
329
330                 /*
331                  * R_SYM or R_AREA references
332                  */
333                 if (mode & R_SYM) {
334                         if (rindex >= hp->h_nglob) {
335                                 fprintf(stderr, "R symbol error\n");
336                                 lkerr++;
337                                 return;
338                         }
339                         reli = symval(s[rindex]);
340                 } else {
341                         if (rindex >= hp->h_narea) {
342                                 fprintf(stderr, "R area error\n");
343                                 lkerr++;
344                                 return;
345                         }
346                         reli = a[rindex]->a_addr;
347                 }
348
349                 /*
350                  * R_PCR addressing
351                  */
352                 if (mode & R_PCR) {
353                         if (mode & R_BYTE) {
354                                 reli -= (pc + (rtp-rtofst) + 1);
355                         } else {
356                                 reli -= (pc + (rtp-rtofst) + 2);
357                         }
358                 }
359
360                 /*
361                  * R_PAG0 or R_PAG addressing
362                  */
363                 if (mode & (R_PAG0 | R_PAG)) {
364                         paga  = sdp.s_area->a_addr;
365                         pags  = sdp.s_addr;
366                         reli -= paga + pags;
367                 }
368
369                 /*
370                  * R_BYTE or R_WORD operation
371                  */
372                 if (mode & R_BYTE) {
373                         if (mode & R_BYT3)
374                         {
375                                 /* This is a three byte address, of which
376                                  * we will select one byte.
377                                  */
378                                 if (mode & R_HIB)
379                                 {
380                                         /* printf("24 bit address selecting hi byte.\n"); */
381                                         relv = adb_24_hi(reli, rtp);
382                                 }
383                                 else if (mode & R_MSB)
384                                 {
385                                         /* Note that in 24 bit mode, R_MSB
386                                          * is really the middle byte, not
387                                          * the most significant byte.
388                                          *
389                                          * This is ugly and I can only apologize
390                                          * for any confusion.
391                                          */
392                                         /* printf("24 bit address selecting middle byte.\n"); */
393                                         relv = adb_24_mid(reli, rtp);
394                                 }
395                                 else
396                                 {
397                                         /* printf("24 bit address selecting lo byte.\n"); */
398                                         relv = adb_24_lo(reli, rtp);
399                                 }
400                         }
401                         else if (mode & R_BYT2) {
402                                 /* This is a two byte address, of
403                                  * which we will select one byte.
404                                  */
405                                 if (mode & R_MSB) {
406                                         relv = adb_hi(reli, rtp);
407                                 } else {
408                                         relv = adb_lo(reli, rtp);
409                                 }
410                         } else {
411                                 relv = adb_b(reli, rtp);
412                         }
413                 } else if (IS_R_J11(mode)) {
414                         /* JLH: 11 bit jump destination for 8051.  Forms
415                         /  two byte instruction with op-code bits
416                         /  in the MIDDLE!
417                         /  rtp points at 3 byte locus: first two
418                         /  will get the instructiion. third one
419                         /  has raw op-code.
420                         */
421
422                         /* Calculate absolute destination
423                         /  relv must be on same 2K page as pc
424                         */
425                         relv = adw_w(reli, rtp);
426
427             if ((relv & ~0x7ff) != ((pc + rtp - rtofst) & ~0x7ff)) {
428                     error = 2;
429             }
430
431             /* Merge MSB (byte 0) with op-code, ignoring
432             /  top 5 bits of address.  Then hide the op-code
433             */
434             rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+2];
435             rtflg[rtp+2] = 0;
436                         rtofst += 1;
437                 }
438                 else if (IS_R_J19(mode)) {
439                         /* 19 bit jump destination for DS80C390.  Forms
440                         /  three byte instruction with op-code bits
441                         /  in the MIDDLE!
442                         /  rtp points at 4 byte locus: first three
443                         /  will get the instructiion. fourth one
444                         /  has raw op-code.
445                          */
446
447                         /* Calculate absolute destination
448                         /  relv must be on same 512K page as pc
449                         */
450                         relv = adw_24(reli, rtp);
451
452             if ((relv & ~0x7ffff) != ((pc + rtp - rtofst) & ~0x7ffff)) {
453                     error = 2;
454                                 }
455
456             /* Merge MSB (byte 0) with op-code, ignoring
457             /  top 5 bits of address.  Then hide the op-code
458             */
459             rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+3];
460             rtflg[rtp+3] = 0;
461                         rtofst += 1;
462                 }
463                 else if (IS_C24(mode))
464                 {
465                         /* 24 bit address */
466                         relv = adw_24(reli, rtp);
467                         }
468                 else
469                 {
470                         /* 16 bit address. */
471                         relv = adw_w(reli, rtp);
472                 }
473
474                 /*
475                  * R_BYTE with R_BYT2 offset adjust
476                  */
477                 if (mode & R_BYTE) {
478                         if (mode & R_BYT2) {
479                                 rtofst += 1;
480                         }
481                 }
482
483                 /*
484                  * Unsigned Byte Checking
485                  */
486                 if (mode & R_USGN && mode & R_BYTE && relv & ~0xFF)
487                         error = 1;
488
489                 /*
490                  * PCR Relocation Error Checking
491                  */
492                 if (mode & R_PCR && mode & R_BYTE) {
493                         r = relv & ~0x7F;
494                         if (r != (Addr_T) ~0x7F && r != 0)
495                                 error = 2;
496                 }
497
498                 /*
499                  * Page Relocation Error Checking
500                  */
501                 /* if (mode & R_PAG0 && (relv & ~0xFF || paga || pags))
502                         error = 3;*/
503                 if (mode & R_PAG  && (relv & ~0xFF))
504                         error = 4;
505
506                 /*
507                  * Error Processing
508                  */
509                 if (error) {
510                         rerr.aindex = aindex;
511                         rerr.mode = mode;
512                         rerr.rtbase = rtbase + rtp - rtofst - 1;
513                         rerr.rindex = rindex;
514                         rerr.rval = relv - reli;
515                         relerr(errmsg[error-1]);
516                 }
517         }
518         if (uflag != 0) {
519                 lkulist(1);
520         }
521
522         /* JLH: output only if data (beyond two byte address) */
523         if ((oflag == 1) && (rtcnt > 2)) {
524                 // int extendedAddress = (a[aindex]->a_addr >> 16) & 0xffff;
525
526                 /* Boy, is this a hack: for ABS sections, the
527                  * base address is stored as zero, and the T records
528                  * indicate the offset from zero.
529                  *
530                  * Since T records can only indicate a 16 bit offset, this
531                  * obviously creates a problem for ABS segments located
532                  * above 64K (this is only meaningful in flat24 mode).
533                  *
534                  * However, the size of an ABS area is stored as
535                  * base address + section size (I suspect this is a bug,
536                  * but it's a handy one right now). So the upper 8 bits of
537                  * the 24 bit address are stored in the size record.
538                  * Thus we add it in.
539                  *
540                  * This is another reason why we can't have areas greater
541                  * than 64K yet, even in flat24 mode.
542                  */
543         //      extendedAddress += ((a[aindex]->a_size) >> 16 & 0xffff);
544         //      commented out by jr
545
546                 if (lastAreaIndex != aindex) {
547                         lastAreaIndex = aindex;
548                         ihxNewArea();
549                 }
550 #if 0
551                 if (extendedAddress != lastExtendedAddress)
552                 {
553
554                     if (lastExtendedAddress!=-1) {
555                       printf("output extended linear address record 0x%x 0x%x\n",
556                              extendedAddress, lastExtendedAddress);
557                     }
558
559                     if (rflag)
560                     {
561                         ihxExtendedLinearAddress(extendedAddress);
562                     }
563                     else if (extendedAddress)
564                     {
565                         /* Not allowed to generate extended address records,
566                          * but one is called for here...
567                          */
568                         fprintf(stderr,
569                                 "warning: extended linear address encountered; "
570                                 "you probably want the -r flag.\n");
571                     }
572                     lastExtendedAddress = extendedAddress;
573                 }
574 #endif
575                 ihx(1);
576         } else
577         if ((oflag == 2) && (rtcnt > 2)) {
578                 s19(1);
579         } else
580         if ((oflag == 3) && (rtcnt > 2)) {
581                 elf(1);
582         }
583 }
584
585 char *errmsg[] = {
586         "Unsigned Byte error",
587         "Byte PCR relocation error",
588         "Page0 relocation error",
589         "Page Mode relocation error"
590 };
591
592
593 /*)Function     VOID    relp()
594  *
595  *      The function relp() evaluates a P line read by
596  *      the linker.  The P line data is combined with the
597  *      previous T line data to set the base page address
598  *      and test the paging boundary and length.
599  *
600  *              P Line
601  *
602  *              P 0 0 nn nn n1 n2 xx xx
603  *
604  *      The P line provides the paging information to the linker as
605  *      specified by a .setdp directive.  The format of the relocation
606  *      information is identical to that of the R line.  The correspond-
607  *      ing T line has the following information:
608  *              T xx xx aa aa bb bb
609  *
610  *      Where aa aa is the area reference number which specifies the
611  *      selected page area and bb bb is the base address of the page.
612  *      bb bb will require relocation processing if the 'n1 n2 xx xx' is
613  *      specified in the P line.  The linker will verify that the base
614  *      address is on a 256 byte boundary and that the page length of an
615  *      area defined with the PAG type is not larger than 256 bytes.
616  *
617  *      local variable:
618  *              areax   **a             pointer to array of area pointers
619  *              int     aindex          area index
620  *              int     mode            relocation mode
621  *              Addr_T  relv    relocation value
622  *              int     rindex          symbol / area index
623  *              int     rtp                     index into T data
624  *              sym     **s                     pointer to array of symbol pointers
625  *
626  *      global variables:
627  *              head *hp                pointer to the head structure
628  *              int     lkerr           error flag
629  *              sdp     sdp                     base page structure
630  *              FILE *stderr    standard error device
631  *
632  *      called functions:
633  *              Addr_T adw_w()  lkrloc.c
634  *              Addr_T evword() lkrloc.c
635  *              int     eval()          lkeval.c
636  *              int     fprintf()       c_library
637  *              int     more()          lklex.c
638  *              int     symval()        lksym.c
639  *
640  *      side effects:
641  *              The P and T lines are combined to set
642  *              the base page address and report any
643  *              paging errors.
644  *
645  */
646
647 VOID relp(VOID)
648 {
649         register int aindex, rindex;
650         int mode, rtp;
651         Addr_T relv;
652         struct areax **a;
653         struct sym **s;
654
655         /*
656          * Get area and symbol lists
657          */
658         a = hp->a_list;
659         s = hp->s_list;
660
661         /*
662          * Verify Area Mode
663          */
664         if (eval() != (R_WORD | R_AREA) || eval()) {
665                 fprintf(stderr, "P input error\n");
666                 lkerr++;
667         }
668
669         /*
670          * Get area pointer
671          */
672         aindex = evword();
673         if (aindex >= hp->h_narea) {
674                 fprintf(stderr, "P area error\n");
675                 lkerr++;
676                 return;
677         }
678
679         /*
680          * Do remaining relocations
681          */
682         while (more()) {
683                 mode = eval();
684                 rtp = eval();
685                 rindex = evword();
686
687                 /*
688                  * R_SYM or R_AREA references
689                  */
690                 if (mode & R_SYM) {
691                         if (rindex >= hp->h_nglob) {
692                                 fprintf(stderr, "P symbol error\n");
693                                 lkerr++;
694                                 return;
695                         }
696                         relv = symval(s[rindex]);
697                 } else {
698                         if (rindex >= hp->h_narea) {
699                                 fprintf(stderr, "P area error\n");
700                                 lkerr++;
701                                 return;
702                         }
703                         relv = a[rindex]->a_addr;
704                 }
705                 adw_w(relv, rtp);
706         }
707
708         /*
709          * Paged values
710          */
711         aindex = adw_w(0,2);
712         if (aindex >= hp->h_narea) {
713                 fprintf(stderr, "P area error\n");
714                 lkerr++;
715                 return;
716         }
717         sdp.s_areax = a[aindex];
718         sdp.s_area = sdp.s_areax->a_bap;
719         sdp.s_addr = adw_w(0,4);
720         if (sdp.s_area->a_addr & 0xFF || sdp.s_addr & 0xFF)
721                 relerp("Page Definition Boundary Error");
722 }
723
724 /*)Function     VOID    rele()
725  *
726  *      The function rele() closes all open output files
727  *      at the end of the linking process.
728  *
729  *      local variable:
730  *              none
731  *
732  *      global variables:
733  *              int     oflag           output type flag
734  *              int     uflag           relocation listing flag
735  *
736  *      called functions:
737  *              VOID    elf()           lkelf.c
738  *              VOID    ihx()           lkihx.c
739  *              VOID    lkulist()       lklist.c
740  *              VOID    s19()           lks19.c
741  *
742  *      side effects:
743  *              All open output files are closed.
744  *
745  */
746
747 VOID rele(VOID)
748 {
749         if (uflag != 0) {
750                 lkulist(0);
751         }
752         if (oflag == 1) {
753                 ihx(0);
754         } else
755         if (oflag == 2) {
756                 s19(0);
757         } else
758         if (oflag == 3) {
759                 elf(0);
760         }
761 }
762
763 /*)Function     Addr_T          evword()
764  *
765  *      The function evword() combines two byte values
766  *      into a single word value.
767  *
768  *      local variable:
769  *              Addr_T  v               temporary evaluation variable
770  *
771  *      global variables:
772  *              hilo                    byte ordering parameter
773  *
774  *      called functions:
775  *              int     eval()          lkeval.c
776  *
777  *      side effects:
778  *              Relocation text line is scanned to combine
779  *              two byte values into a single word value.
780  *
781  */
782
783 Addr_T evword(VOID)
784 {
785         register Addr_T v;
786
787         if (hilo) {
788                 v =  (eval() << 8);
789                 v +=  eval();
790         } else {
791                 v =   eval();
792                 v += (eval() << 8);
793         }
794         return(v);
795 }
796
797 /*)Function     Addr_T          adb_b(v, i)
798  *
799  *              int     v               value to add to byte
800  *              int     i               rtval[] index
801  *
802  *      The function adb_b() adds the value of v to
803  *      the single byte value contained in rtval[i].
804  *      The new value of rtval[i] is returned.
805  *
806  *      local variable:
807  *              none
808  *
809  *      global variables:
810  *              none
811  *
812  *      called functions:
813  *              none
814  *
815  *      side effects:
816  *              The value of rtval[] is changed.
817  *
818  */
819
820 Addr_T adb_b(register Addr_T v, register int i)
821 {
822         return(rtval[i] += v);
823 }
824
825 /*)Function     Addr_T          adb_lo(v, i)
826  *
827  *              int     v               value to add to byte
828  *              int     i               rtval[] index
829  *
830  *      The function adb_lo() adds the value of v to the
831  *      double byte value contained in rtval[i] and rtval[i+1].
832  *      The new value of rtval[i] / rtval[i+1] is returned.
833  *      The MSB rtflg[] is cleared.
834  *
835  *      local variable:
836  *              Addr_T  j               temporary evaluation variable
837  *
838  *      global variables:
839  *              hilo                    byte ordering parameter
840  *
841  *      called functions:
842  *              none
843  *
844  *      side effects:
845  *              The value of rtval[] is changed.
846  *              The rtflg[] value corresponding to the
847  *              MSB of the word value is cleared to reflect
848  *              the fact that the LSB is the selected byte.
849  *
850  */
851
852 Addr_T adb_lo(Addr_T  v, int i)
853 {
854         register Addr_T j;
855
856         j = adw_w(v, i);
857         /*
858          * Remove Hi byte
859          */
860         if (hilo) {
861                 rtflg[i] = 0;
862         } else {
863                 rtflg[i+1] = 0;
864         }
865         return (j);
866 }
867
868 /*)Function     Addr_T          adb_hi(v, i)
869  *
870  *              int     v               value to add to byte
871  *              int     i               rtval[] index
872  *
873  *      The function adb_hi() adds the value of v to the
874  *      double byte value contained in rtval[i] and rtval[i+1].
875  *      The new value of rtval[i] / rtval[i+1] is returned.
876  *      The LSB rtflg[] is cleared.
877  *
878  *      local variable:
879  *              Addr_T  j               temporary evaluation variable
880  *
881  *      global variables:
882  *              hilo                    byte ordering parameter
883  *
884  *      called functions:
885  *              none
886  *
887  *      side effects:
888  *              The value of rtval[] is changed.
889  *              The rtflg[] value corresponding to the
890  *              LSB of the word value is cleared to reflect
891  *              the fact that the MSB is the selected byte.
892  *
893  */
894
895 Addr_T adb_hi(Addr_T  v, int i)
896 {
897         register Addr_T j;
898
899         j = adw_w(v, i);
900         /*
901          * Remove Lo byte
902          */
903         if (hilo) {
904                 rtflg[i+1] = 0;
905         } else {
906                 rtflg[i] = 0;
907         }
908         return (j);
909 }
910
911 /*)Function     Addr_T          adb_24_hi(v, i)
912  *
913  *              int     v               value to add to byte
914  *              int     i               rtval[] index
915  *
916  *      The function adb_24_hi() adds the value of v to the
917  *      24 bit value contained in rtval[i] - rtval[i+2].
918  *      The new value of rtval[i] / rtval[i+1] is returned.
919  *      The LSB & middle byte rtflg[] is cleared.
920  *
921  *      local variable:
922  *              Addr_T  j               temporary evaluation variable
923  *
924  *      global variables:
925  *              hilo                    byte ordering parameter
926  *
927  *      called functions:
928  *              none
929  *
930  *      side effects:
931  *              The value of rtval[] is changed.
932  *              The rtflg[] value corresponding to the
933  *              LSB & middle byte of the word value is cleared to
934  *              reflect the fact that the MSB is the selected byte.
935  *
936  */
937
938 Addr_T adb_24_hi(Addr_T v, int i)
939 {
940         register Addr_T j;
941
942         j = adw_24(v, i);
943
944         /* Remove the lower two bytes. */
945         if (hilo)
946         {
947             rtflg[i+2] = 0;
948         }
949         else
950         {
951             rtflg[i] = 0;
952         }
953         rtflg[i+1] = 0;
954
955         return (j);
956 }
957
958 /*)Function     Addr_T          adb_24_mid(v, i)
959  *
960  *              int     v               value to add to byte
961  *              int     i               rtval[] index
962  *
963  *      The function adb_24_mid() adds the value of v to the
964  *      24 bit value contained in rtval[i] - rtval[i+2].
965  *      The new value of rtval[i] / rtval[i+1] is returned.
966  *      The LSB & MSB byte rtflg[] is cleared.
967  *
968  *      local variable:
969  *              Addr_T  j               temporary evaluation variable
970  *
971  *      global variables:
972  *              hilo                    byte ordering parameter
973  *
974  *      called functions:
975  *              none
976  *
977  *      side effects:
978  *              The value of rtval[] is changed.
979  *              The rtflg[] value corresponding to the
980  *              LSB & MSB of the 24 bit value is cleared to reflect
981  *              the fact that the middle byte is the selected byte.
982  *
983  */
984
985 Addr_T adb_24_mid(Addr_T v, int i)
986 {
987         register Addr_T j;
988
989         j = adw_24(v, i);
990
991         /* remove the MSB & LSB. */
992         rtflg[i+2] = 0;
993         rtflg[i] = 0;
994
995         return (j);
996 }
997
998 /*)Function     Addr_T          adb_24_lo(v, i)
999  *
1000  *              int     v               value to add to byte
1001  *              int     i               rtval[] index
1002  *
1003  *      The function adb_24_lo() adds the value of v to the
1004  *      24 bit value contained in rtval[i] - rtval[i+2].
1005  *      The new value of rtval[i] / rtval[i+1] is returned.
1006  *      The MSB & middle byte rtflg[] is cleared.
1007  *
1008  *      local variable:
1009  *              Addr_T  j               temporary evaluation variable
1010  *
1011  *      global variables:
1012  *              hilo                    byte ordering parameter
1013  *
1014  *      called functions:
1015  *              none
1016  *
1017  *      side effects:
1018  *              The value of rtval[] is changed.
1019  *              The rtflg[] value corresponding to the
1020  *              MSB & middle byte  of the word value is cleared to
1021  *              reflect the fact that the LSB is the selected byte.
1022  *
1023  */
1024
1025 Addr_T adb_24_lo(Addr_T v, int i)
1026 {
1027         register Addr_T j;
1028
1029         j = adw_24(v, i);
1030
1031         /* Remove the upper two bytes. */
1032         if (hilo)
1033         {
1034             rtflg[i] = 0;
1035         }
1036         else
1037         {
1038             rtflg[i+2] = 0;
1039         }
1040         rtflg[i+1] = 0;
1041
1042         return (j);
1043 }
1044
1045 /*)Function     Addr_T          adw_w(v, i)
1046  *
1047  *              int     v               value to add to word
1048  *              int     i               rtval[] index
1049  *
1050  *      The function adw_w() adds the value of v to the
1051  *      word value contained in rtval[i] and rtval[i+1].
1052  *      The new value of rtval[i] / rtval[i+1] is returned.
1053  *
1054  *      local variable:
1055  *              Addr_T  j               temporary evaluation variable
1056  *
1057  *      global variables:
1058  *              hilo                    byte ordering parameter
1059  *
1060  *      called functions:
1061  *              none
1062  *
1063  *      side effects:
1064  *              The word value of rtval[] is changed.
1065  *
1066  */
1067
1068 Addr_T adw_w(register Addr_T v, register int i)
1069 {
1070         register Addr_T j;
1071
1072         if (hilo) {
1073                 j = v + (rtval[i] << 8) + (rtval[i+1] & 0xff);
1074                 rtval[i] = (j >> 8) & 0xff;
1075                 rtval[i+1] = j & 0xff;
1076         } else {
1077                 j = v + (rtval[i] & 0xff) + (rtval[i+1] << 8);
1078                 rtval[i] = j & 0xff;
1079                 rtval[i+1] = (j >> 8) & 0xff;
1080         }
1081         return(j);
1082 }
1083
1084 /*)Function     Addr_T          adw_24(v, i)
1085  *
1086  *              int     v               value to add to word
1087  *              int     i               rtval[] index
1088  *
1089  *      The function adw_w() adds the value of v to the
1090  *      24 bit value contained in rtval[i] - rtval[i+2].
1091  *      The new value of rtval[i] - rtval[i+2] is returned.
1092  *
1093  *      local variable:
1094  *              Addr_T  j               temporary evaluation variable
1095  *
1096  *      global variables:
1097  *              hilo                    byte ordering parameter
1098  *
1099  *      called functions:
1100  *              none
1101  *
1102  *      side effects:
1103  *              The word value of rtval[] is changed.
1104  *
1105  */
1106 Addr_T adw_24(Addr_T v, int i)
1107 {
1108         register Addr_T j;
1109
1110         if (hilo) {
1111                 j = v + ((rtval[i] & 0xff) << 16)
1112                       + ((rtval[i+1] & 0xff) << 8)
1113                       + (rtval[i+2] & 0xff);
1114                 rtval[i] = (j >> 16) & 0xff;
1115                 rtval[i+1] = (j >> 8) & 0xff;
1116                 rtval[i+2] = j & 0xff;
1117         } else {
1118                 j = v + (rtval[i] & 0xff)
1119                       + ((rtval[i+1] & 0xff) << 8)
1120                       + ((rtval[i+2] & 0xff) << 16);
1121                 rtval[i] = j & 0xff;
1122                 rtval[i+1] = (j >> 8) & 0xff;
1123                 rtval[i+2] = (j >> 16) & 0xff;
1124         }
1125         return(j);
1126 }
1127
1128 /*)Function     Addr_T          adw_lo(v, i)
1129  *
1130  *              int     v               value to add to byte
1131  *              int     i               rtval[] index
1132  *
1133  *      The function adw_lo() adds the value of v to the
1134  *      double byte value contained in rtval[i] and rtval[i+1].
1135  *      The new value of rtval[i] / rtval[i+1] is returned.
1136  *      The MSB rtval[] is zeroed.
1137  *
1138  *      local variable:
1139  *              Addr_T  j               temporary evaluation variable
1140  *
1141  *      global variables:
1142  *              hilo                    byte ordering parameter
1143  *
1144  *      called functions:
1145  *              none
1146  *
1147  *      side effects:
1148  *              The value of rtval[] is changed.
1149  *              The MSB of the word value is cleared to reflect
1150  *              the fact that the LSB is the selected byte.
1151  *
1152  */
1153
1154 Addr_T adw_lo(Addr_T  v, int i)
1155 {
1156         register Addr_T j;
1157
1158         j = adw_w(v, i);
1159         /*
1160          * Clear Hi byte
1161          */
1162         if (hilo) {
1163                 rtval[i] = 0;
1164         } else {
1165                 rtval[i+1] = 0;
1166         }
1167         return (j);
1168 }
1169
1170 /*)Function     Addr_T          adw_hi(v, i)
1171  *
1172  *              int     v               value to add to byte
1173  *              int     i               rtval[] index
1174  *
1175  *      The function adw_hi() adds the value of v to the
1176  *      double byte value contained in rtval[i] and rtval[i+1].
1177  *      The new value of rtval[i] / rtval[i+1] is returned.
1178  *      The MSB and LSB values are interchanged.
1179  *      The MSB rtval[] is zeroed.
1180  *
1181  *      local variable:
1182  *              Addr_T  j               temporary evaluation variable
1183  *
1184  *      global variables:
1185  *              hilo                    byte ordering parameter
1186  *
1187  *      called functions:
1188  *              none
1189  *
1190  *      side effects:
1191  *              The value of rtval[] is changed.
1192  *              The MSB and LSB values are interchanged and
1193  *              then the MSB cleared.
1194  *
1195  */
1196
1197 Addr_T adw_hi(Addr_T  v, int i)
1198 {
1199         register Addr_T j;
1200
1201         j = adw_w(v, i);
1202         /*
1203          * LSB = MSB, Clear MSB
1204          */
1205         if (hilo) {
1206                 rtval[i+1] = rtval[i];
1207                 rtval[i] = 0;
1208         } else {
1209                 rtval[i] = rtval[i+1];
1210                 rtval[i+1] = 0;
1211         }
1212         return (j);
1213 }
1214
1215 /*)Function     VOID    relerr(str)
1216  *
1217  *              char    *str            error string
1218  *
1219  *      The function relerr() outputs the error string to
1220  *      stderr and to the map file (if it is open).
1221  *
1222  *      local variable:
1223  *              none
1224  *
1225  *      global variables:
1226  *              FILE    *mfp            handle for the map file
1227  *
1228  *      called functions:
1229  *              VOID    errdmp()        lkrloc.c
1230  *
1231  *      side effects:
1232  *              Error message inserted into map file.
1233  *
1234  */
1235
1236 VOID relerr(char *str)
1237 {
1238         errdmp(stderr, str);
1239         if (mfp)
1240                 errdmp(mfp, str);
1241 }
1242
1243 /*)Function     VOID    errdmp(fptr, str)
1244  *
1245  *              FILE    *fptr           output file handle
1246  *              char    *str            error string
1247  *
1248  *      The function errdmp() outputs the error string str
1249  *      to the device specified by fptr.  Additional information
1250  *      is output about the definition and referencing of
1251  *      the symbol / area error.
1252  *
1253  *      local variable:
1254  *              int     mode            error mode
1255  *              int     aindex          area index
1256  *              int     lkerr           error flag
1257  *              int     rindex          error index
1258  *              sym     **s             pointer to array of symbol pointers
1259  *              areax   **a             pointer to array of area pointers
1260  *              areax   *raxp           error area extension pointer
1261  *
1262  *      global variables:
1263  *              sdp     sdp             base page structure
1264  *
1265  *      called functions:
1266  *              int     fprintf()       c_library
1267  *              VOID    prntval()       lkrloc.c
1268  *
1269  *      side effects:
1270  *              Error reported.
1271  *
1272  */
1273
1274 VOID errdmp(FILE *fptr, char *str)
1275 {
1276         int mode, aindex, rindex;
1277         struct sym **s;
1278         struct areax **a;
1279         struct areax *raxp;
1280
1281         a = hp->a_list;
1282         s = hp->s_list;
1283
1284         mode = rerr.mode;
1285         aindex = rerr.aindex;
1286         rindex = rerr.rindex;
1287
1288         /*
1289          * Print Error
1290          */
1291         fprintf(fptr, "\n?ASlink-Warning-%s", str);
1292         lkerr++;
1293
1294         /*
1295          * Print symbol if symbol based
1296          */
1297         if (mode & R_SYM) {
1298                 fprintf(fptr, " for symbol %s\n",
1299                         &s[rindex]->s_id[0]);
1300         } else {
1301                 fprintf(fptr, "\n");
1302         }
1303
1304         /*
1305          * Print Ref Info
1306          */
1307         fprintf(fptr,
1308                 "         file        module      area        offset\n");
1309         fprintf(fptr,
1310                 "  Refby  %-8.8s    %-8.8s    %-8.8s    ",
1311                         hp->h_lfile->f_idp,
1312                         &hp->m_id[0],
1313                         &a[aindex]->a_bap->a_id[0]);
1314         prntval(fptr, rerr.rtbase);
1315
1316         /*
1317          * Print Def Info
1318          */
1319         if (mode & R_SYM) {
1320                 raxp = s[rindex]->s_axp;
1321         } else {
1322                 raxp = a[rindex];
1323         }
1324         fprintf(fptr,
1325                 "  Defin  %-8.8s    %-8.8s    %-8.8s    ",
1326                         raxp->a_bhp->h_lfile->f_idp,
1327                         &raxp->a_bhp->m_id[0],
1328                         &raxp->a_bap->a_id[0]);
1329         if (mode & R_SYM) {
1330                 prntval(fptr, s[rindex]->s_addr);
1331         } else {
1332                 prntval(fptr, rerr.rval);
1333         }
1334 }
1335
1336 /*)Function     VOID prntval(fptr, v)
1337  *
1338  *              FILE    *fptr   output file handle
1339  *              Addr_T  v               value to output
1340  *
1341  *      The function prntval() outputs the value v, in the
1342  *      currently selected radix, to the device specified
1343  *      by fptr.
1344  *
1345  *      local variable:
1346  *              none
1347  *
1348  *      global variables:
1349  *              int     xflag           current radix
1350  *
1351  *      called functions:
1352  *              int     fprintf()       c_library
1353  *
1354  *      side effects:
1355  *              none
1356  *
1357  */
1358
1359 VOID prntval(FILE *fptr, Addr_T v)
1360 {
1361         if (xflag == 0) {
1362                 fprintf(fptr, "%04X\n", v);
1363         } else
1364         if (xflag == 1) {
1365                 fprintf(fptr, "%06o\n", v);
1366         } else
1367         if (xflag == 2) {
1368                 fprintf(fptr, "%05u\n", v);
1369         }
1370 }
1371
1372 /*)Function     VOID    relerp(str)
1373  *
1374  *              char    *str            error string
1375  *
1376  *      The function relerp() outputs the paging error string to
1377  *      stderr and to the map file (if it is open).
1378  *
1379  *      local variable:
1380  *              none
1381  *
1382  *      global variables:
1383  *              FILE    *mfp            handle for the map file
1384  *
1385  *      called functions:
1386  *              VOID    erpdmp()        lkrloc.c
1387  *
1388  *      side effects:
1389  *              Error message inserted into map file.
1390  *
1391  */
1392
1393 VOID relerp(char *str)
1394 {
1395         erpdmp(stderr, str);
1396         if (mfp)
1397                 erpdmp(mfp, str);
1398 }
1399
1400 /*)Function     VOID    erpdmp(fptr, str)
1401  *
1402  *              FILE    *fptr           output file handle
1403  *              char    *str            error string
1404  *
1405  *      The function erpdmp() outputs the error string str
1406  *      to the device specified by fptr.
1407  *
1408  *      local variable:
1409  *              head    *thp            pointer to head structure
1410  *
1411  *      global variables:
1412  *              int             lkerr           error flag
1413  *              sdp             sdp                     base page structure
1414  *
1415  *      called functions:
1416  *              int     fprintf()               c_library
1417  *              VOID    prntval()       lkrloc.c
1418  *
1419  *      side effects:
1420  *              Error reported.
1421  *
1422  */
1423
1424 VOID erpdmp(FILE *fptr, char *str)
1425 {
1426         register struct head *thp;
1427
1428         thp = sdp.s_areax->a_bhp;
1429
1430         /*
1431          * Print Error
1432          */
1433         fprintf(fptr, "\n?ASlink-Warning-%s\n", str);
1434         lkerr++;
1435
1436         /*
1437          * Print PgDef Info
1438          */
1439         fprintf(fptr,
1440                 "         file        module      pgarea      pgoffset\n");
1441         fprintf(fptr,
1442                 "  PgDef  %-8.8s    %-8.8s    %-8.8s    ",
1443                         thp->h_lfile->f_idp,
1444                         &thp->m_id[0],
1445                         &sdp.s_area->a_id[0]);
1446         prntval(fptr, sdp.s_area->a_addr + sdp.s_addr);
1447 }