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