Add 24 bit flat mode support for DS80C390 to assembler and linker
[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                 rtp = eval();
310                 rindex = evword();
311
312                 /*
313                  * R_SYM or R_AREA references
314                  */
315                 if (mode & R_SYM) {
316                         if (rindex >= hp->h_nglob) {
317                                 fprintf(stderr, "R symbol error\n");
318                                 lkerr++;
319                                 return;
320                         }
321                         reli = symval(s[rindex]);
322                 } else {
323                         if (rindex >= hp->h_narea) {
324                                 fprintf(stderr, "R area error\n");
325                                 lkerr++;
326                                 return;
327                         }
328                         reli = a[rindex]->a_addr;
329                 }
330
331                 /*
332                  * R_PCR addressing
333                  */
334                 if (mode & R_PCR) {
335                         if (mode & R_BYTE) {
336                                 reli -= (pc + (rtp-rtofst) + 1);
337                         } else {
338                                 reli -= (pc + (rtp-rtofst) + 2);
339                         }
340                 }
341
342                 /*
343                  * R_PAG0 or R_PAG addressing
344                  */
345                 if (mode & (R_PAG0|R_PAG)) {
346                         paga  = sdp.s_area->a_addr;
347                         pags  = sdp.s_addr;
348                         reli -= paga + pags;
349                 }
350
351                 /*
352                  * R_BYTE or R_WORD operation
353                  */
354                 if (mode & R_BYTE) {
355                         if (mode & R_BYT2) {
356                                 if (mode & R_MSB) {
357                                         relv = adb_hi(reli, rtp);
358                                 } else {
359                                         relv = adb_lo(reli, rtp);
360                                 }
361                         } else {
362                                 relv = adb_b(reli, rtp);
363                         }
364                 } else if (IS_R_J11(mode)) {
365                         /* JLH: 11 bit jump destination for 8051.  Forms
366                         /  two byte instruction with op-code bits
367                         /  in the MIDDLE!
368                         /  rtp points at 3 byte locus: first two
369                         /  will get the instructiion. third one
370                         /  has raw op-code.
371                         */
372         
373                         /* Calculate absolute destination
374                         /  relv must be on same 2K page as pc
375                         */
376                         relv = adw_w(reli, rtp);
377
378             if ((relv & ~0x7ff) != ((pc + rtp - rtofst) & ~0x7ff)) {
379                     error = 2;
380             }
381
382             /* Merge MSB (byte 0) with op-code, ignoring
383             /  top 5 bits of address.  Then hide the op-code
384             */
385             rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+2];
386             rtflg[rtp+2] = 0;
387                         rtofst += 1;
388                 }
389                 else if (IS_R_J19(mode)) {
390                         /* 19 bit jump destination for DS80C390.  Forms
391                         /  three byte instruction with op-code bits
392                         /  in the MIDDLE!
393                         /  rtp points at 4 byte locus: first three
394                         /  will get the instructiion. fourth one
395                         /  has raw op-code.
396                          */
397         
398                         /* Calculate absolute destination
399                         /  relv must be on same 512K page as pc
400                         */
401                         relv = adw_24(reli, rtp);
402
403             if ((relv & ~0x7ffff) != ((pc + rtp - rtofst) & ~0x7ffff)) {
404                     error = 2;
405                                 }
406
407             /* Merge MSB (byte 0) with op-code, ignoring
408             /  top 5 bits of address.  Then hide the op-code
409             */
410             rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+3];
411             rtflg[rtp+3] = 0;
412                         rtofst += 1;
413                 }                
414                 else if (IS_C24(mode))
415                 {
416                         /* 24 bit address */
417                         relv = adw_24(reli, rtp);
418                         }
419                 else
420                 {
421                         /* 16 bit address. */
422                         relv = adw_w(reli, rtp);
423                 }
424
425                 /*
426                  * R_BYTE with R_BYT2 offset adjust
427                  */
428                 if (mode & R_BYTE) {
429                         if (mode & R_BYT2) {
430                                 rtofst += 1;
431                         }
432                 }
433
434                 /*
435                  * Unsigned Byte Checking
436                  */
437                 if (mode & R_USGN && mode & R_BYTE && relv & ~0xFF)
438                         error = 1;
439
440                 /*
441                  * PCR Relocation Error Checking
442                  */
443                 if (mode & R_PCR && mode & R_BYTE) {
444                         r = relv & ~0x7F;
445                         if (r != (addr_t) ~0x7F && r != 0)
446                                 error = 2; 
447                 }
448
449                 /*
450                  * Page Relocation Error Checking
451                  */
452                 /* if (mode & R_PAG0 && (relv & ~0xFF || paga || pags))
453                         error = 3;*/
454                 if (mode & R_PAG  && (relv & ~0xFF))
455                         error = 4;
456
457                 /*
458                  * Error Processing
459                  */
460                 if (error) {
461                         rerr.aindex = aindex;
462                         rerr.mode = mode;
463                         rerr.rtbase = rtbase + rtp - rtofst - 1;
464                         rerr.rindex = rindex;
465                         rerr.rval = relv - reli;
466                         relerr(errmsg[error-1]);
467                 }
468         }
469         if (uflag != 0) {
470                 lkulist(1);
471         }
472
473         /* JLH: output only if data (beyond two byte address) */
474         if ((oflag == 1) && (rtcnt > 2)) {
475                 int extendedAddress = (a[aindex]->a_addr >> 16) & 0xffff;
476                 
477                 /* Boy, is this a hack: for ABS sections, the
478                  * base address is stored as zero, and the T records
479                  * indicate the offset from zero.
480                  *
481                  * Since T records can only indicate a 16 bit offset, this
482                  * obviously creates a problem for ABS segments located
483                  * above 64K (this is only meaningful in flat24 mode).
484                  *
485                  * However, the size of an ABS area is stored as
486                  * base address + section size (I suspect this is a bug,
487                  * but it's a handy one right now). So the upper 8 bits of
488                  * the 24 bit address are stored in the size record.
489                  * Thus we add it in.
490                  *
491                  * This is another reason why we can't have areas greater
492                  * than 64K yet, even in flat24 mode.
493                  */
494                 extendedAddress += ((a[aindex]->a_size) >> 16 & 0xffff);
495                 
496                 if (extendedAddress != lastExtendedAddress)
497                 {
498                 
499                     #if 0
500                     printf("output extended linear address record 0x%x\n",
501                             extendedAddress);
502                     #endif
503                     
504                     if (rflag)
505                     {
506                         ihxEntendedLinearAddress(extendedAddress);
507                     }
508                     else if (extendedAddress)
509                     {
510                         /* Not allowed to generate extended address records,
511                          * but one is called for here...
512                          */
513                         fprintf(stderr, 
514                                 "warning: extended linear address encountered; "
515                                 "you probably want the -r flag.\n");
516                     }
517                     lastExtendedAddress = extendedAddress;
518                 }
519                 ihx(1);
520         } else
521         if ((oflag == 2) && (rtcnt > 2)) {
522                 s19(1);
523         }
524 }
525
526 char *errmsg[] = {
527         "Unsigned Byte error",
528         "Byte PCR relocation error",
529         "Page0 relocation error",
530         "Page Mode relocation error"
531 };
532
533
534 /*)Function     VOID    relp()
535  *
536  *      The function relp() evaluates a P line read by
537  *      the linker.  The P line data is combined with the
538  *      previous T line data to set the base page address
539  *      and test the paging boundary and length.
540  *
541  *              P Line
542  *
543  *              P 0 0 nn nn n1 n2 xx xx
544  *
545  *      The P line provides the paging information to the linker as
546  *      specified by a .setdp directive.  The format of the relocation
547  *      information is identical to that of the R line.  The correspond-
548  *      ing T line has the following information:
549  *              T xx xx aa aa bb bb
550  *
551  *      Where aa aa is the area reference number which specifies the
552  *      selected page area and bb bb is the base address of the page.
553  *      bb bb will require relocation processing if the 'n1 n2 xx xx' is
554  *      specified in the P line.  The linker will verify that the base
555  *      address is on a 256 byte boundary and that the page length of an
556  *      area defined with the PAG type is not larger than 256 bytes.
557  *
558  *      local variable:
559  *              areax   **a             pointer to array of area pointers
560  *              int     aindex          area index
561  *              int     mode            relocation mode
562  *              addr_t  relv    relocation value
563  *              int     rindex          symbol / area index
564  *              int     rtp                     index into T data
565  *              sym     **s                     pointer to array of symbol pointers
566  *
567  *      global variables:
568  *              head *hp                pointer to the head structure
569  *              int     lkerr           error flag
570  *              sdp     sdp                     base page structure
571  *              FILE *stderr    standard error device
572  *
573  *      called functions:
574  *              addr_t adw_w()  lkrloc.c
575  *              addr_t evword() lkrloc.c
576  *              int     eval()          lkeval.c
577  *              int     fprintf()       c_library
578  *              int     more()          lklex.c
579  *              int     symval()        lksym.c
580  *
581  *      side effects:
582  *              The P and T lines are combined to set
583  *              the base page address and report any
584  *              paging errors.
585  *
586  */
587
588 VOID
589 relp()
590 {
591         register int aindex, rindex;
592         int mode, rtp;
593         addr_t relv;
594         struct areax **a;
595         struct sym **s;
596
597         /*
598          * Get area and symbol lists
599          */
600         a = hp->a_list;
601         s = hp->s_list;
602
603         /*
604          * Verify Area Mode
605          */
606         if (eval() != (R_WORD | R_AREA) || eval()) {
607                 fprintf(stderr, "P input error\n");
608                 lkerr++;
609         }
610
611         /*
612          * Get area pointer
613          */
614         aindex = evword();
615         if (aindex >= hp->h_narea) {
616                 fprintf(stderr, "P area error\n");
617                 lkerr++;
618                 return;
619         }
620
621         /*
622          * Do remaining relocations
623          */
624         while (more()) {
625                 mode = eval();
626                 rtp = eval();
627                 rindex = evword();
628
629                 /*
630                  * R_SYM or R_AREA references
631                  */
632                 if (mode & R_SYM) {
633                         if (rindex >= hp->h_nglob) {
634                                 fprintf(stderr, "P symbol error\n");
635                                 lkerr++;
636                                 return;
637                         }
638                         relv = symval(s[rindex]);
639                 } else {
640                         if (rindex >= hp->h_narea) {
641                                 fprintf(stderr, "P area error\n");
642                                 lkerr++;
643                                 return;
644                         }
645                         relv = a[rindex]->a_addr;
646                 }
647                 adw_w(relv, rtp);
648         }
649
650         /*
651          * Paged values
652          */
653         aindex = adw_w(0,2);
654         if (aindex >= hp->h_narea) {
655                 fprintf(stderr, "P area error\n");
656                 lkerr++;
657                 return;
658         }
659         sdp.s_areax = a[aindex];
660         sdp.s_area = sdp.s_areax->a_bap;
661         sdp.s_addr = adw_w(0,4);
662         if (sdp.s_area->a_addr & 0xFF || sdp.s_addr & 0xFF)
663                 relerp("Page Definition Boundary Error");
664 }
665
666 /*)Function     VOID    rele()
667  *
668  *      The function rele() closes all open output files
669  *      at the end of the linking process.
670  *
671  *      local variable:
672  *              none
673  *
674  *      global variables:
675  *              int     oflag           output type flag
676  *              int     uflag           relocation listing flag
677  *
678  *      called functions:
679  *              VOID    ihx()           lkihx.c
680  *              VOID    lkulist()       lklist.c
681  *              VOID    s19()           lks19.c
682  *
683  *      side effects:
684  *              All open output files are closed.
685  *
686  */
687
688 VOID
689 rele()
690 {
691         if (uflag != 0) {
692                 lkulist(0);
693         }
694         if (oflag == 1) {
695                 ihx(0);
696         } else
697         if (oflag == 2) {
698                 s19(0);
699         }
700 }
701
702 /*)Function     addr_t          evword()
703  *
704  *      The function evword() combines two byte values
705  *      into a single word value.
706  *
707  *      local variable:
708  *              addr_t  v               temporary evaluation variable
709  *
710  *      global variables:
711  *              hilo                    byte ordering parameter
712  *
713  *      called functions:
714  *              int     eval()          lkeval.c
715  *
716  *      side effects:
717  *              Relocation text line is scanned to combine
718  *              two byte values into a single word value.
719  *
720  */
721
722 addr_t
723 evword()
724 {
725         register addr_t v;
726
727         if (hilo) {
728                 v =  (eval() << 8);
729                 v +=  eval();
730         } else {
731                 v =   eval();
732                 v += (eval() << 8);
733         }
734         return(v);
735 }
736
737 /*)Function     addr_t          adb_b(v, i)
738  *
739  *              int     v               value to add to byte
740  *              int     i               rtval[] index
741  *
742  *      The function adb_b() adds the value of v to
743  *      the single byte value contained in rtval[i].
744  *      The new value of rtval[i] is returned.
745  *
746  *      local variable:
747  *              none
748  *
749  *      global variables:
750  *              none
751  *
752  *      called functions:
753  *              none
754  *
755  *      side effects:
756  *              The value of rtval[] is changed.
757  *
758  */
759
760 addr_t
761 adb_b(v, i)
762 register addr_t v;
763 register int i;
764 {
765         return(rtval[i] += v);
766 }
767
768 /*)Function     addr_t          adb_lo(v, i)
769  *
770  *              int     v               value to add to byte
771  *              int     i               rtval[] index
772  *
773  *      The function adb_lo() adds the value of v to the
774  *      double byte value contained in rtval[i] and rtval[i+1].
775  *      The new value of rtval[i] / rtval[i+1] is returned.
776  *      The MSB rtflg[] is cleared.
777  *
778  *      local variable:
779  *              addr_t  j               temporary evaluation variable
780  *
781  *      global variables:
782  *              hilo                    byte ordering parameter
783  *
784  *      called functions:
785  *              none
786  *
787  *      side effects:
788  *              The value of rtval[] is changed.
789  *              The rtflg[] value corresponding to the
790  *              MSB of the word value is cleared to reflect
791  *              the fact that the LSB is the selected byte.
792  *
793  */
794
795 addr_t
796 adb_lo(v, i)
797 addr_t  v;
798 int     i;
799 {
800         register addr_t j;
801
802         j = adw_w(v, i);
803         /*
804          * Remove Hi byte
805          */
806         if (hilo) {
807                 rtflg[i] = 0;
808         } else {
809                 rtflg[i+1] = 0;
810         }
811         return (j);
812 }
813
814 /*)Function     addr_t          adb_hi(v, i)
815  *
816  *              int     v               value to add to byte
817  *              int     i               rtval[] index
818  *
819  *      The function adb_hi() adds the value of v to the
820  *      double byte value contained in rtval[i] and rtval[i+1].
821  *      The new value of rtval[i] / rtval[i+1] is returned.
822  *      The LSB rtflg[] is cleared.
823  *
824  *      local variable:
825  *              addr_t  j               temporary evaluation variable
826  *
827  *      global variables:
828  *              hilo                    byte ordering parameter
829  *
830  *      called functions:
831  *              none
832  *
833  *      side effects:
834  *              The value of rtval[] is changed.
835  *              The rtflg[] value corresponding to the
836  *              LSB of the word value is cleared to reflect
837  *              the fact that the MSB is the selected byte.
838  *
839  */
840
841 addr_t
842 adb_hi(v, i)
843 addr_t  v;
844 int     i;
845 {
846         register addr_t j;
847
848         j = adw_w(v, i);
849         /*
850          * Remove Lo byte
851          */
852         if (hilo) {
853                 rtflg[i+1] = 0;
854         } else {
855                 rtflg[i] = 0;
856         }
857         return (j);
858 }
859
860 /*)Function     addr_t          adw_w(v, i)
861  *
862  *              int     v               value to add to word
863  *              int     i               rtval[] index
864  *
865  *      The function adw_w() adds the value of v to the
866  *      word value contained in rtval[i] and rtval[i+1].
867  *      The new value of rtval[i] / rtval[i+1] is returned.
868  *
869  *      local variable:
870  *              addr_t  j               temporary evaluation variable
871  *
872  *      global variables:
873  *              hilo                    byte ordering parameter
874  *
875  *      called functions:
876  *              none
877  *
878  *      side effects:
879  *              The word value of rtval[] is changed.
880  *
881  */
882
883 addr_t
884 adw_w(v, i)
885 register addr_t v;
886 register int i;
887 {
888         register addr_t j;
889
890         if (hilo) {
891                 j = v + (rtval[i] << 8) + (rtval[i+1] & 0xff);
892                 rtval[i] = (j >> 8) & 0xff;
893                 rtval[i+1] = j & 0xff;
894         } else {
895                 j = v + (rtval[i] & 0xff) + (rtval[i+1] << 8);
896                 rtval[i] = j & 0xff;
897                 rtval[i+1] = (j >> 8) & 0xff;
898         }
899         return(j);
900 }
901
902 /*)Function     addr_t          adw_24(v, i)
903  *
904  *              int     v               value to add to word
905  *              int     i               rtval[] index
906  *
907  *      The function adw_w() adds the value of v to the
908  *      24 bit value contained in rtval[i] - rtval[i+2].
909  *      The new value of rtval[i] - rtval[i+2] is returned.
910  *
911  *      local variable:
912  *              addr_t  j               temporary evaluation variable
913  *
914  *      global variables:
915  *              hilo                    byte ordering parameter
916  *
917  *      called functions:
918  *              none
919  *
920  *      side effects:
921  *              The word value of rtval[] is changed.
922  *
923  */
924 addr_t
925 adw_24(addr_t v, int i)
926 {
927         register addr_t j;
928
929         if (hilo) {
930                 j = v + ((rtval[i] & 0xff) << 16) 
931                       + ((rtval[i+1] & 0xff) << 8)
932                       + (rtval[i+2] & 0xff);
933                 rtval[i] = (j >> 16) & 0xff;
934                 rtval[i+1] = (j >> 8) & 0xff;
935                 rtval[i+2] = j & 0xff;
936         } else {
937                 j = v + (rtval[i] & 0xff) 
938                       + ((rtval[i+1] & 0xff) << 8)
939                       + ((rtval[i+2] & 0xff) << 16);
940                 rtval[i] = j & 0xff;
941                 rtval[i+1] = (j >> 8) & 0xff;
942                 rtval[i+2] = (j >> 16) & 0xff;
943         }
944         return(j);
945 }
946
947 /*)Function     addr_t          adw_lo(v, i)
948  *
949  *              int     v               value to add to byte
950  *              int     i               rtval[] index
951  *
952  *      The function adw_lo() adds the value of v to the
953  *      double byte value contained in rtval[i] and rtval[i+1].
954  *      The new value of rtval[i] / rtval[i+1] is returned.
955  *      The MSB rtval[] is zeroed.
956  *
957  *      local variable:
958  *              addr_t  j               temporary evaluation variable
959  *
960  *      global variables:
961  *              hilo                    byte ordering parameter
962  *
963  *      called functions:
964  *              none
965  *
966  *      side effects:
967  *              The value of rtval[] is changed.
968  *              The MSB of the word value is cleared to reflect
969  *              the fact that the LSB is the selected byte.
970  *
971  */
972
973 addr_t
974 adw_lo(v, i)
975 addr_t  v;
976 int     i;
977 {
978         register addr_t j;
979
980         j = adw_w(v, i);
981         /*
982          * Clear Hi byte
983          */
984         if (hilo) {
985                 rtval[i] = 0;
986         } else {
987                 rtval[i+1] = 0;
988         }
989         return (j);
990 }
991
992 /*)Function     addr_t          adw_hi(v, i)
993  *
994  *              int     v               value to add to byte
995  *              int     i               rtval[] index
996  *
997  *      The function adw_hi() adds the value of v to the
998  *      double byte value contained in rtval[i] and rtval[i+1].
999  *      The new value of rtval[i] / rtval[i+1] is returned.
1000  *      The MSB and LSB values are interchanged.
1001  *      The MSB rtval[] is zeroed.
1002  *
1003  *      local variable:
1004  *              addr_t  j               temporary evaluation variable
1005  *
1006  *      global variables:
1007  *              hilo                    byte ordering parameter
1008  *
1009  *      called functions:
1010  *              none
1011  *
1012  *      side effects:
1013  *              The value of rtval[] is changed.
1014  *              The MSB and LSB values are interchanged and
1015  *              then the MSB cleared.
1016  *
1017  */
1018
1019 addr_t
1020 adw_hi(v, i)
1021 addr_t  v;
1022 int     i;
1023 {
1024         register addr_t j;
1025
1026         j = adw_w(v, i);
1027         /*
1028          * LSB = MSB, Clear MSB
1029          */
1030         if (hilo) {
1031                 rtval[i+1] = rtval[i];
1032                 rtval[i] = 0;
1033         } else {
1034                 rtval[i] = rtval[i+1];
1035                 rtval[i+1] = 0;
1036         }
1037         return (j);
1038 }
1039
1040 /*)Function     VOID    relerr(str)
1041  *
1042  *              char    *str            error string
1043  *
1044  *      The function relerr() outputs the error string to
1045  *      stderr and to the map file (if it is open).
1046  *
1047  *      local variable:
1048  *              none
1049  *
1050  *      global variables:
1051  *              FILE    *mfp            handle for the map file
1052  *
1053  *      called functions:
1054  *              VOID    errdmp()        lkrloc.c
1055  *
1056  *      side effects:
1057  *              Error message inserted into map file.
1058  *
1059  */
1060
1061 VOID
1062 relerr(str)
1063 char *str;
1064 {
1065         errdmp(stderr, str);
1066         if (mfp)
1067                 errdmp(mfp, str);
1068 }
1069
1070 /*)Function     VOID    errdmp(fptr, str)
1071  *
1072  *              FILE    *fptr           output file handle
1073  *              char    *str            error string
1074  *
1075  *      The function errdmp() outputs the error string str
1076  *      to the device specified by fptr.  Additional information
1077  *      is output about the definition and referencing of
1078  *      the symbol / area error.
1079  *
1080  *      local variable:
1081  *              int     mode            error mode
1082  *              int     aindex          area index
1083  *              int     lkerr           error flag
1084  *              int     rindex          error index
1085  *              sym     **s             pointer to array of symbol pointers
1086  *              areax   **a             pointer to array of area pointers
1087  *              areax   *raxp           error area extension pointer
1088  *
1089  *      global variables:
1090  *              sdp     sdp             base page structure
1091  *
1092  *      called functions:
1093  *              int     fprintf()       c_library
1094  *              VOID    prntval()       lkrloc.c
1095  *
1096  *      side effects:
1097  *              Error reported.
1098  *
1099  */
1100
1101 VOID
1102 errdmp(fptr, str)
1103 FILE *fptr;
1104 char *str;
1105 {
1106         int mode, aindex, rindex;
1107         struct sym **s;
1108         struct areax **a;
1109         struct areax *raxp;
1110
1111         a = hp->a_list;
1112         s = hp->s_list;
1113
1114         mode = rerr.mode;
1115         aindex = rerr.aindex;
1116         rindex = rerr.rindex;
1117
1118         /*
1119          * Print Error
1120          */
1121         fprintf(fptr, "\n?ASlink-Warning-%s", str);
1122         lkerr++;
1123
1124         /*
1125          * Print symbol if symbol based
1126          */
1127         if (mode & R_SYM) {
1128                 fprintf(fptr, " for symbol %s\n",
1129                         &s[rindex]->s_id[0]);
1130         } else {
1131                 fprintf(fptr, "\n");
1132         }
1133
1134         /*
1135          * Print Ref Info
1136          */
1137         fprintf(fptr,
1138                 "         file        module      area        offset\n");
1139         fprintf(fptr,
1140                 "  Refby  %-8.8s    %-8.8s    %-8.8s    ",
1141                         hp->h_lfile->f_idp,
1142                         &hp->m_id[0],
1143                         &a[aindex]->a_bap->a_id[0]);
1144         prntval(fptr, rerr.rtbase);
1145
1146         /*
1147          * Print Def Info
1148          */
1149         if (mode & R_SYM) {
1150                 raxp = s[rindex]->s_axp;
1151         } else {
1152                 raxp = a[rindex];
1153         }
1154         fprintf(fptr,
1155                 "  Defin  %-8.8s    %-8.8s    %-8.8s    ",
1156                         raxp->a_bhp->h_lfile->f_idp,
1157                         &raxp->a_bhp->m_id[0],
1158                         &raxp->a_bap->a_id[0]);
1159         if (mode & R_SYM) {
1160                 prntval(fptr, s[rindex]->s_addr);
1161         } else {
1162                 prntval(fptr, rerr.rval);
1163         }
1164 }
1165
1166 /*)Function     VOID prntval(fptr, v)
1167  *
1168  *              FILE    *fptr   output file handle
1169  *              addr_t  v               value to output
1170  *
1171  *      The function prntval() outputs the value v, in the
1172  *      currently selected radix, to the device specified
1173  *      by fptr.
1174  *
1175  *      local variable:
1176  *              none
1177  *
1178  *      global variables:
1179  *              int     xflag           current radix
1180  *
1181  *      called functions:
1182  *              int     fprintf()       c_library
1183  *
1184  *      side effects:
1185  *              none
1186  *
1187  */
1188
1189 VOID
1190 prntval(fptr, v)
1191 FILE *fptr;
1192 addr_t v;
1193 {
1194         if (xflag == 0) {
1195                 fprintf(fptr, "%04X\n", v);
1196         } else
1197         if (xflag == 1) {
1198                 fprintf(fptr, "%06o\n", v);
1199         } else
1200         if (xflag == 2) {
1201                 fprintf(fptr, "%05u\n", v);
1202         }
1203 }
1204
1205 /*)Function     VOID    relerp(str)
1206  *
1207  *              char    *str            error string
1208  *
1209  *      The function relerp() outputs the paging error string to
1210  *      stderr and to the map file (if it is open).
1211  *
1212  *      local variable:
1213  *              none
1214  *
1215  *      global variables:
1216  *              FILE    *mfp            handle for the map file
1217  *
1218  *      called functions:
1219  *              VOID    erpdmp()        lkrloc.c
1220  *
1221  *      side effects:
1222  *              Error message inserted into map file.
1223  *
1224  */
1225
1226 VOID
1227 relerp(str)
1228 char *str;
1229 {
1230         erpdmp(stderr, str);
1231         if (mfp)
1232                 erpdmp(mfp, str);
1233 }
1234
1235 /*)Function     VOID    erpdmp(fptr, str)
1236  *
1237  *              FILE    *fptr           output file handle
1238  *              char    *str            error string
1239  *
1240  *      The function erpdmp() outputs the error string str
1241  *      to the device specified by fptr.
1242  *
1243  *      local variable:
1244  *              head    *thp            pointer to head structure
1245  *
1246  *      global variables:
1247  *              int             lkerr           error flag
1248  *              sdp             sdp                     base page structure
1249  *
1250  *      called functions:
1251  *              int     fprintf()               c_library
1252  *              VOID    prntval()       lkrloc.c
1253  *
1254  *      side effects:
1255  *              Error reported.
1256  *
1257  */
1258
1259 VOID
1260 erpdmp(fptr, str)
1261 FILE *fptr;
1262 char *str;
1263 {
1264         register struct head *thp;
1265
1266         thp = sdp.s_areax->a_bhp;
1267
1268         /*
1269          * Print Error
1270          */
1271         fprintf(fptr, "\n?ASlink-Warning-%s\n", str);
1272         lkerr++;
1273
1274         /*
1275          * Print PgDef Info
1276          */
1277         fprintf(fptr,
1278                 "         file        module      pgarea      pgoffset\n");
1279         fprintf(fptr,
1280                 "  PgDef  %-8.8s    %-8.8s    %-8.8s    ",
1281                         thp->h_lfile->f_idp,
1282                         &thp->m_id[0],
1283                         &sdp.s_area->a_id[0]);
1284         prntval(fptr, sdp.s_area->a_addr + sdp.s_addr);
1285 }