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