4 * (C) Copyright 1989-1995
13 * Extensions: P. Felber
25 * The module lkrloc.c contains the functions which
26 * perform the relocation calculations.
28 * lkrloc.c contains the following functions:
47 * lkrloc.c the local variable errmsg[].
51 /*)Function VOID reloc(c)
55 * The function reloc() calls a particular relocation
56 * function determined by the process code.
62 * int lkerr error flag
65 * int fprintf() c_library
66 * VOID rele() lkrloc.c
67 * VOID relp() lkrloc.c
68 * VOID relr() lkrloc.c
69 * VOId relt() lkrloc.c
72 * Refer to the called relocation functions.
99 fprintf(stderr, "Undefined Relocation Operation\n");
107 /*)Function VOID relt()
109 * The function relt() evaluates a T line read by
110 * the linker. Each byte value read is saved in the
111 * rtval[] array, rtflg[] is set, and the number of
112 * evaluations is maintained in rtcnt.
116 * T xx xx nn nn nn nn nn ...
119 * In: "T n0 n1 n2 n3 ... nn"
121 * Out: 0 1 2 .. rtcnt
122 * +----+----+----+----+----+
123 * rtval | n0 | n1 | n2 | .. | nn |
124 * +----+----+----+----+----+
125 * rtflag| 1 | 1 | 1 | 1 | 1 |
126 * +----+----+----+----+----+
128 * The T line contains the assembled code output by the assem-
129 * bler with xx xx being the offset address from the current area
130 * base address and nn being the assembled instructions and data in
137 * int rtcnt number of values evaluated
138 * int rtflg[] array of evaluation flags
139 * int rtval[] array of evaluation values
142 * int eval() lkeval.c
146 * Linker input T line evaluated.
156 rtval[rtcnt] = eval();
163 /*)Function VOID relr()
165 * The function relr() evaluates a R line read by
166 * the linker. The R line data is combined with the
167 * previous T line data to perform the relocation of
168 * code and data bytes. The S19 / IHX output and
169 * translation of the LST files to RST files may be
174 * R 0 0 nn nn n1 n2 xx xx ...
176 * The R line provides the relocation information to the linker.
177 * The nn nn value is the current area index, i.e. which area the
178 * current values were assembled. Relocation information is en-
179 * coded in groups of 4 bytes:
181 * 1. n1 is the relocation mode and object format
182 * 1. bit 0 word(0x00)/byte(0x01)
183 * 2. bit 1 relocatable area(0x00)/symbol(0x02)
184 * 3. bit 2 normal(0x00)/PC relative(0x04) relocation
185 * 4. bit 3 1-byte(0x00)/2-byte(0x08) object format for
187 * 5. bit 4 signed(0x00)/unsigned(0x10) byte data
188 * 6. bit 5 normal(0x00)/page '0'(0x20) reference
189 * 7. bit 6 normal(0x00)/page 'nnn'(0x40) reference
191 * 2. n2 is a byte index into the corresponding (i.e. pre-
192 * ceeding) T line data (i.e. a pointer to the data to be
193 * updated by the relocation). The T line data may be
194 * 1-byte or 2-byte byte data format or 2-byte word
197 * 3. xx xx is the area/symbol index for the area/symbol be-
198 * ing referenced. the corresponding area/symbol is found
199 * in the header area/symbol lists.
201 * The groups of 4 bytes are repeated for each item requiring relo-
202 * cation in the preceeding T line.
205 * areax **a pointer to array of area pointers
206 * int aindex area index
207 * char *errmsg[] array of pointers to error strings
208 * int error error code
209 * int lkerr error flag
210 * int mode relocation mode
211 * adrr_t paga paging base area address
212 * Addr_T pags paging symbol address
213 * Addr_T pc relocated base address
214 * Addr_T r PCR relocation value
215 * Addr_T reli relocation initial value
216 * Addr_T relv relocation final value
217 * int rindex symbol / area index
218 * Addr_T rtbase base code address
219 * Addr_T rtofst rtval[] index offset
220 * int rtp index into T data
221 * sym **s pointer to array of symbol pointers
224 * head *hp pointer to the head structure
225 * rerr rerr linker error structure
226 * FILE *stderr standard error device
229 * Addr_T adb_b() lkrloc.c
230 * Addr_T adb_lo() lkrloc.c
231 * Addr_T adb_hi() lkrloc.c
232 * Addr_T adw_w() lkrloc.c
233 * Addr_T evword() lkrloc.c
234 * int eval() lkeval.c
235 * int fprintf() c_library
237 * int lkulist lklist.c
239 * VOID relerr() lkrloc.c
241 * int symval() lksym.c
244 * The R and T lines are combined to produce
245 * relocated code and data. Output S19 / IHX
246 * and relocated listing files may be produced.
254 register Addr_T reli, relv;
255 int aindex, rindex, rtp, error;
256 Addr_T r, rtbase, rtofst, paga = 0, pags = 0, pc;
261 * Get area and symbol lists
269 if (eval() != (R_WORD | R_AREA) || eval()) {
270 fprintf(stderr, "R input error\n");
278 if (aindex >= hp->h_narea) {
279 fprintf(stderr, "R area error\n");
287 rtbase = adw_w(0, 0);
293 pc = adw_w(a[aindex]->a_addr, 0);
297 char *s = strrchr(a[aindex]->a_bap->a_id, '_');
298 if(s != NULL && isdigit((unsigned char)s[1]))
299 current_rom_bank = atoi(s+1);
301 current_rom_bank = 0;
305 * Do remaining relocations
314 * R_SYM or R_AREA references
317 if (rindex >= hp->h_nglob) {
318 fprintf(stderr, "R symbol error\n");
322 reli = symval(s[rindex]);
324 if (rindex >= hp->h_narea) {
325 fprintf(stderr, "R area error\n");
329 reli = a[rindex]->a_addr;
337 reli -= (pc + (rtp-rtofst) + 1);
339 reli -= (pc + (rtp-rtofst) + 2);
344 * R_PAG0 or R_PAG addressing
346 if (mode & (R_PAG0|R_PAG)) {
347 paga = sdp.s_area->a_addr;
353 * R_BYTE or R_WORD operation
358 relv = adb_hi(reli, rtp);
360 relv = adb_lo(reli, rtp);
363 relv = adb_b(reli, rtp);
367 * R_WORD with the R_BYT2 mode is flagged
368 * as an 'r' error by the assembler,
369 * but it is processed here anyway.
373 relv = adw_hi(reli, rtp);
375 relv = adw_lo(reli, rtp);
378 relv = adw_w(reli, rtp);
383 * R_BYTE with R_BYT2 offset adjust
392 * Unsigned Byte Checking
394 if (mode & R_USGN && mode & R_BYTE && relv & ~0xFF)
398 * PCR Relocation Error Checking
400 if (mode & R_PCR && mode & R_BYTE) {
402 if (r != (Addr_T) ~0x7F && r != 0)
407 * Page Relocation Error Checking
409 if (mode & R_PAG0 && (relv & ~0xFF || paga || pags))
411 if (mode & R_PAG && (relv & ~0xFF))
418 rerr.aindex = aindex;
420 rerr.rtbase = rtbase + rtp - rtofst - 1;
421 rerr.rindex = rindex;
422 rerr.rval = relv - reli;
423 relerr(errmsg[error-1]);
439 #endif /* GAMEGEAR */
448 "Unsigned Byte error",
449 "Byte PCR relocation error",
450 "Page0 relocation error",
451 "Page Mode relocation error"
455 /*)Function VOID relp()
457 * The function relp() evaluates a P line read by
458 * the linker. The P line data is combined with the
459 * previous T line data to set the base page address
460 * and test the paging boundary and length.
464 * P 0 0 nn nn n1 n2 xx xx
466 * The P line provides the paging information to the linker as
467 * specified by a .setdp directive. The format of the relocation
468 * information is identical to that of the R line. The correspond-
469 * ing T line has the following information:
470 * T xx xx aa aa bb bb
472 * Where aa aa is the area reference number which specifies the
473 * selected page area and bb bb is the base address of the page.
474 * bb bb will require relocation processing if the 'n1 n2 xx xx' is
475 * specified in the P line. The linker will verify that the base
476 * address is on a 256 byte boundary and that the page length of an
477 * area defined with the PAG type is not larger than 256 bytes.
480 * areax **a pointer to array of area pointers
481 * int aindex area index
482 * int mode relocation mode
483 * Addr_T relv relocation value
484 * int rindex symbol / area index
485 * int rtp index into T data
486 * sym **s pointer to array of symbol pointers
489 * head *hp pointer to the head structure
490 * int lkerr error flag
491 * sdp sdp base page structure
492 * FILE *stderr standard error device
495 * Addr_T adw_w() lkrloc.c
496 * Addr_T evword() lkrloc.c
497 * int eval() lkeval.c
498 * int fprintf() c_library
500 * int symval() lksym.c
503 * The P and T lines are combined to set
504 * the base page address and report any
512 register int aindex, rindex;
519 * Get area and symbol lists
527 if (eval() != (R_WORD | R_AREA) || eval()) {
528 fprintf(stderr, "P input error\n");
536 if (aindex >= hp->h_narea) {
537 fprintf(stderr, "P area error\n");
543 * Do remaining relocations
551 * R_SYM or R_AREA references
554 if (rindex >= hp->h_nglob) {
555 fprintf(stderr, "P symbol error\n");
559 relv = symval(s[rindex]);
561 if (rindex >= hp->h_narea) {
562 fprintf(stderr, "P area error\n");
566 relv = a[rindex]->a_addr;
575 if (aindex >= hp->h_narea) {
576 fprintf(stderr, "P area error\n");
580 sdp.s_areax = a[aindex];
581 sdp.s_area = sdp.s_areax->a_bap;
582 sdp.s_addr = adw_w(0,4);
583 if (sdp.s_area->a_addr & 0xFF || sdp.s_addr & 0xFF)
584 relerp("Page Definition Boundary Error");
587 /*)Function VOID rele()
589 * The function rele() closes all open output files
590 * at the end of the linking process.
596 * int oflag output type flag
597 * int uflag relocation listing flag
601 * VOID lkulist() lklist.c
605 * All open output files are closed.
625 #endif /* GAMEGEAR */
633 /*)Function Addr_T evword()
635 * The function evword() combines two byte values
636 * into a single word value.
639 * Addr_T v temporary evaluation variable
642 * hilo byte ordering parameter
645 * int eval() lkeval.c
648 * Relocation text line is scanned to combine
649 * two byte values into a single word value.
668 /*)Function Addr_T adb_b(v, i)
670 * int v value to add to byte
671 * int i rtval[] index
673 * The function adb_b() adds the value of v to
674 * the single byte value contained in rtval[i].
675 * The new value of rtval[i] is returned.
687 * The value of rtval[] is changed.
696 return(rtval[i] += v);
699 /*)Function Addr_T adb_lo(v, i)
701 * int v value to add to byte
702 * int i rtval[] index
704 * The function adb_lo() adds the value of v to the
705 * double byte value contained in rtval[i] and rtval[i+1].
706 * The new value of rtval[i] / rtval[i+1] is returned.
707 * The MSB rtflg[] is cleared.
710 * Addr_T j temporary evaluation variable
713 * hilo byte ordering parameter
719 * The value of rtval[] is changed.
720 * The rtflg[] value corresponding to the
721 * MSB of the word value is cleared to reflect
722 * the fact that the LSB is the selected byte.
745 /*)Function Addr_T adb_hi(v, i)
747 * int v value to add to byte
748 * int i rtval[] index
750 * The function adb_hi() adds the value of v to the
751 * double byte value contained in rtval[i] and rtval[i+1].
752 * The new value of rtval[i] / rtval[i+1] is returned.
753 * The LSB rtflg[] is cleared.
756 * Addr_T j temporary evaluation variable
759 * hilo byte ordering parameter
765 * The value of rtval[] is changed.
766 * The rtflg[] value corresponding to the
767 * LSB of the word value is cleared to reflect
768 * the fact that the MSB is the selected byte.
791 /*)Function Addr_T adw_w(v, i)
793 * int v value to add to word
794 * int i rtval[] index
796 * The function adw_w() adds the value of v to the
797 * word value contained in rtval[i] and rtval[i+1].
798 * The new value of rtval[i] / rtval[i+1] is returned.
801 * Addr_T j temporary evaluation variable
804 * hilo byte ordering parameter
810 * The word value of rtval[] is changed.
822 j = v + (rtval[i] << 8) + (rtval[i+1] & 0xff);
823 rtval[i] = (j >> 8) & 0xff;
824 rtval[i+1] = j & 0xff;
826 j = v + (rtval[i] & 0xff) + (rtval[i+1] << 8);
828 rtval[i+1] = (j >> 8) & 0xff;
833 /*)Function Addr_T adw_lo(v, i)
835 * int v value to add to byte
836 * int i rtval[] index
838 * The function adw_lo() adds the value of v to the
839 * double byte value contained in rtval[i] and rtval[i+1].
840 * The new value of rtval[i] / rtval[i+1] is returned.
841 * The MSB rtval[] is zeroed.
844 * Addr_T j temporary evaluation variable
847 * hilo byte ordering parameter
853 * The value of rtval[] is changed.
854 * The MSB of the word value is cleared to reflect
855 * the fact that the LSB is the selected byte.
878 /*)Function Addr_T adw_hi(v, i)
880 * int v value to add to byte
881 * int i rtval[] index
883 * The function adw_hi() adds the value of v to the
884 * double byte value contained in rtval[i] and rtval[i+1].
885 * The new value of rtval[i] / rtval[i+1] is returned.
886 * The MSB and LSB values are interchanged.
887 * The MSB rtval[] is zeroed.
890 * Addr_T j temporary evaluation variable
893 * hilo byte ordering parameter
899 * The value of rtval[] is changed.
900 * The MSB and LSB values are interchanged and
901 * then the MSB cleared.
914 * LSB = MSB, Clear MSB
917 rtval[i+1] = rtval[i];
920 rtval[i] = rtval[i+1];
926 /*)Function VOID relerr(str)
928 * char *str error string
930 * The function relerr() outputs the error string to
931 * stderr and to the map file (if it is open).
937 * FILE *mfp handle for the map file
940 * VOID errdmp() lkrloc.c
943 * Error message inserted into map file.
956 /*)Function VOID errdmp(fptr, str)
958 * FILE *fptr output file handle
959 * char *str error string
961 * The function errdmp() outputs the error string str
962 * to the device specified by fptr. Additional information
963 * is output about the definition and referencing of
964 * the symbol / area error.
967 * int mode error mode
968 * int aindex area index
969 * int lkerr error flag
970 * int rindex error index
971 * sym **s pointer to array of symbol pointers
972 * areax **a pointer to array of area pointers
973 * areax *raxp error area extension pointer
976 * sdp sdp base page structure
979 * int fprintf() c_library
980 * VOID prntval() lkrloc.c
992 int mode, aindex, rindex;
1001 aindex = rerr.aindex;
1002 rindex = rerr.rindex;
1007 fprintf(fptr, "\n?ASlink-Warning-%s", str);
1011 * Print symbol if symbol based
1014 fprintf(fptr, " for symbol %.*s\n",
1015 NCPS, &s[rindex]->s_id[0]);
1017 fprintf(fptr, "\n");
1024 " file module area offset\n");
1026 " Refby %-8.8s %-8.8s %-8.8s ",
1029 &a[aindex]->a_bap->a_id[0]);
1030 prntval(fptr, rerr.rtbase);
1036 raxp = s[rindex]->s_axp;
1041 " Defin %-8.8s %-8.8s %-8.8s ",
1042 raxp->a_bhp->h_lfile->f_idp,
1043 &raxp->a_bhp->m_id[0],
1044 &raxp->a_bap->a_id[0]);
1046 prntval(fptr, s[rindex]->s_addr);
1048 prntval(fptr, rerr.rval);
1052 /*)Function VOID prntval(fptr, v)
1054 * FILE *fptr output file handle
1055 * Addr_T v value to output
1057 * The function prntval() outputs the value v, in the
1058 * currently selected radix, to the device specified
1065 * int xflag current radix
1068 * int fprintf() c_library
1081 fprintf(fptr, "%04X\n", v);
1084 fprintf(fptr, "%06o\n", v);
1087 fprintf(fptr, "%05u\n", v);
1091 /*)Function VOID relerp(str)
1093 * char *str error string
1095 * The function relerp() outputs the paging error string to
1096 * stderr and to the map file (if it is open).
1102 * FILE *mfp handle for the map file
1105 * VOID erpdmp() lkrloc.c
1108 * Error message inserted into map file.
1116 erpdmp(stderr, str);
1121 /*)Function VOID erpdmp(fptr, str)
1123 * FILE *fptr output file handle
1124 * char *str error string
1126 * The function erpdmp() outputs the error string str
1127 * to the device specified by fptr.
1130 * head *thp pointer to head structure
1133 * int lkerr error flag
1134 * sdp sdp base page structure
1137 * int fprintf() c_library
1138 * VOID prntval() lkrloc.c
1150 register struct head *thp;
1152 thp = sdp.s_areax->a_bhp;
1157 fprintf(fptr, "\n?ASlink-Warning-%s\n", str);
1164 " file module pgarea pgoffset\n");
1166 " PgDef %-8.8s %-8.8s %-8.8s ",
1167 thp->h_lfile->f_idp,
1169 &sdp.s_area->a_id[0]);
1170 prntval(fptr, sdp.s_area->a_addr + sdp.s_addr);