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