4 * (C) Copyright 1989-1995
13 * Extensions: P. Felber
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.
96 fprintf(stderr, "Undefined Relocation Operation\n");
104 /*)Function VOID relt()
106 * The function relt() evaluates a T line read by
107 * the linker. Each byte value read is saved in the
108 * rtval[] array, rtflg[] is set, and the number of
109 * evaluations is maintained in rtcnt.
113 * T xx xx nn nn nn nn nn ...
116 * In: "T n0 n1 n2 n3 ... nn"
118 * Out: 0 1 2 .. rtcnt
119 * +----+----+----+----+----+
120 * rtval | n0 | n1 | n2 | .. | nn |
121 * +----+----+----+----+----+
122 * rtflag| 1 | 1 | 1 | 1 | 1 |
123 * +----+----+----+----+----+
125 * The T line contains the assembled code output by the assem-
126 * bler with xx xx being the offset address from the current area
127 * base address and nn being the assembled instructions and data in
134 * int rtcnt number of values evaluated
135 * int rtflg[] array of evaluation flags
136 * int rtval[] array of evaluation values
139 * int eval() lkeval.c
143 * Linker input T line evaluated.
152 rtval[rtcnt] = eval();
159 /*)Function VOID relr()
161 * The function relr() evaluates a R line read by
162 * the linker. The R line data is combined with the
163 * previous T line data to perform the relocation of
164 * code and data bytes. The S19 / IHX output and
165 * translation of the LST files to RST files may be
170 * R 0 0 nn nn n1 n2 xx xx ...
172 * The R line provides the relocation information to the linker.
173 * The nn nn value is the current area index, i.e. which area the
174 * current values were assembled. Relocation information is en-
175 * coded in groups of 4 bytes:
177 * 1. n1 is the relocation mode and object format
178 * 1. bit 0 word(0x00)/byte(0x01)
179 * 2. bit 1 relocatable area(0x00)/symbol(0x02)
180 * 3. bit 2 normal(0x00)/PC relative(0x04) relocation
181 * 4. bit 3 1-byte(0x00)/2-byte(0x08) object format for
183 * 5. bit 4 signed(0x00)/unsigned(0x10) byte data
184 * 6. bit 5 normal(0x00)/page '0'(0x20) reference
185 * 7. bit 6 normal(0x00)/page 'nnn'(0x40) reference
187 * 2. n2 is a byte index into the corresponding (i.e. pre-
188 * ceeding) T line data (i.e. a pointer to the data to be
189 * updated by the relocation). The T line data may be
190 * 1-byte or 2-byte byte data format or 2-byte word
193 * 3. xx xx is the area/symbol index for the area/symbol be-
194 * ing referenced. the corresponding area/symbol is found
195 * in the header area/symbol lists.
197 * The groups of 4 bytes are repeated for each item requiring relo-
198 * cation in the preceeding T line.
201 * areax **a pointer to array of area pointers
202 * int aindex area index
203 * char *errmsg[] array of pointers to error strings
204 * int error error code
205 * int lkerr error flag
206 * int mode relocation mode
207 * adrr_t paga paging base area address
208 * Addr_T pags paging symbol address
209 * Addr_T pc relocated base address
210 * Addr_T r PCR relocation value
211 * Addr_T reli relocation initial value
212 * Addr_T relv relocation final value
213 * int rindex symbol / area index
214 * Addr_T rtbase base code address
215 * Addr_T rtofst rtval[] index offset
216 * int rtp index into T data
217 * sym **s pointer to array of symbol pointers
220 * head *hp pointer to the head structure
221 * rerr rerr linker error structure
222 * FILE *stderr standard error device
225 * Addr_T adb_b() lkrloc.c
226 * Addr_T adb_lo() lkrloc.c
227 * Addr_T adb_hi() lkrloc.c
228 * Addr_T adw_w() lkrloc.c
229 * Addr_T evword() lkrloc.c
230 * int eval() lkeval.c
231 * int fprintf() c_library
233 * int lkulist lklist.c
235 * VOID relerr() lkrloc.c
237 * int symval() lksym.c
240 * The R and T lines are combined to produce
241 * relocated code and data. Output S19 / IHX
242 * and relocated listing files may be produced.
249 register Addr_T reli, relv;
250 int aindex, rindex, rtp, error;
251 Addr_T r, rtbase, rtofst, paga = 0, pags = 0, pc;
256 * Get area and symbol lists
264 if (eval() != (R_WORD | R_AREA) || eval()) {
265 fprintf(stderr, "R input error\n");
273 if (aindex >= hp->h_narea) {
274 fprintf(stderr, "R area error\n");
282 rtbase = adw_w(0, 0);
288 pc = adw_w(a[aindex]->a_addr, 0);
292 char *s = strrchr(a[aindex]->a_bap->a_id, '_');
293 if(s != NULL && isdigit((unsigned char)s[1]))
294 current_rom_bank = atoi(s+1);
296 current_rom_bank = 0;
300 * Do remaining relocations
309 * R_SYM or R_AREA references
312 if (rindex >= hp->h_nglob) {
313 fprintf(stderr, "R symbol error\n");
317 reli = symval(s[rindex]);
319 if (rindex >= hp->h_narea) {
320 fprintf(stderr, "R area error\n");
324 reli = a[rindex]->a_addr;
332 reli -= (pc + (rtp-rtofst) + 1);
334 reli -= (pc + (rtp-rtofst) + 2);
339 * R_PAG0 or R_PAG addressing
341 if (mode & (R_PAG0 | R_PAG)) {
342 paga = sdp.s_area->a_addr;
348 * R_BYTE or R_WORD operation
352 /* This is a two byte address, of
353 * which we will select one byte.
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
509 register int aindex, rindex;
516 * Get area and symbol lists
524 if (eval() != (R_WORD | R_AREA) || eval()) {
525 fprintf(stderr, "P input error\n");
533 if (aindex >= hp->h_narea) {
534 fprintf(stderr, "P area error\n");
540 * Do remaining relocations
548 * R_SYM or R_AREA references
551 if (rindex >= hp->h_nglob) {
552 fprintf(stderr, "P symbol error\n");
556 relv = symval(s[rindex]);
558 if (rindex >= hp->h_narea) {
559 fprintf(stderr, "P area error\n");
563 relv = a[rindex]->a_addr;
572 if (aindex >= hp->h_narea) {
573 fprintf(stderr, "P area error\n");
577 sdp.s_areax = a[aindex];
578 sdp.s_area = sdp.s_areax->a_bap;
579 sdp.s_addr = adw_w(0,4);
580 if (sdp.s_area->a_addr & 0xFF || sdp.s_addr & 0xFF)
581 relerp("Page Definition Boundary Error");
584 /*)Function VOID rele()
586 * The function rele() closes all open output files
587 * at the end of the linking process.
593 * int oflag output type flag
594 * int uflag relocation listing flag
598 * VOID lkulist() lklist.c
602 * All open output files are closed.
621 #endif /* GAMEGEAR */
629 /*)Function Addr_T evword()
631 * The function evword() combines two byte values
632 * into a single word value.
635 * Addr_T v temporary evaluation variable
638 * hilo byte ordering parameter
641 * int eval() lkeval.c
644 * Relocation text line is scanned to combine
645 * two byte values into a single word value.
663 /*)Function Addr_T adb_b(v, i)
665 * int v value to add to byte
666 * int i rtval[] index
668 * The function adb_b() adds the value of v to
669 * the single byte value contained in rtval[i].
670 * The new value of rtval[i] is returned.
682 * The value of rtval[] is changed.
686 Addr_T adb_b(register Addr_T v, register int i)
688 return(rtval[i] += v);
691 /*)Function Addr_T adb_lo(v, i)
693 * int v value to add to byte
694 * int i rtval[] index
696 * The function adb_lo() adds the value of v to the
697 * double byte value contained in rtval[i] and rtval[i+1].
698 * The new value of rtval[i] / rtval[i+1] is returned.
699 * The MSB rtflg[] is cleared.
702 * Addr_T j temporary evaluation variable
705 * hilo byte ordering parameter
711 * The value of rtval[] is changed.
712 * The rtflg[] value corresponding to the
713 * MSB of the word value is cleared to reflect
714 * the fact that the LSB is the selected byte.
718 Addr_T adb_lo(Addr_T v, int i)
734 /*)Function Addr_T adb_hi(v, i)
736 * int v value to add to byte
737 * int i rtval[] index
739 * The function adb_hi() adds the value of v to the
740 * double byte value contained in rtval[i] and rtval[i+1].
741 * The new value of rtval[i] / rtval[i+1] is returned.
742 * The LSB rtflg[] is cleared.
745 * Addr_T j temporary evaluation variable
748 * hilo byte ordering parameter
754 * The value of rtval[] is changed.
755 * The rtflg[] value corresponding to the
756 * LSB of the word value is cleared to reflect
757 * the fact that the MSB is the selected byte.
761 Addr_T adb_hi(Addr_T v, int i)
777 /*)Function Addr_T adw_w(v, i)
779 * int v value to add to word
780 * int i rtval[] index
782 * The function adw_w() adds the value of v to the
783 * word value contained in rtval[i] and rtval[i+1].
784 * The new value of rtval[i] / rtval[i+1] is returned.
787 * Addr_T j temporary evaluation variable
790 * hilo byte ordering parameter
796 * The word value of rtval[] is changed.
800 Addr_T adw_w(register Addr_T v, register int i)
805 j = v + (rtval[i] << 8) + (rtval[i+1] & 0xff);
806 rtval[i] = (j >> 8) & 0xff;
807 rtval[i+1] = j & 0xff;
809 j = v + (rtval[i] & 0xff) + (rtval[i+1] << 8);
811 rtval[i+1] = (j >> 8) & 0xff;
816 /*)Function Addr_T adw_lo(v, i)
818 * int v value to add to byte
819 * int i rtval[] index
821 * The function adw_lo() adds the value of v to the
822 * double byte value contained in rtval[i] and rtval[i+1].
823 * The new value of rtval[i] / rtval[i+1] is returned.
824 * The MSB rtval[] is zeroed.
827 * Addr_T j temporary evaluation variable
830 * hilo byte ordering parameter
836 * The value of rtval[] is changed.
837 * The MSB of the word value is cleared to reflect
838 * the fact that the LSB is the selected byte.
842 Addr_T adw_lo(Addr_T v, int i)
858 /*)Function Addr_T adw_hi(v, i)
860 * int v value to add to byte
861 * int i rtval[] index
863 * The function adw_hi() adds the value of v to the
864 * double byte value contained in rtval[i] and rtval[i+1].
865 * The new value of rtval[i] / rtval[i+1] is returned.
866 * The MSB and LSB values are interchanged.
867 * The MSB rtval[] is zeroed.
870 * Addr_T j temporary evaluation variable
873 * hilo byte ordering parameter
879 * The value of rtval[] is changed.
880 * The MSB and LSB values are interchanged and
881 * then the MSB cleared.
885 Addr_T adw_hi(Addr_T v, int i)
891 * LSB = MSB, Clear MSB
894 rtval[i+1] = rtval[i];
897 rtval[i] = rtval[i+1];
903 /*)Function VOID relerr(str)
905 * char *str error string
907 * The function relerr() outputs the error string to
908 * stderr and to the map file (if it is open).
914 * FILE *mfp handle for the map file
917 * VOID errdmp() lkrloc.c
920 * Error message inserted into map file.
924 VOID relerr(char *str)
931 /*)Function VOID errdmp(fptr, str)
933 * FILE *fptr output file handle
934 * char *str error string
936 * The function errdmp() outputs the error string str
937 * to the device specified by fptr. Additional information
938 * is output about the definition and referencing of
939 * the symbol / area error.
942 * int mode error mode
943 * int aindex area index
944 * int lkerr error flag
945 * int rindex error index
946 * sym **s pointer to array of symbol pointers
947 * areax **a pointer to array of area pointers
948 * areax *raxp error area extension pointer
951 * sdp sdp base page structure
954 * int fprintf() c_library
955 * VOID prntval() lkrloc.c
962 VOID errdmp(FILE *fptr, char *str)
964 int mode, aindex, rindex;
973 aindex = rerr.aindex;
974 rindex = rerr.rindex;
979 fprintf(fptr, "\n?ASlink-Warning-%s", str);
983 * Print symbol if symbol based
986 fprintf(fptr, " for symbol %.*s\n",
987 NCPS, &s[rindex]->s_id[0]);
996 " file module area offset\n");
998 " Refby %-8.8s %-8.8s %-8.8s ",
1001 &a[aindex]->a_bap->a_id[0]);
1002 prntval(fptr, rerr.rtbase);
1008 raxp = s[rindex]->s_axp;
1013 " Defin %-8.8s %-8.8s %-8.8s ",
1014 raxp->a_bhp->h_lfile->f_idp,
1015 &raxp->a_bhp->m_id[0],
1016 &raxp->a_bap->a_id[0]);
1018 prntval(fptr, s[rindex]->s_addr);
1020 prntval(fptr, rerr.rval);
1024 /*)Function VOID prntval(fptr, v)
1026 * FILE *fptr output file handle
1027 * Addr_T v value to output
1029 * The function prntval() outputs the value v, in the
1030 * currently selected radix, to the device specified
1037 * int xflag current radix
1040 * int fprintf() c_library
1047 VOID prntval(FILE *fptr, Addr_T v)
1050 fprintf(fptr, "%04X\n", v);
1053 fprintf(fptr, "%06o\n", v);
1056 fprintf(fptr, "%05u\n", v);
1060 /*)Function VOID relerp(str)
1062 * char *str error string
1064 * The function relerp() outputs the paging error string to
1065 * stderr and to the map file (if it is open).
1071 * FILE *mfp handle for the map file
1074 * VOID erpdmp() lkrloc.c
1077 * Error message inserted into map file.
1081 VOID relerp(char *str)
1083 erpdmp(stderr, str);
1088 /*)Function VOID erpdmp(fptr, str)
1090 * FILE *fptr output file handle
1091 * char *str error string
1093 * The function erpdmp() outputs the error string str
1094 * to the device specified by fptr.
1097 * head *thp pointer to head structure
1100 * int lkerr error flag
1101 * sdp sdp base page structure
1104 * int fprintf() c_library
1105 * VOID prntval() lkrloc.c
1112 VOID erpdmp(FILE *fptr, char *str)
1114 register struct head *thp;
1116 thp = sdp.s_areax->a_bhp;
1121 fprintf(fptr, "\n?ASlink-Warning-%s\n", str);
1128 " file module pgarea pgoffset\n");
1130 " PgDef %-8.8s %-8.8s %-8.8s ",
1131 thp->h_lfile->f_idp,
1133 &sdp.s_area->a_id[0]);
1134 prntval(fptr, sdp.s_area->a_addr + sdp.s_addr);