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