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