4 * (C) Copyright 1989-1995
13 * Extensions: P. Felber
23 * The module lkrloc.c contains the functions which
24 * perform the relocation calculations.
26 * lkrloc.c contains the following functions:
45 * lkrloc.c the local variable errmsg[].
49 /*)Function VOID reloc(c)
53 * The function reloc() calls a particular relocation
54 * function determined by the process code.
60 * int lkerr error flag
63 * int fprintf() c_library
64 * VOID rele() lkrloc.c
65 * VOID relp() lkrloc.c
66 * VOID relr() lkrloc.c
67 * VOId relt() lkrloc.c
70 * Refer to the called relocation functions.
97 fprintf(stderr, "Undefined Relocation Operation\n");
105 /*)Function VOID relt()
107 * The function relt() evaluates a T line read by
108 * the linker. Each byte value read is saved in the
109 * rtval[] array, rtflg[] is set, and the number of
110 * evaluations is maintained in rtcnt.
114 * T xx xx nn nn nn nn nn ...
117 * In: "T n0 n1 n2 n3 ... nn"
119 * Out: 0 1 2 .. rtcnt
120 * +----+----+----+----+----+
121 * rtval | n0 | n1 | n2 | .. | nn |
122 * +----+----+----+----+----+
123 * rtflag| 1 | 1 | 1 | 1 | 1 |
124 * +----+----+----+----+----+
126 * The T line contains the assembled code output by the assem-
127 * bler with xx xx being the offset address from the current area
128 * base address and nn being the assembled instructions and data in
135 * int rtcnt number of values evaluated
136 * int rtflg[] array of evaluation flags
137 * int rtval[] array of evaluation values
140 * int eval() lkeval.c
144 * Linker input T line evaluated.
154 rtval[rtcnt] = eval();
161 /*)Function VOID relr()
163 * The function relr() evaluates a R line read by
164 * the linker. The R line data is combined with the
165 * previous T line data to perform the relocation of
166 * code and data bytes. The S19 / IHX output and
167 * translation of the LST files to RST files may be
172 * R 0 0 nn nn n1 n2 xx xx ...
174 * The R line provides the relocation information to the linker.
175 * The nn nn value is the current area index, i.e. which area the
176 * current values were assembled. Relocation information is en-
177 * coded in groups of 4 bytes:
179 * 1. n1 is the relocation mode and object format
180 * 1. bit 0 word(0x00)/byte(0x01)
181 * 2. bit 1 relocatable area(0x00)/symbol(0x02)
182 * 3. bit 2 normal(0x00)/PC relative(0x04) relocation
183 * 4. bit 3 1-byte(0x00)/2-byte(0x08) object format for
185 * 5. bit 4 signed(0x00)/unsigned(0x10) byte data
186 * 6. bit 5 normal(0x00)/page '0'(0x20) reference
187 * 7. bit 6 normal(0x00)/page 'nnn'(0x40) reference
189 * 2. n2 is a byte index into the corresponding (i.e. pre-
190 * ceeding) T line data (i.e. a pointer to the data to be
191 * updated by the relocation). The T line data may be
192 * 1-byte or 2-byte byte data format or 2-byte word
195 * 3. xx xx is the area/symbol index for the area/symbol be-
196 * ing referenced. the corresponding area/symbol is found
197 * in the header area/symbol lists.
199 * The groups of 4 bytes are repeated for each item requiring relo-
200 * cation in the preceeding T line.
203 * areax **a pointer to array of area pointers
204 * int aindex area index
205 * char *errmsg[] array of pointers to error strings
206 * int error error code
207 * int lkerr error flag
208 * int mode relocation mode
209 * adrr_t paga paging base area address
210 * addr_t pags paging symbol address
211 * addr_t pc relocated base address
212 * addr_t r PCR relocation value
213 * addr_t reli relocation initial value
214 * addr_t relv relocation final value
215 * int rindex symbol / area index
216 * addr_t rtbase base code address
217 * addr_t rtofst rtval[] index offset
218 * int rtp index into T data
219 * sym **s pointer to array of symbol pointers
222 * head *hp pointer to the head structure
223 * rerr rerr linker error structure
224 * FILE *stderr standard error device
227 * addr_t adb_b() lkrloc.c
228 * addr_t adb_lo() lkrloc.c
229 * addr_t adb_hi() lkrloc.c
230 * addr_t adw_w() lkrloc.c
231 * addr_t evword() lkrloc.c
232 * int eval() lkeval.c
233 * int fprintf() c_library
235 * int lkulist lklist.c
237 * VOID relerr() lkrloc.c
239 * int symval() lksym.c
242 * The R and T lines are combined to produce
243 * relocated code and data. Output S19 / IHX
244 * and relocated listing files may be produced.
252 register addr_t reli, relv;
253 int aindex, rindex, rtp, error;
254 addr_t r, rtbase, rtofst, paga, pags, pc;
259 * Get area and symbol lists
267 if (eval() != (R_WORD | R_AREA) || eval()) {
268 fprintf(stderr, "R input error\n");
276 if (aindex >= hp->h_narea) {
277 fprintf(stderr, "R area error\n");
285 rtbase = adw_w(0, 0);
291 pc = adw_w(a[aindex]->a_addr, 0);
295 char *s = strrchr(a[aindex]->a_bap->a_id, '_');
296 if(s != NULL && isdigit(s[1]))
297 current_rom_bank = atoi(s+1);
299 current_rom_bank = 0;
303 * Do remaining relocations
312 * R_SYM or R_AREA references
315 if (rindex >= hp->h_nglob) {
316 fprintf(stderr, "R symbol error\n");
320 reli = symval(s[rindex]);
322 if (rindex >= hp->h_narea) {
323 fprintf(stderr, "R area error\n");
327 reli = a[rindex]->a_addr;
335 reli -= (pc + (rtp-rtofst) + 1);
337 reli -= (pc + (rtp-rtofst) + 2);
342 * R_PAG0 or R_PAG addressing
344 if (mode & (R_PAG0|R_PAG)) {
345 paga = sdp.s_area->a_addr;
351 * R_BYTE or R_WORD operation
356 relv = adb_hi(reli, rtp);
358 relv = adb_lo(reli, rtp);
361 relv = adb_b(reli, rtp);
365 * R_WORD with the R_BYT2 mode is flagged
366 * as an 'r' error by the assembler,
367 * but it is processed here anyway.
371 relv = adw_hi(reli, rtp);
373 relv = adw_lo(reli, rtp);
376 relv = adw_w(reli, rtp);
381 * R_BYTE with R_BYT2 offset adjust
390 * Unsigned Byte Checking
392 if (mode & R_USGN && mode & R_BYTE && relv & ~0xFF)
396 * PCR Relocation Error Checking
398 if (mode & R_PCR && mode & R_BYTE) {
400 if (r != (addr_t) ~0x7F && r != 0)
405 * Page Relocation Error Checking
407 if (mode & R_PAG0 && (relv & ~0xFF || paga || pags))
409 if (mode & R_PAG && (relv & ~0xFF))
416 rerr.aindex = aindex;
418 rerr.rtbase = rtbase + rtp - rtofst - 1;
419 rerr.rindex = rindex;
420 rerr.rval = relv - reli;
421 relerr(errmsg[error-1]);
437 #endif /* GAMEGEAR */
446 "Unsigned Byte error",
447 "Byte PCR relocation error",
448 "Page0 relocation error",
449 "Page Mode relocation error"
453 /*)Function VOID relp()
455 * The function relp() evaluates a P line read by
456 * the linker. The P line data is combined with the
457 * previous T line data to set the base page address
458 * and test the paging boundary and length.
462 * P 0 0 nn nn n1 n2 xx xx
464 * The P line provides the paging information to the linker as
465 * specified by a .setdp directive. The format of the relocation
466 * information is identical to that of the R line. The correspond-
467 * ing T line has the following information:
468 * T xx xx aa aa bb bb
470 * Where aa aa is the area reference number which specifies the
471 * selected page area and bb bb is the base address of the page.
472 * bb bb will require relocation processing if the 'n1 n2 xx xx' is
473 * specified in the P line. The linker will verify that the base
474 * address is on a 256 byte boundary and that the page length of an
475 * area defined with the PAG type is not larger than 256 bytes.
478 * areax **a pointer to array of area pointers
479 * int aindex area index
480 * int mode relocation mode
481 * addr_t relv relocation value
482 * int rindex symbol / area index
483 * int rtp index into T data
484 * sym **s pointer to array of symbol pointers
487 * head *hp pointer to the head structure
488 * int lkerr error flag
489 * sdp sdp base page structure
490 * FILE *stderr standard error device
493 * addr_t adw_w() lkrloc.c
494 * addr_t evword() lkrloc.c
495 * int eval() lkeval.c
496 * int fprintf() c_library
498 * int symval() lksym.c
501 * The P and T lines are combined to set
502 * the base page address and report any
510 register aindex, rindex;
517 * Get area and symbol lists
525 if (eval() != (R_WORD | R_AREA) || eval()) {
526 fprintf(stderr, "P input error\n");
534 if (aindex >= hp->h_narea) {
535 fprintf(stderr, "P area error\n");
541 * Do remaining relocations
549 * R_SYM or R_AREA references
552 if (rindex >= hp->h_nglob) {
553 fprintf(stderr, "P symbol error\n");
557 relv = symval(s[rindex]);
559 if (rindex >= hp->h_narea) {
560 fprintf(stderr, "P area error\n");
564 relv = a[rindex]->a_addr;
573 if (aindex >= hp->h_narea) {
574 fprintf(stderr, "P area error\n");
578 sdp.s_areax = a[aindex];
579 sdp.s_area = sdp.s_areax->a_bap;
580 sdp.s_addr = adw_w(0,4);
581 if (sdp.s_area->a_addr & 0xFF || sdp.s_addr & 0xFF)
582 relerp("Page Definition Boundary Error");
585 /*)Function VOID rele()
587 * The function rele() closes all open output files
588 * at the end of the linking process.
594 * int oflag output type flag
595 * int uflag relocation listing flag
599 * VOID lkulist() lklist.c
603 * All open output files are closed.
623 #endif /* GAMEGEAR */
631 /*)Function addr_t evword()
633 * The function evword() combines two byte values
634 * into a single word value.
637 * addr_t v temporary evaluation variable
640 * hilo byte ordering parameter
643 * int eval() lkeval.c
646 * Relocation text line is scanned to combine
647 * two byte values into a single word value.
666 /*)Function addr_t adb_b(v, i)
668 * int v value to add to byte
669 * int i rtval[] index
671 * The function adb_b() adds the value of v to
672 * the single byte value contained in rtval[i].
673 * The new value of rtval[i] is returned.
685 * The value of rtval[] is changed.
694 return(rtval[i] += v);
697 /*)Function addr_t adb_lo(v, i)
699 * int v value to add to byte
700 * int i rtval[] index
702 * The function adb_lo() adds the value of v to the
703 * double byte value contained in rtval[i] and rtval[i+1].
704 * The new value of rtval[i] / rtval[i+1] is returned.
705 * The MSB rtflg[] is cleared.
708 * addr_t j temporary evaluation variable
711 * hilo byte ordering parameter
717 * The value of rtval[] is changed.
718 * The rtflg[] value corresponding to the
719 * MSB of the word value is cleared to reflect
720 * the fact that the LSB is the selected byte.
743 /*)Function addr_t adb_hi(v, i)
745 * int v value to add to byte
746 * int i rtval[] index
748 * The function adb_hi() adds the value of v to the
749 * double byte value contained in rtval[i] and rtval[i+1].
750 * The new value of rtval[i] / rtval[i+1] is returned.
751 * The LSB rtflg[] is cleared.
754 * addr_t j temporary evaluation variable
757 * hilo byte ordering parameter
763 * The value of rtval[] is changed.
764 * The rtflg[] value corresponding to the
765 * LSB of the word value is cleared to reflect
766 * the fact that the MSB is the selected byte.
789 /*)Function addr_t adw_w(v, i)
791 * int v value to add to word
792 * int i rtval[] index
794 * The function adw_w() adds the value of v to the
795 * word value contained in rtval[i] and rtval[i+1].
796 * The new value of rtval[i] / rtval[i+1] is returned.
799 * addr_t j temporary evaluation variable
802 * hilo byte ordering parameter
808 * The word value of rtval[] is changed.
820 j = v + (rtval[i] << 8) + (rtval[i+1] & 0xff);
821 rtval[i] = (j >> 8) & 0xff;
822 rtval[i+1] = j & 0xff;
824 j = v + (rtval[i] & 0xff) + (rtval[i+1] << 8);
826 rtval[i+1] = (j >> 8) & 0xff;
831 /*)Function addr_t adw_lo(v, i)
833 * int v value to add to byte
834 * int i rtval[] index
836 * The function adw_lo() adds the value of v to the
837 * double byte value contained in rtval[i] and rtval[i+1].
838 * The new value of rtval[i] / rtval[i+1] is returned.
839 * The MSB rtval[] is zeroed.
842 * addr_t j temporary evaluation variable
845 * hilo byte ordering parameter
851 * The value of rtval[] is changed.
852 * The MSB of the word value is cleared to reflect
853 * the fact that the LSB is the selected byte.
876 /*)Function addr_t adw_hi(v, i)
878 * int v value to add to byte
879 * int i rtval[] index
881 * The function adw_hi() adds the value of v to the
882 * double byte value contained in rtval[i] and rtval[i+1].
883 * The new value of rtval[i] / rtval[i+1] is returned.
884 * The MSB and LSB values are interchanged.
885 * The MSB rtval[] is zeroed.
888 * addr_t j temporary evaluation variable
891 * hilo byte ordering parameter
897 * The value of rtval[] is changed.
898 * The MSB and LSB values are interchanged and
899 * then the MSB cleared.
912 * LSB = MSB, Clear MSB
915 rtval[i+1] = rtval[i];
918 rtval[i] = rtval[i+1];
924 /*)Function VOID relerr(str)
926 * char *str error string
928 * The function relerr() outputs the error string to
929 * stderr and to the map file (if it is open).
935 * FILE *mfp handle for the map file
938 * VOID errdmp() lkrloc.c
941 * Error message inserted into map file.
954 /*)Function VOID errdmp(fptr, str)
956 * FILE *fptr output file handle
957 * char *str error string
959 * The function errdmp() outputs the error string str
960 * to the device specified by fptr. Additional information
961 * is output about the definition and referencing of
962 * the symbol / area error.
965 * int mode error mode
966 * int aindex area index
967 * int lkerr error flag
968 * int rindex error index
969 * sym **s pointer to array of symbol pointers
970 * areax **a pointer to array of area pointers
971 * areax *raxp error area extension pointer
974 * sdp sdp base page structure
977 * int fprintf() c_library
978 * VOID prntval() lkrloc.c
990 int mode, aindex, rindex;
999 aindex = rerr.aindex;
1000 rindex = rerr.rindex;
1005 fprintf(fptr, "\n?ASlink-Warning-%s", str);
1009 * Print symbol if symbol based
1012 fprintf(fptr, " for symbol %.*s\n",
1013 NCPS, &s[rindex]->s_id[0]);
1015 fprintf(fptr, "\n");
1022 " file module area offset\n");
1024 " Refby %-8.8s %-8.8s %-8.8s ",
1027 &a[aindex]->a_bap->a_id[0]);
1028 prntval(fptr, rerr.rtbase);
1034 raxp = s[rindex]->s_axp;
1039 " Defin %-8.8s %-8.8s %-8.8s ",
1040 raxp->a_bhp->h_lfile->f_idp,
1041 &raxp->a_bhp->m_id[0],
1042 &raxp->a_bap->a_id[0]);
1044 prntval(fptr, s[rindex]->s_addr);
1046 prntval(fptr, rerr.rval);
1050 /*)Function VOID prntval(fptr, v)
1052 * FILE *fptr output file handle
1053 * addr_t v value to output
1055 * The function prntval() outputs the value v, in the
1056 * currently selected radix, to the device specified
1063 * int xflag current radix
1066 * int fprintf() c_library
1079 fprintf(fptr, "%04X\n", v);
1082 fprintf(fptr, "%06o\n", v);
1085 fprintf(fptr, "%05u\n", v);
1089 /*)Function VOID relerp(str)
1091 * char *str error string
1093 * The function relerp() outputs the paging error string to
1094 * stderr and to the map file (if it is open).
1100 * FILE *mfp handle for the map file
1103 * VOID erpdmp() lkrloc.c
1106 * Error message inserted into map file.
1114 erpdmp(stderr, str);
1119 /*)Function VOID erpdmp(fptr, str)
1121 * FILE *fptr output file handle
1122 * char *str error string
1124 * The function erpdmp() outputs the error string str
1125 * to the device specified by fptr.
1128 * head *thp pointer to head structure
1131 * int lkerr error flag
1132 * sdp sdp base page structure
1135 * int fprintf() c_library
1136 * VOID prntval() lkrloc.c
1148 register struct head *thp;
1150 thp = sdp.s_areax->a_bhp;
1155 fprintf(fptr, "\n?ASlink-Warning-%s\n", str);
1162 " file module pgarea pgoffset\n");
1164 " PgDef %-8.8s %-8.8s %-8.8s ",
1165 thp->h_lfile->f_idp,
1167 &sdp.s_area->a_id[0]);
1168 prntval(fptr, sdp.s_area->a_addr + sdp.s_addr);