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