4 * (C) Copyright 1989-1995
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
24 * The module lkrloc.c contains the functions which
25 * perform the relocation calculations.
27 * lkrloc.c contains the following functions:
46 * lkrloc.c the local variable errmsg[].
50 /*)Function VOID reloc(c)
54 * The function reloc() calls a particular relocation
55 * function determined by the process code.
61 * int lkerr error flag
64 * int fprintf() c_library
65 * VOID rele() lkrloc.c
66 * VOID relp() lkrloc.c
67 * VOID relr() lkrloc.c
68 * VOId relt() lkrloc.c
71 * Refer to the called relocation functions.
98 fprintf(stderr, "Undefined Relocation Operation\n");
106 /*)Function VOID relt()
108 * The function relt() evaluates a T line read by
109 * the linker. Each byte value read is saved in the
110 * rtval[] array, rtflg[] is set, and the number of
111 * evaluations is maintained in rtcnt.
115 * T xx xx nn nn nn nn nn ...
118 * In: "T n0 n1 n2 n3 ... nn"
120 * Out: 0 1 2 .. rtcnt
121 * +----+----+----+----+----+
122 * rtval | n0 | n1 | n2 | .. | nn |
123 * +----+----+----+----+----+
124 * rtflag| 1 | 1 | 1 | 1 | 1 |
125 * +----+----+----+----+----+
127 * The T line contains the assembled code output by the assem-
128 * bler with xx xx being the offset address from the current area
129 * base address and nn being the assembled instructions and data in
136 * int rtcnt number of values evaluated
137 * int rtflg[] array of evaluation flags
138 * int rtval[] array of evaluation values
141 * int eval() lkeval.c
145 * Linker input T line evaluated.
155 rtval[rtcnt] = eval();
162 /*)Function VOID relr()
164 * The function relr() evaluates a R line read by
165 * the linker. The R line data is combined with the
166 * previous T line data to perform the relocation of
167 * code and data bytes. The S19 / IHX output and
168 * translation of the LST files to RST files may be
173 * R 0 0 nn nn n1 n2 xx xx ...
175 * The R line provides the relocation information to the linker.
176 * The nn nn value is the current area index, i.e. which area the
177 * current values were assembled. Relocation information is en-
178 * coded in groups of 4 bytes:
180 * 1. n1 is the relocation mode and object format
181 * 1. bit 0 word(0x00)/byte(0x01)
182 * 2. bit 1 relocatable area(0x00)/symbol(0x02)
183 * 3. bit 2 normal(0x00)/PC relative(0x04) relocation
184 * 4. bit 3 1-byte(0x00)/2-byte(0x08) object format for
186 * 5. bit 4 signed(0x00)/unsigned(0x10) byte data
187 * 6. bit 5 normal(0x00)/page '0'(0x20) reference
188 * 7. bit 6 normal(0x00)/page 'nnn'(0x40) reference
190 * 2. n2 is a byte index into the corresponding (i.e. pre-
191 * ceeding) T line data (i.e. a pointer to the data to be
192 * updated by the relocation). The T line data may be
193 * 1-byte or 2-byte byte data format or 2-byte word
196 * 3. xx xx is the area/symbol index for the area/symbol be-
197 * ing referenced. the corresponding area/symbol is found
198 * in the header area/symbol lists.
200 * The groups of 4 bytes are repeated for each item requiring relo-
201 * cation in the preceeding T line.
204 * areax **a pointer to array of area pointers
205 * int aindex area index
206 * char *errmsg[] array of pointers to error strings
207 * int error error code
208 * int lkerr error flag
209 * int mode relocation mode
210 * adrr_t paga paging base area address
211 * addr_t pags paging symbol address
212 * addr_t pc relocated base address
213 * addr_t r PCR relocation value
214 * addr_t reli relocation initial value
215 * addr_t relv relocation final value
216 * int rindex symbol / area index
217 * addr_t rtbase base code address
218 * addr_t rtofst rtval[] index offset
219 * int rtp index into T data
220 * sym **s pointer to array of symbol pointers
223 * head *hp pointer to the head structure
224 * rerr rerr linker error structure
225 * FILE *stderr standard error device
228 * addr_t adb_b() lkrloc.c
229 * addr_t adb_lo() lkrloc.c
230 * addr_t adb_hi() lkrloc.c
231 * addr_t adw_w() lkrloc.c
232 * addr_t evword() lkrloc.c
233 * int eval() lkeval.c
234 * int fprintf() c_library
236 * int lkulist lklist.c
238 * VOID relerr() lkrloc.c
240 * int symval() lksym.c
243 * The R and T lines are combined to produce
244 * relocated code and data. Output S19 / IHX
245 * and relocated listing files may be produced.
253 register addr_t reli, relv;
254 int aindex, rindex, rtp, error;
255 addr_t r, rtbase, rtofst, paga, pags, pc;
260 * Get area and symbol lists
268 if (eval() != (R_WORD | R_AREA) || eval()) {
269 fprintf(stderr, "R input error\n");
277 if (aindex >= hp->h_narea) {
278 fprintf(stderr, "R area error\n");
286 rtbase = adw_w(0, 0);
292 pc = adw_w(a[aindex]->a_addr, 0);
295 * Do remaining relocations
304 * R_SYM or R_AREA references
307 if (rindex >= hp->h_nglob) {
308 fprintf(stderr, "R symbol error\n");
312 reli = symval(s[rindex]);
314 if (rindex >= hp->h_narea) {
315 fprintf(stderr, "R area error\n");
319 reli = a[rindex]->a_addr;
327 reli -= (pc + (rtp-rtofst) + 1);
329 reli -= (pc + (rtp-rtofst) + 2);
334 * R_PAG0 or R_PAG addressing
336 if (mode & (R_PAG0|R_PAG)) {
337 paga = sdp.s_area->a_addr;
343 * R_BYTE or R_WORD operation
348 relv = adb_hi(reli, rtp);
350 relv = adb_lo(reli, rtp);
353 relv = adb_b(reli, rtp);
355 } else if (mode & R_J11) {
356 /* JLH: 11 bit jump destination for 8051. Forms
357 / two byte instruction with op-code bits
359 / rtp points at 3 byte locus: first two
360 / will get the instructiion. third one
364 /* Calculate absolute destination
365 / relv must be on same 2K page as pc
367 relv = adw_w(reli, rtp);
369 if ((relv & ~0x7ff) != ((pc + rtp - rtofst) & ~0x7ff)) {
373 /* Merge MSB (byte 0) with op-code, ignoring
374 / top 5 bits of address. Then hide the op-code
376 rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+2];
381 * R_WORD with the R_BYT2 mode is flagged
382 * as an 'r' error by the assembler,
383 * but it is processed here anyway.
386 /* JLH: R_WORD and R_BYT2 together is now subsumed by R_J11 */
390 relv = adw_hi(reli, rtp);
392 relv = adw_lo(reli, rtp);
395 relv = adw_w(reli, rtp);
398 relv = adw_w(reli, rtp);
403 * R_BYTE with R_BYT2 offset adjust
412 * Unsigned Byte Checking
414 if (mode & R_USGN && mode & R_BYTE && relv & ~0xFF)
418 * PCR Relocation Error Checking
420 if (mode & R_PCR && mode & R_BYTE) {
422 if (r != (addr_t) ~0x7F && r != 0)
427 * Page Relocation Error Checking
429 /* if (mode & R_PAG0 && (relv & ~0xFF || paga || pags))
431 if (mode & R_PAG && (relv & ~0xFF))
438 rerr.aindex = aindex;
440 rerr.rtbase = rtbase + rtp - rtofst - 1;
441 rerr.rindex = rindex;
442 rerr.rval = relv - reli;
443 relerr(errmsg[error-1]);
450 /* JLH: output only if data (beyond two byte address) */
451 if ((oflag == 1) && (rtcnt > 2)) {
454 if ((oflag == 2) && (rtcnt > 2)) {
460 "Unsigned Byte error",
461 "Byte PCR relocation error",
462 "Page0 relocation error",
463 "Page Mode relocation error"
467 /*)Function VOID relp()
469 * The function relp() evaluates a P line read by
470 * the linker. The P line data is combined with the
471 * previous T line data to set the base page address
472 * and test the paging boundary and length.
476 * P 0 0 nn nn n1 n2 xx xx
478 * The P line provides the paging information to the linker as
479 * specified by a .setdp directive. The format of the relocation
480 * information is identical to that of the R line. The correspond-
481 * ing T line has the following information:
482 * T xx xx aa aa bb bb
484 * Where aa aa is the area reference number which specifies the
485 * selected page area and bb bb is the base address of the page.
486 * bb bb will require relocation processing if the 'n1 n2 xx xx' is
487 * specified in the P line. The linker will verify that the base
488 * address is on a 256 byte boundary and that the page length of an
489 * area defined with the PAG type is not larger than 256 bytes.
492 * areax **a pointer to array of area pointers
493 * int aindex area index
494 * int mode relocation mode
495 * addr_t relv relocation value
496 * int rindex symbol / area index
497 * int rtp index into T data
498 * sym **s pointer to array of symbol pointers
501 * head *hp pointer to the head structure
502 * int lkerr error flag
503 * sdp sdp base page structure
504 * FILE *stderr standard error device
507 * addr_t adw_w() lkrloc.c
508 * addr_t evword() lkrloc.c
509 * int eval() lkeval.c
510 * int fprintf() c_library
512 * int symval() lksym.c
515 * The P and T lines are combined to set
516 * the base page address and report any
524 register int aindex, rindex;
531 * Get area and symbol lists
539 if (eval() != (R_WORD | R_AREA) || eval()) {
540 fprintf(stderr, "P input error\n");
548 if (aindex >= hp->h_narea) {
549 fprintf(stderr, "P area error\n");
555 * Do remaining relocations
563 * R_SYM or R_AREA references
566 if (rindex >= hp->h_nglob) {
567 fprintf(stderr, "P symbol error\n");
571 relv = symval(s[rindex]);
573 if (rindex >= hp->h_narea) {
574 fprintf(stderr, "P area error\n");
578 relv = a[rindex]->a_addr;
587 if (aindex >= hp->h_narea) {
588 fprintf(stderr, "P area error\n");
592 sdp.s_areax = a[aindex];
593 sdp.s_area = sdp.s_areax->a_bap;
594 sdp.s_addr = adw_w(0,4);
595 if (sdp.s_area->a_addr & 0xFF || sdp.s_addr & 0xFF)
596 relerp("Page Definition Boundary Error");
599 /*)Function VOID rele()
601 * The function rele() closes all open output files
602 * at the end of the linking process.
608 * int oflag output type flag
609 * int uflag relocation listing flag
613 * VOID lkulist() lklist.c
617 * All open output files are closed.
635 /*)Function addr_t evword()
637 * The function evword() combines two byte values
638 * into a single word value.
641 * addr_t v temporary evaluation variable
644 * hilo byte ordering parameter
647 * int eval() lkeval.c
650 * Relocation text line is scanned to combine
651 * two byte values into a single word value.
670 /*)Function addr_t adb_b(v, i)
672 * int v value to add to byte
673 * int i rtval[] index
675 * The function adb_b() adds the value of v to
676 * the single byte value contained in rtval[i].
677 * The new value of rtval[i] is returned.
689 * The value of rtval[] is changed.
698 return(rtval[i] += v);
701 /*)Function addr_t adb_lo(v, i)
703 * int v value to add to byte
704 * int i rtval[] index
706 * The function adb_lo() adds the value of v to the
707 * double byte value contained in rtval[i] and rtval[i+1].
708 * The new value of rtval[i] / rtval[i+1] is returned.
709 * The MSB rtflg[] is cleared.
712 * addr_t j temporary evaluation variable
715 * hilo byte ordering parameter
721 * The value of rtval[] is changed.
722 * The rtflg[] value corresponding to the
723 * MSB of the word value is cleared to reflect
724 * the fact that the LSB is the selected byte.
747 /*)Function addr_t adb_hi(v, i)
749 * int v value to add to byte
750 * int i rtval[] index
752 * The function adb_hi() adds the value of v to the
753 * double byte value contained in rtval[i] and rtval[i+1].
754 * The new value of rtval[i] / rtval[i+1] is returned.
755 * The LSB rtflg[] is cleared.
758 * addr_t j temporary evaluation variable
761 * hilo byte ordering parameter
767 * The value of rtval[] is changed.
768 * The rtflg[] value corresponding to the
769 * LSB of the word value is cleared to reflect
770 * the fact that the MSB is the selected byte.
793 /*)Function addr_t adw_w(v, i)
795 * int v value to add to word
796 * int i rtval[] index
798 * The function adw_w() adds the value of v to the
799 * word value contained in rtval[i] and rtval[i+1].
800 * The new value of rtval[i] / rtval[i+1] is returned.
803 * addr_t j temporary evaluation variable
806 * hilo byte ordering parameter
812 * The word value of rtval[] is changed.
824 j = v + (rtval[i] << 8) + (rtval[i+1] & 0xff);
825 rtval[i] = (j >> 8) & 0xff;
826 rtval[i+1] = j & 0xff;
828 j = v + (rtval[i] & 0xff) + (rtval[i+1] << 8);
830 rtval[i+1] = (j >> 8) & 0xff;
835 /*)Function addr_t adw_lo(v, i)
837 * int v value to add to byte
838 * int i rtval[] index
840 * The function adw_lo() adds the value of v to the
841 * double byte value contained in rtval[i] and rtval[i+1].
842 * The new value of rtval[i] / rtval[i+1] is returned.
843 * The MSB rtval[] is zeroed.
846 * addr_t j temporary evaluation variable
849 * hilo byte ordering parameter
855 * The value of rtval[] is changed.
856 * The MSB of the word value is cleared to reflect
857 * the fact that the LSB is the selected byte.
880 /*)Function addr_t adw_hi(v, i)
882 * int v value to add to byte
883 * int i rtval[] index
885 * The function adw_hi() adds the value of v to the
886 * double byte value contained in rtval[i] and rtval[i+1].
887 * The new value of rtval[i] / rtval[i+1] is returned.
888 * The MSB and LSB values are interchanged.
889 * The MSB rtval[] is zeroed.
892 * addr_t j temporary evaluation variable
895 * hilo byte ordering parameter
901 * The value of rtval[] is changed.
902 * The MSB and LSB values are interchanged and
903 * then the MSB cleared.
916 * LSB = MSB, Clear MSB
919 rtval[i+1] = rtval[i];
922 rtval[i] = rtval[i+1];
928 /*)Function VOID relerr(str)
930 * char *str error string
932 * The function relerr() outputs the error string to
933 * stderr and to the map file (if it is open).
939 * FILE *mfp handle for the map file
942 * VOID errdmp() lkrloc.c
945 * Error message inserted into map file.
958 /*)Function VOID errdmp(fptr, str)
960 * FILE *fptr output file handle
961 * char *str error string
963 * The function errdmp() outputs the error string str
964 * to the device specified by fptr. Additional information
965 * is output about the definition and referencing of
966 * the symbol / area error.
969 * int mode error mode
970 * int aindex area index
971 * int lkerr error flag
972 * int rindex error index
973 * sym **s pointer to array of symbol pointers
974 * areax **a pointer to array of area pointers
975 * areax *raxp error area extension pointer
978 * sdp sdp base page structure
981 * int fprintf() c_library
982 * VOID prntval() lkrloc.c
994 int mode, aindex, rindex;
1003 aindex = rerr.aindex;
1004 rindex = rerr.rindex;
1009 fprintf(fptr, "\n?ASlink-Warning-%s", str);
1013 * Print symbol if symbol based
1016 fprintf(fptr, " for symbol %s\n",
1017 &s[rindex]->s_id[0]);
1019 fprintf(fptr, "\n");
1026 " file module area offset\n");
1028 " Refby %-8.8s %-8.8s %-8.8s ",
1031 &a[aindex]->a_bap->a_id[0]);
1032 prntval(fptr, rerr.rtbase);
1038 raxp = s[rindex]->s_axp;
1043 " Defin %-8.8s %-8.8s %-8.8s ",
1044 raxp->a_bhp->h_lfile->f_idp,
1045 &raxp->a_bhp->m_id[0],
1046 &raxp->a_bap->a_id[0]);
1048 prntval(fptr, s[rindex]->s_addr);
1050 prntval(fptr, rerr.rval);
1054 /*)Function VOID prntval(fptr, v)
1056 * FILE *fptr output file handle
1057 * addr_t v value to output
1059 * The function prntval() outputs the value v, in the
1060 * currently selected radix, to the device specified
1067 * int xflag current radix
1070 * int fprintf() c_library
1083 fprintf(fptr, "%04X\n", v);
1086 fprintf(fptr, "%06o\n", v);
1089 fprintf(fptr, "%05u\n", v);
1093 /*)Function VOID relerp(str)
1095 * char *str error string
1097 * The function relerp() outputs the paging error string to
1098 * stderr and to the map file (if it is open).
1104 * FILE *mfp handle for the map file
1107 * VOID erpdmp() lkrloc.c
1110 * Error message inserted into map file.
1118 erpdmp(stderr, str);
1123 /*)Function VOID erpdmp(fptr, str)
1125 * FILE *fptr output file handle
1126 * char *str error string
1128 * The function erpdmp() outputs the error string str
1129 * to the device specified by fptr.
1132 * head *thp pointer to head structure
1135 * int lkerr error flag
1136 * sdp sdp base page structure
1139 * int fprintf() c_library
1140 * VOID prntval() lkrloc.c
1152 register struct head *thp;
1154 thp = sdp.s_areax->a_bhp;
1159 fprintf(fptr, "\n?ASlink-Warning-%s\n", str);
1166 " file module pgarea pgoffset\n");
1168 " PgDef %-8.8s %-8.8s %-8.8s ",
1169 thp->h_lfile->f_idp,
1171 &sdp.s_area->a_id[0]);
1172 prntval(fptr, sdp.s_area->a_addr + sdp.s_addr);