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