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