3 Copyright (C) 1989-1995 Alan R. Baldwin
4 721 Berkeley St., Kent, Ohio 44240
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 * Extensions: P. Felber
31 * The module lkrloc.c contains the functions which
32 * perform the relocation calculations.
34 * lkrloc.c contains the following functions:
53 * lkrloc.c the local variable errmsg[].
57 /*)Function VOID reloc(c)
61 * The function reloc() calls a particular relocation
62 * function determined by the process code.
68 * int lkerr error flag
71 * int fprintf() c_library
72 * VOID rele() lkrloc.c
73 * VOID relp() lkrloc.c
74 * VOID relr() lkrloc.c
75 * VOId relt() lkrloc.c
78 * Refer to the called relocation functions.
103 fprintf(stderr, "Undefined Relocation Operation\n");
111 /*)Function VOID relt()
113 * The function relt() evaluates a T line read by
114 * the linker. Each byte value read is saved in the
115 * rtval[] array, rtflg[] is set, and the number of
116 * evaluations is maintained in rtcnt.
120 * T xx xx nn nn nn nn nn ...
123 * In: "T n0 n1 n2 n3 ... nn"
125 * Out: 0 1 2 .. rtcnt
126 * +----+----+----+----+----+
127 * rtval | n0 | n1 | n2 | .. | nn |
128 * +----+----+----+----+----+
129 * rtflag| 1 | 1 | 1 | 1 | 1 |
130 * +----+----+----+----+----+
132 * The T line contains the assembled code output by the assem-
133 * bler with xx xx being the offset address from the current area
134 * base address and nn being the assembled instructions and data in
141 * int rtcnt number of values evaluated
142 * int rtflg[] array of evaluation flags
143 * int rtval[] array of evaluation values
146 * int eval() lkeval.c
150 * Linker input T line evaluated.
159 rtval[rtcnt] = eval();
166 /*)Function VOID relr()
168 * The function relr() evaluates a R line read by
169 * the linker. The R line data is combined with the
170 * previous T line data to perform the relocation of
171 * code and data bytes. The S19 / IHX output and
172 * translation of the LST files to RST files may be
177 * R 0 0 nn nn n1 n2 xx xx ...
179 * The R line provides the relocation information to the linker.
180 * The nn nn value is the current area index, i.e. which area the
181 * current values were assembled. Relocation information is en-
182 * coded in groups of 4 bytes:
184 * 1. n1 is the relocation mode and object format
185 * 1. bit 0 word(0x00)/byte(0x01)
186 * 2. bit 1 relocatable area(0x00)/symbol(0x02)
187 * 3. bit 2 normal(0x00)/PC relative(0x04) relocation
188 * 4. bit 3 1-byte(0x00)/2-byte(0x08) object format for
190 * 5. bit 4 signed(0x00)/unsigned(0x10) byte data
191 * 6. bit 5 normal(0x00)/page '0'(0x20) reference
192 * 7. bit 6 normal(0x00)/page 'nnn'(0x40) reference
194 * 2. n2 is a byte index into the corresponding (i.e. pre-
195 * ceeding) T line data (i.e. a pointer to the data to be
196 * updated by the relocation). The T line data may be
197 * 1-byte or 2-byte byte data format or 2-byte word
200 * 3. xx xx is the area/symbol index for the area/symbol be-
201 * ing referenced. the corresponding area/symbol is found
202 * in the header area/symbol lists.
204 * The groups of 4 bytes are repeated for each item requiring relo-
205 * cation in the preceeding T line.
208 * areax **a pointer to array of area pointers
209 * int aindex area index
210 * char *errmsg[] array of pointers to error strings
211 * int error error code
212 * int lkerr error flag
213 * int mode relocation mode
214 * adrr_t paga paging base area address
215 * Addr_T pags paging symbol address
216 * Addr_T pc relocated base address
217 * Addr_T r PCR relocation value
218 * Addr_T reli relocation initial value
219 * Addr_T relv relocation final value
220 * int rindex symbol / area index
221 * Addr_T rtbase base code address
222 * Addr_T rtofst rtval[] index offset
223 * int rtp index into T data
224 * sym **s pointer to array of symbol pointers
227 * head *hp pointer to the head structure
228 * rerr rerr linker error structure
229 * FILE *stderr standard error device
232 * Addr_T adb_b() lkrloc.c
233 * Addr_T adb_lo() lkrloc.c
234 * Addr_T adb_hi() lkrloc.c
235 * Addr_T adw_w() lkrloc.c
236 * Addr_T evword() lkrloc.c
237 * int eval() lkeval.c
238 * int fprintf() c_library
240 * int lkulist lklist.c
242 * VOID relerr() lkrloc.c
244 * int symval() lksym.c
247 * The R and T lines are combined to produce
248 * relocated code and data. Output S19 / IHX
249 * and relocated listing files may be produced.
256 register Addr_T reli, relv;
257 int aindex, rindex, rtp, error;
258 Addr_T r, rtbase, rtofst, paga = 0, pags = 0, pc;
263 * Get area and symbol lists
271 if (eval() != (R_WORD | R_AREA) || eval()) {
272 fprintf(stderr, "R input error\n");
280 if (aindex >= hp->h_narea) {
281 fprintf(stderr, "R area error\n");
289 rtbase = adw_w(0, 0);
295 pc = adw_w(a[aindex]->a_addr, 0);
299 char *s = strrchr(a[aindex]->a_bap->a_id, '_');
300 if(s != NULL && isdigit((unsigned char)s[1]))
301 current_rom_bank = atoi(s+1);
303 current_rom_bank = 0;
307 * Do remaining relocations
316 * R_SYM or R_AREA references
319 if (rindex >= hp->h_nglob) {
320 fprintf(stderr, "R symbol error\n");
324 reli = symval(s[rindex]);
326 if (rindex >= hp->h_narea) {
327 fprintf(stderr, "R area error\n");
331 reli = a[rindex]->a_addr;
339 reli -= (pc + (rtp-rtofst) + 1);
341 reli -= (pc + (rtp-rtofst) + 2);
346 * R_PAG0 or R_PAG addressing
348 if (mode & (R_PAG0 | R_PAG)) {
349 paga = sdp.s_area->a_addr;
355 * R_BYTE or R_WORD operation
359 /* This is a two byte address, of
360 * which we will select one byte.
363 relv = adb_hi(reli, rtp);
365 relv = adb_lo(reli, rtp);
368 relv = adb_b(reli, rtp);
372 * R_WORD with the R_BYT2 mode is flagged
373 * as an 'r' error by the assembler,
374 * but it is processed here anyway.
378 relv = adw_hi(reli, rtp);
380 relv = adw_lo(reli, rtp);
383 relv = adw_w(reli, rtp);
388 * R_BYTE with R_BYT2 offset adjust
397 * Unsigned Byte Checking
399 if (mode & R_USGN && mode & R_BYTE && relv & ~0xFF)
403 * PCR Relocation Error Checking
405 if (mode & R_PCR && mode & R_BYTE) {
407 if (r != (Addr_T) ~0x7F && r != 0)
412 * Page Relocation Error Checking
414 if (mode & R_PAG0 && (relv & ~0xFF || paga || pags))
416 if (mode & R_PAG && (relv & ~0xFF))
423 rerr.aindex = aindex;
425 rerr.rtbase = rtbase + rtp - rtofst - 1;
426 rerr.rindex = rindex;
427 rerr.rval = relv - reli;
428 relerr(errmsg[error-1]);
444 #endif /* GAMEGEAR */
453 "Unsigned Byte error",
454 "Byte PCR relocation error",
455 "Page0 relocation error",
456 "Page Mode relocation error"
460 /*)Function VOID relp()
462 * The function relp() evaluates a P line read by
463 * the linker. The P line data is combined with the
464 * previous T line data to set the base page address
465 * and test the paging boundary and length.
469 * P 0 0 nn nn n1 n2 xx xx
471 * The P line provides the paging information to the linker as
472 * specified by a .setdp directive. The format of the relocation
473 * information is identical to that of the R line. The correspond-
474 * ing T line has the following information:
475 * T xx xx aa aa bb bb
477 * Where aa aa is the area reference number which specifies the
478 * selected page area and bb bb is the base address of the page.
479 * bb bb will require relocation processing if the 'n1 n2 xx xx' is
480 * specified in the P line. The linker will verify that the base
481 * address is on a 256 byte boundary and that the page length of an
482 * area defined with the PAG type is not larger than 256 bytes.
485 * areax **a pointer to array of area pointers
486 * int aindex area index
487 * int mode relocation mode
488 * Addr_T relv relocation value
489 * int rindex symbol / area index
490 * int rtp index into T data
491 * sym **s pointer to array of symbol pointers
494 * head *hp pointer to the head structure
495 * int lkerr error flag
496 * sdp sdp base page structure
497 * FILE *stderr standard error device
500 * Addr_T adw_w() lkrloc.c
501 * Addr_T evword() lkrloc.c
502 * int eval() lkeval.c
503 * int fprintf() c_library
505 * int symval() lksym.c
508 * The P and T lines are combined to set
509 * the base page address and report any
516 register int aindex, rindex;
523 * Get area and symbol lists
531 if (eval() != (R_WORD | R_AREA) || eval()) {
532 fprintf(stderr, "P input error\n");
540 if (aindex >= hp->h_narea) {
541 fprintf(stderr, "P area error\n");
547 * Do remaining relocations
555 * R_SYM or R_AREA references
558 if (rindex >= hp->h_nglob) {
559 fprintf(stderr, "P symbol error\n");
563 relv = symval(s[rindex]);
565 if (rindex >= hp->h_narea) {
566 fprintf(stderr, "P area error\n");
570 relv = a[rindex]->a_addr;
579 if (aindex >= hp->h_narea) {
580 fprintf(stderr, "P area error\n");
584 sdp.s_areax = a[aindex];
585 sdp.s_area = sdp.s_areax->a_bap;
586 sdp.s_addr = adw_w(0,4);
587 if (sdp.s_area->a_addr & 0xFF || sdp.s_addr & 0xFF)
588 relerp("Page Definition Boundary Error");
591 /*)Function VOID rele()
593 * The function rele() closes all open output files
594 * at the end of the linking process.
600 * int oflag output type flag
601 * int uflag relocation listing flag
605 * VOID lkulist() lklist.c
609 * All open output files are closed.
628 #endif /* GAMEGEAR */
636 /*)Function Addr_T evword()
638 * The function evword() combines two byte values
639 * into a single word value.
642 * Addr_T v temporary evaluation variable
645 * hilo byte ordering parameter
648 * int eval() lkeval.c
651 * Relocation text line is scanned to combine
652 * 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.
693 Addr_T adb_b(register Addr_T v, register int i)
695 return(rtval[i] += v);
698 /*)Function Addr_T adb_lo(v, i)
700 * int v value to add to byte
701 * int i rtval[] index
703 * The function adb_lo() adds the value of v to the
704 * double byte value contained in rtval[i] and rtval[i+1].
705 * The new value of rtval[i] / rtval[i+1] is returned.
706 * The MSB rtflg[] is cleared.
709 * Addr_T j temporary evaluation variable
712 * hilo byte ordering parameter
718 * The value of rtval[] is changed.
719 * The rtflg[] value corresponding to the
720 * MSB of the word value is cleared to reflect
721 * the fact that the LSB is the selected byte.
725 Addr_T adb_lo(Addr_T v, int i)
741 /*)Function Addr_T adb_hi(v, i)
743 * int v value to add to byte
744 * int i rtval[] index
746 * The function adb_hi() adds the value of v to the
747 * double byte value contained in rtval[i] and rtval[i+1].
748 * The new value of rtval[i] / rtval[i+1] is returned.
749 * The LSB rtflg[] is cleared.
752 * Addr_T j temporary evaluation variable
755 * hilo byte ordering parameter
761 * The value of rtval[] is changed.
762 * The rtflg[] value corresponding to the
763 * LSB of the word value is cleared to reflect
764 * the fact that the MSB is the selected byte.
768 Addr_T adb_hi(Addr_T v, int i)
784 /*)Function Addr_T adw_w(v, i)
786 * int v value to add to word
787 * int i rtval[] index
789 * The function adw_w() adds the value of v to the
790 * word value contained in rtval[i] and rtval[i+1].
791 * The new value of rtval[i] / rtval[i+1] is returned.
794 * Addr_T j temporary evaluation variable
797 * hilo byte ordering parameter
803 * The word value of rtval[] is changed.
807 Addr_T adw_w(register Addr_T v, register int i)
812 j = v + (rtval[i] << 8) + (rtval[i+1] & 0xff);
813 rtval[i] = (j >> 8) & 0xff;
814 rtval[i+1] = j & 0xff;
816 j = v + (rtval[i] & 0xff) + (rtval[i+1] << 8);
818 rtval[i+1] = (j >> 8) & 0xff;
823 /*)Function Addr_T adw_lo(v, i)
825 * int v value to add to byte
826 * int i rtval[] index
828 * The function adw_lo() adds the value of v to the
829 * double byte value contained in rtval[i] and rtval[i+1].
830 * The new value of rtval[i] / rtval[i+1] is returned.
831 * The MSB rtval[] is zeroed.
834 * Addr_T j temporary evaluation variable
837 * hilo byte ordering parameter
843 * The value of rtval[] is changed.
844 * The MSB of the word value is cleared to reflect
845 * the fact that the LSB is the selected byte.
849 Addr_T adw_lo(Addr_T v, int i)
865 /*)Function Addr_T adw_hi(v, i)
867 * int v value to add to byte
868 * int i rtval[] index
870 * The function adw_hi() adds the value of v to the
871 * double byte value contained in rtval[i] and rtval[i+1].
872 * The new value of rtval[i] / rtval[i+1] is returned.
873 * The MSB and LSB values are interchanged.
874 * The MSB rtval[] is zeroed.
877 * Addr_T j temporary evaluation variable
880 * hilo byte ordering parameter
886 * The value of rtval[] is changed.
887 * The MSB and LSB values are interchanged and
888 * then the MSB cleared.
892 Addr_T adw_hi(Addr_T v, int i)
898 * LSB = MSB, Clear MSB
901 rtval[i+1] = rtval[i];
904 rtval[i] = rtval[i+1];
910 /*)Function VOID relerr(str)
912 * char *str error string
914 * The function relerr() outputs the error string to
915 * stderr and to the map file (if it is open).
921 * FILE *mfp handle for the map file
924 * VOID errdmp() lkrloc.c
927 * Error message inserted into map file.
931 VOID relerr(char *str)
938 /*)Function VOID errdmp(fptr, str)
940 * FILE *fptr output file handle
941 * char *str error string
943 * The function errdmp() outputs the error string str
944 * to the device specified by fptr. Additional information
945 * is output about the definition and referencing of
946 * the symbol / area error.
949 * int mode error mode
950 * int aindex area index
951 * int lkerr error flag
952 * int rindex error index
953 * sym **s pointer to array of symbol pointers
954 * areax **a pointer to array of area pointers
955 * areax *raxp error area extension pointer
958 * sdp sdp base page structure
961 * int fprintf() c_library
962 * VOID prntval() lkrloc.c
969 VOID errdmp(FILE *fptr, char *str)
971 int mode, aindex, rindex;
980 aindex = rerr.aindex;
981 rindex = rerr.rindex;
986 fprintf(fptr, "\n?ASlink-Warning-%s", str);
990 * Print symbol if symbol based
993 fprintf(fptr, " for symbol %.*s\n",
994 NCPS, &s[rindex]->s_id[0]);
1003 " file module area offset\n");
1005 " Refby %-8.8s %-8.8s %-8.8s ",
1008 &a[aindex]->a_bap->a_id[0]);
1009 prntval(fptr, rerr.rtbase);
1015 raxp = s[rindex]->s_axp;
1020 " Defin %-8.8s %-8.8s %-8.8s ",
1021 raxp->a_bhp->h_lfile->f_idp,
1022 &raxp->a_bhp->m_id[0],
1023 &raxp->a_bap->a_id[0]);
1025 prntval(fptr, s[rindex]->s_addr);
1027 prntval(fptr, rerr.rval);
1031 /*)Function VOID prntval(fptr, v)
1033 * FILE *fptr output file handle
1034 * Addr_T v value to output
1036 * The function prntval() outputs the value v, in the
1037 * currently selected radix, to the device specified
1044 * int xflag current radix
1047 * int fprintf() c_library
1054 VOID prntval(FILE *fptr, Addr_T v)
1057 fprintf(fptr, "%04X\n", v);
1060 fprintf(fptr, "%06o\n", v);
1063 fprintf(fptr, "%05u\n", v);
1067 /*)Function VOID relerp(str)
1069 * char *str error string
1071 * The function relerp() outputs the paging error string to
1072 * stderr and to the map file (if it is open).
1078 * FILE *mfp handle for the map file
1081 * VOID erpdmp() lkrloc.c
1084 * Error message inserted into map file.
1088 VOID relerp(char *str)
1090 erpdmp(stderr, str);
1095 /*)Function VOID erpdmp(fptr, str)
1097 * FILE *fptr output file handle
1098 * char *str error string
1100 * The function erpdmp() outputs the error string str
1101 * to the device specified by fptr.
1104 * head *thp pointer to head structure
1107 * int lkerr error flag
1108 * sdp sdp base page structure
1111 * int fprintf() c_library
1112 * VOID prntval() lkrloc.c
1119 VOID erpdmp(FILE *fptr, char *str)
1121 register struct head *thp;
1123 thp = sdp.s_areax->a_bhp;
1128 fprintf(fptr, "\n?ASlink-Warning-%s\n", str);
1135 " file module pgarea pgoffset\n");
1137 " PgDef %-8.8s %-8.8s %-8.8s ",
1138 thp->h_lfile->f_idp,
1140 &sdp.s_area->a_id[0]);
1141 prntval(fptr, sdp.s_area->a_addr + sdp.s_addr);