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