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